@anywalletkit/protocol-swap2-jupiter 0.0.0-stage → 0.2.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.
Files changed (58) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +94 -2
  3. package/dist/activity.cjs +46 -0
  4. package/dist/activity.cjs.map +1 -0
  5. package/dist/activity.d.cts +14 -0
  6. package/dist/activity.d.ts +14 -0
  7. package/dist/activity.js +10 -0
  8. package/dist/activity.js.map +1 -0
  9. package/dist/chunk-5JXNDQHW.js +56 -0
  10. package/dist/chunk-5JXNDQHW.js.map +1 -0
  11. package/dist/chunk-5L7BPEQL.js +51 -0
  12. package/dist/chunk-5L7BPEQL.js.map +1 -0
  13. package/dist/chunk-H4SP5E76.js +20 -0
  14. package/dist/chunk-H4SP5E76.js.map +1 -0
  15. package/dist/chunk-NESHFKWY.js +240 -0
  16. package/dist/chunk-NESHFKWY.js.map +1 -0
  17. package/dist/chunk-OVLAYYGP.js +44 -0
  18. package/dist/chunk-OVLAYYGP.js.map +1 -0
  19. package/dist/chunk-RSAOKVP2.js +27 -0
  20. package/dist/chunk-RSAOKVP2.js.map +1 -0
  21. package/dist/codec.cjs +76 -0
  22. package/dist/codec.cjs.map +1 -0
  23. package/dist/codec.d.cts +27 -0
  24. package/dist/codec.d.ts +27 -0
  25. package/dist/codec.js +23 -0
  26. package/dist/codec.js.map +1 -0
  27. package/dist/config.cjs +64 -0
  28. package/dist/config.cjs.map +1 -0
  29. package/dist/config.d.cts +23 -0
  30. package/dist/config.d.ts +23 -0
  31. package/dist/config.js +31 -0
  32. package/dist/config.js.map +1 -0
  33. package/dist/index.cjs +390 -0
  34. package/dist/index.cjs.map +1 -0
  35. package/dist/index.d.cts +10 -0
  36. package/dist/index.d.ts +10 -0
  37. package/dist/index.js +70 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/protocol.cjs +362 -0
  40. package/dist/protocol.cjs.map +1 -0
  41. package/dist/protocol.d.cts +16 -0
  42. package/dist/protocol.d.ts +16 -0
  43. package/dist/protocol.js +12 -0
  44. package/dist/protocol.js.map +1 -0
  45. package/dist/provider.cjs +348 -0
  46. package/dist/provider.cjs.map +1 -0
  47. package/dist/provider.d.cts +20 -0
  48. package/dist/provider.d.ts +20 -0
  49. package/dist/provider.js +11 -0
  50. package/dist/provider.js.map +1 -0
  51. package/dist/transaction.cjs +75 -0
  52. package/dist/transaction.cjs.map +1 -0
  53. package/dist/transaction.d.cts +23 -0
  54. package/dist/transaction.d.ts +23 -0
  55. package/dist/transaction.js +9 -0
  56. package/dist/transaction.js.map +1 -0
  57. package/module.json +16 -0
  58. package/package.json +96 -3
@@ -0,0 +1,348 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/provider.ts
21
+ var provider_exports = {};
22
+ __export(provider_exports, {
23
+ jupiterProvider: () => jupiterProvider
24
+ });
25
+ module.exports = __toCommonJS(provider_exports);
26
+
27
+ // src/activity.ts
28
+ var import_activity = require("@anywalletkit/protocol-swap2-core/activity");
29
+
30
+ // src/config.ts
31
+ var import_swap2_assets = require("@anywalletkit/swap2-assets");
32
+ var JUPITER_API_DEFAULT = "https://api.jup.ag/swap/v2";
33
+ var JUPITER_PROGRAM = "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";
34
+ var COMPUTE_BUDGET_PROGRAM = "ComputeBudget111111111111111111111111111111";
35
+ var SYSTEM_PROGRAM = "11111111111111111111111111111111";
36
+ var TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
37
+ var TOKEN_2022_PROGRAM = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
38
+ var ATA_PROGRAM = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
39
+ var WSOL_MINT = "So11111111111111111111111111111111111111112";
40
+ var JUPITER_TX_PROGRAMS = /* @__PURE__ */ new Set([JUPITER_PROGRAM, COMPUTE_BUDGET_PROGRAM, SYSTEM_PROGRAM, TOKEN_PROGRAM, TOKEN_2022_PROGRAM, ATA_PROGRAM]);
41
+ var SOLANA_CAIP2 = "solana:mainnet";
42
+ var SOLANA_CHAINS = /* @__PURE__ */ new Set([SOLANA_CAIP2, "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"]);
43
+ var BASE58 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
44
+ var NATIVE = /* @__PURE__ */ new Set(["", "native", "sol", SYSTEM_PROGRAM, WSOL_MINT.toLowerCase(), "0x0000000000000000000000000000000000000000"]);
45
+ function jupiterMint(token) {
46
+ if (NATIVE.has(token.toLowerCase()) || /^0x0+$/.test(token)) return WSOL_MINT;
47
+ const bySymbol = (0, import_swap2_assets.ccAsset)(SOLANA_CAIP2, token);
48
+ if (bySymbol) return bySymbol.contract ?? WSOL_MINT;
49
+ const byMint = BASE58.test(token) ? (0, import_swap2_assets.ccAssetByToken)(SOLANA_CAIP2, token) : void 0;
50
+ if (byMint) return byMint.contract ?? WSOL_MINT;
51
+ return BASE58.test(token) ? token : null;
52
+ }
53
+ var jupiter = {
54
+ supportsChain: (chain) => chain === SOLANA_CAIP2,
55
+ supports: (from, to) => from === SOLANA_CAIP2 && to === SOLANA_CAIP2
56
+ };
57
+
58
+ // src/activity.ts
59
+ var JUPITER_MODULE = "@anywalletkit/protocol-swap2-jupiter";
60
+ function describeJupiterActivity(tx, ctx) {
61
+ if (!SOLANA_CHAINS.has(tx.chain) || tx.call?.to !== JUPITER_PROGRAM) return null;
62
+ const item = (0, import_activity.describeSwapLike)(tx, ctx, { protocol: JUPITER_MODULE, subtitle: "Jupiter", kind: "swap", counterparty: JUPITER_PROGRAM });
63
+ if (item && tx.status !== "failed" && (item.assetsIn.length === 0 || item.assetsOut.length === 0)) return null;
64
+ return item;
65
+ }
66
+
67
+ // src/codec.ts
68
+ var import_base = require("@scure/base");
69
+ var ROUTE_V2 = "bb64facc31c4af14";
70
+ var SHARED_ACCOUNTS_ROUTE_V2 = "d19853937cfed8e9";
71
+ var hex = (b) => Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
72
+ var u64 = (d, o) => new DataView(d.buffer, d.byteOffset + o, 8).getBigUint64(0, true);
73
+ var u16 = (d, o) => new DataView(d.buffer, d.byteOffset + o, 2).getUint16(0, true);
74
+ var fromBase64 = (s) => import_base.base64.decode(s);
75
+ function decodeSwapArgs(data) {
76
+ const disc = hex(data.subarray(0, 8));
77
+ const at = disc === ROUTE_V2 ? 8 : disc === SHARED_ACCOUNTS_ROUTE_V2 ? 9 : -1;
78
+ if (at < 0) throw new Error(`unsupported Jupiter instruction ${disc}`);
79
+ if (data.length < at + 22 + 4) throw new Error("Jupiter swap instruction is truncated");
80
+ return {
81
+ kind: at === 8 ? "route_v2" : "shared_accounts_route_v2",
82
+ inAmount: u64(data, at),
83
+ quotedOutAmount: u64(data, at + 8),
84
+ slippageBps: u16(data, at + 16),
85
+ platformFeeBps: u16(data, at + 18),
86
+ positiveSlippageBps: u16(data, at + 20)
87
+ };
88
+ }
89
+ function minOutOf(quotedOut, slippageBps) {
90
+ return quotedOut * BigInt(1e4 - slippageBps) / 10000n;
91
+ }
92
+ function decodeComputeBudget(data) {
93
+ if (data[0] === 2 && data.length === 5) return { limit: new DataView(data.buffer, data.byteOffset + 1, 4).getUint32(0, true) };
94
+ if (data[0] === 3 && data.length === 9) return { price: u64(data, 1) };
95
+ throw new Error(`unexpected compute-budget instruction ${data[0]}`);
96
+ }
97
+ function setComputeUnitLimit(units) {
98
+ const d = new Uint8Array(5);
99
+ d[0] = 2;
100
+ new DataView(d.buffer).setUint32(1, units, true);
101
+ return d;
102
+ }
103
+ function setComputeUnitPrice(microLamports) {
104
+ const d = new Uint8Array(9);
105
+ d[0] = 3;
106
+ new DataView(d.buffer).setBigUint64(1, microLamports, true);
107
+ return d;
108
+ }
109
+
110
+ // src/transaction.ts
111
+ var import_kit = require("@solana/kit");
112
+ var role = (a) => a.isSigner ? a.isWritable ? import_kit.AccountRole.WRITABLE_SIGNER : import_kit.AccountRole.READONLY_SIGNER : a.isWritable ? import_kit.AccountRole.WRITABLE : import_kit.AccountRole.READONLY;
113
+ var toInstruction = (ix) => ({
114
+ programAddress: (0, import_kit.address)(ix.programId),
115
+ accounts: ix.accounts.map((a) => ({ address: (0, import_kit.address)(a.pubkey), role: role(a) })),
116
+ data: fromBase64(ix.data)
117
+ });
118
+ function assembleTransaction(input) {
119
+ const budget = [
120
+ { programAddress: (0, import_kit.address)(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitLimit(input.computeUnitLimit) },
121
+ { programAddress: (0, import_kit.address)(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitPrice(input.computeUnitPrice) }
122
+ ];
123
+ const blockhash = typeof input.blockhash === "string" ? input.blockhash : (0, import_kit.getBase58Decoder)().decode(input.blockhash);
124
+ const tables = {};
125
+ for (const [table, list] of Object.entries(input.addressesByLookupTableAddress ?? {})) tables[(0, import_kit.address)(table)] = list.map((a) => (0, import_kit.address)(a));
126
+ const message = (0, import_kit.pipe)(
127
+ (0, import_kit.createTransactionMessage)({ version: 0 }),
128
+ (m) => (0, import_kit.setTransactionMessageFeePayer)((0, import_kit.address)(input.taker), m),
129
+ (m) => (0, import_kit.setTransactionMessageLifetimeUsingBlockhash)({ blockhash, lastValidBlockHeight: BigInt(input.lastValidBlockHeight) }, m),
130
+ (m) => (0, import_kit.appendTransactionMessageInstructions)([...budget, ...input.instructions.map(toInstruction)], m),
131
+ (m) => Object.keys(tables).length ? (0, import_kit.compressTransactionMessageUsingAddressLookupTables)(m, tables) : m
132
+ );
133
+ return (0, import_kit.getBase64EncodedWireTransaction)((0, import_kit.compileTransaction)(message));
134
+ }
135
+
136
+ // src/provider.ts
137
+ var import_util = require("@anywalletkit/protocol-swap2-core/util");
138
+ var DEFAULT_SLIPPAGE_BPS = 50;
139
+ var MAX_SLIPPAGE_BPS = 1e3;
140
+ var QUOTE_TTL_MS = 3e4;
141
+ var MAX_COMPUTE_UNITS = 14e5;
142
+ var DEFAULT_MAX_CU_PRICE = 2000000n;
143
+ var BASE_FEE_LAMPORTS = 5000n;
144
+ var DRY_TAKER = "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM";
145
+ var BASE582 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
146
+ var INTENT_PREFIX = "jup:";
147
+ function jupiterProvider(config = {}) {
148
+ config = Object.freeze({ ...config });
149
+ const base = (config.apiUrl ?? JUPITER_API_DEFAULT).replace(/\/$/, "");
150
+ const maxPrice = config.maxComputeUnitPrice ?? DEFAULT_MAX_CU_PRICE;
151
+ const rpcUrls = config.rpcUrls ?? [];
152
+ const get = async (path, signal) => {
153
+ for (let attempt = 0; ; attempt++) {
154
+ const res = await fetch(`${base}${path}`, { headers: { accept: "application/json", ...config.apiKey ? { "x-api-key": config.apiKey } : {} }, signal: signal ?? (0, import_util.timeoutSignal)(12e3) });
155
+ const body = await res.json().catch(() => null);
156
+ if (res.status === 429 && attempt === 0 && !signal?.aborted) {
157
+ const reset = Number(res.headers.get("x-ratelimit-reset"));
158
+ const wait = Number.isFinite(reset) && reset > 0 ? Math.min(3e3, Math.max(250, reset * 1e3 - Date.now())) : 1200;
159
+ await new Promise((r) => setTimeout(r, wait));
160
+ continue;
161
+ }
162
+ return { ok: res.ok, status: res.status, body };
163
+ }
164
+ };
165
+ const rpc = async (method, params) => {
166
+ let last = new Error("no Solana RPC configured");
167
+ for (const url of rpcUrls) {
168
+ try {
169
+ const res = await fetch(url, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }), signal: (0, import_util.timeoutSignal)(1e4) });
170
+ const body = await res.json();
171
+ if (body.error) throw new Error(body.error.message ?? "rpc error");
172
+ return body.result;
173
+ } catch (e) {
174
+ last = e;
175
+ }
176
+ }
177
+ throw last;
178
+ };
179
+ const vet = (b, want) => {
180
+ if (b.swapMode && b.swapMode !== "ExactIn") throw new Error(`swap mode ${b.swapMode}`);
181
+ if (b.inputMint !== want.inputMint || b.outputMint !== want.outputMint) throw new Error("the answer names other mints");
182
+ if (b.inAmount !== want.amountIn.toString()) throw new Error(`the answer spends ${b.inAmount}, not ${want.amountIn}`);
183
+ if (String(b.transactionVersion ?? "0") !== "0") throw new Error(`transaction version ${b.transactionVersion}`);
184
+ if (b.tipInstruction) throw new Error("unexpected tip instruction");
185
+ if (!b.swapInstruction) throw new Error("no swap instruction");
186
+ if (b.swapInstruction.programId !== JUPITER_PROGRAM) throw new Error(`swap instruction targets ${b.swapInstruction.programId}`);
187
+ const args = decodeSwapArgs(fromBase64(b.swapInstruction.data));
188
+ if (args.inAmount !== want.amountIn) throw new Error(`swap instruction spends ${args.inAmount}, not ${want.amountIn}`);
189
+ if (String(args.quotedOutAmount) !== b.outAmount) throw new Error("swap instruction's quoted output differs from the answer");
190
+ if (args.slippageBps !== want.slippageBps) throw new Error(`swap instruction allows ${args.slippageBps} bps slippage, not ${want.slippageBps}`);
191
+ if (args.platformFeeBps !== 0 || args.positiveSlippageBps !== 0) throw new Error("swap instruction takes a platform fee");
192
+ let price = 0n;
193
+ for (const ix of b.computeBudgetInstructions ?? []) {
194
+ if (ix.programId !== COMPUTE_BUDGET_PROGRAM) throw new Error(`compute-budget slot holds ${ix.programId}`);
195
+ const d = decodeComputeBudget(fromBase64(ix.data));
196
+ if (d.price !== void 0) price = d.price;
197
+ }
198
+ const instructions = [...b.setupInstructions ?? [], b.swapInstruction, ...b.cleanupInstruction ? [b.cleanupInstruction] : [], ...b.otherInstructions ?? []];
199
+ for (const ix of instructions) {
200
+ if (!JUPITER_TX_PROGRAMS.has(ix.programId) || ix.programId === COMPUTE_BUDGET_PROGRAM) throw new Error(`instruction for program ${ix.programId}`);
201
+ for (const a of ix.accounts) if (a.isSigner && a.pubkey !== want.taker) throw new Error(`instruction needs signer ${a.pubkey}`);
202
+ }
203
+ return { instructions, price: price > maxPrice ? maxPrice : price, quotedOut: args.quotedOutAmount };
204
+ };
205
+ const simulateUnits = async (wire) => {
206
+ if (!rpcUrls.length) return null;
207
+ let r;
208
+ try {
209
+ r = await rpc("simulateTransaction", [wire, { encoding: "base64", sigVerify: false, replaceRecentBlockhash: true, commitment: "processed" }]);
210
+ } catch {
211
+ return null;
212
+ }
213
+ if (r?.value?.err) {
214
+ const log = (r.value.logs ?? []).filter((l) => /error|failed|insufficient/i.test(l)).slice(-1)[0] ?? "";
215
+ const err = JSON.stringify(r.value.err);
216
+ const jupiterCode = /JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 failed/.test(log) ? /"Custom":(\d+)/.exec(err)?.[1] : void 0;
217
+ if (jupiterCode === "6024" || jupiterCode === "6025" || /"Custom":1\}/.test(err) && /Program 11111111111111111111111111111111 failed/.test(log)) {
218
+ throw new Error(`not enough of the input token in the wallet${jupiterCode === "6025" ? " (no token account for it)" : ""} \u2014 simulation fails: ${err}`);
219
+ }
220
+ throw new Error(`simulation fails: ${err}${log ? ` (${log.slice(0, 160)})` : ""}`);
221
+ }
222
+ const used = r?.value?.unitsConsumed;
223
+ return used ? Math.min(MAX_COMPUTE_UNITS, Math.ceil(used * 1.2)) : null;
224
+ };
225
+ return {
226
+ name: "jupiter",
227
+ describeActivity: describeJupiterActivity,
228
+ enabled: () => config.enabled ?? true,
229
+ supportsSameChain: true,
230
+ supportsChain: (chain) => jupiter.supportsChain(chain),
231
+ supportsChainPair: (from, to) => jupiter.supports(from, to),
232
+ supportsRoute(from, to) {
233
+ if (!jupiter.supports(from.chain, to.chain)) return false;
234
+ const a = jupiterMint(from.token), b = jupiterMint(to.token);
235
+ return !!a && !!b && a !== b;
236
+ },
237
+ async getQuote(params, signal) {
238
+ const dry = params.dry !== false;
239
+ const refuse = (reason) => {
240
+ params.onRefusal?.(`jupiter: ${reason}`);
241
+ return null;
242
+ };
243
+ if (!jupiter.supports(params.sourceChain, params.destChain)) return refuse(`same-chain Solana only (${params.sourceChain} \u2192 ${params.destChain})`);
244
+ if (params.flex) return refuse("amount-flexible deposits are not supported");
245
+ const inputMint = jupiterMint(params.sourceToken), outputMint = jupiterMint(params.destToken);
246
+ if (!inputMint || !outputMint) return refuse(`unknown token (${params.sourceToken} \u2192 ${params.destToken})`);
247
+ if (inputMint === outputMint) return refuse("same token on both sides");
248
+ const amountIn = BigInt(params.amountIn);
249
+ if (amountIn <= 0n) return refuse("amount must be positive");
250
+ const slippageBps = params.slippageBps ?? config.defaultSlippageBps ?? DEFAULT_SLIPPAGE_BPS;
251
+ if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > MAX_SLIPPAGE_BPS) return refuse(`slippage ${slippageBps} bps is out of range`);
252
+ const self = params.refundAddress || params.destAddress;
253
+ if (!dry) {
254
+ if (!self || !BASE582.test(self)) return refuse("live quote without the signer's address");
255
+ if (params.destAddress && params.destAddress !== self) return refuse("the recipient must be the signing wallet (Jupiter pays the taker)");
256
+ }
257
+ const taker = self && BASE582.test(self) ? self : DRY_TAKER;
258
+ const qs = new URLSearchParams({ inputMint, outputMint, amount: params.amountIn, taker, slippageBps: String(slippageBps) });
259
+ if (config.computeUnitPricePercentile) qs.set("computeUnitPricePercentile", config.computeUnitPricePercentile);
260
+ let b;
261
+ try {
262
+ const r = await get(`/build?${qs.toString()}`, signal);
263
+ if (!r.ok) return refuse(`build ${r.status}: ${String(r.body?.error ?? "").slice(0, 160)}`);
264
+ b = r.body ?? {};
265
+ } catch (e) {
266
+ return refuse(`build failed: ${e.message.slice(0, 160)}`);
267
+ }
268
+ if (!b.outAmount || !/^\d+$/.test(b.outAmount)) return refuse("answer without an output amount");
269
+ let vetted;
270
+ try {
271
+ vetted = vet(b, { taker, inputMint, outputMint, amountIn, slippageBps });
272
+ } catch (e) {
273
+ return refuse(e.message);
274
+ }
275
+ const minOut = minOutOf(vetted.quotedOut, slippageBps);
276
+ if (params.minAmountOut !== void 0 && minOut < BigInt(params.minAmountOut)) {
277
+ return refuse(`guaranteed ${minOut} is below the floor ${params.minAmountOut} at ${slippageBps} bps`);
278
+ }
279
+ const route = (b.routePlan ?? []).map((s) => s.swapInfo?.label).filter(Boolean).join(" + ");
280
+ const impact = Number(b.priceImpactPct ?? 0);
281
+ const common = {
282
+ provider: "jupiter",
283
+ depositAddress: "",
284
+ depositMemo: null,
285
+ sourceAmount: params.amountIn,
286
+ destAmount: b.outAmount,
287
+ minDestAmount: minOut.toString(),
288
+ feeUsd: 0,
289
+ etaSeconds: 15,
290
+ reliability: impact > 0.05 ? 0.8 : 0.97,
291
+ validUntilMs: Date.now() + QUOTE_TTL_MS
292
+ };
293
+ if (dry) {
294
+ return { ...common, intentId: `dry:${INTENT_PREFIX}${Date.now().toString(36)}`, fees: [{ type: "network", amount: BASE_FEE_LAMPORTS.toString(), token: "native", included: false, description: "Solana base fee" }], ...route ? { providerData: { route } } : {} };
295
+ }
296
+ const blockhash = b.blockhashWithMetadata?.blockhash;
297
+ const lastValid = b.blockhashWithMetadata?.lastValidBlockHeight;
298
+ if (!blockhash || blockhash.length !== 32 || !lastValid) return refuse("answer without a blockhash");
299
+ const assemble = (limit2) => assembleTransaction({
300
+ taker,
301
+ instructions: vetted.instructions,
302
+ computeUnitLimit: limit2,
303
+ computeUnitPrice: vetted.price,
304
+ blockhash: Uint8Array.from(blockhash),
305
+ lastValidBlockHeight: lastValid,
306
+ addressesByLookupTableAddress: b.addressesByLookupTableAddress
307
+ });
308
+ let wire, limit = MAX_COMPUTE_UNITS;
309
+ try {
310
+ wire = assemble(MAX_COMPUTE_UNITS);
311
+ const units = await simulateUnits(wire);
312
+ if (units) {
313
+ limit = units;
314
+ wire = assemble(units);
315
+ }
316
+ } catch (e) {
317
+ return refuse(e.message.slice(0, 240));
318
+ }
319
+ const priority = (vetted.price * BigInt(limit) + 999999n) / 1000000n;
320
+ return {
321
+ ...common,
322
+ intentId: `${INTENT_PREFIX}${lastValid}:${Date.now().toString(36)}`,
323
+ // `value` declares the native SOL the transaction may take: the input for a SOL source (Jupiter wraps it), none for a token.
324
+ txRequest: { serializedTx: wire, value: inputMint === WSOL_MINT ? params.amountIn : "0" },
325
+ fees: [{ type: "network", amount: (BASE_FEE_LAMPORTS + priority).toString(), token: "native", included: false, description: `Solana base + priority fee (${limit} CU at ${vetted.price} \xB5lamports)` }],
326
+ providerData: { inputMint, outputMint, slippageBps: String(slippageBps), computeUnits: String(limit), ...route ? { route } : {} }
327
+ };
328
+ },
329
+ async buildDeposit(quote) {
330
+ const tx = quote.txRequest?.serializedTx;
331
+ if (!tx || quote.intentId.startsWith("dry:")) throw new Error("jupiter: not a live quote");
332
+ return { chain: SOLANA_CAIP2, to: "", value: quote.txRequest.value ?? "0", serializedTx: tx };
333
+ },
334
+ async trackIntent(ref) {
335
+ if (!ref.sourceTxHash || !rpcUrls.length) return { state: "pending" };
336
+ try {
337
+ const r = await rpc("getSignatureStatuses", [[ref.sourceTxHash], { searchTransactionHistory: true }]);
338
+ const s = r?.value?.[0];
339
+ if (!s) return { state: "pending" };
340
+ if (s.err) return { state: "failed" };
341
+ return s.confirmationStatus === "confirmed" || s.confirmationStatus === "finalized" ? { state: "completed", destTxHash: ref.sourceTxHash } : { state: "pending" };
342
+ } catch {
343
+ return { state: "pending" };
344
+ }
345
+ }
346
+ };
347
+ }
348
+ //# sourceMappingURL=provider.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider.ts","../src/activity.ts","../src/config.ts","../src/codec.ts","../src/transaction.ts"],"sourcesContent":["/**\n * Jupiter provider — Swap API V2 Router path, same-chain Solana swaps:\n * quote + instructions GET /swap/v2/build?inputMint&outputMint&amount&taker&slippageBps\n * status getSignatureStatuses on the caller's own Solana RPC (optional)\n * Routing is Metis (Jupiter's on-chain router); the Router path charges no Jupiter swap fee. Keyless access works at\n * 0.5 RPS; pass `apiKey` (sent as `x-api-key`) for a plan's rate limit.\n *\n * Nothing from the API is trusted as-is. Before a live quote is handed out, every instruction is checked: only the\n * Jupiter program and the token / system / ATA / compute-budget plumbing, the taker is the only signer, no tip, and\n * the swap instruction's own arguments (decoded) carry exactly our input amount, the quoted output, our slippage and\n * a zero platform fee — those are what the program enforces on-chain. The compute budget is rebuilt here: a unit price\n * capped by `maxComputeUnitPrice`, and a unit limit from a simulation (1.2× the units used) when `rpcUrls` is given.\n * The account then executes the assembled transaction through its serialized-transaction guard (simulation +\n * balance proof against the quote) and broadcasts it through its own RPC.\n */\nimport {describeJupiterActivity} from \"./activity.js\";\nimport {JUPITER_API_DEFAULT, JUPITER_PROGRAM, JUPITER_TX_PROGRAMS, COMPUTE_BUDGET_PROGRAM, SOLANA_CAIP2, WSOL_MINT, jupiter as cfg, jupiterMint} from \"./config.js\";\nimport {decodeComputeBudget, decodeSwapArgs, fromBase64, minOutOf} from \"./codec.js\";\nimport {assembleTransaction, type JupiterInstruction} from \"./transaction.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\nconst DEFAULT_SLIPPAGE_BPS = 50;\nconst MAX_SLIPPAGE_BPS = 1_000;\n/** A /build blockhash lives ~60–90 s; the quote must be signed well inside it. */\nconst QUOTE_TTL_MS = 30_000;\nconst MAX_COMPUTE_UNITS = 1_400_000;\n/** 2 000 000 µlamports/CU: at 1.4 M CU the priority fee is ≤ 0.0028 SOL. */\nconst DEFAULT_MAX_CU_PRICE = 2_000_000n;\nconst BASE_FEE_LAMPORTS = 5_000n;\n/** Taker for a dry quote with no address yet: /build needs one, the price does not depend on it. */\nconst DRY_TAKER = \"9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM\";\nconst BASE58 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\nexport interface JupiterProviderConfig {\n enabled?: boolean;\n /** Swap API base (default https://api.jup.ag/swap/v2). */\n apiUrl?: string;\n /** Jupiter Developer Platform key, sent as `x-api-key`. Keyless works at 0.5 RPS. */\n apiKey?: string;\n /** Solana JSON-RPC endpoints: compute-unit simulation and status. Without them the limit is 1.4 M CU and status stays pending. */\n rpcUrls?: readonly string[];\n /** Ceiling on the compute-unit price Jupiter suggests, micro-lamports (default 2 000 000). */\n maxComputeUnitPrice?: bigint;\n /** Passed to /build: \"medium\" | \"high\" | \"veryHigh\" or a percentile in bps (default: Jupiter's 50th percentile). */\n computeUnitPricePercentile?: string;\n /** Slippage when the caller names none, bps (default 50). */\n defaultSlippageBps?: number;\n}\n\ninterface BuildResponse {\n inputMint?: string;\n outputMint?: string;\n inAmount?: string;\n outAmount?: string;\n otherAmountThreshold?: string;\n swapMode?: string;\n slippageBps?: number;\n priceImpactPct?: string;\n routePlan?: {bps?: number; swapInfo?: {label?: string}}[];\n computeBudgetInstructions?: JupiterInstruction[];\n setupInstructions?: JupiterInstruction[];\n swapInstruction?: JupiterInstruction;\n cleanupInstruction?: JupiterInstruction | null;\n otherInstructions?: JupiterInstruction[];\n tipInstruction?: JupiterInstruction | null;\n addressesByLookupTableAddress?: Record<string, string[]> | null;\n transactionVersion?: number | string;\n blockhashWithMetadata?: {blockhash?: number[]; lastValidBlockHeight?: number};\n error?: string;\n}\n\nconst INTENT_PREFIX = \"jup:\";\n\nexport function jupiterProvider(config: JupiterProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const base = (config.apiUrl ?? JUPITER_API_DEFAULT).replace(/\\/$/, \"\");\n const maxPrice = config.maxComputeUnitPrice ?? DEFAULT_MAX_CU_PRICE;\n const rpcUrls = config.rpcUrls ?? [];\n\n /** One GET with a single back-off on 429 (keyless traffic is 0.5 RPS), waiting for `x-ratelimit-reset` when given. */\n const get = async (path: string, signal?: AbortSignal): Promise<{ok: boolean; status: number; body: unknown}> => {\n for (let attempt = 0; ; attempt++) {\n const res = await fetch(`${base}${path}`, {headers: {accept: \"application/json\", ...(config.apiKey ? {\"x-api-key\": config.apiKey} : {})}, signal: signal ?? timeoutSignal(12_000)});\n const body = await res.json().catch(() => null);\n if (res.status === 429 && attempt === 0 && !signal?.aborted) {\n const reset = Number(res.headers.get(\"x-ratelimit-reset\"));\n const wait = Number.isFinite(reset) && reset > 0 ? Math.min(3_000, Math.max(250, reset * 1000 - Date.now())) : 1_200;\n await new Promise((r) => setTimeout(r, wait));\n continue;\n }\n return {ok: res.ok, status: res.status, body};\n }\n };\n\n const rpc = async (method: string, params: unknown[]): Promise<unknown> => {\n let last: unknown = new Error(\"no Solana RPC configured\");\n for (const url of rpcUrls) {\n try {\n const res = await fetch(url, {method: \"POST\", headers: {\"content-type\": \"application/json\"}, body: JSON.stringify({jsonrpc: \"2.0\", id: 1, method, params}), signal: timeoutSignal(10_000)});\n const body = (await res.json()) as {result?: unknown; error?: {message?: string}};\n if (body.error) throw new Error(body.error.message ?? \"rpc error\");\n return body.result;\n } catch (e) { last = e; }\n }\n throw last;\n };\n\n /** Every instruction the API returned, checked; returns the ordered list to assemble and the suggested unit price. */\n const vet = (b: BuildResponse, want: {taker: string; inputMint: string; outputMint: string; amountIn: bigint; slippageBps: number}): {instructions: JupiterInstruction[]; price: bigint; quotedOut: bigint} => {\n if (b.swapMode && b.swapMode !== \"ExactIn\") throw new Error(`swap mode ${b.swapMode}`);\n if (b.inputMint !== want.inputMint || b.outputMint !== want.outputMint) throw new Error(\"the answer names other mints\");\n if (b.inAmount !== want.amountIn.toString()) throw new Error(`the answer spends ${b.inAmount}, not ${want.amountIn}`);\n if (String(b.transactionVersion ?? \"0\") !== \"0\") throw new Error(`transaction version ${b.transactionVersion}`);\n if (b.tipInstruction) throw new Error(\"unexpected tip instruction\");\n if (!b.swapInstruction) throw new Error(\"no swap instruction\");\n if (b.swapInstruction.programId !== JUPITER_PROGRAM) throw new Error(`swap instruction targets ${b.swapInstruction.programId}`);\n const args = decodeSwapArgs(fromBase64(b.swapInstruction.data));\n if (args.inAmount !== want.amountIn) throw new Error(`swap instruction spends ${args.inAmount}, not ${want.amountIn}`);\n if (String(args.quotedOutAmount) !== b.outAmount) throw new Error(\"swap instruction's quoted output differs from the answer\");\n if (args.slippageBps !== want.slippageBps) throw new Error(`swap instruction allows ${args.slippageBps} bps slippage, not ${want.slippageBps}`);\n if (args.platformFeeBps !== 0 || args.positiveSlippageBps !== 0) throw new Error(\"swap instruction takes a platform fee\");\n let price = 0n;\n for (const ix of b.computeBudgetInstructions ?? []) {\n if (ix.programId !== COMPUTE_BUDGET_PROGRAM) throw new Error(`compute-budget slot holds ${ix.programId}`);\n const d = decodeComputeBudget(fromBase64(ix.data));\n if (d.price !== undefined) price = d.price;\n }\n const instructions = [...(b.setupInstructions ?? []), b.swapInstruction, ...(b.cleanupInstruction ? [b.cleanupInstruction] : []), ...(b.otherInstructions ?? [])];\n for (const ix of instructions) {\n if (!JUPITER_TX_PROGRAMS.has(ix.programId) || ix.programId === COMPUTE_BUDGET_PROGRAM) throw new Error(`instruction for program ${ix.programId}`);\n for (const a of ix.accounts) if (a.isSigner && a.pubkey !== want.taker) throw new Error(`instruction needs signer ${a.pubkey}`);\n }\n return {instructions, price: price > maxPrice ? maxPrice : price, quotedOut: args.quotedOutAmount};\n };\n\n /** 1.2× the units a simulation uses (capped); null when no RPC answers. A failing simulation refuses the quote. */\n const simulateUnits = async (wire: string): Promise<number | null> => {\n if (!rpcUrls.length) return null;\n let r: {value?: {err?: unknown; unitsConsumed?: number; logs?: string[]}};\n try {\n r = (await rpc(\"simulateTransaction\", [wire, {encoding: \"base64\", sigVerify: false, replaceRecentBlockhash: true, commitment: \"processed\"}])) as typeof r;\n } catch {\n return null;\n }\n if (r?.value?.err) {\n const log = (r.value.logs ?? []).filter((l) => /error|failed|insufficient/i.test(l)).slice(-1)[0] ?? \"\";\n const err = JSON.stringify(r.value.err);\n // The usual reason, said plainly: the wallet lacks the input. Confirmed 2026-10-24 by building the same\n // USDS / LINK / WBTC → USDC swaps from an empty wallet (6025) and from real holders (built fine).\n // Jupiter 6024 = insufficient funds, 6025 = no token account for the input; System Program 1 = not enough SOL.\n const jupiterCode = /JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 failed/.test(log) ? /\"Custom\":(\\d+)/.exec(err)?.[1] : undefined;\n if (jupiterCode === \"6024\" || jupiterCode === \"6025\" || (/\"Custom\":1\\}/.test(err) && /Program 11111111111111111111111111111111 failed/.test(log))) {\n throw new Error(`not enough of the input token in the wallet${jupiterCode === \"6025\" ? \" (no token account for it)\" : \"\"} — simulation fails: ${err}`);\n }\n throw new Error(`simulation fails: ${err}${log ? ` (${log.slice(0, 160)})` : \"\"}`);\n }\n const used = r?.value?.unitsConsumed;\n return used ? Math.min(MAX_COMPUTE_UNITS, Math.ceil(used * 1.2)) : null;\n };\n\n return {\n name: \"jupiter\",\n describeActivity: describeJupiterActivity,\n enabled: () => config.enabled ?? true,\n supportsSameChain: true,\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (from: string, to: string) => cfg.supports(from, to),\n supportsRoute(from: Asset, to: Asset): boolean {\n if (!cfg.supports(from.chain, to.chain)) return false;\n const a = jupiterMint(from.token), b = jupiterMint(to.token);\n return !!a && !!b && a !== b;\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n const dry = params.dry !== false;\n const refuse = (reason: string): null => {\n params.onRefusal?.(`jupiter: ${reason}`);\n return null;\n };\n if (!cfg.supports(params.sourceChain, params.destChain)) return refuse(`same-chain Solana only (${params.sourceChain} → ${params.destChain})`);\n if (params.flex) return refuse(\"amount-flexible deposits are not supported\");\n const inputMint = jupiterMint(params.sourceToken), outputMint = jupiterMint(params.destToken);\n if (!inputMint || !outputMint) return refuse(`unknown token (${params.sourceToken} → ${params.destToken})`);\n if (inputMint === outputMint) return refuse(\"same token on both sides\");\n const amountIn = BigInt(params.amountIn);\n if (amountIn <= 0n) return refuse(\"amount must be positive\");\n const slippageBps = params.slippageBps ?? config.defaultSlippageBps ?? DEFAULT_SLIPPAGE_BPS;\n if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > MAX_SLIPPAGE_BPS) return refuse(`slippage ${slippageBps} bps is out of range`);\n\n // The swap pays the taker's own token account: a live quote must be for the signer's own address.\n const self = params.refundAddress || params.destAddress;\n if (!dry) {\n if (!self || !BASE58.test(self)) return refuse(\"live quote without the signer's address\");\n if (params.destAddress && params.destAddress !== self) return refuse(\"the recipient must be the signing wallet (Jupiter pays the taker)\");\n }\n const taker = self && BASE58.test(self) ? self : DRY_TAKER;\n\n const qs = new URLSearchParams({inputMint, outputMint, amount: params.amountIn, taker, slippageBps: String(slippageBps)});\n if (config.computeUnitPricePercentile) qs.set(\"computeUnitPricePercentile\", config.computeUnitPricePercentile);\n let b: BuildResponse;\n try {\n const r = await get(`/build?${qs.toString()}`, signal);\n if (!r.ok) return refuse(`build ${r.status}: ${String((r.body as BuildResponse | null)?.error ?? \"\").slice(0, 160)}`);\n b = (r.body ?? {}) as BuildResponse;\n } catch (e) { return refuse(`build failed: ${(e as Error).message.slice(0, 160)}`); }\n if (!b.outAmount || !/^\\d+$/.test(b.outAmount)) return refuse(\"answer without an output amount\");\n\n let vetted: ReturnType<typeof vet>;\n try { vetted = vet(b, {taker, inputMint, outputMint, amountIn, slippageBps}); } catch (e) { return refuse((e as Error).message); }\n const minOut = minOutOf(vetted.quotedOut, slippageBps);\n if (params.minAmountOut !== undefined && minOut < BigInt(params.minAmountOut)) {\n return refuse(`guaranteed ${minOut} is below the floor ${params.minAmountOut} at ${slippageBps} bps`);\n }\n const route = (b.routePlan ?? []).map((s) => s.swapInfo?.label).filter(Boolean).join(\" + \");\n const impact = Number(b.priceImpactPct ?? 0);\n const common = {\n provider: \"jupiter\",\n depositAddress: \"\",\n depositMemo: null,\n sourceAmount: params.amountIn,\n destAmount: b.outAmount,\n minDestAmount: minOut.toString(),\n feeUsd: 0,\n etaSeconds: 15,\n reliability: impact > 0.05 ? 0.8 : 0.97,\n validUntilMs: Date.now() + QUOTE_TTL_MS,\n };\n if (dry) {\n return {...common, intentId: `dry:${INTENT_PREFIX}${Date.now().toString(36)}`, fees: [{type: \"network\" as const, amount: BASE_FEE_LAMPORTS.toString(), token: \"native\", included: false, description: \"Solana base fee\"}], ...(route ? {providerData: {route}} : {})};\n }\n\n const blockhash = b.blockhashWithMetadata?.blockhash;\n const lastValid = b.blockhashWithMetadata?.lastValidBlockHeight;\n if (!blockhash || blockhash.length !== 32 || !lastValid) return refuse(\"answer without a blockhash\");\n const assemble = (limit: number) => assembleTransaction({\n taker, instructions: vetted.instructions, computeUnitLimit: limit, computeUnitPrice: vetted.price,\n blockhash: Uint8Array.from(blockhash), lastValidBlockHeight: lastValid, addressesByLookupTableAddress: b.addressesByLookupTableAddress,\n });\n let wire: string, limit = MAX_COMPUTE_UNITS;\n try {\n wire = assemble(MAX_COMPUTE_UNITS);\n const units = await simulateUnits(wire);\n if (units) { limit = units; wire = assemble(units); }\n } catch (e) { return refuse((e as Error).message.slice(0, 240)); }\n const priority = (vetted.price * BigInt(limit) + 999_999n) / 1_000_000n;\n return {\n ...common,\n intentId: `${INTENT_PREFIX}${lastValid}:${Date.now().toString(36)}`,\n // `value` declares the native SOL the transaction may take: the input for a SOL source (Jupiter wraps it), none for a token.\n txRequest: {serializedTx: wire, value: inputMint === WSOL_MINT ? params.amountIn : \"0\"},\n fees: [{type: \"network\", amount: (BASE_FEE_LAMPORTS + priority).toString(), token: \"native\", included: false, description: `Solana base + priority fee (${limit} CU at ${vetted.price} µlamports)`}],\n providerData: {inputMint, outputMint, slippageBps: String(slippageBps), computeUnits: String(limit), ...(route ? {route} : {})},\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest?.serializedTx;\n if (!tx || quote.intentId.startsWith(\"dry:\")) throw new Error(\"jupiter: not a live quote\");\n return {chain: SOLANA_CAIP2, to: \"\", value: quote.txRequest!.value ?? \"0\", serializedTx: tx};\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash || !rpcUrls.length) return {state: \"pending\"};\n try {\n const r = (await rpc(\"getSignatureStatuses\", [[ref.sourceTxHash], {searchTransactionHistory: true}])) as {value?: ({err?: unknown; confirmationStatus?: string} | null)[]};\n const s = r?.value?.[0];\n if (!s) return {state: \"pending\"};\n if (s.err) return {state: \"failed\"};\n return s.confirmationStatus === \"confirmed\" || s.confirmationStatus === \"finalized\" ? {state: \"completed\", destTxHash: ref.sourceTxHash} : {state: \"pending\"};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n","/**\n * Activity recognition for Jupiter swaps. Solana history (wallet-solana) names the first non-plumbing program a\n * transaction runs as `call.to`: a swap sent to Jupiter v6 directly (this module's /build transactions, jup.ag) has it\n * there. A route that only passes through Jupiter inside another program (an aggregator or bridge CPI-ing into it) names\n * that program instead and is left to its module. The owner must both give and receive an asset: a leg that only sends\n * (a bridge's source leg with a Jupiter pre-swap) is not called a swap.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {describeSwapLike} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {JUPITER_PROGRAM, SOLANA_CHAINS} from \"./config.js\";\n\nexport const JUPITER_MODULE = \"@anywalletkit/protocol-swap2-jupiter\";\n\nexport function describeJupiterActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!SOLANA_CHAINS.has(tx.chain) || tx.call?.to !== JUPITER_PROGRAM) return null;\n const item = describeSwapLike(tx, ctx, {protocol: JUPITER_MODULE, subtitle: \"Jupiter\", kind: \"swap\", counterparty: JUPITER_PROGRAM});\n if (item && tx.status !== \"failed\" && (item.assetsIn.length === 0 || item.assetsOut.length === 0)) return null;\n return item;\n}\n","/**\n * Jupiter (Solana) — Swap API V2, Router path (`GET /swap/v2/build`): Metis on-chain routing, raw instructions, no\n * Jupiter swap fee. The transaction is assembled here and executed by the account's serialized-transaction guard\n * (simulation + balance proof), then broadcast through the wallet's own RPC — Jupiter never lands it for us.\n * Same-chain only: Solana → Solana.\n */\nimport {ccAsset, ccAssetByToken} from \"@anywalletkit/swap2-assets\";\n\nexport const JUPITER_API_DEFAULT = \"https://api.jup.ag/swap/v2\";\n\n/** Jupiter Aggregator v6 — the only program a swap instruction may target. */\nexport const JUPITER_PROGRAM = \"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4\";\nexport const COMPUTE_BUDGET_PROGRAM = \"ComputeBudget111111111111111111111111111111\";\nexport const SYSTEM_PROGRAM = \"11111111111111111111111111111111\";\nexport const TOKEN_PROGRAM = \"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA\";\nexport const TOKEN_2022_PROGRAM = \"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb\";\nexport const ATA_PROGRAM = \"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL\";\n/** Wrapped SOL: Jupiter's name for native SOL (it wraps / unwraps around the swap). */\nexport const WSOL_MINT = \"So11111111111111111111111111111111111111112\";\n\n/** Programs the /build instructions may invoke; anything else refuses the quote before the wallet sees it. */\nexport const JUPITER_TX_PROGRAMS: ReadonlySet<string> = new Set([JUPITER_PROGRAM, COMPUTE_BUDGET_PROGRAM, SYSTEM_PROGRAM, TOKEN_PROGRAM, TOKEN_2022_PROGRAM, ATA_PROGRAM]);\n\n/** swap2 names Solana `solana:mainnet`; wallet history uses the genesis-hash form. */\nexport const SOLANA_CAIP2 = \"solana:mainnet\";\nexport const SOLANA_CHAINS: ReadonlySet<string> = new Set([SOLANA_CAIP2, \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\"]);\n\nconst BASE58 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\nconst NATIVE = new Set([\"\", \"native\", \"sol\", SYSTEM_PROGRAM, WSOL_MINT.toLowerCase(), \"0x0000000000000000000000000000000000000000\"]);\n\n/** A swap2 token ref on Solana (catalog symbol, mint, or a native marker) → the mint Jupiter quotes; null when unknown. */\nexport function jupiterMint(token: string): string | null {\n if (NATIVE.has(token.toLowerCase()) || /^0x0+$/.test(token)) return WSOL_MINT;\n const bySymbol = ccAsset(SOLANA_CAIP2, token);\n if (bySymbol) return bySymbol.contract ?? WSOL_MINT;\n const byMint = BASE58.test(token) ? ccAssetByToken(SOLANA_CAIP2, token) : undefined;\n if (byMint) return byMint.contract ?? WSOL_MINT;\n return BASE58.test(token) ? token : null;\n}\n\nexport const jupiter = {\n supportsChain: (chain: string) => chain === SOLANA_CAIP2,\n supports: (from: string, to: string) => from === SOLANA_CAIP2 && to === SOLANA_CAIP2,\n};\n","/**\n * Byte-level checks of what `/build` returns. The swap instruction is Jupiter v6's Anchor `route_v2` /\n * `shared_accounts_route_v2` (ExactIn): its arguments carry the input amount, the quoted output, the slippage and the\n * platform-fee split that the program enforces on-chain — so they are read back here and must equal the request\n * before the transaction is assembled. Discriminators = sha256(\"global:<name>\")[0..8] (verified 2026-10-23 against\n * live /build answers).\n */\nimport {base64} from \"@scure/base\";\n\n/** `route_v2(in_amount u64, quoted_out_amount u64, slippage_bps u16, platform_fee_bps u16, positive_slippage_bps u16, route_plan Vec)` */\nexport const ROUTE_V2 = \"bb64facc31c4af14\";\n/** `shared_accounts_route_v2(id u8, …the same arguments…)` */\nexport const SHARED_ACCOUNTS_ROUTE_V2 = \"d19853937cfed8e9\";\n\nexport interface JupiterSwapArgs {\n kind: \"route_v2\" | \"shared_accounts_route_v2\";\n inAmount: bigint;\n quotedOutAmount: bigint;\n slippageBps: number;\n platformFeeBps: number;\n positiveSlippageBps: number;\n}\n\nconst hex = (b: Uint8Array) => Array.from(b, (x) => x.toString(16).padStart(2, \"0\")).join(\"\");\nconst u64 = (d: Uint8Array, o: number) => new DataView(d.buffer, d.byteOffset + o, 8).getBigUint64(0, true);\nconst u16 = (d: Uint8Array, o: number) => new DataView(d.buffer, d.byteOffset + o, 2).getUint16(0, true);\n\nexport const fromBase64 = (s: string): Uint8Array => base64.decode(s);\nexport const toBase64 = (b: Uint8Array): string => base64.encode(b);\n\n/** Decode the swap instruction's fixed arguments; throws for any other instruction (ExactOut, legacy v1 routes…). */\nexport function decodeSwapArgs(data: Uint8Array): JupiterSwapArgs {\n const disc = hex(data.subarray(0, 8));\n const at = disc === ROUTE_V2 ? 8 : disc === SHARED_ACCOUNTS_ROUTE_V2 ? 9 : -1;\n if (at < 0) throw new Error(`unsupported Jupiter instruction ${disc}`);\n if (data.length < at + 22 + 4) throw new Error(\"Jupiter swap instruction is truncated\");\n return {\n kind: at === 8 ? \"route_v2\" : \"shared_accounts_route_v2\",\n inAmount: u64(data, at),\n quotedOutAmount: u64(data, at + 8),\n slippageBps: u16(data, at + 16),\n platformFeeBps: u16(data, at + 18),\n positiveSlippageBps: u16(data, at + 20),\n };\n}\n\n/** The worst output the program accepts: quoted · (10 000 − slippage) / 10 000, rounded down (never above the on-chain check). */\nexport function minOutOf(quotedOut: bigint, slippageBps: number): bigint {\n return (quotedOut * BigInt(10_000 - slippageBps)) / 10_000n;\n}\n\n/** ComputeBudget instructions: 2 = SetComputeUnitLimit(u32), 3 = SetComputeUnitPrice(u64 micro-lamports). */\nexport function decodeComputeBudget(data: Uint8Array): {limit?: number; price?: bigint} {\n if (data[0] === 2 && data.length === 5) return {limit: new DataView(data.buffer, data.byteOffset + 1, 4).getUint32(0, true)};\n if (data[0] === 3 && data.length === 9) return {price: u64(data, 1)};\n throw new Error(`unexpected compute-budget instruction ${data[0]}`);\n}\n\nexport function setComputeUnitLimit(units: number): Uint8Array {\n const d = new Uint8Array(5);\n d[0] = 2;\n new DataView(d.buffer).setUint32(1, units, true);\n return d;\n}\n\nexport function setComputeUnitPrice(microLamports: bigint): Uint8Array {\n const d = new Uint8Array(9);\n d[0] = 3;\n new DataView(d.buffer).setBigUint64(1, microLamports, true);\n return d;\n}\n","/**\n * Assemble the v0 transaction from `/build` instructions: our compute budget (limit + capped price), Jupiter's setup,\n * swap, cleanup and other instructions, compressed with the lookup tables the response names, fee payer = the taker,\n * lifetime = the blockhash Jupiter fetched. Signatures stay empty; the account signs after its own guard.\n */\nimport {\n AccountRole, address, appendTransactionMessageInstructions, compileTransaction, compressTransactionMessageUsingAddressLookupTables,\n createTransactionMessage, getBase58Decoder, getBase64EncodedWireTransaction, pipe, setTransactionMessageFeePayer,\n setTransactionMessageLifetimeUsingBlockhash, type Address, type Blockhash, type Instruction,\n} from \"@solana/kit\";\nimport {COMPUTE_BUDGET_PROGRAM} from \"./config.js\";\nimport {fromBase64, setComputeUnitLimit, setComputeUnitPrice} from \"./codec.js\";\n\nexport interface JupiterInstruction {\n programId: string;\n accounts: {pubkey: string; isSigner: boolean; isWritable: boolean}[];\n data: string;\n}\n\nexport interface AssembleInput {\n taker: string;\n /** setup → swap → cleanup → other, in that order; compute-budget instructions are ours and come first. */\n instructions: JupiterInstruction[];\n computeUnitLimit: number;\n computeUnitPrice: bigint;\n blockhash: Uint8Array | string;\n lastValidBlockHeight: number | bigint;\n addressesByLookupTableAddress: Record<string, string[]> | null | undefined;\n}\n\nconst role = (a: {isSigner: boolean; isWritable: boolean}): AccountRole =>\n a.isSigner ? (a.isWritable ? AccountRole.WRITABLE_SIGNER : AccountRole.READONLY_SIGNER) : a.isWritable ? AccountRole.WRITABLE : AccountRole.READONLY;\n\nconst toInstruction = (ix: JupiterInstruction): Instruction => ({\n programAddress: address(ix.programId),\n accounts: ix.accounts.map((a) => ({address: address(a.pubkey), role: role(a)})),\n data: fromBase64(ix.data),\n});\n\n/** The unsigned transaction as base64 wire bytes (what `TxRequest.serializedTx` carries). */\nexport function assembleTransaction(input: AssembleInput): string {\n const budget: Instruction[] = [\n {programAddress: address(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitLimit(input.computeUnitLimit)},\n {programAddress: address(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitPrice(input.computeUnitPrice)},\n ];\n const blockhash = (typeof input.blockhash === \"string\" ? input.blockhash : getBase58Decoder().decode(input.blockhash)) as Blockhash;\n const tables: Record<Address, Address[]> = {};\n for (const [table, list] of Object.entries(input.addressesByLookupTableAddress ?? {})) tables[address(table)] = list.map((a) => address(a));\n const message = pipe(\n createTransactionMessage({version: 0}),\n (m) => setTransactionMessageFeePayer(address(input.taker), m),\n (m) => setTransactionMessageLifetimeUsingBlockhash({blockhash, lastValidBlockHeight: BigInt(input.lastValidBlockHeight)}, m),\n (m) => appendTransactionMessageInstructions([...budget, ...input.instructions.map(toInstruction)], m),\n (m) => (Object.keys(tables).length ? compressTransactionMessageUsingAddressLookupTables(m, tables) : m),\n );\n return getBase64EncodedWireTransaction(compileTransaction(message));\n}\n"],"mappings":"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","names":["BASE58","limit"]}
@@ -0,0 +1,20 @@
1
+ import { CrossChainProvider } from '@anywalletkit/protocol-swap2-core/types';
2
+
3
+ interface JupiterProviderConfig {
4
+ enabled?: boolean;
5
+ /** Swap API base (default https://api.jup.ag/swap/v2). */
6
+ apiUrl?: string;
7
+ /** Jupiter Developer Platform key, sent as `x-api-key`. Keyless works at 0.5 RPS. */
8
+ apiKey?: string;
9
+ /** Solana JSON-RPC endpoints: compute-unit simulation and status. Without them the limit is 1.4 M CU and status stays pending. */
10
+ rpcUrls?: readonly string[];
11
+ /** Ceiling on the compute-unit price Jupiter suggests, micro-lamports (default 2 000 000). */
12
+ maxComputeUnitPrice?: bigint;
13
+ /** Passed to /build: "medium" | "high" | "veryHigh" or a percentile in bps (default: Jupiter's 50th percentile). */
14
+ computeUnitPricePercentile?: string;
15
+ /** Slippage when the caller names none, bps (default 50). */
16
+ defaultSlippageBps?: number;
17
+ }
18
+ declare function jupiterProvider(config?: JupiterProviderConfig): CrossChainProvider;
19
+
20
+ export { type JupiterProviderConfig, jupiterProvider };
@@ -0,0 +1,20 @@
1
+ import { CrossChainProvider } from '@anywalletkit/protocol-swap2-core/types';
2
+
3
+ interface JupiterProviderConfig {
4
+ enabled?: boolean;
5
+ /** Swap API base (default https://api.jup.ag/swap/v2). */
6
+ apiUrl?: string;
7
+ /** Jupiter Developer Platform key, sent as `x-api-key`. Keyless works at 0.5 RPS. */
8
+ apiKey?: string;
9
+ /** Solana JSON-RPC endpoints: compute-unit simulation and status. Without them the limit is 1.4 M CU and status stays pending. */
10
+ rpcUrls?: readonly string[];
11
+ /** Ceiling on the compute-unit price Jupiter suggests, micro-lamports (default 2 000 000). */
12
+ maxComputeUnitPrice?: bigint;
13
+ /** Passed to /build: "medium" | "high" | "veryHigh" or a percentile in bps (default: Jupiter's 50th percentile). */
14
+ computeUnitPricePercentile?: string;
15
+ /** Slippage when the caller names none, bps (default 50). */
16
+ defaultSlippageBps?: number;
17
+ }
18
+ declare function jupiterProvider(config?: JupiterProviderConfig): CrossChainProvider;
19
+
20
+ export { type JupiterProviderConfig, jupiterProvider };
@@ -0,0 +1,11 @@
1
+ import {
2
+ jupiterProvider
3
+ } from "./chunk-NESHFKWY.js";
4
+ import "./chunk-5L7BPEQL.js";
5
+ import "./chunk-5JXNDQHW.js";
6
+ import "./chunk-H4SP5E76.js";
7
+ import "./chunk-OVLAYYGP.js";
8
+ export {
9
+ jupiterProvider
10
+ };
11
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/transaction.ts
21
+ var transaction_exports = {};
22
+ __export(transaction_exports, {
23
+ assembleTransaction: () => assembleTransaction
24
+ });
25
+ module.exports = __toCommonJS(transaction_exports);
26
+ var import_kit = require("@solana/kit");
27
+
28
+ // src/config.ts
29
+ var import_swap2_assets = require("@anywalletkit/swap2-assets");
30
+ var COMPUTE_BUDGET_PROGRAM = "ComputeBudget111111111111111111111111111111";
31
+ var SYSTEM_PROGRAM = "11111111111111111111111111111111";
32
+ var WSOL_MINT = "So11111111111111111111111111111111111111112";
33
+ var NATIVE = /* @__PURE__ */ new Set(["", "native", "sol", SYSTEM_PROGRAM, WSOL_MINT.toLowerCase(), "0x0000000000000000000000000000000000000000"]);
34
+
35
+ // src/codec.ts
36
+ var import_base = require("@scure/base");
37
+ var fromBase64 = (s) => import_base.base64.decode(s);
38
+ function setComputeUnitLimit(units) {
39
+ const d = new Uint8Array(5);
40
+ d[0] = 2;
41
+ new DataView(d.buffer).setUint32(1, units, true);
42
+ return d;
43
+ }
44
+ function setComputeUnitPrice(microLamports) {
45
+ const d = new Uint8Array(9);
46
+ d[0] = 3;
47
+ new DataView(d.buffer).setBigUint64(1, microLamports, true);
48
+ return d;
49
+ }
50
+
51
+ // src/transaction.ts
52
+ var role = (a) => a.isSigner ? a.isWritable ? import_kit.AccountRole.WRITABLE_SIGNER : import_kit.AccountRole.READONLY_SIGNER : a.isWritable ? import_kit.AccountRole.WRITABLE : import_kit.AccountRole.READONLY;
53
+ var toInstruction = (ix) => ({
54
+ programAddress: (0, import_kit.address)(ix.programId),
55
+ accounts: ix.accounts.map((a) => ({ address: (0, import_kit.address)(a.pubkey), role: role(a) })),
56
+ data: fromBase64(ix.data)
57
+ });
58
+ function assembleTransaction(input) {
59
+ const budget = [
60
+ { programAddress: (0, import_kit.address)(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitLimit(input.computeUnitLimit) },
61
+ { programAddress: (0, import_kit.address)(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitPrice(input.computeUnitPrice) }
62
+ ];
63
+ const blockhash = typeof input.blockhash === "string" ? input.blockhash : (0, import_kit.getBase58Decoder)().decode(input.blockhash);
64
+ const tables = {};
65
+ for (const [table, list] of Object.entries(input.addressesByLookupTableAddress ?? {})) tables[(0, import_kit.address)(table)] = list.map((a) => (0, import_kit.address)(a));
66
+ const message = (0, import_kit.pipe)(
67
+ (0, import_kit.createTransactionMessage)({ version: 0 }),
68
+ (m) => (0, import_kit.setTransactionMessageFeePayer)((0, import_kit.address)(input.taker), m),
69
+ (m) => (0, import_kit.setTransactionMessageLifetimeUsingBlockhash)({ blockhash, lastValidBlockHeight: BigInt(input.lastValidBlockHeight) }, m),
70
+ (m) => (0, import_kit.appendTransactionMessageInstructions)([...budget, ...input.instructions.map(toInstruction)], m),
71
+ (m) => Object.keys(tables).length ? (0, import_kit.compressTransactionMessageUsingAddressLookupTables)(m, tables) : m
72
+ );
73
+ return (0, import_kit.getBase64EncodedWireTransaction)((0, import_kit.compileTransaction)(message));
74
+ }
75
+ //# sourceMappingURL=transaction.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transaction.ts","../src/config.ts","../src/codec.ts"],"sourcesContent":["/**\n * Assemble the v0 transaction from `/build` instructions: our compute budget (limit + capped price), Jupiter's setup,\n * swap, cleanup and other instructions, compressed with the lookup tables the response names, fee payer = the taker,\n * lifetime = the blockhash Jupiter fetched. Signatures stay empty; the account signs after its own guard.\n */\nimport {\n AccountRole, address, appendTransactionMessageInstructions, compileTransaction, compressTransactionMessageUsingAddressLookupTables,\n createTransactionMessage, getBase58Decoder, getBase64EncodedWireTransaction, pipe, setTransactionMessageFeePayer,\n setTransactionMessageLifetimeUsingBlockhash, type Address, type Blockhash, type Instruction,\n} from \"@solana/kit\";\nimport {COMPUTE_BUDGET_PROGRAM} from \"./config.js\";\nimport {fromBase64, setComputeUnitLimit, setComputeUnitPrice} from \"./codec.js\";\n\nexport interface JupiterInstruction {\n programId: string;\n accounts: {pubkey: string; isSigner: boolean; isWritable: boolean}[];\n data: string;\n}\n\nexport interface AssembleInput {\n taker: string;\n /** setup → swap → cleanup → other, in that order; compute-budget instructions are ours and come first. */\n instructions: JupiterInstruction[];\n computeUnitLimit: number;\n computeUnitPrice: bigint;\n blockhash: Uint8Array | string;\n lastValidBlockHeight: number | bigint;\n addressesByLookupTableAddress: Record<string, string[]> | null | undefined;\n}\n\nconst role = (a: {isSigner: boolean; isWritable: boolean}): AccountRole =>\n a.isSigner ? (a.isWritable ? AccountRole.WRITABLE_SIGNER : AccountRole.READONLY_SIGNER) : a.isWritable ? AccountRole.WRITABLE : AccountRole.READONLY;\n\nconst toInstruction = (ix: JupiterInstruction): Instruction => ({\n programAddress: address(ix.programId),\n accounts: ix.accounts.map((a) => ({address: address(a.pubkey), role: role(a)})),\n data: fromBase64(ix.data),\n});\n\n/** The unsigned transaction as base64 wire bytes (what `TxRequest.serializedTx` carries). */\nexport function assembleTransaction(input: AssembleInput): string {\n const budget: Instruction[] = [\n {programAddress: address(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitLimit(input.computeUnitLimit)},\n {programAddress: address(COMPUTE_BUDGET_PROGRAM), data: setComputeUnitPrice(input.computeUnitPrice)},\n ];\n const blockhash = (typeof input.blockhash === \"string\" ? input.blockhash : getBase58Decoder().decode(input.blockhash)) as Blockhash;\n const tables: Record<Address, Address[]> = {};\n for (const [table, list] of Object.entries(input.addressesByLookupTableAddress ?? {})) tables[address(table)] = list.map((a) => address(a));\n const message = pipe(\n createTransactionMessage({version: 0}),\n (m) => setTransactionMessageFeePayer(address(input.taker), m),\n (m) => setTransactionMessageLifetimeUsingBlockhash({blockhash, lastValidBlockHeight: BigInt(input.lastValidBlockHeight)}, m),\n (m) => appendTransactionMessageInstructions([...budget, ...input.instructions.map(toInstruction)], m),\n (m) => (Object.keys(tables).length ? compressTransactionMessageUsingAddressLookupTables(m, tables) : m),\n );\n return getBase64EncodedWireTransaction(compileTransaction(message));\n}\n","/**\n * Jupiter (Solana) — Swap API V2, Router path (`GET /swap/v2/build`): Metis on-chain routing, raw instructions, no\n * Jupiter swap fee. The transaction is assembled here and executed by the account's serialized-transaction guard\n * (simulation + balance proof), then broadcast through the wallet's own RPC — Jupiter never lands it for us.\n * Same-chain only: Solana → Solana.\n */\nimport {ccAsset, ccAssetByToken} from \"@anywalletkit/swap2-assets\";\n\nexport const JUPITER_API_DEFAULT = \"https://api.jup.ag/swap/v2\";\n\n/** Jupiter Aggregator v6 — the only program a swap instruction may target. */\nexport const JUPITER_PROGRAM = \"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4\";\nexport const COMPUTE_BUDGET_PROGRAM = \"ComputeBudget111111111111111111111111111111\";\nexport const SYSTEM_PROGRAM = \"11111111111111111111111111111111\";\nexport const TOKEN_PROGRAM = \"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA\";\nexport const TOKEN_2022_PROGRAM = \"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb\";\nexport const ATA_PROGRAM = \"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL\";\n/** Wrapped SOL: Jupiter's name for native SOL (it wraps / unwraps around the swap). */\nexport const WSOL_MINT = \"So11111111111111111111111111111111111111112\";\n\n/** Programs the /build instructions may invoke; anything else refuses the quote before the wallet sees it. */\nexport const JUPITER_TX_PROGRAMS: ReadonlySet<string> = new Set([JUPITER_PROGRAM, COMPUTE_BUDGET_PROGRAM, SYSTEM_PROGRAM, TOKEN_PROGRAM, TOKEN_2022_PROGRAM, ATA_PROGRAM]);\n\n/** swap2 names Solana `solana:mainnet`; wallet history uses the genesis-hash form. */\nexport const SOLANA_CAIP2 = \"solana:mainnet\";\nexport const SOLANA_CHAINS: ReadonlySet<string> = new Set([SOLANA_CAIP2, \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\"]);\n\nconst BASE58 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\nconst NATIVE = new Set([\"\", \"native\", \"sol\", SYSTEM_PROGRAM, WSOL_MINT.toLowerCase(), \"0x0000000000000000000000000000000000000000\"]);\n\n/** A swap2 token ref on Solana (catalog symbol, mint, or a native marker) → the mint Jupiter quotes; null when unknown. */\nexport function jupiterMint(token: string): string | null {\n if (NATIVE.has(token.toLowerCase()) || /^0x0+$/.test(token)) return WSOL_MINT;\n const bySymbol = ccAsset(SOLANA_CAIP2, token);\n if (bySymbol) return bySymbol.contract ?? WSOL_MINT;\n const byMint = BASE58.test(token) ? ccAssetByToken(SOLANA_CAIP2, token) : undefined;\n if (byMint) return byMint.contract ?? WSOL_MINT;\n return BASE58.test(token) ? token : null;\n}\n\nexport const jupiter = {\n supportsChain: (chain: string) => chain === SOLANA_CAIP2,\n supports: (from: string, to: string) => from === SOLANA_CAIP2 && to === SOLANA_CAIP2,\n};\n","/**\n * Byte-level checks of what `/build` returns. The swap instruction is Jupiter v6's Anchor `route_v2` /\n * `shared_accounts_route_v2` (ExactIn): its arguments carry the input amount, the quoted output, the slippage and the\n * platform-fee split that the program enforces on-chain — so they are read back here and must equal the request\n * before the transaction is assembled. Discriminators = sha256(\"global:<name>\")[0..8] (verified 2026-10-23 against\n * live /build answers).\n */\nimport {base64} from \"@scure/base\";\n\n/** `route_v2(in_amount u64, quoted_out_amount u64, slippage_bps u16, platform_fee_bps u16, positive_slippage_bps u16, route_plan Vec)` */\nexport const ROUTE_V2 = \"bb64facc31c4af14\";\n/** `shared_accounts_route_v2(id u8, …the same arguments…)` */\nexport const SHARED_ACCOUNTS_ROUTE_V2 = \"d19853937cfed8e9\";\n\nexport interface JupiterSwapArgs {\n kind: \"route_v2\" | \"shared_accounts_route_v2\";\n inAmount: bigint;\n quotedOutAmount: bigint;\n slippageBps: number;\n platformFeeBps: number;\n positiveSlippageBps: number;\n}\n\nconst hex = (b: Uint8Array) => Array.from(b, (x) => x.toString(16).padStart(2, \"0\")).join(\"\");\nconst u64 = (d: Uint8Array, o: number) => new DataView(d.buffer, d.byteOffset + o, 8).getBigUint64(0, true);\nconst u16 = (d: Uint8Array, o: number) => new DataView(d.buffer, d.byteOffset + o, 2).getUint16(0, true);\n\nexport const fromBase64 = (s: string): Uint8Array => base64.decode(s);\nexport const toBase64 = (b: Uint8Array): string => base64.encode(b);\n\n/** Decode the swap instruction's fixed arguments; throws for any other instruction (ExactOut, legacy v1 routes…). */\nexport function decodeSwapArgs(data: Uint8Array): JupiterSwapArgs {\n const disc = hex(data.subarray(0, 8));\n const at = disc === ROUTE_V2 ? 8 : disc === SHARED_ACCOUNTS_ROUTE_V2 ? 9 : -1;\n if (at < 0) throw new Error(`unsupported Jupiter instruction ${disc}`);\n if (data.length < at + 22 + 4) throw new Error(\"Jupiter swap instruction is truncated\");\n return {\n kind: at === 8 ? \"route_v2\" : \"shared_accounts_route_v2\",\n inAmount: u64(data, at),\n quotedOutAmount: u64(data, at + 8),\n slippageBps: u16(data, at + 16),\n platformFeeBps: u16(data, at + 18),\n positiveSlippageBps: u16(data, at + 20),\n };\n}\n\n/** The worst output the program accepts: quoted · (10 000 − slippage) / 10 000, rounded down (never above the on-chain check). */\nexport function minOutOf(quotedOut: bigint, slippageBps: number): bigint {\n return (quotedOut * BigInt(10_000 - slippageBps)) / 10_000n;\n}\n\n/** ComputeBudget instructions: 2 = SetComputeUnitLimit(u32), 3 = SetComputeUnitPrice(u64 micro-lamports). */\nexport function decodeComputeBudget(data: Uint8Array): {limit?: number; price?: bigint} {\n if (data[0] === 2 && data.length === 5) return {limit: new DataView(data.buffer, data.byteOffset + 1, 4).getUint32(0, true)};\n if (data[0] === 3 && data.length === 9) return {price: u64(data, 1)};\n throw new Error(`unexpected compute-budget instruction ${data[0]}`);\n}\n\nexport function setComputeUnitLimit(units: number): Uint8Array {\n const d = new Uint8Array(5);\n d[0] = 2;\n new DataView(d.buffer).setUint32(1, units, true);\n return d;\n}\n\nexport function setComputeUnitPrice(microLamports: bigint): Uint8Array {\n const d = new Uint8Array(9);\n d[0] = 3;\n new DataView(d.buffer).setBigUint64(1, microLamports, true);\n return d;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,iBAIO;;;ACHP,0BAAsC;AAM/B,IAAM,yBAAyB;AAC/B,IAAM,iBAAiB;AAKvB,IAAM,YAAY;AAUzB,IAAM,SAAS,oBAAI,IAAI,CAAC,IAAI,UAAU,OAAO,gBAAgB,UAAU,YAAY,GAAG,4CAA4C,CAAC;;;ACrBnI,kBAAqB;AAoBd,IAAM,aAAa,CAAC,MAA0B,mBAAO,OAAO,CAAC;AA+B7D,SAAS,oBAAoB,OAA2B;AAC7D,QAAM,IAAI,IAAI,WAAW,CAAC;AAC1B,IAAE,CAAC,IAAI;AACP,MAAI,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,IAAI;AAC/C,SAAO;AACT;AAEO,SAAS,oBAAoB,eAAmC;AACrE,QAAM,IAAI,IAAI,WAAW,CAAC;AAC1B,IAAE,CAAC,IAAI;AACP,MAAI,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,eAAe,IAAI;AAC1D,SAAO;AACT;;;AFxCA,IAAM,OAAO,CAAC,MACZ,EAAE,WAAY,EAAE,aAAa,uBAAY,kBAAkB,uBAAY,kBAAmB,EAAE,aAAa,uBAAY,WAAW,uBAAY;AAE9I,IAAM,gBAAgB,CAAC,QAAyC;AAAA,EAC9D,oBAAgB,oBAAQ,GAAG,SAAS;AAAA,EACpC,UAAU,GAAG,SAAS,IAAI,CAAC,OAAO,EAAC,aAAS,oBAAQ,EAAE,MAAM,GAAG,MAAM,KAAK,CAAC,EAAC,EAAE;AAAA,EAC9E,MAAM,WAAW,GAAG,IAAI;AAC1B;AAGO,SAAS,oBAAoB,OAA8B;AAChE,QAAM,SAAwB;AAAA,IAC5B,EAAC,oBAAgB,oBAAQ,sBAAsB,GAAG,MAAM,oBAAoB,MAAM,gBAAgB,EAAC;AAAA,IACnG,EAAC,oBAAgB,oBAAQ,sBAAsB,GAAG,MAAM,oBAAoB,MAAM,gBAAgB,EAAC;AAAA,EACrG;AACA,QAAM,YAAa,OAAO,MAAM,cAAc,WAAW,MAAM,gBAAY,6BAAiB,EAAE,OAAO,MAAM,SAAS;AACpH,QAAM,SAAqC,CAAC;AAC5C,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,MAAM,iCAAiC,CAAC,CAAC,EAAG,YAAO,oBAAQ,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,UAAM,oBAAQ,CAAC,CAAC;AAC1I,QAAM,cAAU;AAAA,QACd,qCAAyB,EAAC,SAAS,EAAC,CAAC;AAAA,IACrC,CAAC,UAAM,8CAA8B,oBAAQ,MAAM,KAAK,GAAG,CAAC;AAAA,IAC5D,CAAC,UAAM,wDAA4C,EAAC,WAAW,sBAAsB,OAAO,MAAM,oBAAoB,EAAC,GAAG,CAAC;AAAA,IAC3H,CAAC,UAAM,iDAAqC,CAAC,GAAG,QAAQ,GAAG,MAAM,aAAa,IAAI,aAAa,CAAC,GAAG,CAAC;AAAA,IACpG,CAAC,MAAO,OAAO,KAAK,MAAM,EAAE,aAAS,+DAAmD,GAAG,MAAM,IAAI;AAAA,EACvG;AACA,aAAO,gDAAgC,+BAAmB,OAAO,CAAC;AACpE;","names":[]}
@@ -0,0 +1,23 @@
1
+ interface JupiterInstruction {
2
+ programId: string;
3
+ accounts: {
4
+ pubkey: string;
5
+ isSigner: boolean;
6
+ isWritable: boolean;
7
+ }[];
8
+ data: string;
9
+ }
10
+ interface AssembleInput {
11
+ taker: string;
12
+ /** setup → swap → cleanup → other, in that order; compute-budget instructions are ours and come first. */
13
+ instructions: JupiterInstruction[];
14
+ computeUnitLimit: number;
15
+ computeUnitPrice: bigint;
16
+ blockhash: Uint8Array | string;
17
+ lastValidBlockHeight: number | bigint;
18
+ addressesByLookupTableAddress: Record<string, string[]> | null | undefined;
19
+ }
20
+ /** The unsigned transaction as base64 wire bytes (what `TxRequest.serializedTx` carries). */
21
+ declare function assembleTransaction(input: AssembleInput): string;
22
+
23
+ export { type AssembleInput, type JupiterInstruction, assembleTransaction };