@absol-labs/agent 0.7.3 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -4
- package/dist/discovery/registry.d.ts +110 -305
- package/dist/discovery/registry.d.ts.map +1 -1
- package/dist/discovery/registry.js +141 -318
- package/dist/discovery/registry.js.map +1 -1
- package/dist/frameworks/agentkit.d.ts.map +1 -1
- package/dist/frameworks/agentkit.js +23 -6
- package/dist/frameworks/agentkit.js.map +1 -1
- package/dist/gateway/caller-auth-gateway.d.ts +103 -2
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +176 -19
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +12 -0
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +45 -1
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/wallet/autonomous-wallet-store.d.ts +123 -0
- package/dist/wallet/autonomous-wallet-store.d.ts.map +1 -0
- package/dist/wallet/autonomous-wallet-store.js +318 -0
- package/dist/wallet/autonomous-wallet-store.js.map +1 -0
- package/dist/wallet/autonomous-wallet.d.ts +14 -39
- package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet.js +12 -145
- package/dist/wallet/autonomous-wallet.js.map +1 -1
- package/dist/wallet/cdp-sdk.d.ts +23 -0
- package/dist/wallet/cdp-sdk.d.ts.map +1 -0
- package/dist/wallet/cdp-sdk.js +27 -0
- package/dist/wallet/cdp-sdk.js.map +1 -0
- package/dist/wallet/encrypted-file-credential-store.d.ts +41 -0
- package/dist/wallet/encrypted-file-credential-store.d.ts.map +1 -0
- package/dist/wallet/encrypted-file-credential-store.js +221 -0
- package/dist/wallet/encrypted-file-credential-store.js.map +1 -0
- package/dist/wallet/provider.d.ts +1 -1
- package/dist/wallet/provider.d.ts.map +1 -1
- package/dist/wallet/provider.js +8 -3
- package/dist/wallet/provider.js.map +1 -1
- package/dist/wallet/secret-service-probe.d.ts +56 -0
- package/dist/wallet/secret-service-probe.d.ts.map +1 -0
- package/dist/wallet/secret-service-probe.js +407 -0
- package/dist/wallet/secret-service-probe.js.map +1 -0
- package/dist/zktls/reclaim-js-sdk.d.ts +24 -0
- package/dist/zktls/reclaim-js-sdk.d.ts.map +1 -0
- package/dist/zktls/reclaim-js-sdk.js +29 -0
- package/dist/zktls/reclaim-js-sdk.js.map +1 -0
- package/dist/zktls/reclaim.d.ts +14 -2
- package/dist/zktls/reclaim.d.ts.map +1 -1
- package/dist/zktls/reclaim.js +29 -6
- package/dist/zktls/reclaim.js.map +1 -1
- package/dist/zktls/t2-delivery-proof.d.ts +8 -1
- package/dist/zktls/t2-delivery-proof.d.ts.map +1 -1
- package/dist/zktls/t2-delivery-proof.js +22 -6
- package/dist/zktls/t2-delivery-proof.js.map +1 -1
- package/docs/agent-layer.md +150 -0
- package/docs/autonomous-privy-wallet.md +133 -0
- package/docs/crewai.md +70 -0
- package/docs/eliza.md +109 -0
- package/docs/langchain.md +63 -0
- package/docs/mcp-hosted.md +137 -0
- package/docs/privy-embedded-wallet.md +102 -0
- package/docs/quickstart.md +370 -0
- package/docs/threat-model.md +160 -0
- package/package.json +19 -6
- package/src/discovery/registry.ts +242 -414
- package/src/frameworks/agentkit.ts +24 -5
- package/src/gateway/caller-auth-gateway.ts +281 -15
- package/src/gateway/http-server.ts +64 -0
- package/src/index.ts +24 -0
- package/src/wallet/autonomous-wallet-store.ts +487 -0
- package/src/wallet/autonomous-wallet.ts +57 -224
- package/src/wallet/cdp-sdk.ts +33 -0
- package/src/wallet/encrypted-file-credential-store.ts +341 -0
- package/src/wallet/provider.ts +16 -9
- package/src/wallet/secret-service-probe.ts +487 -0
- package/src/zktls/reclaim-js-sdk.ts +50 -0
- package/src/zktls/reclaim.ts +57 -23
- package/src/zktls/t2-delivery-proof.ts +28 -10
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCipheriv,
|
|
3
|
+
createDecipheriv,
|
|
4
|
+
createHash,
|
|
5
|
+
randomBytes,
|
|
6
|
+
scrypt,
|
|
7
|
+
} from "node:crypto";
|
|
8
|
+
import {
|
|
9
|
+
chmod,
|
|
10
|
+
mkdir,
|
|
11
|
+
readFile,
|
|
12
|
+
rename,
|
|
13
|
+
rm,
|
|
14
|
+
writeFile,
|
|
15
|
+
} from "node:fs/promises";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { promisify } from "node:util";
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
AutonomousWalletError,
|
|
22
|
+
isRecord,
|
|
23
|
+
validateStoredRecord,
|
|
24
|
+
type AutonomousWalletCredentialStore,
|
|
25
|
+
type AutonomousWalletRecord,
|
|
26
|
+
type CredentialStoreDurabilityReport,
|
|
27
|
+
} from "./autonomous-wallet-store.js";
|
|
28
|
+
|
|
29
|
+
const scryptAsync = promisify(scrypt) as (
|
|
30
|
+
secret: string | Buffer,
|
|
31
|
+
salt: Buffer,
|
|
32
|
+
keylen: number,
|
|
33
|
+
options: { readonly N: number; readonly r: number; readonly p: number },
|
|
34
|
+
) => Promise<Buffer>;
|
|
35
|
+
|
|
36
|
+
/** Environment variable holding the externally-managed encryption secret. */
|
|
37
|
+
export const METRIK_WALLET_ENCRYPTION_KEY_ENV = "METRIK_WALLET_ENCRYPTION_KEY";
|
|
38
|
+
/** Environment variable overriding where encrypted wallet files are written. */
|
|
39
|
+
export const METRIK_WALLET_STORE_DIR_ENV = "METRIK_WALLET_STORE_DIR";
|
|
40
|
+
|
|
41
|
+
const ENVELOPE_VERSION = 1;
|
|
42
|
+
const CIPHER = "aes-256-gcm";
|
|
43
|
+
const KEY_LENGTH = 32;
|
|
44
|
+
const IV_LENGTH = 12;
|
|
45
|
+
const SALT_LENGTH = 16;
|
|
46
|
+
const SCRYPT_PARAMETERS = Object.freeze({ N: 16_384, r: 8, p: 1 });
|
|
47
|
+
const MINIMUM_SECRET_LENGTH = 16;
|
|
48
|
+
const FILE_MODE = 0o600;
|
|
49
|
+
const DIRECTORY_MODE = 0o700;
|
|
50
|
+
|
|
51
|
+
export interface EncryptedFileCredentialStoreOptions {
|
|
52
|
+
/**
|
|
53
|
+
* Directory holding one encrypted file per store key. Defaults to
|
|
54
|
+
* `$METRIK_WALLET_STORE_DIR`, else `~/.metrik/autonomous-wallets`.
|
|
55
|
+
*/
|
|
56
|
+
readonly directory?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Encryption secret. Defaults to `$METRIK_WALLET_ENCRYPTION_KEY`. Supply it
|
|
59
|
+
* from a platform secret manager (AWS/GCP Secrets Manager, Vault, a
|
|
60
|
+
* Docker/Kubernetes secret) — never commit it next to the encrypted file.
|
|
61
|
+
*/
|
|
62
|
+
readonly encryptionKey?: string;
|
|
63
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface Envelope {
|
|
67
|
+
readonly v: number;
|
|
68
|
+
readonly cipher: string;
|
|
69
|
+
readonly kdf: {
|
|
70
|
+
readonly name: "scrypt";
|
|
71
|
+
readonly N: number;
|
|
72
|
+
readonly r: number;
|
|
73
|
+
readonly p: number;
|
|
74
|
+
readonly saltBase64: string;
|
|
75
|
+
};
|
|
76
|
+
readonly ivBase64: string;
|
|
77
|
+
readonly tagBase64: string;
|
|
78
|
+
readonly ciphertextBase64: string;
|
|
79
|
+
readonly keyDigest: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Durable credential store for headless hosts (servers, containers, VMs, CI
|
|
84
|
+
* runners) that have no OS credential manager.
|
|
85
|
+
*
|
|
86
|
+
* The wallet record is encrypted at rest with AES-256-GCM under a key derived
|
|
87
|
+
* with scrypt from an externally-supplied secret and a fresh random salt per
|
|
88
|
+
* write; the IV is fresh per write and the ciphertext is authenticated against
|
|
89
|
+
* the store key. The secret is never written to disk, so the "no plaintext key
|
|
90
|
+
* on disk" guarantee still holds — but unlike the Linux kernel keyring the file
|
|
91
|
+
* survives a reboot, which is what a fund-controlling key requires.
|
|
92
|
+
*/
|
|
93
|
+
export class EncryptedFileCredentialStore implements AutonomousWalletCredentialStore {
|
|
94
|
+
private readonly directory: string;
|
|
95
|
+
private readonly secret: string;
|
|
96
|
+
|
|
97
|
+
constructor(options: EncryptedFileCredentialStoreOptions = {}) {
|
|
98
|
+
const env = options.env ?? process.env;
|
|
99
|
+
const secret =
|
|
100
|
+
options.encryptionKey ?? env[METRIK_WALLET_ENCRYPTION_KEY_ENV];
|
|
101
|
+
if (typeof secret !== "string" || secret.trim() === "") {
|
|
102
|
+
throw new AutonomousWalletError(
|
|
103
|
+
"invalid-config",
|
|
104
|
+
`EncryptedFileCredentialStore requires an encryption secret: set ${METRIK_WALLET_ENCRYPTION_KEY_ENV} (from your secret manager) or pass encryptionKey. Without it the stored wallet key cannot be decrypted.`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (secret.trim().length < MINIMUM_SECRET_LENGTH) {
|
|
108
|
+
throw new AutonomousWalletError(
|
|
109
|
+
"invalid-config",
|
|
110
|
+
`the autonomous wallet encryption secret must be at least ${MINIMUM_SECRET_LENGTH} characters; generate one with "openssl rand -base64 32"`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
this.secret = secret.trim();
|
|
114
|
+
this.directory =
|
|
115
|
+
options.directory ??
|
|
116
|
+
env[METRIK_WALLET_STORE_DIR_ENV] ??
|
|
117
|
+
join(homedir(), ".metrik", "autonomous-wallets");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async load(key: string): Promise<AutonomousWalletRecord | null> {
|
|
121
|
+
const path = this.pathFor(key);
|
|
122
|
+
let raw: string;
|
|
123
|
+
try {
|
|
124
|
+
raw = await readFile(path, "utf8");
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (isNotFound(error)) return null;
|
|
127
|
+
throw new AutonomousWalletError(
|
|
128
|
+
"store-failure",
|
|
129
|
+
`encrypted wallet file at ${path} could not be read`,
|
|
130
|
+
{ cause: error },
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
const envelope = parseEnvelope(raw, path);
|
|
134
|
+
const digest = digestOf(key);
|
|
135
|
+
if (envelope.keyDigest !== digest) {
|
|
136
|
+
throw new AutonomousWalletError(
|
|
137
|
+
"store-failure",
|
|
138
|
+
`encrypted wallet file at ${path} belongs to a different store key`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const derived = await scryptAsync(
|
|
142
|
+
this.secret,
|
|
143
|
+
Buffer.from(envelope.kdf.saltBase64, "base64"),
|
|
144
|
+
KEY_LENGTH,
|
|
145
|
+
{ N: envelope.kdf.N, r: envelope.kdf.r, p: envelope.kdf.p },
|
|
146
|
+
);
|
|
147
|
+
let plaintext: string;
|
|
148
|
+
try {
|
|
149
|
+
const decipher = createDecipheriv(
|
|
150
|
+
CIPHER,
|
|
151
|
+
derived,
|
|
152
|
+
Buffer.from(envelope.ivBase64, "base64"),
|
|
153
|
+
);
|
|
154
|
+
decipher.setAAD(additionalData(digest));
|
|
155
|
+
decipher.setAuthTag(Buffer.from(envelope.tagBase64, "base64"));
|
|
156
|
+
plaintext = Buffer.concat([
|
|
157
|
+
decipher.update(Buffer.from(envelope.ciphertextBase64, "base64")),
|
|
158
|
+
decipher.final(),
|
|
159
|
+
]).toString("utf8");
|
|
160
|
+
} catch (error) {
|
|
161
|
+
throw new AutonomousWalletError(
|
|
162
|
+
"store-failure",
|
|
163
|
+
`encrypted wallet file at ${path} failed authenticated decryption: the ${METRIK_WALLET_ENCRYPTION_KEY_ENV} secret does not match the one used to write it, or the file was modified. Restore the original secret; the wallet key cannot be recovered without it.`,
|
|
164
|
+
{ cause: error },
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
return validateStoredRecord(JSON.parse(plaintext));
|
|
169
|
+
} catch (error) {
|
|
170
|
+
if (error instanceof AutonomousWalletError) throw error;
|
|
171
|
+
throw new AutonomousWalletError(
|
|
172
|
+
"store-failure",
|
|
173
|
+
`encrypted wallet file at ${path} contains invalid wallet data`,
|
|
174
|
+
{ cause: error },
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async save(key: string, record: AutonomousWalletRecord): Promise<void> {
|
|
180
|
+
const path = this.pathFor(key);
|
|
181
|
+
const digest = digestOf(key);
|
|
182
|
+
try {
|
|
183
|
+
await mkdir(this.directory, { recursive: true, mode: DIRECTORY_MODE });
|
|
184
|
+
const salt = randomBytes(SALT_LENGTH);
|
|
185
|
+
const iv = randomBytes(IV_LENGTH);
|
|
186
|
+
const derived = await scryptAsync(
|
|
187
|
+
this.secret,
|
|
188
|
+
salt,
|
|
189
|
+
KEY_LENGTH,
|
|
190
|
+
SCRYPT_PARAMETERS,
|
|
191
|
+
);
|
|
192
|
+
const cipher = createCipheriv(CIPHER, derived, iv);
|
|
193
|
+
cipher.setAAD(additionalData(digest));
|
|
194
|
+
const ciphertext = Buffer.concat([
|
|
195
|
+
cipher.update(Buffer.from(JSON.stringify(record), "utf8")),
|
|
196
|
+
cipher.final(),
|
|
197
|
+
]);
|
|
198
|
+
const envelope: Envelope = {
|
|
199
|
+
v: ENVELOPE_VERSION,
|
|
200
|
+
cipher: CIPHER,
|
|
201
|
+
kdf: {
|
|
202
|
+
name: "scrypt",
|
|
203
|
+
...SCRYPT_PARAMETERS,
|
|
204
|
+
saltBase64: salt.toString("base64"),
|
|
205
|
+
},
|
|
206
|
+
ivBase64: iv.toString("base64"),
|
|
207
|
+
tagBase64: cipher.getAuthTag().toString("base64"),
|
|
208
|
+
ciphertextBase64: ciphertext.toString("base64"),
|
|
209
|
+
keyDigest: digest,
|
|
210
|
+
};
|
|
211
|
+
const temporaryPath = `${path}.${randomBytes(6).toString("hex")}.tmp`;
|
|
212
|
+
await writeFile(temporaryPath, JSON.stringify(envelope), {
|
|
213
|
+
mode: FILE_MODE,
|
|
214
|
+
});
|
|
215
|
+
// writeFile's mode is subject to the process umask; force 0600.
|
|
216
|
+
await chmod(temporaryPath, FILE_MODE);
|
|
217
|
+
await rename(temporaryPath, path);
|
|
218
|
+
await chmod(path, FILE_MODE);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
throw new AutonomousWalletError(
|
|
221
|
+
"store-failure",
|
|
222
|
+
`encrypted wallet file at ${path} could not be written`,
|
|
223
|
+
{ cause: error },
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async probeDurability(): Promise<CredentialStoreDurabilityReport> {
|
|
229
|
+
const probePath = join(
|
|
230
|
+
this.directory,
|
|
231
|
+
`.durability-probe-${randomBytes(6).toString("hex")}`,
|
|
232
|
+
);
|
|
233
|
+
try {
|
|
234
|
+
await mkdir(this.directory, { recursive: true, mode: DIRECTORY_MODE });
|
|
235
|
+
await writeFile(probePath, "metrik-durability-probe", {
|
|
236
|
+
mode: FILE_MODE,
|
|
237
|
+
});
|
|
238
|
+
const observed = await readFile(probePath, "utf8");
|
|
239
|
+
if (observed !== "metrik-durability-probe") {
|
|
240
|
+
return {
|
|
241
|
+
durability: "volatile",
|
|
242
|
+
backend: "encrypted-file",
|
|
243
|
+
detail: `the probe file at ${this.directory} did not read back with the value written`,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
durability: "durable",
|
|
248
|
+
backend: "encrypted-file",
|
|
249
|
+
detail: `AES-256-GCM encrypted files under ${this.directory} persist across reboots; the key is derived from ${METRIK_WALLET_ENCRYPTION_KEY_ENV}, which you must keep in your secret manager`,
|
|
250
|
+
};
|
|
251
|
+
} catch (error) {
|
|
252
|
+
return {
|
|
253
|
+
durability: "volatile",
|
|
254
|
+
backend: "encrypted-file",
|
|
255
|
+
detail: `${this.directory} is not writable: ${error instanceof Error ? error.message : String(error)}`,
|
|
256
|
+
};
|
|
257
|
+
} finally {
|
|
258
|
+
await rm(probePath, { force: true }).catch(() => undefined);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Absolute path of the encrypted file backing `key`. */
|
|
263
|
+
pathFor(key: string): string {
|
|
264
|
+
if (key.trim() === "") {
|
|
265
|
+
throw new AutonomousWalletError(
|
|
266
|
+
"invalid-config",
|
|
267
|
+
"secure store key is required",
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
// Hash the key so an arbitrary store key can never traverse the directory.
|
|
271
|
+
return join(this.directory, `${digestOf(key)}.metrik-wallet.json`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function additionalData(keyDigest: string): Buffer {
|
|
276
|
+
return Buffer.from(
|
|
277
|
+
`metrik-autonomous-wallet-v${ENVELOPE_VERSION}:${keyDigest}`,
|
|
278
|
+
"utf8",
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function digestOf(key: string): string {
|
|
283
|
+
return createHash("sha256").update(key, "utf8").digest("hex");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function isNotFound(error: unknown): boolean {
|
|
287
|
+
return (
|
|
288
|
+
typeof error === "object" &&
|
|
289
|
+
error !== null &&
|
|
290
|
+
(error as { readonly code?: unknown }).code === "ENOENT"
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function parseEnvelope(raw: string, path: string): Envelope {
|
|
295
|
+
let parsed: unknown;
|
|
296
|
+
try {
|
|
297
|
+
parsed = JSON.parse(raw);
|
|
298
|
+
} catch (error) {
|
|
299
|
+
throw new AutonomousWalletError(
|
|
300
|
+
"store-failure",
|
|
301
|
+
`encrypted wallet file at ${path} is not valid JSON`,
|
|
302
|
+
{ cause: error },
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
const kdf = isRecord(parsed) ? parsed.kdf : undefined;
|
|
306
|
+
if (
|
|
307
|
+
!isRecord(parsed) ||
|
|
308
|
+
parsed.v !== ENVELOPE_VERSION ||
|
|
309
|
+
parsed.cipher !== CIPHER ||
|
|
310
|
+
typeof parsed.ivBase64 !== "string" ||
|
|
311
|
+
typeof parsed.tagBase64 !== "string" ||
|
|
312
|
+
typeof parsed.ciphertextBase64 !== "string" ||
|
|
313
|
+
typeof parsed.keyDigest !== "string" ||
|
|
314
|
+
!isRecord(kdf) ||
|
|
315
|
+
kdf.name !== "scrypt" ||
|
|
316
|
+
typeof kdf.N !== "number" ||
|
|
317
|
+
typeof kdf.r !== "number" ||
|
|
318
|
+
typeof kdf.p !== "number" ||
|
|
319
|
+
typeof kdf.saltBase64 !== "string"
|
|
320
|
+
) {
|
|
321
|
+
throw new AutonomousWalletError(
|
|
322
|
+
"store-failure",
|
|
323
|
+
`encrypted wallet file at ${path} has an unsupported envelope`,
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
v: ENVELOPE_VERSION,
|
|
328
|
+
cipher: CIPHER,
|
|
329
|
+
kdf: {
|
|
330
|
+
name: "scrypt",
|
|
331
|
+
N: kdf.N,
|
|
332
|
+
r: kdf.r,
|
|
333
|
+
p: kdf.p,
|
|
334
|
+
saltBase64: kdf.saltBase64,
|
|
335
|
+
},
|
|
336
|
+
ivBase64: parsed.ivBase64,
|
|
337
|
+
tagBase64: parsed.tagBase64,
|
|
338
|
+
ciphertextBase64: parsed.ciphertextBase64,
|
|
339
|
+
keyDigest: parsed.keyDigest,
|
|
340
|
+
};
|
|
341
|
+
}
|
package/src/wallet/provider.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type StreamProofClientConfig } from "@absol-labs/sdk";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "@coinbase/cdp-sdk";
|
|
2
|
+
// `@coinbase/cdp-sdk` is an OPTIONAL peer dependency: TYPES only here (erased at
|
|
3
|
+
// compile time), the runtime module via `loadCdpSdk()` at the point of first use.
|
|
4
|
+
// This module IS reachable from the package barrel, so a value import here would
|
|
5
|
+
// re-introduce the hard dependency for every consumer. See ./cdp-sdk.ts.
|
|
6
|
+
import type { EvmServerAccount, EvmSmartAccount } from "@coinbase/cdp-sdk";
|
|
7
|
+
import { loadCdpSdk } from "./cdp-sdk.js";
|
|
7
8
|
import {
|
|
8
9
|
custom,
|
|
9
10
|
toHex,
|
|
@@ -173,9 +174,12 @@ export async function resolveAgentWallet(
|
|
|
173
174
|
};
|
|
174
175
|
}
|
|
175
176
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
// An injected factory keeps its synchronous public signature; only the DEFAULT
|
|
178
|
+
// path is async, because it lazily loads the optional @coinbase/cdp-sdk peer.
|
|
179
|
+
const cdpClient =
|
|
180
|
+
options.createCdpClient === undefined
|
|
181
|
+
? await defaultCdpClientFactory(input.cdp)
|
|
182
|
+
: options.createCdpClient(input.cdp);
|
|
179
183
|
const owner = await cdpClient.evm.getOrCreateAccount({
|
|
180
184
|
name: input.cdp.ownerName,
|
|
181
185
|
});
|
|
@@ -338,7 +342,10 @@ export function parseAgentWalletEnv(
|
|
|
338
342
|
};
|
|
339
343
|
}
|
|
340
344
|
|
|
341
|
-
function defaultCdpClientFactory(
|
|
345
|
+
async function defaultCdpClientFactory(
|
|
346
|
+
config: CdpWalletConfig,
|
|
347
|
+
): Promise<CdpClientLike> {
|
|
348
|
+
const { CdpClient } = await loadCdpSdk();
|
|
342
349
|
return new CdpClient({
|
|
343
350
|
...(config.apiKeyId === undefined ? {} : { apiKeyId: config.apiKeyId }),
|
|
344
351
|
...(config.apiKeySecret === undefined
|