Showcase

Example financial transactions using the Chain Protocol

Asset Issuance

Alice wishes to transact on a blockchain network where TrustCo issues digital USD. She connects to the network and generates a one-time-use payment address.

Alice then wires $1,000 to TrustCo's bank account. The wire-transfer instructions include Alice’s blockchain payment address.

TrustCo receives the wire transfer and holds it in trust. It simultaneously constructs a transaction whose input is the issuance of the “TrustCo USD” asset type, and whose output is 1,000 units of that asset paid to Alice’s address. The wire-transfer id is embedded as transaction metadata, for an immutable record of how this issuance was funded.

TrustCo adds its digital signature to the input (as required by the definition of the “TrustCo USD” asset type to permit issuance) and submits this transaction to the block generator. A moment later it appears in the blockchain. Alice now has $1,000 in newly issued TrustCo digital USD to use in blockchain transactions.

# Alice will receive $1000 from TrustCo. To do so, she
# generates a one-time-use address and includes it as
# instructions in the wire transfer to TrustCo.
alice_address = chain.create_address(alice_account_id)

# After receiving Alice's wire transfer, TrustCo issues
# new units of its digital dollar asset to Alice's
# one-time-use address. It also includes the wire
# transfer ID as transaction metadata, providing an
# immutable audit trail
tx = chain.build_transaction(
  inputs: [{
    type: 'issue',
    asset_id: trustco_usd_asset_id
  }],
  outputs: [{
    asset_id: trustco_usd_asset_id,
    amount: 1000,
    address: alice_address
  }],
  metadata: {
    wire_tx_id: incoming_wire_transfer_id
  }.to_hex
)

# TrusCo then signs the transaction with its private key.
chain.sign_transaction(tx)

# Finally, TrustCo submits the transaction to the Chain API.
chain.submit_transaction(tx)

Simple Payment

Alice wants to send a $55 payment to Bob.

Alice asks Bob for his payment address. Bob generates a one-time-use address and gives it to Alice.

Alice now needs at least $55 that she can spend, to be used as input to her transaction. She identifies three unspent outputs of transactions on the blockchain - one for $10, one for $20, and one for $30 - that were paid to her (i.e., to addresses for her account).

The sum of these unspent outputs is $60, which is $5 more than Alice needs. But blockchain outputs cannot be partially consumed. So Alice’s transaction needs two outputs: $55 for Bob, and $5 for Alice as “change.” Alice generates a one-time-use payment address for the change output.

Alice adds her digital signature to each of the three inputs to prove she’s allowed to spend them.

Alice submits the transaction to the block generator. A moment later it appears in the blockchain, at which point the payment is final and settled. Bob may now spend his $55 by constructing a new transaction of his own.

# Bob will receive $55 from Alice. To do so, he generates a
# one-time-use address and sends it to Alice.
bob_address = chain.create_address(bob_account_id)

# Alice uses the Chain API to build a transaction,
# sending $55 from her account to Bob's one-time-use address.
tx = chain.build_transaction(
  inputs: [{
    asset_id: usd_asset_id,
    account_id: alice_account_id,
    amount: 55
  }],
  outputs: [{
    asset_id: usd_asset_id,
    address: bob_address,
    amount: 55
  }]
)

# Alice then signs the transaction with her private key.
chain.sign_transaction(tx)

# Finally, Alice submits the transaction to the Chain API.
chain.submit_transaction(tx)

Bilateral Trade

Alice wishes to buy 100 shares of ACME. Bob agrees to sell them to Alice for $10,600.

They collaborate to form a transaction with the following inputs:

  1. A $5,000 payment previously made to Alice
  2. A $6,000 payment previously made to Alice
  3. The 100 shares of ACME, previously paid to Bob

and the following outputs:

  1. 100 shares of ACME paid to Alice’s address
  2. $10,600 paid to Bob’s address
  3. $400 in change paid to Alice’s address

Alice adds her signature to inputs 1 and 2. Bob adds his signature to input 3.

The transaction is now ready for inclusion on the blockchain. As soon as it appears there, Alice owns the ACME shares and Bob has received his payment for them at the same moment: simultaneous delivery against payment.

# Alice uses the Chain API to build a partial transaction,
# withdrawing $10,600 from her account and depositing 100 ACME
# shares into her account.
partial_tx = chain.build_transaction(
  inputs: [{
    asset_id: usd_asset_id,
    account_id: alice_account_id,
    amount: 10600
  }],
  outputs: [{
    asset_id: acme_asset_id,
    account_id: alice_account_id,
    amount: 100
  }]
)

# Without signing the transaction, Alice serializes it and
# sends it to Bob. Bob fills out the remaining inputs and
# outputs, withdrawing 100 ACME shares from his account and
# depositing $10,600 into his account:
full_tx = chain.build_transaction(
  previous_transaction: partial_tx_from_alice,
  inputs: [{
    asset_id: usd_asset_id,
    account_id: alice_account_id,
    amount: 10600
  }],
  outputs: [{
    asset_id: acme_asset_id,
    account_id: alice_account_id,
    amount: 100
  }],
)

# Bob signs the transaction.
half_signed_tx = chain.sign_transaction(full_tx)

# Alice still needs to sign the transaction, so Bob sends it
# back to Alice. After inspecting the transaction and verifying
# that Bob has satisfied their agreement, Alice signs the
# transaction and submits it to the Chain API.
signed_tx = chain.sign_transaction(half_signed_tx_from_bob)
chain.submit_transaction(signed_tx)

Orderbook

Alice is a foreign-exchange trader with 10,000 euros to sell. She is willing to sell them for either 1.13 USD apiece or 0.79 GBP apiece, and doesn’t care whether they sell all at once or in pieces.

Alice constructs an offer: a transaction with one input (Alice’s 10,000 euros) and one output (those same 10,000 euros). The output is secured with a contract that defines two different ways to redeem it: purchase or cancellation.

The contract describes “cancellation” as follows: the redeeming transaction must pay the entire balance to Alice’s address (which is supplied as part of the contract).

It describes “purchase” as follows:

  • the redeeming transaction may consume (may pay to any address) any number of euros up to the total in the transaction
  • it must pay either 1.13 USD or 0.79 GBP to Alice’s address for each euro consumed
  • it must pay any unconsumed euros into the identical contract

Alice adds her digital signature to the input of her offer (to prove she can spend the 10,000 euros) and submits her transaction for inclusion on the blockchain.

Who owns those euros now? In one sense, no one does; they are paid to a contract that isn’t any particular account’s address. In another sense, everyone does: anyone who’s able to pay Alice her price is allowed to claim them. In a third sense, Alice still does, because she retains the ability to cancel the contract and repay the euros to herself.

Bob sees Alice’s offer on the blockchain and wishes to purchase 500 euros. He assembles a purchase transaction with these inputs:

  1. $600 previously paid to Bob
  2. Alice’s 10,000 EUR offer

and these outputs:

  1. 500 EUR paid to Bob
  2. 565 USD paid to Alice
  3. 9,500 EUR paid to the same contract as in Alice’s offer
  4. $35 change paid to Bob

He adds his signature to input 1 to prove he can spend the $600. Note that no signature is needed on input 2; that’s not part of the contract terms.

Bob submits his transaction for inclusion on the blockchain.

At about the same moment, another buyer, Carol, submits a similar transaction! Bob and Carol are in a race to consume Alice’s 10,000 EUR offer. Since no transaction output can be spent twice, the process of block generation will select one transaction and reject the other.

Bob’s transaction wins; it appears on the blockchain. Carol’s transaction is rejected as a “double-spend.” Carol may now retry her transaction, consuming the new 9,500 EUR offer instead of the (no longer available) 10,000 EUR offer.

# Alice pays 10,000 euros into a contract asking
# for 1.13 USD or 0.79 GBP in return.
tx = chain.build_transaction(
  inputs: [{
    account_id: alice_account_id,
    asset_id:   euro_asset_id,
    amount:     10000
  }],
  outputs: [{
    type:       'orderbook',
    asset_id:   euro_asset_id,
    amount:     10000,
    account_id: alice_account_id,
    orderbook_prices: [{
      asset_id:       usd_asset_id,
      offer_amount:   100,
      payment_amount: 113
    },
    {
      asset_id:       gpb_asset_id,
      offer_amount:   100,
      payment_amount: 79
    }]
  }]
)

chain.sign_transaction(tx)
chain.submit_transaction(tx)

# Bob, looking to exchange his USD for euros, makes an
# API call to discover orderbook contracts on the blockchain
# that offer euros.
results = chain.orderbook_find_open_orders(
  status: 'open',
  offered_asset_ids: [euro_asset_id],
  payment_asset_ids:[usd_asset_id]
)

# Bob discovers Alice's contract, finds the price
# acceptable, and submits a transaction that partially consumes
# the euros paid into Alice's contract.
chain.build_transaction(
  inputs: [{
    asset_id:   usd_asset_id,
    amount:     565,
    account_id: bob_account_id,
  },
  {
    type:             'orderbook-redeem',
    transaction_hash: alice_contract['hash'],
    index:            alice_contract['index'],
    payment_asset_id: usd_asset_id,
    payment_amount:   565,
    amount:           500,
  }],
  outputs: [{
    asset_id: usd_asset_id,
    amount:   565,
    address:  alice_contract['script']
  },
  {
    asset_id:   euro_asset_id,
    amount:     500,
    account_id: bob_account_id
  }]
)

chain.sign_transaction(tx)
chain.submit_transaction(tx)

Collateralized Loan

Alice needs a short-term loan of $100,000 and has ACME shares to offer as collateral. Bob is willing to lend the money to Alice for 30 days at 1%, using 950 shares of ACME as collateral.

They construct a transaction on April 20th with these inputs:

  1. Alice’s 950 ACME shares
  2. Bob’s $100,000

and these outputs:

  1. $100,000 paid to Alice
  2. 950 ACME shares paid to a loan contract

The loan contract describes how the ACME shares may be redeemed: via either repayment or default. “Repayment,” according to the contract, is any transaction that:

  • is on or before May 20th
  • pays $101,000 to Bob
  • pays 950 ACME shares to Alice

“Default” is a transaction that:

  • is after May 20th
  • pays 950 ACME shares to Bob

No other transfer of the 950 ACME shares is valid.

Alice signs input 1 of the loan transaction and Bob signs input 2. They submit the transaction for inclusion on the blockchain. Now Alice has $100,000 to use however she likes, while her collateral is locked up in the contract. On May 18th she repays Bob, and recovers her collateral, with a new transaction whose inputs are:

  1. $101,000 of Alice’s money
  2. The 950 ACME shares in the loan contract

and whose outputs are:

  1. $101,000 paid to Bob
  2. 950 ACME shares paid to Alice
# First, Alice builds a partial transaction, withdrawing
# 950 ACME shares from her account and depositing $100,000
# into her account.
partial_tx = chain.build_transaction(
  inputs: [{
    asset_id: acme_asset_id,
    account_id: alice_account_id,
    amount: 950
  }],
  outputs: [{
    asset_id: usd_asset_id,
    account_id: alice_account_id,
    amount: 100000
  }]
)

# Alice also generates a one-time-use address in her account,
# which will be designated in the loan contract as the
# destination of her ACME shares if she can repay Bob in time.
alice_address = chain.create_address(alice_account_id)

# Alice and Bob agree to terms, so Alice sends Bob the
# partial transaction and her one-time-use address for
# returning her collateral. Bob fills out the rest of the
# transaction, depositing his $100,000, and paying 950 ACME
# shares into a contract that fit Alice and Bob's arrangement.
full_tx = chain.build_transaction(
  previous_transaction: partial_tx_from_alice,
  inputs: [{
    asset_id: usd_asset_id,
    account_id: bob_account_id,
    amount: 100000
  }],
  outputs: [{
    type: 'collateral-loan',

    asset_id: acme_asset_id,
    amount: 950,

    default_time: "2016-05-20T00:00Z",
    debtor_address: alice_redeem_address,
    repayment_asset_id: usd_asset_id,
    repayment_amount: 101000,
    creditor_account_id: bob_account_id,
  }],
)

# Bob then signs the transaction, and sends the half-signed
# transaction back to Alice to inspect and sign.
half_signed_tx = chain.sign_transaction(tx)

# Alice receives Bob's half-signed transaction, and after
# verifying that the contract parameters match the terms she
# and Bob agreed to, signs and submits the transaction to the
# Chain API.
signed_tx = chain.sign_transaction(half_signed_tx_from_bob)
chain.submit_transaction(signed_tx)

Auction

This example involves multiple different contracts coordinating with each other.

Alice has 100 shares of ACME that she would like to sell for the best price she can get, but not less than $10,000. She creates an auction: a transaction that pays those 100 shares of ACME into an auction-asset contract. This contract specifies a deadline, the asset type for bids (e.g., dollars), a minimum bid ($10,000 in this case), a payment address for the highest bidder (no one yet), and three ways to redeem the shares: Cancellation, for when Alice changes her mind and pays the ACME shares back to herself before any bids have been made; Claiming, for when the auction is over and the highest bidder wants to claim the shares; and Bidding, for when the auction is in progress and someone wants to offer to buy the shares.

Bob wants to bid $10,000 for Alice’s shares. He constructs a new transaction with two inputs:

  1. $10,000 of his money
  2. Alice’s auction-asset contract (controlling 100 ACME shares), triggering the Bidding clause

and two outputs:

  1. 100 ACME shares paid to a new copy of the auction-asset contract
  2. $10,000 paid to an auction-bid contract.

The “Bidding” clause of Alice’s auction-asset contract places constraints on the new contracts in the outputs of Bob’s transaction to ensure that e.g. the deadline remains the same, the new minimum bid is $10,001, etc.

The auction-bid contract, containing Bob’s $10,000, has two ways it can be redeemed: Outbidding, when a new bidder offers a higher amount and Bob’s bid must be returned to him; and Payment, when the auction has ended and the bid must be paid to Alice in order to claim the ACME shares.

Carol wants to bid $10,100 for Alice’s shares. She constructs a new transaction with three inputs:

  1. $10,100 of her money
  2. The new copy of Alice’s auction-asset contract created by Bob, triggering the Bidding clause
  3. Bob’s auction-bid contract, triggering the Outbidding clause

and three outputs:

  1. $10,000 paid to Bob
  2. 100 ACME shares paid to a newer copy of Alice’s auction-asset contract
  3. $10,100 paid to a new auction-bid contract

The deadline for the auction arrives with no further bids. Carol creates one more transaction in order to claim the ACME shares and pay Alice. The inputs are:

  1. The newer copy of Alice’s auction-asset contract, triggering the Claiming clause
  2. The new auction-bid contract, triggering the Payment clause

and the outputs are:

  1. 100 ACME shares paid to Carol
  2. $10,100 paid to Alice.

Note that Alice could have initiated the same transaction if she didn’t want to wait for Carol to do it; in fact anyone could have, since no signatures are necessary! Both inputs are Smart Contracts, whose only requirements are that the bid amount goes to the specified payment address, and that the auctioned asset goes to the high bidder.

At every step, the transactions themselves enforce the rules of the auction. Any transaction that fails to follow those rules is invalid and so cannot be included on the blockchain. If Carol had tried to outbid Bob with $9,100 instead of with $10,100, for instance, the “Outbidding” clause of the auction-bid Smart Contract, which tests that the new bid is greater than the old one, would have failed, causing chain.submit_transaction to return an “invalid transaction” error.

# Alice initiates an auction
alice_address = chain.create_address(alice_account_id)
auction_tx = chain.build_transaction(
  inputs: [{
    asset_id: acme_asset_id,
    account_id: alice_account_id,
    amount: 100
    }],
  outputs: [{
    type: 'auction-asset',
    asset_id: acme_asset_id,
    amount: 100,
    payment_address: alice_address,
    bid_asset_id: usd_asset_id,
    minimum_bid: 10000,
    deadline: '2016-05-01 10:00:00'
  }])
chain.sign_transaction(auction_tx)
chain.submit_transaction(auction_tx)

# Bob places an opening bid
bob_address = chain.create_address(bob_account_id)
opening_bid_tx = chain.build_transaction(
  inputs: [{
    asset_id: usd_asset_id,
    amount: 10000,
    account_id: bob_account_id
  },
  {
    type: 'auction-bidding',
    transaction_hash: alice_auction['hash'],
    index: alice_auction['index'],
    bidder_address: bob_address,
    bid_amount: 10000
  }],
  outputs: [{
    type: 'auction-asset',
    asset_id: acme_asset_id,
    amount: 100,
    payment_address: alice_address,
    bid_asset_id: usd_asset_id,
    bid_amount: 10000,
    minimum_bid: 10001,
    deadline: '2016-05-01 10:00:00',
    high_bidder_address: bob_address
  },
  {
    type: 'auction-bid',
    asset_id: usd_asset_id,
    amount: 10000,
    bidder_address: bob_address,
    deadline: '2016-05-01 10:00:00'
  }])
chain.sign_transaction(opening_bid_tx)
chain.submit_transaction(opening_bid_tx)

# Carol outbids Bob
carol_address = chain.create_address(carol_account_id)
outbid_tx = chain.build_transaction(
  inputs: [{
    asset_id: usd_asset_id,
    amount: 10100,
    account_id: carol_account_id
  },
  {
    type: 'auction-bidding',
    transaction_hash: bob_tx_asset['hash'],
    index: bob_tx_asset['index'],
    bidder_address: carol_address,
    bid_amount: 10100
  },
  {
    type: 'auction-outbid',
    transaction_hash: bob_tx_bid['hash'],
    index: bob_tx_bid['index']
  }],
  outputs: [{
    asset_id: usd_asset_id,
    amount: 10000,
    address: bob_tx_bid['bidder_address']
  },
  {
    type: 'auction-asset',
    asset_id: acme_asset_id,
    amount: 100,
    payment_address: alice_address,
    bid_asset_id: usd_asset_id,
    bid_amount: 10100,
    minimum_bid: 10101,
    deadline: '2016-05-01 10:00:00',
    high_bidder_address: carol_address
  },
  {
    type: 'auction-bid',
    asset_id: usd_asset_id,
    amount: 10100,
    bidder_address: carol_address,
    deadline: '2016-05-01 10:00:00'
  }])
chain.sign_transaction(outbid_tx)
chain.submit_transaction(outbid_tx)

# The deadline passes.
# Carol claims the ACME shares and releases payment to Alice.
claim_tx = chain.build_transaction(
  inputs: [{
    type: 'auction-claiming',
    transaction_hash: carol_tx_asset['hash'],
    index: carol_tx_asset['index']
  },
  {
    type: 'auction-payment',
    transaction_hash: carol_tx_bid['hash'],
    index: carol_tx_bid['index']
  }],
  outputs: [{
    asset_id: acme_asset_id,
    amount: 100,
    address: carol_tx_bid['bidder_address']
  },
  {
    asset_id: usd_asset_id,
    amount: 10100,
    address: carol_tx_asset['payment_address']
  }])

# No signatures needed on this transaction!
chain.submit_transaction(claim_tx)

Ready to start building with blockchain?

Get in touch to schedule a Chain Platform demo.

[email protected]