Transactions
Transactions are atomic ledger updates that issue, transfer, and/or retire tokens in the ledger. A transaction is comprised of one or more actions.
On this page
All actions in a transaction occur simultaneously. Each action operates on tokens of a single asset, but you can use multiple actions in a single transaction to atomically operate on multiple assets.
When the core commits a transaction, it gives it a timestamp and a sequence number — its absolute position in the ledger. Neither changes afterwards, and no transaction is inserted before one already committed, so two parties reading the ledger read the same transactions in the same order.
- Issue – The issue action issues new tokens into an account. It accepts an asset id, an amount, and a destination account id. The transaction must be signed with the asset's key(s).
- Transfer – The transfer action transfers tokens from one account to another. It accepts an asset id, an amount, a source account id, a destination account id, and an optional filter. The transaction must be signed with the source account's key(s).
- Retire – The retire action retires tokens from an account. It accepts an asset id, an amount, a source account id, and an optional filter. The transaction must be signed with the source account's key(s).
Data StructureLink to this section
Field DescriptionsLink to this section
| Field | Type | Description |
|---|---|---|
| id | string | Cryptographic, globally unique identifier of the transaction. |
| timestamp | string | Time (in RFC3339 format) that the transaction was committed to the ledger. |
| sequence number | integer | Absolute position in the ledger. |
| actions | array | A sequential list of actions affecting the ledger in the transaction. |
| tags | JSON object | User-specified key-value data about the transaction. |
Example objectLink to this section
{
id: "",
sequenceNumber: 1,
timestamp: "",
actions: [
{
type: "issue",
assetId: "",
amount: 1,
destinationAccountId: "",
tags: {}
},
{
type: "transfer",
assetId: "",
amount: 1,
sourceAccountId: "",
sourceAccountTags: {},
destinationAccountId: "",
destinationAccountTags: {},
tags: {}
},
{
type: "retire",
assetId: "",
amount: 1,
sourceAccountId: "",
sourceAccountTags: {},
tags: {}
}
],
tags: {}
}{
id: "",
sequenceNumber: 1,
timestamp: "",
actions: [
{
type: "issue",
assetId: "",
amount: 1,
destinationAccountId: "",
tags: {}
},
{
type: "transfer",
assetId: "",
amount: 1,
sourceAccountId: "",
sourceAccountTags: {},
destinationAccountId: "",
destinationAccountTags: {},
tags: {}
},
{
type: "retire",
assetId: "",
amount: 1,
sourceAccountId: "",
sourceAccountTags: {},
tags: {}
}
],
tags: {}
}{
id: "",
sequence_number: 1,
timestamp: "",
actions: [
{
type: "issue",
asset_id: "",
amount: 1,
destination_account_id: "",
tags: {},
},
{
type: "transfer",
asset_id: "",
amount: 1,
source_account_id: "",
source_account_tags: {},
destination_account_id: "",
destination_account_tags: {},
tags: {}
},
{
type: "retire",
asset_id: "",
amount: 1,
source_account_id: "",
source_account_tags: {},
tags: {}
}
],
tags: {}ExamplesLink to this section
IssueLink to this section
Issue USD to Alice.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Issue()
.setAssetId("usd")
.setAmount(100)
.setDestinationAccountId("alice")
).transact(ledger);ledger.transactions.transact(builder => {
builder.issue({
assetId: 'usd',
amount: 100,
destinationAccountId: 'alice'
})
}).then(tx => ...)tx = ledger.transactions.transact do |builder|
builder.issue(
asset_id: 'usd',
amount: 100,
destination_account_id: 'alice'
)
endTransferLink to this section
Transfer USD from Alice to Bob.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("usd")
.setAmount(10)
.setSourceAccountId("alice")
.setDestinationAccountId("bob")
).transact(ledger);ledger.transactions.transact(builder => {
builder.transfer({
assetId: 'usd',
amount: 10,
sourceAccountId: 'alice',
destinationAccountId: 'bob'
})
}).then(tx => ...)tx = ledger.transactions.transact do |builder|
builder.transfer(
asset_id: 'usd',
amount: 10,
source_account_id: 'alice',
destination_account_id: 'bob'
)
endRetireLink to this section
Retire USD from Bob.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Retire()
.setAssetId("usd")
.setAmount(5)
.setSourceAccountId("bob")
).transact(ledger);ledger.transactions.transact(builder => {
builder.retire({
assetId: 'usd',
amount: 5,
sourceAccountId: 'bob'
})
}).then(tx => ...)tx = ledger.transactions.transact do |builder|
builder.retire(
asset_id: 'usd',
amount: 5,
source_account_id: 'bob'
)
endMulti-asset transferLink to this section
Transfer USD and EUR from Alice to Bob.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("usd")
.setAmount(10)
.setSourceAccountId("alice")
.setDestinationAccountId("bob")
).addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("eur")
.setAmount(20)
.setSourceAccountId("alice")
.setDestinationAccountId("bob")
).transact(ledger);ledger.transactions.transact(builder => {
builder.transfer({
assetId: 'usd',
amount: 10,
sourceAccountId: 'alice',
destinationAccountId: 'bob'
})
builder.transfer({
assetId: 'eur',
amount: 20,
sourceAccountId: 'alice',
destinationAccountId: 'bob'
})
}).then(tx => ...)tx = ledger.transactions.transact do |builder|
builder.transfer(
asset_id: 'usd',
amount: 10,
source_account_id: 'alice',
destination_account_id: 'bob'
)
builder.transfer(
asset_id: 'eur',
amount: 20,
source_account_id: 'alice',
destination_account_id: 'bob'
)
endMulti-account transferLink to this section
Transfer USD from Alice to Bob and transfer EUR from Bob to Carol.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("usd")
.setAmount(10)
.setSourceAccountId("alice")
.setDestinationAccountId("bob")
).addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("eur")
.setAmount(20)
.setSourceAccountId("bob")
.setDestinationAccountId("carol")
).transact(ledger);ledger.transactions.transact(builder => {
builder.transfer({
assetId: 'usd',
amount: 10,
sourceAccountId: 'alice',
destinationAccountId: 'bob'
})
builder.transfer({
assetId: 'eur',
amount: 20,
sourceAccountId: 'bob',
destinationAccountId: 'carol'
})
}).then(tx => ...)tx = ledger.transactions.transact do |builder|
builder.transfer(
asset_id: 'usd',
amount: 10,
source_account_id: 'alice',
destination_account_id: 'bob'
)
builder.transfer(
asset_id: 'eur',
amount: 20,
source_account_id: 'bob',
destination_account_id: 'carol'
)
endAdd action tagsLink to this section
Add action tags to the issue action to denote the source of the deposit.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Issue()
.setAssetId("usd")
.setAmount(100)
.setDestinationAccountId("alice")
.addActionTagsField("source", "wire")
).transact(ledger);ledger.transactions.transact(builder => {
builder.issue({
assetId: 'usd',
amount: 100,
destinationAccountId: 'alice',
actionTags: {source: 'wire'}
})
}).then(tx => ...)tx = ledger.transactions.transact do |builder|
builder.issue(
asset_id: 'usd',
amount: 100,
destination_account_id: 'alice',
action_tags: {source: 'wire'}
)
endAdd transaction tagsLink to this section
Add transaction tags to record store location and invoice number.
Transaction tx = new Transaction.Builder()
.addAction(new Transaction.Builder.Action.Transfer()
.setAssetId("usd")
.setAmount(10)
.setSourceAccountId("alice")
.setDestinationAccountId("merchant")
)
.addAction(new Transaction.Builder.Action.Issue()
.setAssetId("merchantpoints")
.setAmount(10)
.setDestinationAccountId("alice")
)
.addTransactionTagsField("invoice", "123")
.addTransactionTagsField("storeId", "456")
.transact(ledger);ledger.transactions.transact(builder => {
builder.transfer({
assetId: 'usd',
amount: 10,
sourceAccountId: 'alice',
destinationAccountId: 'merchant'
})
builder.issue({
assetId: 'merchantpoints',
amount: 10,
destinationAccountId: 'alice'
})
builder.transactionTags = {
invoice: '123',
storeId: '456'
}
}).then(tx => ...)tx = ledger.transactions.transact do |builder|
builder.transfer(
asset_id: 'usd',
amount: 10,
source_account_id: 'alice',
destination_account_id: 'merchant'
)
builder.issue(
asset_id: 'merchantpoints',
amount: 10,
destination_account_id: 'alice'
)
builder.transaction_tags = {
invoice: '123',
store_id: '456',
}
endQuerying ExamplesLink to this section
By assetLink to this section
Query all transactions that transferred USD.
Transaction.ItemIterable txs = new Transaction.ListBuilder()
.setFilter("actions(type=$1 AND assetId=$2)")
.addFilterParameter("transfer")
.addFilterParameter("usd")
.getIterable(ledger);
for (Transaction tx : txs) {
System.out.println("transaction id: " + tx.id);
}let all = client.transactions.list(
filter: 'actions(type=$1 AND assetId=$2)',
filterParams: ['transfer', 'usd']
).all()
while (true) {
let { value: tx, done: done } = await all.next()
if (done) { break }
console.log(tx)
}ledger.transactions.list(
filter: 'actions(type=$1 AND asset_id=$2)',
filter_params: ['transfer', 'usd']
).each do |tx|
puts tx.to_json
endBy accountLink to this section
Query all transactions where Alice transferred any tokens to Bob
Transaction.ItemIterable txs = new Transaction.ListBuilder()
.setFilter("actions(sourceAccountId=$1 AND destinationAccountId=$2)")
.addFilterParameter("alice")
.addFilterParameter("bob")
.getIterable(ledger);
for (Transaction tx : txs) {
System.out.println("transaction id: " + tx.id);
}let all = ledger.transactions.list({
filter: 'actions(sourceAccountId=$1 AND destinationAccountId=$2)',
filterParams: ['alice', 'bob']
}).all()
while (true) {
let { value: tx, done: done } = await all.next()
if (done) { break }
console.log(tx)
}ledger.transactions.list(
filter: 'actions(source_account_id=$1 AND destination_account_id=$2)',
filter_params: ['alice', 'bob']
).each do |tx|
puts tx.to_json
endBy action tagsLink to this section
Query all issuances where deposit source was wire transfer.
Transaction.ItemIterable txs = new Transaction.ListBuilder()
.setFilter("actions(type=$1 AND tags.source=$2)")
.addFilterParameter("issue")
.addFilterParameter("wire")
.getIterable(ledger);
for (Transaction tx : txs) {
System.out.println("transaction id: " + tx.id);
}let all = ledger.transactions.list({
filter: 'actions(type=$1 AND tags.source=$2)',
filterParams: ['issue', 'wire']
}).all()
while (true) {
let { value: tx, done: done } = await all.next()
if (done) { break }
console.log(tx)
}ledger.transactions.list(
filter: 'actions(type=$1 AND tags.source=$2)',
filter_params: ['issue', 'wire']
).each do |tx|
puts tx.to_json
endBy asset tagLink to this section
Query all transactions where any type of currency was issued.
Transaction.ItemIterable txs = new Transaction.ListBuilder()
.setFilter("actions(type=$1 AND snapshot.assetTags.type=$2)")
.addFilterParameter("issue")
.addFilterParameter("currency")
.getIterable(ledger);
for (Transaction tx : txs) {
System.out.println("transaction id: " + tx.id);
}ledger.transactions.list({
filter: 'actions(type=$1 AND snapshot.assetTags.type=$2)',
filterParams: ['issue', 'currency']
}).all(tx => {
console.log(tx)
})ledger.transactions.list(
filter: 'actions(type=$1 AND snapshot.asset_tags.type=$2)',
filter_params: ['issue', 'currency']
).each do |tx|
puts tx.to_json
endBy transaction tagsLink to this section
Query all transactions for a store.
Transaction.ItemIterable txs = new Transaction.ListBuilder()
.setFilter("actions(snapshot.transactionTags.storeId=$1)")
.addFilterParameter("456")
.getIterable(ledger);
for (Transaction tx : txs) {
System.out.println(tx.tags);
System.out.println(tx.actions.get(0).snapshot.transactionTags);
}let all = ledger.transactions.list({
filter: 'actions(snapshot.transactionTags.storeId=$1)',
filterParams: ['456']
}).all()
while (true) {
let { value: tx, done: done } = await all.next()
if (done) { break }
console.log(tx.tags)
console.log(tx.actions[0].snapshot.transactionTags)
}ledger.transactions.list(
filter: 'actions(snapshot.transaction_tags.store_id=$1)',
filter_params: ['456']
).each do |tx|
puts tx.tags
puts tx.actions.first.snapshot.transaction_tags
end