tollkit-wallet 0.2.2 → 0.3.1

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 (64) hide show
  1. package/README.md +13 -0
  2. package/dist/actions.d.ts +131 -35
  3. package/dist/ai.d.ts +13 -1
  4. package/dist/ai.js +2 -2
  5. package/dist/ai.js.map +1 -1
  6. package/dist/autopilot.d.ts +7 -0
  7. package/dist/autopilot.js +118 -3
  8. package/dist/autopilot.js.map +1 -1
  9. package/dist/bots.d.ts +92 -0
  10. package/dist/bots.js +183 -0
  11. package/dist/bots.js.map +1 -0
  12. package/dist/bridge.js +7 -5
  13. package/dist/bridge.js.map +1 -1
  14. package/dist/dapp.d.ts +11 -0
  15. package/dist/dapp.js +82 -14
  16. package/dist/dapp.js.map +1 -1
  17. package/dist/dashboard.d.ts +12 -0
  18. package/dist/dashboard.js +136 -14
  19. package/dist/dashboard.js.map +1 -1
  20. package/dist/data/token-list.d.ts +12 -0
  21. package/dist/data/token-list.js +13 -0
  22. package/dist/data/token-list.js.map +1 -0
  23. package/dist/evmsend.d.ts +30 -0
  24. package/dist/evmsend.js +47 -0
  25. package/dist/evmsend.js.map +1 -0
  26. package/dist/holdings.d.ts +6 -0
  27. package/dist/holdings.js +41 -8
  28. package/dist/holdings.js.map +1 -1
  29. package/dist/ledger.d.ts +1 -0
  30. package/dist/ledger.js.map +1 -1
  31. package/dist/mcp.d.ts +1 -1
  32. package/dist/mcp.js +1 -1
  33. package/dist/pay.js +1 -1
  34. package/dist/pay.js.map +1 -1
  35. package/dist/policy.d.ts +2 -2
  36. package/dist/rules.d.ts +57 -6
  37. package/dist/rules.js +46 -4
  38. package/dist/rules.js.map +1 -1
  39. package/dist/seller.js +15 -4
  40. package/dist/seller.js.map +1 -1
  41. package/dist/send.js +3 -2
  42. package/dist/send.js.map +1 -1
  43. package/dist/solconfirm.d.ts +13 -0
  44. package/dist/solconfirm.js +21 -0
  45. package/dist/solconfirm.js.map +1 -0
  46. package/dist/stake.js +3 -2
  47. package/dist/stake.js.map +1 -1
  48. package/dist/swap.d.ts +58 -5
  49. package/dist/swap.js +327 -21
  50. package/dist/swap.js.map +1 -1
  51. package/dist/tokenlist.d.ts +70 -0
  52. package/dist/tokenlist.js +259 -0
  53. package/dist/tokenlist.js.map +1 -0
  54. package/dist/trademode.d.ts +3 -0
  55. package/dist/trademode.js +23 -0
  56. package/dist/trademode.js.map +1 -0
  57. package/dist/ui.js +202 -19
  58. package/dist/ui.js.map +1 -1
  59. package/dist/wallet.d.ts +13 -1
  60. package/dist/wallet.js +85 -5
  61. package/dist/wallet.js.map +1 -1
  62. package/extension/background.js +1 -1
  63. package/extension/popup.js +1 -1
  64. package/package.json +2 -2
@@ -0,0 +1,21 @@
1
+ export async function sendAndConfirm(conn, tx, signers, o = {}) {
2
+ const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash("confirmed");
3
+ tx.recentBlockhash = blockhash;
4
+ if (!tx.feePayer)
5
+ tx.feePayer = signers[0].publicKey;
6
+ tx.sign(...signers);
7
+ const sig = await conn.sendRawTransaction(tx.serialize(), { preflightCommitment: "confirmed", maxRetries: 3 });
8
+ const until = Date.now() + (o.maxMs ?? 90_000);
9
+ for (;;) {
10
+ const st = (await conn.getSignatureStatuses([sig])).value[0];
11
+ if (st?.err)
12
+ throw new Error(`Solana transaction ${sig} failed: ${JSON.stringify(st.err)}`);
13
+ if (st && (st.confirmationStatus === "confirmed" || st.confirmationStatus === "finalized"))
14
+ return sig;
15
+ if (Date.now() > until || (await conn.getBlockHeight("confirmed")) > lastValidBlockHeight) {
16
+ throw new Error(`Solana transaction ${sig} wasn't confirmed in time. Check it on an explorer before trying again.`);
17
+ }
18
+ await new Promise((r) => setTimeout(r, o.pollMs ?? 1500));
19
+ }
20
+ }
21
+ //# sourceMappingURL=solconfirm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solconfirm.js","sourceRoot":"","sources":["../src/solconfirm.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAgB,EAAE,EAAe,EAAE,OAAkB,EAAE,IAAyC,EAAE;IACrI,MAAM,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACvF,EAAE,CAAC,eAAe,GAAG,SAAS,CAAC;IAC/B,IAAI,CAAC,EAAE,CAAC,QAAQ;QAAE,EAAE,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,SAAS,CAAC;IACtD,EAAE,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IACpB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,EAAE,mBAAmB,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/G,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC;IAC/C,SAAS,CAAC;QACR,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7D,IAAI,EAAE,EAAE,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,YAAY,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5F,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,kBAAkB,KAAK,WAAW,IAAI,EAAE,CAAC,kBAAkB,KAAK,WAAW,CAAC;YAAE,OAAO,GAAG,CAAC;QACvG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,GAAG,oBAAoB,EAAE,CAAC;YAC1F,MAAM,IAAI,KAAK,CAAC,sBAAsB,GAAG,yEAAyE,CAAC,CAAC;QACtH,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
package/dist/stake.js CHANGED
@@ -13,7 +13,8 @@
13
13
  * Staking moves no money out of the wallet's control, so it isn't counted against spending limits,
14
14
  * but it needs the password every time and agents can't reach it.
15
15
  */
16
- import { Authorized, Connection, Lockup, PublicKey, StakeProgram, Transaction, ValidatorInfo, sendAndConfirmTransaction } from "@solana/web3.js";
16
+ import { Authorized, Connection, Lockup, PublicKey, StakeProgram, Transaction, ValidatorInfo } from "@solana/web3.js";
17
+ import { sendAndConfirm } from "./solconfirm.js";
17
18
  export const CONFIG_PROGRAM = new PublicKey("Config1111111111111111111111111111111111111");
18
19
  const U64_MAX = "18446744073709551615";
19
20
  const LAMPORTS = 1_000_000_000;
@@ -152,7 +153,7 @@ export class Staking {
152
153
  send(tx, kp) {
153
154
  if (this.o.send)
154
155
  return this.o.send(tx, kp);
155
- return sendAndConfirmTransaction(new Connection(this.o.rpc, "confirmed"), tx, [kp]);
156
+ return sendAndConfirm(new Connection(this.o.rpc, "confirmed"), tx, [kp]);
156
157
  }
157
158
  }
158
159
  //# sourceMappingURL=stake.js.map
package/dist/stake.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stake.js","sourceRoot":"","sources":["../src/stake.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stake.js","sourceRoot":"","sources":["../src/stake.ts"],"names":[],"mappings":"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"}
package/dist/swap.d.ts CHANGED
@@ -4,11 +4,16 @@
4
4
  * quote proxy (api.tollkit.dev/wallet/...), which holds the 0x and Jupiter API
5
5
  * keys and adds the flat 0.5% fee; it only ever sees public data and signed
6
6
  * transactions, never keys. The wallet checks every quote before signing:
7
- * fee not above 0.5%, the only approval ever given is to 0x AllowanceHolder,
8
- * the transaction goes to AllowanceHolder, and the minimum output is set.
7
+ * fee not above 0.5%, the only approval ever given is to 0x AllowanceHolder
8
+ * (exact amount), and the minimum output is set. It doesn't trust the quote
9
+ * server with what it signs (0.2.3): verifySwapTx decodes 0x calldata (exact
10
+ * token, amount and ETH value; the Settler call must pay this wallet the buy
11
+ * token with the minimum shown; Settler must be listed by 0x's on-chain
12
+ * registry, github.com/0xProject/0x-settler README), and simulates Solana
13
+ * swaps, refusing any that take more than the coin being sold.
9
14
  */
10
- import { Connection, Keypair } from "@solana/web3.js";
11
- import { type Wallet, type HDNodeWallet } from "ethers";
15
+ import { Connection, Keypair, PublicKey, VersionedTransaction } from "@solana/web3.js";
16
+ import { JsonRpcProvider, type Wallet, type HDNodeWallet } from "ethers";
12
17
  import { type Chain } from "./chains.js";
13
18
  type Fetch = typeof fetch;
14
19
  export declare const DEFAULT_PROXY = "https://api.tollkit.dev/wallet";
@@ -31,21 +36,69 @@ export interface SwapQuote {
31
36
  venue_fee_bps: number;
32
37
  usd_value: number | null;
33
38
  fee_usd: number | null;
39
+ /** Solana only: Jupiter's route doesn't carry Tollkit's fee, so the wallet sends it on its own, in SOL, after the swap. */
40
+ fee_separate?: boolean;
41
+ /** Solana only: built from Jupiter's instructions with Tollkit's fee (in SOL) inside the same transaction. */
42
+ fee_inline?: boolean;
34
43
  raw: any;
35
44
  }
45
+ /**
46
+ * Jupiter pays Tollkit's 0.5% out of the route only when Tollkit has a fee account for the token Jupiter picks to
47
+ * take the fee in (it prefers SOL, then stablecoins, then other tokens). For any other token the order comes back
48
+ * with Jupiter's own default fee instead (developers.jup.ag/docs/swap/fees: "the order still returns but executes
49
+ * without your fees"), and Tollkit's fee is sent separately.
50
+ */
51
+ export declare function jupiterFeeInRoute(raw: any): boolean;
52
+ /** The coin Tollkit's fee is taken in on Base and Ethereum: a stablecoin side first, then ETH or WETH, else the coin sold. */
53
+ export declare function feeTokenFor(chain: Chain, sell: string, buy: string): string;
54
+ /** Tollkit's 0.5% in lamports: straight from the SOL side when there is one, else the trade's dollar value at SOL's price. */
55
+ export declare function solFeeLamports(q: Pick<SwapQuote, "sell_token" | "buy_token" | "sell_amount" | "buy_amount">, usd: number | null, solUsd: number | null): bigint;
36
56
  /** Dollar value of the sell side when either side is a stablecoin; else null (caller prices it). */
37
57
  export declare function stableValue(q: Pick<SwapQuote, "chain" | "sell_token" | "buy_token" | "sell_amount" | "buy_amount">): number | null;
38
58
  export declare function getQuote(req: SwapRequest, taker: string, opts?: {
39
59
  fetch?: Fetch;
40
60
  proxy?: string;
61
+ build?: boolean;
41
62
  }): Promise<SwapQuote>;
42
63
  /** Everything the wallet refuses to sign. Returns a reason, or null if the quote is safe. */
43
- export declare function vetQuote(q: SwapQuote, req: SwapRequest): string | null;
64
+ export declare function vetQuote(q: SwapQuote, req: SwapRequest, taker?: string): string | null;
65
+ /** 0x Settler registry, the same address on every chain; feature 2 = taker-submitted swaps. */
66
+ export declare const SETTLER_REGISTRY = "0x00000000000004533Fe15556B1E086BB1A72cEae";
67
+ /** Decode a 0x quote's transaction and check it does only the swap shown. Returns the Settler address it uses. */
68
+ export declare function checkZeroExTx(q: SwapQuote, taker: string): string;
69
+ /** Programs a Solana swap may call directly. JUP6…: Jupiter's router (Metis), as seen in live Ultra orders. */
70
+ export declare const SWAP_PROGRAMS: Set<string>;
71
+ export interface VerifyDeps {
72
+ /** A Solana transaction the wallet assembled itself (Jupiter's router path), and the SOL it adds for Tollkit's fee. */ vtx?: VersionedTransaction;
73
+ extraLamports?: bigint;
74
+ /** eth_call on the swap's chain; returns the hex result. */ evmCall?: (chain: Chain, to: string, data: string) => Promise<string>;
75
+ /** Solana connection (tests pass a fake). */ conn?: Pick<Connection, "getBalance" | "getParsedTokenAccountsByOwner" | "simulateTransaction"> & {
76
+ getAddressLookupTable?: Connection["getAddressLookupTable"];
77
+ };
78
+ }
79
+ /** Before signing: check the quote server's transaction does only the swap that was shown. Throws if not. */
80
+ export declare function verifySwapTx(q: SwapQuote, me: {
81
+ evm: string;
82
+ solana: PublicKey;
83
+ }, d?: VerifyDeps & ExecDeps): Promise<void>;
44
84
  export interface ExecDeps {
45
85
  rpc?: Partial<Record<Chain, string>>;
46
86
  fetch?: Fetch;
47
87
  proxy?: string;
88
+ verify?: VerifyDeps; /** tests: the EVM provider to send with */
89
+ provider?: JsonRpcProvider; /** tests: how often to check a Solana send */
90
+ pollMs?: number;
48
91
  }
92
+ /**
93
+ * Jupiter's router instructions (Swap API v2 /build) plus Tollkit's fee as a plain SOL transfer, in one v0
94
+ * transaction: compute-unit limit from a simulation (x1.2, at most 1.4M), Jupiter's priority price, a fresh
95
+ * blockhash. Checked with the same rules as any swap, then sent and confirmed by polling.
96
+ */
97
+ export declare function assembleBuilt(q: SwapQuote, payer: PublicKey, conn: Pick<Connection, "getLatestBlockhash" | "simulateTransaction">): Promise<{
98
+ tx: VersionedTransaction;
99
+ lastValidBlockHeight: number;
100
+ feeLamports: bigint;
101
+ }>;
49
102
  /** Sign and send. Returns the transaction hash / signature. */
50
103
  export declare function executeSwap(q: SwapQuote, keys: {
51
104
  evm: Wallet | HDNodeWallet;
package/dist/swap.js CHANGED
@@ -4,13 +4,53 @@
4
4
  * quote proxy (api.tollkit.dev/wallet/...), which holds the 0x and Jupiter API
5
5
  * keys and adds the flat 0.5% fee; it only ever sees public data and signed
6
6
  * transactions, never keys. The wallet checks every quote before signing:
7
- * fee not above 0.5%, the only approval ever given is to 0x AllowanceHolder,
8
- * the transaction goes to AllowanceHolder, and the minimum output is set.
7
+ * fee not above 0.5%, the only approval ever given is to 0x AllowanceHolder
8
+ * (exact amount), and the minimum output is set. It doesn't trust the quote
9
+ * server with what it signs (0.2.3): verifySwapTx decodes 0x calldata (exact
10
+ * token, amount and ETH value; the Settler call must pay this wallet the buy
11
+ * token with the minimum shown; Settler must be listed by 0x's on-chain
12
+ * registry, github.com/0xProject/0x-settler README), and simulates Solana
13
+ * swaps, refusing any that take more than the coin being sold.
9
14
  */
10
- import { Connection, VersionedTransaction } from "@solana/web3.js";
11
- import { Contract, JsonRpcProvider } from "ethers";
12
- import { ALLOWANCE_HOLDER, DEFAULT_RPC, EVM_CHAIN_ID, STABLES, SWAP_FEE_BPS, isStable } from "./chains.js";
15
+ import { AddressLookupTableAccount, ComputeBudgetProgram, Connection, PublicKey, SystemProgram, TransactionInstruction, TransactionMessage, VersionedTransaction } from "@solana/web3.js";
16
+ import { AbiCoder, Contract, Interface, JsonRpcProvider, ZeroAddress } from "ethers";
17
+ import { KNOWN } from "./tokens.js";
18
+ import { sendingProvider, waitMined } from "./evmsend.js";
19
+ import { ALLOWANCE_HOLDER, DEFAULT_RPC, EVM_CHAIN_ID, NATIVE_EVM, STABLES, SWAP_FEE_BPS, WSOL, isStable } from "./chains.js";
13
20
  export const DEFAULT_PROXY = "https://api.tollkit.dev/wallet";
21
+ /**
22
+ * Jupiter pays Tollkit's 0.5% out of the route only when Tollkit has a fee account for the token Jupiter picks to
23
+ * take the fee in (it prefers SOL, then stablecoins, then other tokens). For any other token the order comes back
24
+ * with Jupiter's own default fee instead (developers.jup.ag/docs/swap/fees: "the order still returns but executes
25
+ * without your fees"), and Tollkit's fee is sent separately.
26
+ */
27
+ export function jupiterFeeInRoute(raw) {
28
+ return !!raw?.referralAccount && Number(raw?.platformFee?.feeBps ?? raw?.feeBps) === SWAP_FEE_BPS;
29
+ }
30
+ /** The coin Tollkit's fee is taken in on Base and Ethereum: a stablecoin side first, then ETH or WETH, else the coin sold. */
31
+ export function feeTokenFor(chain, sell, buy) {
32
+ const eth = (t) => t.toLowerCase() === NATIVE_EVM.toLowerCase() || t.toLowerCase() === KNOWN[chain]?.WETH?.address?.toLowerCase();
33
+ if (isStable(chain, sell))
34
+ return sell;
35
+ if (isStable(chain, buy))
36
+ return buy;
37
+ if (eth(sell))
38
+ return sell;
39
+ if (eth(buy))
40
+ return buy;
41
+ return sell;
42
+ }
43
+ /** Tollkit's 0.5% in lamports: straight from the SOL side when there is one, else the trade's dollar value at SOL's price. */
44
+ export function solFeeLamports(q, usd, solUsd) {
45
+ const bps = BigInt(SWAP_FEE_BPS);
46
+ if (q.sell_token === WSOL)
47
+ return (BigInt(q.sell_amount) * bps) / 10000n;
48
+ if (q.buy_token === WSOL)
49
+ return (BigInt(q.buy_amount) * bps) / 10000n;
50
+ if (!(usd && usd > 0) || !(solUsd && solUsd > 0))
51
+ throw new Error("No SOL price right now to work out Tollkit's fee. Try again in a minute.");
52
+ return BigInt(Math.ceil(((usd * SWAP_FEE_BPS) / 10000 / solUsd) * 1e9));
53
+ }
14
54
  const decimalsOf = (chain, token) => (chain === "solana" ? STABLES.solana[token] : STABLES[chain][token.toLowerCase()])?.decimals;
15
55
  async function getJson(f, url, init) {
16
56
  const r = await f(url, { ...init, signal: AbortSignal.timeout(20_000) });
@@ -33,23 +73,48 @@ export async function getQuote(req, taker, opts = {}) {
33
73
  const u = new URL(`${proxy}/swap/solana/order`);
34
74
  u.search = new URLSearchParams({ inputMint: req.sell_token, outputMint: req.buy_token, amount: req.sell_amount, taker, slippageBps: String(req.slippage_bps) }).toString();
35
75
  const j = await getJson(f, u.toString());
76
+ const inRoute = jupiterFeeInRoute(j);
77
+ if (!inRoute && opts.build !== false) {
78
+ // No Tollkit fee account for the coin Jupiter would take the fee in: build the swap from Jupiter's router
79
+ // instructions instead, so Tollkit's 0.5% (in SOL) goes in the same transaction. If that path isn't
80
+ // available, fall back to the order with the fee sent right after (below).
81
+ try {
82
+ const bu = new URL(`${proxy}/swap/solana/build`);
83
+ bu.search = new URLSearchParams({ inputMint: req.sell_token, outputMint: req.buy_token, amount: req.sell_amount, taker, slippageBps: String(req.slippage_bps) }).toString();
84
+ const b = await getJson(f, bu.toString());
85
+ if (b?.swapInstruction && b?.tollkit_fee && typeof b.tollkit_fee.recipient === "string") {
86
+ return withUsd({
87
+ chain: "solana", venue: "jupiter", sell_token: req.sell_token, buy_token: req.buy_token,
88
+ sell_amount: String(b.inAmount ?? req.sell_amount), buy_amount: String(b.outAmount), min_buy_amount: String(b.otherAmountThreshold ?? b.outAmount),
89
+ fee_bps: Number(b.tollkit_fee.bps) === 0 ? 0 : SWAP_FEE_BPS, venue_fee_bps: 0, usd_value: null, fee_usd: null,
90
+ raw: { build: b, swapUsdValue: j.swapUsdValue, inUsdValue: j.inUsdValue }, fee_inline: true,
91
+ });
92
+ }
93
+ }
94
+ catch { /* the order below, with the fee sent separately */ }
95
+ }
36
96
  const q = {
37
97
  chain: "solana", venue: "jupiter", sell_token: req.sell_token, buy_token: req.buy_token,
38
98
  sell_amount: String(j.inAmount ?? req.sell_amount), buy_amount: String(j.outAmount), min_buy_amount: String(j.otherAmountThreshold ?? j.outAmount),
39
- fee_bps: Number(j.feeBps ?? SWAP_FEE_BPS), venue_fee_bps: 0, usd_value: null, fee_usd: null, raw: j,
99
+ // Tollkit's fee is always 0.5%; when the route doesn't carry it, whatever the route does carry is Jupiter's own.
100
+ fee_bps: SWAP_FEE_BPS, venue_fee_bps: inRoute ? 0 : Math.max(0, Number(j.platformFee?.feeBps ?? j.feeBps ?? 0) || 0),
101
+ usd_value: null, fee_usd: null, raw: j, ...(inRoute ? {} : { fee_separate: true }),
40
102
  };
41
103
  return withUsd(q);
42
104
  }
43
105
  const u = new URL(`${proxy}/swap/evm/quote`);
44
- u.search = new URLSearchParams({ chainId: String(EVM_CHAIN_ID[req.chain]), sellToken: req.sell_token, buyToken: req.buy_token, sellAmount: req.sell_amount, taker, slippageBps: String(req.slippage_bps) }).toString();
106
+ u.search = new URLSearchParams({ chainId: String(EVM_CHAIN_ID[req.chain]), sellToken: req.sell_token, buyToken: req.buy_token, sellAmount: req.sell_amount, taker, slippageBps: String(req.slippage_bps), feeToken: feeTokenFor(req.chain, req.sell_token, req.buy_token) }).toString();
45
107
  const j = await getJson(f, u.toString());
46
- const feeAmt = BigInt(j?.fees?.integratorFee?.amount ?? "0");
47
- const sell = BigInt(j.sellAmount ?? req.sell_amount);
48
- const feeBps = sell > 0n ? Number((feeAmt * 10000n) / sell) : 0;
108
+ const sell = BigInt(j.sellAmount ?? req.sell_amount), buy = BigInt(j.buyAmount ?? "0");
109
+ // A fee is a share of the side it's taken from: the amount sold, or what was bought before the fee came off.
110
+ const share = (fee) => {
111
+ const amt = BigInt(fee?.amount ?? "0"), tok = String(fee?.token ?? req.sell_token).toLowerCase();
112
+ const base = tok === req.buy_token.toLowerCase() ? buy + amt : tok === req.sell_token.toLowerCase() ? sell : 0n;
113
+ return base > 0n ? Number((amt * 20000n / base + 1n) / 2n) : 0;
114
+ };
115
+ const feeBps = share(j?.fees?.integratorFee);
49
116
  // 0x's own fee (0.15% on select pairs on the Standard plan), shown to the user too.
50
- const zx = BigInt(j?.fees?.zeroExFee?.amount ?? "0");
51
- const zxToken = String(j?.fees?.zeroExFee?.token ?? "").toLowerCase();
52
- const venueBps = sell > 0n && zxToken === req.sell_token.toLowerCase() ? Number((zx * 10000n) / sell) : 0;
117
+ const venueBps = j?.fees?.zeroExFee ? share(j.fees.zeroExFee) : 0;
53
118
  return withUsd({
54
119
  chain: req.chain, venue: "0x", sell_token: req.sell_token, buy_token: req.buy_token,
55
120
  sell_amount: String(j.sellAmount ?? req.sell_amount), buy_amount: String(j.buyAmount), min_buy_amount: String(j.minBuyAmount ?? j.buyAmount),
@@ -61,7 +126,9 @@ function withUsd(q) {
61
126
  return { ...q, usd_value: usd, fee_usd: usd === null ? null : (usd * q.fee_bps) / 10000 };
62
127
  }
63
128
  /** Everything the wallet refuses to sign. Returns a reason, or null if the quote is safe. */
64
- export function vetQuote(q, req) {
129
+ export function vetQuote(q, req, taker) {
130
+ if (q.sell_amount !== req.sell_amount)
131
+ return "The quote is for a different amount than requested.";
65
132
  if (q.fee_bps > SWAP_FEE_BPS)
66
133
  return `The quote carries a ${q.fee_bps / 100}% fee; Tollkit's fee is ${SWAP_FEE_BPS / 100}%.`;
67
134
  if (!(BigInt(q.min_buy_amount) > 0n))
@@ -75,18 +142,256 @@ export function vetQuote(q, req) {
75
142
  const spender = q.raw?.issues?.allowance?.spender;
76
143
  if (spender && String(spender).toLowerCase() !== ALLOWANCE_HOLDER.toLowerCase())
77
144
  return `The quote asks to approve ${spender}; only 0x AllowanceHolder is ever approved.`;
78
- if (q.sell_amount !== req.sell_amount)
79
- return "The quote is for a different amount than requested.";
145
+ if (taker && tx.data !== undefined) {
146
+ try {
147
+ checkZeroExTx(q, taker);
148
+ }
149
+ catch (e) {
150
+ return e.message;
151
+ }
152
+ }
80
153
  }
81
154
  else {
82
- if (!q.raw?.transaction || !q.raw?.requestId)
155
+ if (q.raw?.build) {
156
+ if (!q.raw.build.swapInstruction)
157
+ return "The quote has no swap instruction.";
158
+ }
159
+ else if (!q.raw?.transaction || !q.raw?.requestId)
83
160
  return "The quote has no transaction.";
84
161
  }
85
162
  return null;
86
163
  }
87
164
  const ERC20 = ["function approve(address spender, uint256 amount) returns (bool)", "function allowance(address owner, address spender) view returns (uint256)"];
165
+ /** 0x Settler registry, the same address on every chain; feature 2 = taker-submitted swaps. */
166
+ export const SETTLER_REGISTRY = "0x00000000000004533Fe15556B1E086BB1A72cEae";
167
+ const ALLOWANCE_EXEC = new Interface(["function exec(address operator, address token, uint256 amount, address target, bytes data)"]);
168
+ const SETTLER_EXECUTE = "0x1fff991f"; // execute((address recipient, address buyToken, uint256 minAmountOut), bytes[], bytes32)
169
+ /** Decode a 0x quote's transaction and check it does only the swap shown. Returns the Settler address it uses. */
170
+ export function checkZeroExTx(q, taker) {
171
+ const t = q.raw?.transaction ?? {};
172
+ const native = q.sell_token.toLowerCase() === NATIVE_EVM.toLowerCase();
173
+ const value = BigInt(t.value ?? "0"), sell = BigInt(q.sell_amount);
174
+ if (String(t.to ?? "").toLowerCase() !== ALLOWANCE_HOLDER.toLowerCase())
175
+ throw new Error("The swap isn't sent to 0x AllowanceHolder.");
176
+ if (value !== (native ? sell : 0n))
177
+ throw new Error("The swap would send a different amount of ETH than you're selling.");
178
+ let p = null;
179
+ try {
180
+ p = ALLOWANCE_EXEC.parseTransaction({ data: String(t.data ?? "") });
181
+ }
182
+ catch {
183
+ p = null;
184
+ }
185
+ if (!p || p.name !== "exec")
186
+ throw new Error("The swap transaction isn't a 0x swap.");
187
+ const [operator, token, amount, target, inner] = p.args;
188
+ if (token.toLowerCase() !== (native ? ZeroAddress : q.sell_token).toLowerCase() || amount !== sell)
189
+ throw new Error("The swap would take a different coin or amount than you're selling.");
190
+ if (operator.toLowerCase() !== target.toLowerCase())
191
+ throw new Error("The swap transaction isn't a 0x swap.");
192
+ if (!inner.startsWith(SETTLER_EXECUTE) || inner.length < 10 + 64 * 3)
193
+ throw new Error("The swap transaction isn't a 0x swap.");
194
+ const [recipient, buyToken, minOut] = AbiCoder.defaultAbiCoder().decode(["address", "address", "uint256"], "0x" + inner.slice(10, 10 + 64 * 3));
195
+ if (recipient.toLowerCase() !== taker.toLowerCase())
196
+ throw new Error("The swap would pay someone other than this wallet.");
197
+ if (buyToken.toLowerCase() !== q.buy_token.toLowerCase())
198
+ throw new Error("The swap would buy a different coin.");
199
+ if (minOut !== BigInt(q.min_buy_amount))
200
+ throw new Error("The swap's minimum doesn't match the quote shown.");
201
+ return target;
202
+ }
203
+ const TOKEN_PROGRAMS = ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"];
204
+ const ATA_PROGRAM = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
205
+ /** Programs a Solana swap may call directly. JUP6…: Jupiter's router (Metis), as seen in live Ultra orders. */
206
+ export const SWAP_PROGRAMS = new Set(["ComputeBudget111111111111111111111111111111", "11111111111111111111111111111111", ...TOKEN_PROGRAMS, ATA_PROGRAM, "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"]);
207
+ /** Before signing: check the quote server's transaction does only the swap that was shown. Throws if not. */
208
+ export async function verifySwapTx(q, me, d = {}) {
209
+ if (q.venue === "0x") {
210
+ const settler = checkZeroExTx(q, me.evm).toLowerCase();
211
+ const call = d.evmCall ?? ((chain, to, data) => new JsonRpcProvider(d.rpc?.[chain] ?? DEFAULT_RPC[chain], EVM_CHAIN_ID[chain], { staticNetwork: true }).call({ to, data }));
212
+ const reg = async (sel) => { try {
213
+ return String(AbiCoder.defaultAbiCoder().decode(["address"], await call(q.chain, SETTLER_REGISTRY, sel + "0".repeat(63) + "2"))[0]).toLowerCase();
214
+ }
215
+ catch {
216
+ return "";
217
+ } };
218
+ // ownerOf(2) is the current Settler; prev(2) the one before, still used while 0x's API catches up.
219
+ if ((await reg("0x6352211e")) !== settler && (await reg("0xe2603dc2")) !== settler)
220
+ throw new Error("The swap goes through a contract 0x's registry doesn't list. Not signing it.");
221
+ return;
222
+ }
223
+ let vtx;
224
+ if (d.vtx)
225
+ vtx = d.vtx;
226
+ else
227
+ try {
228
+ vtx = VersionedTransaction.deserialize(Buffer.from(String(q.raw?.transaction ?? ""), "base64"));
229
+ }
230
+ catch {
231
+ throw new Error("The quote's transaction can't be read.");
232
+ }
233
+ const signers = vtx.message.staticAccountKeys.slice(0, vtx.message.header.numRequiredSignatures);
234
+ if (!signers.some((k) => k.equals(me.solana)))
235
+ throw new Error("The quote's transaction isn't for this wallet.");
236
+ const conn = d.conn ?? new Connection(d.rpc?.solana ?? DEFAULT_RPC.solana, "confirmed");
237
+ const fail = () => new Error("Couldn't check this swap before signing. Try again in a moment.");
238
+ // Only programs whose behaviour is known: Jupiter's own router (Metis, seen in live orders 2026-10-14) and the
239
+ // Solana programs a swap needs. A route through anything else is refused rather than trusted.
240
+ const statics = vtx.message.staticAccountKeys;
241
+ for (const ix of vtx.message.compiledInstructions) {
242
+ const prog = statics[ix.programIdIndex]?.toBase58();
243
+ if (!prog || !SWAP_PROGRAMS.has(prog))
244
+ throw new Error("This swap route goes through a program Tollkit doesn't sign for. Try again in a moment or change the amount.");
245
+ if (prog === "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" || prog === "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb") {
246
+ // Approve, ApproveChecked, SetAuthority: never part of a swap.
247
+ if ([4, 6, 13].includes(ix.data[0]))
248
+ throw new Error("This swap would change who controls your tokens. Not signing it.");
249
+ }
250
+ }
251
+ const held = new Map();
252
+ try {
253
+ for (const prog of TOKEN_PROGRAMS) {
254
+ const r = await conn.getParsedTokenAccountsByOwner(me.solana, { programId: new PublicKey(prog) });
255
+ for (const a of r.value) {
256
+ const i = a.account.data.parsed?.info;
257
+ if (i)
258
+ held.set(a.pubkey.toBase58(), { mint: i.mint, amount: BigInt(i.tokenAmount.amount), delegate: i.delegate ?? null, close: i.closeAuthority ?? null });
259
+ }
260
+ }
261
+ }
262
+ catch {
263
+ throw fail();
264
+ }
265
+ const luts = [];
266
+ for (const l of vtx.message.addressTableLookups ?? []) {
267
+ const t = await conn.getAddressLookupTable?.(l.accountKey).catch(() => null);
268
+ if (!t?.value)
269
+ throw fail();
270
+ luts.push(t.value);
271
+ }
272
+ const keys = vtx.message.getAccountKeys({ addressLookupTableAccounts: luts });
273
+ const watch = [];
274
+ for (let i = 0; i < keys.length; i++) {
275
+ const k = keys.get(i).toBase58();
276
+ if (held.has(k) && vtx.message.isAccountWritable(i))
277
+ watch.push(k);
278
+ }
279
+ // The account the bought coin lands in, even if it doesn't exist yet (then it starts at 0).
280
+ const buyAtas = q.buy_token === WSOL ? [] : TOKEN_PROGRAMS.map((p) => ataOf(me.solana, new PublicKey(q.buy_token), new PublicKey(p))).filter((a) => !watch.includes(a));
281
+ const addresses = [me.solana.toBase58(), ...watch, ...buyAtas];
282
+ if (addresses.length > 128)
283
+ throw fail();
284
+ let sim;
285
+ try {
286
+ sim = await conn.simulateTransaction(vtx, { sigVerify: false, replaceRecentBlockhash: true, accounts: { encoding: "base64", addresses } });
287
+ }
288
+ catch {
289
+ throw fail();
290
+ }
291
+ const accs = sim?.value?.accounts;
292
+ if (sim?.value?.err || !accs?.[0])
293
+ throw fail();
294
+ const before = await conn.getBalance(me.solana);
295
+ if (accs[0].owner && accs[0].owner !== "11111111111111111111111111111111")
296
+ throw new Error("This swap would hand your wallet account to another program. Not signing it.");
297
+ const tokens = new Map();
298
+ const readTok = (a) => { const b = Buffer.from(String(a?.data?.[0] ?? ""), "base64"); return b.length >= 165 ? b : null; };
299
+ watch.forEach((addr, i) => {
300
+ const w = held.get(addr), a = accs[i + 1];
301
+ if (!a) {
302
+ tokens.set(w.mint, (tokens.get(w.mint) ?? 0n) - w.amount);
303
+ return;
304
+ }
305
+ const b = readTok(a);
306
+ if (!b)
307
+ return;
308
+ if (!b.subarray(32, 64).equals(me.solana.toBuffer()))
309
+ throw new Error("This swap would give one of your token accounts to someone else. Not signing it.");
310
+ const delegate = b.readUInt32LE(72) === 1 ? new PublicKey(b.subarray(76, 108)).toBase58() : null;
311
+ if (delegate && delegate !== w.delegate)
312
+ throw new Error("This swap would let another account spend your tokens later. Not signing it.");
313
+ const close = b.readUInt32LE(129) === 1 ? new PublicKey(b.subarray(133, 165)).toBase58() : null;
314
+ if (close && close !== w.close)
315
+ throw new Error("This swap would let another account close one of your token accounts. Not signing it.");
316
+ tokens.set(w.mint, (tokens.get(w.mint) ?? 0n) + b.readBigUInt64LE(64) - w.amount);
317
+ });
318
+ buyAtas.forEach((_addr, i) => {
319
+ const b = readTok(accs[watch.length + 1 + i]);
320
+ if (!b || !b.subarray(32, 64).equals(me.solana.toBuffer()) || new PublicKey(b.subarray(0, 32)).toBase58() !== q.buy_token)
321
+ return;
322
+ tokens.set(q.buy_token, (tokens.get(q.buy_token) ?? 0n) + b.readBigUInt64LE(64));
323
+ });
324
+ const sell = BigInt(q.sell_amount), sellingSol = q.sell_token === WSOL, buyingSol = q.buy_token === WSOL;
325
+ const solDelta = BigInt(accs[0].lamports) - BigInt(before) + (tokens.get(WSOL) ?? 0n);
326
+ // Network fees, priority fees and a new token account's deposit stay under 0.01 SOL.
327
+ // Plus Tollkit's fee when the wallet put it in this transaction itself.
328
+ const FEES = 10000000n + (d.extraLamports ?? 0n);
329
+ if (sellingSol && -solDelta > sell + FEES)
330
+ throw new Error("This swap would take more SOL than you're selling. Not signing it.");
331
+ if (!sellingSol && !buyingSol && -solDelta > FEES)
332
+ throw new Error("This swap would take more SOL than network fees. Not signing it.");
333
+ for (const [mint, delta] of tokens) {
334
+ if (delta >= 0n || mint === WSOL)
335
+ continue;
336
+ if (mint !== q.sell_token || -delta > sell)
337
+ throw new Error("This swap would take a coin you aren't selling, or more of it. Not signing it.");
338
+ }
339
+ const min = BigInt(q.min_buy_amount);
340
+ const got = buyingSol ? solDelta + FEES : (tokens.get(q.buy_token) ?? 0n);
341
+ if (got < min)
342
+ throw new Error("The checked swap pays less than the minimum shown. Not signing it.");
343
+ }
344
+ /** Associated token account address (the ATA program's seeds: owner, token program, mint). */
345
+ function ataOf(owner, mint, tokenProgram) {
346
+ return PublicKey.findProgramAddressSync([owner.toBuffer(), tokenProgram.toBuffer(), mint.toBuffer()], new PublicKey(ATA_PROGRAM))[0].toBase58();
347
+ }
348
+ const toIx = (i) => new TransactionInstruction({ programId: new PublicKey(i.programId), keys: (i.accounts ?? []).map((a) => ({ pubkey: new PublicKey(a.pubkey), isSigner: !!a.isSigner, isWritable: !!a.isWritable })), data: Buffer.from(String(i.data ?? ""), "base64") });
349
+ const COMPUTE_BUDGET = "ComputeBudget111111111111111111111111111111";
350
+ /**
351
+ * Jupiter's router instructions (Swap API v2 /build) plus Tollkit's fee as a plain SOL transfer, in one v0
352
+ * transaction: compute-unit limit from a simulation (x1.2, at most 1.4M), Jupiter's priority price, a fresh
353
+ * blockhash. Checked with the same rules as any swap, then sent and confirmed by polling.
354
+ */
355
+ export async function assembleBuilt(q, payer, conn) {
356
+ const b = q.raw.build, fee = q.raw.fee;
357
+ const feeLamports = fee ? BigInt(fee.lamports) : 0n;
358
+ const price = (b.computeBudgetInstructions ?? []).map(toIx).filter((ix) => !(ix.programId.toBase58() === COMPUTE_BUDGET && ix.data[0] === 2));
359
+ const body = [...(b.setupInstructions ?? []).map(toIx), toIx(b.swapInstruction), ...(b.cleanupInstruction ? [toIx(b.cleanupInstruction)] : []), ...(b.otherInstructions ?? []).map(toIx)];
360
+ if (feeLamports > 0n)
361
+ body.push(SystemProgram.transfer({ fromPubkey: payer, toPubkey: new PublicKey(fee.to), lamports: feeLamports }));
362
+ const luts = Object.entries(b.addressesByLookupTableAddress ?? {}).map(([key, addrs]) => new AddressLookupTableAccount({ key: new PublicKey(key), state: { deactivationSlot: 18446744073709551615n, lastExtendedSlot: 0, lastExtendedSlotStartIndex: 0, addresses: addrs.map((a) => new PublicKey(a)) } }));
363
+ const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash("confirmed");
364
+ const compile = (units) => new VersionedTransaction(new TransactionMessage({ payerKey: payer, recentBlockhash: blockhash, instructions: [ComputeBudgetProgram.setComputeUnitLimit({ units }), ...price, ...body] }).compileToV0Message(luts));
365
+ const sim = await conn.simulateTransaction(compile(1_400_000), { sigVerify: false, replaceRecentBlockhash: true });
366
+ if (sim.value.err)
367
+ throw new Error(`This swap would fail right now (${JSON.stringify(sim.value.err)}). Try again in a moment.`);
368
+ const units = Math.min(1_400_000, Math.ceil((sim.value.unitsConsumed ?? 1_200_000) * 1.2));
369
+ return { tx: compile(units), lastValidBlockHeight, feeLamports };
370
+ }
371
+ async function executeBuilt(q, keys, deps) {
372
+ const conn = deps.verify?.conn ?? new Connection(deps.rpc?.solana ?? DEFAULT_RPC.solana, "confirmed");
373
+ const { tx, lastValidBlockHeight, feeLamports } = await assembleBuilt(q, keys.solana.publicKey, conn);
374
+ await verifySwapTx(q, { evm: "", solana: keys.solana.publicKey }, { ...deps, ...deps.verify, vtx: tx, extraLamports: feeLamports });
375
+ tx.sign([keys.solana]);
376
+ const sig = await conn.sendRawTransaction(tx.serialize(), { preflightCommitment: "confirmed", maxRetries: 3 });
377
+ const until = Date.now() + 90_000;
378
+ for (;;) {
379
+ const st = (await conn.getSignatureStatuses([sig])).value[0];
380
+ if (st?.err)
381
+ throw new Error(`swap ${sig} failed: ${JSON.stringify(st.err)}`);
382
+ if (st && (st.confirmationStatus === "confirmed" || st.confirmationStatus === "finalized"))
383
+ return sig;
384
+ if (Date.now() > until || (await conn.getBlockHeight("confirmed")) > lastValidBlockHeight)
385
+ throw new Error(`Solana swap ${sig} wasn't confirmed in time. Check it on an explorer before trying again.`);
386
+ await new Promise((r) => setTimeout(r, deps.pollMs ?? 1500));
387
+ }
388
+ }
88
389
  /** Sign and send. Returns the transaction hash / signature. */
89
390
  export async function executeSwap(q, keys, deps = {}) {
391
+ // A built Solana swap is assembled first, then checked as the exact transaction that will be signed.
392
+ if (q.venue === "jupiter" && q.raw?.build)
393
+ return executeBuilt(q, keys, deps);
394
+ await verifySwapTx(q, { evm: keys.evm.address, solana: keys.solana.publicKey }, { ...deps, ...deps.verify });
90
395
  if (q.venue === "jupiter") {
91
396
  const tx = VersionedTransaction.deserialize(Buffer.from(q.raw.transaction, "base64"));
92
397
  tx.sign([keys.solana]);
@@ -99,19 +404,20 @@ export async function executeSwap(q, keys, deps = {}) {
99
404
  throw new Error(`swap failed: ${j.error ?? j.status}`);
100
405
  return String(j.signature);
101
406
  }
102
- const provider = new JsonRpcProvider(deps.rpc?.[q.chain] ?? DEFAULT_RPC[q.chain], EVM_CHAIN_ID[q.chain]);
407
+ // On Ethereum mainnet the approval and the swap go through Flashbots Protect (src/evmsend.ts).
408
+ const provider = deps.provider ?? sendingProvider(q.chain, { rpc: deps.rpc, proxy: deps.proxy, fetch: deps.fetch });
103
409
  const signer = keys.evm.connect(provider);
104
410
  if (q.raw?.issues?.allowance) {
105
411
  const token = new Contract(q.sell_token, ERC20, signer);
106
- const a = await token.approve(ALLOWANCE_HOLDER, BigInt(q.sell_amount)); // exact amount, never unlimited
107
- await a.wait();
412
+ const a = await token.getFunction("approve")(ALLOWANCE_HOLDER, BigInt(q.sell_amount)); // exact amount, never unlimited
413
+ await waitMined(a, "approval");
108
414
  }
109
415
  const t = q.raw.transaction;
110
416
  const sent = await signer.sendTransaction({
111
417
  to: t.to, data: t.data, value: BigInt(t.value ?? "0"),
112
418
  ...(t.gas ? { gasLimit: BigInt(t.gas) } : {}),
113
419
  });
114
- const r = await sent.wait();
420
+ const r = await waitMined(sent, "swap");
115
421
  if (!r || r.status !== 1)
116
422
  throw new Error(`swap transaction ${sent.hash} reverted`);
117
423
  return sent.hash;