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

# Building a Liquidity Provider

> Technical guide for implementing your own liquidity provider service to earn fees from Lidian cross-chain swaps.

## Overview

This guide teaches you how to **build your own liquidity provider service** from scratch. You'll learn the complete technical flow for:

1. Polling for quote requests from users
2. Calculating and submitting competitive quotes
3. Monitoring for quote acceptance
4. Executing the on-chain order fulfillment
5. Settling cross-chain via LayerZero
6. Withdrawing your earned fees

By the end, you'll understand how to implement a production-ready LP service that earns 3-15 basis points per swap.

<Warning>
  This is a technical implementation guide. You should be comfortable with TypeScript, blockchain transactions, and smart contract interactions.
</Warning>

## Prerequisites

* **Blockchain development experience**: Understanding of transactions, gas, signatures
* **TypeScript/JavaScript** knowledge
* **Web3 library**: Viem, ethers.js, or web3.js
* **Funded wallet** with gas tokens and stablecoins on multiple chains
* **API key** from [Lidian Developer Portal](https://calendly.com/dantereminick-lidian/30min)

## Core Concepts

### The LP Business Model

As an LP, you profit from the spread between input and output amounts:

```
User sends:  1000 USDC on Base Sepolia
LP quotes:   998.50 USDC on Polygon Amoy (15 bps fee = 1.50 USDC)
LP provides: 998.50 USDC from their liquidity
LP receives: 1000 USDC + 1.50 USDC fee (after settlement)
Net profit:  1.50 USDC (minus gas costs ~$0.10)
```

### The Order Lifecycle

```
1. QUOTE REQUEST → LP receives user's swap intent
2. QUOTE CREATION → LP calculates output amount with fee
3. QUOTE ACCEPTANCE → User signs order with EIP-712
4. DEPOSIT → LP relays signed order to source chain contract
5. FILL → LP provides liquidity on destination chain
6. SETTLEMENT → LP initiates LayerZero message back to source
7. WITHDRAWAL → LP claims input tokens + earned fee
```

## Step 1: Poll for Quote Requests

### Fetch Quote Requests from API

```typescript theme={null}
interface QuoteRequest {
  id: string;
  inputChain: string;        // e.g., "base-sepolia"
  inputToken: string;        // e.g., "0x036CbD..."
  inputAmount: string;       // e.g., "1000000" (1 USDC with 6 decimals)
  outputChain: string;       // e.g., "polygon-amoy"
  outputToken: string;       // e.g., "0x41E94..."
  offerer: string;           // User's wallet address
  recipient: string;         // Recipient's wallet address
  startTime: number;
  endTime: number;
}

async function pollForQuoteRequests() {
  const response = await fetch('https://api.lidian.finance/api/v1/quote-requests', {
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': process.env.LIDIAN_API_KEY
    }
  });
  
  const { data } = await response.json();
  return data; // Array of QuoteRequest[]
}
```

### Continuous Polling Loop

```typescript theme={null}
const processedRequests = new Set<string>();

async function monitorQuoteRequests() {
  while (true) {
    try {
      const requests = await pollForQuoteRequests();
      
      for (const request of requests) {
        if (processedRequests.has(request.id)) continue;
        
        console.log(`New quote request: ${request.id}`);
        await handleQuoteRequest(request);
        processedRequests.add(request.id);
      }
    } catch (error) {
      console.error('Polling error:', error);
    }
    
    await sleep(2000); // Poll every 2 seconds
  }
}
```

## Step 2: Calculate Quote with Fee

### Fee Structure

Different tokens have different basis point fees:

```typescript theme={null}
const TOKEN_FEES = {
  'base-sepolia': {
    '0x036CbD53842c5426634e7929541eC2318f3dCF7e': 15, // USDC: 15 bps
    '0x66F5018cdb5d6Eb0a3d1AC57F8b77243eb0010fF': 5,  // USDT: 5 bps
  },
  'polygon-amoy': {
    '0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582': 3,  // USDC: 3 bps
    '0x86f6D9931BE92Ad61572e80c0F5FAe45950D4cA1': 3,  // USDT: 3 bps
  }
};
```

### Calculate Output Amount

```typescript theme={null}
function calculateOutputAmount(
  inputAmount: bigint,
  inputDecimals: number,
  outputDecimals: number,
  feeBasisPoints: number
): bigint {
  // For stablecoins (1:1 ratio), calculate fee deduction
  // feeBasisPoints: 15 = 0.15% = 0.0015
  
  const FEE_DENOMINATOR = 10000n;
  const feeBps = BigInt(feeBasisPoints);
  
  // Calculate output = input * (1 - fee)
  // output = input * (10000 - feeBps) / 10000
  const outputAmount = (inputAmount * (FEE_DENOMINATOR - feeBps)) / FEE_DENOMINATOR;
  
  // Adjust for decimal differences if needed
  if (inputDecimals !== outputDecimals) {
    const decimalDiff = outputDecimals - inputDecimals;
    if (decimalDiff > 0) {
      return outputAmount * (10n ** BigInt(decimalDiff));
    } else {
      return outputAmount / (10n ** BigInt(-decimalDiff));
    }
  }
  
  return outputAmount;
}

// Example:
// Input: 1,000,000 (1 USDC with 6 decimals)
// Fee: 15 bps
// Output: 1,000,000 * (10000 - 15) / 10000 = 998,500 (0.9985 USDC)
// LP earns: 1,500 (0.0015 USDC = $1.50 on $1000 swap)
```

### Check Liquidity Availability

```typescript theme={null}
import { createPublicClient, http, parseUnits } from 'viem';
import { polygonAmoy } from 'viem/chains';

async function checkLiquidity(
  chain: typeof polygonAmoy,
  tokenAddress: string,
  requiredAmount: bigint,
  lpWallet: string
): Promise<boolean> {
  const client = createPublicClient({
    chain,
    transport: http()
  });
  
  const balance = await client.readContract({
    address: tokenAddress,
    abi: [{
      name: 'balanceOf',
      type: 'function',
      stateMutability: 'view',
      inputs: [{ name: 'account', type: 'address' }],
      outputs: [{ type: 'uint256' }]
    }],
    functionName: 'balanceOf',
    args: [lpWallet]
  });
  
  return balance >= requiredAmount;
}
```

## Step 3: Submit Quote to API

### Create Quote Object

```typescript theme={null}
async function submitQuote(
  quoteRequestId: string,
  outputAmount: string
): Promise<string> {
  const response = await fetch('https://api.lidian.finance/api/v1/quotes', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': process.env.LIDIAN_API_KEY
    },
    body: JSON.stringify({
      quoteRequestId,
      outputAmount,
      liquidityProviderId: process.env.LP_WALLET_ADDRESS
    })
  });
  
  const { data } = await response.json();
  return data.id; // Returns quote ID (e.g., "quotes/abc123")
}
```

### Handle Quote Request (Complete Flow)

```typescript theme={null}
async function handleQuoteRequest(request: QuoteRequest) {
  // 1. Get token fee
  const inputFee = TOKEN_FEES[request.inputChain]?.[request.inputToken] || 0;
  const outputFee = TOKEN_FEES[request.outputChain]?.[request.outputToken] || 0;
  const maxFee = Math.max(inputFee, outputFee);
  
  // 2. Calculate output amount
  const inputAmount = BigInt(request.inputAmount);
  const outputAmount = calculateOutputAmount(
    inputAmount,
    6, // USDC decimals
    6, // USDC decimals
    maxFee
  );
  
  // 3. Check if we have liquidity
  const hasLiquidity = await checkLiquidity(
    getChain(request.outputChain),
    request.outputToken,
    outputAmount,
    process.env.LP_WALLET_ADDRESS
  );
  
  if (!hasLiquidity) {
    console.log('Insufficient liquidity, skipping quote');
    return;
  }
  
  // 4. Submit quote
  const quoteId = await submitQuote(request.id, outputAmount.toString());
  console.log(`Quote submitted: ${quoteId} - Output: ${outputAmount.toString()}`);
  
  // 5. Start monitoring for acceptance
  monitorQuoteAcceptance(quoteId, request);
}
```

## Step 4: Monitor for Quote Acceptance

### Poll for Order Creation

When a user accepts your quote, they sign the order and create it in the API:

```typescript theme={null}
async function monitorQuoteAcceptance(
  quoteId: string,
  originalRequest: QuoteRequest
) {
  const timeout = Date.now() + 300000; // 5 minute timeout
  
  while (Date.now() < timeout) {
    try {
      // Fetch the quote to see if it was accepted
      const response = await fetch(
        `https://api.lidian.finance/api/v1/quotes/${quoteId}`,
        {
          headers: { 'x-api-key': process.env.LIDIAN_API_KEY }
        }
      );
      
      const { data: quote } = await response.json();
      
      // Check if order was created
      if (quote.orderId) {
        console.log(`Quote accepted! Order ID: ${quote.orderId}`);
        await processOrder(quote.orderId, originalRequest, quote.outputAmount);
        return;
      }
      
      // Check if quote expired/cancelled
      if (quote.status === 'expired' || quote.status === 'cancelled') {
        console.log(`Quote ${quoteId} ${quote.status}`);
        return;
      }
      
    } catch (error) {
      console.error('Error monitoring quote:', error);
    }
    
    await sleep(2000); // Poll every 2 seconds
  }
  
  console.log(`Quote monitoring timeout: ${quoteId}`);
}
```

### Fetch Order Details

```typescript theme={null}
interface Order {
  id: string;
  signature: string;          // EIP-712 signature from user
  quoteId: string;
  status: string;
  moneyMoverAccountId: string; // User's wallet
  liquidityProviderAccountId: string; // Your wallet
}

async function fetchOrder(orderId: string): Promise<Order> {
  const response = await fetch(
    `https://api.lidian.finance/api/v1/orders/${orderId}`,
    {
      headers: { 'x-api-key': process.env.LIDIAN_API_KEY }
    }
  );
  
  const { data } = await response.json();
  return data;
}
```

## Step 5: Execute Deposit on Source Chain

### Build Order Struct for Contract

```typescript theme={null}
import { encodeFunctionData, keccak256, encodePacked } from 'viem';

// Helper: Calculate chain ID hash
function getChainHash(chainKey: string): `0x${string}` {
  return keccak256(encodePacked(['string'], [chainKey]));
}

interface OrderStruct {
  inputAmount: bigint;
  outputAmount: bigint;
  inputToken: `0x${string}`;
  outputToken: `0x${string}`;
  startTime: number;
  endTime: number;
  srcChainId: `0x${string}`;
  dstChainId: `0x${string}`;
  offerer: `0x${string}`;
  recipient: `0x${string}`;
}
```

### Call deposit() on Lidian Contract

```typescript theme={null}
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { baseSepolia } from 'viem/chains';

const LIDIAN_CONTRACT = '0xc2c00E85ab6bcf865986DE84053a6169bCBfa70F'; // Base Sepolia

const LIDIAN_ABI = [{
  name: 'deposit',
  type: 'function',
  stateMutability: 'nonpayable',
  inputs: [
    {
      name: 'order',
      type: 'tuple',
      components: [
        { name: 'inputAmount', type: 'uint128' },
        { name: 'outputAmount', type: 'uint128' },
        { name: 'inputToken', type: 'address' },
        { name: 'outputToken', type: 'address' },
        { name: 'startTime', type: 'uint32' },
        { name: 'endTime', type: 'uint32' },
        { name: 'srcChainId', type: 'bytes32' },
        { name: 'dstChainId', type: 'bytes32' },
        { name: 'offerer', type: 'address' },
        { name: 'recipient', type: 'address' }
      ]
    },
    { name: 'signature', type: 'bytes' }
  ],
  outputs: []
}];

async function executeDeposit(
  order: OrderStruct,
  signature: `0x${string}`
) {
  const account = privateKeyToAccount(process.env.LP_PRIVATE_KEY as `0x${string}`);
  const client = createWalletClient({
    account,
    chain: baseSepolia,
    transport: http()
  });
  
  console.log('Executing deposit on source chain...');
  
  const hash = await client.writeContract({
    address: LIDIAN_CONTRACT,
    abi: LIDIAN_ABI,
    functionName: 'deposit',
    args: [order, signature]
  });
  
  console.log(`Deposit tx: ${hash}`);
  
  // Wait for confirmation
  const receipt = await client.waitForTransactionReceipt({ hash });
  console.log(`Deposit confirmed at block ${receipt.blockNumber}`);
  
  return receipt;
}
```

<Note>
  **Important**: The deposit transaction uses the **user's signature** to pull tokens from their wallet. The LP does not need to hold the input tokens.
</Note>

## Step 6: Execute Fill on Destination Chain

### Approve Token Spending (if needed)

```typescript theme={null}
const ERC20_ABI = [{
  name: 'approve',
  type: 'function',
  stateMutability: 'nonpayable',
  inputs: [
    { name: 'spender', type: 'address' },
    { name: 'amount', type: 'uint256' }
  ],
  outputs: [{ type: 'bool' }]
}];

async function approveTokenIfNeeded(
  tokenAddress: `0x${string}`,
  spenderAddress: `0x${string}`,
  amount: bigint
) {
  const account = privateKeyToAccount(process.env.LP_PRIVATE_KEY as `0x${string}`);
  const client = createWalletClient({
    account,
    chain: polygonAmoy,
    transport: http()
  });
  
  // Check current allowance
  const publicClient = createPublicClient({
    chain: polygonAmoy,
    transport: http()
  });
  
  const allowance = await publicClient.readContract({
    address: tokenAddress,
    abi: [{
      name: 'allowance',
      type: 'function',
      stateMutability: 'view',
      inputs: [
        { name: 'owner', type: 'address' },
        { name: 'spender', type: 'address' }
      ],
      outputs: [{ type: 'uint256' }]
    }],
    functionName: 'allowance',
    args: [account.address, spenderAddress]
  });
  
  if (allowance >= amount) {
    console.log('Sufficient allowance already exists');
    return;
  }
  
  // Approve tokens
  console.log('Approving tokens...');
  const hash = await client.writeContract({
    address: tokenAddress,
    abi: ERC20_ABI,
    functionName: 'approve',
    args: [spenderAddress, amount]
  });
  
  await client.waitForTransactionReceipt({ hash });
  console.log('Approval confirmed');
}
```

### Call fill() on Destination Chain

```typescript theme={null}
const LIDIAN_CONTRACT_AMOY = '0x7bE37DE6d81C6B231c8579901C6717f1A08c41ed'; // Polygon Amoy

async function executeFill(order: OrderStruct) {
  const account = privateKeyToAccount(process.env.LP_PRIVATE_KEY as `0x${string}`);
  const client = createWalletClient({
    account,
    chain: polygonAmoy,
    transport: http()
  });
  
  // 1. Approve Lidian contract to spend output tokens
  await approveTokenIfNeeded(
    order.outputToken,
    LIDIAN_CONTRACT_AMOY,
    order.outputAmount
  );
  
  // 2. Call fill()
  console.log('Executing fill on destination chain...');
  
  const hash = await client.writeContract({
    address: LIDIAN_CONTRACT_AMOY,
    abi: [{
      name: 'fill',
      type: 'function',
      stateMutability: 'payable',
      inputs: [{
        name: 'order',
        type: 'tuple',
        components: [
          { name: 'inputAmount', type: 'uint128' },
          { name: 'outputAmount', type: 'uint128' },
          { name: 'inputToken', type: 'address' },
          { name: 'outputToken', type: 'address' },
          { name: 'startTime', type: 'uint32' },
          { name: 'endTime', type: 'uint32' },
          { name: 'srcChainId', type: 'bytes32' },
          { name: 'dstChainId', type: 'bytes32' },
          { name: 'offerer', type: 'address' },
          { name: 'recipient', type: 'address' }
        ]
      }],
      outputs: []
    }],
    functionName: 'fill',
    args: [order]
  });
  
  console.log(`Fill tx: ${hash}`);
  
  const receipt = await client.waitForTransactionReceipt({ hash });
  console.log(`Fill confirmed at block ${receipt.blockNumber}`);
  
  return receipt;
}
```

<Warning>
  After fill, the LP's output tokens are locked in the destination chain contract. You must complete settlement to unlock your funds on the source chain.
</Warning>

## Step 7: Settle via LayerZero

### Quote LayerZero Fee

```typescript theme={null}
const LZ_ADAPTER_AMOY = '0x9ecf258aA68a483ac89057cBB9deAD71D6a7a3E0';

const ADAPTER_ABI = [{
  name: 'quote',
  type: 'function',
  stateMutability: 'view',
  inputs: [
    { name: 'dstChainId', type: 'bytes32' },
    { name: 'msgType', type: 'uint8' },
    { name: '_options', type: 'bytes' },
    { name: 'payInLzToken', type: 'bool' },
    { name: 'srcChainId', type: 'bytes32' },
    { name: 'sender', type: 'address' }
  ],
  outputs: [{ name: 'nativeFee', type: 'uint256' }]
}];

async function quoteLzFee(
  srcChainHash: `0x${string}`,
  dstChainHash: `0x${string}`,
  lpAddress: `0x${string}`
): Promise<bigint> {
  const client = createPublicClient({
    chain: polygonAmoy,
    transport: http()
  });
  
  // LayerZero options: 300k gas for lzReceive
  const options = '0x00030100110100000000000000000000000000030d40'; // 300k gas
  
  const fee = await client.readContract({
    address: LZ_ADAPTER_AMOY,
    abi: ADAPTER_ABI,
    functionName: 'quote',
    args: [
      dstChainHash,  // destination (source chain)
      0,             // msgType = settlement
      options,
      false,         // don't pay in LZ token
      srcChainHash,  // source chain
      lpAddress      // filler address
    ]
  });
  
  return fee as bigint;
}
```

### Execute Settlement

```typescript theme={null}
async function executeSettlement(
  srcChainHash: `0x${string}`,
  dstChainHash: `0x${string}`
) {
  const account = privateKeyToAccount(process.env.LP_PRIVATE_KEY as `0x${string}`);
  const client = createWalletClient({
    account,
    chain: polygonAmoy,
    transport: http()
  });
  
  // 1. Quote the LayerZero fee
  const lzFee = await quoteLzFee(srcChainHash, dstChainHash, account.address);
  console.log(`LayerZero fee: ${lzFee.toString()} wei`);
  
  // 2. Call settle() with LZ fee as msg.value
  console.log('Executing settlement...');
  
  const options = '0x00030100110100000000000000000000000000030d40';
  
  const hash = await client.writeContract({
    address: LZ_ADAPTER_AMOY,
    abi: [{
      name: 'settle',
      type: 'function',
      stateMutability: 'payable',
      inputs: [
        { name: 'filler', type: 'address' },
        { name: 'dstChainId', type: 'bytes32' },
        { name: '_options', type: 'bytes' }
      ],
      outputs: []
    }],
    functionName: 'settle',
    args: [account.address, dstChainHash, options],
    value: lzFee
  });
  
  console.log(`Settlement tx: ${hash}`);
  
  const receipt = await client.waitForTransactionReceipt({ hash });
  console.log(`Settlement confirmed at block ${receipt.blockNumber}`);
  
  return receipt;
}
```

<Note>
  Settlement triggers a LayerZero cross-chain message. It takes \~30-60 seconds for the message to be delivered and verified on the source chain.
</Note>

## Step 8: Withdraw Funds + Fee

### Wait for Settlement Delivery

```typescript theme={null}
async function waitForSettlement(orderId: string): Promise<boolean> {
  const timeout = Date.now() + 120000; // 2 minute timeout
  
  while (Date.now() < timeout) {
    try {
      // Check if settlement message was delivered
      // You can track this via LayerZero scan or contract events
      const settled = await checkIfSettled(orderId);
      
      if (settled) {
        console.log('Settlement message delivered');
        return true;
      }
    } catch (error) {
      console.error('Error checking settlement:', error);
    }
    
    await sleep(5000); // Check every 5 seconds
  }
  
  console.log('Settlement timeout');
  return false;
}
```

### Execute Withdrawal

```typescript theme={null}
async function executeWithdrawal(
  inputToken: `0x${string}`,
  amount: bigint
) {
  const account = privateKeyToAccount(process.env.LP_PRIVATE_KEY as `0x${string}`);
  const client = createWalletClient({
    account,
    chain: baseSepolia,
    transport: http()
  });
  
  console.log('Executing withdrawal...');
  console.log(`Amount: ${amount.toString()}`);
  
  const hash = await client.writeContract({
    address: LIDIAN_CONTRACT,
    abi: [{
      name: 'withdraw',
      type: 'function',
      stateMutability: 'nonpayable',
      inputs: [
        { name: 'token', type: 'address' },
        { name: 'amount', type: 'uint256' }
      ],
      outputs: []
    }],
    functionName: 'withdraw',
    args: [inputToken, amount]
  });
  
  console.log(`Withdrawal tx: ${hash}`);
  
  const receipt = await client.waitForTransactionReceipt({ hash });
  console.log(`Withdrawal confirmed at block ${receipt.blockNumber}`);
  console.log('✅ Order complete! Fees earned.');
  
  return receipt;
}
```

## Complete Implementation Example

```typescript theme={null}
async function processOrder(
  orderId: string,
  quoteRequest: QuoteRequest,
  outputAmount: string
) {
  try {
    // 1. Fetch order with signature
    const order = await fetchOrder(orderId);
    
    // 2. Build order struct
    const orderStruct: OrderStruct = {
      inputAmount: BigInt(quoteRequest.inputAmount),
      outputAmount: BigInt(outputAmount),
      inputToken: quoteRequest.inputToken as `0x${string}`,
      outputToken: quoteRequest.outputToken as `0x${string}`,
      startTime: quoteRequest.startTime,
      endTime: quoteRequest.endTime,
      srcChainId: getChainHash(quoteRequest.inputChain),
      dstChainId: getChainHash(quoteRequest.outputChain),
      offerer: quoteRequest.offerer as `0x${string}`,
      recipient: quoteRequest.recipient as `0x${string}`
    };
    
    // 3. Deposit on source chain
    await executeDeposit(orderStruct, order.signature as `0x${string}`);
    
    // 4. Fill on destination chain
    await executeFill(orderStruct);
    
    // 5. Settle back to source chain
    await executeSettlement(
      orderStruct.srcChainId,
      orderStruct.dstChainId
    );
    
    // 6. Wait for settlement delivery
    const settled = await waitForSettlement(orderId);
    if (!settled) {
      throw new Error('Settlement timeout');
    }
    
    // 7. Withdraw funds + fee
    const withdrawAmount = orderStruct.inputAmount; // This includes your fee
    await executeWithdrawal(orderStruct.inputToken, withdrawAmount);
    
    console.log(`✅ Order ${orderId} completed successfully!`);
    
  } catch (error) {
    console.error(`❌ Order processing failed:`, error);
    throw error;
  }
}
```

## Profit Calculation

After completing an order, calculate your earnings:

```typescript theme={null}
function calculateProfit(
  inputAmount: bigint,
  outputAmount: bigint,
  gasUsed: {
    deposit: bigint;
    fill: bigint;
    settle: bigint;
    withdraw: bigint;
  },
  gasPrice: bigint
): bigint {
  // Fee earned (difference between input and output)
  const feeEarned = inputAmount - outputAmount;
  
  // Total gas cost
  const totalGas = gasUsed.deposit + gasUsed.fill + gasUsed.settle + gasUsed.withdraw;
  const gasCost = totalGas * gasPrice;
  
  // Net profit (in wei)
  const netProfit = feeEarned - gasCost;
  
  return netProfit;
}

// Example:
// Input: 1,000 USDC (1,000,000,000 with 6 decimals)
// Output: 998.5 USDC (998,500,000 with 6 decimals)
// Fee earned: 1.5 USDC (1,500,000)
// Gas cost: ~$0.10 (100,000 wei assuming USDC = ETH for simplicity)
// Net profit: 1.4 USDC ($1.40)
```

## Production Considerations

### Error Handling

```typescript theme={null}
async function processOrderWithRetry(
  orderId: string,
  maxRetries: number = 3
) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      await processOrder(orderId, quoteRequest, outputAmount);
      return; // Success
    } catch (error) {
      console.error(`Attempt ${attempt} failed:`, error);
      
      if (attempt === maxRetries) {
        // Final failure - alert admin
        await sendAlert(`Order ${orderId} failed after ${maxRetries} attempts`);
        throw error;
      }
      
      // Wait before retry (exponential backoff)
      await sleep(Math.pow(2, attempt) * 1000);
    }
  }
}
```

### Balance Monitoring

```typescript theme={null}
async function checkBalances(): Promise<void> {
  const chains = ['base-sepolia', 'polygon-amoy'];
  
  for (const chain of chains) {
    const balance = await getTokenBalance(
      chain,
      USDC_ADDRESS,
      LP_WALLET
    );
    
    if (balance < MIN_BALANCE_THRESHOLD) {
      await sendAlert(`Low balance on ${chain}: ${balance}`);
    }
  }
}

// Run every 5 minutes
setInterval(checkBalances, 5 * 60 * 1000);
```

### Nonce Management

```typescript theme={null}
class NonceManager {
  private nonces = new Map<string, number>();
  
  async getNonce(address: string, chainId: number): Promise<number> {
    const key = `${address}-${chainId}`;
    
    if (!this.nonces.has(key)) {
      const nonce = await fetchOnChainNonce(address, chainId);
      this.nonces.set(key, nonce);
    }
    
    return this.nonces.get(key)!;
  }
  
  incrementNonce(address: string, chainId: number): void {
    const key = `${address}-${chainId}`;
    const current = this.nonces.get(key) || 0;
    this.nonces.set(key, current + 1);
  }
}
```

## Testing Your Implementation

### Testnet Setup

1. Get testnet tokens from faucets:
   * Base Sepolia: [https://www.coinbase.com/faucets](https://www.coinbase.com/faucets)
   * Polygon Amoy: [https://faucet.polygon.technology/](https://faucet.polygon.technology/)

2. Fund your LP wallet with:
   * Gas tokens (ETH, MATIC)
   * Stablecoins (USDC, USDT)

3. Test with small amounts first:
   * Start with \$1-10 swaps
   * Verify all transactions succeed
   * Check balance updates

### Debug Logging

```typescript theme={null}
function logOrderProgress(step: string, data: any) {
  console.log(`[${new Date().toISOString()}] ${step}`, {
    orderId: data.orderId,
    chain: data.chain,
    txHash: data.txHash,
    gasUsed: data.gasUsed,
    ...data
  });
}
```

## Contract Addresses

### Testnet Contracts

| Network        | Lidian Contract                              | LayerZero Adapter                            |
| -------------- | -------------------------------------------- | -------------------------------------------- |
| Base Sepolia   | `0xc2c00E85ab6bcf865986DE84053a6169bCBfa70F` | `0xe6dF658A8f53D47fec5294F351Adf11111C6fa01` |
| Polygon Amoy   | `0x7bE37DE6d81C6B231c8579901C6717f1A08c41ed` | `0x9ecf258aA68a483ac89057cBB9deAD71D6a7a3E0` |
| Avalanche Fuji | `0x875200c20719eB6914405c5C989226F97418e928` | `0xDfaF9D6f669625eb63C98F3A34d03eC06ea2A073` |

## Next Steps

Now that you understand the implementation:

1. **Build your service** using this guide as a reference
2. **Test thoroughly** on testnets before mainnet
3. **Monitor performance** and optimize for your use case
4. **Scale gradually** as you gain confidence

<Note>
  For production API keys and support, contact the [Lidian team](https://calendly.com/dantereminick-lidian/30min).
</Note>

## Additional Resources

* [API Reference](/api-reference/introduction) - All API endpoints
* [Smart Contracts](/protocol/contracts) - Contract architecture
* [WebSocket API](/developers/websockets) - Real-time updates
* [EIP-712 Signing](/developers/domain) - Signature format
