@coinfello/agent-cli 0.1.3 → 0.1.4
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/dist/index.js +282 -808
- package/dist/secure-enclave-signer.app/Contents/Info.plist +20 -0
- package/dist/secure-enclave-signer.app/Contents/MacOS/secure-enclave-signer +0 -0
- package/dist/secure-enclave-signer.app/Contents/_CodeSignature/CodeResources +123 -0
- package/dist/secure-enclave-signer.app/Contents/embedded.provisionprofile +0 -0
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -2,12 +2,119 @@
|
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { toMetaMaskSmartAccount, Implementation, createDelegation } from "@metamask/smart-accounts-kit";
|
|
4
4
|
import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
|
|
5
|
+
import { toWebAuthnAccount } from "viem/account-abstraction";
|
|
5
6
|
import { createPublicClient, http, serializeErc6492Signature } from "viem";
|
|
6
7
|
import * as chains from "viem/chains";
|
|
7
|
-
import { randomBytes } from "node:crypto";
|
|
8
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
9
|
+
import { execFile } from "node:child_process";
|
|
10
|
+
import { promisify } from "node:util";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { platform, homedir } from "node:os";
|
|
8
14
|
import { readFile, mkdir, writeFile } from "node:fs/promises";
|
|
9
|
-
import {
|
|
10
|
-
|
|
15
|
+
import { createSiweMessage } from "viem/siwe";
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
17
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname$1 = dirname(__filename$1);
|
|
19
|
+
function getBinaryPath() {
|
|
20
|
+
return join(__dirname$1, "secure-enclave-signer.app", "Contents", "MacOS", "secure-enclave-signer");
|
|
21
|
+
}
|
|
22
|
+
function isSecureEnclaveAvailable() {
|
|
23
|
+
return platform() === "darwin";
|
|
24
|
+
}
|
|
25
|
+
async function runCommand(args) {
|
|
26
|
+
const binaryPath = getBinaryPath();
|
|
27
|
+
try {
|
|
28
|
+
const { stdout } = await execFileAsync(binaryPath, args, {
|
|
29
|
+
timeout: 3e4
|
|
30
|
+
});
|
|
31
|
+
return JSON.parse(stdout.trim());
|
|
32
|
+
} catch (err) {
|
|
33
|
+
const error = err;
|
|
34
|
+
if (error.stderr) {
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(error.stderr.trim());
|
|
37
|
+
throw new Error(`SecureEnclave [${parsed.error}]: ${parsed.message}`);
|
|
38
|
+
} catch (parseErr) {
|
|
39
|
+
if (parseErr instanceof SyntaxError) {
|
|
40
|
+
throw new Error(`SecureEnclave error: ${error.stderr}`);
|
|
41
|
+
}
|
|
42
|
+
throw parseErr;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`SecureEnclave command failed: ${error.message ?? "Unknown error"}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function generateKey() {
|
|
49
|
+
const result = await runCommand(["generate"]);
|
|
50
|
+
return {
|
|
51
|
+
tag: result.tag,
|
|
52
|
+
x: BigInt(`0x${result.x}`),
|
|
53
|
+
y: BigInt(`0x${result.y}`)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async function signPayload(tag, payload) {
|
|
57
|
+
const hex = payload.startsWith("0x") ? payload.slice(2) : payload;
|
|
58
|
+
const result = await runCommand(["sign", "--tag", tag, "--payload", hex]);
|
|
59
|
+
return {
|
|
60
|
+
derSignature: `0x${result.signature}`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const RPID = "localhost";
|
|
64
|
+
const ORIGIN = "https://localhost";
|
|
65
|
+
function sha256(data) {
|
|
66
|
+
return createHash("sha256").update(data).digest();
|
|
67
|
+
}
|
|
68
|
+
function toBase64Url(buf) {
|
|
69
|
+
return buf.toString("base64url");
|
|
70
|
+
}
|
|
71
|
+
function createSecureEnclaveGetFn(keyTag) {
|
|
72
|
+
return async function getFn(options) {
|
|
73
|
+
const challengeBuffer = options?.publicKey?.challenge;
|
|
74
|
+
if (!challengeBuffer) {
|
|
75
|
+
throw new Error("No challenge in credential request options");
|
|
76
|
+
}
|
|
77
|
+
const challenge = Buffer.from(challengeBuffer);
|
|
78
|
+
const challengeBase64Url = toBase64Url(challenge);
|
|
79
|
+
const rpIdHash = sha256(Buffer.from(RPID, "utf-8"));
|
|
80
|
+
const flags = Buffer.from([5]);
|
|
81
|
+
const signCount = Buffer.alloc(4);
|
|
82
|
+
const authenticatorData = Buffer.concat([rpIdHash, flags, signCount]);
|
|
83
|
+
const clientDataObj = {
|
|
84
|
+
type: "webauthn.get",
|
|
85
|
+
challenge: challengeBase64Url,
|
|
86
|
+
origin: ORIGIN,
|
|
87
|
+
crossOrigin: false
|
|
88
|
+
};
|
|
89
|
+
const clientDataJSON = JSON.stringify(clientDataObj);
|
|
90
|
+
const clientDataBuffer = Buffer.from(clientDataJSON, "utf-8");
|
|
91
|
+
const clientDataHash = sha256(clientDataBuffer);
|
|
92
|
+
const payload = Buffer.concat([authenticatorData, clientDataHash]);
|
|
93
|
+
const payloadHex = `0x${payload.toString("hex")}`;
|
|
94
|
+
const { derSignature } = await signPayload(keyTag, payloadHex);
|
|
95
|
+
const sigHex = derSignature.startsWith("0x") ? derSignature.slice(2) : derSignature;
|
|
96
|
+
const signatureBuffer = Buffer.from(sigHex, "hex");
|
|
97
|
+
const credentialId = Buffer.from(keyTag, "utf-8").toString("base64url");
|
|
98
|
+
return {
|
|
99
|
+
id: credentialId,
|
|
100
|
+
type: "public-key",
|
|
101
|
+
rawId: toArrayBuffer(Buffer.from(keyTag, "utf-8")),
|
|
102
|
+
authenticatorAttachment: "platform",
|
|
103
|
+
response: {
|
|
104
|
+
authenticatorData: toArrayBuffer(authenticatorData),
|
|
105
|
+
clientDataJSON: toArrayBuffer(clientDataBuffer),
|
|
106
|
+
signature: toArrayBuffer(signatureBuffer)
|
|
107
|
+
},
|
|
108
|
+
getClientExtensionResults: () => ({})
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function toArrayBuffer(buf) {
|
|
113
|
+
const ab = new ArrayBuffer(buf.byteLength);
|
|
114
|
+
const view = new Uint8Array(ab);
|
|
115
|
+
view.set(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));
|
|
116
|
+
return ab;
|
|
117
|
+
}
|
|
11
118
|
function resolveChain(chainName) {
|
|
12
119
|
const chain = chains[chainName];
|
|
13
120
|
if (!chain) {
|
|
@@ -68,6 +175,77 @@ function createSubdelegation({
|
|
|
68
175
|
salt: `0x${randomBytes(32).toString("hex")}`
|
|
69
176
|
});
|
|
70
177
|
}
|
|
178
|
+
async function createSmartAccountWithSecureEnclave(chainInput) {
|
|
179
|
+
const chain = resolveChainInput(chainInput);
|
|
180
|
+
const publicClient = createPublicClient({ chain, transport: http() });
|
|
181
|
+
const keyPair = await generateKey();
|
|
182
|
+
const keyId = `0x${randomBytes(32).toString("hex")}`;
|
|
183
|
+
const xHex = keyPair.x.toString(16).padStart(64, "0");
|
|
184
|
+
const yHex = keyPair.y.toString(16).padStart(64, "0");
|
|
185
|
+
const publicKeyHex = `0x04${xHex}${yHex}`;
|
|
186
|
+
const credentialId = Buffer.from(keyPair.tag).toString("base64url");
|
|
187
|
+
const webAuthnAccount = toWebAuthnAccount({
|
|
188
|
+
credential: {
|
|
189
|
+
id: credentialId,
|
|
190
|
+
publicKey: publicKeyHex
|
|
191
|
+
},
|
|
192
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
193
|
+
getFn: createSecureEnclaveGetFn(keyPair.tag),
|
|
194
|
+
rpId: "localhost"
|
|
195
|
+
});
|
|
196
|
+
const smartAccount = await toMetaMaskSmartAccount({
|
|
197
|
+
client: publicClient,
|
|
198
|
+
implementation: Implementation.Hybrid,
|
|
199
|
+
deployParams: [
|
|
200
|
+
"0x0000000000000000000000000000000000000000",
|
|
201
|
+
[keyId],
|
|
202
|
+
[keyPair.x],
|
|
203
|
+
[keyPair.y]
|
|
204
|
+
],
|
|
205
|
+
deploySalt: "0x",
|
|
206
|
+
signer: { webAuthnAccount, keyId }
|
|
207
|
+
});
|
|
208
|
+
const address = await smartAccount.getAddress();
|
|
209
|
+
return {
|
|
210
|
+
smartAccount,
|
|
211
|
+
address,
|
|
212
|
+
keyTag: keyPair.tag,
|
|
213
|
+
publicKeyX: `0x${xHex}`,
|
|
214
|
+
publicKeyY: `0x${yHex}`,
|
|
215
|
+
keyId
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
async function getSmartAccountFromSecureEnclave(keyTag, publicKeyX, publicKeyY, keyId, chainInput) {
|
|
219
|
+
const chain = resolveChainInput(chainInput);
|
|
220
|
+
const publicClient = createPublicClient({ chain, transport: http() });
|
|
221
|
+
const xBigInt = BigInt(publicKeyX);
|
|
222
|
+
const yBigInt = BigInt(publicKeyY);
|
|
223
|
+
const xHex = xBigInt.toString(16).padStart(64, "0");
|
|
224
|
+
const yHex = yBigInt.toString(16).padStart(64, "0");
|
|
225
|
+
const publicKeyHex = `0x04${xHex}${yHex}`;
|
|
226
|
+
const credentialId = Buffer.from(keyTag).toString("base64url");
|
|
227
|
+
const webAuthnAccount = toWebAuthnAccount({
|
|
228
|
+
credential: {
|
|
229
|
+
id: credentialId,
|
|
230
|
+
publicKey: publicKeyHex
|
|
231
|
+
},
|
|
232
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
233
|
+
getFn: createSecureEnclaveGetFn(keyTag),
|
|
234
|
+
rpId: "localhost"
|
|
235
|
+
});
|
|
236
|
+
return toMetaMaskSmartAccount({
|
|
237
|
+
client: publicClient,
|
|
238
|
+
implementation: Implementation.Hybrid,
|
|
239
|
+
deployParams: [
|
|
240
|
+
"0x0000000000000000000000000000000000000000",
|
|
241
|
+
[keyId],
|
|
242
|
+
[xBigInt],
|
|
243
|
+
[yBigInt]
|
|
244
|
+
],
|
|
245
|
+
deploySalt: "0x",
|
|
246
|
+
signer: { webAuthnAccount, keyId }
|
|
247
|
+
});
|
|
248
|
+
}
|
|
71
249
|
const CONFIG_DIR = join(homedir(), ".clawdbot", "skills", "coinfello");
|
|
72
250
|
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
73
251
|
async function loadConfig() {
|
|
@@ -860,7 +1038,7 @@ function validate(bool, cbOrMessage, message) {
|
|
|
860
1038
|
}
|
|
861
1039
|
var ParameterError = class extends Error {
|
|
862
1040
|
};
|
|
863
|
-
var version
|
|
1041
|
+
var version = "6.0.0";
|
|
864
1042
|
var PrefixSecurityEnum = {
|
|
865
1043
|
SILENT: "silent",
|
|
866
1044
|
STRICT: "strict",
|
|
@@ -2306,7 +2484,7 @@ var CookieJar = class _CookieJar {
|
|
|
2306
2484
|
// The version of tough-cookie that serialized this jar. Generally a good
|
|
2307
2485
|
// practice since future versions can make data import decisions based on
|
|
2308
2486
|
// known past behavior. When/if this matters, use `semver`.
|
|
2309
|
-
version: `tough-cookie@${version
|
|
2487
|
+
version: `tough-cookie@${version}`,
|
|
2310
2488
|
// add the store type, to make humans happy:
|
|
2311
2489
|
storeType: type,
|
|
2312
2490
|
// CookieJar configuration:
|
|
@@ -2720,797 +2898,35 @@ async function getTransactionStatus(txnId) {
|
|
|
2720
2898
|
}
|
|
2721
2899
|
return response.json();
|
|
2722
2900
|
}
|
|
2723
|
-
const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
|
|
2724
|
-
const _32n = /* @__PURE__ */ BigInt(32);
|
|
2725
|
-
function fromBig(n, le = false) {
|
|
2726
|
-
if (le)
|
|
2727
|
-
return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
|
|
2728
|
-
return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
|
|
2729
|
-
}
|
|
2730
|
-
function split(lst, le = false) {
|
|
2731
|
-
const len = lst.length;
|
|
2732
|
-
let Ah = new Uint32Array(len);
|
|
2733
|
-
let Al = new Uint32Array(len);
|
|
2734
|
-
for (let i = 0; i < len; i++) {
|
|
2735
|
-
const { h, l } = fromBig(lst[i], le);
|
|
2736
|
-
[Ah[i], Al[i]] = [h, l];
|
|
2737
|
-
}
|
|
2738
|
-
return [Ah, Al];
|
|
2739
|
-
}
|
|
2740
|
-
const rotlSH = (h, l, s) => h << s | l >>> 32 - s;
|
|
2741
|
-
const rotlSL = (h, l, s) => l << s | h >>> 32 - s;
|
|
2742
|
-
const rotlBH = (h, l, s) => l << s - 32 | h >>> 64 - s;
|
|
2743
|
-
const rotlBL = (h, l, s) => h << s - 32 | l >>> 64 - s;
|
|
2744
|
-
function isBytes(a) {
|
|
2745
|
-
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
2746
|
-
}
|
|
2747
|
-
function anumber(n) {
|
|
2748
|
-
if (!Number.isSafeInteger(n) || n < 0)
|
|
2749
|
-
throw new Error("positive integer expected, got " + n);
|
|
2750
|
-
}
|
|
2751
|
-
function abytes(b, ...lengths) {
|
|
2752
|
-
if (!isBytes(b))
|
|
2753
|
-
throw new Error("Uint8Array expected");
|
|
2754
|
-
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
2755
|
-
throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
|
|
2756
|
-
}
|
|
2757
|
-
function aexists(instance, checkFinished = true) {
|
|
2758
|
-
if (instance.destroyed)
|
|
2759
|
-
throw new Error("Hash instance has been destroyed");
|
|
2760
|
-
if (checkFinished && instance.finished)
|
|
2761
|
-
throw new Error("Hash#digest() has already been called");
|
|
2762
|
-
}
|
|
2763
|
-
function aoutput(out, instance) {
|
|
2764
|
-
abytes(out);
|
|
2765
|
-
const min = instance.outputLen;
|
|
2766
|
-
if (out.length < min) {
|
|
2767
|
-
throw new Error("digestInto() expects output buffer of length at least " + min);
|
|
2768
|
-
}
|
|
2769
|
-
}
|
|
2770
|
-
function u32(arr) {
|
|
2771
|
-
return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
|
|
2772
|
-
}
|
|
2773
|
-
function clean(...arrays) {
|
|
2774
|
-
for (let i = 0; i < arrays.length; i++) {
|
|
2775
|
-
arrays[i].fill(0);
|
|
2776
|
-
}
|
|
2777
|
-
}
|
|
2778
|
-
const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68)();
|
|
2779
|
-
function byteSwap(word) {
|
|
2780
|
-
return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255;
|
|
2781
|
-
}
|
|
2782
|
-
function byteSwap32(arr) {
|
|
2783
|
-
for (let i = 0; i < arr.length; i++) {
|
|
2784
|
-
arr[i] = byteSwap(arr[i]);
|
|
2785
|
-
}
|
|
2786
|
-
return arr;
|
|
2787
|
-
}
|
|
2788
|
-
const swap32IfBE = isLE ? (u) => u : byteSwap32;
|
|
2789
|
-
function utf8ToBytes(str) {
|
|
2790
|
-
if (typeof str !== "string")
|
|
2791
|
-
throw new Error("string expected");
|
|
2792
|
-
return new Uint8Array(new TextEncoder().encode(str));
|
|
2793
|
-
}
|
|
2794
|
-
function toBytes$1(data) {
|
|
2795
|
-
if (typeof data === "string")
|
|
2796
|
-
data = utf8ToBytes(data);
|
|
2797
|
-
abytes(data);
|
|
2798
|
-
return data;
|
|
2799
|
-
}
|
|
2800
|
-
class Hash {
|
|
2801
|
-
}
|
|
2802
|
-
function createHasher(hashCons) {
|
|
2803
|
-
const hashC = (msg) => hashCons().update(toBytes$1(msg)).digest();
|
|
2804
|
-
const tmp = hashCons();
|
|
2805
|
-
hashC.outputLen = tmp.outputLen;
|
|
2806
|
-
hashC.blockLen = tmp.blockLen;
|
|
2807
|
-
hashC.create = () => hashCons();
|
|
2808
|
-
return hashC;
|
|
2809
|
-
}
|
|
2810
|
-
const _0n = BigInt(0);
|
|
2811
|
-
const _1n = BigInt(1);
|
|
2812
|
-
const _2n = BigInt(2);
|
|
2813
|
-
const _7n = BigInt(7);
|
|
2814
|
-
const _256n = BigInt(256);
|
|
2815
|
-
const _0x71n = BigInt(113);
|
|
2816
|
-
const SHA3_PI = [];
|
|
2817
|
-
const SHA3_ROTL = [];
|
|
2818
|
-
const _SHA3_IOTA = [];
|
|
2819
|
-
for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
|
|
2820
|
-
[x, y] = [y, (2 * x + 3 * y) % 5];
|
|
2821
|
-
SHA3_PI.push(2 * (5 * y + x));
|
|
2822
|
-
SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64);
|
|
2823
|
-
let t = _0n;
|
|
2824
|
-
for (let j = 0; j < 7; j++) {
|
|
2825
|
-
R = (R << _1n ^ (R >> _7n) * _0x71n) % _256n;
|
|
2826
|
-
if (R & _2n)
|
|
2827
|
-
t ^= _1n << (_1n << /* @__PURE__ */ BigInt(j)) - _1n;
|
|
2828
|
-
}
|
|
2829
|
-
_SHA3_IOTA.push(t);
|
|
2830
|
-
}
|
|
2831
|
-
const IOTAS = split(_SHA3_IOTA, true);
|
|
2832
|
-
const SHA3_IOTA_H = IOTAS[0];
|
|
2833
|
-
const SHA3_IOTA_L = IOTAS[1];
|
|
2834
|
-
const rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s);
|
|
2835
|
-
const rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s);
|
|
2836
|
-
function keccakP(s, rounds = 24) {
|
|
2837
|
-
const B = new Uint32Array(5 * 2);
|
|
2838
|
-
for (let round = 24 - rounds; round < 24; round++) {
|
|
2839
|
-
for (let x = 0; x < 10; x++)
|
|
2840
|
-
B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
|
|
2841
|
-
for (let x = 0; x < 10; x += 2) {
|
|
2842
|
-
const idx1 = (x + 8) % 10;
|
|
2843
|
-
const idx0 = (x + 2) % 10;
|
|
2844
|
-
const B0 = B[idx0];
|
|
2845
|
-
const B1 = B[idx0 + 1];
|
|
2846
|
-
const Th = rotlH(B0, B1, 1) ^ B[idx1];
|
|
2847
|
-
const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
|
|
2848
|
-
for (let y = 0; y < 50; y += 10) {
|
|
2849
|
-
s[x + y] ^= Th;
|
|
2850
|
-
s[x + y + 1] ^= Tl;
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
let curH = s[2];
|
|
2854
|
-
let curL = s[3];
|
|
2855
|
-
for (let t = 0; t < 24; t++) {
|
|
2856
|
-
const shift = SHA3_ROTL[t];
|
|
2857
|
-
const Th = rotlH(curH, curL, shift);
|
|
2858
|
-
const Tl = rotlL(curH, curL, shift);
|
|
2859
|
-
const PI = SHA3_PI[t];
|
|
2860
|
-
curH = s[PI];
|
|
2861
|
-
curL = s[PI + 1];
|
|
2862
|
-
s[PI] = Th;
|
|
2863
|
-
s[PI + 1] = Tl;
|
|
2864
|
-
}
|
|
2865
|
-
for (let y = 0; y < 50; y += 10) {
|
|
2866
|
-
for (let x = 0; x < 10; x++)
|
|
2867
|
-
B[x] = s[y + x];
|
|
2868
|
-
for (let x = 0; x < 10; x++)
|
|
2869
|
-
s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
|
|
2870
|
-
}
|
|
2871
|
-
s[0] ^= SHA3_IOTA_H[round];
|
|
2872
|
-
s[1] ^= SHA3_IOTA_L[round];
|
|
2873
|
-
}
|
|
2874
|
-
clean(B);
|
|
2875
|
-
}
|
|
2876
|
-
class Keccak extends Hash {
|
|
2877
|
-
// NOTE: we accept arguments in bytes instead of bits here.
|
|
2878
|
-
constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
|
|
2879
|
-
super();
|
|
2880
|
-
this.pos = 0;
|
|
2881
|
-
this.posOut = 0;
|
|
2882
|
-
this.finished = false;
|
|
2883
|
-
this.destroyed = false;
|
|
2884
|
-
this.enableXOF = false;
|
|
2885
|
-
this.blockLen = blockLen;
|
|
2886
|
-
this.suffix = suffix;
|
|
2887
|
-
this.outputLen = outputLen;
|
|
2888
|
-
this.enableXOF = enableXOF;
|
|
2889
|
-
this.rounds = rounds;
|
|
2890
|
-
anumber(outputLen);
|
|
2891
|
-
if (!(0 < blockLen && blockLen < 200))
|
|
2892
|
-
throw new Error("only keccak-f1600 function is supported");
|
|
2893
|
-
this.state = new Uint8Array(200);
|
|
2894
|
-
this.state32 = u32(this.state);
|
|
2895
|
-
}
|
|
2896
|
-
clone() {
|
|
2897
|
-
return this._cloneInto();
|
|
2898
|
-
}
|
|
2899
|
-
keccak() {
|
|
2900
|
-
swap32IfBE(this.state32);
|
|
2901
|
-
keccakP(this.state32, this.rounds);
|
|
2902
|
-
swap32IfBE(this.state32);
|
|
2903
|
-
this.posOut = 0;
|
|
2904
|
-
this.pos = 0;
|
|
2905
|
-
}
|
|
2906
|
-
update(data) {
|
|
2907
|
-
aexists(this);
|
|
2908
|
-
data = toBytes$1(data);
|
|
2909
|
-
abytes(data);
|
|
2910
|
-
const { blockLen, state } = this;
|
|
2911
|
-
const len = data.length;
|
|
2912
|
-
for (let pos = 0; pos < len; ) {
|
|
2913
|
-
const take = Math.min(blockLen - this.pos, len - pos);
|
|
2914
|
-
for (let i = 0; i < take; i++)
|
|
2915
|
-
state[this.pos++] ^= data[pos++];
|
|
2916
|
-
if (this.pos === blockLen)
|
|
2917
|
-
this.keccak();
|
|
2918
|
-
}
|
|
2919
|
-
return this;
|
|
2920
|
-
}
|
|
2921
|
-
finish() {
|
|
2922
|
-
if (this.finished)
|
|
2923
|
-
return;
|
|
2924
|
-
this.finished = true;
|
|
2925
|
-
const { state, suffix, pos, blockLen } = this;
|
|
2926
|
-
state[pos] ^= suffix;
|
|
2927
|
-
if ((suffix & 128) !== 0 && pos === blockLen - 1)
|
|
2928
|
-
this.keccak();
|
|
2929
|
-
state[blockLen - 1] ^= 128;
|
|
2930
|
-
this.keccak();
|
|
2931
|
-
}
|
|
2932
|
-
writeInto(out) {
|
|
2933
|
-
aexists(this, false);
|
|
2934
|
-
abytes(out);
|
|
2935
|
-
this.finish();
|
|
2936
|
-
const bufferOut = this.state;
|
|
2937
|
-
const { blockLen } = this;
|
|
2938
|
-
for (let pos = 0, len = out.length; pos < len; ) {
|
|
2939
|
-
if (this.posOut >= blockLen)
|
|
2940
|
-
this.keccak();
|
|
2941
|
-
const take = Math.min(blockLen - this.posOut, len - pos);
|
|
2942
|
-
out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
|
|
2943
|
-
this.posOut += take;
|
|
2944
|
-
pos += take;
|
|
2945
|
-
}
|
|
2946
|
-
return out;
|
|
2947
|
-
}
|
|
2948
|
-
xofInto(out) {
|
|
2949
|
-
if (!this.enableXOF)
|
|
2950
|
-
throw new Error("XOF is not possible for this instance");
|
|
2951
|
-
return this.writeInto(out);
|
|
2952
|
-
}
|
|
2953
|
-
xof(bytes) {
|
|
2954
|
-
anumber(bytes);
|
|
2955
|
-
return this.xofInto(new Uint8Array(bytes));
|
|
2956
|
-
}
|
|
2957
|
-
digestInto(out) {
|
|
2958
|
-
aoutput(out, this);
|
|
2959
|
-
if (this.finished)
|
|
2960
|
-
throw new Error("digest() was already called");
|
|
2961
|
-
this.writeInto(out);
|
|
2962
|
-
this.destroy();
|
|
2963
|
-
return out;
|
|
2964
|
-
}
|
|
2965
|
-
digest() {
|
|
2966
|
-
return this.digestInto(new Uint8Array(this.outputLen));
|
|
2967
|
-
}
|
|
2968
|
-
destroy() {
|
|
2969
|
-
this.destroyed = true;
|
|
2970
|
-
clean(this.state);
|
|
2971
|
-
}
|
|
2972
|
-
_cloneInto(to) {
|
|
2973
|
-
const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
|
|
2974
|
-
to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
|
|
2975
|
-
to.state32.set(this.state32);
|
|
2976
|
-
to.pos = this.pos;
|
|
2977
|
-
to.posOut = this.posOut;
|
|
2978
|
-
to.finished = this.finished;
|
|
2979
|
-
to.rounds = rounds;
|
|
2980
|
-
to.suffix = suffix;
|
|
2981
|
-
to.outputLen = outputLen;
|
|
2982
|
-
to.enableXOF = enableXOF;
|
|
2983
|
-
to.destroyed = this.destroyed;
|
|
2984
|
-
return to;
|
|
2985
|
-
}
|
|
2986
|
-
}
|
|
2987
|
-
const gen = (suffix, blockLen, outputLen) => createHasher(() => new Keccak(blockLen, suffix, outputLen));
|
|
2988
|
-
const keccak_256 = /* @__PURE__ */ (() => gen(1, 136, 256 / 8))();
|
|
2989
|
-
function isHex(value, { strict = true } = {}) {
|
|
2990
|
-
if (!value)
|
|
2991
|
-
return false;
|
|
2992
|
-
if (typeof value !== "string")
|
|
2993
|
-
return false;
|
|
2994
|
-
return strict ? /^0x[0-9a-fA-F]*$/.test(value) : value.startsWith("0x");
|
|
2995
|
-
}
|
|
2996
|
-
const version = "2.45.1";
|
|
2997
|
-
let errorConfig = {
|
|
2998
|
-
getDocsUrl: ({ docsBaseUrl, docsPath = "", docsSlug }) => docsPath ? `${docsBaseUrl ?? "https://viem.sh"}${docsPath}${docsSlug ? `#${docsSlug}` : ""}` : void 0,
|
|
2999
|
-
version: `viem@${version}`
|
|
3000
|
-
};
|
|
3001
|
-
class BaseError extends Error {
|
|
3002
|
-
constructor(shortMessage, args = {}) {
|
|
3003
|
-
const details = (() => {
|
|
3004
|
-
if (args.cause instanceof BaseError)
|
|
3005
|
-
return args.cause.details;
|
|
3006
|
-
if (args.cause?.message)
|
|
3007
|
-
return args.cause.message;
|
|
3008
|
-
return args.details;
|
|
3009
|
-
})();
|
|
3010
|
-
const docsPath = (() => {
|
|
3011
|
-
if (args.cause instanceof BaseError)
|
|
3012
|
-
return args.cause.docsPath || args.docsPath;
|
|
3013
|
-
return args.docsPath;
|
|
3014
|
-
})();
|
|
3015
|
-
const docsUrl = errorConfig.getDocsUrl?.({ ...args, docsPath });
|
|
3016
|
-
const message = [
|
|
3017
|
-
shortMessage || "An error occurred.",
|
|
3018
|
-
"",
|
|
3019
|
-
...args.metaMessages ? [...args.metaMessages, ""] : [],
|
|
3020
|
-
...docsUrl ? [`Docs: ${docsUrl}`] : [],
|
|
3021
|
-
...details ? [`Details: ${details}`] : [],
|
|
3022
|
-
...errorConfig.version ? [`Version: ${errorConfig.version}`] : []
|
|
3023
|
-
].join("\n");
|
|
3024
|
-
super(message, args.cause ? { cause: args.cause } : void 0);
|
|
3025
|
-
Object.defineProperty(this, "details", {
|
|
3026
|
-
enumerable: true,
|
|
3027
|
-
configurable: true,
|
|
3028
|
-
writable: true,
|
|
3029
|
-
value: void 0
|
|
3030
|
-
});
|
|
3031
|
-
Object.defineProperty(this, "docsPath", {
|
|
3032
|
-
enumerable: true,
|
|
3033
|
-
configurable: true,
|
|
3034
|
-
writable: true,
|
|
3035
|
-
value: void 0
|
|
3036
|
-
});
|
|
3037
|
-
Object.defineProperty(this, "metaMessages", {
|
|
3038
|
-
enumerable: true,
|
|
3039
|
-
configurable: true,
|
|
3040
|
-
writable: true,
|
|
3041
|
-
value: void 0
|
|
3042
|
-
});
|
|
3043
|
-
Object.defineProperty(this, "shortMessage", {
|
|
3044
|
-
enumerable: true,
|
|
3045
|
-
configurable: true,
|
|
3046
|
-
writable: true,
|
|
3047
|
-
value: void 0
|
|
3048
|
-
});
|
|
3049
|
-
Object.defineProperty(this, "version", {
|
|
3050
|
-
enumerable: true,
|
|
3051
|
-
configurable: true,
|
|
3052
|
-
writable: true,
|
|
3053
|
-
value: void 0
|
|
3054
|
-
});
|
|
3055
|
-
Object.defineProperty(this, "name", {
|
|
3056
|
-
enumerable: true,
|
|
3057
|
-
configurable: true,
|
|
3058
|
-
writable: true,
|
|
3059
|
-
value: "BaseError"
|
|
3060
|
-
});
|
|
3061
|
-
this.details = details;
|
|
3062
|
-
this.docsPath = docsPath;
|
|
3063
|
-
this.metaMessages = args.metaMessages;
|
|
3064
|
-
this.name = args.name ?? this.name;
|
|
3065
|
-
this.shortMessage = shortMessage;
|
|
3066
|
-
this.version = version;
|
|
3067
|
-
}
|
|
3068
|
-
walk(fn) {
|
|
3069
|
-
return walk(this, fn);
|
|
3070
|
-
}
|
|
3071
|
-
}
|
|
3072
|
-
function walk(err, fn) {
|
|
3073
|
-
if (fn?.(err))
|
|
3074
|
-
return err;
|
|
3075
|
-
if (err && typeof err === "object" && "cause" in err && err.cause !== void 0)
|
|
3076
|
-
return walk(err.cause, fn);
|
|
3077
|
-
return fn ? null : err;
|
|
3078
|
-
}
|
|
3079
|
-
class SizeExceedsPaddingSizeError extends BaseError {
|
|
3080
|
-
constructor({ size: size2, targetSize, type }) {
|
|
3081
|
-
super(`${type.charAt(0).toUpperCase()}${type.slice(1).toLowerCase()} size (${size2}) exceeds padding size (${targetSize}).`, { name: "SizeExceedsPaddingSizeError" });
|
|
3082
|
-
}
|
|
3083
|
-
}
|
|
3084
|
-
function pad(hexOrBytes, { dir, size: size2 = 32 } = {}) {
|
|
3085
|
-
if (typeof hexOrBytes === "string")
|
|
3086
|
-
return padHex(hexOrBytes, { dir, size: size2 });
|
|
3087
|
-
return padBytes(hexOrBytes, { dir, size: size2 });
|
|
3088
|
-
}
|
|
3089
|
-
function padHex(hex_, { dir, size: size2 = 32 } = {}) {
|
|
3090
|
-
if (size2 === null)
|
|
3091
|
-
return hex_;
|
|
3092
|
-
const hex = hex_.replace("0x", "");
|
|
3093
|
-
if (hex.length > size2 * 2)
|
|
3094
|
-
throw new SizeExceedsPaddingSizeError({
|
|
3095
|
-
size: Math.ceil(hex.length / 2),
|
|
3096
|
-
targetSize: size2,
|
|
3097
|
-
type: "hex"
|
|
3098
|
-
});
|
|
3099
|
-
return `0x${hex[dir === "right" ? "padEnd" : "padStart"](size2 * 2, "0")}`;
|
|
3100
|
-
}
|
|
3101
|
-
function padBytes(bytes, { dir, size: size2 = 32 } = {}) {
|
|
3102
|
-
if (size2 === null)
|
|
3103
|
-
return bytes;
|
|
3104
|
-
if (bytes.length > size2)
|
|
3105
|
-
throw new SizeExceedsPaddingSizeError({
|
|
3106
|
-
size: bytes.length,
|
|
3107
|
-
targetSize: size2,
|
|
3108
|
-
type: "bytes"
|
|
3109
|
-
});
|
|
3110
|
-
const paddedBytes = new Uint8Array(size2);
|
|
3111
|
-
for (let i = 0; i < size2; i++) {
|
|
3112
|
-
const padEnd = dir === "right";
|
|
3113
|
-
paddedBytes[padEnd ? i : size2 - i - 1] = bytes[padEnd ? i : bytes.length - i - 1];
|
|
3114
|
-
}
|
|
3115
|
-
return paddedBytes;
|
|
3116
|
-
}
|
|
3117
|
-
class IntegerOutOfRangeError extends BaseError {
|
|
3118
|
-
constructor({ max, min, signed, size: size2, value }) {
|
|
3119
|
-
super(`Number "${value}" is not in safe ${size2 ? `${size2 * 8}-bit ${signed ? "signed" : "unsigned"} ` : ""}integer range ${max ? `(${min} to ${max})` : `(above ${min})`}`, { name: "IntegerOutOfRangeError" });
|
|
3120
|
-
}
|
|
3121
|
-
}
|
|
3122
|
-
class SizeOverflowError extends BaseError {
|
|
3123
|
-
constructor({ givenSize, maxSize }) {
|
|
3124
|
-
super(`Size cannot exceed ${maxSize} bytes. Given size: ${givenSize} bytes.`, { name: "SizeOverflowError" });
|
|
3125
|
-
}
|
|
3126
|
-
}
|
|
3127
|
-
function size(value) {
|
|
3128
|
-
if (isHex(value, { strict: false }))
|
|
3129
|
-
return Math.ceil((value.length - 2) / 2);
|
|
3130
|
-
return value.length;
|
|
3131
|
-
}
|
|
3132
|
-
function assertSize(hexOrBytes, { size: size$1 }) {
|
|
3133
|
-
if (size(hexOrBytes) > size$1)
|
|
3134
|
-
throw new SizeOverflowError({
|
|
3135
|
-
givenSize: size(hexOrBytes),
|
|
3136
|
-
maxSize: size$1
|
|
3137
|
-
});
|
|
3138
|
-
}
|
|
3139
|
-
function numberToHex(value_, opts = {}) {
|
|
3140
|
-
const { signed, size: size2 } = opts;
|
|
3141
|
-
const value = BigInt(value_);
|
|
3142
|
-
let maxValue;
|
|
3143
|
-
if (size2) {
|
|
3144
|
-
if (signed)
|
|
3145
|
-
maxValue = (1n << BigInt(size2) * 8n - 1n) - 1n;
|
|
3146
|
-
else
|
|
3147
|
-
maxValue = 2n ** (BigInt(size2) * 8n) - 1n;
|
|
3148
|
-
} else if (typeof value_ === "number") {
|
|
3149
|
-
maxValue = BigInt(Number.MAX_SAFE_INTEGER);
|
|
3150
|
-
}
|
|
3151
|
-
const minValue = typeof maxValue === "bigint" && signed ? -maxValue - 1n : 0;
|
|
3152
|
-
if (maxValue && value > maxValue || value < minValue) {
|
|
3153
|
-
const suffix = typeof value_ === "bigint" ? "n" : "";
|
|
3154
|
-
throw new IntegerOutOfRangeError({
|
|
3155
|
-
max: maxValue ? `${maxValue}${suffix}` : void 0,
|
|
3156
|
-
min: `${minValue}${suffix}`,
|
|
3157
|
-
signed,
|
|
3158
|
-
size: size2,
|
|
3159
|
-
value: `${value_}${suffix}`
|
|
3160
|
-
});
|
|
3161
|
-
}
|
|
3162
|
-
const hex = `0x${(signed && value < 0 ? (1n << BigInt(size2 * 8)) + BigInt(value) : value).toString(16)}`;
|
|
3163
|
-
if (size2)
|
|
3164
|
-
return pad(hex, { size: size2 });
|
|
3165
|
-
return hex;
|
|
3166
|
-
}
|
|
3167
|
-
const encoder = /* @__PURE__ */ new TextEncoder();
|
|
3168
|
-
function toBytes(value, opts = {}) {
|
|
3169
|
-
if (typeof value === "number" || typeof value === "bigint")
|
|
3170
|
-
return numberToBytes(value, opts);
|
|
3171
|
-
if (typeof value === "boolean")
|
|
3172
|
-
return boolToBytes(value, opts);
|
|
3173
|
-
if (isHex(value))
|
|
3174
|
-
return hexToBytes(value, opts);
|
|
3175
|
-
return stringToBytes(value, opts);
|
|
3176
|
-
}
|
|
3177
|
-
function boolToBytes(value, opts = {}) {
|
|
3178
|
-
const bytes = new Uint8Array(1);
|
|
3179
|
-
bytes[0] = Number(value);
|
|
3180
|
-
if (typeof opts.size === "number") {
|
|
3181
|
-
assertSize(bytes, { size: opts.size });
|
|
3182
|
-
return pad(bytes, { size: opts.size });
|
|
3183
|
-
}
|
|
3184
|
-
return bytes;
|
|
3185
|
-
}
|
|
3186
|
-
const charCodeMap = {
|
|
3187
|
-
zero: 48,
|
|
3188
|
-
nine: 57,
|
|
3189
|
-
A: 65,
|
|
3190
|
-
F: 70,
|
|
3191
|
-
a: 97,
|
|
3192
|
-
f: 102
|
|
3193
|
-
};
|
|
3194
|
-
function charCodeToBase16(char) {
|
|
3195
|
-
if (char >= charCodeMap.zero && char <= charCodeMap.nine)
|
|
3196
|
-
return char - charCodeMap.zero;
|
|
3197
|
-
if (char >= charCodeMap.A && char <= charCodeMap.F)
|
|
3198
|
-
return char - (charCodeMap.A - 10);
|
|
3199
|
-
if (char >= charCodeMap.a && char <= charCodeMap.f)
|
|
3200
|
-
return char - (charCodeMap.a - 10);
|
|
3201
|
-
return void 0;
|
|
3202
|
-
}
|
|
3203
|
-
function hexToBytes(hex_, opts = {}) {
|
|
3204
|
-
let hex = hex_;
|
|
3205
|
-
if (opts.size) {
|
|
3206
|
-
assertSize(hex, { size: opts.size });
|
|
3207
|
-
hex = pad(hex, { dir: "right", size: opts.size });
|
|
3208
|
-
}
|
|
3209
|
-
let hexString = hex.slice(2);
|
|
3210
|
-
if (hexString.length % 2)
|
|
3211
|
-
hexString = `0${hexString}`;
|
|
3212
|
-
const length = hexString.length / 2;
|
|
3213
|
-
const bytes = new Uint8Array(length);
|
|
3214
|
-
for (let index = 0, j = 0; index < length; index++) {
|
|
3215
|
-
const nibbleLeft = charCodeToBase16(hexString.charCodeAt(j++));
|
|
3216
|
-
const nibbleRight = charCodeToBase16(hexString.charCodeAt(j++));
|
|
3217
|
-
if (nibbleLeft === void 0 || nibbleRight === void 0) {
|
|
3218
|
-
throw new BaseError(`Invalid byte sequence ("${hexString[j - 2]}${hexString[j - 1]}" in "${hexString}").`);
|
|
3219
|
-
}
|
|
3220
|
-
bytes[index] = nibbleLeft * 16 + nibbleRight;
|
|
3221
|
-
}
|
|
3222
|
-
return bytes;
|
|
3223
|
-
}
|
|
3224
|
-
function numberToBytes(value, opts) {
|
|
3225
|
-
const hex = numberToHex(value, opts);
|
|
3226
|
-
return hexToBytes(hex);
|
|
3227
|
-
}
|
|
3228
|
-
function stringToBytes(value, opts = {}) {
|
|
3229
|
-
const bytes = encoder.encode(value);
|
|
3230
|
-
if (typeof opts.size === "number") {
|
|
3231
|
-
assertSize(bytes, { size: opts.size });
|
|
3232
|
-
return pad(bytes, { dir: "right", size: opts.size });
|
|
3233
|
-
}
|
|
3234
|
-
return bytes;
|
|
3235
|
-
}
|
|
3236
|
-
function keccak256(value, to_) {
|
|
3237
|
-
const bytes = keccak_256(isHex(value, { strict: false }) ? toBytes(value) : value);
|
|
3238
|
-
return bytes;
|
|
3239
|
-
}
|
|
3240
|
-
class LruMap extends Map {
|
|
3241
|
-
constructor(size2) {
|
|
3242
|
-
super();
|
|
3243
|
-
Object.defineProperty(this, "maxSize", {
|
|
3244
|
-
enumerable: true,
|
|
3245
|
-
configurable: true,
|
|
3246
|
-
writable: true,
|
|
3247
|
-
value: void 0
|
|
3248
|
-
});
|
|
3249
|
-
this.maxSize = size2;
|
|
3250
|
-
}
|
|
3251
|
-
get(key) {
|
|
3252
|
-
const value = super.get(key);
|
|
3253
|
-
if (super.has(key) && value !== void 0) {
|
|
3254
|
-
this.delete(key);
|
|
3255
|
-
super.set(key, value);
|
|
3256
|
-
}
|
|
3257
|
-
return value;
|
|
3258
|
-
}
|
|
3259
|
-
set(key, value) {
|
|
3260
|
-
super.set(key, value);
|
|
3261
|
-
if (this.maxSize && this.size > this.maxSize) {
|
|
3262
|
-
const firstKey = this.keys().next().value;
|
|
3263
|
-
if (firstKey)
|
|
3264
|
-
this.delete(firstKey);
|
|
3265
|
-
}
|
|
3266
|
-
return this;
|
|
3267
|
-
}
|
|
3268
|
-
}
|
|
3269
|
-
class InvalidAddressError extends BaseError {
|
|
3270
|
-
constructor({ address }) {
|
|
3271
|
-
super(`Address "${address}" is invalid.`, {
|
|
3272
|
-
metaMessages: [
|
|
3273
|
-
"- Address must be a hex value of 20 bytes (40 hex characters).",
|
|
3274
|
-
"- Address must match its checksum counterpart."
|
|
3275
|
-
],
|
|
3276
|
-
name: "InvalidAddressError"
|
|
3277
|
-
});
|
|
3278
|
-
}
|
|
3279
|
-
}
|
|
3280
|
-
const checksumAddressCache = /* @__PURE__ */ new LruMap(8192);
|
|
3281
|
-
function checksumAddress(address_, chainId) {
|
|
3282
|
-
if (checksumAddressCache.has(`${address_}.${chainId}`))
|
|
3283
|
-
return checksumAddressCache.get(`${address_}.${chainId}`);
|
|
3284
|
-
const hexAddress = address_.substring(2).toLowerCase();
|
|
3285
|
-
const hash = keccak256(stringToBytes(hexAddress));
|
|
3286
|
-
const address = hexAddress.split("");
|
|
3287
|
-
for (let i = 0; i < 40; i += 2) {
|
|
3288
|
-
if (hash[i >> 1] >> 4 >= 8 && address[i]) {
|
|
3289
|
-
address[i] = address[i].toUpperCase();
|
|
3290
|
-
}
|
|
3291
|
-
if ((hash[i >> 1] & 15) >= 8 && address[i + 1]) {
|
|
3292
|
-
address[i + 1] = address[i + 1].toUpperCase();
|
|
3293
|
-
}
|
|
3294
|
-
}
|
|
3295
|
-
const result = `0x${address.join("")}`;
|
|
3296
|
-
checksumAddressCache.set(`${address_}.${chainId}`, result);
|
|
3297
|
-
return result;
|
|
3298
|
-
}
|
|
3299
|
-
function getAddress(address, chainId) {
|
|
3300
|
-
if (!isAddress(address, { strict: false }))
|
|
3301
|
-
throw new InvalidAddressError({ address });
|
|
3302
|
-
return checksumAddress(address, chainId);
|
|
3303
|
-
}
|
|
3304
|
-
const addressRegex = /^0x[a-fA-F0-9]{40}$/;
|
|
3305
|
-
const isAddressCache = /* @__PURE__ */ new LruMap(8192);
|
|
3306
|
-
function isAddress(address, options) {
|
|
3307
|
-
const { strict = true } = options ?? {};
|
|
3308
|
-
const cacheKey = `${address}.${strict}`;
|
|
3309
|
-
if (isAddressCache.has(cacheKey))
|
|
3310
|
-
return isAddressCache.get(cacheKey);
|
|
3311
|
-
const result = (() => {
|
|
3312
|
-
if (!addressRegex.test(address))
|
|
3313
|
-
return false;
|
|
3314
|
-
if (address.toLowerCase() === address)
|
|
3315
|
-
return true;
|
|
3316
|
-
if (strict)
|
|
3317
|
-
return checksumAddress(address) === address;
|
|
3318
|
-
return true;
|
|
3319
|
-
})();
|
|
3320
|
-
isAddressCache.set(cacheKey, result);
|
|
3321
|
-
return result;
|
|
3322
|
-
}
|
|
3323
|
-
class SiweInvalidMessageFieldError extends BaseError {
|
|
3324
|
-
constructor(parameters) {
|
|
3325
|
-
const { docsPath, field, metaMessages } = parameters;
|
|
3326
|
-
super(`Invalid Sign-In with Ethereum message field "${field}".`, {
|
|
3327
|
-
docsPath,
|
|
3328
|
-
metaMessages,
|
|
3329
|
-
name: "SiweInvalidMessageFieldError"
|
|
3330
|
-
});
|
|
3331
|
-
}
|
|
3332
|
-
}
|
|
3333
|
-
function isUri(value) {
|
|
3334
|
-
if (/[^a-z0-9:/?#[\]@!$&'()*+,;=.\-_~%]/i.test(value))
|
|
3335
|
-
return false;
|
|
3336
|
-
if (/%[^0-9a-f]/i.test(value))
|
|
3337
|
-
return false;
|
|
3338
|
-
if (/%[0-9a-f](:?[^0-9a-f]|$)/i.test(value))
|
|
3339
|
-
return false;
|
|
3340
|
-
const splitted = splitUri(value);
|
|
3341
|
-
const scheme = splitted[1];
|
|
3342
|
-
const authority = splitted[2];
|
|
3343
|
-
const path = splitted[3];
|
|
3344
|
-
const query = splitted[4];
|
|
3345
|
-
const fragment = splitted[5];
|
|
3346
|
-
if (!(scheme?.length && path.length >= 0))
|
|
3347
|
-
return false;
|
|
3348
|
-
if (authority?.length) {
|
|
3349
|
-
if (!(path.length === 0 || /^\//.test(path)))
|
|
3350
|
-
return false;
|
|
3351
|
-
} else {
|
|
3352
|
-
if (/^\/\//.test(path))
|
|
3353
|
-
return false;
|
|
3354
|
-
}
|
|
3355
|
-
if (!/^[a-z][a-z0-9+\-.]*$/.test(scheme.toLowerCase()))
|
|
3356
|
-
return false;
|
|
3357
|
-
let out = "";
|
|
3358
|
-
out += `${scheme}:`;
|
|
3359
|
-
if (authority?.length)
|
|
3360
|
-
out += `//${authority}`;
|
|
3361
|
-
out += path;
|
|
3362
|
-
if (query?.length)
|
|
3363
|
-
out += `?${query}`;
|
|
3364
|
-
if (fragment?.length)
|
|
3365
|
-
out += `#${fragment}`;
|
|
3366
|
-
return out;
|
|
3367
|
-
}
|
|
3368
|
-
function splitUri(value) {
|
|
3369
|
-
return value.match(/(?:([^:/?#]+):)?(?:\/\/([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/);
|
|
3370
|
-
}
|
|
3371
|
-
function createSiweMessage(parameters) {
|
|
3372
|
-
const { chainId, domain, expirationTime, issuedAt = /* @__PURE__ */ new Date(), nonce, notBefore, requestId, resources, scheme, uri, version: version2 } = parameters;
|
|
3373
|
-
{
|
|
3374
|
-
if (chainId !== Math.floor(chainId))
|
|
3375
|
-
throw new SiweInvalidMessageFieldError({
|
|
3376
|
-
field: "chainId",
|
|
3377
|
-
metaMessages: [
|
|
3378
|
-
"- Chain ID must be a EIP-155 chain ID.",
|
|
3379
|
-
"- See https://eips.ethereum.org/EIPS/eip-155",
|
|
3380
|
-
"",
|
|
3381
|
-
`Provided value: ${chainId}`
|
|
3382
|
-
]
|
|
3383
|
-
});
|
|
3384
|
-
if (!(domainRegex.test(domain) || ipRegex.test(domain) || localhostRegex.test(domain)))
|
|
3385
|
-
throw new SiweInvalidMessageFieldError({
|
|
3386
|
-
field: "domain",
|
|
3387
|
-
metaMessages: [
|
|
3388
|
-
"- Domain must be an RFC 3986 authority.",
|
|
3389
|
-
"- See https://www.rfc-editor.org/rfc/rfc3986",
|
|
3390
|
-
"",
|
|
3391
|
-
`Provided value: ${domain}`
|
|
3392
|
-
]
|
|
3393
|
-
});
|
|
3394
|
-
if (!nonceRegex.test(nonce))
|
|
3395
|
-
throw new SiweInvalidMessageFieldError({
|
|
3396
|
-
field: "nonce",
|
|
3397
|
-
metaMessages: [
|
|
3398
|
-
"- Nonce must be at least 8 characters.",
|
|
3399
|
-
"- Nonce must be alphanumeric.",
|
|
3400
|
-
"",
|
|
3401
|
-
`Provided value: ${nonce}`
|
|
3402
|
-
]
|
|
3403
|
-
});
|
|
3404
|
-
if (!isUri(uri))
|
|
3405
|
-
throw new SiweInvalidMessageFieldError({
|
|
3406
|
-
field: "uri",
|
|
3407
|
-
metaMessages: [
|
|
3408
|
-
"- URI must be a RFC 3986 URI referring to the resource that is the subject of the signing.",
|
|
3409
|
-
"- See https://www.rfc-editor.org/rfc/rfc3986",
|
|
3410
|
-
"",
|
|
3411
|
-
`Provided value: ${uri}`
|
|
3412
|
-
]
|
|
3413
|
-
});
|
|
3414
|
-
if (version2 !== "1")
|
|
3415
|
-
throw new SiweInvalidMessageFieldError({
|
|
3416
|
-
field: "version",
|
|
3417
|
-
metaMessages: [
|
|
3418
|
-
"- Version must be '1'.",
|
|
3419
|
-
"",
|
|
3420
|
-
`Provided value: ${version2}`
|
|
3421
|
-
]
|
|
3422
|
-
});
|
|
3423
|
-
if (scheme && !schemeRegex.test(scheme))
|
|
3424
|
-
throw new SiweInvalidMessageFieldError({
|
|
3425
|
-
field: "scheme",
|
|
3426
|
-
metaMessages: [
|
|
3427
|
-
"- Scheme must be an RFC 3986 URI scheme.",
|
|
3428
|
-
"- See https://www.rfc-editor.org/rfc/rfc3986#section-3.1",
|
|
3429
|
-
"",
|
|
3430
|
-
`Provided value: ${scheme}`
|
|
3431
|
-
]
|
|
3432
|
-
});
|
|
3433
|
-
const statement2 = parameters.statement;
|
|
3434
|
-
if (statement2?.includes("\n"))
|
|
3435
|
-
throw new SiweInvalidMessageFieldError({
|
|
3436
|
-
field: "statement",
|
|
3437
|
-
metaMessages: [
|
|
3438
|
-
"- Statement must not include '\\n'.",
|
|
3439
|
-
"",
|
|
3440
|
-
`Provided value: ${statement2}`
|
|
3441
|
-
]
|
|
3442
|
-
});
|
|
3443
|
-
}
|
|
3444
|
-
const address = getAddress(parameters.address);
|
|
3445
|
-
const origin = (() => {
|
|
3446
|
-
if (scheme)
|
|
3447
|
-
return `${scheme}://${domain}`;
|
|
3448
|
-
return domain;
|
|
3449
|
-
})();
|
|
3450
|
-
const statement = (() => {
|
|
3451
|
-
if (!parameters.statement)
|
|
3452
|
-
return "";
|
|
3453
|
-
return `${parameters.statement}
|
|
3454
|
-
`;
|
|
3455
|
-
})();
|
|
3456
|
-
const prefix = `${origin} wants you to sign in with your Ethereum account:
|
|
3457
|
-
${address}
|
|
3458
|
-
|
|
3459
|
-
${statement}`;
|
|
3460
|
-
let suffix = `URI: ${uri}
|
|
3461
|
-
Version: ${version2}
|
|
3462
|
-
Chain ID: ${chainId}
|
|
3463
|
-
Nonce: ${nonce}
|
|
3464
|
-
Issued At: ${issuedAt.toISOString()}`;
|
|
3465
|
-
if (expirationTime)
|
|
3466
|
-
suffix += `
|
|
3467
|
-
Expiration Time: ${expirationTime.toISOString()}`;
|
|
3468
|
-
if (notBefore)
|
|
3469
|
-
suffix += `
|
|
3470
|
-
Not Before: ${notBefore.toISOString()}`;
|
|
3471
|
-
if (requestId)
|
|
3472
|
-
suffix += `
|
|
3473
|
-
Request ID: ${requestId}`;
|
|
3474
|
-
if (resources) {
|
|
3475
|
-
let content = "\nResources:";
|
|
3476
|
-
for (const resource of resources) {
|
|
3477
|
-
if (!isUri(resource))
|
|
3478
|
-
throw new SiweInvalidMessageFieldError({
|
|
3479
|
-
field: "resources",
|
|
3480
|
-
metaMessages: [
|
|
3481
|
-
"- Every resource must be a RFC 3986 URI.",
|
|
3482
|
-
"- See https://www.rfc-editor.org/rfc/rfc3986",
|
|
3483
|
-
"",
|
|
3484
|
-
`Provided value: ${resource}`
|
|
3485
|
-
]
|
|
3486
|
-
});
|
|
3487
|
-
content += `
|
|
3488
|
-
- ${resource}`;
|
|
3489
|
-
}
|
|
3490
|
-
suffix += content;
|
|
3491
|
-
}
|
|
3492
|
-
return `${prefix}
|
|
3493
|
-
${suffix}`;
|
|
3494
|
-
}
|
|
3495
|
-
const domainRegex = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}(:[0-9]{1,5})?$/;
|
|
3496
|
-
const ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(:[0-9]{1,5})?$/;
|
|
3497
|
-
const localhostRegex = /^localhost(:[0-9]{1,5})?$/;
|
|
3498
|
-
const nonceRegex = /^[a-zA-Z0-9]{8,}$/;
|
|
3499
|
-
const schemeRegex = /^([a-zA-Z][a-zA-Z0-9+-.]*)$/;
|
|
3500
2901
|
async function signInWithAgent(baseUrl, config) {
|
|
3501
|
-
if (!config.private_key) {
|
|
3502
|
-
throw new Error("No private key found in config. Run 'create_account' first.");
|
|
3503
|
-
}
|
|
3504
2902
|
if (!config.smart_account_address) {
|
|
3505
2903
|
throw new Error("No smart account address found in config. Run 'create_account' first.");
|
|
3506
2904
|
}
|
|
3507
2905
|
if (!config.chain) {
|
|
3508
2906
|
throw new Error("No chain found in config. Run 'create_account' first.");
|
|
3509
2907
|
}
|
|
2908
|
+
if (config.signer_type !== "secureEnclave" && !config.private_key) {
|
|
2909
|
+
throw new Error("No private key found in config. Run 'create_account' first.");
|
|
2910
|
+
}
|
|
3510
2911
|
const chain = resolveChain(config.chain);
|
|
3511
2912
|
const chainId = chain.id;
|
|
3512
2913
|
const walletAddress = config.smart_account_address;
|
|
3513
|
-
|
|
2914
|
+
let smartAccount;
|
|
2915
|
+
if (config.signer_type === "secureEnclave") {
|
|
2916
|
+
if (!config.secure_enclave) {
|
|
2917
|
+
throw new Error("Secure Enclave config missing. Run 'create_account --secure-enclave' first.");
|
|
2918
|
+
}
|
|
2919
|
+
smartAccount = await getSmartAccountFromSecureEnclave(
|
|
2920
|
+
config.secure_enclave.key_tag,
|
|
2921
|
+
config.secure_enclave.public_key_x,
|
|
2922
|
+
config.secure_enclave.public_key_y,
|
|
2923
|
+
config.secure_enclave.key_id,
|
|
2924
|
+
config.chain
|
|
2925
|
+
);
|
|
2926
|
+
} else {
|
|
2927
|
+
const result2 = await createSmartAccount(config.private_key, config.chain);
|
|
2928
|
+
smartAccount = result2.smartAccount;
|
|
2929
|
+
}
|
|
3514
2930
|
const url = new URL(baseUrl);
|
|
3515
2931
|
const domain = url.host;
|
|
3516
2932
|
console.log("fetching nonce...");
|
|
@@ -3623,24 +3039,67 @@ function parseScope(raw) {
|
|
|
3623
3039
|
}
|
|
3624
3040
|
const program = new Command();
|
|
3625
3041
|
program.name("openclaw").description("CoinFello CLI - MetaMask Smart Account interactions").version("1.0.0");
|
|
3626
|
-
program.command("create_account").description("Create a MetaMask smart account and save its address to local config").argument("<chain>", "Chain name (e.g. sepolia, mainnet, polygon, arbitrum)").
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3042
|
+
program.command("create_account").description("Create a MetaMask smart account and save its address to local config").argument("<chain>", "Chain name (e.g. sepolia, mainnet, polygon, arbitrum)").option(
|
|
3043
|
+
"--use-unsafe-private-key",
|
|
3044
|
+
"Use a raw private key instead of hardware-backed key (Secure Enclave / TPM 2.0)"
|
|
3045
|
+
).option("--delete-existing-private-key", "Delete the existing account and create a new one").action(
|
|
3046
|
+
async (chain, opts) => {
|
|
3047
|
+
try {
|
|
3048
|
+
const config = await loadConfig();
|
|
3049
|
+
if (config.smart_account_address) {
|
|
3050
|
+
if (!opts.deleteExistingPrivateKey) {
|
|
3051
|
+
console.error(
|
|
3052
|
+
`Error: An account already exists (${config.smart_account_address}). Use --delete-existing-private-key to overwrite it.`
|
|
3053
|
+
);
|
|
3054
|
+
process.exit(1);
|
|
3055
|
+
}
|
|
3056
|
+
console.warn("Deleting existing account and creating a new one...");
|
|
3057
|
+
}
|
|
3058
|
+
const useHardwareKey = !opts.useUnsafePrivateKey && isSecureEnclaveAvailable();
|
|
3059
|
+
if (useHardwareKey) {
|
|
3060
|
+
console.log(`Creating Secure Enclave-backed smart account on ${chain}...`);
|
|
3061
|
+
const { address, keyTag, publicKeyX, publicKeyY, keyId } = await createSmartAccountWithSecureEnclave(chain);
|
|
3062
|
+
const config2 = await loadConfig();
|
|
3063
|
+
config2.signer_type = "secureEnclave";
|
|
3064
|
+
config2.smart_account_address = address;
|
|
3065
|
+
config2.chain = chain;
|
|
3066
|
+
config2.secure_enclave = {
|
|
3067
|
+
key_tag: keyTag,
|
|
3068
|
+
public_key_x: publicKeyX,
|
|
3069
|
+
public_key_y: publicKeyY,
|
|
3070
|
+
key_id: keyId
|
|
3071
|
+
};
|
|
3072
|
+
delete config2.private_key;
|
|
3073
|
+
await saveConfig(config2);
|
|
3074
|
+
console.log("Secure Enclave smart account created successfully.");
|
|
3075
|
+
console.log(`Address: ${address}`);
|
|
3076
|
+
console.log(`Key tag: ${keyTag}`);
|
|
3077
|
+
console.log(`Config saved to: ${CONFIG_PATH}`);
|
|
3078
|
+
} else {
|
|
3079
|
+
if (!opts.useUnsafePrivateKey) {
|
|
3080
|
+
console.warn(
|
|
3081
|
+
"Warning: No hardware key support detected. Falling back to raw private key."
|
|
3082
|
+
);
|
|
3083
|
+
}
|
|
3084
|
+
console.log(`Creating smart account on ${chain}...`);
|
|
3085
|
+
const privateKey = generatePrivateKey();
|
|
3086
|
+
const { address } = await createSmartAccount(privateKey, chain);
|
|
3087
|
+
const config2 = await loadConfig();
|
|
3088
|
+
config2.private_key = privateKey;
|
|
3089
|
+
config2.signer_type = "privateKey";
|
|
3090
|
+
config2.smart_account_address = address;
|
|
3091
|
+
config2.chain = chain;
|
|
3092
|
+
await saveConfig(config2);
|
|
3093
|
+
console.log("Smart account created successfully.");
|
|
3094
|
+
console.log(`Address: ${address}`);
|
|
3095
|
+
console.log(`Config saved to: ${CONFIG_PATH}`);
|
|
3096
|
+
}
|
|
3097
|
+
} catch (err) {
|
|
3098
|
+
console.error(`Failed to create account: ${err.message}`);
|
|
3099
|
+
process.exit(1);
|
|
3100
|
+
}
|
|
3642
3101
|
}
|
|
3643
|
-
|
|
3102
|
+
);
|
|
3644
3103
|
program.command("get_account").description("Display the current smart account address from local config").action(async () => {
|
|
3645
3104
|
try {
|
|
3646
3105
|
const config = await loadConfig();
|
|
@@ -3687,10 +3146,6 @@ program.command("set_delegation").description("Store a signed delegation (JSON)
|
|
|
3687
3146
|
program.command("send_prompt").description("Send a prompt to CoinFello, creating a delegation if requested by the server").argument("<prompt>", "The prompt to send").action(async (prompt) => {
|
|
3688
3147
|
try {
|
|
3689
3148
|
const config = await loadConfig();
|
|
3690
|
-
if (!config.private_key) {
|
|
3691
|
-
console.error("Error: No private key found in config. Run 'create_account' first.");
|
|
3692
|
-
process.exit(1);
|
|
3693
|
-
}
|
|
3694
3149
|
if (!config.smart_account_address) {
|
|
3695
3150
|
console.error("Error: No smart account found. Run 'create_account' first.");
|
|
3696
3151
|
process.exit(1);
|
|
@@ -3699,6 +3154,10 @@ program.command("send_prompt").description("Send a prompt to CoinFello, creating
|
|
|
3699
3154
|
console.error("Error: No chain found in config. Run 'create_account' first.");
|
|
3700
3155
|
process.exit(1);
|
|
3701
3156
|
}
|
|
3157
|
+
if (config.signer_type !== "secureEnclave" && !config.private_key) {
|
|
3158
|
+
console.error("Error: No private key found in config. Run 'create_account' first.");
|
|
3159
|
+
process.exit(1);
|
|
3160
|
+
}
|
|
3702
3161
|
if (config.session_token) {
|
|
3703
3162
|
await loadSessionToken(config.session_token, BASE_URL_V1);
|
|
3704
3163
|
}
|
|
@@ -3728,7 +3187,22 @@ program.command("send_prompt").description("Send a prompt to CoinFello, creating
|
|
|
3728
3187
|
console.log("Fetching CoinFello delegate address...");
|
|
3729
3188
|
const delegateAddress = await getCoinFelloAddress();
|
|
3730
3189
|
console.log("Loading smart account...");
|
|
3731
|
-
|
|
3190
|
+
let smartAccount;
|
|
3191
|
+
if (config.signer_type === "secureEnclave") {
|
|
3192
|
+
if (!config.secure_enclave) {
|
|
3193
|
+
console.error("Error: Secure Enclave config missing. Run 'create_account' first.");
|
|
3194
|
+
process.exit(1);
|
|
3195
|
+
}
|
|
3196
|
+
smartAccount = await getSmartAccountFromSecureEnclave(
|
|
3197
|
+
config.secure_enclave.key_tag,
|
|
3198
|
+
config.secure_enclave.public_key_x,
|
|
3199
|
+
config.secure_enclave.public_key_y,
|
|
3200
|
+
config.secure_enclave.key_id,
|
|
3201
|
+
args.chainId
|
|
3202
|
+
);
|
|
3203
|
+
} else {
|
|
3204
|
+
smartAccount = await getSmartAccount(config.private_key, args.chainId);
|
|
3205
|
+
}
|
|
3732
3206
|
const scope = parseScope(args.scope);
|
|
3733
3207
|
console.log("Creating subdelegation...");
|
|
3734
3208
|
const subdelegation = createSubdelegation({
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleIdentifier</key>
|
|
6
|
+
<string>com.coinfello.agent-cli</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>secure-enclave-signer</string>
|
|
9
|
+
<key>CFBundleName</key>
|
|
10
|
+
<string>secure-enclave-signer</string>
|
|
11
|
+
<key>CFBundleVersion</key>
|
|
12
|
+
<string>1</string>
|
|
13
|
+
<key>CFBundleShortVersionString</key>
|
|
14
|
+
<string>1.0</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>APPL</string>
|
|
17
|
+
<key>LSMinimumSystemVersion</key>
|
|
18
|
+
<string>13.0</string>
|
|
19
|
+
</dict>
|
|
20
|
+
</plist>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>files</key>
|
|
6
|
+
<dict/>
|
|
7
|
+
<key>files2</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>embedded.provisionprofile</key>
|
|
10
|
+
<dict>
|
|
11
|
+
<key>hash2</key>
|
|
12
|
+
<data>
|
|
13
|
+
oD3tt3NC4z7ziSt9JgVtw936hY3YVeP6PO2HsBqNEQI=
|
|
14
|
+
</data>
|
|
15
|
+
</dict>
|
|
16
|
+
</dict>
|
|
17
|
+
<key>rules</key>
|
|
18
|
+
<dict>
|
|
19
|
+
<key>^Resources/</key>
|
|
20
|
+
<true/>
|
|
21
|
+
<key>^Resources/.*\.lproj/</key>
|
|
22
|
+
<dict>
|
|
23
|
+
<key>optional</key>
|
|
24
|
+
<true/>
|
|
25
|
+
<key>weight</key>
|
|
26
|
+
<real>1000</real>
|
|
27
|
+
</dict>
|
|
28
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
29
|
+
<dict>
|
|
30
|
+
<key>omit</key>
|
|
31
|
+
<true/>
|
|
32
|
+
<key>weight</key>
|
|
33
|
+
<real>1100</real>
|
|
34
|
+
</dict>
|
|
35
|
+
<key>^Resources/Base\.lproj/</key>
|
|
36
|
+
<dict>
|
|
37
|
+
<key>weight</key>
|
|
38
|
+
<real>1010</real>
|
|
39
|
+
</dict>
|
|
40
|
+
<key>^version.plist$</key>
|
|
41
|
+
<true/>
|
|
42
|
+
</dict>
|
|
43
|
+
<key>rules2</key>
|
|
44
|
+
<dict>
|
|
45
|
+
<key>.*\.dSYM($|/)</key>
|
|
46
|
+
<dict>
|
|
47
|
+
<key>weight</key>
|
|
48
|
+
<real>11</real>
|
|
49
|
+
</dict>
|
|
50
|
+
<key>^(.*/)?\.DS_Store$</key>
|
|
51
|
+
<dict>
|
|
52
|
+
<key>omit</key>
|
|
53
|
+
<true/>
|
|
54
|
+
<key>weight</key>
|
|
55
|
+
<real>2000</real>
|
|
56
|
+
</dict>
|
|
57
|
+
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
|
58
|
+
<dict>
|
|
59
|
+
<key>nested</key>
|
|
60
|
+
<true/>
|
|
61
|
+
<key>weight</key>
|
|
62
|
+
<real>10</real>
|
|
63
|
+
</dict>
|
|
64
|
+
<key>^.*</key>
|
|
65
|
+
<true/>
|
|
66
|
+
<key>^Info\.plist$</key>
|
|
67
|
+
<dict>
|
|
68
|
+
<key>omit</key>
|
|
69
|
+
<true/>
|
|
70
|
+
<key>weight</key>
|
|
71
|
+
<real>20</real>
|
|
72
|
+
</dict>
|
|
73
|
+
<key>^PkgInfo$</key>
|
|
74
|
+
<dict>
|
|
75
|
+
<key>omit</key>
|
|
76
|
+
<true/>
|
|
77
|
+
<key>weight</key>
|
|
78
|
+
<real>20</real>
|
|
79
|
+
</dict>
|
|
80
|
+
<key>^Resources/</key>
|
|
81
|
+
<dict>
|
|
82
|
+
<key>weight</key>
|
|
83
|
+
<real>20</real>
|
|
84
|
+
</dict>
|
|
85
|
+
<key>^Resources/.*\.lproj/</key>
|
|
86
|
+
<dict>
|
|
87
|
+
<key>optional</key>
|
|
88
|
+
<true/>
|
|
89
|
+
<key>weight</key>
|
|
90
|
+
<real>1000</real>
|
|
91
|
+
</dict>
|
|
92
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
|
93
|
+
<dict>
|
|
94
|
+
<key>omit</key>
|
|
95
|
+
<true/>
|
|
96
|
+
<key>weight</key>
|
|
97
|
+
<real>1100</real>
|
|
98
|
+
</dict>
|
|
99
|
+
<key>^Resources/Base\.lproj/</key>
|
|
100
|
+
<dict>
|
|
101
|
+
<key>weight</key>
|
|
102
|
+
<real>1010</real>
|
|
103
|
+
</dict>
|
|
104
|
+
<key>^[^/]+$</key>
|
|
105
|
+
<dict>
|
|
106
|
+
<key>nested</key>
|
|
107
|
+
<true/>
|
|
108
|
+
<key>weight</key>
|
|
109
|
+
<real>10</real>
|
|
110
|
+
</dict>
|
|
111
|
+
<key>^embedded\.provisionprofile$</key>
|
|
112
|
+
<dict>
|
|
113
|
+
<key>weight</key>
|
|
114
|
+
<real>20</real>
|
|
115
|
+
</dict>
|
|
116
|
+
<key>^version\.plist$</key>
|
|
117
|
+
<dict>
|
|
118
|
+
<key>weight</key>
|
|
119
|
+
<real>20</real>
|
|
120
|
+
</dict>
|
|
121
|
+
</dict>
|
|
122
|
+
</dict>
|
|
123
|
+
</plist>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coinfello/agent-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"viem": "^2.45.1"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
+
"@noble/curves": "^2.0.1",
|
|
27
|
+
"@noble/hashes": "^2.0.1",
|
|
26
28
|
"@types/node": "^25.2.1",
|
|
27
29
|
"dotenv": "^17.3.1",
|
|
28
30
|
"eslint": "^10.0.0",
|
|
@@ -34,8 +36,9 @@
|
|
|
34
36
|
"vitest": "^4.0.18"
|
|
35
37
|
},
|
|
36
38
|
"scripts": {
|
|
37
|
-
"build": "vite build",
|
|
39
|
+
"build": "vite build && pnpm run build:swift",
|
|
38
40
|
"build:swift": "bash swift/SecureEnclaveSigner/build.sh",
|
|
41
|
+
"build:signed": "vite build && SIGN_IDENTITY=\"Apple Development: Brett Cleary (WF45KCA35Q)\" PROVISIONING_PROFILE=\"$HOME/Agent_Cli_Dev_Profile_1.provisionprofile\" pnpm run build:swift",
|
|
39
42
|
"codecheck": "tsc --noEmit",
|
|
40
43
|
"lint": "eslint src",
|
|
41
44
|
"prettier-fix": "prettier --write src coinfello",
|