Counterparty Development 101

Originally posted on Medium.com, I have updated the links and explaination below to reflect the latest information as of 2024. Understanding of how building on Bitcoin works is much more widespread now thanks to Ordinals, BRC-20, and Runes.

Counterparty is NOT a blockchain itself, but a software that uses the Bitcoin blockchain for its immutabiliy, signing features, and P2P network to embed and propogate protocol messages.

Nodes running the Counterparty software parse and validate state changes each block and achieve consensus by running software that interprets the embedded data deterministically.

Counterparty works in the same way Ordinals, BRC-20, or Runes do in that they all index the Bitcoin blockchain to compute state that is not natively validated by Bitcoin Core. Counterparty differs in that it is account-based like Ethereum or Solana rather than utxo-based.

Update: Optional utxo-binding is now supported as of version 10.4 to allow PSBTs.

Protocol Messages

There's more to it, but basically Counterparty nodes look for a CNTRPRTY prefix in OP_RETURN outputs and if it contains a valid protocol message the ledger is updated globally.

You can think of each Counterparty message as a standardized input to a hard-coded smart contract. This differentiates Counterparty from other platforms, like Ethereum, where users write their own smart contract code resulting in varying standards, like ERC-20 vs ERC-721.

Rather than users writing their own code and using different approaches for common tasks, Counterparty standardizes tasks as features: issue asset, place order, send transactions, etc.

Counterparty Core

Counterparty Core is the reference implementation of the protocol. It is not recommended to run alternate or out-dated versions of the code because consensus relies heavily on the state of the network being computed the same way by all nodes.

Counterparty API

Counterparty API is well-documented and the developers host a public node that can be used while getting yours running. This is the quickest way to get started.

One of the best features of the API, in my opinion, is the ?verbose=true option which will return more complete information and normalized quantities.

ServiceNetworkHostPortUserPass
CounterpartyMainnetapi.counterparty.io4000rpcrpc
CounterpartyTestnetapi.counterparty.io14000rpcrpc
BitcoinMainnetapi.counterparty.io8332rpcrpc
BitcoinTestnetapi.counterparty.io18332rpcrpc

Counterparty CLI

Counterparty CLI is less well-documented, but is an option if you are running a node.

Getting Started

The best resources are the code itself, the docs, and the API docs.

I would start by using the public APIs (see table above) as they may be all you need for things like checking an address balance or listing open dex orders.

Running your own node helps with decentralization and security, especially if you will be using your node for composing transations, but is not necessary. ($200-300/month cloud-hosted.)

Things to Know

Here's a few things to know about how Counterparty works...

Asset Divisibility

Assets can be divisible to 8 places or be non-divisible. All quantities are stored as integers in the database, so divisible assets need to be divided by 100000000.

  • ?verbose=true on API endpoints will normalized values for you.
  • Assets can be reset by owners to change the divisibility settings.

Asset Management

Assets are created and updated through Issuance messages. This includes: transferring ownership, updating description, reseting divisibility, issuing supply, and locking supply.

Asset Names

There are three types of names to be aware of:

  • Named Assets: 4-12 uppercase letters, cannot start with A.
  • Numeric Asets: Starts with A, followed by number between 2612 + 1 and 264 - 1
  • Subassets: Like a subdomain, 2-250 characters long. Allows: a-z, A-Z, 0-9, .-_@!.

Asset IDs

Mostly a backend thing, but it's worth knowing that every asset has an ID. In the case of named assets, the ID is derived from the characters in the string.

Numeric assets and subassets have random IDs within a range that's larger than the longest 12 character asset name to avoid collisions.

    # Convert the Base 26 string to an integer.
    n = 0
    for c in asset_name:
        n *= 26
        if c not in util.B26_DIGITS:
            raise exceptions.AssetNameError("invalid character:", c)
        digit = util.B26_DIGITS.index(c)
        n += digit
    asset_id = n

    # Divide that integer into Base 26 string.
    res = []
    n = asset_id
    while n > 0:
        n, r = divmod(n, 26)
        res.append(util.B26_DIGITS[r])
    asset_name = "".join(res[::-1])

Asset Longnames

The asset ID generation method limits asset names to 4-12 letters, so to work around that subassets are issued with two names: asset and asset_longname. Asset is a random numeric asset for the backend and asset_longname is the string to display to users.

Enhanced Asset Info

One optional feature of Counterparty is to put a JSON url as the asset description which allows for tx-free updates to the description and larger amounts of information.

There have been a lot of alternative standards proposed for how to associate media and content with an asset that are worth looking into: Stamps, Freeport, Ordinals inscriptions, etc.

Send Transactions

There are a few ways to send assets, to save fees you can perform a MPMA send (multi-send). Sends can have memos. And addresses can require a memo to receive assets.

Counterparty Dex

The Dex is a great way to trustlessly trade Counterparty assets it just requires that two orders match. The matching is done by Counterparty in the ledger, not onchain like a PSBT.

Order Expirations

Orders cannot be open for longer than 8064 blocks and will automatically close once they expire. They can be canceled earlier with a tx.

Dispenser Risks

Dispensers can be front-run in a way that risks losing funds. In most cases, there is no issue, but someone can broadcast a tx with a higher fee. Unlike with PSBTs, both txs will be valid.

  • Sending BTC without a Counterparty message will no longer trigger a dispense!

BTC Required

You need to pay bitcoin miners tx fees to create a Counterparty transaction. You can receive Counterparty without having BTC. And, unless you are using utxo-binding, you can drain an address of BTC without effecting Counterparty balances.

XCP Gas Fees

It costs XCP to issue a named asset, issue a dividend, or bind to a utxo.

Deprecated Code

There are some things like RPS and Bets which are basically deprecated.

Resources

CODE

DOCS

RESOURCES

COMMUNITY