diff options
| author | Adam Soltys <[email protected]> | 2026-06-28 09:31:51 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-06-28 09:31:51 -0700 |
| commit | 0fbeb3c55413fb221d890b3bf3464ebd2aed9fa1 (patch) | |
| tree | f8f034c2ba00d0f78a34e1df1972a46712487151 /src/wallet.js | |
| parent | 96d9b7ee6914b157a17e078cfe597cb40f35c9e2 (diff) | |
| download | coinosv3-0fbeb3c55413fb221d890b3bf3464ebd2aed9fa1.tar.gz coinosv3-0fbeb3c55413fb221d890b3bf3464ebd2aed9fa1.zip | |
Locked gifts: let NIP-07 extension users decrypt in-place, skip the code
The gift payload is now encrypted two ways in the link: under the one-time code
(the DM / manual path) AND to the recipient's nostr pubkey via an ephemeral key.
When a NIP-07 browser extension (window.nostr) is present, the claim view offers
'Claim with nostr extension' — it checks the extension's pubkey matches the gift,
decrypts ctKey via window.nostr.nip44.decrypt, and claims into a fresh wallet with
no code. The pasted-code path remains as the fallback for everyone else.
Verified: both decrypt paths recover the payload from the blob; a different
extension account is rejected.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'src/wallet.js')
| -rw-r--r-- | src/wallet.js | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/src/wallet.js b/src/wallet.js index b2ff3e3..e2b5b35 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -23,7 +23,7 @@ import { concatBytes } from '@scure/btc-signer/utils.js'; import { Api, pool, getBackend, explorerWeb, electrumCandidates, spIndexerUrl } from './api.js'; import { ElectrumApi } from './electrum.js'; -import { NostrSync, getSyncConfig, encryptWithCode, npubOf } from './nostr.js'; +import { NostrSync, getSyncConfig, encryptGiftPayload, npubOf } from './nostr.js'; import { isSilentPaymentAddress, decodeSilentPaymentAddress, silentPaymentScripts, silentPaymentPlaceholder, deriveSilentPaymentKeys, encodeSilentPaymentAddress, silentPaymentScan, silentPaymentOutputPrivKey, silentPaymentCandidate, bloomHas } from './silentpay.js'; import { schnorr } from '@noble/curves/secp256k1'; @@ -2579,8 +2579,8 @@ const LOCKED_GIFT_VERSION = 1; // to the recipient via a nostr DM; the public link carries only the ciphertext. // Returns { blob (for the /lg/ link), claimCode (to DM) }. export function lockGift(code, amount, recipientPkHex) { - const { code: claimCode, ct } = encryptWithCode(code); - const blob = base64urlnopad.encode(new TextEncoder().encode(JSON.stringify({ v: LOCKED_GIFT_VERSION, amount, to: recipientPkHex, ct }))); + const { code: claimCode, ctCode, eph, ctKey } = encryptGiftPayload(code, recipientPkHex); + const blob = base64urlnopad.encode(new TextEncoder().encode(JSON.stringify({ v: LOCKED_GIFT_VERSION, amount, to: recipientPkHex, ct: ctCode, eph, ctKey }))); return { blob, claimCode }; } // The public fields of a locked-gift blob (or null). Decryption needs the code. |
