moneyos 0.2.0 → 0.3.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/dist/index.cjs ADDED
@@ -0,0 +1,720 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ EOAExecutor: () => EOAExecutor,
24
+ FileKeyStore: () => FileKeyStore,
25
+ LocalAccessAdapter: () => LocalAccessAdapter,
26
+ MoneyOS: () => MoneyOS,
27
+ NATIVE_TOKEN_ADDRESS: () => NATIVE_TOKEN_ADDRESS,
28
+ OdosProvider: () => OdosProvider,
29
+ ViemReadClient: () => ViemReadClient,
30
+ chains: () => chains,
31
+ createMoneyOS: () => createMoneyOS,
32
+ defaultChain: () => defaultChain,
33
+ getChain: () => getChain,
34
+ getToken: () => getToken,
35
+ getTokenAddress: () => getTokenAddress,
36
+ tokens: () => tokens
37
+ });
38
+ module.exports = __toCommonJS(src_exports);
39
+
40
+ // src/core/client.ts
41
+ var import_viem4 = require("viem");
42
+
43
+ // packages/core/dist/index.js
44
+ var NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
45
+ var tokens = {
46
+ ETH: {
47
+ symbol: "ETH",
48
+ name: "Ether",
49
+ decimals: 18,
50
+ addresses: {
51
+ 42161: NATIVE_TOKEN_ADDRESS,
52
+ 1: NATIVE_TOKEN_ADDRESS
53
+ }
54
+ },
55
+ POL: {
56
+ symbol: "POL",
57
+ name: "POL",
58
+ decimals: 18,
59
+ addresses: {
60
+ 137: NATIVE_TOKEN_ADDRESS
61
+ }
62
+ },
63
+ USDC: {
64
+ symbol: "USDC",
65
+ name: "USD Coin",
66
+ decimals: 6,
67
+ addresses: {
68
+ 42161: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
69
+ 1: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
70
+ 137: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
71
+ }
72
+ },
73
+ USDT: {
74
+ symbol: "USDT",
75
+ name: "Tether USD",
76
+ decimals: 6,
77
+ addresses: {
78
+ 42161: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
79
+ 1: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
80
+ 137: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
81
+ }
82
+ },
83
+ RYZE: {
84
+ symbol: "RYZE",
85
+ name: "RYZE",
86
+ decimals: 18,
87
+ addresses: {
88
+ 42161: "0x7712da72127d5dD213B621497D6E4899d5989e5C"
89
+ }
90
+ }
91
+ };
92
+ function getToken(symbol) {
93
+ return tokens[symbol.toUpperCase()];
94
+ }
95
+ function getTokenAddress(symbol, chainId) {
96
+ return getToken(symbol)?.addresses[chainId];
97
+ }
98
+ var chains = {
99
+ arbitrum: {
100
+ id: 42161,
101
+ name: "Arbitrum One",
102
+ rpcUrl: "https://arb1.arbitrum.io/rpc",
103
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
104
+ blockExplorer: "https://arbiscan.io"
105
+ },
106
+ ethereum: {
107
+ id: 1,
108
+ name: "Ethereum",
109
+ rpcUrl: "https://eth.public-rpc.com",
110
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
111
+ blockExplorer: "https://etherscan.io"
112
+ },
113
+ polygon: {
114
+ id: 137,
115
+ name: "Polygon",
116
+ rpcUrl: "https://polygon-rpc.com",
117
+ nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
118
+ blockExplorer: "https://polygonscan.com"
119
+ }
120
+ };
121
+ var defaultChain = chains.arbitrum;
122
+ function getChain(idOrName) {
123
+ if (typeof idOrName === "number") {
124
+ return Object.values(chains).find((c) => c.id === idOrName);
125
+ }
126
+ return chains[idOrName.toLowerCase()];
127
+ }
128
+
129
+ // src/core/eoa.ts
130
+ var import_viem2 = require("viem");
131
+ var import_chains = require("viem/chains");
132
+
133
+ // src/core/signer.ts
134
+ var import_viem = require("viem");
135
+ var import_accounts = require("viem/accounts");
136
+ function privateKeyToManagedAccount(privateKey) {
137
+ return (0, import_accounts.privateKeyToAccount)(privateKey, { nonceManager: import_viem.nonceManager });
138
+ }
139
+
140
+ // src/core/eoa.ts
141
+ var viemChainMap = {
142
+ 42161: import_chains.arbitrum,
143
+ 1: import_chains.mainnet,
144
+ 137: import_chains.polygon
145
+ };
146
+ function getViemChain(chainId) {
147
+ return viemChainMap[chainId];
148
+ }
149
+ var ViemReadClient = class {
150
+ clients = /* @__PURE__ */ new Map();
151
+ config;
152
+ constructor(config) {
153
+ this.config = config;
154
+ }
155
+ getClient(chainId) {
156
+ let client = this.clients.get(chainId);
157
+ if (!client) {
158
+ const chain = getViemChain(chainId);
159
+ const chainInfo = getChain(chainId);
160
+ const rpcUrl = chainId === this.config.defaultChainId ? this.config.rpcUrl : void 0;
161
+ client = (0, import_viem2.createPublicClient)({
162
+ chain,
163
+ transport: (0, import_viem2.http)(rpcUrl ?? chainInfo?.rpcUrl)
164
+ });
165
+ this.clients.set(chainId, client);
166
+ }
167
+ return client;
168
+ }
169
+ async getBalance(params) {
170
+ const client = this.getClient(params.chainId);
171
+ return client.getBalance({ address: params.address });
172
+ }
173
+ async readContract(params) {
174
+ const client = this.getClient(params.chainId);
175
+ return client.readContract({
176
+ address: params.address,
177
+ abi: params.abi,
178
+ functionName: params.functionName,
179
+ args: params.args
180
+ });
181
+ }
182
+ };
183
+ var EOAExecutor = class _EOAExecutor {
184
+ mode = "eoa";
185
+ signer;
186
+ walletClients = /* @__PURE__ */ new Map();
187
+ publicClients = /* @__PURE__ */ new Map();
188
+ config;
189
+ constructor(signer, config) {
190
+ this.signer = signer;
191
+ this.config = config;
192
+ }
193
+ /**
194
+ * Convenience factory: build an EOAExecutor from a raw private key.
195
+ * Equivalent to `new EOAExecutor(privateKeyToAccount(privateKey), config)`.
196
+ * Kept as a helper so the common "I have a hex key" path stays one line
197
+ * while the constructor itself takes a viem `Account` to accommodate
198
+ * future keystore-backed signers (hardware, KMS, MPC).
199
+ *
200
+ * Attach viem's nonce manager so back-to-back live transactions use a
201
+ * pending-aware nonce source instead of relying on RPC fill behavior.
202
+ */
203
+ static fromPrivateKey(privateKey, config) {
204
+ return new _EOAExecutor(privateKeyToManagedAccount(privateKey), config);
205
+ }
206
+ getWalletClient(chainId) {
207
+ let client = this.walletClients.get(chainId);
208
+ if (!client) {
209
+ const chain = getViemChain(chainId);
210
+ const chainInfo = getChain(chainId);
211
+ const rpcUrl = chainId === this.config.defaultChainId ? this.config.rpcUrl : void 0;
212
+ client = (0, import_viem2.createWalletClient)({
213
+ account: this.signer,
214
+ chain,
215
+ transport: (0, import_viem2.http)(rpcUrl ?? chainInfo?.rpcUrl)
216
+ });
217
+ this.walletClients.set(chainId, client);
218
+ }
219
+ return client;
220
+ }
221
+ getPublicClient(chainId) {
222
+ let client = this.publicClients.get(chainId);
223
+ if (!client) {
224
+ const chain = getViemChain(chainId);
225
+ const chainInfo = getChain(chainId);
226
+ const rpcUrl = chainId === this.config.defaultChainId ? this.config.rpcUrl : void 0;
227
+ client = (0, import_viem2.createPublicClient)({
228
+ chain,
229
+ transport: (0, import_viem2.http)(rpcUrl ?? chainInfo?.rpcUrl)
230
+ });
231
+ this.publicClients.set(chainId, client);
232
+ }
233
+ return client;
234
+ }
235
+ getAddress() {
236
+ return this.signer.address;
237
+ }
238
+ async send(call) {
239
+ const walletClient = this.getWalletClient(call.chainId);
240
+ const hash = await walletClient.sendTransaction({
241
+ account: walletClient.account,
242
+ to: call.to,
243
+ data: call.data,
244
+ value: call.value ?? 0n,
245
+ chain: walletClient.chain
246
+ });
247
+ const publicClient = this.getPublicClient(call.chainId);
248
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
249
+ if (receipt.status !== "success") {
250
+ throw new Error(
251
+ `Transaction ${hash} reverted on chain ${call.chainId} (block ${receipt.blockNumber}).`
252
+ );
253
+ }
254
+ return { hash, chainId: call.chainId };
255
+ }
256
+ capabilities() {
257
+ return {
258
+ sponsoredGas: false,
259
+ batching: false,
260
+ simulation: false
261
+ };
262
+ }
263
+ };
264
+
265
+ // src/tools/swap.ts
266
+ var import_viem3 = require("viem");
267
+ var ERC20_ABI = [
268
+ {
269
+ name: "approve",
270
+ type: "function",
271
+ stateMutability: "nonpayable",
272
+ inputs: [
273
+ { name: "spender", type: "address" },
274
+ { name: "amount", type: "uint256" }
275
+ ],
276
+ outputs: [{ name: "", type: "bool" }]
277
+ },
278
+ {
279
+ name: "allowance",
280
+ type: "function",
281
+ stateMutability: "view",
282
+ inputs: [
283
+ { name: "owner", type: "address" },
284
+ { name: "spender", type: "address" }
285
+ ],
286
+ outputs: [{ name: "", type: "uint256" }]
287
+ }
288
+ ];
289
+ async function executeSwap(input, ctx) {
290
+ const { tokenIn, tokenOut, amount, provider, chainId, slippage } = input;
291
+ const { read, execute, assets } = ctx;
292
+ const sender = execute.getAddress();
293
+ const tokenInAddress = assets.getTokenAddress(tokenIn, chainId);
294
+ const tokenOutAddress = assets.getTokenAddress(tokenOut, chainId);
295
+ if (!tokenInAddress) {
296
+ throw new Error(`Token ${tokenIn} not found on chain ${chainId}`);
297
+ }
298
+ if (!tokenOutAddress) {
299
+ throw new Error(`Token ${tokenOut} not found on chain ${chainId}`);
300
+ }
301
+ const tokenInInfo = assets.getToken(tokenIn);
302
+ const amountWei = (0, import_viem3.parseUnits)(amount, tokenInInfo.decimals);
303
+ const quote = await provider.getQuote({
304
+ chainId,
305
+ tokenIn: tokenInAddress,
306
+ tokenOut: tokenOutAddress,
307
+ amount: amountWei,
308
+ sender,
309
+ slippage
310
+ });
311
+ const calldata = await provider.getCalldata(quote);
312
+ const isNativeIn = tokenInAddress === assets.nativeTokenAddress;
313
+ if (!isNativeIn) {
314
+ const currentAllowance = await read.readContract({
315
+ address: tokenInAddress,
316
+ abi: ERC20_ABI,
317
+ functionName: "allowance",
318
+ args: [sender, calldata.to],
319
+ chainId
320
+ });
321
+ if (currentAllowance < amountWei) {
322
+ const approveData = (0, import_viem3.encodeFunctionData)({
323
+ abi: ERC20_ABI,
324
+ functionName: "approve",
325
+ args: [calldata.to, amountWei]
326
+ });
327
+ await execute.send({ to: tokenInAddress, data: approveData, chainId });
328
+ }
329
+ }
330
+ const result = await execute.send({
331
+ to: calldata.to,
332
+ data: calldata.data,
333
+ value: isNativeIn ? amountWei : calldata.value,
334
+ chainId
335
+ });
336
+ const tokenOutInfo = assets.getToken(tokenOut);
337
+ return {
338
+ hash: result.hash,
339
+ tokenIn: tokenInInfo.symbol,
340
+ tokenOut: tokenOutInfo.symbol,
341
+ amountIn: amount,
342
+ amountOut: (0, import_viem3.formatUnits)(BigInt(quote.expectedOut), tokenOutInfo.decimals),
343
+ chainId
344
+ };
345
+ }
346
+
347
+ // src/core/client.ts
348
+ var ERC20_ABI2 = [
349
+ {
350
+ name: "balanceOf",
351
+ type: "function",
352
+ stateMutability: "view",
353
+ inputs: [{ name: "account", type: "address" }],
354
+ outputs: [{ name: "", type: "uint256" }]
355
+ },
356
+ {
357
+ name: "transfer",
358
+ type: "function",
359
+ stateMutability: "nonpayable",
360
+ inputs: [
361
+ { name: "to", type: "address" },
362
+ { name: "amount", type: "uint256" }
363
+ ],
364
+ outputs: [{ name: "", type: "bool" }]
365
+ },
366
+ {
367
+ name: "decimals",
368
+ type: "function",
369
+ stateMutability: "view",
370
+ inputs: [],
371
+ outputs: [{ name: "", type: "uint8" }]
372
+ },
373
+ {
374
+ name: "symbol",
375
+ type: "function",
376
+ stateMutability: "view",
377
+ inputs: [],
378
+ outputs: [{ name: "", type: "string" }]
379
+ }
380
+ ];
381
+ var DefaultAssetRegistry = class {
382
+ nativeTokenAddress = NATIVE_TOKEN_ADDRESS;
383
+ getToken = getToken;
384
+ getTokenAddress = getTokenAddress;
385
+ getChain = getChain;
386
+ };
387
+ var MoneyOS = class {
388
+ read;
389
+ executor;
390
+ assets;
391
+ runtimeConfig;
392
+ constructor(config) {
393
+ const provided = [];
394
+ if (config.execute) provided.push("execute");
395
+ if (config.privateKey) provided.push("privateKey");
396
+ if (config.signer) provided.push("signer");
397
+ if (provided.length > 1) {
398
+ throw new Error(
399
+ `MoneyOSConfig: pass at most one of \`execute\`, \`privateKey\`, or \`signer\`. Received: ${provided.join(", ")}.`
400
+ );
401
+ }
402
+ this.runtimeConfig = {
403
+ defaultChainId: config.chainId ?? defaultChain.id,
404
+ rpcUrl: config.rpcUrl
405
+ };
406
+ this.read = config.read ?? new ViemReadClient(this.runtimeConfig);
407
+ this.assets = config.assets ?? new DefaultAssetRegistry();
408
+ if (config.execute) {
409
+ this.executor = config.execute;
410
+ } else if (config.signer) {
411
+ this.executor = new EOAExecutor(config.signer, this.runtimeConfig);
412
+ } else if (config.privateKey) {
413
+ this.executor = EOAExecutor.fromPrivateKey(
414
+ config.privateKey,
415
+ this.runtimeConfig
416
+ );
417
+ }
418
+ }
419
+ get runtime() {
420
+ return {
421
+ read: this.read,
422
+ execute: this.requireExecutor(),
423
+ assets: this.assets,
424
+ config: this.runtimeConfig
425
+ };
426
+ }
427
+ get address() {
428
+ return this.requireExecutor().getAddress();
429
+ }
430
+ requireExecutor() {
431
+ if (!this.executor) {
432
+ throw new Error(
433
+ "No signing account configured. Set `signer`, `privateKey`, or `execute` in MoneyOS config."
434
+ );
435
+ }
436
+ return this.executor;
437
+ }
438
+ async balance(token, options) {
439
+ const chainId = options?.chainId ?? this.runtimeConfig.defaultChainId;
440
+ const account = options?.address ?? this.address;
441
+ const tokenAddress = this.assets.getTokenAddress(token, chainId);
442
+ if (!tokenAddress) {
443
+ throw new Error(`Token ${token} not found on chain ${chainId}`);
444
+ }
445
+ const tokenInfo = this.assets.getToken(token);
446
+ if (tokenAddress === NATIVE_TOKEN_ADDRESS) {
447
+ const raw2 = await this.read.getBalance({ address: account, chainId });
448
+ return {
449
+ token: tokenInfo.name,
450
+ symbol: tokenInfo.symbol,
451
+ amount: (0, import_viem4.formatUnits)(raw2, tokenInfo.decimals),
452
+ rawAmount: raw2,
453
+ decimals: tokenInfo.decimals,
454
+ chainId
455
+ };
456
+ }
457
+ const raw = await this.read.readContract({
458
+ address: tokenAddress,
459
+ abi: ERC20_ABI2,
460
+ functionName: "balanceOf",
461
+ args: [account],
462
+ chainId
463
+ });
464
+ return {
465
+ token: tokenInfo.name,
466
+ symbol: tokenInfo.symbol,
467
+ amount: (0, import_viem4.formatUnits)(raw, tokenInfo.decimals),
468
+ rawAmount: raw,
469
+ decimals: tokenInfo.decimals,
470
+ chainId
471
+ };
472
+ }
473
+ async send(token, to, amount, options) {
474
+ const execute = this.requireExecutor();
475
+ const chainId = options?.chainId ?? this.runtimeConfig.defaultChainId;
476
+ const from = execute.getAddress();
477
+ const tokenAddress = this.assets.getTokenAddress(token, chainId);
478
+ if (!tokenAddress) {
479
+ throw new Error(`Token ${token} not found on chain ${chainId}`);
480
+ }
481
+ const tokenInfo = this.assets.getToken(token);
482
+ const value = (0, import_viem4.parseUnits)(amount, tokenInfo.decimals);
483
+ if (tokenAddress === NATIVE_TOKEN_ADDRESS) {
484
+ const result2 = await execute.send({ to, value, chainId });
485
+ return {
486
+ hash: result2.hash,
487
+ from,
488
+ to,
489
+ amount,
490
+ token: tokenInfo.symbol,
491
+ chainId
492
+ };
493
+ }
494
+ const data = (0, import_viem4.encodeFunctionData)({
495
+ abi: ERC20_ABI2,
496
+ functionName: "transfer",
497
+ args: [to, value]
498
+ });
499
+ const result = await execute.send({ to: tokenAddress, data, chainId });
500
+ return {
501
+ hash: result.hash,
502
+ from,
503
+ to,
504
+ amount,
505
+ token: tokenInfo.symbol,
506
+ chainId
507
+ };
508
+ }
509
+ async swap(tokenIn, tokenOut, amount, provider, options) {
510
+ const execute = this.requireExecutor();
511
+ const chainId = options?.chainId ?? this.runtimeConfig.defaultChainId;
512
+ return executeSwap(
513
+ { tokenIn, tokenOut, amount, provider, chainId, slippage: options?.slippage },
514
+ { read: this.read, execute, assets: this.assets }
515
+ );
516
+ }
517
+ };
518
+
519
+ // src/providers/odos.ts
520
+ var ODOS_API = "https://api.odos.xyz";
521
+ var ODOS_NATIVE_ADDRESS = "0x0000000000000000000000000000000000000000";
522
+ var OdosProvider = class {
523
+ name = "odos";
524
+ apiKey;
525
+ constructor(options) {
526
+ this.apiKey = options?.apiKey;
527
+ }
528
+ toOdosAddress(address) {
529
+ return address === NATIVE_TOKEN_ADDRESS ? ODOS_NATIVE_ADDRESS : address;
530
+ }
531
+ async getQuote(params) {
532
+ const headers = {
533
+ "Content-Type": "application/json"
534
+ };
535
+ if (this.apiKey) {
536
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
537
+ }
538
+ const response = await fetch(`${ODOS_API}/sor/quote/v2`, {
539
+ method: "POST",
540
+ headers,
541
+ body: JSON.stringify({
542
+ chainId: params.chainId,
543
+ inputTokens: [
544
+ {
545
+ tokenAddress: this.toOdosAddress(params.tokenIn),
546
+ amount: params.amount.toString()
547
+ }
548
+ ],
549
+ outputTokens: [
550
+ {
551
+ tokenAddress: this.toOdosAddress(params.tokenOut),
552
+ proportion: 1
553
+ }
554
+ ],
555
+ userAddr: params.sender,
556
+ slippageLimitPercent: params.slippage ?? 1,
557
+ referralCode: 0,
558
+ compact: true
559
+ })
560
+ });
561
+ if (!response.ok) {
562
+ const text = await response.text();
563
+ throw new Error(`Odos quote failed: ${response.status} ${text}`);
564
+ }
565
+ const data = await response.json();
566
+ return {
567
+ tokenIn: params.tokenIn,
568
+ tokenOut: params.tokenOut,
569
+ amountIn: params.amount.toString(),
570
+ expectedOut: data.outAmounts[0],
571
+ router: "",
572
+ chainId: params.chainId,
573
+ pathId: data.pathId,
574
+ sender: params.sender
575
+ };
576
+ }
577
+ async getCalldata(quote) {
578
+ const headers = {
579
+ "Content-Type": "application/json"
580
+ };
581
+ if (this.apiKey) {
582
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
583
+ }
584
+ const response = await fetch(`${ODOS_API}/sor/assemble`, {
585
+ method: "POST",
586
+ headers,
587
+ body: JSON.stringify({
588
+ userAddr: quote.sender,
589
+ pathId: quote.pathId,
590
+ simulate: false
591
+ })
592
+ });
593
+ if (!response.ok) {
594
+ const text = await response.text();
595
+ throw new Error(`Odos assemble failed: ${response.status} ${text}`);
596
+ }
597
+ const data = await response.json();
598
+ return {
599
+ to: data.transaction.to,
600
+ data: data.transaction.data,
601
+ value: BigInt(data.transaction.value)
602
+ };
603
+ }
604
+ };
605
+
606
+ // src/core/access-local.ts
607
+ var import_accounts2 = require("viem/accounts");
608
+ var LocalAccessSession = class {
609
+ kind = "local";
610
+ address;
611
+ constructor(privateKey) {
612
+ this.address = (0, import_accounts2.privateKeyToAccount)(privateKey).address;
613
+ }
614
+ getAddress() {
615
+ return this.address;
616
+ }
617
+ };
618
+ var LocalAccessAdapter = class {
619
+ name = "local";
620
+ privateKey;
621
+ constructor(privateKey) {
622
+ this.privateKey = privateKey;
623
+ }
624
+ async openSession(_ctx) {
625
+ return new LocalAccessSession(this.privateKey);
626
+ }
627
+ };
628
+
629
+ // src/core/keystore-file.ts
630
+ var import_node_fs = require("fs");
631
+ var import_node_os = require("os");
632
+ var import_node_path = require("path");
633
+ var import_accounts3 = require("viem/accounts");
634
+ var DEFAULT_CONFIG_PATH = (0, import_node_path.join)((0, import_node_os.homedir)(), ".moneyos", "config.json");
635
+ var FileKeyStore = class {
636
+ kind = "file";
637
+ configPath;
638
+ constructor(options = {}) {
639
+ this.configPath = options.configPath ?? DEFAULT_CONFIG_PATH;
640
+ }
641
+ async hasKey() {
642
+ const config = this.readConfig();
643
+ return Boolean(config?.privateKey);
644
+ }
645
+ async metadata() {
646
+ const config = this.readConfig();
647
+ const address = config?.privateKey ? (0, import_accounts3.privateKeyToAccount)(config.privateKey).address : void 0;
648
+ return {
649
+ kind: "file",
650
+ address
651
+ };
652
+ }
653
+ async loadSigner() {
654
+ const config = this.readConfig();
655
+ if (!config?.privateKey) {
656
+ throw new Error(
657
+ `FileKeyStore: no private key found at ${this.configPath}. Run \`moneyos init\` to create one.`
658
+ );
659
+ }
660
+ return privateKeyToManagedAccount(config.privateKey);
661
+ }
662
+ /**
663
+ * Read and validate the config file. Returns `undefined` if the file does
664
+ * not exist. Throws with context for any other failure mode (malformed
665
+ * JSON, wrong top-level type, wrong `privateKey` type). The hex format of
666
+ * the key itself is validated later by viem's `privateKeyToAccount`.
667
+ */
668
+ readConfig() {
669
+ if (!(0, import_node_fs.existsSync)(this.configPath)) {
670
+ return void 0;
671
+ }
672
+ let parsed;
673
+ try {
674
+ parsed = JSON.parse((0, import_node_fs.readFileSync)(this.configPath, "utf-8"));
675
+ } catch (error) {
676
+ throw new Error(
677
+ `FileKeyStore: failed to read config at ${this.configPath}`,
678
+ { cause: error }
679
+ );
680
+ }
681
+ if (typeof parsed !== "object" || parsed === null) {
682
+ throw new Error(
683
+ `FileKeyStore: config at ${this.configPath} is not a JSON object`
684
+ );
685
+ }
686
+ const pk = parsed.privateKey;
687
+ if (pk === void 0 || pk === null) {
688
+ return {};
689
+ }
690
+ if (typeof pk !== "string") {
691
+ throw new Error(
692
+ `FileKeyStore: privateKey at ${this.configPath} must be a string`
693
+ );
694
+ }
695
+ return { privateKey: pk };
696
+ }
697
+ };
698
+
699
+ // src/core/factory.ts
700
+ function createMoneyOS(config) {
701
+ return new MoneyOS(config);
702
+ }
703
+ // Annotate the CommonJS export names for ESM import in node:
704
+ 0 && (module.exports = {
705
+ EOAExecutor,
706
+ FileKeyStore,
707
+ LocalAccessAdapter,
708
+ MoneyOS,
709
+ NATIVE_TOKEN_ADDRESS,
710
+ OdosProvider,
711
+ ViemReadClient,
712
+ chains,
713
+ createMoneyOS,
714
+ defaultChain,
715
+ getChain,
716
+ getToken,
717
+ getTokenAddress,
718
+ tokens
719
+ });
720
+ //# sourceMappingURL=index.cjs.map