feat(nipcash): bearer slice lifecycle — check, rekey, multi-source transfer - #22
Merged
Merged
Conversation
…ion_key sources ResolvedConnectionKey builds a connection_key Recipient/Target directly from a nipIC.ConnectionKey the caller already has (e.g. decoded from an nconnection1... string via nipIC.DecodeNConnection), without needing the raw external ID ConnectionKey itself hashes internally. cash_consolidate's wire shape (consolidateSourceParam) had no attestation_event field at all, so a connection_key source's proof had nowhere to travel — added the field and wired Request() to populate it instead of discarding buildProof's attestation return value. Sources may now be pubkey or connection_key; bearer sources remain rejected (no signature, no binding to the request carrying it).
cash_consolidate's new_identity target was pubkey-only client-side, even though this NIP-CASH revision's server side already accepts bearer and connection_key targets too. ErrConsolidateTargetNotPubkey renamed to ErrConsolidateTargetInvalid: the only thing rejected client-side now is a nil To, not a real Target's own type. Also passes IAPubkey through for a connection_key target, previously dropped entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…sentation Splits a bearer slice's optional combined "<token>#<bearer_secret>" display-layer presentation back into its two parts, so a caller presenting the two together in one string has a symmetric way to pull them back apart on the receiving end. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Resolves the three-way NewWalletToken ambiguity on a transfer result (in-place reassignment vs. spin-off vs. partial split) into the one answer a caller actually needs: the token the recipient should use. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
RecipientStatus.IsBearer keeps identityTypeBearer's own comparison inside the package. MatchClaim/MatchClaimAuto are the pure matching rule CheckClaim (nipcash/client) builds on: only ever considers an unclaimed recipient a match, bearer matches any unclaimed bearer entry, non-bearer matches only an unclaimed entry whose IdentityValue equals the caller's own pubkey exactly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…fore acting on it Confirms a matching, unclaimed recipient actually exists on the Hub for a token, live via ListRecipients + MatchClaimAuto, rather than trusting a token's own identity_required TLV (a stale-prone hint, not a live guarantee). A method, not a self-dialing package function: several callers already hold a live, connected *Client for the same wallet by the time they need this check. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rogressError transferConsolidater is the narrow slice of *Client that RekeyBearerSlice/TransferFromSources actually call, factored out so their own call-sequencing logic is unit-testable against a hand-built fake, without a live Cash Hub. PartialProgressError is returned by both when their first wire call lands for real but their second then fails -- exactly one of Transferred/Consolidated is set, whichever call type actually succeeded, so the caller can update its own ledger from whichever landed without an extra round trip. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nder a fresh secret Moves a bearer-mode slice out of shared custody: the current secret is presented once, consumed, and replaced with a fresh secret only the caller knows. Optionally merges the slice with other same-issuer sources into a freshly-minted bearer wallet -- requires an interim reassignment onto a pubkey identity first, since cash_consolidate never accepts a bearer-identified source. nipcash.IsPubkeyTarget validates that interim identity client-side, before any wire call. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rawn from multiple sources Transfers Amount to To, drawing from one or more Sources. A single source transfers (or splits) directly; more than one consolidates first into InterimIdentity, then reconnects to that newly-consolidated wallet specifically before transferring onward -- cash_consolidate always spins off a genuinely new wallet pubkey, but CashTransfer's own proof-building binds to the Client's original dial-target pubkey, so acting through the original client on the new wallet would bind the proof to the wrong pubkey entirely (confirmed live: NOT_FOUND). Reconnecting first avoids that failure mode. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Walks through minting a bearer slice, handing over the combined "<token>#<bearer_secret>" string, and the recipient's side: split it back apart, CheckClaim to confirm it's real before trusting it, then RekeyBearerSlice to move it out of shared custody under a fresh secret only the new holder knows. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…lice-lifecycle # Conflicts: # CHANGELOG.md
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
mainup to date withdevelop, including the already-committed85b129c(ResolvedConnectionKey+ connection_key consolidate sources), plus new work building on top of it:cash_consolidatenow accepts a bearer or connection_keyTotarget, not just pubkey (ErrConsolidateTargetNotPubkey→ErrConsolidateTargetInvalid);IAPubkeynow passes through for connection_key targets.nipcash.SplitBearerSliceStringsplits the combined"<token>#<bearer_secret>"presentation back apart.nipcash.CheckClaim(nipcash/client.CheckClaim) confirms a token has a real, unclaimed recipient before a caller acts on it.nipcash/client.RekeyBearerSlicemoves a bearer-mode slice out of shared custody under a fresh secret, optionally consolidating with other same-issuer sources.nipcash/client.TransferFromSourcestransfers an amount drawn from one or more sources, auto-consolidating first (and reconnecting to the newly-consolidated wallet, fixing aNOT_FOUNDfailure the naive approach hits).nipcash/client.PartialProgressErrorreports partial progress if the interim call of either composite above lands but the following one fails.Split into 9 commits, one concern each (see commit log) — infra (
transferConsolidater/PartialProgressError) lands before its two consumers,cash_consolidate's target-acceptance change lands beforeRekeyBearerSlicedepends on it, andCHANGELOG.md/README.mdentries land with (or right after) the piece they document.This is independent of #21 (
fix(nip47)), which is a separate, unrelated wire-compat fix split into its own PR.Test plan
go build ./...go vet ./...go test -count=1 ./...(full suite, all packages green)🤖 Generated with Claude Code