bun add @aori/aori-tsor
npm install @aori/aori-tsor
yarn add @aori/aori-tsInteracting with the Aori API currently requires an API key. Inquire at https://aori.io/contact
When you have your API key, you can include it in any API request by passing it as an additional parameter to any of the SDK functions:
import { getQuote, submitSwap } from '@aori/aori-ts'; // Load API key from your preferred method const apiKey = process.env.AORI_API_KEY; // Use it with any API call const quote = await getQuote(quoteRequest, 'https://api.aori.io', apiKey); // Then submit a swap with the same key const swap = await submitSwap(swapRequest, 'https://api.aori.io', apiKey);You can also use API keys with WebSocket connections:
import { Aori } from '@aori/aori-ts'; // Create an Aori instance with API key const aori = await Aori.create('https://api.aori.io', 'wss://api.aori.io', apiKey); // Connect to WebSocket with optional filter and callbacks await aori.connect({ orderHash: '0x...', // Filter by specific order hash offerer: '0x...', // Filter by offerer address recipient: '0x...', // Filter by recipient address inputToken: '0x...', // Filter by input token address inputChain: 'arbitrum', // Filter by input chain outputToken: '0x...', // Filter by output token address outputChain: 'base', // Filter by output chain eventType: 'completed' // Filter by event type (created, received, completed, failed) }, { onMessage: (event) => console.log(event), onConnect: () => console.log('Connected!'), onDisconnect: (event) => console.log('Disconnected:', event), onError: (error) => console.error('WebSocket error:', error) }); // Check connection status console.log('Connected:', aori.isConnected()); // Disconnect when done aori.disconnect();The SDK supports two usage patterns and two initialization formats:
The options object format provides better developer experience with named parameters:
import { Aori } from '@aori/aori-ts'; // Simple initialization const aori = await Aori.create({}); // With API key only const aori = await Aori.create({ apiKey: process.env.AORI_API_KEY }); // With custom endpoints const aori = await Aori.create({ apiBaseUrl: 'https://staging-api.aori.io', wsBaseUrl: 'wss://staging-ws.aori.io', apiKey: process.env.STAGING_API_KEY }); // With token pre-loading const aori = await Aori.create({ apiKey: process.env.AORI_API_KEY, loadTokens: true }); // Advanced: custom chains and domain const aori = await Aori.create({ apiKey: process.env.AORI_API_KEY, chains: myCustomChains, domain: myCustomDomain, loadTokens: true });The original parameter format is still supported for backward compatibility:
// Simple initialization const aori = await Aori.create(); // With API key const aori = await Aori.create( 'https://api.aori.io', 'wss://api.aori.io', process.env.AORI_API_KEY ); // With token pre-loading const aori = await Aori.create( 'https://api.aori.io', 'wss://api.aori.io', process.env.AORI_API_KEY, true // loadTokens );For applications that need to maintain state (API keys, chain information, WebSocket connections), use the Aori class:
import { Aori } from '@aori/aori-ts'; // Create an Aori instance with API key const aori = await Aori.create('https://api.aori.io', 'wss://api.aori.io', apiKey); // Or use the new options object format const aori = await Aori.create({ apiBaseUrl: 'https://api.aori.io', wsBaseUrl: 'wss://api.aori.io', apiKey: apiKey }); // Use the instance methods const quote = await aori.getQuote(quoteRequest); const swap = await aori.submitSwap(swapRequest); // WebSocket functionality await aori.connect(); aori.disconnect();For simple one-off operations, use the standalone functions:
import { getQuote, submitSwap } from '@aori/aori-ts'; // Pass API key and URL to each function const quote = await getQuote(quoteRequest, 'https://api.aori.io', apiKey); const swap = await submitSwap(swapRequest, 'https://api.aori.io', apiKey);All API functions in the Aori SDK now support request cancellation using the native AbortSignal API. This allows you to cancel ongoing HTTP requests, which is especially useful for:
- Timeout handling: Cancel requests that take too long
- User cancellation: Allow users to cancel operations in progress
- Component cleanup: Cancel requests when React components unmount
- Race conditions: Cancel older requests when new ones are made
All functions accept an optional { signal } parameter as their last argument:
// Cancel request after 5 seconds const signal = AbortSignal.timeout(5000); const quote = await getQuote(quoteRequest, baseUrl, apiKey, { signal });import { getQuote, getOrderStatus } from '@aori/aori-ts'; // Set a 3-second timeout for quote requests try { const quote = await getQuote(quoteRequest, 'https://api.aori.io', apiKey, { signal: AbortSignal.timeout(3000) }); console.log('Quote received:', quote); } catch (error) { if (error.name === 'TimeoutError') { console.log('Quote request timed out after 3 seconds'); } } // Set a 10-second timeout for order status polling const status = await getOrderStatus(orderHash, 'https://api.aori.io', apiKey, { signal: AbortSignal.timeout(10000) });// Create an abort controller for manual cancellation const controller = new AbortController(); // Start a request const quotePromise = getQuote(quoteRequest, 'https://api.aori.io', apiKey, { signal: controller.signal }); // Cancel the request after 2 seconds setTimeout(() => { controller.abort('User cancelled the request'); }, 2000); try { const quote = await quotePromise; } catch (error) { if (error.name === 'AbortError') { console.log('Request was cancelled:', error.reason); } }import React, { useEffect, useState } from 'react'; import { getQuote } from '@aori/aori-ts'; function QuoteComponent({ quoteRequest }) { const [quote, setQuote] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { const controller = new AbortController(); const fetchQuote = async () => { setLoading(true); try { const result = await getQuote( quoteRequest, 'https://api.aori.io', apiKey, { signal: controller.signal } ); setQuote(result); } catch (error) { if (error.name !== 'AbortError') { console.error('Quote failed:', error); } } finally { setLoading(false); } }; fetchQuote(); // Cleanup: cancel the request if component unmounts return () => controller.abort(); }, [quoteRequest]); return loading ? <div>Loading...</div> : <div>{quote ? 'Quote loaded' : 'No quote'}</div>; }All the following functions support AbortSignal:
getQuote(request, baseUrl, apiKey, { signal })submitSwap(request, baseUrl, apiKey, { signal })executeSwap(quote, config, baseUrl, apiKey, { signal })getOrderStatus(orderHash, baseUrl, apiKey, { signal })pollOrderStatus(orderHash, baseUrl, options, apiKey, { signal })getOrderDetails(orderHash, baseUrl, apiKey, { signal })getOrder(orderHash, chains, baseUrl, apiKey, { signal })queryOrders(baseUrl, params, apiKey, { signal })fetchAllChains(baseUrl, apiKey, { signal })getDomain(baseUrl, apiKey, { signal })getChain(chain, baseUrl, apiKey, { signal })getChainByEid(eid, baseUrl, apiKey, { signal })getAddress(chain, baseUrl, apiKey, { signal })fetchAllTokens(baseUrl, apiKey, { signal, chain })getTokens(chain, baseUrl, apiKey, { signal })cancelOrder(orderHashOrCancelTx, txExecutor, baseUrl, apiKey, { signal })getCancelTx(orderHash, baseUrl, apiKey, { signal })canCancel(orderHash, orderDetails, baseUrl, apiKey, { signal })
The Aori class methods also support AbortSignal through the same pattern:
const aori = await Aori.create(); // All instance methods support signal parameter const quote = await aori.getQuote(quoteRequest, { signal: AbortSignal.timeout(5000) }); const swapResult = await aori.executeSwap(quote, config, { signal: controller.signal }); const status = await aori.getOrderStatus(orderHash, { signal: controller.signal }); const order = await aori.getOrder(orderHash, { signal: AbortSignal.timeout(3000) }); // Token methods also support AbortSignal await aori.loadTokens('ethereum', { signal: AbortSignal.timeout(3000) }); const tokens = await aori.fetchTokens('base', { signal: controller.signal }); // Cancellation methods also support AbortSignal const canCancel = await aori.canCancel(orderHash, { signal: AbortSignal.timeout(5000) }); const cancelTx = await aori.getCancelTx(orderHash, { signal: controller.signal }); const cancelResult = await aori.cancelOrder(orderHash, txExecutor, { signal: controller.signal });| Method | Endpoint | Description | Request Body |
|---|---|---|---|
GET | /chains | Get a list of supported chains | - |
GET | /domain | Get EIP-712 domain information | - |
GET | /tokens | Get a list of supported tokens | - |
POST | /quote | Get a quote | <QuoteRequest> |
POST | /swap | Execute Swap | <SwapRequest> |
POST | /cancel | Get cancellation transaction data | { "orderHash": "0x..." } |
GET | /data/query | Query Historical Orders Database | |
GET | /data/details/{orderHash} | Query Single Orders Database | - |
GET | /data/status/{orderHash} | Get Swap Details/Status | - |
WS | /stream | Open a Websocket Connection | - |
The domain endpoint provides EIP-712 domain information needed for typed data signing. This information is automatically fetched and cached when creating an Aori instance.
{ "domainTypeString": "EIP712Domain(string name,string version,address verifyingContract)", "name": "Aori", "orderTypeString": "Order(uint128 inputAmount,uint128 outputAmount,address inputToken,address outputToken,uint32 startTime,uint32 endTime,uint32 srcEid,uint32 dstEid,address offerer,address recipient)", "version": "0.3.1" }The swap endpoint acts as the primary endpoint for users to request quotes.
curl -X POST https://api.aori.io/quote \ -H "Content-Type: application/json" \ -H "x-api-key: your_api_key_here" \ -d '{ "offerer": "0x0000000000000000000000000000000000000001", "recipient": "0x0000000000000000000000000000000000000001", "inputToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "outputToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", "inputAmount": "100000000", "inputChain": "base", "outputChain": "arbitrum" }'{ "orderHash": "0x...", "signingHash": "0x...", "offerer": "0x0000000000000000000000000000000000000001", "recipient": "0x0000000000000000000000000000000000000001", "inputToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "outputToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", "inputAmount": "100000000", "outputAmount": "99999999", "inputChain": "base", "outputChain": "arbitrum", "startTime": "1700000000", "endTime": "1700000010", "estimatedTime": 3000, }The swap endpoint acts as the primary endpoint for users to post signed orders for execution.
curl -X POST https://api.aori.io/swap \ -H "Content-Type: application/json" \ -d '{ "orderHash": "0x...", "signature": "0x..." }'{ "orderHash": "0x...", "offerer": "0x0000000000000000000000000000000000000001", "recipient": "0x0000000000000000000000000000000000000001", "inputToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "outputToken": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", "inputAmount": "1000000000000000000", "outputAmount": "1000000000000000000", "inputChain": "base", "outputChain": "arbitrum", "startTime": "1700000000", "endTime": "1700000010", "status": "pending", "createdAt": "1700000000" }The cancel endpoint provides pre-calculated transaction data for cancelling orders. This endpoint handles all the complex logic including chain detection, LayerZero fee calculation, and ABI encoding.
curl -X POST https://api.aori.io/cancel \ -H "Content-Type: application/json" \ -H "x-api-key: your_api_key_here" \ -d '{ "orderHash": "0x89f0b7fcb38e0b97fb66701579583c038031c3034abfa8ff75e0f8914f65ccf3" }'{ "orderHash": "0x89f0b7fcb38e0b97fb66701579583c038031c3034abfa8ff75e0f8914f65ccf3", "to": "0x5f4e18f8D3D3952A02FBBE7cb9800D189059F66d", "data": "0x983f7fd189f0b7fcb38e0b97fb66701579583c038031c3034abfa8ff75e0f8914f65ccf3...", "value": "74173060168071", "chain": "ethereum" }The response provides all the data needed to execute the cancellation transaction:
orderHash: The order being cancelledto: Contract address to send the transaction todata: Encoded function call datavalue: Transaction value (LayerZero fees for cross-chain cancellations)chain: The chain where the cancellation should be executed
The data endpoint acts as the primary endpoint for users to query historical orders.
| Parameter | Type | Description |
|---|---|---|
| order_hash | String | Hash of the order |
| offerer | String | Address of the order creator |
| recipient | String | Address of the order recipient |
| input_token | String | Address of the token being sent |
| input_amount | String | Amount of input token |
| output_token | String | Address of the token being received |
| output_amount | String | Amount of output token |
| input_chain | String | Chain key for the input token (e.g., "arbitrum") |
| output_chain | String | Chain key for the output token (e.g., "base") |
| src_tx | Option | Source chain transaction hash |
| dst_tx | Option | Destination chain transaction hash |
| status | String | Order status (Pending, Received, Filled, Confirmed, Failed) |
| min_time | u64 | Unix timestamp, start of filter range by created_at |
| max_time | u64 | Unix timestamp, end of filter range by created_at |
| page | u64 | Page number (1-x) |
| limit | u64 | Results per page (1-100) |
| Chain | chainKey | chainId | eid | address | vm |
|---|---|---|---|---|---|
| Ethereum | ethereum | 1 | 30101 | 0x98AD96Ef787ba5180814055039F8E37d98ADea63 | EVM |
| Base | base | 8453 | 30184 | 0xFfe691A6dDb5D2645321e0a920C2e7Bdd00dD3D8 | EVM |
| Arbitrum | arbitrum | 42161 | 30110 | 0xFfe691A6dDb5D2645321e0a920C2e7Bdd00dD3D8 | EVM |
| Optimism | optimism | 10 | 30111 | 0xFfe691A6dDb5D2645321e0a920C2e7Bdd00dD3D8 | EVM |
You can easily fetch complete chain information or just the contract address using these helper functions:
import { getChain } from '@aori/aori-ts'; // Using chainKey (string) const optimismChain = await getChain("optimism"); console.log(optimismChain); // { chainKey: "optimism", chainId: 10, eid: 30111, address: "0x...", explorerUrl: "..." } // Using chainId (number) const baseChain = await getChain(8453); console.log(baseChain.address); // "0xFfe691A6dDb5D2645321e0a920C2e7Bdd00dD3D8" // With API key const ethereumChain = await getChain("ethereum", "https://api.aori.io", apiKey);When using the Aori class, you can easily get all supported chains at once:
import { Aori } from '@aori/aori-ts'; const aori = await Aori.create('https://api.aori.io', 'wss://api.aori.io', apiKey); // Get all chains as a mapping of chainKey -> ChainInfo const allChains = aori.getAllChains(); console.log(allChains); // { // base: { chainKey: "base", chainId: 8453, eid: 30184, address: "0x...", ... }, // arbitrum: { chainKey: "arbitrum", chainId: 42161, eid: 30110, address: "0x...", ... }, // ... // } // Iterate through all chains Object.entries(allChains).forEach(([chainKey, chainInfo]) => { console.log(`${chainKey}: Chain ID ${chainInfo.chainId}, EID ${chainInfo.eid}`); }); // Check if a specific chain is supported if ('polygon' in allChains) { console.log('Polygon is supported!'); } // Get all chain IDs const chainIds = Object.values(allChains).map(chain => chain.chainId); console.log('Supported chain IDs:', chainIds); // [1, 8453, 42161, 10] // Find chains by specific criteria const evmChains = Object.values(allChains).filter(chain => chain.vm === 'EVM'); console.log('EVM chains:', evmChains.length); // Get contract addresses for all chains const contractAddresses = Object.fromEntries( Object.entries(allChains).map(([key, chain]) => [key, chain.address]) ); console.log('Contract addresses:', contractAddresses);For standalone usage, you can use the fetchAllChains function:
import { fetchAllChains } from '@aori/aori-ts'; // Fetch all chains without creating an Aori instance const allChains = await fetchAllChains('https://api.aori.io', apiKey); // Same operations as above console.log('Available chains:', Object.keys(allChains));import { getAddress } from '@aori/aori-ts'; // Using chainKey (string) const optimismAddress = await getAddress("optimism"); console.log(optimismAddress); // "0xFfe691A6dDb5D2645321e0a920C2e7Bdd00dD3D8" // Using chainId (number) const baseAddress = await getAddress(8453); console.log(baseAddress); // "0xFfe691A6dDb5D2645321e0a920C2e7Bdd00dD3D8" // With API key const address = await getAddress("ethereum", "https://api.aori.io", apiKey);The Aori SDK automatically handles EIP-712 domain information needed for typed data signing. This information includes the domain name, version, and type definitions required for secure order signing.
When you create an Aori instance, domain information is automatically fetched and cached:
import { Aori } from '@aori/aori-ts'; // Domain info is automatically fetched and cached during creation const aori = await Aori.create('https://api.aori.io', 'wss://api.aori.io', apiKey); // Access cached domain information const domainInfo = aori.getDomain(); console.log(domainInfo); // { // domainTypeString: "EIP712Domain(string name,string version,address verifyingContract)", // name: "Aori", // orderTypeString: "Order(uint128 inputAmount,uint128 outputAmount,...)", // version: "0.3.1" // }For stateless usage, you can fetch domain information directly:
import { getDomain } from '@aori/aori-ts'; const domainInfo = await getDomain('https://api.aori.io', apiKey); console.log(`Domain: ${domainInfo.name} v${domainInfo.version}`);Domain information is automatically used when signing orders with EIP-712:
// When using the Aori class, domain info is automatically included const { orderHash, signature } = await aori.signReadableOrder( quote, walletWrapper, userAddress ); // Domain info from cache is used automatically // For standalone usage, domain info is fetched automatically if not provided const { orderHash, signature } = await signReadableOrder( quote, walletWrapper, userAddress, 'https://api.aori.io', apiKey ); // Domain info is fetched from API automaticallyThe Aori class provides a stateful interface for interacting with the Aori API. It automatically fetches chain information on initialization and maintains API configuration.
The Aori.create() method supports two calling patterns:
Legacy Parameter Format:
const aori = await Aori.create( apiBaseUrl?: string, // Default: 'https://api.aori.io' wsBaseUrl?: string, // Default: 'wss://api.aori.io' apiKey?: string, // Optional API key loadTokens?: boolean, // Optional: load all tokens during initialization chains?: Record<string, ChainInfo>, // Optional: custom chains domain?: DomainInfo // Optional: custom domain info );Options Object Format (Recommended):
const aori = await Aori.create({ apiBaseUrl?: string, // Default: 'https://api.aori.io' wsBaseUrl?: string, // Default: 'wss://api.aori.io' apiKey?: string, // Optional API key loadTokens?: boolean, // Optional: load all tokens during initialization chains?: Record<string, ChainInfo>, // Optional: custom chains domain?: DomainInfo // Optional: custom domain info });The loadTokens parameter allows you to pre-load all tokens during initialization:
// Don't load tokens (default behavior) const aori = await Aori.create(); // Legacy format - Load all tokens across all chains const aoriWithAllTokens = await Aori.create( 'https://api.aori.io', 'wss://api.aori.io', apiKey, true // Load all tokens ); // Options object format - Load all tokens const aoriWithAllTokens = await Aori.create({ apiBaseUrl: 'https://api.aori.io', wsBaseUrl: 'wss://api.aori.io', apiKey: apiKey, loadTokens: true }); // For specific chains, load them after creation const aori = await Aori.create({ apiKey }); // Load tokens for specific chains using instance method await aori.loadTokens('ethereum'); // Load Ethereum tokens await aori.loadTokens(8453); // Load Base tokens (chainId: 8453) await aori.loadTokens(); // Load all tokensPerformance Benefits: Pre-loading all tokens during initialization eliminates the need for separate API calls later when you call getTokens() or getAllTokens(). For specific chains, use the loadTokens() instance method after creation.
| Method | Description | Parameters | Return Type |
|---|---|---|---|
getQuote | Requests a quote for a token swap | request: QuoteRequest, options?: { signal?: AbortSignal } | Promise<QuoteResponse> |
signOrder | Signs an order using the provided private key | quoteResponse: QuoteResponse, signer: SignerType | Promise<string> |
signReadableOrder | Signs an order using EIP-712 typed data | quoteResponse: QuoteResponse, signer: TypedDataSigner, userAddress: string | Promise<{orderHash: string, signature: string}> |
submitSwap | Submits a signed swap order to the Aori API | request: SwapRequest, options?: { signal?: AbortSignal } | Promise<SwapResponse> |
executeSwap | Executes a swap (sign + submit for ERC20, submit + execute for native) | quote: QuoteResponse, config: SwapConfig, options?: { signal?: AbortSignal } | Promise<TransactionResponse | SwapResponse> |
getOrderStatus | Gets the current status of an order | orderHash: string, options?: { signal?: AbortSignal } | Promise<OrderStatus> |
pollOrderStatus | Polls the status of an order until completion or timeout | orderHash: string, options?: PollOrderStatusOptions, abortOptions?: { signal?: AbortSignal } | Promise<OrderStatus> |
getOrderDetails | Fetches detailed information about an order | orderHash: string, options?: { signal?: AbortSignal } | Promise<OrderDetails> |
getOrder | Fetches order details and parses into Order object | orderHash: string, options?: { signal?: AbortSignal } | Promise<Order> |
parseOrder | Parses QuoteResponse/SwapResponse/OrderDetails into Order object | order: QuoteResponse | SwapResponse | OrderDetails | Promise<Order> |
queryOrders | Queries orders with filtering criteria | params: QueryOrdersParams, options?: { signal?: AbortSignal } | Promise<QueryOrdersResponse> |
cancelOrder | Cancels an order by executing the cancellation transaction | orderHash: string, txExecutor: CancelTxExecutor, options?: { signal?: AbortSignal } | Promise<CancelOrderResponse> |
getCancelTx | Gets cancellation transaction data from the API | orderHash: string, options?: { signal?: AbortSignal } | Promise<CancelTx> |
canCancel | Checks if an order can be cancelled based on its state | orderHash: string, options?: { signal?: AbortSignal } | Promise<boolean> |
connect | Connects to the WebSocket server | filter?: SubscriptionParams, callbacks?: WebSocketCallbacks | Promise<void> |
disconnect | Disconnects from the WebSocket server | - | void |
isConnected | Checks if WebSocket is connected | - | boolean |
getChain | Gets chain info by chain identifier | chain: string | number | ChainInfo | undefined |
getChainByEid | Gets chain info by EID | eid: number | ChainInfo | undefined |
getChainInfoByEid | Gets chain info by EID (alias for getChainByEid) | eid: number | ChainInfo | undefined |
getAllChains | Gets all supported chains and their information | - | Record<string, ChainInfo> |
getDomain | Gets cached EIP-712 domain information | - | DomainInfo | null |
loadTokens | Loads tokens into cache from API | chain?: string | number, options?: { signal?: AbortSignal } | Promise<void> |
getAllTokens | Gets all cached tokens | - | TokenInfo[] |
getTokens | Gets cached tokens for specific chain | chain: string | number | TokenInfo[] |
fetchTokens | Fetches tokens from API (bypasses cache) | chain: string | number, options?: { signal?: AbortSignal } | Promise<TokenInfo[]> |
isNativeToken | Checks if a token address is the native token | tokenAddress: string | boolean |
getNativeTokenAddress | Gets the native token address | - | string |
isNativeSwap | Checks if a quote response is for a native token swap | quoteResponse: QuoteResponse | boolean |
executeNativeSwap | Executes a native token swap transaction | nativeResponse: NativeSwapResponse, txExecutor: TxExecutor, gasLimit?: string | Promise<TransactionResponse> |
constructNativeSwapTransaction | Constructs a native swap transaction request | nativeResponse: NativeSwapResponse, gasLimit?: string | TransactionRequest |
For simple operations without maintaining state, use these standalone functions:
| Function | Description | Parameters | Return Type |
|---|---|---|---|
getQuote | Requests a quote for a token swap | request: QuoteRequest, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<QuoteResponse> |
signOrder | Signs an order using the provided private key | quoteResponse: QuoteResponse, signer: SignerType | Promise<string> |
signReadableOrder | Signs an order using EIP-712 typed data | quoteResponse: QuoteResponse, signer: TypedDataSigner, userAddress: string, baseUrl?: string, apiKey?: string, inputChain?: ChainInfo, outputChain?: ChainInfo | Promise<{orderHash: string, signature: string}> |
submitSwap | Submits a signed swap order to the Aori API | request: SwapRequest, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<SwapResponse> |
executeSwap | Executes a swap (sign + submit for ERC20, submit + execute for native) | quote: QuoteResponse, config: SwapConfig, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<TransactionResponse | SwapResponse> |
getOrderStatus | Gets the current status of an order | orderHash: string, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<OrderStatus> |
pollOrderStatus | Polls the status of an order until completion or timeout | orderHash: string, baseUrl?: string, options?: PollOrderStatusOptions, apiKey?: string, abortOptions?: { signal?: AbortSignal } | Promise<OrderStatus> |
getOrderDetails | Fetches detailed information about an order | orderHash: string, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<OrderDetails> |
getOrder | Fetches order details and parses into Order object | orderHash: string, chains?: Record<string, ChainInfo>, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<Order> |
parseOrder | Parses QuoteResponse/SwapResponse/OrderDetails into Order object | order: QuoteResponse | SwapResponse | OrderDetails, chains?: Record<string, ChainInfo>, baseUrl?: string, apiKey?: string | Promise<Order> |
queryOrders | Queries orders with filtering criteria | baseUrl: string, params: QueryOrdersParams, apiKey?: string, options?: { signal?: AbortSignal } | Promise<QueryOrdersResponse> |
cancelOrder | Cancels an order by executing the cancellation transaction | orderHashOrCancelTx: string | CancelTx, txExecutor: CancelTxExecutor, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<CancelOrderResponse> |
getCancelTx | Gets cancellation transaction data from the API | orderHash: string, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<CancelTx> |
canCancel | Checks if an order can be cancelled based on its state | orderHash: string, orderDetails?: OrderDetails, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<boolean> |
fetchAllChains | Fetches the list of supported chains | baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<Record<string, ChainInfo>> |
getDomain | Fetches EIP-712 domain information for typed data signing | baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<DomainInfo> |
getChain | Fetches the chain information for a specific chain | chain: string | number, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<ChainInfo> |
getChainByEid | Fetches the chain information for a specific EID | eid: number, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<ChainInfo> |
getAddress | Fetches the contract address for a specific chain | chain: string | number, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<string> |
fetchAllTokens | Fetches all tokens, optionally filtered by chain | baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal, chain?: string | number } | Promise<TokenInfo[]> |
getTokens | Fetches tokens for a specific chain | chain: string | number, baseUrl?: string, apiKey?: string, options?: { signal?: AbortSignal } | Promise<TokenInfo[]> |
isNativeToken | Checks if a token address is the native token | tokenAddress: string | boolean |
isNativeQuoteResponse | Type guard for native quote responses | response: QuoteResponse | response is NativeQuoteResponse |
isERC20QuoteResponse | Type guard for ERC20 quote responses | response: QuoteResponse | response is ERC20QuoteResponse |
isNativeSwap | Checks if a quote response is for a native token swap | quoteResponse: QuoteResponse | boolean |
isNativeSwapResponse | Type guard for native swap responses | response: SwapResponse | response is NativeSwapResponse |
isERC20SwapResponse | Type guard for ERC20 swap responses | response: SwapResponse | response is ERC20SwapResponse |
executeNativeSwap | Executes a native token swap transaction | nativeResponse: NativeSwapResponse, txExecutor: TxExecutor, gasLimit?: string | Promise<TransactionResponse> |
validateNativeSwapResponse | Validates a native swap response | response: NativeSwapResponse | void |
constructNativeSwapTransaction | Constructs a native swap transaction request | nativeResponse: NativeSwapResponse, gasLimit?: string | TransactionRequest |
validateContractAddress | Validates a contract address against trusted addresses | contractAddress: string, trustedAddresses?: string[] | void |
validateDepositNativeCalldata | Validates transaction calldata for native deposits | data: string | boolean |
createTypedData | Creates EIP-712 typed data for order signing | quoteResponse: QuoteResponse, params: TypedDataParams | TypedData |
This example demonstrates how to use the Aori class for stateful API interactions:
import { Aori } from '@aori/aori-ts'; async function executeSwapWithClass() { // Create Aori instance with API key (legacy format) const aori = await Aori.create( 'https://api.aori.io', 'wss://api.aori.io', process.env.AORI_API_KEY ); // Or using options object (recommended) const aori = await Aori.create({ apiBaseUrl: 'https://api.aori.io', wsBaseUrl: 'wss://api.aori.io', apiKey: process.env.AORI_API_KEY }); // Create a quote request const quoteRequest = { offerer: "0x0000000000000000000000000000000000000001", recipient: "0x0000000000000000000000000000000000000001", inputToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", outputToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", inputAmount: "100000000", inputChain: "base", outputChain: "arbitrum" }; // Get quote using instance method const quote = await aori.getQuote(quoteRequest); console.log('Quote received:', quote); // ... sign the quote ... // Submit the swap using instance method const swapResponse = await aori.submitSwap({ orderHash: quote.orderHash, signature: signature }); // Check order status using instance method const status = await aori.getOrderStatus(swapResponse.orderHash); console.log('Order status:', status); // Use WebSocket functionality with filter and callbacks await aori.connect({ orderHash: swapResponse.orderHash, // Only listen to events for this specific order eventType: 'completed' // Only listen to completion events }, { onMessage: (event) => console.log('WebSocket event:', event), onConnect: () => console.log('WebSocket connected'), onDisconnect: (event) => console.log('WebSocket disconnected:', event), onError: (error) => console.error('WebSocket error:', error) }); // WebSocket events will be handled by the callbacks above aori.disconnect(); } executeSwapWithClass().catch(console.error);This example demonstrates how to use API keys from environment variables with standalone functions:
import dotenv from 'dotenv'; import { getQuote, submitSwap, getOrderStatus } from '@aori/aori-ts'; // Load environment variables dotenv.config(); async function executeSwap() { // Get API key from environment const apiKey = process.env.AORI_API_KEY; // Create a quote request const quoteRequest = { offerer: "0x0000000000000000000000000000000000000001", recipient: "0x0000000000000000000000000000000000000001", inputToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", outputToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", inputAmount: "100000000", inputChain: "base", outputChain: "arbitrum" }; // Include API key in all requests const quote = await getQuote(quoteRequest, 'https://api.aori.io', apiKey); console.log('Quote received:', quote); // ... sign the quote ... // Submit the swap with API key const swapResponse = await submitSwap({ orderHash: quote.orderHash, signature: signature }, 'https://api.aori.io', apiKey); // Check order status with API key const status = await getOrderStatus(swapResponse.orderHash, 'https://api.aori.io', apiKey); console.log('Order status:', status); } executeSwap().catch(console.error);This example demonstrates how to cancel an order using the SDK's cancellation functionality:
import { Aori } from '@aori/aori-ts'; import { useWalletClient } from 'wagmi'; async function cancelOrderExample() { const apiKey = process.env.AORI_API_KEY; const aori = await Aori.create({ apiBaseUrl: 'https://api.aori.io', wsBaseUrl: 'wss://api.aori.io', apiKey }); const orderHash = "0x89f0b7fcb38e0b97fb66701579583c038031c3034abfa8ff75e0f8914f65ccf3"; // 1. Check if the order can be cancelled const canCancel = await aori.canCancel(orderHash); if (!canCancel) { console.log("Order cannot be cancelled - it may be completed, already cancelled, or expired"); return; } // 2. Get cancellation transaction data const cancelTx = await aori.getCancelTx(orderHash); console.log(`Cancellation requires ${cancelTx.chain} network`); console.log(`LayerZero fee: ${cancelTx.value === "0" ? "0 ETH (single-chain)" : `${Number(cancelTx.value) / 1e18} ETH`}`); // 3. Create transaction executor (using wagmi as example) const walletClient = await connector?.getWalletClient(); const txExecutor = { address: userAddress, getChainId: async () => walletClient.chain?.id || 0, sendTransaction: async (request) => { const hash = await walletClient.sendTransaction({ to: request.to, data: request.data, value: BigInt(request.value), gas: request.gasLimit ? BigInt(request.gasLimit) : undefined, }); return { hash, wait: async () => { const { waitForTransactionReceipt } = await import('viem/actions'); return await waitForTransactionReceipt(walletClient, { hash }); } }; }, estimateGas: async (request) => { const { estimateGas } = await import('viem/actions'); return await estimateGas(walletClient, { to: request.to, data: request.data, value: BigInt(request.value), }); } }; // 4. Execute the cancellation try { const result = await aori.cancelOrder(orderHash, txExecutor); if (result.success) { console.log(`✅ Order cancelled successfully!`); console.log(`Transaction hash: ${result.txHash}`); console.log(`Cross-chain: ${result.isCrossChain ? 'Yes' : 'No'}`); if (result.fee) { console.log(`LayerZero fee paid: ${Number(result.fee) / 1e18} ETH`); } } else { console.error(`❌ Cancellation failed: ${result.error}`); } } catch (error) { console.error('Cancellation error:', error); } } // Usage with standalone functions import { canCancel, getCancelTx, cancelOrder } from '@aori/aori-ts'; async function cancelOrderStandalone() { const apiKey = process.env.AORI_API_KEY; const orderHash = "0x89f0b7fcb38e0b97fb66701579583c038031c3034abfa8ff75e0f8914f65ccf3"; // Check cancellability const canCancelResult = await canCancel(orderHash, undefined, 'https://api.aori.io', apiKey); if (!canCancelResult) return; // Get cancel data const cancelTx = await getCancelTx(orderHash, 'https://api.aori.io', apiKey); // Execute cancellation const result = await cancelOrder(orderHash, txExecutor, 'https://api.aori.io', apiKey); console.log('Cancellation result:', result); } cancelOrderExample().catch(console.error);These examples demonstrates how to use the SDK with a wallet in a frontend application:
import { useAccount } from "wagmi"; import { Aori, getQuote, signReadableOrder, submitSwap, getOrderStatus, } from "aori-ts"; // React component example with Aori class function SwapComponentWithClass() { const { address, connector } = useAccount(); // Get API key from environment variables or a secured source const apiKey = process.env.REACT_APP_AORI_API_KEY; const handleSwap = async () => { try { // Create Aori instance using options object const aori = await Aori.create({ apiBaseUrl: 'https://api.aori.io', wsBaseUrl: 'wss://api.aori.io', apiKey }); // 1. Get the quote first const quoteRequest = { offerer: address, recipient: address, inputToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", outputToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", inputAmount: "100000000", inputChain: "base", outputChain: "arbitrum" }; const quote = await aori.getQuote(quoteRequest); // 2. Get the wallet client: const walletClient = await connector?.getWalletClient(); // 3. Create a wrapper for the wallet client: const walletWrapper = { signTypedData: async (params) => { return walletClient.signTypedData({ account: params.account, domain: params.domain, types: params.types, primaryType: params.primaryType, message: params.message, }); }, }; // 4. Sign the order using EIP-712 (chains fetched automatically from quote): const { orderHash, signature } = await aori.signReadableOrder( quote, walletWrapper, address ); // Alternative: Optimize by pre-fetching and caching chain info to avoid repeated API calls // const inputChain = await getChain(quote.inputChain, "https://api.aori.io", apiKey); // const outputChain = await getChain(quote.outputChain, "https://api.aori.io", apiKey); // const { orderHash, signature } = await signReadableOrder( // quote, // walletWrapper, // address, // "https://api.aori.io", // apiKey, // inputChain, // Pre-fetched chain info // outputChain // Pre-fetched chain info // ); // 5. Submit the swap with signature: const swapRequest = { orderHash, signature, }; const swapResponse = await aori.submitSwap(swapRequest); console.log("Swap submitted successfully:", swapResponse); // 6. Check current order status: const status = await aori.getOrderStatus(swapResponse.orderHash); console.log(`Current order status: ${status.status}`); } catch (error) { console.error("Swap failed:", error); } }; return <button onClick={handleSwap}> Swap Tokens </button>; }function SwapComponentWithFunctions() { const { address, connector } = useAccount(); const apiKey = process.env.REACT_APP_AORI_API_KEY; const handleSwap = async () => { try { // 1. Get the quote first const quoteRequest = { offerer: address, recipient: address, inputToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", outputToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", inputAmount: "100000000", inputChain: "base", outputChain: "arbitrum" }; const quote = await getQuote(quoteRequest, "https://api.aori.io", apiKey); // 2. Get the wallet client: const walletClient = await connector?.getWalletClient(); // 3. Create a wrapper for the wallet client: const walletWrapper = { signTypedData: async (params) => { return walletClient.signTypedData({ account: params.account, domain: params.domain, types: params.types, primaryType: params.primaryType, message: params.message, }); }, }; // 4. Sign the order using EIP-712 (chains fetched automatically from quote): const { orderHash, signature } = await signReadableOrder( quote, walletWrapper, address, "https://api.aori.io", apiKey ); // Alternative: Optimize by pre-fetching and caching chain info to avoid repeated API calls // const inputChain = await getChain(quote.inputChain, "https://api.aori.io", apiKey); // const outputChain = await getChain(quote.outputChain, "https://api.aori.io", apiKey); // const { orderHash, signature } = await signReadableOrder( // quote, // walletWrapper, // address, // "https://api.aori.io", // apiKey, // inputChain, // Pre-fetched chain info // outputChain // Pre-fetched chain info // ); // 5. Submit the swap with signature: const swapRequest = { orderHash, signature, }; const swapResponse = await submitSwap(swapRequest, "https://api.aori.io", apiKey); console.log("Swap submitted successfully:", swapResponse); // 6. Check current order status: const status = await getOrderStatus(swapResponse.orderHash, "https://api.aori.io", apiKey); console.log(`Current order status: ${status.status}`); } catch (error) { console.error("Swap failed:", error); } }; return <button onClick={handleSwap}> Swap Tokens </button>; }This example demonstrates how to implement proper request cancellation and timeout handling:
import { getQuote, submitSwap, pollOrderStatus } from '@aori/aori-ts'; async function executeSwapWithTimeouts() { const apiKey = process.env.AORI_API_KEY; try { // 1. Get quote with 5-second timeout console.log('Requesting quote...'); const quote = await getQuote(quoteRequest, 'https://api.aori.io', apiKey, { signal: AbortSignal.timeout(5000) }); console.log('Quote received:', quote); // ... sign the quote ... // 2. Submit swap with 10-second timeout console.log('Submitting swap...'); const swapResponse = await submitSwap({ orderHash: quote.orderHash, signature: signature }, 'https://api.aori.io', apiKey, { signal: AbortSignal.timeout(10000) }); console.log('Swap submitted:', swapResponse); // 3. Poll order status with overall 5-minute timeout console.log('Monitoring order status...'); const finalStatus = await pollOrderStatus( swapResponse.orderHash, 'https://api.aori.io', { interval: 2000, // Check every 2 seconds maxAttempts: 150, // Maximum 150 attempts (5 minutes) onStatusChange: (status) => console.log(`Status changed to: ${status.status}`) }, apiKey, { signal: AbortSignal.timeout(300000) } // 5-minute overall timeout ); console.log('Final status:', finalStatus); } catch (error) { if (error.name === 'TimeoutError') { console.error('Operation timed out:', error.message); } else if (error.name === 'AbortError') { console.error('Operation was cancelled:', error.message); } else { console.error('Operation failed:', error); } } } // Usage with manual cancellation async function executeSwapWithManualCancellation() { const controller = new AbortController(); // Set up cancellation after 30 seconds const timeoutId = setTimeout(() => { controller.abort('Operation taking too long'); }, 30000); try { const quote = await getQuote(quoteRequest, 'https://api.aori.io', apiKey, { signal: controller.signal }); // Clear timeout if quote succeeds quickly clearTimeout(timeoutId); // Continue with swap... const swapResponse = await submitSwap(swapRequest, 'https://api.aori.io', apiKey, { signal: controller.signal }); console.log('Swap completed:', swapResponse); } catch (error) { clearTimeout(timeoutId); if (error.name === 'AbortError') { console.log('User cancelled the operation'); } else { console.error('Swap failed:', error); } } } // React hook for cancellable requests function useAoriSwap() { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const controllerRef = useRef(); const executeSwap = useCallback(async (quoteRequest) => { // Cancel any existing request if (controllerRef.current) { controllerRef.current.abort(); } controllerRef.current = new AbortController(); setLoading(true); setError(null); try { const quote = await getQuote( quoteRequest, 'https://api.aori.io', apiKey, { signal: controllerRef.current.signal } ); // Continue with signing and submission... // All using the same signal for consistent cancellation return quote; } catch (err) { if (err.name !== 'AbortError') { setError(err); } throw err; } finally { setLoading(false); } }, []); const cancel = useCallback(() => { if (controllerRef.current) { controllerRef.current.abort(); } }, []); // Cleanup on unmount useEffect(() => { return () => { if (controllerRef.current) { controllerRef.current.abort(); } }; }, []); return { executeSwap, cancel, loading, error }; }This example demonstrates how to use getAllChains() to build applications that work across multiple chains:
import { Aori } from '@aori/aori-ts'; async function buildMultiChainApp() { const aori = await Aori.create({ apiBaseUrl: 'https://api.aori.io', wsBaseUrl: 'wss://api.aori.io', apiKey }); // Get all supported chains const allChains = aori.getAllChains(); // Create a chain selector for a UI const chainOptions = Object.entries(allChains).map(([key, chain]) => ({ value: key, label: `${chain.chainKey} (${chain.chainId})`, chainId: chain.chainId, address: chain.address })); console.log('Chain options for UI:', chainOptions); // Validate user input against supported chains function validateChainInput(userChainInput: string | number): boolean { if (typeof userChainInput === 'string') { return userChainInput.toLowerCase() in allChains; } else { return Object.values(allChains).some(chain => chain.chainId === userChainInput); } } // Get optimal routes between chains function getAvailableRoutes() { const routes = []; const chainKeys = Object.keys(allChains); for (const inputChain of chainKeys) { for (const outputChain of chainKeys) { if (inputChain !== outputChain) { routes.push({ from: inputChain, to: outputChain, fromChainId: allChains[inputChain].chainId, toChainId: allChains[outputChain].chainId }); } } } return routes; } const availableRoutes = getAvailableRoutes(); console.log(`Total available routes: ${availableRoutes.length}`); // Check contract deployment status function checkContractDeployments() { const deployments = Object.entries(allChains).map(([key, chain]) => ({ chain: key, chainId: chain.chainId, contractAddress: chain.address, isDeployed: !!chain.address })); const deployedCount = deployments.filter(d => d.isDeployed).length; console.log(`Contracts deployed on ${deployedCount}/${deployments.length} chains`); return deployments; } checkContractDeployments(); // Build a quote request with validation async function requestQuoteWithValidation(inputChain: string, outputChain: string, amount: string) { // Validate chains are supported if (!validateChainInput(inputChain)) { throw new Error(`Input chain '${inputChain}' is not supported`); } if (!validateChainInput(outputChain)) { throw new Error(`Output chain '${outputChain}' is not supported`); } if (inputChain === outputChain) { throw new Error('Input and output chains must be different'); } const quoteRequest = { offerer: userAddress, recipient: userAddress, inputToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base outputToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum inputAmount: amount, inputChain: inputChain, outputChain: outputChain }; console.log(`Requesting quote: ${inputChain} → ${outputChain}`); return await aori.getQuote(quoteRequest); } // Example usage try { const quote = await requestQuoteWithValidation('base', 'arbitrum', '1000000'); console.log('Quote received:', quote); } catch (error) { console.error('Quote failed:', error.message); } } buildMultiChainApp().catch(console.error); // Performance optimization example with chain caching async function performanceOptimizedBatch() { const apiKey = process.env.AORI_API_KEY; // Pre-fetch all chains once to avoid repeated API calls const allChains = await fetchAllChains('https://api.aori.io', apiKey); const orders = [ { inputChain: 'base', outputChain: 'arbitrum', amount: '1000000' }, { inputChain: 'arbitrum', outputChain: 'optimism', amount: '2000000' }, { inputChain: 'optimism', outputChain: 'base', amount: '1500000' } ]; for (const order of orders) { try { // Get quote const quote = await getQuote({ offerer: userAddress, recipient: userAddress, inputToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', outputToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', inputAmount: order.amount, inputChain: order.inputChain, outputChain: order.outputChain }, 'https://api.aori.io', apiKey); // Get cached chain info (no API calls needed!) const inputChain = allChains[order.inputChain]; const outputChain = allChains[order.outputChain]; // Sign with cached chain info - this avoids 2 API calls per order const { orderHash, signature } = await signReadableOrder( quote, walletWrapper, userAddress, 'https://api.aori.io', apiKey, inputChain, // Use cached chain info outputChain // Use cached chain info ); console.log(`Order ${orderHash} signed efficiently with cached chain data`); // Submit swap const swapResponse = await submitSwap({ orderHash, signature }, 'https://api.aori.io', apiKey); console.log(`Swap submitted: ${swapResponse.orderHash}`); } catch (error) { console.error(`Failed to process order ${order.inputChain} → ${order.outputChain}:`, error); } } } // React component for chain selection function ChainSelector({ onChainSelect }) { const [chains, setChains] = useState({}); const [loading, setLoading] = useState(true); useEffect(() => { async function loadChains() { try { const aori = await Aori.create(); const allChains = aori.getAllChains(); setChains(allChains); } catch (error) { console.error('Failed to load chains:', error); } finally { setLoading(false); } } loadChains(); }, []); if (loading) return <div>Loading chains...</div>; return ( <select onChange={(e) => onChainSelect(e.target.value)}> <option value="">Select a chain</option> {Object.entries(chains).map(([key, chain]) => ( <option key={key} value={key}> {chain.chainKey} (Chain ID: {chain.chainId}) </option> ))} </select> ); }This project is released under the MIT License.
