Skip to content

fix(invoice): accept @nametag as --target#17

Open
vrogojin wants to merge 2 commits into
mainfrom
fix/invoice-create-nametag-resolution
Open

fix(invoice): accept @nametag as --target#17
vrogojin wants to merge 2 commits into
mainfrom
fix/invoice-create-nametag-resolution

Conversation

@vrogojin
Copy link
Copy Markdown
Contributor

Summary

sphere invoice create --target @bob-tag --asset "1000000 UCT" now resolves the @nametag (and chain pubkey / alpha1...) to the canonical DIRECT:// address before calling AccountingModule.createInvoice. Symmetric with payments send --recipient @nametag which already accepts these forms.

Why resolve at the CLI layer

  • AccountingModule.createInvoice validates target.address.startsWith('DIRECT://') and throws INVOICE_INVALID_ADDRESS otherwise. This is correct SDK behaviour — invoice terms cryptographically bind the recipient identity, so the canonical DIRECT:// form is what gets signed and shipped.
  • The CLI is the right layer to translate user-facing identifiers (@NameTag, chain pubkey, alpha1) into canonical addresses. The same pattern is already in dm-history and payments send --recipient.
  • Resolution happens once at create-time; the resolved DIRECT:// is what's persisted in the invoice's signed terms, so a later nametag rename does NOT invalidate the invoice (correct semantic).

Before / After

Before:

$ sphere invoice create --target @bob-tag --asset "1000000 UCT"
Error: Invalid target address: must be DIRECT:// format

After:

$ sphere invoice create --target @bob-tag --asset "1000000 UCT"
Invoice created:
{ ... "address": "DIRECT://0000..." ... }

Test plan

  • Live testnet validation via manual-test-full-recovery.sh (sphere-sdk PR #222) — §C.1 invoice create now succeeds with @bob-... target; resolved address appears in the signed invoice terms.
  • Reviewer: re-run manual-test-full-recovery.sh to confirm §C.1 passes end-to-end.

Related

  • sphere-sdk PR #222 — manual-test walkthrough + script that surfaced this.
  • sphere-sdk PR #225 (merged) — issue #223 cross-process UXF delivery fix; this CLI fix was discovered while validating that change via the CLI surface.

`sphere invoice create --target @bob-tag --asset "1000000 UCT"` now
resolves the @NameTag (or chain pubkey, or alpha1 address) to the
canonical `DIRECT://` address before calling `AccountingModule.create
Invoice`. Symmetric with `payments send --recipient @nametag` which
already accepts these forms.

Why resolve at the CLI layer:

  - `AccountingModule.createInvoice` validates `target.address.starts
    With('DIRECT://')` (modules/accounting/AccountingModule.ts:906)
    and throws `INVOICE_INVALID_ADDRESS` otherwise. This is correct
    SDK behaviour — invoice terms cryptographically bind the
    recipient identity, so the canonical DIRECT:// form is what
    gets signed and shipped.
  - The CLI is the right layer to translate user-facing identifiers
    (@NameTag, chain pubkey, alpha1) into canonical addresses. The
    same pattern is already in `dm-history`
    (legacy-cli.ts:3108) and in `payments send --recipient`.
  - Resolution happens once at create-time; the resolved DIRECT://
    address is what's persisted in the invoice's signed terms, so
    a later nametag rename does NOT invalidate the invoice (which
    is the correct semantic).

Before this fix:

  $ sphere invoice create --target @bob-tag --asset "1000000 UCT"
  Error: Invalid target address: must be DIRECT:// format

After:

  $ sphere invoice create --target @bob-tag --asset "1000000 UCT"
  Invoice created:
  { ... "address": "DIRECT://0000..." ... }

Validated against live testnet during issue-223 cross-process manual
recovery test (see sphere-sdk's
manual-test-full-recovery.sh + walkthrough doc on PR #222 / branch
docs/issue-218-full-recovery-manual-test).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…gration/all-fixes tip

The previous pinned SHA `86468103a` was the tip of
`refactor/extract-cli-to-sphere-cli` at the time the workflow was added.
That branch has since been deleted from the public sphere-sdk repo.
The commit still exists in the GitHub repo's object database but is
no longer reachable via any branch tip, so a default `git clone` does
not fetch it and the subsequent `git checkout --detach $SHA` fails with
`fatal: unable to read tree`. PR #17's CI started failing for this
reason — symptom unrelated to PR contents.

Fix: re-pin to `02cb4550fac` (the tip of `integration/all-fixes` after
PR #225, the cross-process UXF delivery fix). That branch contains the
same CLI-consumed type exports (`CreateInvoiceRequest`, `PayInvoice
Params`, `InvoiceRequestedAsset`, encrypt/decrypt helpers, ...) that
the original pin provided. Verified locally:

  grep -E 'CreateInvoiceRequest|PayInvoiceParams|InvoiceRequestedAsset' \
    sphere-sdk/index.ts
    CreateInvoiceRequest,
    InvoiceRequestedAsset,
    PayInvoiceParams,

Defense-in-depth: add `git fetch origin "$SPHERE_SDK_SHA" || true`
before checkout so the workflow keeps working when integration/all-
fixes advances past this commit (the SHA stays pinned for supply-chain
integrity, but the explicit fetch picks it up via the object database
even if it's no longer on a branch tip).

Both `ci.yml` and `integration-nightly.yml` updated together so a
nightly run stays hermetic with PR CI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
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