moneyos 0.2.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -25
- package/dist/cli/index.js +2169 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.cjs +720 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +405 -0
- package/dist/index.d.ts +300 -30
- package/dist/index.js +474 -240
- package/dist/index.js.map +1 -1
- package/package.json +30 -10
- package/dist/cli/index.mjs +0 -570
- package/dist/cli/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -135
- package/dist/index.mjs +0 -429
- package/dist/index.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,75 +1,11 @@
|
|
|
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
|
-
MoneyOS: () => MoneyOS,
|
|
24
|
-
NATIVE_TOKEN_ADDRESS: () => NATIVE_TOKEN_ADDRESS,
|
|
25
|
-
OdosProvider: () => OdosProvider,
|
|
26
|
-
chains: () => chains,
|
|
27
|
-
defaultChain: () => defaultChain,
|
|
28
|
-
getChain: () => getChain,
|
|
29
|
-
getToken: () => getToken,
|
|
30
|
-
getTokenAddress: () => getTokenAddress,
|
|
31
|
-
tokens: () => tokens
|
|
32
|
-
});
|
|
33
|
-
module.exports = __toCommonJS(src_exports);
|
|
34
|
-
|
|
35
1
|
// src/core/client.ts
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
var chains = {
|
|
42
|
-
arbitrum: {
|
|
43
|
-
id: 42161,
|
|
44
|
-
name: "Arbitrum One",
|
|
45
|
-
rpcUrl: "https://arb1.arbitrum.io/rpc",
|
|
46
|
-
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
47
|
-
blockExplorer: "https://arbiscan.io"
|
|
48
|
-
},
|
|
49
|
-
ethereum: {
|
|
50
|
-
id: 1,
|
|
51
|
-
name: "Ethereum",
|
|
52
|
-
rpcUrl: "https://eth.public-rpc.com",
|
|
53
|
-
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
54
|
-
blockExplorer: "https://etherscan.io"
|
|
55
|
-
},
|
|
56
|
-
polygon: {
|
|
57
|
-
id: 137,
|
|
58
|
-
name: "Polygon",
|
|
59
|
-
rpcUrl: "https://polygon-rpc.com",
|
|
60
|
-
nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
|
|
61
|
-
blockExplorer: "https://polygonscan.com"
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
var defaultChain = chains.arbitrum;
|
|
65
|
-
function getChain(idOrName) {
|
|
66
|
-
if (typeof idOrName === "number") {
|
|
67
|
-
return Object.values(chains).find((c) => c.id === idOrName);
|
|
68
|
-
}
|
|
69
|
-
return chains[idOrName.toLowerCase()];
|
|
70
|
-
}
|
|
2
|
+
import {
|
|
3
|
+
formatUnits as formatUnits2,
|
|
4
|
+
parseUnits as parseUnits2,
|
|
5
|
+
encodeFunctionData as encodeFunctionData2
|
|
6
|
+
} from "viem";
|
|
71
7
|
|
|
72
|
-
//
|
|
8
|
+
// packages/core/dist/index.js
|
|
73
9
|
var NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
74
10
|
var tokens = {
|
|
75
11
|
ETH: {
|
|
@@ -78,7 +14,14 @@ var tokens = {
|
|
|
78
14
|
decimals: 18,
|
|
79
15
|
addresses: {
|
|
80
16
|
42161: NATIVE_TOKEN_ADDRESS,
|
|
81
|
-
1: NATIVE_TOKEN_ADDRESS
|
|
17
|
+
1: NATIVE_TOKEN_ADDRESS
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
POL: {
|
|
21
|
+
symbol: "POL",
|
|
22
|
+
name: "POL",
|
|
23
|
+
decimals: 18,
|
|
24
|
+
addresses: {
|
|
82
25
|
137: NATIVE_TOKEN_ADDRESS
|
|
83
26
|
}
|
|
84
27
|
},
|
|
@@ -117,9 +60,265 @@ function getToken(symbol) {
|
|
|
117
60
|
function getTokenAddress(symbol, chainId) {
|
|
118
61
|
return getToken(symbol)?.addresses[chainId];
|
|
119
62
|
}
|
|
63
|
+
var chains = {
|
|
64
|
+
arbitrum: {
|
|
65
|
+
id: 42161,
|
|
66
|
+
name: "Arbitrum One",
|
|
67
|
+
rpcUrl: "https://arb1.arbitrum.io/rpc",
|
|
68
|
+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
69
|
+
blockExplorer: "https://arbiscan.io"
|
|
70
|
+
},
|
|
71
|
+
ethereum: {
|
|
72
|
+
id: 1,
|
|
73
|
+
name: "Ethereum",
|
|
74
|
+
rpcUrl: "https://eth.public-rpc.com",
|
|
75
|
+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
76
|
+
blockExplorer: "https://etherscan.io"
|
|
77
|
+
},
|
|
78
|
+
polygon: {
|
|
79
|
+
id: 137,
|
|
80
|
+
name: "Polygon",
|
|
81
|
+
rpcUrl: "https://polygon-rpc.com",
|
|
82
|
+
nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
|
|
83
|
+
blockExplorer: "https://polygonscan.com"
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var defaultChain = chains.arbitrum;
|
|
87
|
+
function getChain(idOrName) {
|
|
88
|
+
if (typeof idOrName === "number") {
|
|
89
|
+
return Object.values(chains).find((c) => c.id === idOrName);
|
|
90
|
+
}
|
|
91
|
+
return chains[idOrName.toLowerCase()];
|
|
92
|
+
}
|
|
120
93
|
|
|
121
|
-
// src/core/
|
|
94
|
+
// src/core/eoa.ts
|
|
95
|
+
import {
|
|
96
|
+
createPublicClient,
|
|
97
|
+
createWalletClient,
|
|
98
|
+
http
|
|
99
|
+
} from "viem";
|
|
100
|
+
import { arbitrum, mainnet, polygon } from "viem/chains";
|
|
101
|
+
|
|
102
|
+
// src/core/signer.ts
|
|
103
|
+
import { nonceManager } from "viem";
|
|
104
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
105
|
+
function privateKeyToManagedAccount(privateKey) {
|
|
106
|
+
return privateKeyToAccount(privateKey, { nonceManager });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/core/eoa.ts
|
|
110
|
+
var viemChainMap = {
|
|
111
|
+
42161: arbitrum,
|
|
112
|
+
1: mainnet,
|
|
113
|
+
137: polygon
|
|
114
|
+
};
|
|
115
|
+
function getViemChain(chainId) {
|
|
116
|
+
return viemChainMap[chainId];
|
|
117
|
+
}
|
|
118
|
+
var ViemReadClient = class {
|
|
119
|
+
clients = /* @__PURE__ */ new Map();
|
|
120
|
+
config;
|
|
121
|
+
constructor(config) {
|
|
122
|
+
this.config = config;
|
|
123
|
+
}
|
|
124
|
+
getClient(chainId) {
|
|
125
|
+
let client = this.clients.get(chainId);
|
|
126
|
+
if (!client) {
|
|
127
|
+
const chain = getViemChain(chainId);
|
|
128
|
+
const chainInfo = getChain(chainId);
|
|
129
|
+
const rpcUrl = chainId === this.config.defaultChainId ? this.config.rpcUrl : void 0;
|
|
130
|
+
client = createPublicClient({
|
|
131
|
+
chain,
|
|
132
|
+
transport: http(rpcUrl ?? chainInfo?.rpcUrl)
|
|
133
|
+
});
|
|
134
|
+
this.clients.set(chainId, client);
|
|
135
|
+
}
|
|
136
|
+
return client;
|
|
137
|
+
}
|
|
138
|
+
async getBalance(params) {
|
|
139
|
+
const client = this.getClient(params.chainId);
|
|
140
|
+
return client.getBalance({ address: params.address });
|
|
141
|
+
}
|
|
142
|
+
async readContract(params) {
|
|
143
|
+
const client = this.getClient(params.chainId);
|
|
144
|
+
return client.readContract({
|
|
145
|
+
address: params.address,
|
|
146
|
+
abi: params.abi,
|
|
147
|
+
functionName: params.functionName,
|
|
148
|
+
args: params.args
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
var EOAExecutor = class _EOAExecutor {
|
|
153
|
+
mode = "eoa";
|
|
154
|
+
signer;
|
|
155
|
+
walletClients = /* @__PURE__ */ new Map();
|
|
156
|
+
publicClients = /* @__PURE__ */ new Map();
|
|
157
|
+
config;
|
|
158
|
+
constructor(signer, config) {
|
|
159
|
+
this.signer = signer;
|
|
160
|
+
this.config = config;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Convenience factory: build an EOAExecutor from a raw private key.
|
|
164
|
+
* Equivalent to `new EOAExecutor(privateKeyToAccount(privateKey), config)`.
|
|
165
|
+
* Kept as a helper so the common "I have a hex key" path stays one line
|
|
166
|
+
* while the constructor itself takes a viem `Account` to accommodate
|
|
167
|
+
* future keystore-backed signers (hardware, KMS, MPC).
|
|
168
|
+
*
|
|
169
|
+
* Attach viem's nonce manager so back-to-back live transactions use a
|
|
170
|
+
* pending-aware nonce source instead of relying on RPC fill behavior.
|
|
171
|
+
*/
|
|
172
|
+
static fromPrivateKey(privateKey, config) {
|
|
173
|
+
return new _EOAExecutor(privateKeyToManagedAccount(privateKey), config);
|
|
174
|
+
}
|
|
175
|
+
getWalletClient(chainId) {
|
|
176
|
+
let client = this.walletClients.get(chainId);
|
|
177
|
+
if (!client) {
|
|
178
|
+
const chain = getViemChain(chainId);
|
|
179
|
+
const chainInfo = getChain(chainId);
|
|
180
|
+
const rpcUrl = chainId === this.config.defaultChainId ? this.config.rpcUrl : void 0;
|
|
181
|
+
client = createWalletClient({
|
|
182
|
+
account: this.signer,
|
|
183
|
+
chain,
|
|
184
|
+
transport: http(rpcUrl ?? chainInfo?.rpcUrl)
|
|
185
|
+
});
|
|
186
|
+
this.walletClients.set(chainId, client);
|
|
187
|
+
}
|
|
188
|
+
return client;
|
|
189
|
+
}
|
|
190
|
+
getPublicClient(chainId) {
|
|
191
|
+
let client = this.publicClients.get(chainId);
|
|
192
|
+
if (!client) {
|
|
193
|
+
const chain = getViemChain(chainId);
|
|
194
|
+
const chainInfo = getChain(chainId);
|
|
195
|
+
const rpcUrl = chainId === this.config.defaultChainId ? this.config.rpcUrl : void 0;
|
|
196
|
+
client = createPublicClient({
|
|
197
|
+
chain,
|
|
198
|
+
transport: http(rpcUrl ?? chainInfo?.rpcUrl)
|
|
199
|
+
});
|
|
200
|
+
this.publicClients.set(chainId, client);
|
|
201
|
+
}
|
|
202
|
+
return client;
|
|
203
|
+
}
|
|
204
|
+
getAddress() {
|
|
205
|
+
return this.signer.address;
|
|
206
|
+
}
|
|
207
|
+
async send(call) {
|
|
208
|
+
const walletClient = this.getWalletClient(call.chainId);
|
|
209
|
+
const hash = await walletClient.sendTransaction({
|
|
210
|
+
account: walletClient.account,
|
|
211
|
+
to: call.to,
|
|
212
|
+
data: call.data,
|
|
213
|
+
value: call.value ?? 0n,
|
|
214
|
+
chain: walletClient.chain
|
|
215
|
+
});
|
|
216
|
+
const publicClient = this.getPublicClient(call.chainId);
|
|
217
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
218
|
+
if (receipt.status !== "success") {
|
|
219
|
+
throw new Error(
|
|
220
|
+
`Transaction ${hash} reverted on chain ${call.chainId} (block ${receipt.blockNumber}).`
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
return { hash, chainId: call.chainId };
|
|
224
|
+
}
|
|
225
|
+
capabilities() {
|
|
226
|
+
return {
|
|
227
|
+
sponsoredGas: false,
|
|
228
|
+
batching: false,
|
|
229
|
+
simulation: false
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// src/tools/swap.ts
|
|
235
|
+
import {
|
|
236
|
+
formatUnits,
|
|
237
|
+
parseUnits,
|
|
238
|
+
encodeFunctionData
|
|
239
|
+
} from "viem";
|
|
122
240
|
var ERC20_ABI = [
|
|
241
|
+
{
|
|
242
|
+
name: "approve",
|
|
243
|
+
type: "function",
|
|
244
|
+
stateMutability: "nonpayable",
|
|
245
|
+
inputs: [
|
|
246
|
+
{ name: "spender", type: "address" },
|
|
247
|
+
{ name: "amount", type: "uint256" }
|
|
248
|
+
],
|
|
249
|
+
outputs: [{ name: "", type: "bool" }]
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "allowance",
|
|
253
|
+
type: "function",
|
|
254
|
+
stateMutability: "view",
|
|
255
|
+
inputs: [
|
|
256
|
+
{ name: "owner", type: "address" },
|
|
257
|
+
{ name: "spender", type: "address" }
|
|
258
|
+
],
|
|
259
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
260
|
+
}
|
|
261
|
+
];
|
|
262
|
+
async function executeSwap(input, ctx) {
|
|
263
|
+
const { tokenIn, tokenOut, amount, provider, chainId, slippage } = input;
|
|
264
|
+
const { read, execute, assets } = ctx;
|
|
265
|
+
const sender = execute.getAddress();
|
|
266
|
+
const tokenInAddress = assets.getTokenAddress(tokenIn, chainId);
|
|
267
|
+
const tokenOutAddress = assets.getTokenAddress(tokenOut, chainId);
|
|
268
|
+
if (!tokenInAddress) {
|
|
269
|
+
throw new Error(`Token ${tokenIn} not found on chain ${chainId}`);
|
|
270
|
+
}
|
|
271
|
+
if (!tokenOutAddress) {
|
|
272
|
+
throw new Error(`Token ${tokenOut} not found on chain ${chainId}`);
|
|
273
|
+
}
|
|
274
|
+
const tokenInInfo = assets.getToken(tokenIn);
|
|
275
|
+
const amountWei = parseUnits(amount, tokenInInfo.decimals);
|
|
276
|
+
const quote = await provider.getQuote({
|
|
277
|
+
chainId,
|
|
278
|
+
tokenIn: tokenInAddress,
|
|
279
|
+
tokenOut: tokenOutAddress,
|
|
280
|
+
amount: amountWei,
|
|
281
|
+
sender,
|
|
282
|
+
slippage
|
|
283
|
+
});
|
|
284
|
+
const calldata = await provider.getCalldata(quote);
|
|
285
|
+
const isNativeIn = tokenInAddress === assets.nativeTokenAddress;
|
|
286
|
+
if (!isNativeIn) {
|
|
287
|
+
const currentAllowance = await read.readContract({
|
|
288
|
+
address: tokenInAddress,
|
|
289
|
+
abi: ERC20_ABI,
|
|
290
|
+
functionName: "allowance",
|
|
291
|
+
args: [sender, calldata.to],
|
|
292
|
+
chainId
|
|
293
|
+
});
|
|
294
|
+
if (currentAllowance < amountWei) {
|
|
295
|
+
const approveData = encodeFunctionData({
|
|
296
|
+
abi: ERC20_ABI,
|
|
297
|
+
functionName: "approve",
|
|
298
|
+
args: [calldata.to, amountWei]
|
|
299
|
+
});
|
|
300
|
+
await execute.send({ to: tokenInAddress, data: approveData, chainId });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const result = await execute.send({
|
|
304
|
+
to: calldata.to,
|
|
305
|
+
data: calldata.data,
|
|
306
|
+
value: isNativeIn ? amountWei : calldata.value,
|
|
307
|
+
chainId
|
|
308
|
+
});
|
|
309
|
+
const tokenOutInfo = assets.getToken(tokenOut);
|
|
310
|
+
return {
|
|
311
|
+
hash: result.hash,
|
|
312
|
+
tokenIn: tokenInInfo.symbol,
|
|
313
|
+
tokenOut: tokenOutInfo.symbol,
|
|
314
|
+
amountIn: amount,
|
|
315
|
+
amountOut: formatUnits(BigInt(quote.expectedOut), tokenOutInfo.decimals),
|
|
316
|
+
chainId
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/core/client.ts
|
|
321
|
+
var ERC20_ABI2 = [
|
|
123
322
|
{
|
|
124
323
|
name: "balanceOf",
|
|
125
324
|
type: "function",
|
|
@@ -150,211 +349,144 @@ var ERC20_ABI = [
|
|
|
150
349
|
stateMutability: "view",
|
|
151
350
|
inputs: [],
|
|
152
351
|
outputs: [{ name: "", type: "string" }]
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
name: "approve",
|
|
156
|
-
type: "function",
|
|
157
|
-
stateMutability: "nonpayable",
|
|
158
|
-
inputs: [
|
|
159
|
-
{ name: "spender", type: "address" },
|
|
160
|
-
{ name: "amount", type: "uint256" }
|
|
161
|
-
],
|
|
162
|
-
outputs: [{ name: "", type: "bool" }]
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
name: "allowance",
|
|
166
|
-
type: "function",
|
|
167
|
-
stateMutability: "view",
|
|
168
|
-
inputs: [
|
|
169
|
-
{ name: "owner", type: "address" },
|
|
170
|
-
{ name: "spender", type: "address" }
|
|
171
|
-
],
|
|
172
|
-
outputs: [{ name: "", type: "uint256" }]
|
|
173
352
|
}
|
|
174
353
|
];
|
|
175
|
-
var
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
354
|
+
var DefaultAssetRegistry = class {
|
|
355
|
+
nativeTokenAddress = NATIVE_TOKEN_ADDRESS;
|
|
356
|
+
getToken = getToken;
|
|
357
|
+
getTokenAddress = getTokenAddress;
|
|
358
|
+
getChain = getChain;
|
|
179
359
|
};
|
|
180
360
|
var MoneyOS = class {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
361
|
+
read;
|
|
362
|
+
executor;
|
|
363
|
+
assets;
|
|
364
|
+
runtimeConfig;
|
|
184
365
|
constructor(config) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
366
|
+
const provided = [];
|
|
367
|
+
if (config.execute) provided.push("execute");
|
|
368
|
+
if (config.privateKey) provided.push("privateKey");
|
|
369
|
+
if (config.signer) provided.push("signer");
|
|
370
|
+
if (provided.length > 1) {
|
|
371
|
+
throw new Error(
|
|
372
|
+
`MoneyOSConfig: pass at most one of \`execute\`, \`privateKey\`, or \`signer\`. Received: ${provided.join(", ")}.`
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
this.runtimeConfig = {
|
|
376
|
+
defaultChainId: config.chainId ?? defaultChain.id,
|
|
377
|
+
rpcUrl: config.rpcUrl
|
|
188
378
|
};
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
});
|
|
201
|
-
this.publicClients.set(id, client);
|
|
379
|
+
this.read = config.read ?? new ViemReadClient(this.runtimeConfig);
|
|
380
|
+
this.assets = config.assets ?? new DefaultAssetRegistry();
|
|
381
|
+
if (config.execute) {
|
|
382
|
+
this.executor = config.execute;
|
|
383
|
+
} else if (config.signer) {
|
|
384
|
+
this.executor = new EOAExecutor(config.signer, this.runtimeConfig);
|
|
385
|
+
} else if (config.privateKey) {
|
|
386
|
+
this.executor = EOAExecutor.fromPrivateKey(
|
|
387
|
+
config.privateKey,
|
|
388
|
+
this.runtimeConfig
|
|
389
|
+
);
|
|
202
390
|
}
|
|
203
|
-
return client;
|
|
204
391
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const account = (0, import_accounts.privateKeyToAccount)(this.config.privateKey);
|
|
213
|
-
const chain = viemChains[this.config.chainId];
|
|
214
|
-
const chainInfo = getChain(this.config.chainId);
|
|
215
|
-
this.walletClient = (0, import_viem.createWalletClient)({
|
|
216
|
-
account,
|
|
217
|
-
chain,
|
|
218
|
-
transport: (0, import_viem.http)(this.config.rpcUrl ?? chainInfo?.rpcUrl)
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
return this.walletClient;
|
|
392
|
+
get runtime() {
|
|
393
|
+
return {
|
|
394
|
+
read: this.read,
|
|
395
|
+
execute: this.requireExecutor(),
|
|
396
|
+
assets: this.assets,
|
|
397
|
+
config: this.runtimeConfig
|
|
398
|
+
};
|
|
222
399
|
}
|
|
223
400
|
get address() {
|
|
224
|
-
|
|
225
|
-
|
|
401
|
+
return this.requireExecutor().getAddress();
|
|
402
|
+
}
|
|
403
|
+
requireExecutor() {
|
|
404
|
+
if (!this.executor) {
|
|
405
|
+
throw new Error(
|
|
406
|
+
"No signing account configured. Set `signer`, `privateKey`, or `execute` in MoneyOS config."
|
|
407
|
+
);
|
|
226
408
|
}
|
|
227
|
-
return
|
|
409
|
+
return this.executor;
|
|
228
410
|
}
|
|
229
411
|
async balance(token, options) {
|
|
230
|
-
const chainId = options?.chainId ?? this.
|
|
412
|
+
const chainId = options?.chainId ?? this.runtimeConfig.defaultChainId;
|
|
231
413
|
const account = options?.address ?? this.address;
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
234
|
-
|
|
414
|
+
const tokenAddress = this.assets.getTokenAddress(token, chainId);
|
|
415
|
+
if (!tokenAddress) {
|
|
416
|
+
throw new Error(`Token ${token} not found on chain ${chainId}`);
|
|
417
|
+
}
|
|
418
|
+
const tokenInfo = this.assets.getToken(token);
|
|
419
|
+
if (tokenAddress === NATIVE_TOKEN_ADDRESS) {
|
|
420
|
+
const raw2 = await this.read.getBalance({ address: account, chainId });
|
|
235
421
|
return {
|
|
236
|
-
token:
|
|
237
|
-
symbol:
|
|
238
|
-
amount: (
|
|
422
|
+
token: tokenInfo.name,
|
|
423
|
+
symbol: tokenInfo.symbol,
|
|
424
|
+
amount: formatUnits2(raw2, tokenInfo.decimals),
|
|
239
425
|
rawAmount: raw2,
|
|
240
|
-
decimals:
|
|
426
|
+
decimals: tokenInfo.decimals,
|
|
241
427
|
chainId
|
|
242
428
|
};
|
|
243
429
|
}
|
|
244
|
-
const
|
|
245
|
-
if (!tokenAddress) {
|
|
246
|
-
throw new Error(`Token ${token} not found on chain ${chainId}`);
|
|
247
|
-
}
|
|
248
|
-
const tokenInfo = getToken(token);
|
|
249
|
-
const raw = await client.readContract({
|
|
430
|
+
const raw = await this.read.readContract({
|
|
250
431
|
address: tokenAddress,
|
|
251
|
-
abi:
|
|
432
|
+
abi: ERC20_ABI2,
|
|
252
433
|
functionName: "balanceOf",
|
|
253
|
-
args: [account]
|
|
434
|
+
args: [account],
|
|
435
|
+
chainId
|
|
254
436
|
});
|
|
255
437
|
return {
|
|
256
438
|
token: tokenInfo.name,
|
|
257
439
|
symbol: tokenInfo.symbol,
|
|
258
|
-
amount: (
|
|
440
|
+
amount: formatUnits2(raw, tokenInfo.decimals),
|
|
259
441
|
rawAmount: raw,
|
|
260
442
|
decimals: tokenInfo.decimals,
|
|
261
443
|
chainId
|
|
262
444
|
};
|
|
263
445
|
}
|
|
264
446
|
async send(token, to, amount, options) {
|
|
265
|
-
const
|
|
266
|
-
const
|
|
267
|
-
const from =
|
|
268
|
-
|
|
269
|
-
const value2 = (0, import_viem.parseUnits)(amount, 18);
|
|
270
|
-
const account = (0, import_accounts.privateKeyToAccount)(this.config.privateKey);
|
|
271
|
-
const hash2 = await walletClient.sendTransaction({
|
|
272
|
-
account,
|
|
273
|
-
to,
|
|
274
|
-
value: value2,
|
|
275
|
-
chain: viemChains[chainId]
|
|
276
|
-
});
|
|
277
|
-
return { hash: hash2, from, to, amount, token: "ETH", chainId };
|
|
278
|
-
}
|
|
279
|
-
const tokenAddress = getTokenAddress(token, chainId);
|
|
447
|
+
const execute = this.requireExecutor();
|
|
448
|
+
const chainId = options?.chainId ?? this.runtimeConfig.defaultChainId;
|
|
449
|
+
const from = execute.getAddress();
|
|
450
|
+
const tokenAddress = this.assets.getTokenAddress(token, chainId);
|
|
280
451
|
if (!tokenAddress) {
|
|
281
452
|
throw new Error(`Token ${token} not found on chain ${chainId}`);
|
|
282
453
|
}
|
|
283
|
-
const tokenInfo = getToken(token);
|
|
284
|
-
const value = (
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
async swap(tokenIn, tokenOut, amount, provider, options) {
|
|
297
|
-
const chainId = options?.chainId ?? this.config.chainId;
|
|
298
|
-
const walletClient = this.getWalletClient();
|
|
299
|
-
const client = this.getPublicClient(chainId);
|
|
300
|
-
const sender = this.address;
|
|
301
|
-
const tokenInAddress = getTokenAddress(tokenIn, chainId);
|
|
302
|
-
const tokenOutAddress = getTokenAddress(tokenOut, chainId);
|
|
303
|
-
if (!tokenInAddress) {
|
|
304
|
-
throw new Error(`Token ${tokenIn} not found on chain ${chainId}`);
|
|
305
|
-
}
|
|
306
|
-
if (!tokenOutAddress) {
|
|
307
|
-
throw new Error(`Token ${tokenOut} not found on chain ${chainId}`);
|
|
308
|
-
}
|
|
309
|
-
const tokenInInfo = getToken(tokenIn);
|
|
310
|
-
const amountWei = (0, import_viem.parseUnits)(amount, tokenInInfo.decimals);
|
|
311
|
-
const quote = await provider.getQuote({
|
|
312
|
-
chainId,
|
|
313
|
-
tokenIn: tokenInAddress,
|
|
314
|
-
tokenOut: tokenOutAddress,
|
|
315
|
-
amount: amountWei,
|
|
316
|
-
sender,
|
|
317
|
-
slippage: options?.slippage
|
|
318
|
-
});
|
|
319
|
-
const calldata = await provider.getCalldata(quote);
|
|
320
|
-
const isNativeIn = tokenInAddress === NATIVE_TOKEN_ADDRESS;
|
|
321
|
-
if (!isNativeIn) {
|
|
322
|
-
const currentAllowance = await client.readContract({
|
|
323
|
-
address: tokenInAddress,
|
|
324
|
-
abi: ERC20_ABI,
|
|
325
|
-
functionName: "allowance",
|
|
326
|
-
args: [sender, calldata.to]
|
|
327
|
-
});
|
|
328
|
-
if (currentAllowance < amountWei) {
|
|
329
|
-
const account2 = (0, import_accounts.privateKeyToAccount)(this.config.privateKey);
|
|
330
|
-
const { request: approveRequest } = await client.simulateContract({
|
|
331
|
-
address: tokenInAddress,
|
|
332
|
-
abi: ERC20_ABI,
|
|
333
|
-
functionName: "approve",
|
|
334
|
-
args: [calldata.to, amountWei],
|
|
335
|
-
account: account2
|
|
336
|
-
});
|
|
337
|
-
await walletClient.writeContract(approveRequest);
|
|
338
|
-
}
|
|
454
|
+
const tokenInfo = this.assets.getToken(token);
|
|
455
|
+
const value = parseUnits2(amount, tokenInfo.decimals);
|
|
456
|
+
if (tokenAddress === NATIVE_TOKEN_ADDRESS) {
|
|
457
|
+
const result2 = await execute.send({ to, value, chainId });
|
|
458
|
+
return {
|
|
459
|
+
hash: result2.hash,
|
|
460
|
+
from,
|
|
461
|
+
to,
|
|
462
|
+
amount,
|
|
463
|
+
token: tokenInfo.symbol,
|
|
464
|
+
chainId
|
|
465
|
+
};
|
|
339
466
|
}
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
data: calldata.data,
|
|
345
|
-
value: isNativeIn ? amountWei : calldata.value,
|
|
346
|
-
chain: viemChains[chainId]
|
|
467
|
+
const data = encodeFunctionData2({
|
|
468
|
+
abi: ERC20_ABI2,
|
|
469
|
+
functionName: "transfer",
|
|
470
|
+
args: [to, value]
|
|
347
471
|
});
|
|
348
|
-
const
|
|
472
|
+
const result = await execute.send({ to: tokenAddress, data, chainId });
|
|
349
473
|
return {
|
|
350
|
-
hash,
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
474
|
+
hash: result.hash,
|
|
475
|
+
from,
|
|
476
|
+
to,
|
|
477
|
+
amount,
|
|
478
|
+
token: tokenInfo.symbol,
|
|
355
479
|
chainId
|
|
356
480
|
};
|
|
357
481
|
}
|
|
482
|
+
async swap(tokenIn, tokenOut, amount, provider, options) {
|
|
483
|
+
const execute = this.requireExecutor();
|
|
484
|
+
const chainId = options?.chainId ?? this.runtimeConfig.defaultChainId;
|
|
485
|
+
return executeSwap(
|
|
486
|
+
{ tokenIn, tokenOut, amount, provider, chainId, slippage: options?.slippage },
|
|
487
|
+
{ read: this.read, execute, assets: this.assets }
|
|
488
|
+
);
|
|
489
|
+
}
|
|
358
490
|
};
|
|
359
491
|
|
|
360
492
|
// src/providers/odos.ts
|
|
@@ -443,16 +575,118 @@ var OdosProvider = class {
|
|
|
443
575
|
};
|
|
444
576
|
}
|
|
445
577
|
};
|
|
446
|
-
|
|
447
|
-
|
|
578
|
+
|
|
579
|
+
// src/core/access-local.ts
|
|
580
|
+
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
581
|
+
var LocalAccessSession = class {
|
|
582
|
+
kind = "local";
|
|
583
|
+
address;
|
|
584
|
+
constructor(privateKey) {
|
|
585
|
+
this.address = privateKeyToAccount2(privateKey).address;
|
|
586
|
+
}
|
|
587
|
+
getAddress() {
|
|
588
|
+
return this.address;
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
var LocalAccessAdapter = class {
|
|
592
|
+
name = "local";
|
|
593
|
+
privateKey;
|
|
594
|
+
constructor(privateKey) {
|
|
595
|
+
this.privateKey = privateKey;
|
|
596
|
+
}
|
|
597
|
+
async openSession(_ctx) {
|
|
598
|
+
return new LocalAccessSession(this.privateKey);
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
// src/core/keystore-file.ts
|
|
603
|
+
import { existsSync, readFileSync } from "fs";
|
|
604
|
+
import { homedir } from "os";
|
|
605
|
+
import { join } from "path";
|
|
606
|
+
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
607
|
+
var DEFAULT_CONFIG_PATH = join(homedir(), ".moneyos", "config.json");
|
|
608
|
+
var FileKeyStore = class {
|
|
609
|
+
kind = "file";
|
|
610
|
+
configPath;
|
|
611
|
+
constructor(options = {}) {
|
|
612
|
+
this.configPath = options.configPath ?? DEFAULT_CONFIG_PATH;
|
|
613
|
+
}
|
|
614
|
+
async hasKey() {
|
|
615
|
+
const config = this.readConfig();
|
|
616
|
+
return Boolean(config?.privateKey);
|
|
617
|
+
}
|
|
618
|
+
async metadata() {
|
|
619
|
+
const config = this.readConfig();
|
|
620
|
+
const address = config?.privateKey ? privateKeyToAccount3(config.privateKey).address : void 0;
|
|
621
|
+
return {
|
|
622
|
+
kind: "file",
|
|
623
|
+
address
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
async loadSigner() {
|
|
627
|
+
const config = this.readConfig();
|
|
628
|
+
if (!config?.privateKey) {
|
|
629
|
+
throw new Error(
|
|
630
|
+
`FileKeyStore: no private key found at ${this.configPath}. Run \`moneyos init\` to create one.`
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
return privateKeyToManagedAccount(config.privateKey);
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Read and validate the config file. Returns `undefined` if the file does
|
|
637
|
+
* not exist. Throws with context for any other failure mode (malformed
|
|
638
|
+
* JSON, wrong top-level type, wrong `privateKey` type). The hex format of
|
|
639
|
+
* the key itself is validated later by viem's `privateKeyToAccount`.
|
|
640
|
+
*/
|
|
641
|
+
readConfig() {
|
|
642
|
+
if (!existsSync(this.configPath)) {
|
|
643
|
+
return void 0;
|
|
644
|
+
}
|
|
645
|
+
let parsed;
|
|
646
|
+
try {
|
|
647
|
+
parsed = JSON.parse(readFileSync(this.configPath, "utf-8"));
|
|
648
|
+
} catch (error) {
|
|
649
|
+
throw new Error(
|
|
650
|
+
`FileKeyStore: failed to read config at ${this.configPath}`,
|
|
651
|
+
{ cause: error }
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
655
|
+
throw new Error(
|
|
656
|
+
`FileKeyStore: config at ${this.configPath} is not a JSON object`
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
const pk = parsed.privateKey;
|
|
660
|
+
if (pk === void 0 || pk === null) {
|
|
661
|
+
return {};
|
|
662
|
+
}
|
|
663
|
+
if (typeof pk !== "string") {
|
|
664
|
+
throw new Error(
|
|
665
|
+
`FileKeyStore: privateKey at ${this.configPath} must be a string`
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
return { privateKey: pk };
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
// src/core/factory.ts
|
|
673
|
+
function createMoneyOS(config) {
|
|
674
|
+
return new MoneyOS(config);
|
|
675
|
+
}
|
|
676
|
+
export {
|
|
677
|
+
EOAExecutor,
|
|
678
|
+
FileKeyStore,
|
|
679
|
+
LocalAccessAdapter,
|
|
448
680
|
MoneyOS,
|
|
449
681
|
NATIVE_TOKEN_ADDRESS,
|
|
450
682
|
OdosProvider,
|
|
683
|
+
ViemReadClient,
|
|
451
684
|
chains,
|
|
685
|
+
createMoneyOS,
|
|
452
686
|
defaultChain,
|
|
453
687
|
getChain,
|
|
454
688
|
getToken,
|
|
455
689
|
getTokenAddress,
|
|
456
690
|
tokens
|
|
457
|
-
}
|
|
691
|
+
};
|
|
458
692
|
//# sourceMappingURL=index.js.map
|