LayerHopdocs

Reference

SDK reference

The @layerhop/sdk TypeScript client — LayerHop class options, quote, buildTx, submit, status, watch, types and errors.

Open in ClaudeOpen in ChatGPT

@layerhop/sdk is a thin, typed client for the REST API. It has no runtime dependencies besides @layerhop/shared, uses the global fetch, and works in Node 20+, browsers and edge runtimes.

Coming soon

publication on npm. Inside the monorepo use "@layerhop/sdk": "workspace:*".

new LayerHop(options?)#

TypeScript
import { LayerHop } from "@layerhop/sdk";

const lh = new LayerHop({
  baseUrl: "http://localhost:8787",
  apiKey: process.env.LAYERHOP_API_KEY,
  channel: "api",
});
Option Type Default Description
baseUrl string https://api.layerhop.com API origin, without /v1. A trailing slash is removed.
apiKey string — Sent as the x-api-key header. Not enforced by the API yet.
channel "api" | "web" | "widget" | "bot" "api" Fee channel sent with every quote.
fetch typeof fetch globalThis.fetch Custom fetch (tests, proxies, retries).

quote(params)#

Calls GET /v1/quote. Returns every successful quote, best for the user first.

TypeScript
quote(p: QuoteParams): Promise<QuoteResponse>
Param Type Description
srcChain string | number Chain id or slug, e.g. "base", 8453.
srcToken string Symbol from the token list or address / mint.
amount string Integer string in base units of srcToken.
dstChain string | number Chain id or slug.
dstToken string Symbol or address / mint.
sender string Address that signs on the source chain.
recipient string Address that receives on the destination chain.
slippageBps number? Default 50. Range 1–5000.
TypeScript
interface QuoteResponse {
  best: Quote;     // same as quotes[0]
  quotes: Quote[];
  errors: { provider: string; code: string; message: string }[];
}

interface Quote {
  quoteId: string;
  provider: ProviderId;      // "jupiter" | "relay" | "debridge" | "zerox" | "lifi" | …
  dstAmount: string;         // expected output, base units
  dstAmountMin: string;      // after slippage
  estimatedSeconds: number;
  fees: { ourFeeBps: number; providerFeeUsd?: number; gasUsd?: number };
  expiresAt: number;         // unix seconds
}

buildTx(quoteId)#

Calls POST /v1/orders and returns only the transaction.

TypeScript
buildTx(quoteId: string): Promise<BuiltTx>

type BuiltTx = EvmTx | SvmTx;

type EvmTx = {
  vm: "evm";
  chainId: number;
  to: string;
  data: string;
  value: string; // wei
  approval?: { token: string; spender: string; amount: string };
};

type SvmTx = {
  vm: "svm";
  serializedTx: string;   // base64 VersionedTransaction
  submitViaApi?: boolean; // sign only, then call submit()
};

Narrow on tx.vm. See Approvals and the submitViaApi flow.

submit(quoteId, signedTransaction)#

Calls POST /v1/orders/submit. Only for SvmTx with submitViaApi: true. Returns the Solana transaction signature.

TypeScript
submit(quoteId: string, signedTransaction: string /* base64 */): Promise<string>

status(provider, id)#

Calls GET /v1/orders/{provider}/{id}. The id is URL-encoded for you.

TypeScript
status(provider: ProviderId, id: string): Promise<OrderStatus>

interface OrderStatus {
  provider: ProviderId;
  id: string;
  state: "pending" | "filled" | "refunded" | "failed" | "unknown";
  srcTxHash?: string;
  dstTxHash?: string;
}

Which id to pass per provider: Order tracking.

watch(provider, id, options?)#

Polls status() and yields each change of state until it is filled, refunded or failed, or until the timeout.

TypeScript
watch(provider: ProviderId, id: string, opts?: { intervalMs?: number; timeoutMs?: number }): AsyncGenerator<OrderStatus>
Option Default
intervalMs 3000
timeoutMs 1800000 (30 minutes)
TypeScript
for await (const s of lh.watch("debridge", srcTxHash)) console.log(s.state);

When the timeout is reached the generator simply ends; check the last state you saw. Errors from status() are thrown out of the loop — wrap it if you want to keep polling through transient provider errors.

LayerHopApiError#

Every non-2xx response is thrown as LayerHopApiError:

Property Type Description
code string Stable error code ("INTERNAL" if the body had none).
message string Human-readable message.
status number HTTP status.
requestId string? Request id for support.
TypeScript
import { LayerHopApiError } from "@layerhop/sdk";

try {
  await lh.buildTx(id);
} catch (e) {
  if (e instanceof LayerHopApiError && e.code === "QUOTE_EXPIRED") { /* re-quote */ }
}

Re-exports#

For convenience the SDK re-exports from @layerhop/shared:

Export What
CHAINS, getChain(idOrSlug) The chain registry.
TOKENS, findToken(chainId, symbolOrAddress) The built-in token list.
SOLANA_CHAIN_ID 7565164, LayerHop's id for Solana.
EVM_NATIVE, SOL_NATIVE Native coin addresses (0x000…000, wrapped-SOL mint).
Types BuiltTx, EvmTx, SvmTx, OrderStatus, ProviderId, FeeChannel.
TypeScript
import { findToken, getChain } from "@layerhop/sdk";

const base = getChain("base")!;               // { id: 8453, … }
const usdc = findToken(base.id, "USDC")!;     // { decimals: 6, address: "0x8335…" }
const amount = (100n * 10n ** BigInt(usdc.decimals)).toString(); // "100000000"

Coming soon

@layerhop/react hooks (useQuote, useSwap, useOrderStatus, useTokens) and Python, Go and Rust SDKs generated from the OpenAPI spec.