Skip to main content

Documentation Index

Fetch the complete documentation index at: https://flashnet-build.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

client.deposit references one or more existing Spark transfers and credits the resulting EVM balance in a single signed intent. The Spark transfer leg is the caller’s responsibility — client.deposit does not move funds out of the SparkWallet. The single-intent round-trip pattern that does both legs lives on TradingClient.swap({ useAvailableBalance: true }); see Swaps.

Native sats

import { ExecutionClient } from "@flashnet/sdk";

const execClient = new ExecutionClient(sparkWallet, {
  gatewayUrl,
  rpcUrl,
  chainId,
});
await execClient.authenticate();

// 1. Send the Spark transfer to the gateway's deposit address.
const { spark } = await execClient.getNetworkInfo();
const transfer = await sparkWallet.transfer({
  amountSats: 100_000,
  receiverSparkAddress: spark.depositAddress,
});

// 2. Reference its id in the deposit intent. The gateway requires pure
//    hex (no dashes, no 0x prefix), which is what the Spark SDK returns
//    for tokens. For BTC the Spark SDK returns a UUID — strip the dashes.
const sparkTransferId = transfer.id.replace(/-/g, "");

const result = await execClient.deposit({
  deposits: [
    { sparkTransferId, amount: 100_000n, asset: { type: "btc" } },
  ],
});

console.log(result.intentId, result.status);
The intent enters oracle_pending while the deposit oracle confirms the Spark transfer against the operator DB. Once confirmed and finalized, your EVM-side balance reflects the credit. The recipient field is optional. If omitted, the deposit credits the EVM address derived from the same identity key. Pass an explicit address when you want to fund a different account.

Spark tokens

Tokens follow the same two-step shape, with two name changes: transferTokens instead of transfer, and the tokenId in the deposit payload is the 32-byte hex form, not bech32m.
import { decodeSparkHumanReadableTokenIdentifier } from "@flashnet/sdk";

const { tokenIdentifier: bech32m } = { tokenIdentifier: "btknrt1..." };
const { tokenIdentifier: hexTokenId } = decodeSparkHumanReadableTokenIdentifier(
  bech32m,
  "REGTEST"
);

const { spark } = await execClient.getNetworkInfo();
const sparkTransferId = await sparkWallet.transferTokens({
  tokenIdentifier: bech32m,
  tokenAmount: 1_000_000n,
  receiverSparkAddress: spark.depositAddress,
});

await execClient.deposit({
  deposits: [
    {
      sparkTransferId,
      amount: 1_000_000n,
      asset: { type: "token", tokenId: hexTokenId },
    },
  ],
});
If this is the first deposit of that token, the gateway deploys a SparkToken contract via CREATE2 and credits the balance to your EVM address. Subsequent deposits hit the same contract.

Multiple deposits in one intent

The deposits array carries any number of assets, each with its own sparkTransferId. Submit them together when you want them to land atomically:
await execClient.deposit({
  deposits: [
    { sparkTransferId: btcTransferId,   amount: 50_000n,    asset: { type: "btc" } },
    { sparkTransferId: tokenTransferId, amount: 1_000_000n, asset: { type: "token", tokenId: hexTokenId } },
  ],
});
This is the foundation of the swap-and-withdraw flow that TradingClient builds on. The pattern is: deposit → execute action → withdraw, all in one signed intent.

Status lifecycle

The response includes a submissionId and an intentId. The intent moves through:
accepted -> oracle_pending -> included_pending_finality -> finalized
                                                        \-> rejected
                                                        \-> expired
oracle_pending is where deposit-shaped intents wait for the Spark operator-DB to confirm every transfer id. Most flows can wait for finalized before reading downstream balances. For low-latency UIs, included_pending_finality is enough to update optimistic state. See Intents → Status lifecycle.

Constraints

  • Minimum deposit. The gateway advertises an advisory client-side minimum at getNetworkInfo().minDepositSats. The gateway enforces its own bounds at admission, so a deposit below the advertised minimum may still be rejected. Treat the value as a UI hint, not a contract.
  • Sub-sat alignment. Native sats deposits must be whole-sat amounts. The contract rejects sub-sat dust.
  • Replay protection. Each Spark transfer id can only be applied once. SparkGateway.usedTransferIds records the binding on first use; a second deposit referencing the same id reverts with TransferAlreadyUsed().
  • Expiry. Intents expire after 15 minutes by default. Set expiresAt (unix ms) for a longer window, up to the gateway’s 24h cap.