Skip to content

Refactor: Host shared transfer status and amount vocabulary - #432

Open
sephynox wants to merge 2 commits into
mainfrom
refactor/move-types
Open

Refactor: Host shared transfer status and amount vocabulary#432
sephynox wants to merge 2 commits into
mainfrom
refactor/move-types

Conversation

@sephynox

@sephynox sephynox commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Downstream consumers (asset-movement-anchor-sdk, sentinel, and the planned sentinel-client) need one shared transfer vocabulary, and anchor is the only common lower layer that keeps the package graph acyclic. This change hosts the ISO 20022 transfer state machine and the self-describing amount value object.


Note

Medium Risk
New fund-precision and state-transition rules will govern future transfer flows; incorrect adoption could affect money handling, but this PR only adds library code and tests without wiring production paths yet.

Overview
Adds shared asset-movement transfer primitives in anchor (src/services/asset-movement/lib/) so downstream packages can share one vocabulary without circular deps. Package version bumps 0.0.96 → 0.0.97.

Introduces an ISO 20022–style transfer state machine (transfer-status.ts): status constants, per-status metadata (category, phase, cancelable/terminal), a transition graph, and helpers (canTransition, assertTransition, isTransferStatus).

Adds KeetaAssetMovementTransferError (transfer-error.ts) with stable MovementErrorCode values, HTTP status mapping, and JSON serialization—used by amount rescaling and illegal transitions.

Adds KeetaAnchorAmount (amount.ts) as an immutable smallest-unit + decimals + asset type, with loss-checked toDecimals, location-based precision via AmountLocation, minorToMajor / majorToMinor, and cross-precision equals. Vitest coverage exercises transitions and amount behavior.

Reviewed by Cursor Bugbot for commit 5ee953b. Bugbot is set up for automated code reviews on this repo. Configure here.

@sephynox sephynox self-assigned this Aug 20, 2026
@sephynox sephynox added the enhancement New feature or request label Aug 20, 2026
@sonarqubecloud

Copy link
Copy Markdown

export class KeetaAnchorAmount {
readonly #value: bigint;
readonly #decimals: number;
readonly #asset: Asset['id'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why just the asset id and not the full asset with id/location? The decimals can be different on different locations.

/**
* An amount of an on-chain token, at the token's precision.
*/
static fromToken(value: bigint, token: AmountToken): KeetaAnchorAmount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be generalized more to an asset instead of a keeta token?

* An immutable amount value object: smallest-unit integer `value` at
* `decimals` precision, denominated in `asset`.
*/
export class KeetaAnchorAmount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've talked about having an asset amount class that includes many of these attributes, should it be generalized more to support any asset/location/id etc?

Comment on lines +15 to +34
export interface LocationAssetPrecision {
readonly id: Asset['id'];
readonly decimals: number;
}

/**
* The per-asset precision table of a location, for
* {@link KeetaAnchorAmount.toLocationDecimals}.
*/
export interface AmountLocation {
readonly assets: readonly LocationAssetPrecision[];
}

/**
* The token shape {@link KeetaAnchorAmount.fromToken} accepts.
*/
export interface AmountToken {
readonly tokenPublicKey: TokenPublicKeyString;
readonly decimals: number;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit confused by these types, are they necessary when we could just have a KeetaAssetAmount (or the new KeetaAnchorAmount class that handles these types within it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants