402-mcp 4.2.2 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -15
- package/build/config.d.ts +6 -0
- package/build/config.js +41 -10
- package/build/config.js.map +1 -1
- package/build/fetch/resilient-fetch.js +15 -4
- package/build/fetch/resilient-fetch.js.map +1 -1
- package/build/fetch/transport.d.ts +1 -0
- package/build/fetch/transport.js +37 -14
- package/build/fetch/transport.js.map +1 -1
- package/build/http-security.d.ts +13 -0
- package/build/http-security.js +38 -0
- package/build/http-security.js.map +1 -0
- package/build/index.js +184 -119
- package/build/index.js.map +1 -1
- package/build/spend-tracker.d.ts +31 -4
- package/build/spend-tracker.js +102 -17
- package/build/spend-tracker.js.map +1 -1
- package/build/store/cashu-tokens.d.ts +19 -0
- package/build/store/cashu-tokens.js +32 -0
- package/build/store/cashu-tokens.js.map +1 -1
- package/build/store/credentials.d.ts +5 -0
- package/build/store/credentials.js +1 -0
- package/build/store/credentials.js.map +1 -1
- package/build/store/pending-payments.d.ts +36 -0
- package/build/store/pending-payments.js +88 -0
- package/build/store/pending-payments.js.map +1 -0
- package/build/tools/buy-credits.d.ts +9 -0
- package/build/tools/buy-credits.js +40 -3
- package/build/tools/buy-credits.js.map +1 -1
- package/build/tools/config.d.ts +5 -0
- package/build/tools/config.js.map +1 -1
- package/build/tools/confirm.d.ts +12 -0
- package/build/tools/confirm.js +27 -0
- package/build/tools/confirm.js.map +1 -0
- package/build/tools/fetch.d.ts +7 -1
- package/build/tools/fetch.js +255 -140
- package/build/tools/fetch.js.map +1 -1
- package/build/tools/nostr-subscribe.js.map +1 -1
- package/build/tools/pay.d.ts +9 -0
- package/build/tools/pay.js +65 -8
- package/build/tools/pay.js.map +1 -1
- package/build/tools/reconcile.d.ts +33 -0
- package/build/tools/reconcile.js +111 -0
- package/build/tools/reconcile.js.map +1 -0
- package/build/tools/redeem-cashu.js +1 -1
- package/build/tools/redeem-cashu.js.map +1 -1
- package/build/tools/register-widgets.js +5 -5
- package/build/tools/register-widgets.js.map +1 -1
- package/build/tools/search.js +17 -3
- package/build/tools/search.js.map +1 -1
- package/build/tools/untrusted.d.ts +3 -0
- package/build/tools/untrusted.js +18 -0
- package/build/tools/untrusted.js.map +1 -0
- package/build/wallet/cashu.js +101 -21
- package/build/wallet/cashu.js.map +1 -1
- package/build/wallet/lnurlcash.js +25 -7
- package/build/wallet/lnurlcash.js.map +1 -1
- package/build/wallet/nwc.js +51 -3
- package/build/wallet/nwc.js.map +1 -1
- package/build/wallet/types.d.ts +17 -0
- package/build/x402/parse.d.ts +15 -3
- package/build/x402/parse.js +23 -9
- package/build/x402/parse.js.map +1 -1
- package/build/x402/payment.js +11 -6
- package/build/x402/payment.js.map +1 -1
- package/llms-full.txt +71 -33
- package/llms.txt +48 -21
- package/package.json +3 -3
- package/src/widgets/dist/service-directory.html +11 -2
package/build/wallet/cashu.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
import { tryDecodeBolt11, verifyPreimage } from 'farrier-kit';
|
|
2
|
+
const UNKNOWN_REASON = 'Call l402-reconcile with this payment hash before paying this service again.';
|
|
1
3
|
async function doPayInvoice(invoice, tokenStore, _options) {
|
|
4
|
+
// The payment hash is what proves settlement later, so an invoice that
|
|
5
|
+
// cannot be decoded is refused before any token leaves the store.
|
|
6
|
+
const invoiceDecoded = tryDecodeBolt11(invoice);
|
|
7
|
+
if (!invoiceDecoded) {
|
|
8
|
+
return { paid: false, method: 'cashu', reason: 'Invalid BOLT-11 invoice' };
|
|
9
|
+
}
|
|
10
|
+
const paymentHash = invoiceDecoded.paymentHashHex;
|
|
2
11
|
const token = tokenStore.consumeFirst();
|
|
3
12
|
if (!token) {
|
|
4
13
|
return { paid: false, method: 'cashu', reason: 'No Cashu tokens available' };
|
|
@@ -33,39 +42,75 @@ async function doPayInvoice(invoice, tokenStore, _options) {
|
|
|
33
42
|
// From this point, only proofsToSend/proofsToKeep are valid — never
|
|
34
43
|
// re-add the original token. Track this so the catch block knows
|
|
35
44
|
// whether the original or the new proofs should be restored.
|
|
36
|
-
sendProofs = { proofsToSend, proofsToKeep, getEncodedTokenV4 };
|
|
45
|
+
sendProofs = { proofsToSend, proofsToKeep, getEncodedTokenV4, quoteId: meltQuote.quote };
|
|
37
46
|
const meltResponse = await wallet.meltProofs(meltQuote, proofsToSend);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
restoreChangeProofs(tokenStore, getEncodedTokenV4, token.mint, proofsToKeep, meltResponse.change);
|
|
47
|
+
const state = meltResponse.quote.state;
|
|
48
|
+
if (state === 'PAID') {
|
|
49
|
+
// The sent proofs are spent. Keep and change proofs are ours either way.
|
|
50
|
+
restoreChangeProofs(tokenStore, getEncodedTokenV4, token.mint, proofsToKeep, meltResponse.change ?? []);
|
|
51
|
+
// NUT-05 lets a mint report PAID with a null preimage. Without a
|
|
52
|
+
// preimage that hashes to the invoice, settlement is only the mint's
|
|
53
|
+
// word, and a caller told "not paid" would pay again.
|
|
54
|
+
const preimage = meltResponse.quote.payment_preimage ?? undefined;
|
|
55
|
+
if (!preimage || !verifyPreimage(preimage, paymentHash)) {
|
|
56
|
+
return {
|
|
57
|
+
paid: false,
|
|
58
|
+
method: 'cashu',
|
|
59
|
+
outcome: 'unknown',
|
|
60
|
+
reason: `The mint reported the melt as paid but returned no preimage that matches the invoice. ${UNKNOWN_REASON}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return { paid: true, preimage, method: 'cashu' };
|
|
64
|
+
}
|
|
65
|
+
if (state === 'PENDING') {
|
|
66
|
+
// The mint may still pay with the sent proofs, so they are neither
|
|
67
|
+
// spendable nor lost. Hold them aside until reconcile rules on them.
|
|
68
|
+
restoreChangeProofs(tokenStore, getEncodedTokenV4, token.mint, proofsToKeep, []);
|
|
69
|
+
reserveProofs(tokenStore, getEncodedTokenV4, token.mint, proofsToSend, paymentHash, meltQuote.quote);
|
|
42
70
|
return {
|
|
43
|
-
paid:
|
|
44
|
-
preimage: meltResponse.quote.payment_preimage ?? undefined,
|
|
71
|
+
paid: false,
|
|
45
72
|
method: 'cashu',
|
|
73
|
+
outcome: 'unknown',
|
|
74
|
+
reason: `The mint reports the melt as pending. ${UNKNOWN_REASON}`,
|
|
46
75
|
};
|
|
47
76
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return { paid: false, method: 'cashu', reason: 'Cashu melt failed' };
|
|
53
|
-
}
|
|
77
|
+
// UNPAID: the mint refused the melt, so the swapped proofs are still
|
|
78
|
+
// valid. Re-add the send + keep proofs (NOT the dead original token).
|
|
79
|
+
restoreChangeProofs(tokenStore, getEncodedTokenV4, token.mint, proofsToKeep, proofsToSend);
|
|
80
|
+
return { paid: false, method: 'cashu', reason: 'Cashu melt failed' };
|
|
54
81
|
}
|
|
55
82
|
catch {
|
|
56
83
|
if (sendProofs) {
|
|
57
|
-
// send() succeeded
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
// send() succeeded, so the melt request may have reached the mint
|
|
85
|
+
// before the error. Only the keep proofs are certainly ours; the sent
|
|
86
|
+
// ones are held aside until reconcile learns what the mint did.
|
|
87
|
+
console.warn('[402-mcp] Cashu melt failed after send() succeeded; melt outcome unknown, sent proofs reserved');
|
|
88
|
+
restoreChangeProofs(tokenStore, sendProofs.getEncodedTokenV4, token.mint, sendProofs.proofsToKeep, []);
|
|
89
|
+
reserveProofs(tokenStore, sendProofs.getEncodedTokenV4, token.mint, sendProofs.proofsToSend, paymentHash, sendProofs.quoteId);
|
|
90
|
+
return {
|
|
91
|
+
paid: false,
|
|
92
|
+
method: 'cashu',
|
|
93
|
+
outcome: 'unknown',
|
|
94
|
+
reason: `The Cashu melt request failed after it may have reached the mint. ${UNKNOWN_REASON}`,
|
|
95
|
+
};
|
|
65
96
|
}
|
|
97
|
+
// Error occurred before send(); original token is still valid
|
|
98
|
+
tokenStore.add(token);
|
|
66
99
|
return { paid: false, method: 'cashu', reason: 'Cashu payment failed' };
|
|
67
100
|
}
|
|
68
101
|
}
|
|
102
|
+
function reserveProofs(tokenStore, encodeFn, mint, proofs, paymentHash, quoteId) {
|
|
103
|
+
const amountSats = proofs.reduce((sum, p) => sum + p.amount, 0);
|
|
104
|
+
if (amountSats <= 0)
|
|
105
|
+
return;
|
|
106
|
+
try {
|
|
107
|
+
const now = new Date().toISOString();
|
|
108
|
+
tokenStore.reserve({ token: encodeFn({ mint, proofs }), mint, amountSats, addedAt: now, paymentHash, quoteId, reservedAt: now });
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
console.warn('[402-mcp] Failed to reserve proofs from an unresolved melt');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
69
114
|
/** Creates a Cashu wallet provider that melts ecash tokens to pay Lightning invoices. */
|
|
70
115
|
export function createCashuWallet(tokenStore, lock) {
|
|
71
116
|
// Use external lock if provided (shared with xcashu path), otherwise internal
|
|
@@ -84,8 +129,43 @@ export function createCashuWallet(tokenStore, lock) {
|
|
|
84
129
|
payInvoice(invoice, options) {
|
|
85
130
|
return withLock(() => doPayInvoice(invoice, tokenStore, options));
|
|
86
131
|
},
|
|
132
|
+
lookupPayment(paymentHash) {
|
|
133
|
+
return withLock(() => lookupMelt(paymentHash, tokenStore));
|
|
134
|
+
},
|
|
87
135
|
};
|
|
88
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Asks the mint about a melt whose proofs were reserved. An UNPAID quote
|
|
139
|
+
* returns the proofs to the spendable pool; a PAID one with a matching
|
|
140
|
+
* preimage forgets them.
|
|
141
|
+
*/
|
|
142
|
+
async function lookupMelt(paymentHash, tokenStore) {
|
|
143
|
+
const reserved = tokenStore.getReserved(paymentHash);
|
|
144
|
+
if (!reserved) {
|
|
145
|
+
return { state: 'pending', reason: 'No reserved Cashu melt matches this payment hash, so the mint cannot be asked about it.' };
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const { Wallet } = await import('@cashu/cashu-ts');
|
|
149
|
+
const wallet = new Wallet(reserved.mint, { unit: 'sat' });
|
|
150
|
+
const quote = await wallet.checkMeltQuoteBolt11(reserved.quoteId);
|
|
151
|
+
if (quote.state === 'PAID') {
|
|
152
|
+
const preimage = quote.payment_preimage ?? undefined;
|
|
153
|
+
if (preimage && verifyPreimage(preimage, paymentHash)) {
|
|
154
|
+
tokenStore.dropReserved(paymentHash);
|
|
155
|
+
return { state: 'settled', preimage: preimage.toLowerCase() };
|
|
156
|
+
}
|
|
157
|
+
return { state: 'pending', reason: 'The mint reports the melt as paid but gave no preimage that matches the invoice.' };
|
|
158
|
+
}
|
|
159
|
+
if (quote.state === 'UNPAID') {
|
|
160
|
+
tokenStore.releaseReserved(paymentHash);
|
|
161
|
+
return { state: 'failed', reason: 'The mint reports the melt as unpaid; the reserved proofs are spendable again.' };
|
|
162
|
+
}
|
|
163
|
+
return { state: 'pending', reason: 'The mint still reports the melt as pending.' };
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return { state: 'pending', reason: 'The mint could not be reached. Try again later.' };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
89
169
|
/**
|
|
90
170
|
* Encodes leftover proofs back into a Cashu token and adds them to the store.
|
|
91
171
|
* Handles both `keep` proofs (from wallet.send() coin selection) and `change`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cashu.js","sourceRoot":"","sources":["../../src/wallet/cashu.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cashu.js","sourceRoot":"","sources":["../../src/wallet/cashu.ts"],"names":[],"mappings":"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"}
|
|
@@ -134,18 +134,19 @@ export function createLnurlcashWallet(store, options = {}, lock) {
|
|
|
134
134
|
return { paid: false, method: METHOD, reason: 'Amountless BOLT-11 invoices require an explicit amount and are refused' };
|
|
135
135
|
}
|
|
136
136
|
// A reconcile can turn up a payment that landed after an earlier attempt
|
|
137
|
-
// gave up on it. That
|
|
138
|
-
// is
|
|
139
|
-
//
|
|
140
|
-
//
|
|
137
|
+
// gave up on it. That is said out loud here rather than only filed: the
|
|
138
|
+
// caller is a wallet asking to spend, and "by the way, that payment you
|
|
139
|
+
// wrote off did go through" changes what they do next. The preimage
|
|
140
|
+
// itself is a credential, so it stays in the store and out of tool
|
|
141
|
+
// output; l402-reconcile turns it into a stored credential.
|
|
141
142
|
let recoveredNote = '';
|
|
142
143
|
try {
|
|
143
144
|
const report = await ops.reconcile();
|
|
144
145
|
if (report.recovered.length > 0) {
|
|
145
146
|
const each = report.recovered
|
|
146
|
-
.map(m => `${m.paymentHashHex.slice(0, 12)}
|
|
147
|
-
.join('
|
|
148
|
-
recoveredNote = ` Also recovered ${report.recovered.length} earlier melt(s) that settled after being written off
|
|
147
|
+
.map(m => `${m.paymentHashHex.slice(0, 12)}…`)
|
|
148
|
+
.join(', ');
|
|
149
|
+
recoveredNote = ` Also recovered ${report.recovered.length} earlier melt(s) that settled after being written off (payment hash ${each}); call l402-reconcile with each payment hash to use it.`;
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
catch { /* best effort; selection below simply sees fewer notes */ }
|
|
@@ -198,6 +199,23 @@ export function createLnurlcashWallet(store, options = {}, lock) {
|
|
|
198
199
|
payInvoice(invoice, options) {
|
|
199
200
|
return withLock(() => doPayInvoice(invoice, options));
|
|
200
201
|
},
|
|
202
|
+
lookupPayment(paymentHash) {
|
|
203
|
+
return withLock(async () => {
|
|
204
|
+
try {
|
|
205
|
+
await ops.reconcile();
|
|
206
|
+
}
|
|
207
|
+
catch { /* the stored record below still counts */ }
|
|
208
|
+
const settled = store.settledMelts().find(m => m.paymentHashHex === paymentHash);
|
|
209
|
+
if (settled)
|
|
210
|
+
return { state: 'settled', preimage: settled.preimage };
|
|
211
|
+
return {
|
|
212
|
+
state: 'pending',
|
|
213
|
+
reason: store.byState('melting').some(n => n.paymentHashHex === paymentHash)
|
|
214
|
+
? 'The mint has not yet settled the melt for this payment.'
|
|
215
|
+
: 'No settlement has been recovered for this payment. Check with the mint, or supply the preimage.',
|
|
216
|
+
};
|
|
217
|
+
});
|
|
218
|
+
},
|
|
201
219
|
};
|
|
202
220
|
}
|
|
203
221
|
//# sourceMappingURL=lnurlcash.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lnurlcash.js","sourceRoot":"","sources":["../../src/wallet/lnurlcash.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"lnurlcash.js","sourceRoot":"","sources":["../../src/wallet/lnurlcash.ts"],"names":[],"mappings":"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"}
|
package/build/wallet/nwc.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { NwcClient, NwcError, inspectNwcConnection } from '@forgesworn/nwc-kit';
|
|
2
2
|
import { tryDecodeBolt11, verifyPreimage } from 'farrier-kit';
|
|
3
|
+
/**
|
|
4
|
+
* nwc-kit raises these before a request is published (connection parsing,
|
|
5
|
+
* capability discovery, method and encryption checks, request validation), so
|
|
6
|
+
* the wallet never saw a payment and none can have been made.
|
|
7
|
+
*/
|
|
8
|
+
const PRE_PUBLICATION_FAILURES = {
|
|
9
|
+
INVALID_CONNECTION: 'The NWC connection URI is invalid.',
|
|
10
|
+
INFO_UNAVAILABLE: 'The NWC wallet published no signed capability event on its relays. Check that the wallet is online and the connection lists the right relays.',
|
|
11
|
+
UNSUPPORTED_ENCRYPTION: 'This NWC wallet does not support NIP-44 v2 encryption, which 402-mcp requires.',
|
|
12
|
+
UNSUPPORTED_METHOD: 'This NWC connection does not permit pay_invoice.',
|
|
13
|
+
UNSUPPORTED_EXTENSION: 'This NWC wallet lacks an extension the request needs.',
|
|
14
|
+
INVALID_REQUEST: 'The NWC payment request was invalid.',
|
|
15
|
+
};
|
|
3
16
|
/**
|
|
4
17
|
* Creates a Nostr Wallet Connect provider that reports success only after an
|
|
5
18
|
* authenticated wallet response and independent BOLT-11 settlement proof.
|
|
@@ -28,7 +41,7 @@ export function createNwcWallet(nwcUri, clientOptions = {}) {
|
|
|
28
41
|
paid: false,
|
|
29
42
|
method: 'nwc',
|
|
30
43
|
outcome: 'unknown',
|
|
31
|
-
reason: 'NWC wallet responded but settlement could not be proven.
|
|
44
|
+
reason: 'NWC wallet responded but settlement could not be proven. Call l402-reconcile with this payment hash before paying this service again.',
|
|
32
45
|
};
|
|
33
46
|
}
|
|
34
47
|
return { paid: true, preimage: paid.preimage, method: 'nwc' };
|
|
@@ -38,12 +51,16 @@ export function createNwcWallet(nwcUri, clientOptions = {}) {
|
|
|
38
51
|
if (error.code === 'WALLET_ERROR') {
|
|
39
52
|
return { paid: false, method: 'nwc', reason: error.message };
|
|
40
53
|
}
|
|
54
|
+
const preflight = PRE_PUBLICATION_FAILURES[error.code];
|
|
55
|
+
if (preflight) {
|
|
56
|
+
return { paid: false, method: 'nwc', reason: `${preflight} Nothing was sent to the wallet, so no payment was made.` };
|
|
57
|
+
}
|
|
41
58
|
if (['PUBLISH_FAILED', 'RESPONSE_TIMEOUT', 'REQUEST_ABORTED', 'CLIENT_CLOSED', 'INVALID_RESPONSE'].includes(error.code)) {
|
|
42
59
|
return {
|
|
43
60
|
paid: false,
|
|
44
61
|
method: 'nwc',
|
|
45
62
|
outcome: 'unknown',
|
|
46
|
-
reason: 'NWC payment outcome is unknown.
|
|
63
|
+
reason: 'NWC payment outcome is unknown. Call l402-reconcile with this payment hash before paying this service again.',
|
|
47
64
|
};
|
|
48
65
|
}
|
|
49
66
|
}
|
|
@@ -53,13 +70,44 @@ export function createNwcWallet(nwcUri, clientOptions = {}) {
|
|
|
53
70
|
paid: false,
|
|
54
71
|
method: 'nwc',
|
|
55
72
|
outcome: 'unknown',
|
|
56
|
-
reason: 'NWC payment outcome is unknown.
|
|
73
|
+
reason: 'NWC payment outcome is unknown. Call l402-reconcile with this payment hash before paying this service again.',
|
|
57
74
|
};
|
|
58
75
|
}
|
|
59
76
|
finally {
|
|
60
77
|
client?.close();
|
|
61
78
|
}
|
|
62
79
|
},
|
|
80
|
+
async lookupPayment(paymentHash) {
|
|
81
|
+
let client;
|
|
82
|
+
try {
|
|
83
|
+
client = new NwcClient(nwcUri, clientOptions);
|
|
84
|
+
const tx = await client.lookupInvoice({ payment_hash: paymentHash });
|
|
85
|
+
if (tx.state === 'settled' && tx.preimage && verifyPreimage(tx.preimage, paymentHash)) {
|
|
86
|
+
return { state: 'settled', preimage: tx.preimage.toLowerCase() };
|
|
87
|
+
}
|
|
88
|
+
if (tx.state === 'failed' || tx.state === 'expired') {
|
|
89
|
+
return { state: 'failed', reason: `The wallet reports the payment as ${tx.state}.` };
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
state: 'pending',
|
|
93
|
+
reason: tx.state === 'settled'
|
|
94
|
+
? 'The wallet reports the payment as settled but gave no preimage that matches the invoice.'
|
|
95
|
+
: `The wallet reports the payment as ${tx.state ?? 'in an unknown state'}.`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (error instanceof NwcError && error.code === 'UNSUPPORTED_METHOD') {
|
|
100
|
+
return { state: 'pending', reason: 'This NWC wallet does not support lookup_invoice. Check the payment in the wallet itself.' };
|
|
101
|
+
}
|
|
102
|
+
if (error instanceof NwcError && error.code === 'WALLET_ERROR') {
|
|
103
|
+
return { state: 'pending', reason: 'The wallet could not look this payment up. Check it in the wallet itself.' };
|
|
104
|
+
}
|
|
105
|
+
return { state: 'pending', reason: 'The NWC wallet could not be reached. Try again later.' };
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
client?.close();
|
|
109
|
+
}
|
|
110
|
+
},
|
|
63
111
|
};
|
|
64
112
|
}
|
|
65
113
|
//# sourceMappingURL=nwc.js.map
|
package/build/wallet/nwc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nwc.js","sourceRoot":"","sources":["../../src/wallet/nwc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAE/E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAG7D;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,gBAAkC,EAAE;IAClF,2EAA2E;IAC3E,4DAA4D;IAC5D,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAC5B,OAAO;QACL,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,IAAI;QAEf,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,QAA4B;YAC5D,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;YACxC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAA;YAC1E,CAAC;YACD,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;gBACjC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,wEAAwE,EAAE,CAAA;YACzH,CAAC;YAED,IAAI,MAA6B,CAAA;YACjC,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;gBAC7C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;gBACjD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;oBAC3D,OAAO;wBACL,IAAI,EAAE,KAAK;wBACX,MAAM,EAAE,KAAK;wBACb,OAAO,EAAE,SAAS;wBAClB,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"nwc.js","sourceRoot":"","sources":["../../src/wallet/nwc.ts"],"names":[],"mappings":"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"}
|
package/build/wallet/types.d.ts
CHANGED
|
@@ -16,8 +16,25 @@ export interface PaymentResult {
|
|
|
16
16
|
*/
|
|
17
17
|
verifyUrl?: string;
|
|
18
18
|
}
|
|
19
|
+
/** What a wallet can say, after the fact, about a payment it attempted. */
|
|
20
|
+
export type PaymentLookup = {
|
|
21
|
+
state: 'settled';
|
|
22
|
+
preimage: string;
|
|
23
|
+
} | {
|
|
24
|
+
state: 'failed';
|
|
25
|
+
reason?: string;
|
|
26
|
+
} | {
|
|
27
|
+
state: 'pending';
|
|
28
|
+
reason?: string;
|
|
29
|
+
};
|
|
19
30
|
export interface WalletProvider {
|
|
20
31
|
method: WalletMethod;
|
|
21
32
|
available: boolean;
|
|
22
33
|
payInvoice(invoice: string, options?: PayInvoiceOptions): Promise<PaymentResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Asks the wallet what became of an earlier payment. Only a preimage that
|
|
36
|
+
* hashes to `paymentHash` may be reported as settled, and only a wallet's
|
|
37
|
+
* definite answer as failed; anything else is pending.
|
|
38
|
+
*/
|
|
39
|
+
lookupPayment?(paymentHash: string): Promise<PaymentLookup>;
|
|
23
40
|
}
|
package/build/x402/parse.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Whether an asset's amount can be read straight from a USD price. */
|
|
2
|
+
export declare function isUsdStablecoin(asset: string): boolean;
|
|
1
3
|
export interface X402Challenge {
|
|
2
4
|
receiver: string;
|
|
3
5
|
network: string;
|
|
@@ -5,7 +7,7 @@ export interface X402Challenge {
|
|
|
5
7
|
amountUsd: number;
|
|
6
8
|
/** EVM chain ID for the network (e.g. 8453 for Base). */
|
|
7
9
|
chainId: number | null;
|
|
8
|
-
/** Amount in smallest asset unit (e.g. 1000000 for 1 USDC). */
|
|
10
|
+
/** Amount in smallest asset unit (e.g. 1000000 for 1 USDC); null unless the asset is a USD stablecoin. */
|
|
9
11
|
amountSmallestUnit: bigint | null;
|
|
10
12
|
}
|
|
11
13
|
/** Detects whether a 402 response contains an x402 challenge via the X-Payment-Required header. */
|
|
@@ -13,7 +15,17 @@ export declare function isX402Challenge(headers: Headers): boolean;
|
|
|
13
15
|
/**
|
|
14
16
|
* Parses an x402 challenge from the response body.
|
|
15
17
|
* Expected shape: `{ x402: { receiver, network, asset, amount_usd } }`.
|
|
18
|
+
*
|
|
19
|
+
* Experimental: this is a custom format, not the x402 specification, whose
|
|
20
|
+
* servers send a base64 `PAYMENT-REQUIRED` header. Real x402 services are not
|
|
21
|
+
* understood here.
|
|
16
22
|
*/
|
|
17
23
|
export declare function parseX402Challenge(body: unknown): X402Challenge | null;
|
|
18
|
-
/**
|
|
19
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Formerly built an EIP-681 link, but one with no token contract or amount
|
|
26
|
+
* sends the wrong asset or nothing at all. Kept so existing imports resolve.
|
|
27
|
+
*
|
|
28
|
+
* @deprecated Returns null. A correct link needs the token contract address,
|
|
29
|
+
* which the challenge does not carry.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildPaymentDeeplink(_challenge: X402Challenge): string | null;
|
package/build/x402/parse.js
CHANGED
|
@@ -7,13 +7,21 @@ const CHAIN_IDS = {
|
|
|
7
7
|
arbitrum: 42161,
|
|
8
8
|
polygon: 137,
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Decimal places for USD stablecoins, where a USD amount is also the token
|
|
12
|
+
* amount. Assets priced in anything else (ETH, for one) are left out: turning
|
|
13
|
+
* a USD figure into their smallest unit would need an exchange rate, and
|
|
14
|
+
* treating dollars as ether would ask for thousands of times the price.
|
|
15
|
+
*/
|
|
11
16
|
const ASSET_DECIMALS = {
|
|
12
17
|
usdc: 6,
|
|
13
18
|
usdt: 6,
|
|
14
19
|
dai: 18,
|
|
15
|
-
eth: 18,
|
|
16
20
|
};
|
|
21
|
+
/** Whether an asset's amount can be read straight from a USD price. */
|
|
22
|
+
export function isUsdStablecoin(asset) {
|
|
23
|
+
return asset.toLowerCase() in ASSET_DECIMALS;
|
|
24
|
+
}
|
|
17
25
|
const ETH_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
18
26
|
/** Detects whether a 402 response contains an x402 challenge via the X-Payment-Required header. */
|
|
19
27
|
export function isX402Challenge(headers) {
|
|
@@ -23,6 +31,10 @@ export function isX402Challenge(headers) {
|
|
|
23
31
|
/**
|
|
24
32
|
* Parses an x402 challenge from the response body.
|
|
25
33
|
* Expected shape: `{ x402: { receiver, network, asset, amount_usd } }`.
|
|
34
|
+
*
|
|
35
|
+
* Experimental: this is a custom format, not the x402 specification, whose
|
|
36
|
+
* servers send a base64 `PAYMENT-REQUIRED` header. Real x402 services are not
|
|
37
|
+
* understood here.
|
|
26
38
|
*/
|
|
27
39
|
export function parseX402Challenge(body) {
|
|
28
40
|
if (body === null || typeof body !== 'object')
|
|
@@ -59,12 +71,14 @@ export function parseX402Challenge(body) {
|
|
|
59
71
|
amountSmallestUnit,
|
|
60
72
|
};
|
|
61
73
|
}
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Formerly built an EIP-681 link, but one with no token contract or amount
|
|
76
|
+
* sends the wrong asset or nothing at all. Kept so existing imports resolve.
|
|
77
|
+
*
|
|
78
|
+
* @deprecated Returns null. A correct link needs the token contract address,
|
|
79
|
+
* which the challenge does not carry.
|
|
80
|
+
*/
|
|
81
|
+
export function buildPaymentDeeplink(_challenge) {
|
|
82
|
+
return null;
|
|
69
83
|
}
|
|
70
84
|
//# sourceMappingURL=parse.js.map
|
package/build/x402/parse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/x402/parse.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,MAAM,SAAS,GAA2B;IACxC,IAAI,EAAE,IAAI;IACV,cAAc,EAAE,KAAK;IACrB,QAAQ,EAAE,CAAC;IACX,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,KAAK;IACf,OAAO,EAAE,GAAG;CACb,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/x402/parse.ts"],"names":[],"mappings":"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"}
|
package/build/x402/payment.js
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isUsdStablecoin } from './parse.js';
|
|
2
2
|
/** Format the x402 challenge as a human-readable payment request for the agent to present. */
|
|
3
3
|
export function formatX402PaymentRequest(challenge) {
|
|
4
|
-
const
|
|
4
|
+
const asset = challenge.asset.toUpperCase();
|
|
5
|
+
// A USD price is a token amount only for a USD stablecoin. For anything
|
|
6
|
+
// else say it is a dollar value, not a quantity of the asset.
|
|
7
|
+
const price = isUsdStablecoin(challenge.asset)
|
|
8
|
+
? `${challenge.amountUsd} ${asset}`
|
|
9
|
+
: `$${challenge.amountUsd} (a USD value, payable in ${asset} at the current rate)`;
|
|
5
10
|
const json = {
|
|
6
11
|
status: 402,
|
|
7
12
|
protocol: 'x402',
|
|
8
13
|
receiver: challenge.receiver,
|
|
9
14
|
network: challenge.network,
|
|
10
|
-
asset
|
|
15
|
+
asset,
|
|
11
16
|
amountUsd: challenge.amountUsd,
|
|
12
17
|
...(challenge.chainId !== null ? { chainId: challenge.chainId } : {}),
|
|
13
|
-
|
|
14
|
-
message: `Payment required:
|
|
15
|
-
+ `Send to ${challenge.receiver}. `
|
|
18
|
+
experimental: 'x402 support is experimental and uses a custom format, not the x402 specification. Check the details with the service before paying.',
|
|
19
|
+
message: `Payment required: ${price} on ${challenge.network}. `
|
|
20
|
+
+ `Send to ${challenge.receiver} from your own wallet. `
|
|
16
21
|
+ `After payment, provide the transaction hash to retry the request.`,
|
|
17
22
|
};
|
|
18
23
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment.js","sourceRoot":"","sources":["../../src/x402/payment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"payment.js","sourceRoot":"","sources":["../../src/x402/payment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,8FAA8F;AAC9F,MAAM,UAAU,wBAAwB,CAAC,SAAwB;IAM/D,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAA;IAC3C,wEAAwE;IACxE,8DAA8D;IAC9D,MAAM,KAAK,GAAG,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC;QAC5C,CAAC,CAAC,GAAG,SAAS,CAAC,SAAS,IAAI,KAAK,EAAE;QACnC,CAAC,CAAC,IAAI,SAAS,CAAC,SAAS,6BAA6B,KAAK,uBAAuB,CAAA;IAEpF,MAAM,IAAI,GAA4B;QACpC,MAAM,EAAE,GAAG;QACX,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,SAAS,CAAC,QAAQ;QAC5B,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,KAAK;QACL,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,GAAG,CAAC,SAAS,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,YAAY,EAAE,sIAAsI;QACpJ,OAAO,EAAE,qBAAqB,KAAK,OAAO,SAAS,CAAC,OAAO,IAAI;cAC3D,WAAW,SAAS,CAAC,QAAQ,yBAAyB;cACtD,mEAAmE;KACxE,CAAA;IAED,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,IAAI,CAAC,OAAiB;KAChC,CAAA;AACH,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzC,CAAC"}
|