Debt & asset finance
Model distinct rights and connect repayment, distributions and records.
← All implementation patternsIssue equipment-finance positions and reconcile repayments
Track positions in an equipment business separately when maturity or payment terms differ. Map BondToken classId to a category of terms and nonceId to an issuance series or maturity, then record each investor’s units.
Build a view connecting agreement terms, issuance series, investor holdings, payment schedules and actual receipts.
Architecture and responsibilities
Agreements and investors
Manage agreement originals, investor eligibility and payment schedules.
Application API / DBPositions and holdings
Track issuance and holdings for each classId and nonceId pair.
BondTokenHelperPayments and claims
Reconcile bank transfers or connect token-based claim processing as appropriate.
Bank integration / DebtManagerHelperOperations and reporting
Store holdings at the record date and payment outcomes for reporting.
Snapshots / Application ledger
Example data model
Map application records to the data managed by the chain or APIs. Field names and values below illustrate the application model for this architecture.
| Field and example | Stored in | Purpose and mapping |
|---|---|---|
agreementId / termsVersionFIN-001 / v1 | Application DB | Identify principal, dates, equipment and the agreement version. |
classId20 | Chain and DB mapping | Category of rights or terms, defined by the application. |
nonceId202709 | Chain and DB mapping | An issuance series within a class, distinct from signature replay-protection nonces. |
investor / unitsinvestorWallet / 10 | Chain | Holdings are integer units. The agreement defines the amount and currency per unit. |
paymentId / recordDatePAY-2027-09 / timestamp | Application DB | Identify the payment and record date, retaining the snapshot ID or block used. |
bankReference / transactionHashbank-ref / 0x… | Application DB | Record bank transfers and chain transactions as separate evidence. |
Processing flow
Map terms to a class and series
Map FIN-001 to classId 20 and its series to nonceId 202709. Create both identifiers and include only public metadata on chain.
createClass(classId, data) → createNonce(classId, nonceId, data)Issue after eligibility and funding checks
Check identity, agreement and funding in the application. Configure any required allowlist, then issue 10 units. Token issuance does not itself verify a bank deposit.
issue(investor, classId, nonceId, 10n)Fix holdings at the record date
Associate payment entitlement with holdings at the contractual record date, not the current balance at payment time. BondToken snapshots are created when called; they cannot retroactively create a snapshot for an arbitrary date.
snapshot() → balanceOfAt(holder, classId, nonceId, snapshotId)Connect the payment path
For bank transfers, reconcile amounts and receipts in the application ledger. With DebtManager, configure BondToken, principal and coupon tokens, permissions and schedules, then fund the coupon using payCoupon.
DebtManager: createTranche → addCouponSchedule → payCoupon → claimCouponReconcile redemption and records
Reconcile principal repayment with retiring units. BondToken redeem burns units; linking that action to a payout requires a payment workflow such as DebtManager.
BondToken.redeem / DebtManager.redeemAtMaturity
Before using the code
- Provide an initialized BondToken, an existing classId and nonceId, and a signer with MINTER_ROLE.
- Pass position units as bigint. Distinguish these units from ERC-20 amounts with decimals.
- Complete eligibility, agreement and funding checks, including any required allowlisting, before calling.
npm install --save-exact @hazbase/kit@0.9.0 ethers@6.16.0The TypeScript functions below are called from your application with the appropriate connections, permissions and data. Integrate the UI, persistence and recovery using the architecture above.
Allocate a position in a specific series
Use classId: 20n, nonceId: 202709n and units: 10n. agreementId is your application’s agreement ID, included in the result for ledger persistence.
import { BondTokenHelper } from '@hazbase/kit';
type Signer = Parameters<typeof BondTokenHelper.deploy>[1];
export async function allocateBond(input: {
agreementId: string;
tokenAddress: string;
classId: bigint;
nonceId: bigint;
investor: string;
units: bigint;
issuer: Signer;
}) {
// The class and nonce must already exist; issuer needs MINTER_ROLE.
if (input.units <= 0n) throw new Error('Units must be positive.');
const bond = BondTokenHelper.attach(input.tokenAddress, input.issuer);
const receipt = await bond.issue(
input.investor, input.classId, input.nonceId, input.units,
);
const balance = await bond.balanceOf(
input.investor, input.classId, input.nonceId,
);
return {
agreementId: input.agreementId,
classId: input.classId.toString(),
nonceId: input.nonceId.toString(),
investor: input.investor,
issuedUnits: input.units.toString(),
balance: balance.toString(),
transactionHash: receipt.hash,
};
}
Result and application integration
The investor’s balance for the class and nonce increases and a transaction hash is returned. This operation does not move money. Reconcile funding confirmation and issuance using the agreement ID.
Implementation considerations
Coupon record dates
DebtManager payCoupon uses a snapshot taken at execution. If entitlement belongs to holders at an earlier record date, use a workflow matching that record rather than distributing to current holders.
Currencies, decimals and rounding
Distinguish principal currency, coupon-token decimals and amount per unit. Align rounding and residual handling between the ledger and contract calculations.
Permissions and funding
DebtManager needs the necessary BondToken permissions plus payment-token balances and allowances. Keep insufficient-funding and overdue states distinct from paid.
Extending the architecture
Fixed routes versus holder distributions
Splitter routes funds to configured recipients and ratios; it does not enumerate token holders for dividends. Separate fixed counterparty splits from record-date holder distributions.
Working with Fund Ops
Fund Ops serves fund operators investing in RWAs, particularly asset finance. Map its scope to your own agreement and investor-management systems when integrating.