Before your token can exist on Spark, it needs to be announced on Bitcoin L1 — publicly and immutably.

To do this, you broadcast a transaction embedding your token’s identifier and metadata in an OP_RETURN output, a special field in Bitcoin transactions that lets you attach arbitrary data. Learn more about OP_RETURN.

This is a one-time commitment. Once the transaction is mined, your LRC-20 token is locked in — name, supply, decimals, and any additional settings become part of Bitcoin’s canonical history. It’s like etching the blueprint into stone — once it’s set, there’s no going back.

What you keed to know

  • Each Issuer Wallet can only issue one token
  • Bitcoin network fees are required for the announcement
  • Confirmation typically takes 1–2 blocks (~10–20 minutes)
  • Token metadata is permanent after announcement
  • Save the announcement transaction ID so you can refer to it later

Prerequisites

Step 1: Get Your L1 Wallet Address

Once your wallet is initialized, retrieve its Bitcoin L1 address. This is where you’ll send funds to cover the announcement transaction fee.

const l1Address = wallet.getTokenL1Address();
console.log(l1Address); // example: bcrt1....

Step 2: Fund Your L1 Wallet

Send a small amount of BTC to the address above - around $3-5 worth is plenty. This will be used to pay the network fee for your token announcement and should take about >10 minutes to confirm.

If you’re testing on Lightspark regtest, use our faucet:.

  • Username: hackathon
  • Password: MakeBitcoinMoneyAgain

Step 3: Broadcast the L1 Announcement Transaction

You’re now ready to announce your token on Bitcoin L1.

const announcementTx = await wallet.announceTokenL1({
    tokenName: "Test Token",
    tokenTicker: "TEST",
    decimals: 8,
    maxSupply: 10000000n,
    isFreezable: true,
});

console.log("Announcement TX:", announcementTx);

Parameters

The announceTokenL1() function accepts the following metadata:

ParameterTypeDescription
tokenNamestringHuman-readable token name (e.g., “USD Coin”)
tokenTickerstringToken symbol (e.g., “USDC”)
decimalsnumberNumber of decimal places (e.g., 6 for USDC, 8 for BTC)
maxSupplybigintMaximum token supply in base units. Set to 0n for unlimited supply
isFreezeablebooleanWhether the token can be frozen after issuance

Returns

Promise<string>; // Bitcoin transaction ID of the announcement

Examples

Creating an Unlimited Supply Token

const txId = await wallet.announceTokenL1({
  tokenName: "USD Coin",
  tokenTicker: "USDC",
  maxSupply: 0n, // Unlimited supply
  decimals: 6, // 1 USDC = 1_000_000 base units
  isFreezeable: true,
});

console.log("Announcement TX:", txId);

Creating a Fixed Supply Token

// Create a token with max supply of 1 million
const txId = await wallet.announceTokenL1({
  tokenName: "My Fixed Token",
  tokenTicker: "MFT",
  maxSupply: 1_000_000_000_000n, // 1,000,000.000000 tokens
  decimals: 6,
  feeRate: 2,
  isFreezeable: false,
});

console.log("Announcement TX:", txId);

Next Steps

Once your token is created, you can mint some tokens.