@piprail/sdk 2.16.2 → 3.1.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/CHANGELOG.md +448 -0
- package/README.md +1 -0
- package/dist/{algorand-Q3TUQLPK.cjs → algorand-4FTTEV7X.cjs} +212 -51
- package/dist/{algorand-25FMBCT3.js → algorand-KJ5XHSMT.js} +164 -3
- package/dist/{aptos-VBJONBFY.cjs → aptos-5QBXJ6NV.cjs} +255 -39
- package/dist/{aptos-SBV6SGDP.js → aptos-H5VLH2QL.js} +217 -1
- package/dist/{chunk-QONQSZHJ.cjs → chunk-6XTNI2OQ.cjs} +44 -44
- package/dist/{chunk-OXEFPLZA.cjs → chunk-6ZRAIQXF.cjs} +4 -4
- package/dist/chunk-GVCGUSTE.js +30 -0
- package/dist/{chunk-V2IJ5HUW.cjs → chunk-MZAJQYM3.cjs} +1 -0
- package/dist/chunk-MZXVXC3C.cjs +30 -0
- package/dist/{chunk-2CX7XRZK.js → chunk-TZDVZCTC.js} +1 -0
- package/dist/{chunk-C52H5TYB.js → chunk-YXBQKBDH.js} +2 -2
- package/dist/index.cjs +2906 -1262
- package/dist/index.d.cts +679 -21
- package/dist/index.d.ts +679 -21
- package/dist/index.js +2678 -1034
- package/dist/{ledger-Crc1bZox.d.cts → ledger-DkHUORUe.d.cts} +7 -0
- package/dist/{ledger-Crc1bZox.d.ts → ledger-DkHUORUe.d.ts} +7 -0
- package/dist/{near-OLKCMTBI.js → near-5X2CQGML.js} +197 -1
- package/dist/{near-5LTTDU6G.cjs → near-XSQXEIHT.cjs} +242 -46
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/{solana-AI2G7V33.cjs → solana-TIEJV742.cjs} +218 -53
- package/dist/{solana-HTKDRTD3.js → solana-WRXL54MR.js} +174 -9
- package/dist/{stellar-E2KWEV2E.cjs → stellar-5GMZJBTA.cjs} +200 -30
- package/dist/{stellar-EUFZLX6J.js → stellar-YQLOIFDD.js} +172 -2
- package/dist/{sui-KCIITCYH.js → sui-JFQSDNSZ.js} +165 -3
- package/dist/{sui-Q3NJOJZS.cjs → sui-WIZEAO7E.cjs} +185 -23
- package/dist/{ton-J7TQWRN4.cjs → ton-AGTKLQA5.cjs} +264 -22
- package/dist/{ton-WH2JVQOO.js → ton-OZKFNRLT.js} +244 -2
- package/dist/{tron-FXBXDNEY.js → tron-HG3IOOCG.js} +283 -1
- package/dist/{tron-HIPMOX7S.cjs → tron-S4WX7OHY.cjs} +323 -41
- package/dist/{xrpl-RUOB37QH.js → xrpl-5K444RGX.js} +238 -6
- package/dist/{xrpl-SVVS445B.cjs → xrpl-G2FKFXRI.cjs} +289 -57
- package/package.json +12 -2
- package/dist/{chunk-QU25LSVS.js → chunk-5GRBEMCA.js} +44 -44
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
+
var _chunkMZXVXC3Ccjs = require('./chunk-MZXVXC3C.cjs');
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
|
|
@@ -8,7 +9,11 @@
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var _chunk6XTNI2OQcjs = require('./chunk-6XTNI2OQ.cjs');
|
|
12
17
|
|
|
13
18
|
// src/drivers/solana/index.ts
|
|
14
19
|
var _web3js = require('@solana/web3.js');
|
|
@@ -102,6 +107,148 @@ async function paySolana(params) {
|
|
|
102
107
|
return signature;
|
|
103
108
|
}
|
|
104
109
|
|
|
110
|
+
// src/drivers/solana/swap.ts
|
|
111
|
+
|
|
112
|
+
var JUPITER_API = "https://lite-api.jup.ag/swap/v1";
|
|
113
|
+
var WSOL_MINT = "So11111111111111111111111111111111111111112";
|
|
114
|
+
function sourceFor(platformFee) {
|
|
115
|
+
const charged = platformFee != null && !(typeof platformFee === "object" && Object.keys(platformFee).length === 0);
|
|
116
|
+
return {
|
|
117
|
+
kind: "provider",
|
|
118
|
+
name: "Jupiter",
|
|
119
|
+
note: "Third-party Solana DEX aggregator (lite-api.jup.ag), used keyless. It routes and builds the transaction; your own key signs it and Jupiter never holds your funds. " + (charged ? `\u26A0\uFE0F THIS QUOTE CARRIES A PLATFORM FEE: ${JSON.stringify(platformFee)}. PipRail did not set one.` : "This quote carries no platform fee, and PipRail adds none.")
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function mintFor(t) {
|
|
123
|
+
return t.asset === "native" ? WSOL_MINT : t.asset;
|
|
124
|
+
}
|
|
125
|
+
function side(t, amount) {
|
|
126
|
+
const decimals = t.asset === "native" ? SOL_DECIMALS : t.decimals;
|
|
127
|
+
return {
|
|
128
|
+
asset: t.asset,
|
|
129
|
+
symbol: _nullishCoalesce(t.symbol, () => ( (t.asset === "native" ? "SOL" : t.asset))),
|
|
130
|
+
decimals,
|
|
131
|
+
amount: amount.toString(),
|
|
132
|
+
amountFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, amount, decimals)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
async function getJson(url, init) {
|
|
136
|
+
const ctrl = new AbortController();
|
|
137
|
+
const timer = setTimeout(() => ctrl.abort(), 1e4);
|
|
138
|
+
try {
|
|
139
|
+
const res = await fetch(url, { ..._nullishCoalesce(init, () => ( {})), signal: ctrl.signal });
|
|
140
|
+
if (!res.ok) return null;
|
|
141
|
+
return await res.json();
|
|
142
|
+
} catch (e2) {
|
|
143
|
+
return null;
|
|
144
|
+
} finally {
|
|
145
|
+
clearTimeout(timer);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async function quoteSolanaSwap(p) {
|
|
149
|
+
if (p.wantAmount <= 0n) return null;
|
|
150
|
+
const inputMint = mintFor(p.from);
|
|
151
|
+
const outputMint = mintFor(p.to);
|
|
152
|
+
if (inputMint === outputMint) return null;
|
|
153
|
+
const url = `${JUPITER_API}/quote?inputMint=${inputMint}&outputMint=${outputMint}&amount=${p.wantAmount.toString()}&swapMode=ExactOut&slippageBps=${p.slippageBps}`;
|
|
154
|
+
const q = await getJson(url);
|
|
155
|
+
if (!_optionalChain([q, 'optionalAccess', _ => _.otherAmountThreshold]) || !q.inAmount) return null;
|
|
156
|
+
if (q.swapMode !== "ExactOut") return null;
|
|
157
|
+
if (q.outAmount !== p.wantAmount.toString()) return null;
|
|
158
|
+
let spend;
|
|
159
|
+
let maxSpend;
|
|
160
|
+
try {
|
|
161
|
+
spend = BigInt(q.inAmount);
|
|
162
|
+
const jupCap = BigInt(q.otherAmountThreshold);
|
|
163
|
+
const ourCap = _chunkMZXVXC3Ccjs.applySlippage.call(void 0, spend, p.slippageBps);
|
|
164
|
+
maxSpend = jupCap > ourCap ? jupCap : ourCap;
|
|
165
|
+
} catch (e3) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
if (spend <= 0n) return null;
|
|
169
|
+
const fromDecimals = p.from.asset === "native" ? SOL_DECIMALS : p.from.decimals;
|
|
170
|
+
return {
|
|
171
|
+
source: sourceFor(q.platformFee),
|
|
172
|
+
network: p.network,
|
|
173
|
+
from: side(p.from, spend),
|
|
174
|
+
to: side(p.to, p.wantAmount),
|
|
175
|
+
maxSpend: maxSpend.toString(),
|
|
176
|
+
maxSpendFormatted: _chunk6XTNI2OQcjs.formatUnits.call(void 0, maxSpend, fromDecimals),
|
|
177
|
+
slippageBps: p.slippageBps,
|
|
178
|
+
// Jupiter needs its own quote object back verbatim to build the transaction.
|
|
179
|
+
route: q
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
async function swapSolana(p) {
|
|
183
|
+
const { connection, keypair, quote } = p;
|
|
184
|
+
const jupQuote = quote.route;
|
|
185
|
+
if (!_optionalChain([jupQuote, 'optionalAccess', _2 => _2.otherAmountThreshold])) {
|
|
186
|
+
throw new Error("Solana: swap quote is missing its Jupiter routing data \u2014 re-quote before swapping.");
|
|
187
|
+
}
|
|
188
|
+
const built = await getJson(`${JUPITER_API}/swap`, {
|
|
189
|
+
method: "POST",
|
|
190
|
+
headers: { "content-type": "application/json" },
|
|
191
|
+
body: JSON.stringify({
|
|
192
|
+
quoteResponse: jupQuote,
|
|
193
|
+
userPublicKey: keypair.publicKey.toBase58(),
|
|
194
|
+
// Let Jupiter create + close the wrapped-SOL account in the same transaction,
|
|
195
|
+
// so a SOL leg needs no separate setup step from the caller.
|
|
196
|
+
wrapAndUnwrapSol: true,
|
|
197
|
+
dynamicComputeUnitLimit: true
|
|
198
|
+
})
|
|
199
|
+
});
|
|
200
|
+
if (!_optionalChain([built, 'optionalAccess', _3 => _3.swapTransaction])) {
|
|
201
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
202
|
+
"Jupiter could not build this swap transaction (no route, or the market moved). Nothing was spent \u2014 re-quote and retry."
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
let tx;
|
|
206
|
+
try {
|
|
207
|
+
tx = _web3js.VersionedTransaction.deserialize(Buffer.from(built.swapTransaction, "base64"));
|
|
208
|
+
} catch (cause) {
|
|
209
|
+
throw new Error("Solana: Jupiter returned a transaction this SDK could not decode.", { cause });
|
|
210
|
+
}
|
|
211
|
+
tx.sign([keypair]);
|
|
212
|
+
try {
|
|
213
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
214
|
+
const sig = await connection.sendRawTransaction(tx.serialize(), {
|
|
215
|
+
skipPreflight: false,
|
|
216
|
+
maxRetries: 3
|
|
217
|
+
});
|
|
218
|
+
const conf = await connection.confirmTransaction(
|
|
219
|
+
{ signature: sig, blockhash, lastValidBlockHeight },
|
|
220
|
+
"confirmed"
|
|
221
|
+
);
|
|
222
|
+
if (_optionalChain([conf, 'optionalAccess', _4 => _4.value, 'optionalAccess', _5 => _5.err])) {
|
|
223
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
224
|
+
`Solana swap failed on-chain (tx ${sig}): ${JSON.stringify(conf.value.err)}. Nothing was swapped. The usual cause is slippage \u2014 re-quote and retry.`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
transaction: sig,
|
|
229
|
+
network: quote.network,
|
|
230
|
+
source: quote.source,
|
|
231
|
+
from: quote.from,
|
|
232
|
+
to: quote.to
|
|
233
|
+
};
|
|
234
|
+
} catch (err) {
|
|
235
|
+
const msg = String(_nullishCoalesce(_optionalChain([err, 'optionalAccess', _6 => _6.message]), () => ( err)));
|
|
236
|
+
if (/insufficient|0x1\b/i.test(msg)) {
|
|
237
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
238
|
+
`Solana swap failed: the wallet can't cover it (token balance, or SOL for fees and rent). (${msg.slice(0, 160)})`,
|
|
239
|
+
{ cause: err }
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
if (/slippage|0x1771/i.test(msg)) {
|
|
243
|
+
throw new (0, _chunk6XTNI2OQcjs.InsufficientFundsError)(
|
|
244
|
+
"Solana swap refused: the price moved past your slippage cap, so nothing was spent. Re-quote and retry, or raise slippageBps.",
|
|
245
|
+
{ cause: err }
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
throw err;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
105
252
|
// src/drivers/solana/verify.ts
|
|
106
253
|
async function verifySolana(params) {
|
|
107
254
|
const { connection, signature, accept } = params;
|
|
@@ -112,7 +259,7 @@ async function verifySolana(params) {
|
|
|
112
259
|
commitment: "confirmed",
|
|
113
260
|
maxSupportedTransactionVersion: 0
|
|
114
261
|
});
|
|
115
|
-
} catch (
|
|
262
|
+
} catch (e4) {
|
|
116
263
|
return notFound(signature);
|
|
117
264
|
}
|
|
118
265
|
if (!tx) return notFound(signature);
|
|
@@ -171,7 +318,7 @@ async function verifySolana(params) {
|
|
|
171
318
|
for (const p of post) {
|
|
172
319
|
if (p.mint !== mint || p.owner !== accept.payTo) continue;
|
|
173
320
|
const before = pre.find((x) => x.accountIndex === p.accountIndex);
|
|
174
|
-
delta += BigInt(p.uiTokenAmount.amount) - BigInt(_nullishCoalesce(_optionalChain([before, 'optionalAccess',
|
|
321
|
+
delta += BigInt(p.uiTokenAmount.amount) - BigInt(_nullishCoalesce(_optionalChain([before, 'optionalAccess', _7 => _7.uiTokenAmount, 'access', _8 => _8.amount]), () => ( "0")));
|
|
175
322
|
}
|
|
176
323
|
if (delta < required) {
|
|
177
324
|
return {
|
|
@@ -229,15 +376,15 @@ var MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 100000n;
|
|
|
229
376
|
var CB_SET_UNIT_LIMIT = 2;
|
|
230
377
|
var CB_SET_UNIT_PRICE = 3;
|
|
231
378
|
function tokenProgramFor(accept) {
|
|
232
|
-
return _optionalChain([accept, 'access',
|
|
379
|
+
return _optionalChain([accept, 'access', _9 => _9.extra, 'optionalAccess', _10 => _10.tokenProgram]) === "token-2022" ? _spltoken.TOKEN_2022_PROGRAM_ID : _spltoken.TOKEN_PROGRAM_ID;
|
|
233
380
|
}
|
|
234
381
|
async function readMintDecimals(connection, mint) {
|
|
235
382
|
try {
|
|
236
383
|
const info = await connection.getAccountInfo(mint);
|
|
237
|
-
const data = _optionalChain([info, 'optionalAccess',
|
|
384
|
+
const data = _optionalChain([info, 'optionalAccess', _11 => _11.data]);
|
|
238
385
|
if (!data || data.length < 45) return void 0;
|
|
239
386
|
return data[44];
|
|
240
|
-
} catch (
|
|
387
|
+
} catch (e5) {
|
|
241
388
|
return void 0;
|
|
242
389
|
}
|
|
243
390
|
}
|
|
@@ -246,8 +393,8 @@ function isEmptySig(sig) {
|
|
|
246
393
|
}
|
|
247
394
|
function memoRandomNonce() {
|
|
248
395
|
const g = globalThis.crypto;
|
|
249
|
-
if (!_optionalChain([g, 'optionalAccess',
|
|
250
|
-
throw new (0,
|
|
396
|
+
if (!_optionalChain([g, 'optionalAccess', _12 => _12.getRandomValues])) {
|
|
397
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
251
398
|
"this runtime lacks Web Crypto (globalThis.crypto.getRandomValues); SVM exact needs a CSPRNG nonce."
|
|
252
399
|
);
|
|
253
400
|
}
|
|
@@ -256,10 +403,10 @@ function memoRandomNonce() {
|
|
|
256
403
|
return Buffer.from([...raw].map((b) => b.toString(16).padStart(2, "0")).join(""), "utf8");
|
|
257
404
|
}
|
|
258
405
|
function memoDataFor(accept) {
|
|
259
|
-
if (_optionalChain([accept, 'access',
|
|
406
|
+
if (_optionalChain([accept, 'access', _13 => _13.extra, 'optionalAccess', _14 => _14.memo]) !== void 0) {
|
|
260
407
|
const bytes = Buffer.from(accept.extra.memo, "utf8");
|
|
261
408
|
if (bytes.length > MAX_MEMO_BYTES) {
|
|
262
|
-
throw new (0,
|
|
409
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
263
410
|
`SVM exact: extra.memo is ${bytes.length} bytes; the scheme caps it at ${MAX_MEMO_BYTES}.`
|
|
264
411
|
);
|
|
265
412
|
}
|
|
@@ -273,13 +420,13 @@ function memoInstruction(accept) {
|
|
|
273
420
|
async function payExactSolana(input) {
|
|
274
421
|
const { connection, keypair, accept } = input;
|
|
275
422
|
if (accept.asset === "native") {
|
|
276
|
-
throw new (0,
|
|
423
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
277
424
|
"SVM exact is SPL-token only (TransferChecked); native SOL is not exact-payable. Pay via onchain-proof."
|
|
278
425
|
);
|
|
279
426
|
}
|
|
280
427
|
const extra = _nullishCoalesce(accept.extra, () => ( {}));
|
|
281
428
|
if (!extra.feePayer) {
|
|
282
|
-
throw new (0,
|
|
429
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)("SVM exact rail must advertise extra.feePayer (the merchant sponsor key).");
|
|
283
430
|
}
|
|
284
431
|
let feePayer;
|
|
285
432
|
let mint;
|
|
@@ -289,24 +436,24 @@ async function payExactSolana(input) {
|
|
|
289
436
|
mint = new (0, _web3js.PublicKey)(accept.asset);
|
|
290
437
|
payTo = new (0, _web3js.PublicKey)(accept.payTo);
|
|
291
438
|
} catch (err) {
|
|
292
|
-
throw new (0,
|
|
439
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
293
440
|
`SVM exact: bad feePayer/asset/payTo (${err instanceof Error ? err.message : String(err)}).`
|
|
294
441
|
);
|
|
295
442
|
}
|
|
296
443
|
const onChainDecimals = await readMintDecimals(connection, mint);
|
|
297
444
|
const decimals = _nullishCoalesce(onChainDecimals, () => ( extra.decimals));
|
|
298
445
|
if (decimals === void 0) {
|
|
299
|
-
throw new (0,
|
|
446
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
300
447
|
`SVM exact: couldn't read the decimals of mint ${accept.asset} on-chain, and the rail states none. Retry with a reliable rpcUrl \u2014 TransferChecked cannot be built without them.`
|
|
301
448
|
);
|
|
302
449
|
}
|
|
303
450
|
if (onChainDecimals !== void 0 && extra.decimals !== void 0 && extra.decimals !== onChainDecimals) {
|
|
304
|
-
throw new (0,
|
|
451
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
305
452
|
`SVM exact: the rail states ${extra.decimals} decimals for ${accept.asset} but the mint says ${onChainDecimals} \u2014 refusing to sign (a mismatch this size misprices the transfer).`
|
|
306
453
|
);
|
|
307
454
|
}
|
|
308
455
|
if (feePayer.equals(payTo)) {
|
|
309
|
-
throw new (0,
|
|
456
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
310
457
|
"SVM exact: the fee payer must differ from payTo \u2014 payTo appears in the transfer instruction, which the fee payer must not (a scheme MUST-rule). Use a separate relayer key for the gate."
|
|
311
458
|
);
|
|
312
459
|
}
|
|
@@ -316,11 +463,11 @@ async function payExactSolana(input) {
|
|
|
316
463
|
let destInfo = "unknown";
|
|
317
464
|
try {
|
|
318
465
|
destInfo = await input.connection.getAccountInfo(dest);
|
|
319
|
-
} catch (
|
|
466
|
+
} catch (e6) {
|
|
320
467
|
destInfo = "unknown";
|
|
321
468
|
}
|
|
322
469
|
if (destInfo === null) {
|
|
323
|
-
throw new (0,
|
|
470
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)(
|
|
324
471
|
`SVM exact: the recipient's token account for ${mint.toBase58()} doesn't exist yet \u2014 the exact rail can't create it. Pay via onchain-proof (which creates it), or have ${payTo.toBase58()} create its associated token account first.`
|
|
325
472
|
);
|
|
326
473
|
}
|
|
@@ -352,11 +499,11 @@ async function payExactSolana(input) {
|
|
|
352
499
|
tx.sign([keypair]);
|
|
353
500
|
const buyerIndex = message.staticAccountKeys.findIndex((k) => k.equals(keypair.publicKey));
|
|
354
501
|
if (buyerIndex < 1 || buyerIndex >= message.header.numRequiredSignatures) {
|
|
355
|
-
throw new (0,
|
|
502
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)("SVM exact: could not locate the buyer signer slot.");
|
|
356
503
|
}
|
|
357
504
|
const buyerSig = tx.signatures[buyerIndex];
|
|
358
505
|
if (!buyerSig || isEmptySig(buyerSig)) {
|
|
359
|
-
throw new (0,
|
|
506
|
+
throw new (0, _chunk6XTNI2OQcjs.UnsupportedSchemeError)("SVM exact: the wallet did not produce a buyer signature.");
|
|
360
507
|
}
|
|
361
508
|
const transaction = Buffer.from(tx.serialize()).toString("base64");
|
|
362
509
|
return {
|
|
@@ -380,18 +527,18 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
380
527
|
try {
|
|
381
528
|
payTo = new (0, _web3js.PublicKey)(accept.payTo);
|
|
382
529
|
mint = new (0, _web3js.PublicKey)(accept.asset);
|
|
383
|
-
if (!_optionalChain([accept, 'access',
|
|
530
|
+
if (!_optionalChain([accept, 'access', _15 => _15.extra, 'optionalAccess', _16 => _16.feePayer])) throw new Error("rail is missing extra.feePayer");
|
|
384
531
|
railFeePayer = new (0, _web3js.PublicKey)(accept.extra.feePayer);
|
|
385
532
|
} catch (err) {
|
|
386
|
-
throw new (0,
|
|
533
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(`SVM exact: rail has a bad payTo/asset/feePayer (${err instanceof Error ? err.message : String(err)}).`);
|
|
387
534
|
}
|
|
388
535
|
if (!railFeePayer.equals(feePayerKeypair.publicKey)) {
|
|
389
|
-
throw new (0,
|
|
536
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(
|
|
390
537
|
"SVM exact: the gate relayer key does not match the rail extra.feePayer \u2014 misconfigured rail."
|
|
391
538
|
);
|
|
392
539
|
}
|
|
393
540
|
if (feePayerKeypair.publicKey.equals(payTo)) {
|
|
394
|
-
throw new (0,
|
|
541
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)("SVM exact: the fee payer must differ from payTo \u2014 misconfigured rail.");
|
|
395
542
|
}
|
|
396
543
|
const program = tokenProgramFor(accept);
|
|
397
544
|
let tx;
|
|
@@ -410,7 +557,7 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
410
557
|
try {
|
|
411
558
|
;
|
|
412
559
|
({ value } = await connection.getAddressLookupTable(lookup.accountKey));
|
|
413
|
-
} catch (
|
|
560
|
+
} catch (e7) {
|
|
414
561
|
return fail("tx_not_found", `Could not read lookup table ${lookup.accountKey.toBase58()} (transient RPC) \u2014 retry.`);
|
|
415
562
|
}
|
|
416
563
|
if (!value) {
|
|
@@ -432,7 +579,7 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
432
579
|
return fail("signature_invalid", "The fee payer is invoked as a program.");
|
|
433
580
|
}
|
|
434
581
|
for (const i of ix.accountKeyIndexes) {
|
|
435
|
-
if (_optionalChain([keys, 'access',
|
|
582
|
+
if (_optionalChain([keys, 'access', _17 => _17.get, 'call', _18 => _18(i), 'optionalAccess', _19 => _19.equals, 'call', _20 => _20(feePayerKey)])) {
|
|
436
583
|
return fail("signature_invalid", "The fee payer appears in an instruction account list (would risk a fund drain).");
|
|
437
584
|
}
|
|
438
585
|
}
|
|
@@ -481,14 +628,14 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
481
628
|
}),
|
|
482
629
|
program
|
|
483
630
|
);
|
|
484
|
-
} catch (
|
|
631
|
+
} catch (e8) {
|
|
485
632
|
continue;
|
|
486
633
|
}
|
|
487
634
|
if (!decoded.keys.mint.pubkey.equals(mint)) continue;
|
|
488
635
|
if (!decoded.keys.destination.pubkey.equals(expectedDest)) {
|
|
489
636
|
return fail("wrong_recipient", `A transfer pays ${decoded.keys.destination.pubkey.toBase58()}, not payTo's ATA ${expectedDest.toBase58()}.`);
|
|
490
637
|
}
|
|
491
|
-
if (_optionalChain([accept, 'access',
|
|
638
|
+
if (_optionalChain([accept, 'access', _21 => _21.extra, 'optionalAccess', _22 => _22.decimals]) !== void 0 && decoded.data.decimals !== accept.extra.decimals) {
|
|
492
639
|
return fail("transfer_not_found", `Transfer decimals ${decoded.data.decimals} \u2260 rail decimals ${accept.extra.decimals}.`);
|
|
493
640
|
}
|
|
494
641
|
sawTransferToPayTo = true;
|
|
@@ -533,7 +680,7 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
533
680
|
} catch (err) {
|
|
534
681
|
const msg = err instanceof Error ? err.message : String(err);
|
|
535
682
|
if (/blockhash|block height|expired/i.test(msg)) return fail("payment_expired", `Settle broadcast rejected \u2014 blockhash expired: ${shorten(msg)}.`);
|
|
536
|
-
throw new (0,
|
|
683
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(
|
|
537
684
|
`SVM exact settle: the merchant fee payer failed to broadcast (${shorten(msg)}). The buyer's signed transaction is still valid \u2014 fund/fix the fee payer and the buyer can re-present it.`,
|
|
538
685
|
{ cause: err }
|
|
539
686
|
);
|
|
@@ -543,7 +690,7 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
543
690
|
return fail("tx_reverted", `Settle tx ${txid} reverted on-chain (a post-simulate race).`);
|
|
544
691
|
}
|
|
545
692
|
if (confirmed === "timeout") {
|
|
546
|
-
throw new (0,
|
|
693
|
+
throw new (0, _chunk6XTNI2OQcjs.SettlementError)(
|
|
547
694
|
`SVM exact settle: broadcast ${txid} but it did not confirm in time. It likely landed \u2014 re-verify by signature before re-presenting; do NOT re-pay.`
|
|
548
695
|
);
|
|
549
696
|
}
|
|
@@ -569,7 +716,7 @@ async function pollConfirmed(connection, signature) {
|
|
|
569
716
|
try {
|
|
570
717
|
const { value } = await connection.getSignatureStatuses([signature], { searchTransactionHistory: true });
|
|
571
718
|
info = value[0];
|
|
572
|
-
} catch (
|
|
719
|
+
} catch (e9) {
|
|
573
720
|
info = null;
|
|
574
721
|
}
|
|
575
722
|
if (info) {
|
|
@@ -586,18 +733,18 @@ async function pollConfirmed(connection, signature) {
|
|
|
586
733
|
|
|
587
734
|
function toKeypair(wallet, network) {
|
|
588
735
|
if (typeof wallet !== "object" || wallet === null) {
|
|
589
|
-
throw new (0,
|
|
736
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
590
737
|
`chain ${network} is Solana; wallet must be { key } (base58 secret) or { signer }.`
|
|
591
738
|
);
|
|
592
739
|
}
|
|
593
|
-
|
|
740
|
+
_chunk6XTNI2OQcjs.assertNoLegacyWalletKey.call(void 0, wallet, "Solana");
|
|
594
741
|
if ("signer" in wallet) {
|
|
595
742
|
return wallet.signer;
|
|
596
743
|
}
|
|
597
744
|
if ("key" in wallet) {
|
|
598
745
|
const sk = wallet.key;
|
|
599
746
|
if (typeof sk === "string" && sk.startsWith("0x")) {
|
|
600
|
-
throw new (0,
|
|
747
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
601
748
|
`chain ${network} is Solana, but the wallet { key } is a 0x\u2026 hex key \u2014 that's an EVM key. A Solana key is a base58 secret string (or a 64-byte Uint8Array).`
|
|
602
749
|
);
|
|
603
750
|
}
|
|
@@ -605,17 +752,18 @@ function toKeypair(wallet, network) {
|
|
|
605
752
|
const bytes = typeof sk === "string" ? _bs582.default.decode(sk) : sk;
|
|
606
753
|
return _web3js.Keypair.fromSecretKey(bytes);
|
|
607
754
|
} catch (err) {
|
|
608
|
-
throw new (0,
|
|
755
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
609
756
|
`chain ${network} is Solana; the wallet { key } isn't a valid Solana secret (expected a base58 secret string or a 64-byte Uint8Array): ${err instanceof Error ? err.message : String(err)}.`
|
|
610
757
|
);
|
|
611
758
|
}
|
|
612
759
|
}
|
|
613
|
-
throw new (0,
|
|
760
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
614
761
|
`chain ${network} is Solana; wallet must be { key } (base58 secret) or { signer }.`
|
|
615
762
|
);
|
|
616
763
|
}
|
|
617
764
|
|
|
618
765
|
// src/drivers/solana/index.ts
|
|
766
|
+
var RENT_EXEMPT_MIN_LAMPORTS = 890880n;
|
|
619
767
|
var solanaDriver = {
|
|
620
768
|
family: "solana",
|
|
621
769
|
resolve(opts) {
|
|
@@ -639,15 +787,15 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
639
787
|
const info = preset.tokens[token.toUpperCase()];
|
|
640
788
|
if (!info) {
|
|
641
789
|
const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
|
|
642
|
-
throw new (0,
|
|
790
|
+
throw new (0, _chunk6XTNI2OQcjs.UnknownTokenError)(
|
|
643
791
|
`token "${token}" isn't built in for Solana (known: ${known}). Pass { mint, decimals } instead, or use 'native'.`
|
|
644
792
|
);
|
|
645
793
|
}
|
|
646
794
|
return { asset: info.mint, decimals: info.decimals, symbol: info.symbol };
|
|
647
795
|
}
|
|
648
|
-
|
|
796
|
+
_chunk6XTNI2OQcjs.rejectForeignToken.call(void 0, token, "solana", network);
|
|
649
797
|
if (!("mint" in token)) {
|
|
650
|
-
throw new (0,
|
|
798
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
651
799
|
`chain ${network} is Solana; a custom token must be { mint, decimals }.`
|
|
652
800
|
);
|
|
653
801
|
}
|
|
@@ -666,14 +814,14 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
666
814
|
},
|
|
667
815
|
assertValidPayTo(payTo) {
|
|
668
816
|
if (payTo.startsWith("0x")) {
|
|
669
|
-
throw new (0,
|
|
817
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
670
818
|
`chain ${network} is Solana, but payTo "${payTo}" looks like an EVM address.`
|
|
671
819
|
);
|
|
672
820
|
}
|
|
673
821
|
try {
|
|
674
822
|
new (0, _web3js.PublicKey)(payTo);
|
|
675
|
-
} catch (
|
|
676
|
-
throw new (0,
|
|
823
|
+
} catch (e10) {
|
|
824
|
+
throw new (0, _chunk6XTNI2OQcjs.WrongFamilyError)(
|
|
677
825
|
`chain ${network} is Solana, but payTo "${payTo}" is not a base58 address.`
|
|
678
826
|
);
|
|
679
827
|
}
|
|
@@ -685,7 +833,7 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
685
833
|
try {
|
|
686
834
|
return await paySolana({ connection, keypair: wallet._native, accept });
|
|
687
835
|
} catch (err) {
|
|
688
|
-
throw _nullishCoalesce(
|
|
836
|
+
throw _nullishCoalesce(_chunk6XTNI2OQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
689
837
|
}
|
|
690
838
|
},
|
|
691
839
|
async confirm(ref) {
|
|
@@ -696,19 +844,19 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
696
844
|
});
|
|
697
845
|
info = value[0];
|
|
698
846
|
} catch (err) {
|
|
699
|
-
throw new (0,
|
|
847
|
+
throw new (0, _chunk6XTNI2OQcjs.ConfirmationTimeoutError)(
|
|
700
848
|
`Solana payment ${ref} could not be confirmed (RPC read failed).`,
|
|
701
849
|
{ cause: err }
|
|
702
850
|
);
|
|
703
851
|
}
|
|
704
852
|
if (!info || info.err || info.confirmationStatus !== "confirmed" && info.confirmationStatus !== "finalized") {
|
|
705
|
-
throw new (0,
|
|
853
|
+
throw new (0, _chunk6XTNI2OQcjs.ConfirmationTimeoutError)(`Solana payment ${ref} did not confirm in time.`);
|
|
706
854
|
}
|
|
707
855
|
return { height: String(info.slot) };
|
|
708
856
|
},
|
|
709
857
|
async estimateCost(accept) {
|
|
710
858
|
if (accept.scheme === "exact") {
|
|
711
|
-
return
|
|
859
|
+
return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
|
|
712
860
|
symbol: "SOL",
|
|
713
861
|
decimals: SOL_DECIMALS,
|
|
714
862
|
fee: 0n,
|
|
@@ -718,7 +866,7 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
718
866
|
}
|
|
719
867
|
const base = 5000n;
|
|
720
868
|
if (accept.asset === "native") {
|
|
721
|
-
return
|
|
869
|
+
return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
|
|
722
870
|
symbol: "SOL",
|
|
723
871
|
decimals: SOL_DECIMALS,
|
|
724
872
|
fee: base,
|
|
@@ -727,7 +875,7 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
727
875
|
});
|
|
728
876
|
}
|
|
729
877
|
const ataRent = 2039280n;
|
|
730
|
-
return
|
|
878
|
+
return _chunk6XTNI2OQcjs.nativeCost.call(void 0, {
|
|
731
879
|
symbol: "SOL",
|
|
732
880
|
decimals: SOL_DECIMALS,
|
|
733
881
|
fee: base + ataRent,
|
|
@@ -735,15 +883,25 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
735
883
|
detail: "1 signature + recipient token-account rent (~0.00204 SOL, if not already created)"
|
|
736
884
|
});
|
|
737
885
|
},
|
|
886
|
+
/** The bound wallet's own address — where THIS wallet gets paid. Derived from the key
|
|
887
|
+
* material only: no RPC, nothing moved. See {@link ResolvedNetwork.addressOf}. */
|
|
888
|
+
async addressOf(wallet) {
|
|
889
|
+
return wallet._native.publicKey.toBase58();
|
|
890
|
+
},
|
|
738
891
|
async balanceOf(wallet, asset) {
|
|
739
892
|
const owner = wallet._native.publicKey;
|
|
740
893
|
const native = await connection.getBalance(owner).then((n) => BigInt(n)).catch(() => null);
|
|
741
|
-
if (asset === "native")
|
|
894
|
+
if (asset === "native") {
|
|
895
|
+
if (native === null) return { token: null, native };
|
|
896
|
+
const reserve = await connection.getMinimumBalanceForRentExemption(0).then((n) => BigInt(n)).catch(() => RENT_EXEMPT_MIN_LAMPORTS);
|
|
897
|
+
const spendable = native > reserve ? native - reserve : 0n;
|
|
898
|
+
return { token: spendable, native };
|
|
899
|
+
}
|
|
742
900
|
let token;
|
|
743
901
|
try {
|
|
744
902
|
const mint = new (0, _web3js.PublicKey)(asset);
|
|
745
903
|
const info = await connection.getAccountInfo(mint);
|
|
746
|
-
const programId = _optionalChain([info, 'optionalAccess',
|
|
904
|
+
const programId = _optionalChain([info, 'optionalAccess', _23 => _23.owner, 'access', _24 => _24.equals, 'call', _25 => _25(_spltoken.TOKEN_2022_PROGRAM_ID)]) ? _spltoken.TOKEN_2022_PROGRAM_ID : _spltoken.TOKEN_PROGRAM_ID;
|
|
747
905
|
const ata = _spltoken.getAssociatedTokenAddressSync.call(void 0, mint, owner, false, programId);
|
|
748
906
|
token = (await _spltoken.getAccount.call(void 0, connection, ata, "confirmed", programId)).amount;
|
|
749
907
|
} catch (e) {
|
|
@@ -764,6 +922,13 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
764
922
|
async recipientReady() {
|
|
765
923
|
return { ready: "n/a" };
|
|
766
924
|
},
|
|
925
|
+
/* ---- swap (OPTIONAL, opt-in): via Jupiter, keyless + no platform fee. See ./swap.ts ---- */
|
|
926
|
+
async quoteSwap({ from, to, wantAmount, slippageBps }) {
|
|
927
|
+
return quoteSolanaSwap({ network, from, to, wantAmount, slippageBps });
|
|
928
|
+
},
|
|
929
|
+
async swap(wallet, quote) {
|
|
930
|
+
return swapSolana({ connection, keypair: wallet._native, quote });
|
|
931
|
+
},
|
|
767
932
|
async verify(ref, accept) {
|
|
768
933
|
return verifySolana({ connection, signature: ref, accept });
|
|
769
934
|
},
|
|
@@ -801,14 +966,14 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
801
966
|
if (!fp) return null;
|
|
802
967
|
try {
|
|
803
968
|
new (0, _web3js.PublicKey)(fp);
|
|
804
|
-
} catch (
|
|
969
|
+
} catch (e11) {
|
|
805
970
|
return null;
|
|
806
971
|
}
|
|
807
972
|
let tokenProgram = "spl-token";
|
|
808
973
|
try {
|
|
809
974
|
const info = await connection.getAccountInfo(new (0, _web3js.PublicKey)(asset));
|
|
810
|
-
if (_optionalChain([info, 'optionalAccess',
|
|
811
|
-
} catch (
|
|
975
|
+
if (_optionalChain([info, 'optionalAccess', _26 => _26.owner, 'access', _27 => _27.equals, 'call', _28 => _28(_spltoken.TOKEN_2022_PROGRAM_ID)])) tokenProgram = "token-2022";
|
|
976
|
+
} catch (e12) {
|
|
812
977
|
}
|
|
813
978
|
return { method: "svm", extra: { feePayer: fp, tokenProgram } };
|
|
814
979
|
}
|