Tokens in @bsv/simple are PushDrop outputs with encrypted payloads. They can hold any JSON-serializable data, be transferred between wallets, and be sent peer-to-peer via MessageBox.
Creating a Token
Copy const result = await wallet . createToken ( {
data : { type : ' loyalty ' , points : 100 , tier : ' gold ' },
basket : ' my-tokens ' ,
satoshis : 1
} )
console . log ( ' Token created: ' , result . txid )
console . log ( ' Basket: ' , result . basket )
console . log ( ' Encrypted: ' , result . encrypted ) // true How Token Creation Works
Your data is serialized to JSON
The JSON is encrypted using the wallet's key derivation (counterparty: 'self')
The ciphertext is locked in a PushDrop script
The output is stored in the specified basket with customInstructions containing the decryption parameters
The listTokenDetails method:
Fetches all outputs from the basket with locking scripts and custom instructions
Decodes each PushDrop locking script
Reads the customInstructions to get decryption parameters
Decrypts the payload and parses it as JSON
Falls back to counterparty: 'anyone' if 'self' decryption fails (for compatibility with older tokens)
Sending a Token (On-Chain)
Transfer a token to another wallet directly on-chain:
How Token Send Works
This is a two-step signing flow:
The original token output is fetched with its full transaction (BEEF format)
The PushDrop fields are decoded from the original locking script
A new PushDrop output is created with a fresh key, locked to the recipient
createAction() is called with the old token as input and new token as output
The SDK returns a signableTransaction (since we need to provide the PushDrop unlock)
The unlock template signs the transaction
signAction() completes the transaction
The token stays in the same basket but with updated customInstructions reflecting the new key and counterparty.
Redeeming a Token
Spend a token and recover its satoshis:
This uses the same two-step signing flow as sendToken, but creates no outputs — the token's satoshis return to the wallet as change.
Sending a Token via MessageBox
Transfer a token to another wallet using MessageBox P2P messaging:
This creates the token transfer transaction on-chain, then sends the transaction bytes to the recipient via the simple_token_inbox MessageBox.
Receiving Tokens via MessageBox
acceptIncomingToken internalizes the token using basket insertion protocol and acknowledges the message to remove it from the inbox.
Incoming Token Structure
Complete Example