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.

A Spark token on the Execution side is a SparkToken ERC20 contract that represents a Spark-native asset one-to-one. The gateway deploys it the first time anyone deposits that asset, then mints and burns through the same contract for every subsequent deposit and withdrawal.

How it gets deployed

  1. A user submits a deposit intent referencing a Spark transfer of token id T.
  2. The gateway looks up T in its registry. If no contract exists, it calls depositBtknWithDeploy on SparkGateway.
  3. The gateway deploys a fresh SparkToken ERC20 via CREATE2. The address is deterministic in (salt = T, name, symbol, decimals).
  4. The gateway mints the deposit amount to the recipient’s EVM address. Subsequent deposits skip the deploy step and just mint.
The deployment is idempotent: if the contract already exists, the deploy step is a no-op.

Get the contract address

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

const tokenIdHex = "...";  // 64-char hex token id (decoded from bech32m)
const tokenAddress = await querySparkTokenAddress(
  rpcUrl,
  gatewayAddress,
  tokenIdHex
);

if (!tokenAddress) {
  // Token not deployed yet. Submit a deposit (or depositBtknWithDeploy) first.
}
The bech32m form (btknrt1... / btkn1...) is what users see; the gateway indexes by the underlying 32-byte hex id. To convert:
import { decodeSparkHumanReadableTokenIdentifier } from "@flashnet/sdk";

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

Wait for first deployment

A first-deposit intent deploys the contract atomically with the first mint. If you submit a deposit and want the address back as soon as it lands, poll:
import { waitForSparkTokenAddress } from "@flashnet/sdk";

const address = await waitForSparkTokenAddress(
  rpcUrl,
  gatewayAddress,
  tokenIdHex,
  20_000  // timeout ms
);
Returns null on timeout. Adjust the timeout based on how long your gateway takes to reach finality on first-deposit intents (usually a few seconds).

Properties

SparkToken is a standard ERC20 with three notable differences:
FeatureBehavior
DecimalsSet at deploy time from Spark token metadata. Not always 18. Always read with decimals() before doing amount math.
EIP-2612 PermitImplemented. Lets TradingClient swap your tokens without a standing allowance.
Mint and burnRestricted to the gateway. The token’s OnlyGateway() error fires if anyone else tries.
Standard ERC20 calls (balanceOf, transfer, approve, transferFrom) work as expected. Use the regular reading-state helpers to query.

Bytecode determinism

Because SparkToken is deployed via CREATE2 with the Spark token id as salt, the resulting EVM address is the same on every Flashnet deployment that shares the same SparkGateway proxy. You can compute it off-chain if you need to reference the address before the first deposit. In practice, query tokenBySparkId or querySparkTokenAddress instead — the gateway is the source of truth.

Listing all deployed tokens

SparkGateway.getDeployedTokens() returns every Spark token contract the gateway has spawned. For paginated listing, use getDeployedTokensPaginated(offset, limit). Off-chain indexers (Blockscout, the /network/info endpoint) are the better path for production UIs — chain reads of getDeployedTokens() aren’t bounded.