Sigil treats fungible tokens as a native primitive. There is no contract to deploy. You issue a token class with CreateTokenClass, mint supply with MintToken, transfer with TransferToken, and burn with BurnToken. The executor enforces the supply policy on every state transition.

When to use this

  • Issue a stablecoin, points balance, or revenue-share unit.
  • Mint a treasury currency for an autonomous organisation.
  • Wrap an external asset for use in Sigil DEX pools.
For NFTs (non-fungible, one-of-one) see Mint an NFT.

Prerequisites

  • A funded controller DID (the DID that will hold mint and policy authority).
  • An RPC endpoint and the standard SIGIL_* environment variables.

Recipe

1

Create the token class

CreateTokenClass defines the token’s identifier, ticker, decimals, issuer, controller, and supply policy. The token id must be globally unique.
import { signAndSend } from './lib'; // see Quickstart for the signAndSend pattern

await signAndSend({
  CreateTokenClass: {
    token_id: 'tok:demo:points',
    ticker: 'PTS',
    decimals: 0,
    issuer_did: process.env.SIGIL_SENDER_DID,
    controller_did: process.env.SIGIL_SENDER_DID,
    supply_policy: {
      // Capped supply, no further inflation after cap reached.
      Capped: { max_supply: '1000000' },
    },
    transfer_policy: null,    // null = no restriction
    metadata_uri: 'ipfs://bafkrei.../points.json',
  },
});
supply_policy variants live in sigil-core/src/transaction.rs: Fixed, Capped, Inflationary, and Controlled.
2

Mint initial supply

await signAndSend({
  MintToken: {
    token_id: 'tok:demo:points',
    recipient_did: 'did:oas:sigil:agent:recipient...',
    amount: '500000',
  },
});
Amounts are decimal strings on the wire — u128 does not fit in JavaScript’s Number.
3

Transfer the token

await signAndSend({
  TransferToken: {
    token_id: 'tok:demo:points',
    recipient_did: 'did:oas:sigil:agent:other...',
    amount: '1000',
    memo: 'rewards Q1',
  },
});
4

Burn to reduce supply

Only the holder (or a controller, depending on transfer_policy) can burn.
await signAndSend({
  BurnToken: {
    token_id: 'tok:demo:points',
    owner_did: process.env.SIGIL_SENDER_DID,
    amount: '100',
  },
});

Reading state

curl -s "$SIGIL_RPC_URL" \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"sigil_getAccount",
       "params":{"did":"did:oas:sigil:agent:recipient...","token_id":"tok:demo:points"}}'
The response includes the holder’s balance for that specific token.

Common errors

SymptomCauseFix
token_id already existsThe id was used in a prior blockChoose a new id — token ids are immutable
mint exceeds max_supplyCapped policy exhaustedBurn first, or raise the cap via SetTokenPolicy
transfer denied by policytransfer_policy restricts transfersSubmit through the policy controller’s flow
decimals out of rangedecimals > 18Pick a value in [0, 18]

See also