Skip to main content
This flow starts with a funded source asset on any supported chain and ends with BTC delivered to Spark, Bitcoin L1, or Lightning, or USDB delivered to Spark. If you want a reusable deposit address that runs this flow automatically on each deposit, use Accumulation Addresses. Common uses:
  • Wallet buy flow: users pay USDC and receive BTC to a Spark address, Bitcoin address, or Lightning invoice.
  • Payout rails: convert USDC into BTC without running Bitcoin infrastructure.
  • USDC (solana|base|ethereum|arbitrum|optimism|polygon|tron) -> BTC (spark|bitcoin|lightning)
  • USDC (solana|base|ethereum|arbitrum|optimism|polygon|tron) -> USDB (spark)
  • USDT (ethereum|arbitrum|optimism|tron|plasma) -> BTC (spark|bitcoin|lightning)
  • USDT (ethereum|arbitrum|optimism|tron|plasma) -> USDB (spark)
  • ETH (ethereum) -> BTC (spark|bitcoin|lightning)
  • ETH (ethereum) -> USDB (spark)
  • SOL (solana) -> BTC (spark|bitcoin|lightning)
  • SOL (solana) -> USDB (spark)
For other chains (ethereum, arbitrum, optimism, polygon, tron, plasma), deposits are detected automatically.
ChainTokenAddress
BaseUSDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
SolanaUSDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
EthereumUSDC0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
EthereumUSDT0xdAC17F958D2ee523a2206206994597C13D831ec7
ArbitrumUSDC0xaf88d065e77c8cC2239327C5EDb3A432268e5831
ArbitrumUSDT0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9
OptimismUSDC0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85
OptimismUSDT0x94b008aA00579c1307B0EF2c499aD98a8ce58e58
PolygonUSDC0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359
TronUSDTTR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t
PlasmaUSDT

Flow

  1. Create a quote: POST /v1/orchestration/quote.
  2. Send the source asset to depositAddress for amountIn.
  3. Submit the deposit transaction: POST /v1/orchestration/submit.
  4. Track status via webhooks or GET /v1/orchestration/status?id=....
Quotes expire 2 minutes after creation. Deposits arriving after expiry are repriced at live market rates.

Affiliate Fees

App fees are supported on these routes when amountMode=exact_in. Fees are computed in USDC and settled on Solana. Flashnet retains a 20% platform cut of all app fees; the remaining 80% goes to the fee recipient. Affiliate fees use a holdback model where the recipient’s 80% share accumulates and is claimed by the affiliate. For SOL/ETH routes, the engine converts to USDC first, then applies fees. See Quotes and Orders for the full affiliate fee model.

Example: USDC (Base) to BTC (Spark)

const BASE_URL = 'https://orchestration.flashnet.xyz';

const quote = await fetch(`${BASE_URL}/v1/orchestration/quote`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${process.env.FLASHNET_API_KEY}`,
    // Required for authenticated quotes.
    'X-Idempotency-Key': `quote:${Date.now()}`,
  },
  body: JSON.stringify({
    sourceChain: 'base',
    sourceAsset: 'USDC',
    destinationChain: 'spark',
    destinationAsset: 'BTC',
    amount: '100000000',
    recipientAddress: 'spark1...',
    slippageBps: 50,
  }),
}).then((r) => r.json());

// Send USDC to quote.depositAddress for quote.amountIn.
// Capture the deposit transaction hash.
const txHash = await sendUsdcOnBase({
  to: quote.depositAddress,
  amountUsdcSmallest: quote.amountIn,
});

const submit = await fetch(`${BASE_URL}/v1/orchestration/submit`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${process.env.FLASHNET_API_KEY}`,
    'X-Idempotency-Key': `submit:${quote.quoteId}:${txHash}`,
  },
  body: JSON.stringify({
    quoteId: quote.quoteId,
    txHash,
    // Optional but recommended. When present, the deposit verifier checks the sender address.
    sourceAddress: '0xYourSenderAddress',
  }),
}).then((r) => r.json());

const status = await fetch(
  `${BASE_URL}/v1/orchestration/status?id=${encodeURIComponent(submit.orderId)}`,
).then((r) => r.json());

console.log(status.order.status);

Example: SOL (Solana) to BTC (Spark)

{
  "sourceChain": "solana",
  "sourceAsset": "SOL",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "25000000",
  "recipientAddress": "spark1...",
  "slippageBps": 50
}
amount is lamports (1 SOL = 1_000_000_000 lamports).

Example: SOL (Solana) to BTC (Spark) with Affiliate Fee

{
  "sourceChain": "solana",
  "sourceAsset": "SOL",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "100000000",
  "recipientAddress": "spark1...",
  "appFees": [
    {
      "recipient": "Dtkxt55zEUDj6NTXGRtH8uQsACsTjoSVkXfYBEF8xkkT",
      "fee": 100
    }
  ],
  "slippageBps": 50
}

Example: SOL (Solana) to BTC (Spark) with Affiliate Registry

{
  "sourceChain": "solana",
  "sourceAsset": "SOL",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "100000000",
  "recipientAddress": "spark1...",
  "affiliateId": "flashpartner",
  "slippageBps": 50
}

Example: USDC to BTC (Bitcoin L1)

Set destinationChain = bitcoin and provide a Bitcoin address in recipientAddress.
{
  "sourceChain": "base",
  "sourceAsset": "USDC",
  "destinationChain": "bitcoin",
  "destinationAsset": "BTC",
  "amount": "100000000",
  "recipientAddress": "bc1...",
  "slippageBps": 50
}
The submit step is the same as any USDC source quote.

Example: USDC to BTC (Lightning)

Lightning-destination routes use a tiered platform fee: 0.20% (20 bps) when the counterpart asset is USDB, 0.40% (40 bps) for all other routes. For Lightning payouts, recipientAddress must be a BOLT11 invoice. Use an amountless (0-amount) invoice for exact-in mode, or an invoice with an amount matching the target sats for exact-out mode. Amountless invoices are accepted in both modes.
{
  "sourceChain": "solana",
  "sourceAsset": "USDC",
  "destinationChain": "lightning",
  "destinationAsset": "BTC",
  "amount": "25000000",
  "recipientAddress": "lnbc1...",
  "slippageBps": 50
}
The submit step is the same as any USDC source quote.

Example: USDC to BTC (Lightning, Exact Out)

Use exact-out when the recipient must receive a precise number of sats on Lightning. The system determines the required USDC input and includes a routing fee buffer.
{
  "sourceChain": "base",
  "sourceAsset": "USDC",
  "destinationChain": "lightning",
  "destinationAsset": "BTC",
  "amount": "100000",
  "amountMode": "exact_out",
  "recipientAddress": "lnbc1u1...",
  "refundAddress": "0xYourBaseUsdcRefundAddress",
  "slippageBps": 0
}
amount is the target BTC delivery in sats. The recipientAddress can be an amountless invoice or an invoice encoding the same amount (100,000 sats in this case). The quote response includes the same exact-out fields as BTC-to-USDC exact-out:
  • targetAmountOut: the requested sats (matches amount)
  • requiredAmountIn: USDC to deposit
  • maxAcceptedAmountIn: upper bound on accepted deposit
  • inputBufferBps: buffer applied to the required input
Affiliate fees (appFees / affiliateId / affiliateIds) are not supported with amountMode=exact_out.

Example: USDT (Ethereum) to BTC (Spark)

For chain sources other than Solana, the quote returns a deposit address on the source chain. The deposit is detected automatically.
{
  "sourceChain": "ethereum",
  "sourceAsset": "USDT",
  "destinationChain": "spark",
  "destinationAsset": "BTC",
  "amount": "10000000",
  "recipientAddress": "spark1...",
  "slippageBps": 50
}
amount is in USDT smallest units (6 decimals). The depositAddress in the response is an Ethereum address. Send USDT there and the order is created automatically.

Deposit Verification

The engine verifies that the deposit transaction sent the correct asset to the quoted depositAddress. When sourceAddress is provided on submit, the verifier also confirms the sender matches. Deposits do not need to match the quoted amountIn exactly. See Deposit Amount Flexibility for details on how over/underpayments are handled.

Next Steps