Skip to main content

@hlf-core/coin

hlf-core splits working with tokens into two packages, and this is the same split as everywhere else: the vocabulary separately, the execution separately. @hlf-core/coin, which is what we are talking about here, is the platform-neutral models, commands, and events, without any tie to Fabric. They can be used outside the blockchain too, while execution on the ledger side is handled by @hlf-core/coin-chaincode.

The primary model is Coin (a token with a balance field), and the owner’s state is described by CoinAccount. An account has two states: inUse — what can be disposed of — and held — what is locked under some operation, and the operations add, remove, hold, unhold, nullify move funds between them. All amounts are stored as strings, and this is fundamental: financial precision cannot be entrusted to floating-point numbers, otherwise a discrepancy inevitably accumulates on rounding. CoinBalance extends the account with auditing — emitted, burned, total — so that a full accounting of what has been issued and burned is visible through it.

The account address deserves a word of its own — CoinAccountObject of the form {ownerUid, id}. It is an object, not two separate strings, and that is done deliberately: a single owner can have several accounts for a single coin (say, OWNER and PAYOUT), and in a transfer it is important to us that the parties cannot be accidentally swapped.

The operations are described by commands inheriting HlfTransportCommandAsync — CoinEmitCommand, CoinBurnCommand, CoinTransferCommand, CoinHoldCommand, CoinUnholdCommand, CoinNullifyCommand, and a pair of readonly commands, CoinGetCommand and CoinBalanceGetCommand. Each action has its own event — CoinEmittedEvent, CoinTransferredEvent (where the recipient is named target, not to) and so on.

const transfer = new CoinTransferCommand({
object: {ownerUid: 'alice', id: 'OWNER'}, // sender
target: {ownerUid: 'bob', id: 'OWNER'}, // recipient
value: '500',
coinUid: 'coin_issuer_8_MYTOKEN',
});

The account keys are built by CoinAccountUtil on top of StateKey, and the order of the parts in the key is chosen here so that all of an owner’s accounts for a coin can be enumerated with a single range query.