Ledger objects

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

FieldTypeDescription
idstringCryptographic, globally unique identifier of the transaction.
timestampstringTime (in RFC3339 format) that the transaction was committed to the ledger.
sequence numberintegerAbsolute position in the ledger.
actionsarrayA sequential list of actions affecting the ledger in the transaction.
tagsJSON objectUser-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'
  )
end

TransferLink 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'
  )
end

RetireLink 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'
  )
end

Multi-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'
  )
end

Multi-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'
  )
end

Add 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'}
  )
end

Add 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',
  }
end

Querying 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
end

By 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
end

By 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
end

By 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
end

By 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