aboutsummaryrefslogtreecommitdiffstats
path: root/src/wallet.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-28 09:31:51 -0700
committerAdam Soltys <[email protected]>2026-06-28 09:31:51 -0700
commit0fbeb3c55413fb221d890b3bf3464ebd2aed9fa1 (patch)
treef8f034c2ba00d0f78a34e1df1972a46712487151 /src/wallet.js
parent96d9b7ee6914b157a17e078cfe597cb40f35c9e2 (diff)
downloadcoinosv3-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.js6
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.