> ## Documentation Index
> Fetch the complete documentation index at: https://docs.walletsuite.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Samples

> Copy-paste WalletSuite SDK samples for common wallet integrations, from local key derivation in testing to bring-your-own-signer in production.

## Crypto & Wallets

<Warning>
  This section demonstrates local key derivation for testing and development. In production, keys live in your existing key-management system (KMS, HSM, or custodian) — use the SDK's prepare → broadcast surface and sign with that infrastructure. See [Bring your own signer](/sdk/end-to-end-token-transfer-flow#bring-your-own-signer).
</Warning>

<Steps>
  <Step>
    #### Create a new wallet (mnemonic) and derive Ethereum

    default path `m/44'/60'/0'/0/0`

    ```ts theme={null}
    import { WalletSuiteSDK } from "@walletsuite/wallet-sdk";

    const sdk = new WalletSuiteSDK({
      apiKey: process.env.WALLETSUITE_API_KEY!,
      env: "prod",
    });

    await sdk.init();

    const { mnemonic, wallet: w } = await sdk.createWallet(); // 12 words by default
    const eth = await w.deriveEthereum();

    console.log("mnemonic:", mnemonic);
    console.log("eth.address:", eth.address);
    console.log(
      "eth.privateKeyHex (64 hex):",
      eth.privateKeyHex.slice(0, 10) + "…",
    );
    console.log("eth.publicKeyHex (130 hex):", eth.publicKeyHex.slice(0, 12) + "…");
    ```

    Return object shape:

    ```ts theme={null}
    // DerivedKey
    {
      privateKeyHex: string; // 64 hex chars
      publicKeyHex: string; // 130 hex chars (uncompressed secp256k1)
      address: string; // 0x… (EVM address)
    }
    ```

    <Warning>
      Security: never log full private keys in production. Above we truncate for demonstration.
    </Warning>
  </Step>

  <Step>
    #### Derive Tron

    default path `m/44'/195'/0'/0/0`

    ```ts theme={null}
    const tron = await w.deriveTron();
    console.log("tron.address:", tron.address);
    console.log("tron.privateKeyHex:", tron.privateKeyHex.slice(0, 10) + "…");
    console.log("tron.publicKeyHex:", tron.publicKeyHex.slice(0, 12) + "…");
    ```

    Return object shape:

    ```ts theme={null}
    {
      privateKeyHex: string; // 64 hex chars
      publicKeyHex: string; // 130 hex chars
      address: string; // T… (base58) or 41… hex depending on encoding
    }
    ```
  </Step>
</Steps>

***

## API calls through SDK

Assume:

```ts theme={null}
// Using the sdk instance created above:
const api = sdk.api;
```

<Steps>
  <Step>
    #### Prices — by symbol

    ```ts theme={null}
    const price = await api.getPriceBySymbol("ETH", "USD");
    console.log("symbol:", price.symbol);
    console.log("value:", price.value);
    console.log("updatedAt:", price.updatedAt);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      symbol: string; // e.g. "ETH"
      basePair: string; // e.g. "USD" (API supports other basePairs as well e.g. EURO, AED etc.)
      value: number; // latest price
      updatedAt: string; // ISO timestamp
    }
    ```
  </Step>

  <Step>
    #### Prices — by contract address

    ```ts theme={null}
    const p2 = await api.getPriceByContract("0xA0b86991…", "ethereum", "USD");
    console.log("symbol:", p2.symbol);
    console.log("value:", p2.value);
    ```

    Returned (brief): same shape as above.
  </Step>

  <Step>
    #### Blocks — latest indexed block information

    ```ts theme={null}
    const block = await api.getLatestBlocks("ethereum");
    console.log("number:", block.number);
    console.log("hash:", block.hash);
    console.log("timestamp:", block.timestamp);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      number: number;
      hash: string;
      parentHash?: string;
      timestamp: number;   // unix milliseconds
    }
    ```
  </Step>

  <Step>
    #### Balances — native balance

    ```ts theme={null}
    const bal = await api.getNativeBalance("0xYourAddress", "ethereum", "USD");
    console.log("ok:", bal.ok);
    console.log("amount:", bal.data?.amount);
    console.log("symbol:", bal.data?.symbol);
    console.log("fiatValue:", bal.data?.fiatValue);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean;
      code: string;
      message: string;
      data?: {
        chain: string; symbol: string; decimals: number; address: string;
        smallestUnit: string | number; amount: number; fiatCurrency?: string; fiatValue?: number;
      };
    }
    ```
  </Step>

  <Step>
    #### Balances — native plus token balances

    ```ts theme={null}
    const res = await api.getAssetBalances("0xYourAddress", {
      chain: "ethereum",
      fiat: "USD",
      assetIds: [
        "0xdAC17F958D2ee523a2206206994597C13D831ec7", // USDT
        "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC
      ],
      includeNative: true,
    });

    console.log("totalFiatValue:", res.data.totalFiatValue);
    console.log("assets:", res.data.assets);
    ```

    Notes:

    * If `assetIds` is omitted, WalletSuite uses a default set:
      * Ethereum: USDT and USDC
      * Tron: USDT
    * Zero balances are omitted from `assets`.
  </Step>

  <Step>
    #### Assets — list supported assets

    ```ts theme={null}
    // Default: every supported asset on the chain
    const list = await api.listAssets({ chain: "ethereum" });
    console.log("count:", list.data?.length);
    if (list.data?.[0])
      console.log("first asset:", list.data[0].id, list.data[0].symbol);

    // Filter: only stablecoins
    const stables = await api.listAssets({
      chain: "ethereum",
      stablecoinOnly: true,
    });

    // Search by symbol or name (substring match), with a custom page size
    const usdc = await api.listAssets({
      chain: "ethereum",
      symbol: "USDC",
      limit: 5,
    });
    const wrapped = await api.listAssets({
      chain: "ethereum",
      name: "Wrapped",
      limit: 20,
    });

    // Drop the market-cap floor (defaults to true) to include long-tail assets
    const all = await api.listAssets({ chain: "ethereum", requireMcap: false });
    ```

    Filter parameters (all optional):

    ```ts theme={null}
    {
      chain?: string;            // default "ethereum"
      stablecoinOnly?: boolean;  // default false
      requireMcap?: boolean;     // default true; false includes long-tail assets
      symbol?: string;           // case-insensitive substring match on symbol
      name?: string;             // case-insensitive substring match on name
      limit?: number;            // default 10
    }
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: Array<{
        id: string; name: string; symbol: string; type: string; decimals: number;
        description?: string; website?: string; explorer?: string; logo?: string;
      }>;
    }
    ```
  </Step>

  <Step>
    #### Assets — single asset by id

    ```ts theme={null}
    const asset = await api.getAssetById("usdc", "ethereum");
    console.log("asset:", asset.data?.name, asset.data?.symbol);
    ```

    Returned (brief): same `TokenInfo` object as in list items.
  </Step>

  <Step>
    #### Fees — transfer fee quote

    ```ts theme={null}
    const quote = await api.quoteTransferFee({
      chain: "ethereum",
      from: "0xYourAddress",
      to: "0xRecipient",
      amountWei: "10000000000000000", // 0.01 ETH in wei (string recommended)
      tokenContract: null,
      fiat: "USD",
    });

    console.log("feeAmount:", quote.data.feeAmount);
    console.log("fiatValue:", quote.data.fiatValue);
    ```

    Token transfer example:

    ```ts theme={null}
    const quoteToken = await api.quoteTransferFee({
      chain: "ethereum",
      from: "0xYourAddress",
      to: "0xRecipient",
      amountWei: "1000000", // token smallest units (example)
      tokenContract: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC
      fiat: "USD",
    });

    console.log("feeSymbol:", quoteToken.data.feeSymbol);
    console.log("feeAmount:", quoteToken.data.feeAmount);
    ```

    Tron memo example (optional `memo` field; on Tron this adds a fixed 1 TRX fee + extra bandwidth):

    ```ts theme={null}
    const quoteWithMemo = await api.quoteTransferFee({
      chain: "tron",
      from: "TYourAddress",
      to: "TRecipient",
      amountWei: "1000000", // 1 USDT (6 decimals)
      tokenContract: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", // USDT on Tron
      memo: "invoice #1234",
      fiat: "USD",
    });
    ```
  </Step>

  <Step>
    #### Transactions — live status by tx hash

    ```ts theme={null}
    const tx = await api.getTransactionStatus("0xTransactionHash…", "ethereum");
    console.log("status:", tx.status);
    console.log("success:", tx.success);
    console.log("from→to:", tx.from, "→", tx.to);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      status: "PENDING" | "SUCCEEDED" | "FAILED" | "UNKNOWN";
      success: boolean;
      blockNumber?: number; txIndex?: number; gasUsed?: string;
      from?: string; to?: string; value?: string; displayValue?: string;
      txType:
        | "TRANSFER_NATIVE" | "TRANSFER_TOKEN"
        | "CONTRACT_CREATION" | "CONTRACT_CALL"
        | "SWAP" | "STAKE" | "UNSTAKE" | "CLAIM_REWARDS"
        | "UNKNOWN";
      tokenContract?: string; tokenTo?: string; tokenValue?: string; methodId?: string;
      blockTimestamp?: number; // unix milliseconds; null until confirmed
    }
    ```
  </Step>

  <Step>
    #### Transactions — history by address

    ```ts theme={null}
    const history = await api.getTransactionHistory("0xYourAddress", {
      chain: "ethereum",
    });
    console.log("items:", history.length);
    if (history[0])
      console.log(
        "first:",
        history[0].hash,
        history[0].txType,
        history[0].displayValue,
      );
    ```

    Returned (brief):

    ```ts theme={null}
    Array<{
      hash: string;
      chain: string;
      blockNumber: number;
      timestamp: string;
      from: string;
      to: string;
      value: string | null;
      displayValue: string | null;
      txType:
        | "TRANSFER_NATIVE"
        | "TRANSFER_TOKEN"
        | "CONTRACT_CREATION"
        | "CONTRACT_CALL"
        | "SWAP"
        | "STAKE"
        | "UNSTAKE"
        | "CLAIM_REWARDS"
        | "UNKNOWN";
      tokenContract?: string | null;
      tokenSymbol?: string | null;
      tokenDecimals?: number | null;
      tokenValue?: string | null;
      tokenDisplayValue?: string | null;
      direction: "IN" | "OUT" | string;
    }>;
    ```
  </Step>

  <Step>
    #### Transactions — send signed transaction

    ```ts theme={null}
    const sent = await api.sendSignedTransaction({
      chain: "ethereum",
      signedTx: "0xSignedRawTransactionHex",
    });

    console.log("hash:", sent.data.hash);
    ```

    Notes:

    * Ethereum expects `signedTx` as `0x` prefixed raw signed tx hex.
    * Tron expects signed tx hex; `0x` prefix is accepted.
  </Step>

  <Step>
    #### Transactions — prepare signing payload for transfers

    This endpoint prepares an EVM signing payload for:

    * `TRANSFER_NATIVE`
    * `TRANSFER_TOKEN`

    It calculates:

    * `nonce` (EVM only) if not provided
    * `data` for ERC20 transfers
    * fee params (EIP1559 by default when supported; legacy fallback when chain does not support)
    * a simulation check using gas estimation

    Native transfer example:

    ```ts theme={null}
    const prep = await api.prepareTransferSign({
      chain: "ethereum",
      txType: "TRANSFER_NATIVE",
      from: "0xYourAddress",
      to: "0xRecipient",
      amountWei: "10000000000000000", // 0.01 ETH
      nonce: null,
      tokenContract: null,
      maxPriorityFeePerGasWei: null,
      priorityFeeMultiplier: 1.0,
    });

    console.log("nonce:", prep.data.nonce);
    console.log("fee mode:", prep.data.fee.mode);
    ```

    Token transfer example:

    ```ts theme={null}
    const prepToken = await api.prepareTransferSign({
      chain: "ethereum",
      txType: "TRANSFER_TOKEN",
      from: "0xYourAddress",
      to: "0xRecipient",
      amountWei: "1000000",
      tokenContract: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      nonce: null,
      maxPriorityFeePerGasWei: "1500000000",
      priorityFeeMultiplier: 1.0,
    });

    console.log("data:", prepToken.data.data); // ERC20 calldata
    console.log("fee:", prepToken.data.fee);
    ```

    Human-readable amount (alternative to `amountWei`):

    ```ts theme={null}
    // Native: backend resolves "1.5" using the chain's native decimals (18 for ETH)
    const prepNative = await api.prepareTransferSign({
      chain: "ethereum",
      txType: "TRANSFER_NATIVE",
      from: "0xYourAddress",
      to: "0xRecipient",
      amount: "1.5",
    });

    // Token: backend resolves "1.5" using the token's decimals (looked up via tokenContract)
    // `symbol` is an optional decimal hint; ignored when `amountWei` is set or for native txs.
    const prepUsdc = await api.prepareTransferSign({
      chain: "ethereum",
      txType: "TRANSFER_TOKEN",
      from: "0xYourAddress",
      to: "0xRecipient",
      amount: "1.5",
      tokenContract: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      symbol: "USDC",
    });
    ```

    Notes:

    * `amountWei` and `amount` are **mutually exclusive** — provide one or the other (at least one is required).
    * `amount` is a human-readable decimal string (e.g. `"1.5"`); the backend converts it to smallest units using the chain (native) or asset registry (token).
    * `symbol` is an optional decimal hint paired with `amount` for token transfers; never replaces `tokenContract`.
    * `nonce` is optional; if omitted or null, WalletSuite fetches it automatically for EVM.
    * For `TRANSFER_TOKEN`, `tokenContract` is required.
    * `maxPriorityFeePerGasWei` can be provided to speed up inclusion; otherwise the backend uses a suggested value.
    * `priorityFeeMultiplier` is an optional multiplier applied on top of `maxPriorityFeePerGasWei` or suggested tip.
  </Step>

  <Step>
    #### Chains — list supported chains

    ```ts theme={null}
    const chains = await api.listChains();
    console.log("count:", chains.data?.length);
    if (chains.data?.[0])
      console.log("first:", chains.data[0].id, chains.data[0].symbol);

    // Optional family filter, e.g. only EVM chains
    const evm = await api.listChains("ethereum");
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean;
      code: string;
      message: string;
      data?: Array<{
        id: string;                  // e.g. "ethereum", "tron"
        name: string;                // human-readable name
        symbol: string;              // native asset symbol e.g. "ETH", "TRX"
        decimals: number;
        slipId?: string | null;      // SLIP-44 coin type
        chainId?: string | null;     // EVM chain id (numeric string)
        chainFamily?: string | null; // e.g. "ethereum", "tron"
        curve?: string | null;
        publicKeyType?: string | null;
        explorer?: { url?: string; txPath?: string; accountPath?: string } | null;
        info?: { url?: string; source?: string; rpc?: string; documentation?: string } | null;
        tier?: number | null;        // provider tier: 1 = high traffic, 2 = moderate, 3 = niche; null = unclassified
      }>;
    }
    ```

    Companion methods on the same surface:

    ```ts theme={null}
    await api.getChainByKey("ethereum");
    await api.getChainsBySlipId("60");
    await api.getInfo();
    await api.getInfoChains();
    ```
  </Step>

  <Step>
    #### Chains — fee policy

    Read the chain's recommended priority fee tiers before building or signing a transaction. Pair with `quoteTransferFee` for fiat conversion and `prepareTransferSign` to actually use a custom tip.

    ```ts theme={null}
    const policy = await api.getChainFeePolicy("ethereum");
    console.log("policy:", policy.data?.policy);
    console.log("recommended:", policy.data?.recommendedPriorityFeeWei);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        policy: string;                            // "eip1559" | "legacy" | "resource" (resource = Tron's energy/bandwidth model)
        minPriorityFeeWei?: string | null;         // smallest unit string
        recommendedPriorityFeeWei?: string | null;
        fastPriorityFeeWei?: string | null;
      };
    }
    ```
  </Step>

  <Step>
    #### Approvals — get current allowance

    Inspect how many tokens an `owner` has approved a `spender` to move on a given ERC-20 contract.

    ```ts theme={null}
    const allowance = await api.getAllowance({
      chain: "ethereum",
      owner: "0xYourAddress",
      tokenContract: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC
      spender: "0xRouterContract",
    });
    console.log("allowance (smallest unit):", allowance.data?.allowance);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        owner: string;
        tokenContract: string;
        spender: string;
        allowance: string;     // BigInteger as decimal string
        updatedAt: string;     // ISO 8601
      };
    }
    ```
  </Step>

  <Step>
    #### Approvals — check sufficiency

    Compare current allowance to the `requiredAmount` for an upcoming spend. The backend returns a single boolean plus the gap so the client doesn't need to compare BigInts.

    ```ts theme={null}
    const check = await api.checkApproval({
      chain: "ethereum",
      owner: "0xYourAddress",
      tokenContract: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      spender: "0xRouterContract",
      requiredAmount: "1000000", // 1 USDC (6 decimals)
    });
    if (!check.data?.approved) {
      // need to call buildApproveTransaction below first
    }
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        approved: boolean;
        currentAllowance: string;  // BigInteger as decimal string
        requiredAmount: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Approvals — build approve transaction

    Build the unsigned ERC-20 `approve(spender, amount)` calldata. Same prepare → sign → broadcast pattern as `prepareTransferSign`.

    ```ts theme={null}
    const built = await api.buildApproveTransaction({
      chain: "ethereum",
      owner: "0xYourAddress",
      tokenContract: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      spender: "0xRouterContract",
      amount: "1000000000", // raise allowance to 1,000 USDC (6 decimals)
      // optional fee controls:
      // nonce: "42",
      // maxPriorityFeePerGasWei: "1500000000",
      // priorityFeeMultiplier: 1.2,
    });

    const signedTx = sdk.signEvmTransaction(built.data, eth.privateKeyHex);
    const sent = await api.sendSignedTransaction({ chain: "ethereum", signedTx });
    console.log("approval tx:", sent.data?.hash);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        chainId?: number | null;
        from: string;
        to: string;                // tokenContract — the call target
        valueWei: string;          // "0" for token approvals
        data: string;              // 0x-prefixed approve(spender, amount) calldata
        nonce?: string | null;
        fee: {
          mode: "eip1559" | "legacy";
          gasLimit?: string | null;
          maxPriorityFeePerGas?: string | null;
          maxFeePerGas?: string | null;
          gasPrice?: string | null;
        };
      };
    }
    ```
  </Step>

  <Step>
    #### Asset status — enablement

    Whether an asset is currently enabled on the platform, with a human-readable reason if disabled.

    ```ts theme={null}
    const status = await api.getAssetStatus("usdc", "ethereum");
    console.log("status:", status.data?.status);
    if (status.data?.reason) console.log("reason:", status.data.reason);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        assetId: string;
        status: "ENABLED" | "DISABLED" | "BLACKLISTED" | string;
        reason?: string | null;
        updatedAt: string; // ISO 8601
      };
    }
    ```
  </Step>

  <Step>
    #### Asset status — per-action restrictions

    Buy / sell / transfer / swap allowances per asset. Useful for compliance-aware UIs that hide or disable individual buttons.

    ```ts theme={null}
    const r = await api.getAssetRestrictions("usdc", "ethereum");
    console.log("canTransfer:", r.data?.canTransfer);
    console.log("canSwap:", r.data?.canSwap);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        assetId: string;
        canBuy: boolean;
        canSell: boolean;
        canTransfer: boolean;
        canSwap: boolean;
        reason?: string | null;
        updatedAt: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Name service — resolve name to address

    ENS, TNS, or any chain-specific name service the backend knows about. Names are normalized server-side (trimmed and lowercased).

    ```ts theme={null}
    const r = await api.resolveName({
      chain: "ethereum",
      name: "vitalik.eth",
    });
    console.log("address:", r.data?.address);
    console.log("resolver:", r.data?.resolver); // e.g. "ENS"
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        name: string;
        address: string;
        resolver?: string | null;
        updatedAt: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Name service — reverse resolve

    Look up the human-readable name an address advertises (if any).

    ```ts theme={null}
    const r = await api.reverseResolveName({
      chain: "ethereum",
      address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    });
    console.log("name:", r.data?.name); // null when no reverse record exists
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        address: string;
        name?: string | null;
        updatedAt: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Chain-specific — EVM token metadata by contract

    Look up `name` / `symbol` / `decimals` for any ERC-20 contract, even ones outside the curated `listAssets` set. Useful when you only have a contract address from on-chain logs or a partner integration.

    ```ts theme={null}
    const meta = await api.getEvmTokenMetadata({
      chain: "ethereum",
      contract: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    });
    console.log(meta.data?.symbol, meta.data?.decimals);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        contract: string;
        name?: string | null;
        symbol?: string | null;
        decimals?: number | null;
        verified: boolean;
        updatedAt: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Chain-specific — Tron account resources

    Energy and bandwidth used vs available for a Tron address. Decide whether to burn TRX as fee or stake for resources before sending a TRC-20 transfer.

    ```ts theme={null}
    const res = await api.getTronResources("TJRabPrwbZy45sbavfcjinPJC18kjpRTv8");
    console.log("energy:", res.data?.energyUsed, "/", res.data?.energyLimit);
    console.log(
      "bandwidth:",
      res.data?.bandwidthUsed,
      "/",
      res.data?.bandwidthLimit,
    );
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: "tron";
        address: string;
        energyUsed: number;
        energyLimit: number;
        bandwidthUsed: number;
        bandwidthLimit: number;
        updatedAt: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Chain-specific — EVM L2 fee estimate

    L2 chains (Optimism, Base, Arbitrum, etc.) charge an additional L1 data fee that's not part of `gasPrice * gasUsed`. Estimate it before signing.

    ```ts theme={null}
    const l1 = await api.estimateEvmL2Fee({
      chain: "base",
      from: "0xYourAddress",
      to: "0xRecipient",
      valueWei: "10000000000000000", // 0.01 ETH
      data: null, // or 0x… for contract calls
    });
    console.log("L1 data fee (wei):", l1.data?.l1FeeWei);
    console.log("currency:", l1.data?.currency); // e.g. "ETH"
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        l1FeeWei: string;  // BigInteger as decimal string
        currency: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Staking — APR / APY

    Current annual percentage rate and yield for native staking on the given chain. Caches at the source so two consecutive calls return the same numbers.

    ```ts theme={null}
    const apr = await api.getStakingApr("tron");
    console.log("APR:", apr.data?.apr, "APY:", apr.data?.apy);
    console.log("source:", apr.data?.source);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        apr: string;     // BigDecimal as string, e.g. "0.0532"
        apy: string;
        updatedAt: string;
        source: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Staking — list validators

    Active set of validators with commission and per-validator APR estimate.

    ```ts theme={null}
    const v = await api.listStakingValidators("tron");
    v.data?.validators.forEach((val) =>
      console.log(val.id, val.name, "commission:", val.commissionBps / 100, "%"),
    );
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        validators: Array<{
          id: string;
          name: string;
          commissionBps: number;          // 100 = 1%
          aprEstimate?: string | null;    // BigDecimal as string
          active: boolean;
        }>;
        updatedAt: string;
      };
    }
    ```
  </Step>

  <Step>
    #### Staking — positions by address

    Every active and unbonding position for an address. `unfreezeExpireTimeMs` is set during the unstaking cooldown period.

    ```ts theme={null}
    const p = await api.getStakingPositions(
      "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "tron",
    );
    p.data?.positions.forEach((pos) =>
      console.log(
        pos.validatorId,
        "staked:",
        pos.stakedAmountWei,
        "rewards:",
        pos.rewardsWei,
      ),
    );
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        address: string;
        positions: Array<{
          chain: string;
          address: string;
          validatorId: string;
          stakedAmountWei: string;       // BigInteger as decimal string
          rewardsWei: string;
          status: string;                // e.g. "ACTIVE" | "UNBONDING" | "INACTIVE"
          unfreezeExpireTimeMs?: number | null;
          updatedAt: string;
        }>;
      };
    }
    ```
  </Step>

  <Step>
    #### Staking — build delegate transaction

    Build an unsigned delegate (stake) transaction.

    ```ts theme={null}
    const built = await api.buildStakingDelegateTransaction({
      chain: "tron",
      from: "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      validatorId: "TVj7RNVHy6thbM7BWdSe9G6gXwKhjhdNZS",
      amountWei: "1000000000", // 1,000 TRX (sun = 6 decimals)
    });

    const signedTx = sdk.signTronTransaction(built.data, tron.privateKeyHex);
    const sent = await api.sendSignedTransaction({ chain: "tron", signedTx });
    ```

    Returned (brief): same `BuildStakingTxResponseDto` shape as below — feedable directly into `sdk.signEvmTransaction(...)` for EVM staking chains or `sdk.signTronTransaction(...)` for Tron.

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        chainId?: number | null;
        from: string;
        to: string;
        valueWei: string;
        data?: string | null;
        nonce?: string | null;
        fee: {
          mode: "eip1559" | "legacy" | "tron" | string;
          gasLimit?: string | null;
          maxPriorityFeePerGas?: string | null;
          maxFeePerGas?: string | null;
          gasPrice?: string | null;
        };
      };
    }
    ```
  </Step>

  <Step>
    #### Staking — build undelegate transaction

    ```ts theme={null}
    const built = await api.buildStakingUndelegateTransaction({
      chain: "tron",
      from: "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      validatorId: "TVj7RNVHy6thbM7BWdSe9G6gXwKhjhdNZS",
      amountWei: "500000000", // unstake 500 TRX
    });

    const signedTx = sdk.signTronTransaction(built.data, tron.privateKeyHex);
    const sent = await api.sendSignedTransaction({ chain: "tron", signedTx });
    ```

    Returned (brief): same `BuildStakingTxResponseDto` shape as the delegate step above.
  </Step>

  <Step>
    #### Staking — build claim rewards transaction

    `validatorId` is optional; omit to claim across every position the address holds.

    ```ts theme={null}
    const built = await api.buildStakingClaimRewardsTransaction({
      chain: "tron",
      from: "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      validatorId: "TVj7RNVHy6thbM7BWdSe9G6gXwKhjhdNZS",
    });

    const signedTx = sdk.signTronTransaction(built.data, tron.privateKeyHex);
    const sent = await api.sendSignedTransaction({ chain: "tron", signedTx });
    ```

    Returned (brief): same `BuildStakingTxResponseDto` shape as the delegate step above.
  </Step>

  <Step>
    #### NFTs — list collections owned by an address

    ```ts theme={null}
    const cols = await api.listNftCollections("0xYourAddress", "ethereum");
    cols.data?.forEach((c) =>
      console.log(c.standard, c.symbol ?? "(no symbol)", c.contract),
    );
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: Array<{
        chain: string;
        contract: string;
        name?: string | null;
        symbol?: string | null;
        standard: "ERC721" | "ERC1155" | "TRC721" | "TRC1155";
        imageUrl?: string | null;
      }>;
    }
    ```
  </Step>

  <Step>
    #### NFTs — item metadata

    Fetch a single NFT's metadata (name, image, attributes) by `contract` + `tokenId`.

    ```ts theme={null}
    const item = await api.getNftItem({
      chain: "ethereum",
      contract: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", // BAYC
      tokenId: "1",
    });
    console.log("name:", item.data?.name, "image:", item.data?.imageUrl);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        contract: string;
        tokenId: string;
        standard: "ERC721" | "ERC1155" | "TRC721" | "TRC1155";
        name?: string | null;
        description?: string | null;
        imageUrl?: string | null;
        attributes: Record<string, string>;
        lastUpdatedAt: string;
      };
    }
    ```
  </Step>

  <Step>
    #### NFTs — owners of a token

    For ERC-721 returns one owner; for ERC-1155 may return many with non-1 quantities.

    ```ts theme={null}
    const owners = await api.getNftOwners({
      chain: "ethereum",
      contract: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
      tokenId: "1",
    });
    owners.data?.owners.forEach((o) => console.log(o.owner, "qty:", o.quantity));
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        contract: string;
        tokenId: string;
        owners: Array<{ owner: string; quantity: string }>;
      };
    }
    ```
  </Step>

  <Step>
    #### NFTs — build transfer transaction

    Builds the unsigned `transferFrom` (ERC-721) or `safeTransferFrom` (ERC-1155 / TRC-1155) calldata. For 1155 standards, set `amount`.

    ```ts theme={null}
    const built = await api.buildNftTransferTransaction({
      chain: "ethereum",
      from: "0xYourAddress",
      to: "0xRecipient",
      contract: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
      tokenId: "1",
      standard: "ERC721",
      // amount: "1",   // required for ERC1155 / TRC1155
    });

    const signedTx = sdk.signEvmTransaction(built.data, eth.privateKeyHex);
    const sent = await api.sendSignedTransaction({ chain: "ethereum", signedTx });
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        chainId?: number | null;
        from: string;
        to: string;          // contract address — the call target
        contract: string;
        tokenId: string;
        standard: "ERC721" | "ERC1155" | "TRC721" | "TRC1155";
        valueWei: string;    // "0" for NFT transfers
        data: string;        // 0x-prefixed transfer calldata
        nonce?: string | null;
      };
    }
    ```
  </Step>

  <Step>
    #### Swaps — list available tokens

    ```ts theme={null}
    const tokens = await api.listSwapTokens("ethereum");
    tokens.data?.forEach((t) => console.log(t.symbol, t.token, t.decimals));
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: Array<{
        chain: string;
        token: string;          // contract address (or "ETH" for native)
        symbol?: string | null;
        decimals?: number | null;
      }>;
    }
    ```
  </Step>

  <Step>
    #### Swaps — quote

    Quote a swap and receive a `quoteId` to feed into `getSwapRoute` and `buildSwapTransaction`. `provider` is optional; the backend picks a best provider when omitted.

    ```ts theme={null}
    const quote = await api.getSwapQuote({
      chain: "ethereum",
      fromAddress: "0xYourAddress",
      sellToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
      buyToken: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC
      sellAmount: "1000000000000000000", // 1 WETH (18 decimals)
      slippageBps: 50, // 0.50%
      // provider: "ZERO_X",
    });

    console.log("quoteId:", quote.data?.quoteId);
    console.log("buyAmount:", quote.data?.buyAmount);
    console.log("price:", quote.data?.price);
    console.log("expiresAt:", quote.data?.expiresAt);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        provider:
          | "ZERO_X" | "ONE_INCH" | "PANCAKE_SWAP" | "QUICK_SWAP"
          | "FLUID_SWAP" | "BALANCER" | "CURVE_FINANCE_SWAP"
          | "UNISWAP" | "WOOFI" | "INTERNAL";
        quoteId: string;          // pass to getSwapRoute / buildSwapTransaction
        sellToken: string;
        buyToken: string;
        sellAmount: string;       // BigInteger as decimal string
        buyAmount: string;
        minBuyAmount: string;     // buyAmount after slippage
        price: string;            // BigDecimal as decimal string
        priceImpactBps?: number | null;
        estimatedGas?: string | null;
        issues: string[];         // backend-flagged warnings (e.g. "low liquidity")
        expiresAt: string;        // ISO 8601 — quote re-fetch required after this
      };
    }
    ```
  </Step>

  <Step>
    #### Swaps — route preview

    Inspect the multi-hop route the backend will execute, including any approval that will be inserted as a prerequisite. Useful for building UI affordances ("you'll be asked to approve USDC first").

    ```ts theme={null}
    const route = await api.getSwapRoute({
      chain: "ethereum",
      quoteId: quote.data!.quoteId,
    });
    route.data?.steps.forEach((s) =>
      console.log(s.kind, s.description, s.needsApproval ? "(needs approval)" : ""),
    );
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        provider: SwapProvider;            // same union as in getSwapQuote
        quoteId: string;
        steps: Array<{
          kind: string;                    // e.g. "approval" | "swap"
          description: string;
          spender?: string | null;
          needsApproval: boolean;
          approvalToken?: string | null;
          approvalAmount?: string | null;  // BigInteger as decimal string
          callTo?: string | null;
          callData?: string | null;
        }>;
        totalEstimatedGas?: string | null;
        warnings: string[];
      };
    }
    ```
  </Step>

  <Step>
    #### Swaps — build swap transaction

    Build the final unsigned swap tx from a `quoteId`. If `getSwapRoute` indicated `needsApproval`, run `buildApproveTransaction` first and broadcast that approval before calling this one.

    ```ts theme={null}
    const built = await api.buildSwapTransaction({
      chain: "ethereum",
      fromAddress: "0xYourAddress",
      quoteId: quote.data!.quoteId,
      // optional fee controls:
      // nonce: "42",
      // maxPriorityFeePerGasWei: "1500000000",
      // priorityFeeMultiplier: 1.2,
    });

    const signedTx = sdk.signEvmTransaction(built.data, eth.privateKeyHex);
    const sent = await api.sendSignedTransaction({ chain: "ethereum", signedTx });
    console.log("swap tx:", sent.data?.hash);
    ```

    Returned (brief):

    ```ts theme={null}
    {
      ok: boolean; code: string; message: string;
      data?: {
        chain: string;
        chainId?: number | null;
        from: string;
        to: string;          // router / aggregator contract
        valueWei: string;    // non-zero only when selling the native asset
        data: string;        // 0x-prefixed swap calldata
        nonce?: string | null;
        fee: {
          mode: "eip1559" | "legacy";
          gasLimit?: string | null;
          maxPriorityFeePerGas?: string | null;
          maxFeePerGas?: string | null;
          gasPrice?: string | null;
        };
      };
    }
    ```
  </Step>
</Steps>
