Skip to main content

API

Cross-chain Providers

A set of classes and utilities for handling cross-chain operations through various protocols.

Methods

  • createCrossChainProvider(protocolName: string, config?: ProviderConfig): CrossChainProvider

    Creates a provider instance for a supported cross-chain protocol. Config is optional for Across (uses mainnet defaults), required for OIF.

    import { createCrossChainProvider } from "@wonderland/interop-cross-chain";

    // Across - config optional (defaults to mainnet)
    const provider = createCrossChainProvider("across");

    // Across - with testnet config
    const testnetProvider = createCrossChainProvider("across", { isTestnet: true });

    // Relay - config optional (defaults to mainnet)
    const relayProvider = createCrossChainProvider("relay");

    // Relay - with API key
    const relayWithKey = createCrossChainProvider("relay", {
    apiKey: "your-api-key",
    });

    // OIF - config required
    const oifProvider = createCrossChainProvider("oif", {
    solverId: "my-solver",
    url: "https://solver.example.com",
    });

CrossChainProvider Class

An abstract class that defines the interface for cross-chain protocol providers.

  • protocolName: string

    The name of the protocol this provider implements.

    const protocolName = provider.protocolName; // e.g., "across"
  • providerId: string

    The unique provider instance ID.

    const providerId = provider.providerId; // e.g., "across-1"
  • getQuotes(params: QuoteRequest): Promise<Quote[]>

    Fetches quotes for a cross-chain operation.

    const quotes = await provider.getQuotes({
    user: "0xYourAddress",
    input: {
    chainId: 1,
    assetAddress: "0xTokenAddress",
    amount: "1000000000000000000",
    },
    output: {
    chainId: 42161,
    assetAddress: "0xOutputTokenAddress",
    recipient: "0xRecipientAddress",
    },
    swapType: "exact-input",
    });
  • buildQuote(params: BuildQuoteRequest): Promise<Quote>

    Builds a quote locally without calling a solver API. Returns a Quote with a TransactionStep that the consumer can execute directly. Both input and output amounts are required (the user controls the fee). Not all providers support this -- throws ProviderExecuteNotImplemented if unsupported.

    const quote = await provider.buildQuote({
    user: "0xYourAddress",
    input: { chainId: 11155111, assetAddress: "0xInputToken", amount: "1000000" },
    output: { chainId: 84532, assetAddress: "0xOutputToken", amount: "980000" },
    escrowContractAddress: "0xSpokePoolAddress",
    fillDeadline: Math.floor(Date.now() / 1000) + 3600,
    });
  • submitOrder(quote: Quote, signature: Hex): Promise<SubmitOrderResponse>

    Submits a signed order for gasless execution.

    const response = await provider.submitOrder(quote, signature);
  • getTrackingConfig(): TrackingConfig

    Returns protocol-specific tracking configuration for intent monitoring.

    const config = provider.getTrackingConfig();
    // config.openedIntentParserConfig — how to parse opened intents from origin chain
    // config.fillWatcherConfig — how to watch for fills on destination chain
    // config.preTrackerConfig — optional pre-tracking step (e.g., notify provider API)

Aggregator

A utility for managing multiple cross-chain providers and executing operations across them.

Methods

  • createAggregator(config: AggregatorConfig): Aggregator

    Creates an aggregator instance for managing multiple providers.

    import {
    AssetDiscoveryFactory,
    createAggregator,
    OrderTrackerFactory,
    SortingStrategyFactory,
    } from "@wonderland/interop-cross-chain";

    const aggregator = createAggregator({
    providers: [acrossProvider],
    sortingStrategy: SortingStrategyFactory.createStrategy("bestOutput"), // optional
    timeoutMs: 15000, // optional
    trackerFactory: new OrderTrackerFactory({ rpcUrls }), // optional
    discoveryFactory: new AssetDiscoveryFactory(), // optional (default)
    });

Aggregator Class

A class that manages multiple cross-chain providers and coordinates their operations.

  • getQuotes(params: QuoteRequest): Promise<GetQuotesResponse>

    Retrieves quotes from all available providers for a given operation.

    const response = await aggregator.getQuotes({
    user: "0xYourAddress",
    input: {
    chainId: 1,
    assetAddress: "0xInputToken",
    amount: "1000000000000000000",
    },
    output: {
    chainId: 42161,
    assetAddress: "0xOutputToken",
    recipient: "0xRecipient",
    },
    swapType: "exact-input",
    });

    // Handle results
    if (response.quotes.length > 0) {
    const bestQuote = response.quotes[0];
    }
    response.errors.forEach((error) => console.error(error.errorMsg));
  • buildQuote(providerId: string, params: BuildQuoteRequest): Promise<ExecutableQuote>

    Builds a quote locally for a specific provider without calling a solver API. The user provides both amounts (controlling the fee) and a fill deadline. The returned quote feeds into the same execution and tracking pipeline as API-fetched quotes.

    const quote = await aggregator.buildQuote("across", {
    user: "0xYourAddress",
    input: { chainId: 11155111, assetAddress: "0xInputToken", amount: "1000000" },
    output: { chainId: 84532, assetAddress: "0xOutputToken", amount: "980000" },
    escrowContractAddress: "0xSpokePoolAddress",
    fillDeadline: Math.floor(Date.now() / 1000) + 3600,
    });
  • submitOrder(quote: ExecutableQuote, signatureOrResults: Hex | StepResult[]): Promise<SubmitOrderResponse>

    Submits an order for execution. Pass a single Hex signature for single-step orders, or an array of StepResult for multi-step orders.

    // Single signature
    const response = await aggregator.submitOrder(quote, signature);

    // Multi-step results
    const results: StepResult[] = [{ stepIndex: 0, signature: "0x..." }];
    const response = await aggregator.submitOrder(quote, results);
  • track(params: TrackParams): OrderTracker

    Starts tracking an executed transaction with real-time events.

    import { OrderStatus } from "@wonderland/interop-cross-chain";

    const tracker = aggregator.track({
    txHash: hash,
    providerId: quote.provider,
    originChainId: 11155111,
    destinationChainId: 84532,
    timeout: 300000,
    });

    tracker.on(OrderStatus.Finalized, (update) => console.log("Finalized!", update.fillTxHash));
  • getOrderStatus(params: GetOrderStatusParams): Promise<OrderTrackingInfo>

    Gets the current status of an order without watching.

    const status = await aggregator.getOrderStatus({
    txHash: "0x...",
    providerId: "across",
    originChainId: 11155111,
    });
    console.log(status.status); // OrderStatus
  • prepareTracking(providerId: string): OrderTracker

    Returns an OrderTracker instance for a provider. Use this to set up event listeners before sending a transaction.

    const tracker = aggregator.prepareTracking(quote.provider);
    tracker.on(OrderStatus.Finalized, (update) => console.log("Done!", update.fillTxHash));
    // ...then send the transaction and call tracker.startTracking(...)
  • discoverAssets(options?: AssetDiscoveryOptions): Promise<DiscoveredAssets>

    Discovers supported assets from all configured providers.

    const discovered = await aggregator.discoverAssets({ chainIds: [1, 42161] });
    // discovered.tokensByChain — token addresses grouped by numeric chain ID
    // discovered.tokenMetadata — token metadata nested by chain ID then lowercase address
  • getProvidersForRoute(query: RouteQuery): Promise<string[]>

    Returns provider IDs that support a given origin/destination asset pair. Uses plain 0x addresses and numeric chain IDs.

    const providers = await aggregator.getProvidersForRoute({
    originChainId: 1,
    originAsset: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    destinationChainId: 42161,
    destinationAsset: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
    });

Sorting Strategies

SortingStrategyFactory

A factory for creating quote sorting strategies.

  • createStrategy(type: string): SortingStrategy

    Creates a sorting strategy instance.

    import { SortingStrategyFactory } from "@wonderland/interop-cross-chain";

    const strategy = SortingStrategyFactory.createStrategy("bestOutput");

    Available strategies:

    • bestOutput - Sorts quotes by highest output amount (default)

    Additional sorting strategies may be added in future releases.

Order Tracker

A utility for tracking cross-chain orders from initiation to completion (ERC-7683 open event parsing + fill watching).

Methods

  • createOrderTracker(provider: CrossChainProvider, config: OrderTrackerConfig): OrderTracker

    Creates an order tracker instance for a specific provider.

    import { createOrderTracker } from "@wonderland/interop-cross-chain";

    const tracker = createOrderTracker(acrossProvider, {
    rpcUrls: {
    11155111: "https://sepolia.infura.io/v3/YOUR_API_KEY",
    84532: "https://base-sepolia.g.alchemy.com/v2/YOUR_API_KEY",
    },
    });

OrderTracker Class

A class that tracks cross-chain orders through their lifecycle.

  • watchOrder(params: WatchOrderParams): AsyncGenerator<OrderTrackerYield>

    Watches an order and yields status updates as it progresses.

    import { OrderStatus, OrderTrackerYieldType } from "@wonderland/interop-cross-chain";

    for await (const item of tracker.watchOrder({
    txHash: "0x...",
    originChainId: 11155111,
    destinationChainId: 84532,
    timeout: 300000, // Optional, in milliseconds
    })) {
    if (item.type === OrderTrackerYieldType.Timeout) break;
    console.log(item.update.status, item.update.message);
    if (item.update.status === OrderStatus.Finalized) break;
    }
  • getOrderStatus(txHash: Hex, originChainId: number): Promise<OrderTrackingInfo>

    Gets the current status of an order without watching.

    const status = await tracker.getOrderStatus("0x...", 11155111);
    console.log(status.status); // OrderStatus

Types

QuoteRequest

interface QuoteRequest {
user: string;
input: {
chainId: number;
assetAddress: string;
amount?: string;
};
output: {
chainId: number;
assetAddress: string;
amount?: string;
recipient?: string;
calldata?: string;
};
swapType?: "exact-input" | "exact-output"; // default: "exact-input"
}

BuildQuoteRequest

interface BuildQuoteRequest {
user: string;
input: {
chainId: number;
assetAddress: string;
amount: string; // required (unlike QuoteRequest)
};
output: {
chainId: number;
assetAddress: string;
amount: string; // required (unlike QuoteRequest)
recipient?: string;
calldata?: string;
};
escrowContractAddress: string; // settlement contract address
fillDeadline: number; // unix timestamp
orderDataType?: string; // hex-encoded, max 32 bytes (e.g. "0x00")
orderData?: string; // hex-encoded (e.g. "0x1234")
}

Quote

interface Quote {
order: Order;
preview: {
inputs: { chainId: number; accountAddress: string; assetAddress: string; amount: string }[];
outputs: {
chainId: number;
accountAddress: string;
assetAddress: string;
amount: string;
}[];
};
provider: string;
validUntil?: number; // quote validity (unix timestamp)
eta?: number; // estimated time to completion (seconds)
quoteId?: string;
failureHandling?: string;
partialFill?: boolean;
fees?: QuoteFees;
tracking?: QuoteTracking;
metadata?: Record<string, unknown>;
}

QuoteFeeEntry

interface QuoteFeeEntry {
amount: string; // Raw amount in token units
amountUsd?: string; // USD equivalent
token?: {
symbol: string;
decimals: number;
address?: string;
};
}

QuoteTracking

interface QuoteTracking {
orderId?: string; // Protocol-specific order identifier for tracking
}

QuoteFees

interface QuoteFees {
bridgeFee?: QuoteFeeEntry; // Bridge/relayer fee
bridgeFeePct?: string; // Fee as percentage (wei-encoded, 1e18 = 100%)
originGas?: QuoteFeeEntry; // Origin chain gas cost
}

Order

interface Order {
steps: (SignatureStep | TransactionStep)[];
lock?: LockMechanism;
checks?: OrderChecks;
metadata?: Record<string, unknown>;
}

OrderChecks

interface OrderChecks {
allowances?: {
chainId: number;
tokenAddress: string;
owner: string;
spender: string;
required: string;
}[];
}

ExecutableQuote

interface ExecutableQuote extends Quote {
// Use quote.provider for provider identification
}

StepResult

interface StepResult {
stepIndex: number; // Index into order.steps[]
signature: Hex; // EIP-712 signature
}

GetQuotesResponse

interface GetQuotesResponse {
quotes: ExecutableQuote[];
errors: { errorMsg: string; error: Error }[];
}

TokenTransfer

ERC-7683 token transfer structure used in OrderTrackingInfo.

interface TokenTransfer {
token: Hex;
amount: bigint;
recipient: Hex;
chainId: number;
}

FillInstruction

ERC-7683 fill instruction for destination chain.

interface FillInstruction {
destinationChainId: number;
destinationSettler: Hex;
originData: Hex;
}

OrderTrackingInfo

interface OrderTrackingInfo {
status: OrderStatus;
orderId: Hex;
openTxHash: Hex;
user: Address;
originChainId: number;
openDeadline: number;
fillDeadline: number;
maxSpent: TokenTransfer[];
minReceived: TokenTransfer[];
fillInstructions: FillInstruction[];
fillEvent?: FillEvent;
failureReason?: OrderFailureReason;
}

OrderTrackingUpdate

interface OrderTrackingUpdate {
status: OrderStatus;
orderId?: Hex;
openTxHash?: Hex;
fillTxHash?: Hex;
timestamp: number;
message: string;
failureReason?: OrderFailureReason;
}

FillEvent

interface FillEvent {
fillTxHash: Hex;
blockNumber?: bigint;
timestamp: number;
originChainId: number;
orderId: Hex;
relayer?: Address;
recipient?: Address;
metadata?: unknown;
}

Provider Configuration

Across

FieldTypeRequiredDescription
isTestnetbooleanNoUse testnet API (default: false)
apiUrlstringNoCustom API endpoint URL (overrides isTestnet)
providerIdstringNoCustom provider identifier

Payload validation:

OperationValidation
Simple bridge (same token)Full validation (depositor, recipient, tokens, amount, chain)
Cross-chain swap (different tokens)Coming soon

Relay

FieldTypeRequiredDescription
baseUrlstringNoCustom API base URL (overrides isTestnet)
isTestnetbooleanNoUse testnet API (default: false)
providerIdstringNoCustom provider identifier (default: "relay")
apiKeystringNoRelay API key for authentication

OIF

FieldTypeRequiredDescription
solverIdstringYesSolver identifier
urlstringYesSolver API endpoint URL
headersobjectNoCustom HTTP headers
adapterMetadataobjectNoAdditional metadata for the solver
providerIdstringNoCustom provider identifier
supportedLocksstring[]NoLock mechanisms to request (e.g. ["oif-escrow"], ["compact-resource-lock"]). Default: ["oif-escrow"]
submissionModesstring[]NoExecution modes: ["user-transaction"], ["gasless"], or both (default). Controls order types

Lock mechanism mapping:

Lock MechanismOIF Order Types
oif-escrowoif-escrow-v0, oif-3009-v0
compact-resource-lockoif-resource-lock-v0

Supported order types:

  • oif-escrow-v0 — Permit2-based escrow (gasless)
  • oif-3009-v0 — EIP-3009 transfer with authorization (gasless)
  • oif-resource-lock-v0 — Compact resource locking (gasless)
  • oif-user-open-v0 — User executes transaction directly

Payload validation:

Order TypeValidation
oif-escrow-v0token, amount, deadline
oif-resource-lock-v0token, amount, sponsor, expiration
oif-3009-v0from, value, token address, expiration
oif-user-open-v0allowances (token, user, spender, amount)

References