Skip to content

feat(fiber): object-form-only _transferAsset recipient, fail-loud#193

Open
ottobot-ai wants to merge 1 commit into
mainfrom
feat/transfer-asset-recipient-object-form
Open

feat(fiber): object-form-only _transferAsset recipient, fail-loud#193
ottobot-ai wants to merge 1 commit into
mainfrom
feat/transfer-asset-recipient-object-form

Conversation

@ottobot-ai

@ottobot-ai ottobot-ai commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Implements F2 of the fiber-ergonomics program, revised per review to drop back-compat (greenfield) and surface parse failures instead of dropping them.

The new contract for _transferAsset recipient

  • Object form ONLY{"Fiber":{"fiberId":..}} / {"Wallet":{"address":..}}, decoded strictly through the same magnolia AssetHolder codec as every other holder surface. The legacy bare-string UUID/DAG-address disambiguation is removed.
  • Fail loud — any malformed directive (non-object item, missing/non-UUID assetId, a recipient that isn't a well-formed AssetHolder object, or a gas/eval failure) raises a graceful CombineRejected instead of being silently dropped. A silently-dropped transfer is a latent bug; surfacing it is deliberate.

Why combine is the right layer (and what's caught earlier)

The recipient isn't in the signed TransitionStateMachine message — it's the evaluated output of the definition's effect against runtime context (usually dynamic, {"Fiber":{"fiberId":{"var":"event.x"}}}). So the resolved holder is only knowable at combine, and extraction runs only on the combiner apply path (never validateSignedUpdate) — making the raise a rule-#2 graceful reject (caught at insertRejectionReceipt), the same pattern AssetCombiner already uses for the R1 holder check. The static recipient shape is caught earlier and advisory by the DefinitionLinter (linter-only — no hard registration gate, per review).

Migrates every call site

  • chain tests: AssetFiberTransferSuite (escrow E2E + extractor units — escrow now moves to both Fiber and Wallet object recipients through the full combiner; "malformed dropped" → "malformed REJECTED"), AssetTransferRecipientObjectFormSuite (the contract). Full sharedData/test green (572/0).
  • e2e defs: riverdale-economy (7 recipients → Fiber), staked-oracle-pool (4 → Wallet, event.agent = a wallet address). sigma-mixer has no _transferAsset recipients. Validated end-to-end by the e2e lanes on CI.

The SDK builder side (@ottochain/sdk transferAsset/toFiber/toWallet → object form + app examples) is migrated separately on the SDK PR (#227).

Part of the fiber-ergonomics implementation set (RFCs in #192).

🤖 Generated with Claude Code

The `_transferAsset` directive recipient is now the canonical AssetHolder
OBJECT form ONLY (`{"Fiber":{"fiberId":..}}` / `{"Wallet":{"address":..}}`),
decoded strictly through the same magnolia codec as every other holder
surface. The legacy bare-string UUID/DAG-address disambiguation is removed
(greenfield — no back-compat).

Any malformed directive — a non-object item, missing/non-UUID assetId, a
recipient that is not a well-formed AssetHolder object, or a gas/eval
failure — now raises a graceful CombineRejected instead of being silently
dropped. A silently-dropped transfer is a latent bug; surfacing it is
deliberate. Safe because effect extraction runs only on the combiner apply
path (never validateSignedUpdate), so the raise is caught at insert ->
RejectionReceipt (rule #2), the same authoritative-gate pattern AssetCombiner
already uses for the R1 holder check. The static recipient SHAPE is caught
earlier/advisory by the DefinitionLinter (linter-only, no hard registration
gate).

Migrates every call site:
  - chain: AssetFiberTransferSuite (escrow E2E + extractor units),
    AssetTransferRecipientObjectFormSuite (contract). Full sharedData/test
    green (572).
  - e2e defs: riverdale-economy (7 recipients -> Fiber), staked-oracle-pool
    (4 -> Wallet). sigma-mixer has no _transferAsset recipients. Validated
    by the e2e lanes on CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5TUSJPD8FCtJagf7siXgt
@ottobot-ai ottobot-ai changed the title feat(fiber): accept AssetHolder object form in _transferAsset recipient feat(fiber): object-form-only _transferAsset recipient, fail-loud Jun 27, 2026
@ottobot-ai ottobot-ai force-pushed the feat/transfer-asset-recipient-object-form branch from 72646ab to 877dac7 Compare June 27, 2026 03:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant