Shared types and utilities for Long.xyz API
npm install @longdotxyz/sharedShared TypeScript library for Long.xyz API containing GraphQL types, REST API contracts, and utilities.
``bash`
npm install @longdotxyz/sharedor
pnpm add @longdotxyz/shared
- GraphQL Types & SDK: Auto-generated types and SDK client from GraphQL schema
- REST API Contracts: Type-safe API contracts built with ts-rest
- Type Utilities: Common types for blockchain addresses, pool keys, and more
- Utilities: Helper functions for native token handling
The library includes auto-generated GraphQL types and a ready-to-use SDK client.
`typescript
import { GraphQLClient } from "graphql-request";
import { getSdk } from "@longdotxyz/shared";
// Initialize GraphQL client
const client = new GraphQLClient("https://graphql.long.xyz");
// Create SDK instance
const sdk = getSdk(client);
`
`typescript
import { GetAuctionByAddressQuery, getSdk } from "@longdotxyz/shared";
// Query an auction
const { auction_pool } = await sdk.GetAuctionByAddress({
address: "0x123...",
});
// Type-safe access to auction data
if (auction_pool) {
console.log(auction_pool.auction_pool_address);
console.log(auction_pool.asset_address);
console.log(auction_pool.numeraire_address);
}
`
`typescript
import type { Asset, Asset_Bool_Exp, Asset_Order_By, AuctionPool, GraduationPool } from "@longdotxyz/shared";
// Use types for type-safe queries
const assetFilter: Asset_Bool_Exp = {
chain_id: { _eq: 1 },
asset_address: { _ilike: "0x%" },
};
`
The library provides type-safe REST API contracts using ts-rest.
`typescript
import { initClient } from "@ts-rest/core";
import { rootContract } from "@longdotxyz/shared";
// Create typed API client
const apiClient = initClient(rootContract, {
baseUrl: "https://api.long.xyz/v1",
baseHeaders: {
"Content-Type": "application/json",
},
});
`
`typescript
// Get dynamic auction details
const auctionResponse = await apiClient.auctions.getDynamicAuction({
params: {
address: "0x123...",
},
});
if (auctionResponse.status === 200) {
const { auction_pool_address, auction_base_token_symbol } = auctionResponse.body.result;
console.log(Pool: ${auction_pool_address}, Symbol: ${auction_base_token_symbol});
}
// Create dynamic auction
const createResponse = await apiClient.auctions.createDynamicAuction({
body: {
chain_id: 8453, // Base
template_id: "template_123",
metadata: {
token_name: "My Token",
token_symbol: "MTK",
token_uri: "ipfs://...",
migration_duration: 86400,
migration_beneficiaries: [{ address: "0xabc...", amount: 10000 }],
user_address: "0xdef...",
},
},
});
if (createResponse.status === 200) {
const { governance_factory, pool_initializer, liquidity_migrator } = createResponse.body.result;
console.log("Auction created with factories:", { governance_factory, pool_initializer });
}
`
`typescript
// V4 Exact Input Quote
const v4InputQuote = await apiClient.quotes.v4ExactInputSingle({
body: {
chain_id: 8453,
pool_key: {
currency0: "0x0000000000000000000000000000000000000000", // ETH
currency1: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
fee: 500,
tick_spacing: 10,
hooks: "0x0000000000000000000000000000000000000000",
},
zero_for_one: true,
exact_amount: "1000000000000000000", // 1 ETH
hook_data: "0x", // Optional hook data
},
});
if (v4InputQuote.status === 200) {
console.log(Output amount: ${v4InputQuote.body.result.amount_out});Gas estimate: ${v4InputQuote.body.result.gas_estimate}
console.log();
}
// V4 Exact Output Quote
const v4OutputQuote = await apiClient.quotes.v4ExactOutputSingle({
body: {
chain_id: 8453,
pool_key: {
currency0: "0x0000000000000000000000000000000000000000", // ETH
currency1: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
fee: 500,
tick_spacing: 10,
hooks: "0x0000000000000000000000000000000000000000",
},
zero_for_one: true,
exact_amount: "1000000000", // 1000 USDC output
hook_data: "0x", // Optional hook data
},
});
if (v4OutputQuote.status === 200) {
console.log(Input required: ${v4OutputQuote.body.result.amount_in});Gas estimate: ${v4OutputQuote.body.result.gas_estimate}
console.log();
}
// V3 Exact Input Quote
const v3InputQuote = await apiClient.quotes.v3ExactInputSingle({
body: {
chain_id: 1,
token_in: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
token_out: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
amount_in: "1000000000000000000", // 1 WETH
fee: 500, // 0.05%
sqrt_price_limit_x96: "0", // Optional price limit
},
});
if (v3InputQuote.status === 200) {
console.log(Output amount: ${v3InputQuote.body.result.amount_out});Price after: ${v3InputQuote.body.result.sqrt_price_x96_after}
console.log();Ticks crossed: ${v3InputQuote.body.result.initialized_ticks_crossed}
console.log();Gas estimate: ${v3InputQuote.body.result.gas_estimate}
console.log();
}
// V3 Exact Output Quote
const v3OutputQuote = await apiClient.quotes.v3ExactOutputSingle({
body: {
chain_id: 1,
token_in: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
token_out: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
amount_out: "1000000000", // 1000 USDC
fee: 500, // 0.05%
},
});
if (v3OutputQuote.status === 200) {
console.log(Input required: ${v3OutputQuote.body.result.amount_in});Price after: ${v3OutputQuote.body.result.sqrt_price_x96_after}
console.log();Ticks crossed: ${v3OutputQuote.body.result.initialized_ticks_crossed}
console.log();Gas estimate: ${v3OutputQuote.body.result.gas_estimate}
console.log();`
}
`typescript
// Fetch all communities
const communities = await apiClient.communities.fetchCommunities();
if (communities.status === 200) {
communities.body.result.forEach((community) => {
console.log(${community.label}: ${community.description});Funding: ${community.funding_amount}
console.log();
});
}
// Get specific community
const community = await apiClient.communities.getCommunity({
params: { id: 1 },
});
`
`typescript
// Upload an image to IPFS
const formData = new FormData();
formData.append("image", imageFile); // imageFile is a File object
const imageUpload = await apiClient.ipfs.uploadImage({
body: formData,
});
if (imageUpload.status === 200) {
const imageHash = imageUpload.body.result;
console.log(Image IPFS hash: ${imageHash});
}
// Upload metadata to IPFS
const metadataUpload = await apiClient.ipfs.uploadMetadata({
body: {
name: "My Token",
description: "Token description",
image_hash: imageHash, // From previous upload
social_links: [
{ label: "Twitter", url: "https://twitter.com/mytoken" },
{ label: "Discord", url: "https://discord.gg/mytoken" },
],
vesting_recipients: [
{ address: "0xabc...", amount: 5000 },
{ address: "0xdef...", amount: 5000 },
],
fee_receiver: "0x123...",
},
});
if (metadataUpload.status === 200) {
const metadataHash = metadataUpload.body.result;
console.log(Metadata IPFS hash: ${metadataHash});`
}
#### Get Swap Paths
`typescript
import { apiClient } from "@longdotxyz/shared";
// Basic usage (Codex only)
const paths = await apiClient.pathfinding.fetchTokenPaths({
params: { tokenInAddress: "0xTokenAddress" },
});
// With Kyber fallback (when amount provided)
const pathsWithFallback = await apiClient.pathfinding.fetchTokenPaths({
params: { tokenInAddress: "0xTokenAddress" },
query: {
amount: "1000000000000000000", // 1 token in wei
tokenOut: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // Optional: USDC
},
});
if (pathsWithFallback.status === 200) {
const { paths, paths_count } = pathsWithFallback.body;
paths.forEach((path) => {
if (path.source === "kyber") {
// Kyber route includes executable calldata
console.log("Router:", path.router_address);
console.log("Calldata:", path.encoded_calldata);
console.log("Expected output:", path.amount_out);
} else {
// Codex route includes liquidity metrics
console.log("Liquidity:", path.total_liquidity_usd);
console.log("Volume:", path.total_volume_usd);
}
});
}
`
Query Parameters:
- amount (optional): Swap amount in wei. When provided, enables Kyber fallback if Codex returns no paths.tokenOut
- (optional): Target token address. If omitted, queries all exit tokens (WETH, USDC, ETH on Base).
Response Fields:
- source: Either "codex" or "kyber" - indicates which service provided the routeencoded_calldata
- (Kyber only): Ready-to-execute swap calldatarouter_address
- (Kyber only): Kyber router contract addressamount_in
- (Kyber only): Input amount in weiamount_out
- (Kyber only): Expected output amount in weigas_estimate
- (Kyber only): Estimated gas for the swap
`typescript
import { PoolKey } from "@longdotxyz/shared";
const poolKey: PoolKey = {
currency0: "0x0000000000000000000000000000000000000000",
currency1: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
fee: 500,
tick_spacing: 10,
hooks: "0x0000000000000000000000000000000000000000",
};
`
`typescript
import { z } from "zod";
import { hex } from "@longdotxyz/shared";
// Validate and normalize hex addresses
const addressSchema = z.string().pipe(hex);
const validAddress = addressSchema.parse("0xabc..."); // Returns lowercase hex
`
`typescript
import { coerceBigInt } from "@longdotxyz/shared";
const amount = coerceBigInt.parse("1000000000000000000"); // Returns bigint
const amount2 = coerceBigInt.parse(1000n); // Also accepts bigint
`
`typescript
import { isNativeToken, isNativeTokenAddress } from "@longdotxyz/shared";
// Check if address is native token (ETH)
isNativeTokenAddress("0x0000000000000000000000000000000000000000"); // true
isNativeTokenAddress("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"); // true
// Check token object
isNativeToken({
address: "0x0000000000000000000000000000000000000000",
symbol: "ETH",
}); // true
`
`bashGenerate GraphQL types
pnpm codegen
$3
The GraphQL types are generated from a schema using
@graphql-codegen. Configuration is in codegen.ts.`bash
pnpm codegen
`API Contract Structure
All API contracts are defined using ts-rest and exported from
@longdotxyz/shared/contracts:- Auctions:
/auctions/* - Dynamic auction creation and management
- Quotes: /quotes/* - Uniswap V3/V4 swap quotes
- Communities: /communities/* - Community data management
- IPFS: /ipfs/*` - IPFS content creationUNLICENSED