How to pay asset (token) dividend using the Counterparty API


#1

Let’s say I’m an asset owner (the person who issued the asset (token), or if the token was transferred, the last transferee) who wants to pay a dividend to all addresses that hold my token (except the owner’s address) and I want to use the API for that.

Using the API, I have to do the following:

  • Create a dividend transaction using the Counterparty API create_dividend method
  • Counterparty API then returns a raw transaction, which I need to sign using a bitcoin wallet
  • Having a signed transaction, send (broadcast) it to the bitcoin network

Create a dividend transaction

You should at least take a look at the Counterparty API documentation, because I won’t repeat that content here.
Basically the parameters are dividend_asset (what I am paying my dividend in), asset (for which token/asset I’m paying the dividend) and source (which must be the asset owner’s address.

Here’s an example from testnet:

  • I’m paying dividend for DIVTEST (which I own at mofv...) using BTC.
  • WARNING WARNING WARNING: you must keep in mind that in the API for Divisible (such as BTC) assets, the amount is in 100-millionth fractions (e.g.s satoshis), while for Indivisible assets (which can be quoted only in whole units), it is the absolute amount. This is different from Counterwallet and the CLI which takes care of that conversion for you.
  • Here I’m paying dividend in BTC (a Divisible asset) so quantity_per_unit of 100,000 means that the holders of DIVTEST will get 0.0001 BTC (100,000/100,000,000) for each unit of DIVTEST they possess. If I were to use an indivisible coin for dividend_asset here, then quantity_per_unit: 100 would mean each holder of DIVTEST would get 100 of dividend_asset.
  • Examples:
  • In this example: Donald owns 123.4 DIVTEST and I’m paying a dividend of 0.001 BTC per each. She’ll receive 123.4 * 0.001 BTC to her DIVTEST address
  • With the dividend paid in indivisible asset (e.g. a token called MOVIETICKET), maybe I’d pay 3 tokens per each unit of DIVTEST held, so Donald would receive 123.4 * 3 of 370.2 (actually 370, since MOVIETICKET isn’t divisible) of the dividend token.

{"jsonrpc": "2.0", "params": {"dividend_asset": "BTC", "asset": "DIVTEST", "quantity_per_unit": 100000, "source": "mofvU5ypG4CXBkgAZoUEcup9LkASr6V3eT"}, "method": "create_dividend", "id": 0}

Change the parameters and put it in a curl or a script such as Python. There are examples for other methods in here:
http://counterparty.io/docs/api/#example-implementations-for-json-rpc-api

Now run this script against a Counterparty API server (for testnet or mainnet), and it will return a raw unsigned transaction to you.

{
  "id": 0,
  "jsonrpc": "2.0",
  "result": "0100000001437fcd704435f894184effd2506093490ae1300c981c797b7777de7372348635020000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588acffffffff028c230000000000001976a9147a80c2e066cc7cf14f9db8c5331bc86acffcb1ec88acf1377200000000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588ac00000000"
}

If you don’t trust the server, or want to confirm what the hell is packed inside of this transaction, you can decode the transaction before you sign & send. An exercise for the reader, as they say.

Sign the Transaction

Most wallets, including Bitcoin Core, can sign transactions. Of course you need to have the address (and its private key) in the wallet, otherwise it won’t be able to sign it (if you want to import an address to Bitcoin Core wallet, seek help on importprivkey).

That’s why one cannot just copy and paste command examples below - they are based on the inputs from the JSON string above.

Example for Bitcoin (testnet):

bitcoin-cli -testnet signrawtransaction "0100000001437fcd704435f894184effd2506093490ae1300c981c797b7777de7372348635020000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588acffffffff028c230000000000001976a9147a80c2e066cc7cf14f9db8c5331bc86acffcb1ec88acf1377200000000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588ac00000000"

Send (Broadcast)

You can broadcast the signed transaction using the sendrawtransaction command. Its input is the output of the previous (signrawtransaction) command above.

Practice Before You Pay

As with all actions, there is no undo (at least not on the bitcoin blockchain). Practice on testnet as long as necessary.

There’s a similar tutorial for create_send and there’s a short intro about getting started with the API as well as these instructions specific to CoinDaddy’s public API server.

The technically easiest way to pay a dividend is to use a wallet that allows that. There are other ways (for example you can install Bitcoin Core addrindex version and counterparty-cli and complete this with one line command (counterparty-client dividend --source mofvU5ypG4CXBkgAZoUEcup9LkASr6V3eT --quantity-per-unit 0.001 --asset DIVTEST --dividend-asset XCP (again, unlike in the API, here quantity-per-unit 0.001 means 0.001 and 100,000 would mean 100K).

But if you don’t want to download 100+ GB of blockchain data to pay dividend and have no access to a wallet that lets you, with a bit of practice and care, that can be successfully accomplished within minutes using the API. In this how-to I used Bitcoin Core (i.e. I probably downloaded at least a pruned blockchain), but you can sign the transaction with any wallet - including “thin” or SPV wallets - and broadcast it trustlessly from most public servers or ask a friend with full node to do it for you.


Appendix: Complete Example on Testnet

Counterparty API: create_dividend

  • Dividend of 0.01 XCP per 1 DIVTEST held to all holders except the owner (mofvU5ypG4CXBkgAZoUEcup9LkASr6V3eT)
  • Using CoinDaddy’s public API server on testnet

JSON-RPC:

{"jsonrpc": "2.0", "params": {"dividend_asset": "XCP", "asset": "DIVTEST", "quantity_per_unit": 1000000, "source": "mofvU5ypG4CXBkgAZoUEcup9LkASr6V3eT"}

Complete curl command:

curl -X POST http://public.coindaddy.io:14000/api/ --user rpc:1234 -H 'Content-Type: application/json; charset=UTF-8' -H 'Accept: application/json, text/javascript' --data-binary '{"jsonrpc": "2.0", "params": {"dividend_asset": "XCP", "asset": "DIVTEST", "quantity_per_unit": 1000000, "source": "mofvU5ypG4CXBkgAZoUEcup9LkASr6V3eT"}, "method": "create_dividend", "id": 0}'

Raw unsigned transaction:

{
  "id": 0,
  "jsonrpc": "2.0",
  "result": "01000000018c4088a797ff8c2e71ebfccbb245ae2db47c6d0c8b7289cad688a113ec064ccb020000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588acffffffff020000000000000000266a242d21123c24d80e010fb00d9f5e7220f5b1e3088555d5119b44bf5e57cc258f6b1826d3c715267200000000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588ac00000000"
}

Bitcoin Wallet: Sign

Using bitcoin-cli on testnet:

signrawtransaction 01000000018c4088a797ff8c2e71ebfccbb245ae2db47c6d0c8b7289cad688a113ec064ccb020000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588acffffffff020000000000000000266a242d21123c24d80e010fb00d9f5e7220f5b1e3088555d5119b44bf5e57cc258f6b1826d3c715267200000000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588ac00000000

Response:


{
  "hex": "01000000018c4088a797ff8c2e71ebfccbb245ae2db47c6d0c8b7289cad688a113ec064ccb020000006b483045022100df99c95e53295c0b294b894a8cdea7aa6b80a082cfab7984adabfe72cf87546e02200ef98cfef882a8baa1cf144a730fc38a84167bb414928e96d850b927ef296d13012103d375cd4077faa8d95298b6e55825bac37ed73339585f84767527efacb25872dbffffffff020000000000000000266a242d21123c24d80e010fb00d9f5e7220f5b1e3088555d5119b44bf5e57cc258f6b1826d3c715267200000000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588ac00000000",
  "complete": true
}

Bitcoin Wallet: Send

Using bitcoin-cli on testnet:

sendrawtransaction "01000000018c4088a797ff8c2e71ebfccbb245ae2db47c6d0c8b7289cad688a113ec064ccb020000006b483045022100df99c95e53295c0b294b894a8cdea7aa6b80a082cfab7984adabfe72cf87546e02200ef98cfef882a8baa1cf144a730fc38a84167bb414928e96d850b927ef296d13012103d375cd4077faa8d95298b6e55825bac37ed73339585f84767527efacb25872dbffffffff020000000000000000266a242d21123c24d80e010fb00d9f5e7220f5b1e3088555d5119b44bf5e57cc258f6b1826d3c715267200000000001976a9145973398cc2f7852166c1d3770e5d9754f2f9509588ac00000000"

Response (the hash of the transaction we sent to the network):

67831c7d055e897db9510adbc7c922f003b5cf676ba60c2f2591ca42440e9f38

Verify

Search for your address or the transaction hash. Use the mainnet URL for mainnet (doh!).

2017-01-19-T13:51:59+0800 [INFO] Dividend: mofvU5ypG4CXBkgAZoUEcup9LkASr6V3eT paid 0.01 XCP per unit of DIVTEST (67831c7d055e897db9510adbc7c922f003b5cf676ba60c2f2591ca42440e9f38) [valid]

https://testnet.counterpartychain.io/transaction/67831c7d055e897db9510adbc7c922f003b5cf676ba60c2f2591ca42440e9f38

Edit: interestingly there’s something wrong with the explorer so the above transaction is not valid.
However you could use the API or CLI to check the transaction:

$ counterparty-client --testnet getrows --table dividends --filter 'source' '=' 'mofvU5ypG4CXBkgAZoUEcup9LkASr6V3eT'