Buy transactions

Ok, so we’ve looked at how to get hold of some swapbill, either through a backed exchange, or by burning host coin.

SwapBill is intended to serve a fairly specific purpose, however, (for facilitating decentralised cross currency exchange, specifically), and when you’ve finished using your swapbill you will most likely want to exchange this back for host currency.

You can do this with the buy offer transaction (buying host coin with swapbill). The process for this is similar to backed sell offers, but even more straightforward, because there’s no need to select a backer in this case.

Checking sell offers

Starting with a buyer, who has 1.5 swapbill they want to exchange for host coin:

~/git/swapbill $ python Client.py get_balance
...
Operation successful
balance : 1.5

Let’s check the current list of sell offers:

~/git/swapbill $ python Client.py get_sell_offers
...
Operation successful
exchange rate : 0.91
    host coin offered : 0.9
    deposit : 0.06181319
    swapbill equivalent : 0.98901099
    mine : False
exchange rate : 0.88
    host coin offered : 1
    deposit : 0.07102273
    swapbill equivalent : 1.13636364
    mine : False

Matching the top offer

The best rate here is 0.91 host coin per swapbill. Let’s assume we’re ok with exchanging at anything down to 0.9 host coin per swapbill. So, we’ll try and match that top offer first:

~/git/swapbill $ python Client.py buy_offer --swapBillOffered 0.98901099 --blocksUntilExpiry 1 --exchangeRate 0.91
...
attempting to send BuyOffer, hostCoinBuy output address=mijmaJQvuLdpbXNqx5MRz6qnTUTZALK2Qy, exchangeRate=910000000, maxBlock=279588, receivingAddress=myxz78GA8zBmAbwtqN6qEhEwgE2f1tBjEY, swapBillOffered=98901099
Operation successful
transaction id : 34be36f0bdb7f165838bb1210f0eaf0aa8a91416a6f4c38e0b3431088ebbdf5f

This is similar to the sell offer we posted in the previous example, but there a couple of other points to note here.

First of all, note that we’ve specified a value for blocksUntilExpiry. This is because we just want to match the top existing offer, but there is a possibility that someone else matches that offer first. So we’ve set our transaction to expire in the next block, if it doesn’t match, so that we can then go on and use the swapbill in another offer without having to wait too long.

A second point to note is that the decimal fractions displayed by queries such as get_sell_offers, and passed in for transaction parameters are actually exact values, and not subject to approximation errors during parsing or display. So we can copy the exact text printed for the top sell offer and expect our offer to match this exactly. (This is a subtle point, but nevertheless quite an important implementation detail!)

No other offers come in before our buy offer, then, and this matches the top offer.

The amount offered is debited from our balance:

~/git/swapbill $ python Client.py get_balance
...
Operation successful
balance : 0.51098901

And we can see that the top sell offer has been removed:

~/git/swapbill $ python Client.py get_sell_offers
...
in memory: BuyOffer
 - 1.5 swapbill output consumed
 - 0.51098901 swapbill output added
In memory state updated to end of block 279587
Operation successful
exchange rate : 0.88
    deposit : 0.07102273
    swapbill equivalent : 1.13636364
    host coin offered : 1
    mine : False

Posting a speculative offer

We decide to post the remaining funds again, in another buy offer:

~/git/swapbill $ python Client.py --buy_offer --swapBillOffered 0.51098901 --exchangeRate 0.9
...
attempting to send BuyOffer, hostCoinBuy output address=mo8ACE96HGVUfrthq4u1g4nZCZTB94jEuS, exchangeRate=900000000, maxBlock=279596, receivingAddress=mzaY6QqQxYtcCC1vJc19nxBet9f6frzsRs, swapBillOffered=51098901
Operation successful
transaction id : 98998855e17ffec7a63e9342981d4fad8f5acc97f4ae51dd27915479ac20863e

Again, note that we can post the exact current balance value, and the client will then include the whole balance in the offer. Remember that the SwapBill protocol includes a minimum balance constraint, so we’re not permitted to submit transactions that would leave a very small amount of change. (If so, the client will report an error, and refuse to submit the transaction. Try spending very slightly less than your current balance, to see this in practice.)

In this case we didn’t specify blocksUntilExpiry. For buy transactions this currently defaults to 8. For backed sell transactions there is no expiry and for unbacked sells the default is just 2 blocks (because unbacked sells need to be followed up with exchange completion for each matching buyer).

This offer doesn’t match any existing sell offer, and is therefore added to the existing order book as an outstanding offer:

~/git/swapbill $ python Client.py get_buy_offers
...
Operation successful
exchange rate : 0.9
    swapbill offered : 0.51098901
    host coin equivalent : 0.45989011
    mine : True
exchange rate : 0.92
    swapbill offered : 0.92211766
    host coin equivalent : 0.84834825
    mine : False
exchange rate : 0.95
    swapbill offered : 2
    host coin equivalent : 1.9
    mine : False

If no-one posts a matching offer before the end of the expiry period, the swapbill amount offered will be returned to our active balance. But, as it is, a couple of sell offers come along in the next few blocks, and match the outstanding offer remainder.

We can see the SellOffer transactions come up in the sync output, and we can also see that the buy offer has been matched and is no longer present:

~/git/swapbill $ python Client.py get_buy_offers
Loaded cached state data successfully
State update starting from block 279570
...
in memory: SellOffer
 - trade offer updated
in memory: SellOffer
 - trade offer updated
In memory state updated to end of block 279591
Operation successful
exchange rate : 0.92
    swapbill offered : 0.92211766
    host coin equivalent : 0.84834825
    mine : False
exchange rate : 0.95
    swapbill offered : 2
    host coin equivalent : 1.9
    mine : False

It turns out that our second offer was actually matched by two smaller sell offers. And so at this point, we now have three trade offer matches outstanding, waiting for final host coin payments from the seller to complete.

We can see this with the get_pending_exchanges query:

~/git/swapbill $ python Client.py get_pending_exchanges
...
Operation successful
pending exchange index : 1
    swap bill paid by buyer : 0.98901099
    I am buyer (and waiting for payment) : True
    deposit paid by seller : 0.06181319
    I am seller (and need to complete) : False
    expires on block : 279602
    blocks until expiry : 12
    confirmations : 4
    outstanding host coin payment amount : 0.9
pending exchange index : 2
    swap bill paid by buyer : 0.33333333
    I am buyer (and waiting for payment) : True
    deposit paid by seller : 0.02083334
    I am seller (and need to complete) : False
    expires on block : 279605
    blocks until expiry : 15
    confirmations : 1
    outstanding host coin payment amount : 0.3
pending exchange index : 3
    swap bill paid by buyer : 0.17765568
    I am buyer (and waiting for payment) : True
    deposit paid by seller : 0.01110348
    I am seller (and need to complete) : False
    expires on block : 279606
    blocks until expiry : 15
    confirmations : 1
    outstanding host coin payment amount : 0.15989011

As a host coin buyer, we don’t have to take any action here. Either the seller pays the required host coin amount and completes the exchange, or we are refunded our swapbill plus some deposit paid by the seller as part of their sell offer.

A bit later we can see that one of the exchanges has been completed:

~/git/swapbill $ python Client.py get_pending_exchanges
...
Operation successful
pending exchange index : 1
    blocks until expiry : 11
    confirmations : 5
    I am seller (and need to complete) : True
    I am buyer (and waiting for payment) : False
    expires on block : 279602
    deposit paid by seller : 0.06181319
    swap bill paid by buyer : 0.98901099
    outstanding host coin payment amount : 0.9
pending exchange index : 2
    blocks until expiry : 14
    confirmations : 2
    I am seller (and need to complete) : True
    I am buyer (and waiting for payment) : False
    expires on block : 279605
    deposit paid by seller : 0.02083334
    swap bill paid by buyer : 0.33333333
    outstanding host coin payment amount : 0.3

You can check your host coin balance separately, with bitcoin/src/bitcoin-cli getbalance, to confirm that you’ve received the host coin amount for this exchange. (The SwapBill client verifies that the payment transaction is received, but does not track your host coin balance.)