Tokens
All value in a ledger is represented as tokens. Each token is an indivisible, single unit of an asset, which denotes a specific type of value - for example, USD or acme-series-a.
On this page
To create new value in a ledger, you issue tokens into an account with a transaction. To transfer value in a ledger, you transfer tokens from one account to another. To remove value from a ledger, you retire tokens from an account.
Token TagsLink to this section
When issuing or transferring tokens into an account, you may wish to tag them for later distinction by providing token tags.
You can then specify a filter when transferring or retiring tokens from the account to target the tokens with specific tags.
Unlike the tags on other objects in the ledger, token tags only exist on the current state of the tokens in an account. Once those tokens are transferred in a transaction, the tags are removed and new tags can be added as they land in the destination account.
Updating tagsLink to this section
Since tokens are the fundamental state of the ledger, in order to update the tags on a group of tokens, you must create a transaction. In the future we will provide a special method for building a transaction that updates tags on tokens, but for now, you transfer them to and from the same account.
Data StructureLink to this section
The ledger does not store individual token objects, but rather token group objects, which each represent an amount of identical tokens.
If every token is unique, each token group will have an amount of 1.
Field DescriptionsLink to this section
| Field | Type | Description |
|---|---|---|
| amount | integer | Amount of tokens. |
| tags | JSON object | Arbitrary, user-supplied, key-value data about the tokens. |
| asset id | string | The id of the asset of the tokens. |
| asset tags | JSON object | The tags of the asset of the tokens. |
| account id | string | The id of the account that holds the tokens. |
| account tags | string | The tags of the account that holds the tokens. |
Example ObjectLink to this section
{
amount: 10,
tags: {},
assetId: ""
assetTags: {},
accountId: "",
accountTags: {},
}{
amount: 10,
tags: {},
assetId: ""
assetTags: {},
accountId: "",
accountTags: {},
}{
amount: 10,
tags: {},
asset_id: ""
asset_tags: {},
account_id: "",
account_tags: {},
}QueriesLink to this section
There are two different types of queries that you can perform on tokens:
- A list query lists token groups in the ledger
- A sum query is an aggregate over the
amountfields in a filtered list of token groups.
Both queries accept a filter to narrow the results.
List tokensLink to this section
The list tokens query is useful when you use token tags to differentiate tokens of the same asset in an account.
For example, if your application tracks stock certificates by tagging Acme stock tokens with a cost basis and purchase date in the token tags, you can list the token groups in Alice's account to see all her certificates.
Sum tokensLink to this section
The sum tokens query is how you calculate balances in the ledger.
For example, to calculate all the USD balance in Alice's account, you sum all the USD tokens in her account. Or to calculate the total amount of USD in the ledger, you sum all the USD tokens across all accounts.
ExamplesLink to this section
Issue tokensLink to this section
Issue 100 USD tokens to Alice's account.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Issue()
.setAssetId("usd")
.setAmount(100)
.setDestinationAccountId("alice")
).transact(ledger);await ledger.transactions.transact(b => {
b.issue({
amount: 100,
assetId: 'usd',
destinationAccountId: 'alice',
})
})tx = ledger.transactions.transact do |builder|
builder.issue(
asset_id: 'usd',
amount: 100,
destination_account_id: 'alice'
)
endIssue tokens with tagsLink to this section
Issue 100 debt tokens to Alice's account that are due December, 2018:
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Issue()
.setAssetId("debt")
.setAmount(100)
.setDestinationAccountId("alice")
.addTokenTagsField("due", "Dec2018")
).transact(ledger);await ledger.transactions.transact(b => {
b.issue({
amount: 100,
assetId: 'debt',
destinationAccountId: 'alice',
tokenTags: { due: 'Dec2018' },
})
})tx = ledger.transactions.transact do |builder|
builder.issue(
asset_id: 'debt',
amount: 100,
destination_account_id: 'alice',
token_tags: {due: 'Dec2018'}
)
endTransfer tokensLink to this section
Transfer 20 USD tokens from Alice's account to Bob's account.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("usd")
.setAmount(20)
.setSourceAccountId("alice")
.setDestinationAccountId("bob")
).transact(ledger);await ledger.transactions.transact(b => {
b.transfer({
amount: 20,
assetId: 'usd',
sourceAccountId: 'alice',
destinationAccountId: 'bob',
})
})tx = ledger.transactions.transact do |builder|
builder.transfer(
asset_id: 'usd',
amount: 20,
source_account_id: 'alice',
destination_account_id: 'bob'
)
endUpdate tags by transferring tokens to same accountLink to this section
Update the due date from Dec2018 to Feb2019 on 20 debt tokens in Alice's account:
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("debt")
.setAmount(20)
.setSourceAccountId("alice")
.setDestinationAccountId("alice")
.setFilter("tags.due=$1")
.addFilterParameter("Dec2018")
.addTokenTagsField("due", "Feb2019")
).transact(ledger);await ledger.transactions.transact(b => {
b.transfer({
amount: 20,
assetId: 'debt',
sourceAccountId: 'alice',
destinationAccountId: 'alice',
filter: 'tags.due=$1',
filterParams: ['Dec2018'],
tokenTags: { due: 'Feb2019' },
})
})tx = ledger.transactions.transact do |builder|
builder.transfer(
asset_id: 'debt',
amount: 20,
source_account_id: 'alice',
destination_account_id: 'alice',
filter: 'tags.due=$1',
filter_params: ['Dec2018'],
token_tags: {due: 'Feb2019'}
)
endRetire tokensLink to this section
Retire 5 USD tokens from Bob's account.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Retire()
.setAssetId("usd")
.setAmount(5)
.setSourceAccountId("bob")
).transact(ledger);await ledger.transactions.transact(b => {
b.retire({
amount: 5,
assetId: 'usd',
sourceAccountId: 'bob'
})
})tx = ledger.transactions.transact do |builder|
builder.retire(
asset_id: 'usd',
amount: 5,
source_account_id: 'bob'
)
endRetire tokens filtered by tagsLink to this section
Retire 80 of Alice's debt tokens due December 2018:
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Retire()
.setAssetId("debt")
.setAmount(80)
.setSourceAccountId("alice")
.setFilter("tags.due=$1")
.addFilterParameter("Dec2018")
).transact(ledger);await ledger.transactions.transact(b => {
b.retire({
assetId: 'debt',
amount: 80,
sourceAccountId: 'alice',
filter: 'tags.due=$1',
filterParams: ['Dec2018']
})
})tx = ledger.transactions.transact do |builder|
builder.retire(
asset_id: 'debt',
amount: 80,
source_account_id: 'alice',
filter: 'tags.due=$1',
filter_params: ['Dec2018']
)
endSum tokens in an accountLink to this section
Query the first two pages of "balances" in Alice's account.
TokenSum.Page page1 = new Token.SumBuilder()
.setFilter("accountId=$1")
.addFilterParameter("alice")
.addGroupByField("assetId")
.setPageSize(10)
.getPage(ledger);
for (TokenSum balance : page1.items) {
System.out.println("amount: " + balance.amount);
System.out.println("asset: " + balance.assetId);
}
String cursor = page1.cursor;
TokenSum.Page page2 = new Token.SumBuilder()
.getPage(ledger, cursor);
for (TokenSum balance : page2.items) {
System.out.println("amount: " + balance.amount);
System.out.println("asset: " + balance.assetId);
}let page1 = await ledger.tokens
.sum({
filter: 'accountId=$1',
filterParams: ['alice'],
groupBy: ['assetId'],
})
.page({ size: 10 })
page1.items.forEach(balance => {
// console.log(balance)
})
let page2 = await ledger.tokens
.sum()
.page({ cursor: page1.cursor })
page2.items.forEach(balance => {
// console.log(balance)
})page1 = ledger.tokens.sum(
filter: 'account_id=$1',
filter_params: ['alice'],
group_by: ['asset_id'],
).page(size: 10)
page1.each do |balance|
puts 'amount: ', balance.amount
puts 'asset: ', balance.asset_id
end
cursor = page1.cursor
page2 = ledger.tokens.sum.page(cursor: cursor)
page2.each do |balance|
puts 'amount: ', balance.amount
puts 'asset: ', balance.asset_id
endList tokens in an accountLink to this section
Query the first two pages of token groups in Alice's account.
Token.Page page1 = new Token.ListBuilder()
.setFilter("accountId=$1")
.addFilterParameter("alice")
.setPageSize(10)
.getPage(ledger);
for (Token token : page1.items) {
...
}
String cursor = page1.cursor;
Token.Page page2 = new Token.ListBuilder()
.getPage(ledger, cursor);
for (Token token : page2.items) {
...
}page1 = await ledger.tokens
.list({
filter: 'accountId=$1',
filterParams: ['alice'],
})
.page({ size: 10 })
page1.items.forEach(group => {
// console.log(group)
})
page2 = await ledger.tokens
.list()
.page({ cursor: page1.cursor })
page2.items.forEach(group => {
// console.log(group)
})page1 = ledger.tokens.list(
filter: 'account_id=$1',
filter_params: ['alice'],
).page(size: 10)
page1.each do |group|
puts group.to_json
end
cursor = page1.cursor
page2 = ledger.tokens.list.page(cursor: cursor)
page2.each do |group|
puts group.to_json
end