@palmyr/cli 1.0.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 +731 -0
- package/dist/admin-auth.d.ts +1 -0
- package/dist/admin-auth.js +52 -0
- package/dist/admin-auth.js.map +1 -0
- package/dist/app.d.ts +182 -0
- package/dist/app.js +218 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +3495 -0
- package/dist/cli.js.map +1 -0
- package/dist/compute-ssh.d.ts +246 -0
- package/dist/compute-ssh.js +577 -0
- package/dist/compute-ssh.js.map +1 -0
- package/dist/config.d.ts +46 -0
- package/dist/config.js +183 -0
- package/dist/config.js.map +1 -0
- package/dist/credential-store.d.ts +4 -0
- package/dist/credential-store.js +180 -0
- package/dist/credential-store.js.map +1 -0
- package/dist/mascot-data.d.ts +1 -0
- package/dist/mascot-data.js +14 -0
- package/dist/mascot-data.js.map +1 -0
- package/dist/pay.d.ts +60 -0
- package/dist/pay.js +483 -0
- package/dist/pay.js.map +1 -0
- package/dist/sdk.d.ts +259 -0
- package/dist/sdk.js +944 -0
- package/dist/sdk.js.map +1 -0
- package/dist/social-queue.d.ts +125 -0
- package/dist/social-queue.js +340 -0
- package/dist/social-queue.js.map +1 -0
- package/dist/social-vault.d.ts +118 -0
- package/dist/social-vault.js +268 -0
- package/dist/social-vault.js.map +1 -0
- package/dist/social-worker.d.ts +43 -0
- package/dist/social-worker.js +155 -0
- package/dist/social-worker.js.map +1 -0
- package/dist/totp.d.ts +2 -0
- package/dist/totp.js +46 -0
- package/dist/totp.js.map +1 -0
- package/dist/ui.d.ts +77 -0
- package/dist/ui.js +441 -0
- package/dist/ui.js.map +1 -0
- package/dist/vault.d.ts +65 -0
- package/dist/vault.js +455 -0
- package/dist/vault.js.map +1 -0
- package/package.json +75 -0
package/dist/pay.js
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 payment handler for Palmyr CLI
|
|
3
|
+
* Supports both Solana (SPL USDC transfer) and Base/EVM (EIP-3009 TransferWithAuthorization).
|
|
4
|
+
* Both flows are gasless: the server/facilitator absorbs chain fees.
|
|
5
|
+
*/
|
|
6
|
+
import { createRequire } from 'module';
|
|
7
|
+
import { loadKeypair, loadConfig, log } from './config.js';
|
|
8
|
+
import { getVaultSolanaKeypair, getVaultEvmWallet, hasVaultWallets, listVaultWallets } from './vault.js';
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
// Solana constants
|
|
11
|
+
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
|
|
12
|
+
const TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';
|
|
13
|
+
const ASSOCIATED_TOKEN_PROGRAM = 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL';
|
|
14
|
+
const COMPUTE_BUDGET = 'ComputeBudget111111111111111111111111111111';
|
|
15
|
+
const MEMO_PROGRAM = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
|
|
16
|
+
const SOLANA_RPC = process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com';
|
|
17
|
+
// Base constants
|
|
18
|
+
const BASE_USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
19
|
+
const BASE_CHAIN_ID = 8453;
|
|
20
|
+
/**
|
|
21
|
+
* Parse a 402 response. Returns available payment options by chain plus the
|
|
22
|
+
* top-level `resource` block so callers can echo it into the PaymentPayload.
|
|
23
|
+
*/
|
|
24
|
+
export function parsePaymentRequired(data) {
|
|
25
|
+
const accepts = data.accepts || [];
|
|
26
|
+
const sol = accepts.find((a) => a.network?.startsWith('solana:'));
|
|
27
|
+
const evm = accepts.find((a) => a.network?.startsWith('eip155:'));
|
|
28
|
+
return {
|
|
29
|
+
solana: sol ? {
|
|
30
|
+
amount: BigInt(sol.amount),
|
|
31
|
+
payTo: sol.payTo,
|
|
32
|
+
feePayer: sol.extra?.feePayer || '',
|
|
33
|
+
asset: sol.asset || USDC_MINT,
|
|
34
|
+
network: sol.network,
|
|
35
|
+
requirements: sol,
|
|
36
|
+
} : null,
|
|
37
|
+
base: evm ? {
|
|
38
|
+
amount: BigInt(evm.amount),
|
|
39
|
+
payTo: evm.payTo,
|
|
40
|
+
feePayer: '', // facilitator handles gas
|
|
41
|
+
asset: evm.asset || BASE_USDC,
|
|
42
|
+
network: evm.network,
|
|
43
|
+
requirements: evm,
|
|
44
|
+
} : null,
|
|
45
|
+
resource: data.resource,
|
|
46
|
+
extensions: data.extensions,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the Solana payer keypair. Prefers a vault wallet (Palmyr native,
|
|
51
|
+
* BIP-39 encrypted, requires passphrase) and falls back to a legacy keyfile.
|
|
52
|
+
*
|
|
53
|
+
* Vault wallet selection order:
|
|
54
|
+
* 1. walletId argument (explicit)
|
|
55
|
+
* 2. config.defaultPayWalletId
|
|
56
|
+
* 3. PALMYR_PAY_WALLET env var
|
|
57
|
+
* 4. First vault wallet with a Solana address
|
|
58
|
+
*
|
|
59
|
+
* Passphrase resolution:
|
|
60
|
+
* 1. passphrase argument (explicit)
|
|
61
|
+
* 2. PALMYR_WALLET_PASSPHRASE env var
|
|
62
|
+
*/
|
|
63
|
+
function resolvePayerKeypair(walletId, passphrase) {
|
|
64
|
+
const cfg = loadConfig();
|
|
65
|
+
const pass = passphrase || process.env.PALMYR_WALLET_PASSPHRASE;
|
|
66
|
+
// Try the vault first (session secret from OS cred store, falls back to passphrase)
|
|
67
|
+
if (hasVaultWallets()) {
|
|
68
|
+
const targetId = walletId || cfg.defaultPayWalletId || process.env.PALMYR_PAY_WALLET;
|
|
69
|
+
try {
|
|
70
|
+
if (targetId)
|
|
71
|
+
return getVaultSolanaKeypair(targetId, pass);
|
|
72
|
+
const wallets = listVaultWallets();
|
|
73
|
+
const first = wallets.find(w => w.solanaAddress);
|
|
74
|
+
if (first)
|
|
75
|
+
return getVaultSolanaKeypair(first.id, pass);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.error(` Vault wallet load failed: ${err.message}`);
|
|
79
|
+
// Fall through to keyfile
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Fall back to the legacy keyfile flow
|
|
83
|
+
const keypairBytes = loadKeypair();
|
|
84
|
+
if (!keypairBytes)
|
|
85
|
+
return null;
|
|
86
|
+
const { Keypair } = require('@solana/web3.js');
|
|
87
|
+
return Keypair.fromSecretKey(keypairBytes);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build and partially sign a USDC transfer transaction for x402 payment.
|
|
91
|
+
* Uses raw keypair for transaction building (needed for multi-instruction Solana txs).
|
|
92
|
+
*/
|
|
93
|
+
export async function buildPaymentTransaction(payTo, amount, feePayer, walletId, passphrase) {
|
|
94
|
+
const payer = resolvePayerKeypair(walletId, passphrase);
|
|
95
|
+
if (!payer) {
|
|
96
|
+
console.error(' No wallet configured. Create one with: palmyr wallet create');
|
|
97
|
+
console.error(' Or configure a keyfile: palmyr setup --keyfile /path/to/keypair.json');
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
// Dynamic import to keep CLI fast when payment isn't needed
|
|
101
|
+
const { Connection, PublicKey, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = await import('@solana/web3.js');
|
|
102
|
+
const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint } = await import('@solana/spl-token');
|
|
103
|
+
const connection = new Connection(SOLANA_RPC, 'confirmed');
|
|
104
|
+
const payerPub = payer.publicKey;
|
|
105
|
+
const feePayerPub = new PublicKey(feePayer);
|
|
106
|
+
const recipientPub = new PublicKey(payTo);
|
|
107
|
+
const mintPub = new PublicKey(USDC_MINT);
|
|
108
|
+
// Get token accounts
|
|
109
|
+
const sourceAta = await getAssociatedTokenAddress(mintPub, payerPub);
|
|
110
|
+
const destAta = await getAssociatedTokenAddress(mintPub, recipientPub);
|
|
111
|
+
// Get mint info for decimals
|
|
112
|
+
const mintInfo = await getMint(connection, mintPub);
|
|
113
|
+
// Build transfer instruction
|
|
114
|
+
const transferIx = createTransferCheckedInstruction(sourceAta, mintPub, destAta, payerPub, amount, mintInfo.decimals);
|
|
115
|
+
// Compute budget
|
|
116
|
+
const computeLimitIx = ComputeBudgetProgram.setComputeUnitLimit({ units: 20000 });
|
|
117
|
+
const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 });
|
|
118
|
+
// Memo for uniqueness
|
|
119
|
+
const memoIx = {
|
|
120
|
+
keys: [],
|
|
121
|
+
programId: new PublicKey(MEMO_PROGRAM),
|
|
122
|
+
data: Buffer.from(crypto.getRandomValues(new Uint8Array(16)).reduce((s, b) => s + b.toString(16).padStart(2, '0'), ''))
|
|
123
|
+
};
|
|
124
|
+
// Get blockhash
|
|
125
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
126
|
+
// Build message with feePayer paying gas
|
|
127
|
+
const message = new TransactionMessage({
|
|
128
|
+
payerKey: feePayerPub,
|
|
129
|
+
recentBlockhash: blockhash,
|
|
130
|
+
instructions: [computeLimitIx, computePriceIx, transferIx, memoIx],
|
|
131
|
+
}).compileToV0Message();
|
|
132
|
+
const tx = new VersionedTransaction(message);
|
|
133
|
+
// Partially sign with our key (feePayer signs on the server)
|
|
134
|
+
tx.sign([payer]);
|
|
135
|
+
// Serialize to base64
|
|
136
|
+
const serialized = Buffer.from(tx.serialize()).toString('base64');
|
|
137
|
+
return {
|
|
138
|
+
transaction: serialized,
|
|
139
|
+
payer: payerPub.toBase58(),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Make a paid request: call endpoint → if 402 → build payment → retry with payment
|
|
144
|
+
*
|
|
145
|
+
* Passphrase resolution: explicit arg → PALMYR_WALLET_PASSPHRASE env var → fail
|
|
146
|
+
*/
|
|
147
|
+
/**
|
|
148
|
+
* Build and sign an EIP-3009 TransferWithAuthorization for Base USDC.
|
|
149
|
+
* The user signs a typed data message; the facilitator submits the on-chain call.
|
|
150
|
+
* Gasless for the user — no ETH required.
|
|
151
|
+
*/
|
|
152
|
+
async function buildEvmPaymentAuthorization(payTo, amount, walletId, passphrase) {
|
|
153
|
+
const cfg = loadConfig();
|
|
154
|
+
const targetId = walletId || cfg.defaultPayWalletId || process.env.PALMYR_PAY_WALLET;
|
|
155
|
+
if (!targetId)
|
|
156
|
+
return null;
|
|
157
|
+
let evmWallet;
|
|
158
|
+
try {
|
|
159
|
+
evmWallet = getVaultEvmWallet(targetId, passphrase);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
console.error(` Vault wallet load failed: ${err.message}`);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
const { ethers } = require('ethers');
|
|
166
|
+
// Random 32-byte nonce
|
|
167
|
+
const nonce = '0x' + Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString('hex');
|
|
168
|
+
const validAfter = 0;
|
|
169
|
+
const validBefore = Math.floor(Date.now() / 1000) + 3600; // 1 hour
|
|
170
|
+
// EIP-3009 TransferWithAuthorization for Base USDC (Circle USDC v2)
|
|
171
|
+
const domain = {
|
|
172
|
+
name: 'USD Coin',
|
|
173
|
+
version: '2',
|
|
174
|
+
chainId: BASE_CHAIN_ID,
|
|
175
|
+
verifyingContract: BASE_USDC,
|
|
176
|
+
};
|
|
177
|
+
const types = {
|
|
178
|
+
TransferWithAuthorization: [
|
|
179
|
+
{ name: 'from', type: 'address' },
|
|
180
|
+
{ name: 'to', type: 'address' },
|
|
181
|
+
{ name: 'value', type: 'uint256' },
|
|
182
|
+
{ name: 'validAfter', type: 'uint256' },
|
|
183
|
+
{ name: 'validBefore', type: 'uint256' },
|
|
184
|
+
{ name: 'nonce', type: 'bytes32' },
|
|
185
|
+
],
|
|
186
|
+
};
|
|
187
|
+
const message = {
|
|
188
|
+
from: evmWallet.address,
|
|
189
|
+
to: ethers.getAddress(payTo),
|
|
190
|
+
value: amount.toString(),
|
|
191
|
+
validAfter: validAfter.toString(),
|
|
192
|
+
validBefore: validBefore.toString(),
|
|
193
|
+
nonce,
|
|
194
|
+
};
|
|
195
|
+
const signature = await evmWallet.signTypedData(domain, types, message);
|
|
196
|
+
return {
|
|
197
|
+
signature,
|
|
198
|
+
authorization: {
|
|
199
|
+
from: evmWallet.address,
|
|
200
|
+
to: ethers.getAddress(payTo),
|
|
201
|
+
value: amount.toString(),
|
|
202
|
+
validAfter: validAfter.toString(),
|
|
203
|
+
validBefore: validBefore.toString(),
|
|
204
|
+
nonce,
|
|
205
|
+
},
|
|
206
|
+
payer: evmWallet.address,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Construct a spec-compliant x402 v2 PaymentPayload.
|
|
211
|
+
*
|
|
212
|
+
* The canonical shape (from `@x402/core` types — `PaymentPayload`) is:
|
|
213
|
+
*
|
|
214
|
+
* { x402Version, resource, accepted: <full PaymentRequirements>, payload, extensions? }
|
|
215
|
+
*
|
|
216
|
+
* Echoing the FULL `accepted` object (asset, amount, payTo, maxTimeoutSeconds,
|
|
217
|
+
* extra) and the top-level `resource` block is non-negotiable on the EVM/CDP
|
|
218
|
+
* facilitator path: Coinbase's API runs zod validation on `paymentPayload` and
|
|
219
|
+
* rejects stubbed `{ scheme, network }` inputs with `cdp_verify_failed`. Our
|
|
220
|
+
* own SVM verifier reads only `payload.transaction` and ignores `accepted`,
|
|
221
|
+
* which is why the bug only manifested on Base.
|
|
222
|
+
*
|
|
223
|
+
* `extensions` is preserved opportunistically — the spec marks it optional and
|
|
224
|
+
* some facilitators read flags out of it, so passing it through is harmless.
|
|
225
|
+
*/
|
|
226
|
+
function buildSpecCompliantPayload(opts) {
|
|
227
|
+
const out = {
|
|
228
|
+
x402Version: 2,
|
|
229
|
+
accepted: opts.requirements,
|
|
230
|
+
payload: opts.payload,
|
|
231
|
+
};
|
|
232
|
+
if (opts.resource !== undefined)
|
|
233
|
+
out.resource = opts.resource;
|
|
234
|
+
if (opts.extensions !== undefined)
|
|
235
|
+
out.extensions = opts.extensions;
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Like paidRequest, but returns the raw Response from the final paid call
|
|
240
|
+
* so the caller can consume a streaming body (e.g. text/event-stream for i402).
|
|
241
|
+
*
|
|
242
|
+
* The probe request is always issued without a payment header to elicit the
|
|
243
|
+
* server's 402 with proper payment-required metadata — this lets the server
|
|
244
|
+
* advertise the exact amount due (critical for i402 /chat/:id/execute which
|
|
245
|
+
* charges plan.total_cost_usdc rather than a fixed fee).
|
|
246
|
+
*/
|
|
247
|
+
export async function paidStreamRequest(api, method, path, body, passphrase) {
|
|
248
|
+
const probeOpts = {
|
|
249
|
+
method,
|
|
250
|
+
headers: { 'Content-Type': 'application/json', Accept: 'text/event-stream' },
|
|
251
|
+
};
|
|
252
|
+
if (body)
|
|
253
|
+
probeOpts.body = JSON.stringify(body);
|
|
254
|
+
const probeRes = await fetch(api + path, probeOpts);
|
|
255
|
+
if (probeRes.status !== 402) {
|
|
256
|
+
return { response: probeRes, paid: false, amountUsdc: 0 };
|
|
257
|
+
}
|
|
258
|
+
const probeData = await probeRes.json().catch(() => ({}));
|
|
259
|
+
const options = parsePaymentRequired(probeData);
|
|
260
|
+
const cfg = loadConfig();
|
|
261
|
+
const preferredChain = (cfg.defaultPayChain || 'solana');
|
|
262
|
+
const selected = preferredChain === 'base' ? options.base : options.solana;
|
|
263
|
+
if (!selected) {
|
|
264
|
+
throw new Error(`Server did not offer ${preferredChain} payment for streaming endpoint. ` +
|
|
265
|
+
`Received: ${JSON.stringify(probeData).slice(0, 200)}`);
|
|
266
|
+
}
|
|
267
|
+
const amountUsdc = Number(selected.amount) / 1e6;
|
|
268
|
+
let paymentPayload;
|
|
269
|
+
let payer;
|
|
270
|
+
if (preferredChain === 'base') {
|
|
271
|
+
const auth = await buildEvmPaymentAuthorization(selected.payTo, selected.amount, undefined, passphrase);
|
|
272
|
+
if (!auth)
|
|
273
|
+
throw new Error('Failed to build EVM payment authorization');
|
|
274
|
+
paymentPayload = buildSpecCompliantPayload({
|
|
275
|
+
payload: { signature: auth.signature, authorization: auth.authorization },
|
|
276
|
+
requirements: selected.requirements,
|
|
277
|
+
resource: options.resource,
|
|
278
|
+
extensions: options.extensions,
|
|
279
|
+
});
|
|
280
|
+
payer = auth.payer;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
const tx = await buildPaymentTransaction(selected.payTo, selected.amount, selected.feePayer, undefined, passphrase);
|
|
284
|
+
if (!tx)
|
|
285
|
+
throw new Error('Failed to build Solana payment transaction');
|
|
286
|
+
paymentPayload = buildSpecCompliantPayload({
|
|
287
|
+
payload: { transaction: tx.transaction },
|
|
288
|
+
requirements: selected.requirements,
|
|
289
|
+
resource: options.resource,
|
|
290
|
+
extensions: options.extensions,
|
|
291
|
+
});
|
|
292
|
+
payer = tx.payer;
|
|
293
|
+
}
|
|
294
|
+
const encoded = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
|
|
295
|
+
const paidOpts = {
|
|
296
|
+
method,
|
|
297
|
+
headers: {
|
|
298
|
+
'Content-Type': 'application/json',
|
|
299
|
+
Accept: 'text/event-stream',
|
|
300
|
+
// Spec header is `X-PAYMENT`; legacy `Payment-Signature` is sent for
|
|
301
|
+
// backward compat with our older server build (drops a release after
|
|
302
|
+
// both ends are confirmed on X-PAYMENT only).
|
|
303
|
+
'X-PAYMENT': encoded,
|
|
304
|
+
'Payment-Signature': encoded,
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
if (body)
|
|
308
|
+
paidOpts.body = JSON.stringify(body);
|
|
309
|
+
const paidRes = await fetch(api + path, paidOpts);
|
|
310
|
+
log(`stream payment: ${amountUsdc} USDC → ${path} on ${preferredChain} (payer: ${payer})`);
|
|
311
|
+
return { response: paidRes, paid: true, amountUsdc, payer };
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Detect transient Solana errors that warrant rebuilding the tx with a fresh
|
|
315
|
+
* blockhash and retrying. Most common: "Blockhash not found" (the blockhash
|
|
316
|
+
* we signed against expired in flight, ~60s window).
|
|
317
|
+
*/
|
|
318
|
+
function isTransientSolanaError(message) {
|
|
319
|
+
if (!message)
|
|
320
|
+
return false;
|
|
321
|
+
const m = message.toLowerCase();
|
|
322
|
+
return (m.includes('blockhash not found') ||
|
|
323
|
+
m.includes('block height exceeded') ||
|
|
324
|
+
m.includes('blockhashnotfound'));
|
|
325
|
+
}
|
|
326
|
+
export async function paidRequest(api, method, path, body, passphrase, attempt = 1) {
|
|
327
|
+
const opts = {
|
|
328
|
+
method,
|
|
329
|
+
headers: { 'Content-Type': 'application/json' },
|
|
330
|
+
};
|
|
331
|
+
const allowsBody = method !== 'GET' && method !== 'HEAD';
|
|
332
|
+
if (body && allowsBody)
|
|
333
|
+
opts.body = JSON.stringify(body);
|
|
334
|
+
// First attempt
|
|
335
|
+
const res = await fetch(api + path, opts);
|
|
336
|
+
const data = await res.json();
|
|
337
|
+
// Not a 402 — return as-is
|
|
338
|
+
if (res.status !== 402) {
|
|
339
|
+
if (data.error)
|
|
340
|
+
throw new Error(data.error);
|
|
341
|
+
return { data, paid: false };
|
|
342
|
+
}
|
|
343
|
+
// 402 — need to pay. Chain is decided by config — no silent fallback.
|
|
344
|
+
const options = parsePaymentRequired(data);
|
|
345
|
+
const cfg = loadConfig();
|
|
346
|
+
const preferredChain = (cfg.defaultPayChain || 'solana');
|
|
347
|
+
const selected = preferredChain === 'base' ? options.base : options.solana;
|
|
348
|
+
if (!selected) {
|
|
349
|
+
throw new Error(`Server did not offer ${preferredChain} as a payment option. ` +
|
|
350
|
+
`Either the endpoint doesn't support ${preferredChain} yet, or use: palmyr wallet use <ID> --chain ${preferredChain === 'base' ? 'solana' : 'base'}`);
|
|
351
|
+
}
|
|
352
|
+
const amountUsdc = Number(selected.amount) / 1e6;
|
|
353
|
+
let paymentPayload;
|
|
354
|
+
let payer;
|
|
355
|
+
// Only show the spinner when attached to an interactive terminal. Piped
|
|
356
|
+
// output (agents running in cron / Docker / pipelines) stays clean JSON.
|
|
357
|
+
const interactive = process.stdout.isTTY;
|
|
358
|
+
let spinner = null;
|
|
359
|
+
const chainLabel = preferredChain === 'base' ? 'Base (gasless)' : 'Solana';
|
|
360
|
+
if (interactive) {
|
|
361
|
+
const { Spinner } = await import('./ui.js');
|
|
362
|
+
spinner = new Spinner();
|
|
363
|
+
spinner.start(`Paying ${amountUsdc} USDC on ${chainLabel}`);
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
if (preferredChain === 'base') {
|
|
367
|
+
const auth = await buildEvmPaymentAuthorization(selected.payTo, selected.amount, undefined, passphrase);
|
|
368
|
+
if (!auth)
|
|
369
|
+
throw new Error('Failed to build EVM payment authorization — no wallet configured');
|
|
370
|
+
paymentPayload = buildSpecCompliantPayload({
|
|
371
|
+
payload: {
|
|
372
|
+
signature: auth.signature,
|
|
373
|
+
authorization: auth.authorization,
|
|
374
|
+
},
|
|
375
|
+
requirements: selected.requirements,
|
|
376
|
+
resource: options.resource,
|
|
377
|
+
extensions: options.extensions,
|
|
378
|
+
});
|
|
379
|
+
payer = auth.payer;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
const tx = await buildPaymentTransaction(selected.payTo, selected.amount, selected.feePayer, undefined, passphrase);
|
|
383
|
+
if (!tx)
|
|
384
|
+
throw new Error('Failed to build Solana payment transaction — no wallet configured');
|
|
385
|
+
paymentPayload = buildSpecCompliantPayload({
|
|
386
|
+
payload: { transaction: tx.transaction },
|
|
387
|
+
requirements: selected.requirements,
|
|
388
|
+
resource: options.resource,
|
|
389
|
+
extensions: options.extensions,
|
|
390
|
+
});
|
|
391
|
+
payer = tx.payer;
|
|
392
|
+
}
|
|
393
|
+
if (spinner)
|
|
394
|
+
spinner.update(`Waiting for server...`);
|
|
395
|
+
const chosenChain = preferredChain;
|
|
396
|
+
const encoded = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
|
|
397
|
+
const paidOpts = {
|
|
398
|
+
method,
|
|
399
|
+
headers: {
|
|
400
|
+
'Content-Type': 'application/json',
|
|
401
|
+
// Spec header is `X-PAYMENT`; legacy `Payment-Signature` kept for
|
|
402
|
+
// back-compat with older Palmyr server builds (drop a release after
|
|
403
|
+
// both ends are confirmed on X-PAYMENT only).
|
|
404
|
+
'X-PAYMENT': encoded,
|
|
405
|
+
'Payment-Signature': encoded,
|
|
406
|
+
},
|
|
407
|
+
};
|
|
408
|
+
if (body && allowsBody)
|
|
409
|
+
paidOpts.body = JSON.stringify(body);
|
|
410
|
+
const paidRes = await fetch(api + path, paidOpts);
|
|
411
|
+
// Some edge layers (Cloudflare, nginx) serve HTML error pages for
|
|
412
|
+
// upstream timeouts/5xx. Detect that before JSON.parse so the user sees
|
|
413
|
+
// "Server returned 504" instead of "Unexpected token '<'". Payment has
|
|
414
|
+
// likely already settled on-chain at this point — flag for manual review.
|
|
415
|
+
const paidContentType = paidRes.headers.get('content-type') || '';
|
|
416
|
+
let paidData;
|
|
417
|
+
if (paidContentType.includes('application/json')) {
|
|
418
|
+
paidData = await paidRes.json();
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
const text = await paidRes.text().catch(() => '');
|
|
422
|
+
throw new Error(`Payment was submitted but server returned ${paidRes.status} ${paidRes.statusText} ` +
|
|
423
|
+
`with non-JSON body (${paidContentType || 'no content-type'}). ` +
|
|
424
|
+
`Your payment may have settled on-chain — check your wallet and contact support with this domain before retrying. ` +
|
|
425
|
+
`First 200 chars: ${text.slice(0, 200)}`);
|
|
426
|
+
}
|
|
427
|
+
if (paidData.error) {
|
|
428
|
+
const detail = paidData.message && paidData.message !== paidData.error
|
|
429
|
+
? `${paidData.error}: ${paidData.message}`
|
|
430
|
+
: paidData.error;
|
|
431
|
+
// Transient Solana errors (blockhash expired etc.) self-heal with a
|
|
432
|
+
// rebuilt tx that picks up a fresh blockhash. Retry once before
|
|
433
|
+
// surfacing the failure to the user.
|
|
434
|
+
if (attempt < 2 && isTransientSolanaError(String(detail))) {
|
|
435
|
+
if (spinner)
|
|
436
|
+
spinner.update(`Retrying with fresh blockhash...`);
|
|
437
|
+
await new Promise(r => setTimeout(r, 500));
|
|
438
|
+
if (spinner)
|
|
439
|
+
spinner.cancel();
|
|
440
|
+
return paidRequest(api, method, path, body, passphrase, attempt + 1);
|
|
441
|
+
}
|
|
442
|
+
if (spinner)
|
|
443
|
+
spinner.cancel();
|
|
444
|
+
throw new Error(summarizeUpstreamError(detail));
|
|
445
|
+
}
|
|
446
|
+
if (spinner)
|
|
447
|
+
spinner.stop(`Paid ${amountUsdc} USDC on ${chainLabel}`, true);
|
|
448
|
+
log(`payment: ${amountUsdc} USDC → ${path} on ${chosenChain} (payer: ${payer})`);
|
|
449
|
+
return { data: paidData, paid: true, txHash: paidData.txHash };
|
|
450
|
+
}
|
|
451
|
+
catch (e) {
|
|
452
|
+
if (spinner)
|
|
453
|
+
spinner.cancel();
|
|
454
|
+
// Also retry on transient errors that surface as exceptions (network
|
|
455
|
+
// hiccups, RPC errors thrown before paidData parsing).
|
|
456
|
+
if (attempt < 2 && isTransientSolanaError(String(e?.message ?? e))) {
|
|
457
|
+
await new Promise(r => setTimeout(r, 500));
|
|
458
|
+
return paidRequest(api, method, path, body, passphrase, attempt + 1);
|
|
459
|
+
}
|
|
460
|
+
throw e;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
// Trim noisy upstream error bodies (HTML pages, multi-line stack-traces) into
|
|
464
|
+
// a single human-readable line. The full body is still available in logs.
|
|
465
|
+
function summarizeUpstreamError(raw) {
|
|
466
|
+
if (!raw)
|
|
467
|
+
return 'unknown error';
|
|
468
|
+
const s = String(raw);
|
|
469
|
+
// HTML page (e.g. nginx 401 / Cloudflare 502): extract <title> if present,
|
|
470
|
+
// otherwise strip tags and collapse whitespace.
|
|
471
|
+
if (/<html|<body/i.test(s)) {
|
|
472
|
+
const title = s.match(/<title>([^<]+)<\/title>/i);
|
|
473
|
+
if (title)
|
|
474
|
+
return title[1].trim();
|
|
475
|
+
const stripped = s.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
|
|
476
|
+
return stripped.length > 200 ? stripped.slice(0, 197) + '...' : stripped;
|
|
477
|
+
}
|
|
478
|
+
// Plain-text but excessively long: truncate.
|
|
479
|
+
if (s.length > 300)
|
|
480
|
+
return s.slice(0, 297) + '...';
|
|
481
|
+
return s;
|
|
482
|
+
}
|
|
483
|
+
//# sourceMappingURL=pay.js.map
|
package/dist/pay.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pay.js","sourceRoot":"","sources":["../pay.ts"],"names":[],"mappings":"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"}
|