tollkit-wallet 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -2
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/dist/actions.d.ts +34 -33
- package/dist/actions.js +5 -1
- package/dist/actions.js.map +1 -1
- package/dist/bridge.d.ts +148 -0
- package/dist/bridge.js +460 -0
- package/dist/bridge.js.map +1 -0
- package/dist/buy.d.ts +17 -0
- package/dist/buy.js +23 -0
- package/dist/buy.js.map +1 -0
- package/dist/cli.js +68 -2
- package/dist/cli.js.map +1 -1
- package/dist/dapp.d.ts +89 -0
- package/dist/dapp.js +505 -0
- package/dist/dapp.js.map +1 -0
- package/dist/dashboard.d.ts +2 -0
- package/dist/dashboard.js +145 -2
- package/dist/dashboard.js.map +1 -1
- package/dist/holdings.d.ts +92 -0
- package/dist/holdings.js +200 -0
- package/dist/holdings.js.map +1 -0
- package/dist/keystore.d.ts +58 -11
- package/dist/keystore.js +87 -11
- package/dist/keystore.js.map +1 -1
- package/dist/ledger.d.ts +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/netguard.d.ts +8 -0
- package/dist/netguard.js +44 -0
- package/dist/netguard.js.map +1 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.js +1 -0
- package/dist/paths.js.map +1 -1
- package/dist/policy.d.ts +4 -4
- package/dist/rules.d.ts +4 -4
- package/dist/sell.d.ts +60 -0
- package/dist/sell.js +71 -0
- package/dist/sell.js.map +1 -0
- package/dist/stake.d.ts +84 -0
- package/dist/stake.js +158 -0
- package/dist/stake.js.map +1 -0
- package/dist/ui.js +306 -32
- package/dist/ui.js.map +1 -1
- package/dist/wallet.d.ts +57 -2
- package/dist/wallet.js +185 -4
- package/dist/wallet.js.map +1 -1
- package/extension/PRIVACY.md +19 -0
- package/extension/README.md +16 -0
- package/extension/background.js +88 -0
- package/extension/content.js +34 -0
- package/extension/icons/icon.svg +1 -0
- package/extension/icons/icon128.png +0 -0
- package/extension/icons/icon16.png +0 -0
- package/extension/icons/icon32.png +0 -0
- package/extension/icons/icon48.png +0 -0
- package/extension/inpage.js +129 -0
- package/extension/manifest.json +15 -0
- package/extension/popup.html +35 -0
- package/extension/popup.js +39 -0
- package/package.json +3 -2
package/dist/bridge.js
ADDED
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Move between networks": USDC between Base, Ethereum and Solana with Circle's CCTP V2,
|
|
3
|
+
* and ETH between Base and Ethereum with Across (through Tollkit's server, which holds the Across key).
|
|
4
|
+
*
|
|
5
|
+
* Checked against primary sources on 2026-10-14:
|
|
6
|
+
* CCTP domains Ethereum 0, Solana 5, Base 6 (developers.circle.com/cctp/concepts/supported-chains-and-domains)
|
|
7
|
+
* EVM TokenMessengerV2 0x28b5…cf5d (developers.circle.com/cctp/evm-smart-contracts);
|
|
8
|
+
* depositForBurnWithHook signature from Circle's own example (circlefin/solana-cctp-contracts examples/v2/evm.ts)
|
|
9
|
+
* Solana TokenMessengerMinterV2 CCTPV2vP…, MessageTransmitterV2 CCTPV2Sm… (that repo's README and IDL);
|
|
10
|
+
* deposit_for_burn_with_hook accounts, PDA seeds and discriminator from examples/target/idl/token_messenger_minter_v2.json
|
|
11
|
+
* Fees: GET iris-api.circle.com/v2/burn/USDC/fees/{src}/{dst}?forward=true (no key); Fast Transfer = finality 1000
|
|
12
|
+
* Forwarding Service: hookData "cctp-forward" (32 bytes; 65 with Solana token-account setup), Circle mints on the
|
|
13
|
+
* destination so no gas is needed there (developers.circle.com/cctp/howtos/transfer-usdc-with-forwarding-service)
|
|
14
|
+
* Across SpokePoolPeriphery 0x97CC…fD4 on Base and Ethereum (docs.across.to/chains-and-contracts)
|
|
15
|
+
* Tollkit's fee (0.25%) is sent as its own small USDC transfer for CCTP moves, and taken by Across as its app fee for ETH.
|
|
16
|
+
* Moves stay inside this wallet (same owner on both networks), so they don't count against spending limits,
|
|
17
|
+
* but they need the password every time and agents can't reach them.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
import { createHash } from "node:crypto";
|
|
22
|
+
import { Connection, Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction, sendAndConfirmTransaction } from "@solana/web3.js";
|
|
23
|
+
import { AbiCoder, Contract, Interface, JsonRpcProvider, ZeroAddress, ZeroHash, concat, getAddress, getBytes, hexlify, toUtf8Bytes, zeroPadBytes, zeroPadValue } from "ethers";
|
|
24
|
+
import { DEFAULT_RPC, EVM_CHAIN_ID } from "./chains.js";
|
|
25
|
+
import { walletHome } from "./paths.js";
|
|
26
|
+
export const BRIDGE_FEE_BPS = 25;
|
|
27
|
+
export const IRIS = "https://iris-api.circle.com";
|
|
28
|
+
export const CCTP_DOMAIN = { ethereum: 0, solana: 5, base: 6 };
|
|
29
|
+
export const TOKEN_MESSENGER_V2 = "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d";
|
|
30
|
+
export const SOL_TMM = new PublicKey("CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe");
|
|
31
|
+
export const SOL_MT = new PublicKey("CCTPV2Sm4AdWt5296sk4P66VBZ7bEhcARwFaaS9YPbeC");
|
|
32
|
+
export const ACROSS_PERIPHERY = "0x97CCDBea4632140639aD5eA9b944aa034eb15fD4";
|
|
33
|
+
export const USDC = {
|
|
34
|
+
base: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
35
|
+
ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
36
|
+
solana: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
37
|
+
};
|
|
38
|
+
const TOKEN_PROGRAM = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
39
|
+
/** Anchor discriminator for deposit_for_burn_with_hook, from the IDL. */
|
|
40
|
+
const DFB_HOOK_DISC = Uint8Array.from([111, 245, 62, 131, 204, 108, 223, 155]);
|
|
41
|
+
/** Seconds to arrive with Fast Transfer, by source (developers.circle.com/cctp/concepts/finality-and-block-confirmations). */
|
|
42
|
+
const FAST_ETA = { ethereum: 20, base: 8, solana: 8 };
|
|
43
|
+
/** The Forwarding Service hook: "cctp-forward" padded to 24 bytes, version 0, length 0 (32 bytes). */
|
|
44
|
+
export function forwardHook(solanaRecipientSetup) {
|
|
45
|
+
const head = getBytes(zeroPadBytes(toUtf8Bytes("cctp-forward"), 24));
|
|
46
|
+
const u32 = (n) => { const b = new Uint8Array(4); new DataView(b.buffer).setUint32(0, n, false); return b; };
|
|
47
|
+
if (!solanaRecipientSetup)
|
|
48
|
+
return getBytes(concat([head, u32(0), u32(0)]));
|
|
49
|
+
// Extended form: create the recipient's USDC account on Solana (flag 1, then the wallet address).
|
|
50
|
+
return getBytes(concat([head, u32(0), u32(33), Uint8Array.from([1]), solanaRecipientSetup.toBytes()]));
|
|
51
|
+
}
|
|
52
|
+
export const canMove = (asset, from, to) => from !== to && (asset === "USDC" || (asset === "ETH" && from !== "solana" && to !== "solana"));
|
|
53
|
+
const decimals = (a) => (a === "USDC" ? 6 : 18);
|
|
54
|
+
export const fmtAmount = (a, atomic) => {
|
|
55
|
+
const n = Number(BigInt(atomic)) / 10 ** decimals(a);
|
|
56
|
+
return `${n.toLocaleString("en-US", { maximumFractionDigits: a === "USDC" ? 2 : 6 })} ${a}`;
|
|
57
|
+
};
|
|
58
|
+
export class Mover {
|
|
59
|
+
o;
|
|
60
|
+
cfg = null;
|
|
61
|
+
file;
|
|
62
|
+
constructor(o) {
|
|
63
|
+
this.o = o;
|
|
64
|
+
this.file = path.join(walletHome(o.dir), "moves.json");
|
|
65
|
+
}
|
|
66
|
+
get f() { return this.o.fetch ?? fetch; }
|
|
67
|
+
rpc(c) { return this.o.rpc?.[c] ?? DEFAULT_RPC[c]; }
|
|
68
|
+
sol() { return this.o.solConn ?? new Connection(this.rpc("solana"), "confirmed"); }
|
|
69
|
+
async config() {
|
|
70
|
+
if (this.cfg && Date.now() - this.cfg.at < 600_000)
|
|
71
|
+
return this.cfg.v;
|
|
72
|
+
const r = await this.f(`${this.o.proxy}/bridge/config`, { signal: AbortSignal.timeout(15_000) });
|
|
73
|
+
if (r.status === 404)
|
|
74
|
+
throw new Error("Moving between networks isn't available from Tollkit's server yet.");
|
|
75
|
+
const j = await r.json();
|
|
76
|
+
if (!r.ok)
|
|
77
|
+
throw new Error(j?.message ?? `Tollkit's server answered HTTP ${r.status}.`);
|
|
78
|
+
const fee = Number(j.fee_bps);
|
|
79
|
+
if (!(fee >= 0 && fee <= BRIDGE_FEE_BPS))
|
|
80
|
+
throw new Error(`Tollkit's server asked for a ${fee / 100}% fee; the wallet allows at most ${BRIDGE_FEE_BPS / 100}%.`);
|
|
81
|
+
const evm = typeof j.fee_recipient?.evm === "string" && /^0x[0-9a-fA-F]{40}$/.test(j.fee_recipient.evm) ? getAddress(j.fee_recipient.evm.toLowerCase()) : null;
|
|
82
|
+
let solana = null;
|
|
83
|
+
try {
|
|
84
|
+
if (j.fee_recipient?.solana)
|
|
85
|
+
solana = new PublicKey(j.fee_recipient.solana).toBase58();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
solana = null;
|
|
89
|
+
}
|
|
90
|
+
const v = { fee_bps: fee, fee_recipient: { evm, solana }, across: !!j.across };
|
|
91
|
+
this.cfg = { at: Date.now(), v };
|
|
92
|
+
return v;
|
|
93
|
+
}
|
|
94
|
+
/** The owner's USDC token account on Solana, and whether it exists yet. */
|
|
95
|
+
async solUsdcAccount(owner) {
|
|
96
|
+
const { getAssociatedTokenAddressSync } = await import("@solana/spl-token");
|
|
97
|
+
const ata = getAssociatedTokenAddressSync(new PublicKey(USDC.solana), owner);
|
|
98
|
+
return { ata, exists: !!(await this.sol().getAccountInfo(ata)) };
|
|
99
|
+
}
|
|
100
|
+
async quote(asset, from, to, amountAtomic) {
|
|
101
|
+
if (!canMove(asset, from, to))
|
|
102
|
+
throw new Error(asset === "ETH" ? "ETH moves between Base and Ethereum only." : "Pick two different networks.");
|
|
103
|
+
if (!/^\d+$/.test(amountAtomic) || BigInt(amountAtomic) <= 0n)
|
|
104
|
+
throw new Error("Enter an amount.");
|
|
105
|
+
const amount = BigInt(amountAtomic);
|
|
106
|
+
const cfg = await this.config();
|
|
107
|
+
return asset === "USDC" ? this.quoteCctp(from, to, amount, cfg) : this.quoteAcross(from, to, amount, cfg);
|
|
108
|
+
}
|
|
109
|
+
async quoteCctp(from, to, amount, cfg) {
|
|
110
|
+
if (!cfg.fee_recipient[from === "solana" ? "solana" : "evm"] && cfg.fee_bps > 0)
|
|
111
|
+
throw new Error(`Moving from ${from} isn't set up on Tollkit's server yet.`);
|
|
112
|
+
let setup = false, mintRecipient;
|
|
113
|
+
if (to === "solana") {
|
|
114
|
+
const { ata, exists } = await this.solUsdcAccount(new PublicKey(this.o.solana));
|
|
115
|
+
setup = !exists;
|
|
116
|
+
mintRecipient = hexlify(ata.toBytes());
|
|
117
|
+
}
|
|
118
|
+
else
|
|
119
|
+
mintRecipient = zeroPadValue(this.o.evm, 32);
|
|
120
|
+
const url = `${IRIS}/v2/burn/USDC/fees/${CCTP_DOMAIN[from]}/${CCTP_DOMAIN[to]}?forward=true${setup ? "&includeRecipientSetup=true" : ""}`;
|
|
121
|
+
const r = await this.f(url, { signal: AbortSignal.timeout(15_000) });
|
|
122
|
+
if (!r.ok)
|
|
123
|
+
throw new Error(`Circle's fee service answered HTTP ${r.status}.`);
|
|
124
|
+
const rows = await r.json();
|
|
125
|
+
const fast = rows.find((x) => x.finalityThreshold === 1000);
|
|
126
|
+
if (!fast)
|
|
127
|
+
throw new Error("Circle didn't offer a fast transfer for this route.");
|
|
128
|
+
const tollkit = (amount * BigInt(cfg.fee_bps)) / 10000n;
|
|
129
|
+
const burn = amount - tollkit;
|
|
130
|
+
// minimumFee is in basis points and can be fractional (1.3); round up.
|
|
131
|
+
const mf = BigInt(Math.round(Number(fast.minimumFee) * 1000));
|
|
132
|
+
const protocol = (burn * mf + 10000000n - 1n) / 10000000n;
|
|
133
|
+
const forward = BigInt(String(fast.forwardFee?.med ?? fast.forwardFee?.high ?? "0"));
|
|
134
|
+
const maxFee = protocol + forward;
|
|
135
|
+
const receive = burn - maxFee;
|
|
136
|
+
if (receive <= 0n || (maxFee + tollkit) * 10n > amount)
|
|
137
|
+
throw new Error(`That's too small to move: fees would be about ${fmtAmount("USDC", maxFee + tollkit)}. Try ${fmtAmount("USDC", (maxFee + tollkit) * 10n)} or more.`);
|
|
138
|
+
return {
|
|
139
|
+
asset: "USDC", from, to, via: "cctp", amount: amount.toString(), tollkit_fee: tollkit.toString(), bridge_fee_max: maxFee.toString(), receive_min: receive.toString(),
|
|
140
|
+
eta_seconds: FAST_ETA[from], burn: burn.toString(), max_fee: maxFee.toString(), mint_recipient: mintRecipient, recipient_setup: setup,
|
|
141
|
+
hook: hexlify(forwardHook(setup ? new PublicKey(this.o.solana) : undefined)),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
async quoteAcross(from, to, amount, cfg) {
|
|
145
|
+
if (!cfg.across || !cfg.fee_recipient.evm)
|
|
146
|
+
throw new Error("Moving ETH isn't set up on Tollkit's server yet.");
|
|
147
|
+
const q = new URLSearchParams({ from, to, amount: amount.toString(), address: this.o.evm });
|
|
148
|
+
const r = await this.f(`${this.o.proxy}/bridge/across?${q}`, { signal: AbortSignal.timeout(25_000) });
|
|
149
|
+
const j = await r.json().catch(() => ({}));
|
|
150
|
+
if (!r.ok)
|
|
151
|
+
throw new Error(j?.message ?? `Tollkit's server answered HTTP ${r.status}.`);
|
|
152
|
+
const tx = j.swapTx;
|
|
153
|
+
if (!tx || !/^0x[0-9a-fA-F]{40}$/.test(String(tx.to)) || getAddress(String(tx.to).toLowerCase()) !== ACROSS_PERIPHERY)
|
|
154
|
+
throw new Error("The ETH route isn't Across's contract, so it wasn't used.");
|
|
155
|
+
if (Number(tx.chainId) !== EVM_CHAIN_ID[from])
|
|
156
|
+
throw new Error("The ETH route is for the wrong network.");
|
|
157
|
+
if (BigInt(tx.value ?? 0) !== amount)
|
|
158
|
+
throw new Error("The ETH route doesn't match the amount.");
|
|
159
|
+
if (Array.isArray(j.approvalTxns) && j.approvalTxns.length)
|
|
160
|
+
throw new Error("The ETH route asked for a token approval, which ETH doesn't need.");
|
|
161
|
+
// Everything shown and checked comes from the transaction itself, not from the server's numbers.
|
|
162
|
+
const d = checkAcrossDeposit(String(tx.data), { from: from, to: to, amount, me: this.o.evm, feeRecipient: cfg.fee_recipient.evm, feeBps: cfg.fee_bps });
|
|
163
|
+
if ((amount - d.receive) * 100n > amount * 3n)
|
|
164
|
+
throw new Error(`Fees on this amount are over 3% (you'd get ${fmtAmount("ETH", d.receive)}). Try a larger amount.`);
|
|
165
|
+
return {
|
|
166
|
+
asset: "ETH", from, to, via: "across", amount: amount.toString(), tollkit_fee: d.fee.toString(),
|
|
167
|
+
bridge_fee_max: (amount - d.output).toString(), receive_min: d.receive.toString(),
|
|
168
|
+
eta_seconds: Number(j.expectedFillTime) || 10, tx: { to: ACROSS_PERIPHERY, data: String(tx.data), value: amount.toString(), chainId: Number(tx.chainId) },
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** Sign and send. Returns the record that the dashboard tracks until it arrives. */
|
|
172
|
+
async execute(q, keys) {
|
|
173
|
+
const cfg = await this.config();
|
|
174
|
+
const id = createHash("sha256").update(JSON.stringify(q) + Date.now()).digest("hex").slice(0, 12);
|
|
175
|
+
let tx, feeTx;
|
|
176
|
+
if (q.via === "across") {
|
|
177
|
+
tx = await this.evmSend(q.from, { to: q.tx.to, data: q.tx.data, value: BigInt(q.tx.value) }, keys);
|
|
178
|
+
}
|
|
179
|
+
else if (q.from === "solana") {
|
|
180
|
+
tx = await this.burnFromSolana(q, keys, cfg);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
const r = await this.burnFromEvm(q, keys, cfg);
|
|
184
|
+
tx = r.tx;
|
|
185
|
+
feeTx = r.feeTx;
|
|
186
|
+
}
|
|
187
|
+
const rec = { id, ts: new Date().toISOString(), asset: q.asset, from: q.from, to: q.to, amount: q.amount, receive_min: q.receive_min, via: q.via, tx, ...(feeTx ? { fee_tx: feeTx } : {}), state: "sent", eta_seconds: q.eta_seconds };
|
|
188
|
+
this.save([rec, ...this.list()].slice(0, 100));
|
|
189
|
+
return rec;
|
|
190
|
+
}
|
|
191
|
+
async evmSend(from, t, keys) {
|
|
192
|
+
if (this.o.sendEvm)
|
|
193
|
+
return this.o.sendEvm(from, t, keys);
|
|
194
|
+
const p = new JsonRpcProvider(this.rpc(from), EVM_CHAIN_ID[from], { staticNetwork: true });
|
|
195
|
+
const sent = await keys.evm.connect(p).sendTransaction({ to: t.to, data: t.data, value: t.value ?? 0n });
|
|
196
|
+
const rc = await sent.wait();
|
|
197
|
+
if (!rc || rc.status !== 1)
|
|
198
|
+
throw new Error(`Transaction ${sent.hash} failed.`);
|
|
199
|
+
return sent.hash;
|
|
200
|
+
}
|
|
201
|
+
async evmRead(from, what) {
|
|
202
|
+
if (this.o.evmRead)
|
|
203
|
+
return this.o.evmRead(from, what);
|
|
204
|
+
const p = new JsonRpcProvider(this.rpc(from), EVM_CHAIN_ID[from], { staticNetwork: true });
|
|
205
|
+
if (what === "eth")
|
|
206
|
+
return p.getBalance(this.o.evm);
|
|
207
|
+
const c = new Contract(USDC[from], ["function balanceOf(address) view returns (uint256)", "function allowance(address,address) view returns (uint256)"], p);
|
|
208
|
+
return what === "usdc" ? c.balanceOf(this.o.evm) : c.allowance(this.o.evm, TOKEN_MESSENGER_V2);
|
|
209
|
+
}
|
|
210
|
+
async burnFromEvm(q, keys, cfg) {
|
|
211
|
+
const ERC20 = new Contract(USDC[q.from], ["function approve(address,uint256) returns (bool)", "function transfer(address,uint256) returns (bool)"]);
|
|
212
|
+
const TM = new Contract(TOKEN_MESSENGER_V2, ["function depositForBurnWithHook(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller, uint256 maxFee, uint32 minFinalityThreshold, bytes hookData)"]);
|
|
213
|
+
const amount = BigInt(q.amount), burn = BigInt(q.burn), fee = BigInt(q.tollkit_fee);
|
|
214
|
+
const have = await this.evmRead(q.from, "usdc");
|
|
215
|
+
if (have < amount)
|
|
216
|
+
throw new Error(`The wallet has ${fmtAmount("USDC", have)} on ${q.from}, less than ${fmtAmount("USDC", amount)}.`);
|
|
217
|
+
if ((await this.evmRead(q.from, "eth")) === 0n)
|
|
218
|
+
throw new Error(`Moving from ${q.from} needs a little ETH there for network fees.`);
|
|
219
|
+
// Approve exactly the amount being burned, only to Circle's TokenMessengerV2.
|
|
220
|
+
if ((await this.evmRead(q.from, "allowance")) < burn)
|
|
221
|
+
await this.evmSend(q.from, { to: USDC[q.from], data: ERC20.interface.encodeFunctionData("approve", [TOKEN_MESSENGER_V2, burn]) }, keys);
|
|
222
|
+
const tx = await this.evmSend(q.from, { to: TOKEN_MESSENGER_V2, data: TM.interface.encodeFunctionData("depositForBurnWithHook", [burn, CCTP_DOMAIN[q.to], q.mint_recipient, USDC[q.from], ZeroHash, BigInt(q.max_fee), 1000, q.hook]) }, keys);
|
|
223
|
+
let feeTx;
|
|
224
|
+
if (fee > 0n && cfg.fee_recipient.evm)
|
|
225
|
+
feeTx = await this.evmSend(q.from, { to: USDC[q.from], data: ERC20.interface.encodeFunctionData("transfer", [cfg.fee_recipient.evm, fee]) }, keys).catch(() => undefined);
|
|
226
|
+
return { tx, feeTx };
|
|
227
|
+
}
|
|
228
|
+
/** One Solana transaction: Tollkit's fee transfer + CCTP deposit_for_burn_with_hook (all or nothing). */
|
|
229
|
+
async solanaBurnTx(q, owner, cfg, event, feeAtaExists = true) {
|
|
230
|
+
const spl = await import("@solana/spl-token");
|
|
231
|
+
const mint = new PublicKey(USDC.solana);
|
|
232
|
+
const ownerAta = spl.getAssociatedTokenAddressSync(mint, owner);
|
|
233
|
+
const tx = new Transaction();
|
|
234
|
+
const fee = BigInt(q.tollkit_fee);
|
|
235
|
+
if (fee > 0n) {
|
|
236
|
+
const feeOwner = new PublicKey(cfg.fee_recipient.solana);
|
|
237
|
+
const feeAta = spl.getAssociatedTokenAddressSync(mint, feeOwner);
|
|
238
|
+
// Only pay into an account that already exists, so the owner never pays rent for Tollkit's account.
|
|
239
|
+
if (feeAtaExists)
|
|
240
|
+
tx.add(spl.createTransferCheckedInstruction(ownerAta, mint, feeAta, owner, fee, 6));
|
|
241
|
+
}
|
|
242
|
+
tx.add(depositForBurnWithHookIx({ owner, burnTokenAccount: ownerAta, mint, event: event.publicKey, amount: BigInt(q.burn), destinationDomain: CCTP_DOMAIN[q.to], mintRecipient: getBytes(q.mint_recipient), maxFee: BigInt(q.max_fee), minFinality: 1000, hook: getBytes(q.hook) }));
|
|
243
|
+
return tx;
|
|
244
|
+
}
|
|
245
|
+
async burnFromSolana(q, keys, cfg) {
|
|
246
|
+
const owner = keys.solana.publicKey;
|
|
247
|
+
const conn = this.sol();
|
|
248
|
+
const accts = await conn.getParsedTokenAccountsByOwner(owner, { mint: new PublicKey(USDC.solana) });
|
|
249
|
+
const have = accts.value.reduce((s, x) => s + BigInt(x.account.data.parsed.info.tokenAmount.amount), 0n);
|
|
250
|
+
if (have < BigInt(q.amount))
|
|
251
|
+
throw new Error(`The wallet has ${fmtAmount("USDC", have)} on Solana, less than ${fmtAmount("USDC", q.amount)}.`);
|
|
252
|
+
if ((await conn.getBalance(owner)) < 10_000_000)
|
|
253
|
+
throw new Error("Moving from Solana needs about 0.01 SOL for network fees and a small refundable deposit.");
|
|
254
|
+
const event = Keypair.generate();
|
|
255
|
+
const spl = await import("@solana/spl-token");
|
|
256
|
+
const feeAta = cfg.fee_recipient.solana ? spl.getAssociatedTokenAddressSync(new PublicKey(USDC.solana), new PublicKey(cfg.fee_recipient.solana)) : null;
|
|
257
|
+
const feeAtaExists = !!feeAta && !!(await conn.getAccountInfo(feeAta));
|
|
258
|
+
const tx = await this.solanaBurnTx(q, owner, cfg, event, feeAtaExists);
|
|
259
|
+
if (this.o.sendSolana)
|
|
260
|
+
return this.o.sendSolana(tx, [keys.solana, event]);
|
|
261
|
+
return sendAndConfirmTransaction(new Connection(this.rpc("solana"), "confirmed"), tx, [keys.solana, event]);
|
|
262
|
+
}
|
|
263
|
+
list() {
|
|
264
|
+
try {
|
|
265
|
+
return existsSync(this.file) ? JSON.parse(readFileSync(this.file, "utf8")) : [];
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
save(l) { writeFileSync(this.file, JSON.stringify(l, null, 2), { mode: 0o600 }); }
|
|
272
|
+
/** Check Circle's attestation service for USDC moves still on their way (at most every 10 s each). */
|
|
273
|
+
async refresh() {
|
|
274
|
+
const l = this.list();
|
|
275
|
+
let changed = false;
|
|
276
|
+
for (const m of l) {
|
|
277
|
+
if (m.state !== "sent")
|
|
278
|
+
continue;
|
|
279
|
+
if (m.via === "across") {
|
|
280
|
+
if (Date.now() - Date.parse(m.ts) > Math.max(120, m.eta_seconds * 6) * 1000) {
|
|
281
|
+
m.state = "arrived";
|
|
282
|
+
changed = true;
|
|
283
|
+
}
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (m.checked && Date.now() - Date.parse(m.checked) < 10_000)
|
|
287
|
+
continue;
|
|
288
|
+
m.checked = new Date().toISOString();
|
|
289
|
+
changed = true;
|
|
290
|
+
try {
|
|
291
|
+
const r = await this.f(`${IRIS}/v2/messages/${CCTP_DOMAIN[m.from]}?transactionHash=${m.tx}`, { signal: AbortSignal.timeout(10_000) });
|
|
292
|
+
if (!r.ok)
|
|
293
|
+
continue;
|
|
294
|
+
const msg = (await r.json())?.messages?.[0];
|
|
295
|
+
if (msg?.forwardTxHash) {
|
|
296
|
+
m.state = "arrived";
|
|
297
|
+
m.dest_tx = String(msg.forwardTxHash);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
catch { /* try again later */ }
|
|
301
|
+
}
|
|
302
|
+
if (changed)
|
|
303
|
+
this.save(l);
|
|
304
|
+
return l;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/** deposit_for_burn_with_hook, encoded by hand from Circle's IDL (Anchor: 8-byte discriminator + Borsh params). */
|
|
308
|
+
export function depositForBurnWithHookIx(a) {
|
|
309
|
+
if (a.mintRecipient.length !== 32)
|
|
310
|
+
throw new Error("mint recipient must be 32 bytes");
|
|
311
|
+
const pda = (seeds, prog) => PublicKey.findProgramAddressSync(seeds, prog)[0];
|
|
312
|
+
const s = (x) => Buffer.from(x, "utf8");
|
|
313
|
+
const u64 = (n) => { const b = Buffer.alloc(8); b.writeBigUInt64LE(n); return b; };
|
|
314
|
+
const u32 = (n) => { const b = Buffer.alloc(4); b.writeUInt32LE(n); return b; };
|
|
315
|
+
const data = Buffer.concat([
|
|
316
|
+
Buffer.from(DFB_HOOK_DISC), u64(a.amount), u32(a.destinationDomain), Buffer.from(a.mintRecipient), Buffer.alloc(32) /* destination_caller: anyone */,
|
|
317
|
+
u64(a.maxFee), u32(a.minFinality), u32(a.hook.length), Buffer.from(a.hook),
|
|
318
|
+
]);
|
|
319
|
+
const k = (pubkey, isWritable = false, isSigner = false) => ({ pubkey, isWritable, isSigner });
|
|
320
|
+
return new TransactionInstruction({
|
|
321
|
+
programId: SOL_TMM,
|
|
322
|
+
data,
|
|
323
|
+
keys: [
|
|
324
|
+
k(a.owner, false, true),
|
|
325
|
+
k(a.owner, true, true), // event_rent_payer
|
|
326
|
+
k(pda([s("sender_authority")], SOL_TMM)),
|
|
327
|
+
k(a.burnTokenAccount, true),
|
|
328
|
+
k(pda([s("denylist_account"), a.owner.toBuffer()], SOL_TMM)),
|
|
329
|
+
k(pda([s("message_transmitter")], SOL_MT), true),
|
|
330
|
+
k(pda([s("token_messenger")], SOL_TMM)),
|
|
331
|
+
k(pda([s("remote_token_messenger"), s(String(a.destinationDomain))], SOL_TMM)),
|
|
332
|
+
k(pda([s("token_minter")], SOL_TMM)),
|
|
333
|
+
k(pda([s("local_token"), a.mint.toBuffer()], SOL_TMM), true),
|
|
334
|
+
k(a.mint, true),
|
|
335
|
+
k(a.event, true, true),
|
|
336
|
+
k(SOL_MT),
|
|
337
|
+
k(SOL_TMM),
|
|
338
|
+
k(TOKEN_PROGRAM),
|
|
339
|
+
k(SystemProgram.programId),
|
|
340
|
+
k(pda([s("__event_authority")], SOL_TMM)),
|
|
341
|
+
k(SOL_TMM), // program
|
|
342
|
+
],
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
/** Across (docs.across.to/chains-and-contracts): SpokePool per network, MulticallHandler on both; WETH from tokens.ts. */
|
|
346
|
+
export const ACROSS_SPOKE = { base: "0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64", ethereum: "0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5" };
|
|
347
|
+
export const ACROSS_MULTICALL = "0x0F7Ae28dE1C8532170AD4ee566B5801485c13a0E";
|
|
348
|
+
const WETH = { base: "0x4200000000000000000000000000000000000006", ethereum: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" };
|
|
349
|
+
/** SpokePoolPeriphery.depositNative and MulticallHandler, from the ABIs in @across-protocol/contracts 5.0.27. */
|
|
350
|
+
const PERIPHERY = new Interface(["function depositNative(address spokePool, address depositor, bytes32 recipient, address inputToken, uint256 inputAmount, bytes32 outputToken, uint256 outputAmount, uint256 destinationChainId, bytes32 exclusiveRelayer, uint32 quoteTimestamp, uint32 fillDeadline, uint32 exclusivityParameter, bytes message) payable"]);
|
|
351
|
+
const HANDLER = new Interface(["function makeCallWithBalance(address target, bytes callData, uint256 value, tuple(address token, uint256 offset)[] replacement)", "function drainLeftoverTokens(address token, address destination)"]);
|
|
352
|
+
const WETH_IFACE = new Interface(["function withdraw(uint256)"]);
|
|
353
|
+
const EMIT_DATA = "0xd836083e"; // AcrossEventEmitter.emitData(bytes): logs only, no value
|
|
354
|
+
/**
|
|
355
|
+
* Decode and check an Across ETH deposit before signing: Across's SpokePool on this network, from this wallet,
|
|
356
|
+
* ETH in for exactly the amount, ETH out on the other network to this wallet (directly, or through Across's
|
|
357
|
+
* MulticallHandler whose only steps unwrap WETH, pay Tollkit's fee, and send everything left to this wallet).
|
|
358
|
+
* Returns what's actually delivered, Tollkit's fee, and what this wallet receives at least.
|
|
359
|
+
*/
|
|
360
|
+
export function checkAcrossDeposit(data, o) {
|
|
361
|
+
const bad = (why) => new Error(`The ETH route failed a safety check (${why}), so it wasn't used.`);
|
|
362
|
+
let a;
|
|
363
|
+
try {
|
|
364
|
+
a = PERIPHERY.decodeFunctionData("depositNative", data);
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
throw bad("not an Across ETH deposit");
|
|
368
|
+
}
|
|
369
|
+
const eq = (x, y) => x.toLowerCase() === y.toLowerCase();
|
|
370
|
+
const b32 = (addr) => zeroPadValue(addr.toLowerCase(), 32);
|
|
371
|
+
if (!eq(a.spokePool, ACROSS_SPOKE[o.from]))
|
|
372
|
+
throw bad("wrong SpokePool");
|
|
373
|
+
if (!eq(a.depositor, o.me))
|
|
374
|
+
throw bad("depositor isn't this wallet");
|
|
375
|
+
if (!eq(a.inputToken, WETH[o.from]) || BigInt(a.inputAmount) !== o.amount)
|
|
376
|
+
throw bad("input isn't this amount of ETH");
|
|
377
|
+
if (!eq(a.outputToken, b32(WETH[o.to])))
|
|
378
|
+
throw bad("output isn't ETH");
|
|
379
|
+
if (BigInt(a.destinationChainId) !== BigInt(EVM_CHAIN_ID[o.to]))
|
|
380
|
+
throw bad("wrong destination network");
|
|
381
|
+
const output = BigInt(a.outputAmount);
|
|
382
|
+
if (output <= 0n || output > o.amount)
|
|
383
|
+
throw bad("odd output amount");
|
|
384
|
+
if (eq(a.recipient, b32(o.me))) {
|
|
385
|
+
if (a.message !== "0x")
|
|
386
|
+
throw bad("unexpected message");
|
|
387
|
+
return { output, fee: 0n, receive: output };
|
|
388
|
+
}
|
|
389
|
+
if (!eq(a.recipient, b32(ACROSS_MULTICALL)))
|
|
390
|
+
throw bad("recipient isn't this wallet");
|
|
391
|
+
let ins;
|
|
392
|
+
try {
|
|
393
|
+
[ins] = AbiCoder.defaultAbiCoder().decode(["tuple(tuple(address target, bytes callData, uint256 value)[] calls, address fallbackRecipient)"], a.message);
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
throw bad("unreadable instructions");
|
|
397
|
+
}
|
|
398
|
+
if (!(eq(ins.fallbackRecipient, ZeroAddress) || eq(ins.fallbackRecipient, o.me)))
|
|
399
|
+
throw bad("leftovers go elsewhere");
|
|
400
|
+
let fee = 0n, drainedEth = false, drainedWeth = false, unwrapped = false;
|
|
401
|
+
for (const c of ins.calls) {
|
|
402
|
+
const target = String(c.target), value = BigInt(c.value), cd = String(c.callData);
|
|
403
|
+
if (eq(target, ACROSS_MULTICALL) && value === 0n) {
|
|
404
|
+
let p;
|
|
405
|
+
try {
|
|
406
|
+
p = HANDLER.parseTransaction({ data: cd });
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
throw bad("unknown handler step");
|
|
410
|
+
}
|
|
411
|
+
if (p?.name === "makeCallWithBalance" && !drainedEth) {
|
|
412
|
+
// Unwrap all the WETH that arrived into ETH.
|
|
413
|
+
if (!eq(p.args.target, WETH[o.to]) || BigInt(p.args.value) !== 0n)
|
|
414
|
+
throw bad("unexpected call");
|
|
415
|
+
try {
|
|
416
|
+
WETH_IFACE.decodeFunctionData("withdraw", p.args.callData);
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
throw bad("unexpected WETH call");
|
|
420
|
+
}
|
|
421
|
+
// The handler writes its WETH balance into withdraw's amount, right after the 4-byte selector.
|
|
422
|
+
if (p.args.replacement.length !== 1 || !eq(p.args.replacement[0].token, WETH[o.to]) || BigInt(p.args.replacement[0].offset) !== 4n)
|
|
423
|
+
throw bad("unexpected WETH call");
|
|
424
|
+
unwrapped = true;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (p?.name === "drainLeftoverTokens") {
|
|
428
|
+
// Send everything left (ETH, then any WETH) to this wallet.
|
|
429
|
+
if (!eq(p.args.destination, o.me))
|
|
430
|
+
throw bad("leftovers go elsewhere");
|
|
431
|
+
if (!unwrapped)
|
|
432
|
+
throw bad("leftovers sent before unwrapping");
|
|
433
|
+
if (eq(p.args.token, ZeroAddress))
|
|
434
|
+
drainedEth = true;
|
|
435
|
+
else if (eq(p.args.token, WETH[o.to]))
|
|
436
|
+
drainedWeth = true;
|
|
437
|
+
else
|
|
438
|
+
throw bad("unexpected token");
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
throw bad("unknown handler step");
|
|
442
|
+
}
|
|
443
|
+
// Tollkit's fee, paid in ETH before the rest goes to this wallet.
|
|
444
|
+
if (eq(target, o.feeRecipient) && cd === "0x" && value > 0n && unwrapped && !drainedEth) {
|
|
445
|
+
fee += value;
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
// Across's event log after the payout: no value, nothing left to move.
|
|
449
|
+
if (drainedEth && value === 0n && cd.slice(0, 10) === EMIT_DATA)
|
|
450
|
+
continue;
|
|
451
|
+
throw bad(`unexpected call to ${target}`);
|
|
452
|
+
}
|
|
453
|
+
if (!unwrapped || !drainedEth || !drainedWeth)
|
|
454
|
+
throw bad("the ETH isn't sent to this wallet");
|
|
455
|
+
// Tollkit's fee: at most fee_bps of what arrives (rounded up by 1 wei for Across's rounding).
|
|
456
|
+
if (fee > (output * BigInt(o.feeBps)) / 10000n + 1n)
|
|
457
|
+
throw bad("fee is more than 0.25%");
|
|
458
|
+
return { output, fee, receive: output - fee };
|
|
459
|
+
}
|
|
460
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/buy.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Chain } from "./chains.js";
|
|
2
|
+
export declare const BUY_ASSETS: Record<Chain, string[]>;
|
|
3
|
+
export declare function buyLink(addresses: {
|
|
4
|
+
evm: string;
|
|
5
|
+
solana: string;
|
|
6
|
+
}, o: {
|
|
7
|
+
chain: Chain;
|
|
8
|
+
asset: string;
|
|
9
|
+
amount_usd?: number;
|
|
10
|
+
sandbox?: boolean;
|
|
11
|
+
}, opts?: {
|
|
12
|
+
proxy?: string;
|
|
13
|
+
fetch?: typeof fetch;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
url: string;
|
|
16
|
+
sandbox: boolean;
|
|
17
|
+
}>;
|
package/dist/buy.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Buy": asks Tollkit's server (POST {proxy}/onramp) for a single-use Coinbase
|
|
3
|
+
* Onramp checkout link that sends the crypto to this wallet's own address.
|
|
4
|
+
* Only the public address, network, coin and amount are sent. Coinbase does
|
|
5
|
+
* the payment and ID checks; the wallet never handles card details.
|
|
6
|
+
*/
|
|
7
|
+
import { DEFAULT_PROXY } from "./swap.js";
|
|
8
|
+
export const BUY_ASSETS = { base: ["USDC", "ETH"], ethereum: ["USDC", "ETH"], solana: ["USDC", "SOL"] };
|
|
9
|
+
export async function buyLink(addresses, o, opts = {}) {
|
|
10
|
+
if (!BUY_ASSETS[o.chain]?.includes(o.asset))
|
|
11
|
+
throw new Error(`On ${o.chain} you can buy ${(BUY_ASSETS[o.chain] ?? []).join(" or ")}.`);
|
|
12
|
+
const r = await (opts.fetch ?? fetch)(`${opts.proxy ?? DEFAULT_PROXY}/onramp`, {
|
|
13
|
+
method: "POST", headers: { "content-type": "application/json" }, signal: AbortSignal.timeout(25_000),
|
|
14
|
+
body: JSON.stringify({ address: o.chain === "solana" ? addresses.solana : addresses.evm, network: o.chain, asset: o.asset, ...(o.amount_usd ? { amount_usd: o.amount_usd } : {}), ...(o.sandbox ? { sandbox: true } : {}) }),
|
|
15
|
+
});
|
|
16
|
+
const j = await r.json().catch(() => ({}));
|
|
17
|
+
if (!r.ok)
|
|
18
|
+
throw new Error(r.status === 404 ? "Buying isn't available from Tollkit's server yet." : j?.message ?? `Tollkit's server answered HTTP ${r.status}.`);
|
|
19
|
+
if (typeof j.url !== "string" || !j.url.startsWith("https://pay.coinbase.com/"))
|
|
20
|
+
throw new Error("Didn't get a Coinbase checkout link.");
|
|
21
|
+
return { url: j.url, sandbox: !!j.sandbox };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=buy.js.map
|
package/dist/buy.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buy.js","sourceRoot":"","sources":["../src/buy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,CAAC,MAAM,UAAU,GAA4B,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;AAEjI,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,SAA0C,EAAE,CAA0E,EAAE,OAAiD,EAAE;IACvM,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvI,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,aAAa,SAAS,EAAE;QAC7E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;QACpG,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;KAC7N,CAAC,CAAC;IACH,MAAM,CAAC,GAAQ,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,mDAAmD,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,kCAAkC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACjK,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,2BAA2B,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACzI,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;AAC9C,CAAC"}
|