feat(trader): add 'sphere trader withdraw' subcommand#9
Open
feat(trader): add 'sphere trader withdraw' subcommand#9
Conversation
added 3 commits
May 4, 2026 14:16
Closes the gap noted in trader-service PR-17 recovery review: trader-service's ACP WITHDRAW_TOKEN handler exists, but no operator-facing CLI exposed it. Operators couldn't pull funds back out of their trader. Adds: - 'sphere trader withdraw --asset <symbol> --amount <bigint> --to-address <addr>' invokes WITHDRAW_TOKEN over ACP. Three required flags mirror the trader-side validation (asset non-empty, amount > 0 positive integer string, to_address valid). - buildWithdrawParams pure function (exported for unit testing). - 8 unit tests pinning the wire-shape contract: snake_case wire fields, bigint-string amount preservation (no Number coercion / precision loss), strict positive-integer amount validation (rejects 0, negative, decimal, '1e6', leading-zero, non-numeric), all three address forms accepted (@NameTag, DIRECT://hex, raw hex). - Subcommand-tree test now asserts 7 controller-scoped subcommands (was 6 — withdraw is the 7th). Verified: 114/114 tests pass (was 106, +8 new wire-shape tests). typecheck + lint clean. The same withdraw subcommand is added to trader-service's bundled trader-ctl in vrogojin/trader-service PR #17, so direct-docker e2e tests can also exercise the full deposit→trade→withdraw flow.
Steelman finding (companion to trader-service fix): a leading or trailing space in --asset or --to-address would pass the empty-after-trim CLI guard but reach the trader's address regex verbatim, producing a confusing INVALID_PARAM remote error rather than a local CLI message. trim() at the wire boundary normalizes valid inputs without changing the validation contract (empty-after- trim was and still is rejected at the CLI layer above). The trader-side regex fix (accepts @NameTag, DIRECT://hex, and raw hex pubkey rather than only alphanumeric) lands in trader-service's recover/merge-real-settlement branch. Together the two fixes make all three address forms advertised in --help actually work end-to-end. Verified: 114/114 tests pass.
…s help sphere-sdk's parseAddress does NOT accept bare hex without a DIRECT://, PROXY://, or @ prefix. The CLI advertised three forms but only two would actually work. trader-service's strict address validator (now layered on top of parseAddress + isValidNametag, plus a hex regex for DIRECT/PROXY) makes the contract explicit. Verified: 114/114 tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the missing withdraw subcommand to `sphere trader`. Trader-service's ACP `WITHDRAW_TOKEN` handler has existed for some time, but no operator-facing CLI exposed it — operators could deposit and trade but couldn't pull funds back out.
This PR closes that gap on the canonical CLI side. A parallel commit in vrogojin/trader-service#17 adds the same subcommand to the bundled `trader-ctl` so direct-docker e2e tests also gain the full deposit → trade → withdraw flow.
API
```
sphere trader withdraw \
--tenant @trader-alice \
--asset UCT \
--amount 1000000000 \
--to-address @bob
```
Three required flags mirror the trader-side validation in `trader-service/src/trader/trader-command-handler.ts:633`:
CLI-layer validation (in `buildWithdrawParams`) catches trivial cases before the round-trip:
Tests
```
$ npm run check
Tests 114 passed (114) # was 106, +8 new wire-shape tests
typecheck + lint clean
```
8 new tests pin the wire-shape contract:
Plus the subcommand-tree test now asserts 7 controller-scoped subcommands (was 6).
Verification
```
$ node bin/sphere.mjs trader --help | grep withdraw
withdraw [options] Withdraw a token from the trader to an external address (ACP WITHDRAW_TOKEN)
$ node bin/sphere.mjs trader withdraw --help
Destination address: @NameTag, DIRECT://hex, or 64-char hex pubkeyUsage: sphere trader withdraw [options]
Withdraw a token from the trader to an external address (ACP WITHDRAW_TOKEN)
Options:
--asset Asset symbol (e.g. UCT, USDU) or hex coin id
--amount Amount to withdraw in smallest units (string-encoded bigint, must be > 0)
--to-address
-h, --help display help for command
```
Test plan