Learn how to create your first token on Spark. This guide covers token creation, parameter configuration, and best practices for launching tokens on the Spark network.
Token Creation Flow
The complete process for creating a token on Spark:
Initialize Issuer Wallet
Set up your issuer wallet to manage token operations. import { IssuerSparkWallet } from "@buildonspark/issuer-sdk" ;
const { wallet } = await IssuerSparkWallet . initialize ({
options: { network: "REGTEST" }
});
console . log ( "Issuer wallet ready for token creation" );
Define Token Parameters
Configure your token’s core metadata and properties. const tokenParams = {
tokenName: "My Token" ,
tokenTicker: "MTK" ,
decimals: 8 ,
maxSupply: BigInt ( 1000000 ),
isFreezable: true
};
Create Token
Deploy your token to the Spark network instantly. const tokenCreationTx = await wallet . createToken ( tokenParams );
console . log ( "Token created! Transaction ID:" , tokenCreationTx );
Verify Creation
Confirm your token was created successfully. const metadata = await wallet . getIssuerTokenMetadata ();
console . log ( "Token Name:" , metadata . tokenName );
console . log ( "Token Symbol:" , metadata . tokenSymbol );
console . log ( "Max Supply:" , metadata . maxSupply );
Create Token
Creating a token on Spark is instant and free. This is the moment where you define its core parameters and commit them to chain.
createToken(params)
Creates a new token directly on Spark using Spark Native Tokens (recommended).
const tokenCreationTx = await wallet . createToken ({
tokenName: "Test Token" ,
tokenTicker: "TEST" ,
decimals: 8 ,
maxSupply: BigInt ( 10000000 ),
isFreezable: true
});
console . log ( "Token Creation TX:" , tokenCreationTx );
Human-readable token name (e.g., “USD Coin”)
Token symbol (e.g., “USDC”)
Number of decimal places (e.g., 6 for USDC, 8 for BTC)
Maximum token supply in base units. Set to 0n for unlimited supply
Whether the token can be frozen after issuance
Spark transaction ID of the token creation
What You Need to Know
One Token Per Wallet Token creation is limited to one token per issuer wallet
No L1 Funding Required No Bitcoin L1 funding needed for token creation
Instant Creation Tokens are created instantly on the Spark network
Immutable Metadata Token metadata cannot be changed once set
Immediate Minting Minting can begin immediately after creation
Free Creation Token creation is completely free on Spark
Token Supply Options
Unlimited Supply Tokens
Create tokens with no maximum supply limit:
const unlimitedToken = await wallet . createToken ({
tokenName: "USD Coin" ,
tokenTicker: "USDC" ,
maxSupply: BigInt ( 0 ), // 0n = unlimited supply
decimals: 6 , // 1 USDC = 1_000_000 base units
isFreezable: true
});
console . log ( "Unlimited supply token created:" , unlimitedToken );
Fixed Supply Tokens
Create tokens with a predetermined maximum supply:
// Create a token with max supply of 1 million
const fixedToken = await wallet . createToken ({
tokenName: "My Fixed Token" ,
tokenTicker: "MFT" ,
maxSupply: BigInt ( 1000000000000 ), // 1,000,000.000000 tokens
decimals: 6 ,
isFreezable: false
});
console . log ( "Fixed supply token created:" , fixedToken );
Bitcoin-Style Token
Create a token with Bitcoin-like characteristics:
// Create a token with max 21 million supply and minimum denomination of 0.00000001
const bitcoinToken = await wallet . createToken ({
tokenName: "Example Bitcoin" ,
tokenTicker: "ExBTC" ,
maxSupply: BigInt ( 2100000000000000 ), // 21,000,000.00000000 tokens
decimals: 8 ,
isFreezable: false
});
console . log ( "Bitcoin-style token created:" , bitcoinToken );
Decimal Precision
Understanding how decimals work in token creation:
6 Decimals Example: USDC
Base Units: 1,000,000
Display: 1.000000 USDC
8 Decimals Example: Bitcoin
Base Units: 100,000,000
Display: 1.00000000 BTC
18 Decimals Example: Ethereum
Base Units: 1,000,000,000,000,000,000
Display: 1.000000000000000000 ETH
Decimal Examples
// 6 decimal token (like USDC)
const usdcToken = await wallet . createToken ({
tokenName: "USD Coin" ,
tokenTicker: "USDC" ,
decimals: 6 ,
maxSupply: BigInt ( 1000000000000 ), // 1,000,000 USDC
isFreezable: true
});
// 8 decimal token (like Bitcoin)
const btcToken = await wallet . createToken ({
tokenName: "Bitcoin Token" ,
tokenTicker: "BTC" ,
decimals: 8 ,
maxSupply: BigInt ( 2100000000000000 ), // 21,000,000 BTC
isFreezable: false
});
Freezable vs Non-Freezable Tokens
Freezable Tokens
Tokens that can be frozen by the issuer after creation:
const freezableToken = await wallet . createToken ({
tokenName: "Regulated Token" ,
tokenTicker: "REG" ,
decimals: 8 ,
maxSupply: BigInt ( 1000000 ),
isFreezable: true // Can be frozen by issuer
});
// Later, issuer can freeze tokens for specific addresses
await wallet . freezeTokens ( "spark1..." );
Use cases:
Regulatory compliance
Security tokens
Tokens requiring issuer control
Non-Freezable Tokens
Tokens that cannot be frozen once created:
const nonFreezableToken = await wallet . createToken ({
tokenName: "Decentralized Token" ,
tokenTicker: "DCT" ,
decimals: 8 ,
maxSupply: BigInt ( 1000000 ),
isFreezable: false // Cannot be frozen
});
Use cases:
Decentralized tokens
Utility tokens
Community tokens
Verify Token Creation
After creating your token, verify it was created successfully:
getIssuerTokenMetadata()
Gets the metadata about the issuer’s token.
const metadata = await wallet . getIssuerTokenMetadata ();
console . log ( "Token Name:" , metadata . tokenName );
console . log ( "Token Symbol:" , metadata . tokenSymbol );
console . log ( "Token Decimals:" , metadata . tokenDecimals );
console . log ( "Max Supply:" , metadata . maxSupply );
console . log ( "Is Freezable:" , metadata . isFreezable );
console . log ( "Token Identifier:" , metadata . bech32mTokenIdentifier );
metadata
IssuerTokenMetadata
required
Object containing complete token metadata including public key, name, symbol, decimals, max supply, freezable status, and Bech32m identifier
Legacy L1 Announcements
Deprecated: L1 token announcements via announceTokenL1() are being phased out. While existing tokens announced on-chain will continue to function normally, we recommend using Spark Native Tokens (createToken()) for all new token launches. The L1 announcement flow will be removed from the SDK in upcoming releases.
Why Use Spark Native Tokens?
Instant Creation No waiting for Bitcoin L1 confirmations
No L1 Fees No Bitcoin transaction fees required
Better UX Seamless user experience
Future-Proof Recommended approach for new tokens
Existing tokens that were announced on Bitcoin L1 continue to work exactly as before. From Spark’s perspective, there is no difference in functionality between L1-announced tokens and Spark Native Tokens.
Best Practices
Token Naming
Clear and Descriptive : Use names that clearly describe the token’s purpose
Avoid Confusion : Don’t use names that could be confused with existing tokens
Professional : Use proper capitalization and avoid special characters
Ticker Symbols
Short and Memorable : Keep tickers to 3-5 characters
Uppercase : Use all uppercase letters
Unique : Ensure your ticker is not already in use
Decimal Precision
Match Use Case : Choose decimals that match your token’s intended use
Consider UX : More decimals can complicate user interfaces
Standard Practices : Follow industry standards (6 for stablecoins, 8 for Bitcoin-like tokens)
Supply Strategy
Plan Ahead : Consider your token’s economic model before setting max supply
Unlimited vs Fixed : Decide based on your token’s purpose
Future Flexibility : Remember that metadata is immutable once set
Complete Example
import { IssuerSparkWallet } from "@buildonspark/issuer-sdk" ;
async function createMyToken () {
try {
// 1. Initialize issuer wallet
const { wallet } = await IssuerSparkWallet . initialize ({
options: { network: "REGTEST" }
});
console . log ( "Issuer wallet initialized" );
// 2. Create token with specific parameters
const tokenCreationTx = await wallet . createToken ({
tokenName: "My Awesome Token" ,
tokenTicker: "MAT" ,
decimals: 8 ,
maxSupply: BigInt ( 1000000000000 ), // 1,000,000.00000000 tokens
isFreezable: true
});
console . log ( "Token created successfully!" );
console . log ( "Transaction ID:" , tokenCreationTx );
// 3. Verify token creation
const metadata = await wallet . getIssuerTokenMetadata ();
console . log ( "Token Details:" );
console . log ( "- Name:" , metadata . tokenName );
console . log ( "- Symbol:" , metadata . tokenSymbol );
console . log ( "- Decimals:" , metadata . tokenDecimals );
console . log ( "- Max Supply:" , metadata . maxSupply );
console . log ( "- Is Freezable:" , metadata . isFreezable );
console . log ( "- Token ID:" , metadata . bech32mTokenIdentifier );
// 4. Start minting tokens
const mintTx = await wallet . mintTokens ( BigInt ( 100000000 )); // 1.00000000 tokens
console . log ( "Initial tokens minted:" , mintTx );
} catch ( error ) {
console . error ( "Token creation failed:" , error );
}
}
createMyToken (). catch ( console . error );