@hlf-core/coin-chaincode
This is the executing half of the token system — what happens in the ledger when a command arrives
from @hlf-core/coin. The package takes the models and commands from coin and turns
them into real state changes, with validation, events, and meaningful errors.
The central class is CoinManager, a descendant of EntityManagerImpl. It is
responsible both for the coins themselves (creation, reading, saving, deletion) and for operations
on balances: emit and emitHeld, burn and burnHeld, hold and unhold, nullify, and a
whole family of transfers — transfer, transferToHeld, transferFromHeld, transferFromToHeld.
Access to accounts goes through accountGet, accountSet, and accountList. Deleting a coin, by
the way, also removes all of its accounts by prefix — behind this stands a traversal, whose cost I
will mention below.
CoinAccountManager stands apart — the account manager, and it has one characteristic habit:
save deletes an account as soon as it turns out to be empty. That is, zero-balance accounts are
not stored in the state at all, and accountGet for an address with no funds returns not null
but a new empty account. This frees the calling code from extra existence checks.
On top of the managers lies CoinService — the business-logic facade. Its methods take a holder, a
DTO, and an event-dispatch flag; they validate the input, perform the operation, and dispatch the
event. It is usually this that the command handler works with.
const manager = new CoinManager(logger, stub);
const coin = manager.create('MYCOIN', 18, 'owner-uid');
await manager.emit(coin, {ownerUid: 'user-uid', id: 'OWNER'}, '1000');
await service.transfer(holder, {coinUid: coin.uid, object: {...}, target: {...}, value: '100'}, true);
:::warning On cost and responsibility
Here you should be careful. A single transfer performs several state operations, and
accountList and the deletion of a coin traverse all accounts in a single transaction — the cost
grows linearly and sooner or later runs into Fabric’s limits. And one more thing you must not
forget: the package does not check access rights, this is deliberately left to the calling code.
hlf-core provides the mechanics of tokens, while the decision of “who is allowed” remains with the
application logic.
:::