Skip to content

trader create-intent: accept human-friendly floats, convert to bigint via token-registry decimals #47

Description

@vrogojin

Why

Today the sphere trader create-intent CLI declares --rate-min <bigint> / --rate-max <bigint> / --volume-min <bigint> / --volume-max <bigint> and forwards the literal strings through to the trader's ACP CREATE_INTENT payload without conversion (see src/trader/trader-commands.ts:386-389 + :224-231). Operators must type fully-scaled smallest-unit integers — for example 80000000000000000 for 0.08 ETH per UCT given UCT is 18-decimal.

Per project owner UX guidance, the intended CLI surface is human-friendly floats: --rate-min 0.08, --volume-min 50. The CLI converts to bigint smallest-units internally via a token-registry decimals lookup before sending the ACP payload. The ACP wire format stays bigint-string (canonical JSON preserves precision); only the CLI surface changes.

This is the third leg of the three-way drift documented in sphere-sdk/blob/main/docs/uxf/PROTOCOL-SPEC-DRIFT-474.md finding D-NEW:

  • Design intent: float at CLI surface, bigint at ACP wire (convert at CLI boundary).
  • Spec (trader-service docs/protocol-spec.md §2.4 / §4.2): number end-to-end.
  • Implementation today: bigint-string end-to-end including the CLI.

The implementation side will stay on bigint (the ACP wire shouldn't change), the spec side is tracked separately in trader-service. This issue is the CLI side.

Scope

sphere trader create-intent is the primary surface. Same UX should apply to anywhere else in sphere trader (and sphere swap) that touches amounts or rates.

Behavior

  1. Default: accept floats. --rate-min 0.08 --rate-max 0.12 --volume-min 50 --volume-max 50. Convert via BigInt(Math.round(value × 10**decimals)) using each asset's decimals from the token registry. Send the bigint-string on the ACP wire.
  2. Power-user fallback: --rate-min-bigint <int> / --volume-min-bigint <int> etc. for operators who want to type the smallest-unit form explicitly. The two flag families are mutually exclusive per axis.
  3. Validation, pre-flight (CLI-side, before any DM):
    • Reject non-finite floats (NaN, Infinity).
    • Reject negatives / zero.
    • Reject more decimal digits than the asset supports (e.g. --rate-min 0.123456789012345678999 against an 18-decimal asset).
    • Reject --rate-min > --rate-max and --volume-min > --volume-max.
    • Report the resulting bigint in the CLI's confirmation log line so operators can sanity-check.
  4. Decimals source: token registry (@unicitylabs/sphere-sdk TokenRegistry.decimalsFor(coinId) or equivalent). If the registry has no entry for the asset, fall back to a reasonable default (18) and warn loudly. Do NOT silently assume 18 decimals — the warning is critical because UCT-on-mainnet may differ from UCT-on-testnet in some future revision.
  5. Help text: clarify the units. --rate-min <float> "Minimum acceptable rate (quote per base unit, decimal; e.g. 0.08 for 0.08 ETH per UCT)". --volume-min <float> "Minimum volume per match (in whole base-asset units; e.g. 50 for 50 UCT)".

Acceptance

  • sphere trader create-intent --tenant @x --direction sell --base UCT --quote ETH --rate-min 0.08 --rate-max 0.12 --volume-min 50 --volume-max 50 --expiry-ms 3600000 --json succeeds against a v0.1+ trader-agent image and the ACP payload's rate_min/rate_max/volume_min/volume_max are bigint strings of the right magnitude.
  • All four CLI float-validation guardrails reject malformed input with a clear local message (no DM round-trip).
  • sphere trader create-intent --help documents the float UX.
  • Unit tests cover the float→bigint conversion in buildCreateIntentParams.
  • Cross-check: when the sphere-sdk soak manual-test-trader-roundtrip.sh is re-run after this lands, the bigint-shim fallback (create_intent_with_shim second branch) is never taken — the first-attempt float form succeeds.

Out of scope

  • The trader-service spec patch (D1 in the drift audit) — tracked separately against vrogojin/trader-service.
  • The trader-agent image rebuild — tracked separately against vrogojin/agentic_hosting.
  • The ACP wire format — stays bigint-string.

Related

  • sphere-sdk#474 — trader-roundtrip soak (PR #475) — writes the float form already, with a bigint-shim fallback that this issue eliminates.
  • sphere-sdk PR #475 — manual-test-trader-roundtrip.sh exercises this UX.
  • sphere-sdk PROTOCOL-SPEC-DRIFT-474.md (in PR #475) — Finding D-NEW for the full three-way drift discussion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions