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.
Files changed (61) hide show
  1. package/README.md +49 -2
  2. package/THIRD_PARTY_NOTICES.md +4 -0
  3. package/dist/actions.d.ts +34 -33
  4. package/dist/actions.js +5 -1
  5. package/dist/actions.js.map +1 -1
  6. package/dist/bridge.d.ts +148 -0
  7. package/dist/bridge.js +460 -0
  8. package/dist/bridge.js.map +1 -0
  9. package/dist/buy.d.ts +17 -0
  10. package/dist/buy.js +23 -0
  11. package/dist/buy.js.map +1 -0
  12. package/dist/cli.js +68 -2
  13. package/dist/cli.js.map +1 -1
  14. package/dist/dapp.d.ts +89 -0
  15. package/dist/dapp.js +505 -0
  16. package/dist/dapp.js.map +1 -0
  17. package/dist/dashboard.d.ts +2 -0
  18. package/dist/dashboard.js +145 -2
  19. package/dist/dashboard.js.map +1 -1
  20. package/dist/holdings.d.ts +92 -0
  21. package/dist/holdings.js +200 -0
  22. package/dist/holdings.js.map +1 -0
  23. package/dist/keystore.d.ts +58 -11
  24. package/dist/keystore.js +87 -11
  25. package/dist/keystore.js.map +1 -1
  26. package/dist/ledger.d.ts +1 -1
  27. package/dist/mcp.d.ts +1 -1
  28. package/dist/mcp.js +1 -1
  29. package/dist/netguard.d.ts +8 -0
  30. package/dist/netguard.js +44 -0
  31. package/dist/netguard.js.map +1 -0
  32. package/dist/paths.d.ts +1 -0
  33. package/dist/paths.js +1 -0
  34. package/dist/paths.js.map +1 -1
  35. package/dist/policy.d.ts +4 -4
  36. package/dist/rules.d.ts +4 -4
  37. package/dist/sell.d.ts +60 -0
  38. package/dist/sell.js +71 -0
  39. package/dist/sell.js.map +1 -0
  40. package/dist/stake.d.ts +84 -0
  41. package/dist/stake.js +158 -0
  42. package/dist/stake.js.map +1 -0
  43. package/dist/ui.js +306 -32
  44. package/dist/ui.js.map +1 -1
  45. package/dist/wallet.d.ts +57 -2
  46. package/dist/wallet.js +185 -4
  47. package/dist/wallet.js.map +1 -1
  48. package/extension/PRIVACY.md +19 -0
  49. package/extension/README.md +16 -0
  50. package/extension/background.js +88 -0
  51. package/extension/content.js +34 -0
  52. package/extension/icons/icon.svg +1 -0
  53. package/extension/icons/icon128.png +0 -0
  54. package/extension/icons/icon16.png +0 -0
  55. package/extension/icons/icon32.png +0 -0
  56. package/extension/icons/icon48.png +0 -0
  57. package/extension/inpage.js +129 -0
  58. package/extension/manifest.json +15 -0
  59. package/extension/popup.html +35 -0
  60. package/extension/popup.js +39 -0
  61. package/package.json +3 -2
@@ -3,6 +3,15 @@
3
3
  * EVM: the standard Ethereum JSON keystore (ethers v6, scrypt + AES-128-CTR).
4
4
  * Solana: the 64-byte secret key, scrypt-derived key + AES-256-GCM.
5
5
  * Tollkit never sees either key or the password.
6
+ *
7
+ * New wallets come from a 12-word BIP-39 recovery phrase, derived the way
8
+ * MetaMask and Phantom do it, so the same phrase restores the same addresses
9
+ * there too (checked 2026-10-14):
10
+ * EVM m/44'/60'/0'/0/0 (MetaMask: "default BIP-44 derivation path (m/44'/60'/0'/0)";
11
+ * Phantom default bip44Change "m/44'/60'/0'/0/${index}")
12
+ * Solana m/44'/501'/0'/0' (Phantom default bip44Change "m/44'/501'/${index}'/0'"),
13
+ * ed25519 via SLIP-0010 (hardened only).
14
+ * The phrase is kept encrypted like the keys so the owner can view it again with the password.
6
15
  */
7
16
  import { Keypair } from "@solana/web3.js";
8
17
  import { Wallet, HDNodeWallet } from "ethers";
@@ -18,30 +27,67 @@ export interface KeystoreFile {
18
27
  evm_address: string;
19
28
  solana_address: string;
20
29
  evm: string;
21
- solana: {
22
- kdf: "scrypt";
23
- N: number;
24
- r: number;
25
- p: number;
26
- salt: string;
27
- iv: string;
28
- tag: string;
29
- ct: string;
30
- };
30
+ solana: Sealed;
31
+ /** The recovery phrase, sealed like the Solana key. Absent on wallets made before 0.2.2 (keys only). */
32
+ phrase?: Sealed;
31
33
  }
34
+ type Sealed = {
35
+ kdf: "scrypt";
36
+ N: number;
37
+ r: number;
38
+ p: number;
39
+ salt: string;
40
+ iv: string;
41
+ tag: string;
42
+ ct: string;
43
+ };
44
+ export declare const EVM_PATH = "m/44'/60'/0'/0/0";
45
+ export declare const SOLANA_PATH = "m/44'/501'/0'/0'";
46
+ /** SLIP-0010 ed25519 private key for a hardened-only path, from a BIP-39 seed. */
47
+ export declare function slip10Ed25519(seed: Uint8Array, path: string): Uint8Array;
48
+ /** Both keys from a recovery phrase. Throws on an invalid phrase. */
49
+ export declare function keysFromPhrase(phrase: string): {
50
+ evm: HDNodeWallet;
51
+ solana: Keypair;
52
+ phrase: string;
53
+ };
54
+ export declare function newPhrase(): string;
32
55
  export interface Keys {
33
56
  evm: Wallet | HDNodeWallet;
34
57
  solana: Keypair;
35
58
  }
36
- /** Make a new wallet (or import keys). Refuses to overwrite an existing one. */
59
+ /**
60
+ * Make a new wallet from a fresh recovery phrase, restore one from a phrase, or import raw keys.
61
+ * Refuses to overwrite an existing wallet unless `replace` is set, which keeps the old file as keystore.json.replaced-<time>.
62
+ */
37
63
  export declare function createKeystore(password: string, opts?: {
38
64
  dir?: string;
65
+ phrase?: string;
39
66
  evmPrivateKey?: string;
40
67
  solanaSecretKey?: Uint8Array;
41
68
  scrypt?: ScryptParams;
69
+ replace?: boolean;
42
70
  }): Promise<{
43
71
  evm: string;
44
72
  solana: string;
73
+ phrase: string | undefined;
74
+ }>;
75
+ /** Whether the owner has confirmed they wrote the backup down. */
76
+ export declare function backupDone(dir?: string): boolean;
77
+ export declare function markBackedUp(dir?: string): void;
78
+ /** Is there a recovery phrase, or only keys (wallets made before 0.2.2)? */
79
+ export declare function backupKind(dir?: string): "phrase" | "keys";
80
+ /**
81
+ * What the owner writes down to restore the wallet: the phrase, or for older wallets
82
+ * the two private keys (EVM hex, Solana base58, the formats other wallets import).
83
+ */
84
+ export declare function revealBackup(password: string, dir?: string): Promise<{
85
+ kind: "phrase";
86
+ phrase: string;
87
+ } | {
88
+ kind: "keys";
89
+ evm_private_key: string;
90
+ solana_secret_key: string;
45
91
  }>;
46
92
  export declare function readKeystore(dir?: string): KeystoreFile;
47
93
  /** Public addresses only; no password needed. */
@@ -51,3 +97,4 @@ export declare function addresses(dir?: string): {
51
97
  };
52
98
  /** Unlock both keys. Throws "wrong password" on a bad password. */
53
99
  export declare function unlock(password: string, dir?: string): Promise<Keys>;
100
+ export {};
package/dist/keystore.js CHANGED
@@ -3,22 +3,64 @@
3
3
  * EVM: the standard Ethereum JSON keystore (ethers v6, scrypt + AES-128-CTR).
4
4
  * Solana: the 64-byte secret key, scrypt-derived key + AES-256-GCM.
5
5
  * Tollkit never sees either key or the password.
6
+ *
7
+ * New wallets come from a 12-word BIP-39 recovery phrase, derived the way
8
+ * MetaMask and Phantom do it, so the same phrase restores the same addresses
9
+ * there too (checked 2026-10-14):
10
+ * EVM m/44'/60'/0'/0/0 (MetaMask: "default BIP-44 derivation path (m/44'/60'/0'/0)";
11
+ * Phantom default bip44Change "m/44'/60'/0'/0/${index}")
12
+ * Solana m/44'/501'/0'/0' (Phantom default bip44Change "m/44'/501'/${index}'/0'"),
13
+ * ed25519 via SLIP-0010 (hardened only).
14
+ * The phrase is kept encrypted like the keys so the owner can view it again with the password.
6
15
  */
7
16
  import { Keypair } from "@solana/web3.js";
8
- import { Wallet, encryptKeystoreJson } from "ethers";
17
+ import { Wallet, HDNodeWallet, Mnemonic, encryptKeystoreJson, computeHmac, getBytes, concat, toBeArray, zeroPadValue, encodeBase58, randomBytes as ethersRandom } from "ethers";
9
18
  import { createCipheriv, createDecipheriv, randomBytes, scrypt as scryptCb } from "node:crypto";
10
19
  import { existsSync, readFileSync, writeFileSync, renameSync } from "node:fs";
11
20
  import { files, walletHome } from "./paths.js";
21
+ import path from "node:path";
12
22
  export const DEFAULT_SCRYPT = { N: 1 << 17, r: 8, p: 1 };
23
+ export const EVM_PATH = "m/44'/60'/0'/0/0";
24
+ export const SOLANA_PATH = "m/44'/501'/0'/0'";
25
+ /** SLIP-0010 ed25519 private key for a hardened-only path, from a BIP-39 seed. */
26
+ export function slip10Ed25519(seed, path) {
27
+ if (!/^m(\/\d+')*$/.test(path))
28
+ throw new Error("ed25519 paths must be fully hardened, e.g. m/44'/501'/0'/0'");
29
+ let I = getBytes(computeHmac("sha512", new TextEncoder().encode("ed25519 seed"), seed));
30
+ let key = I.slice(0, 32), chain = I.slice(32);
31
+ for (const seg of path.split("/").slice(1)) {
32
+ const index = (Number(seg.slice(0, -1)) + 0x80000000) >>> 0;
33
+ const data = concat([new Uint8Array([0]), key, zeroPadValue(toBeArray(index), 4)]);
34
+ I = getBytes(computeHmac("sha512", chain, data));
35
+ key = I.slice(0, 32);
36
+ chain = I.slice(32);
37
+ }
38
+ return key;
39
+ }
40
+ /** Both keys from a recovery phrase. Throws on an invalid phrase. */
41
+ export function keysFromPhrase(phrase) {
42
+ const clean = phrase.trim().toLowerCase().split(/\s+/).join(" ");
43
+ let m;
44
+ try {
45
+ m = Mnemonic.fromPhrase(clean);
46
+ }
47
+ catch {
48
+ throw new Error("That recovery phrase isn't valid. Check the words and their order.");
49
+ }
50
+ const evm = HDNodeWallet.fromMnemonic(m, EVM_PATH);
51
+ const solana = Keypair.fromSeed(slip10Ed25519(getBytes(m.computeSeed()), SOLANA_PATH));
52
+ return { evm, solana, phrase: m.phrase };
53
+ }
54
+ export function newPhrase() { return Mnemonic.fromEntropy(ethersRandom(16)).phrase; }
13
55
  const scrypt = (pw, salt, s) => new Promise((res, rej) => scryptCb(pw, salt, 32, { N: s.N, r: s.r, p: s.p, maxmem: 256 * 1024 * 1024 }, (e, k) => (e ? rej(e) : res(k))));
14
- async function sealSolana(secret, pw, s) {
56
+ async function seal(secret, pw, s) {
15
57
  const salt = randomBytes(16), iv = randomBytes(12);
16
58
  const key = await scrypt(pw, salt, s);
17
59
  const c = createCipheriv("aes-256-gcm", key, iv);
18
60
  const ct = Buffer.concat([c.update(Buffer.from(secret)), c.final()]);
19
61
  return { kdf: "scrypt", ...s, salt: salt.toString("hex"), iv: iv.toString("hex"), tag: c.getAuthTag().toString("hex"), ct: ct.toString("hex") };
20
62
  }
21
- async function openSolana(box, pw) {
63
+ async function openSealed(box, pw) {
22
64
  const key = await scrypt(pw, Buffer.from(box.salt, "hex"), { N: box.N, r: box.r, p: box.p });
23
65
  const d = createDecipheriv("aes-256-gcm", key, Buffer.from(box.iv, "hex"));
24
66
  d.setAuthTag(Buffer.from(box.tag, "hex"));
@@ -29,21 +71,38 @@ async function openSolana(box, pw) {
29
71
  catch {
30
72
  throw new Error("wrong password");
31
73
  }
32
- return Keypair.fromSecretKey(new Uint8Array(secret));
74
+ return secret;
33
75
  }
76
+ const openSolana = async (box, pw) => Keypair.fromSecretKey(new Uint8Array(await openSealed(box, pw)));
34
77
  function checkPassword(pw) {
35
78
  if (typeof pw !== "string" || pw.length < 12)
36
79
  throw new Error("Use a password of at least 12 characters.");
37
80
  }
38
- /** Make a new wallet (or import keys). Refuses to overwrite an existing one. */
81
+ /**
82
+ * Make a new wallet from a fresh recovery phrase, restore one from a phrase, or import raw keys.
83
+ * Refuses to overwrite an existing wallet unless `replace` is set, which keeps the old file as keystore.json.replaced-<time>.
84
+ */
39
85
  export async function createKeystore(password, opts = {}) {
40
86
  checkPassword(password);
41
87
  const f = files(walletHome(opts.dir));
42
- if (existsSync(f.keystore))
43
- throw new Error(`A wallet already exists at ${f.keystore}. Back it up and remove it first if you want a new one.`);
88
+ if (existsSync(f.keystore)) {
89
+ if (!opts.replace)
90
+ throw new Error(`A wallet already exists at ${f.keystore}. Back it up and remove it first if you want a new one.`);
91
+ // Keep the old wallet's files (renamed, never deleted). Its limits and saved password were sealed with the old password.
92
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
93
+ for (const old of [f.keystore, f.policy, f.backup, path.join(walletHome(opts.dir), "password")])
94
+ if (existsSync(old))
95
+ renameSync(old, `${old}.replaced-${stamp}`);
96
+ }
44
97
  const s = opts.scrypt ?? DEFAULT_SCRYPT;
45
- const evm = opts.evmPrivateKey ? new Wallet(opts.evmPrivateKey) : Wallet.createRandom();
46
- const sol = opts.solanaSecretKey ? Keypair.fromSecretKey(opts.solanaSecretKey) : Keypair.generate();
98
+ const importing = !!(opts.evmPrivateKey || opts.solanaSecretKey);
99
+ if (importing && opts.phrase)
100
+ throw new Error("Give a recovery phrase or keys, not both.");
101
+ if (importing && !(opts.evmPrivateKey && opts.solanaSecretKey))
102
+ throw new Error("Importing keys needs both the EVM private key and the Solana secret key.");
103
+ const fromPhrase = importing ? null : keysFromPhrase(opts.phrase ?? newPhrase());
104
+ const evm = fromPhrase ? fromPhrase.evm : new Wallet(opts.evmPrivateKey);
105
+ const sol = fromPhrase ? fromPhrase.solana : Keypair.fromSecretKey(opts.solanaSecretKey);
47
106
  const evmJson = await encryptKeystoreJson({ address: evm.address, privateKey: evm.privateKey }, password, { scrypt: { N: s.N, r: s.r, p: s.p } });
48
107
  const ks = {
49
108
  version: 1,
@@ -51,12 +110,29 @@ export async function createKeystore(password, opts = {}) {
51
110
  evm_address: evm.address,
52
111
  solana_address: sol.publicKey.toBase58(),
53
112
  evm: evmJson,
54
- solana: await sealSolana(sol.secretKey, password, s),
113
+ solana: await seal(sol.secretKey, password, s),
114
+ ...(fromPhrase ? { phrase: await seal(new TextEncoder().encode(fromPhrase.phrase), password, s) } : {}),
55
115
  };
56
116
  const tmp = f.keystore + ".tmp";
57
117
  writeFileSync(tmp, JSON.stringify(ks, null, 2), { mode: 0o600 });
58
118
  renameSync(tmp, f.keystore);
59
- return { evm: ks.evm_address, solana: ks.solana_address };
119
+ return { evm: ks.evm_address, solana: ks.solana_address, phrase: fromPhrase?.phrase };
120
+ }
121
+ /** Whether the owner has confirmed they wrote the backup down. */
122
+ export function backupDone(dir) { return existsSync(files(walletHome(dir)).backup); }
123
+ export function markBackedUp(dir) { writeFileSync(files(walletHome(dir)).backup, JSON.stringify({ confirmed_at: new Date().toISOString() }) + "\n", { mode: 0o600 }); }
124
+ /** Is there a recovery phrase, or only keys (wallets made before 0.2.2)? */
125
+ export function backupKind(dir) { return readKeystore(dir).phrase ? "phrase" : "keys"; }
126
+ /**
127
+ * What the owner writes down to restore the wallet: the phrase, or for older wallets
128
+ * the two private keys (EVM hex, Solana base58, the formats other wallets import).
129
+ */
130
+ export async function revealBackup(password, dir) {
131
+ const ks = readKeystore(dir);
132
+ if (ks.phrase)
133
+ return { kind: "phrase", phrase: new TextDecoder().decode(await openSealed(ks.phrase, password)) };
134
+ const k = await unlock(password, dir);
135
+ return { kind: "keys", evm_private_key: k.evm.privateKey, solana_secret_key: encodeBase58(k.solana.secretKey) };
60
136
  }
61
137
  export function readKeystore(dir) {
62
138
  const f = files(walletHome(dir));
@@ -1 +1 @@
1
- {"version":3,"file":"keystore.js","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keystore.js","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"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"}
package/dist/ledger.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Policy } from "./policy.js";
2
- export type Kind = "trade" | "payment" | "withdrawal";
2
+ export type Kind = "trade" | "payment" | "withdrawal" | "stake" | "move" | "dapp";
3
3
  export type Status = "pending" | "done" | "failed";
4
4
  export interface Entry {
5
5
  id: string;
package/dist/mcp.d.ts CHANGED
@@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { TollkitWallet } from "./wallet.js";
3
3
  /** The only tools the wallet's built-in AI chat gets: read, look at prices, and suggest rules for the owner to turn on. */
4
4
  export declare const ADVISOR_TOOLS: string[];
5
- export declare const VERSION = "0.2.1";
5
+ export declare const VERSION = "0.2.2";
6
6
  export declare function passwordFromEnv(): string;
7
7
  export declare function buildServer(w: TollkitWallet, o?: {
8
8
  advisor?: boolean;
package/dist/mcp.js CHANGED
@@ -13,7 +13,7 @@ import { TollkitWallet } from "./wallet.js";
13
13
  import { ACTIONS, proposeRules } from "./actions.js";
14
14
  /** The only tools the wallet's built-in AI chat gets: read, look at prices, and suggest rules for the owner to turn on. */
15
15
  export const ADVISOR_TOOLS = ["wallet_status", "wallet_balances", "swap_quote", "receipts", "market_prices", "price_history", "autopilot_rules", "autopilot_propose", "paper_status"];
16
- export const VERSION = "0.2.1";
16
+ export const VERSION = "0.2.2";
17
17
  export function passwordFromEnv() {
18
18
  const file = process.env.TOLLKIT_WALLET_PASSWORD_FILE;
19
19
  if (file)
@@ -0,0 +1,8 @@
1
+ /** Keeping agent-driven requests on the public internet. */
2
+ /** This computer and private networks (so an agent can't reach the local dashboard or devices). */
3
+ export declare function isLocalUrl(u: string): boolean;
4
+ /**
5
+ * fetch that refuses this computer and private networks, on the first URL and on every redirect
6
+ * (Node's fetch would otherwise follow a redirect to 127.0.0.1 with the same method and headers).
7
+ */
8
+ export declare function publicFetch(f?: typeof fetch): typeof fetch;
@@ -0,0 +1,44 @@
1
+ /** Keeping agent-driven requests on the public internet. */
2
+ /** This computer and private networks (so an agent can't reach the local dashboard or devices). */
3
+ export function isLocalUrl(u) {
4
+ let h;
5
+ try {
6
+ h = new URL(u).hostname.toLowerCase().replace(/^\[|\]$/g, "");
7
+ }
8
+ catch {
9
+ return true;
10
+ }
11
+ if (h === "localhost" || h.endsWith(".localhost") || h.endsWith(".local") || h === "0.0.0.0" || h === "::" || h === "::1")
12
+ return true;
13
+ if (h.includes(":"))
14
+ return /^(fe80|fc|fd)/.test(h) || h.startsWith("::ffff:");
15
+ const m = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(h);
16
+ if (!m)
17
+ return false;
18
+ const [a, b] = [Number(m[1]), Number(m[2])];
19
+ return a === 127 || a === 10 || a === 0 || (a === 169 && b === 254) || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 100 && b >= 64 && b <= 127);
20
+ }
21
+ /**
22
+ * fetch that refuses this computer and private networks, on the first URL and on every redirect
23
+ * (Node's fetch would otherwise follow a redirect to 127.0.0.1 with the same method and headers).
24
+ */
25
+ export function publicFetch(f = fetch) {
26
+ return (async (input, init = {}) => {
27
+ let url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
28
+ let opts = { ...init };
29
+ for (let hop = 0; hop <= 5; hop++) {
30
+ if (isLocalUrl(url))
31
+ throw new Error("Refused: that address is on this computer or a private network.");
32
+ const r = await f(url, { ...opts, redirect: "manual" });
33
+ const loc = r.headers.get("location");
34
+ if (![301, 302, 303, 307, 308].includes(r.status) || !loc)
35
+ return r;
36
+ url = new URL(loc, url).href;
37
+ const m = String(opts.method ?? "GET").toUpperCase();
38
+ if (r.status === 303 || ((r.status === 301 || r.status === 302) && m === "POST"))
39
+ opts = { ...opts, method: "GET", body: undefined };
40
+ }
41
+ throw new Error("Too many redirects.");
42
+ });
43
+ }
44
+ //# sourceMappingURL=netguard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"netguard.js","sourceRoot":"","sources":["../src/netguard.ts"],"names":[],"mappings":"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"}
package/dist/paths.d.ts CHANGED
@@ -10,4 +10,5 @@ export declare const files: (dir: string) => {
10
10
  lock: string;
11
11
  sanctions: string;
12
12
  telegram: string;
13
+ backup: string;
13
14
  };
package/dist/paths.js CHANGED
@@ -18,5 +18,6 @@ export const files = (dir) => ({
18
18
  lock: path.join(dir, ".lock"),
19
19
  sanctions: path.join(dir, "sanctions.json"),
20
20
  telegram: path.join(dir, "telegram.json"),
21
+ backup: path.join(dir, "backup.json"),
21
22
  });
22
23
  //# sourceMappingURL=paths.js.map
package/dist/paths.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,MAAM,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAC/F,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,CAAC;AACX,CAAC;AAED,qGAAqG;AACrG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;AACrF,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEvI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC;IACrC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC;IACzC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC;IACrC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC;IACtC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC3C,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC;CAC1C,CAAC,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,MAAM,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAC/F,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,CAAC;AACX,CAAC;AAED,qGAAqG;AACrG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;AACrF,0EAA0E;AAC1E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEvI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC;IACrC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC;IACzC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC;IACrC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC;IACtC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC3C,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC;IACzC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC;CACtC,CAAC,CAAC"}
package/dist/policy.d.ts CHANGED
@@ -17,12 +17,12 @@ export declare const PolicySchema: z.ZodObject<{
17
17
  address: z.ZodString;
18
18
  label: z.ZodDefault<z.ZodString>;
19
19
  }, "strip", z.ZodTypeAny, {
20
- chain: "base" | "ethereum" | "solana";
21
20
  address: string;
21
+ chain: "base" | "ethereum" | "solana";
22
22
  label: string;
23
23
  }, {
24
- chain: "base" | "ethereum" | "solana";
25
24
  address: string;
25
+ chain: "base" | "ethereum" | "solana";
26
26
  label?: string | undefined;
27
27
  }>, "many">>;
28
28
  }, "strip", z.ZodTypeAny, {
@@ -37,8 +37,8 @@ export declare const PolicySchema: z.ZodObject<{
37
37
  block_seller_warnings: boolean;
38
38
  agent_rules: "propose" | "auto";
39
39
  withdraw_addresses: {
40
- chain: "base" | "ethereum" | "solana";
41
40
  address: string;
41
+ chain: "base" | "ethereum" | "solana";
42
42
  label: string;
43
43
  }[];
44
44
  }, {
@@ -53,8 +53,8 @@ export declare const PolicySchema: z.ZodObject<{
53
53
  block_seller_warnings: boolean;
54
54
  agent_rules?: "propose" | "auto" | undefined;
55
55
  withdraw_addresses?: {
56
- chain: "base" | "ethereum" | "solana";
57
56
  address: string;
57
+ chain: "base" | "ethereum" | "solana";
58
58
  label?: string | undefined;
59
59
  }[] | undefined;
60
60
  }>;
package/dist/rules.d.ts CHANGED
@@ -31,12 +31,12 @@ export declare const RuleInput: z.ZodObject<{
31
31
  /** Id of an existing rule this one replaces: turning this on cancels that one (e.g. moving a stop-loss up). */
32
32
  replaces: z.ZodOptional<z.ZodString>;
33
33
  }, "strip", z.ZodTypeAny, {
34
- chain: "base" | "ethereum" | "solana";
35
34
  kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
35
+ chain: "base" | "ethereum" | "solana";
36
36
  token: string;
37
37
  every?: "hour" | "day" | "week" | undefined;
38
- reason?: string | undefined;
39
38
  name?: string | undefined;
39
+ reason?: string | undefined;
40
40
  sell_amount?: string | undefined;
41
41
  amount_usd?: number | undefined;
42
42
  sell_percent?: number | undefined;
@@ -49,12 +49,12 @@ export declare const RuleInput: z.ZodObject<{
49
49
  expires_at?: string | undefined;
50
50
  replaces?: string | undefined;
51
51
  }, {
52
- chain: "base" | "ethereum" | "solana";
53
52
  kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
53
+ chain: "base" | "ethereum" | "solana";
54
54
  token: string;
55
55
  every?: "hour" | "day" | "week" | undefined;
56
- reason?: string | undefined;
57
56
  name?: string | undefined;
57
+ reason?: string | undefined;
58
58
  sell_amount?: string | undefined;
59
59
  amount_usd?: number | undefined;
60
60
  sell_percent?: number | undefined;
package/dist/sell.d.ts ADDED
@@ -0,0 +1,60 @@
1
+ import type { Chain } from "./chains.js";
2
+ export declare const SELL_ASSETS: Record<Chain, string[]>;
3
+ /** Coinbase's window after "Cash out now" (docs.cdp.coinbase.com/onramp/offramp/offramp-integration-guide). */
4
+ export declare const SEND_WINDOW_MS: number;
5
+ export interface Sale {
6
+ ref: string;
7
+ ts: string;
8
+ chain: Chain;
9
+ asset: string;
10
+ amount: string | null;
11
+ state: "open" | "sending" | "sent" | "done" | "failed" | "expired";
12
+ tx?: string;
13
+ payout?: string;
14
+ reason?: string;
15
+ }
16
+ export interface OfframpTx {
17
+ id: string;
18
+ status: string;
19
+ asset: string;
20
+ network: string;
21
+ sell_amount: {
22
+ value: string;
23
+ currency: string;
24
+ } | null;
25
+ total: {
26
+ value: string;
27
+ currency: string;
28
+ } | null;
29
+ coinbase_fee: {
30
+ value: string;
31
+ currency: string;
32
+ } | null;
33
+ to_address: string;
34
+ from_address: string;
35
+ tx_hash: string;
36
+ created_at: string;
37
+ updated_at: string;
38
+ }
39
+ type Fetch = typeof fetch;
40
+ export declare class Sales {
41
+ private o;
42
+ private file;
43
+ constructor(o: {
44
+ dir?: string;
45
+ proxy?: string;
46
+ fetch?: Fetch;
47
+ });
48
+ private get f();
49
+ private get proxy();
50
+ list(): Sale[];
51
+ get(ref: string): Sale | undefined;
52
+ update(ref: string, patch: Partial<Sale>): void;
53
+ start(address: string, chain: Chain, asset: string, amount?: string): Promise<{
54
+ url: string;
55
+ ref: string;
56
+ }>;
57
+ /** Coinbase's latest word on a sale (null until the owner has started on Coinbase). */
58
+ status(address: string, ref: string): Promise<OfframpTx | null>;
59
+ }
60
+ export {};
package/dist/sell.js ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * "Cash out": sell crypto to your bank or PayPal through Coinbase Offramp.
3
+ *
4
+ * 1. The wallet asks Tollkit's server (POST {proxy}/offramp) for a single-use Coinbase sell link and a reference.
5
+ * 2. The owner signs in to Coinbase, picks where the money goes and clicks "Cash out now".
6
+ * 3. Coinbase then says where to send the crypto (GET {proxy}/offramp/status). The wallet shows that to the owner,
7
+ * who confirms with the password; only then is the crypto sent. Coinbase allows 30 minutes for this.
8
+ * Only the public address, network, coin and amount are sent to Tollkit's server. A Coinbase account is required.
9
+ */
10
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
11
+ import path from "node:path";
12
+ import { DEFAULT_PROXY } from "./swap.js";
13
+ import { walletHome } from "./paths.js";
14
+ export const SELL_ASSETS = { base: ["USDC", "ETH"], ethereum: ["USDC", "ETH"], solana: ["USDC", "SOL"] };
15
+ /** Coinbase's window after "Cash out now" (docs.cdp.coinbase.com/onramp/offramp/offramp-integration-guide). */
16
+ export const SEND_WINDOW_MS = 30 * 60_000;
17
+ export class Sales {
18
+ o;
19
+ file;
20
+ constructor(o) {
21
+ this.o = o;
22
+ this.file = path.join(walletHome(o.dir), "sales.json");
23
+ }
24
+ get f() { return this.o.fetch ?? fetch; }
25
+ get proxy() { return this.o.proxy ?? DEFAULT_PROXY; }
26
+ list() { try {
27
+ return existsSync(this.file) ? JSON.parse(readFileSync(this.file, "utf8")) : [];
28
+ }
29
+ catch {
30
+ return [];
31
+ } }
32
+ get(ref) { return this.list().find((s) => s.ref === ref); }
33
+ update(ref, patch) {
34
+ const l = this.list().map((s) => (s.ref === ref ? { ...s, ...patch } : s));
35
+ writeFileSync(this.file, JSON.stringify(l, null, 2), { mode: 0o600 });
36
+ }
37
+ async start(address, chain, asset, amount) {
38
+ if (!SELL_ASSETS[chain]?.includes(asset))
39
+ throw new Error(`On ${chain} you can cash out ${(SELL_ASSETS[chain] ?? []).join(" or ")}.`);
40
+ if (amount === undefined || !(/^\d+(\.\d+)?$/.test(amount) && Number(amount) > 0))
41
+ throw new Error("Enter how much to cash out, like 25 or 0.05.");
42
+ const r = await this.f(`${this.proxy}/offramp`, { method: "POST", headers: { "content-type": "application/json" }, signal: AbortSignal.timeout(25_000), body: JSON.stringify({ address, network: chain, asset, ...(amount ? { amount } : {}) }) });
43
+ const j = await r.json().catch(() => ({}));
44
+ if (!r.ok)
45
+ throw new Error(r.status === 404 ? "Cashing out isn't available from Tollkit's server yet." : j?.message ?? `Tollkit's server answered HTTP ${r.status}.`);
46
+ if (typeof j.url !== "string" || !j.url.startsWith("https://pay.coinbase.com/v3/sell/") || !/^tw-[0-9a-f]{16}-[0-9a-f]{16}$/.test(String(j.ref)))
47
+ throw new Error("Didn't get a Coinbase sell link.");
48
+ const sale = { ref: j.ref, ts: new Date().toISOString(), chain, asset, amount: amount ?? null, state: "open" };
49
+ writeFileSync(this.file, JSON.stringify([sale, ...this.list()].slice(0, 50), null, 2), { mode: 0o600 });
50
+ return { url: j.url, ref: j.ref };
51
+ }
52
+ /** Coinbase's latest word on a sale (null until the owner has started on Coinbase). */
53
+ async status(address, ref) {
54
+ const r = await this.f(`${this.proxy}/offramp/status?${new URLSearchParams({ ref, address })}`, { signal: AbortSignal.timeout(20_000) });
55
+ const j = await r.json().catch(() => ({}));
56
+ if (!r.ok)
57
+ throw new Error(j?.message ?? `Tollkit's server answered HTTP ${r.status}.`);
58
+ const t = j.transaction;
59
+ if (t) {
60
+ const s = this.get(ref);
61
+ if (s && s.state !== "done" && /SUCCESS/.test(t.status))
62
+ this.update(ref, { state: "done", payout: t.total ? `${t.total.value} ${t.total.currency}` : undefined });
63
+ else if (s && s.state !== "failed" && /FAILED/.test(t.status))
64
+ this.update(ref, { state: "failed" });
65
+ else if (s && s.state === "open" && /EXPIRED/.test(t.status))
66
+ this.update(ref, { state: "expired" });
67
+ }
68
+ return t;
69
+ }
70
+ }
71
+ //# sourceMappingURL=sell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sell.js","sourceRoot":"","sources":["../src/sell.ts"],"names":[],"mappings":"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"}