@vleap/warps-adapter-evm 0.2.0-alpha.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 +400 -0
- package/dist/index.d.mts +139 -0
- package/dist/index.d.ts +139 -0
- package/dist/index.js +793 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +761 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +36 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
var EVM_CHAIN_CONFIGS = {
|
|
3
|
+
ethereum: {
|
|
4
|
+
mainnet: {
|
|
5
|
+
apiUrl: "https://eth-mainnet.g.alchemy.com/v2/demo",
|
|
6
|
+
explorerUrl: "https://etherscan.io",
|
|
7
|
+
chainId: "1",
|
|
8
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
9
|
+
nativeToken: "ETH",
|
|
10
|
+
blockTime: 12
|
|
11
|
+
},
|
|
12
|
+
testnet: {
|
|
13
|
+
apiUrl: "https://eth-sepolia.g.alchemy.com/v2/demo",
|
|
14
|
+
explorerUrl: "https://sepolia.etherscan.io",
|
|
15
|
+
chainId: "11155111",
|
|
16
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
17
|
+
nativeToken: "ETH",
|
|
18
|
+
blockTime: 12
|
|
19
|
+
},
|
|
20
|
+
devnet: {
|
|
21
|
+
apiUrl: "http://localhost:8545",
|
|
22
|
+
explorerUrl: "http://localhost:4000",
|
|
23
|
+
chainId: "1337",
|
|
24
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
25
|
+
nativeToken: "ETH",
|
|
26
|
+
blockTime: 12
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
arbitrum: {
|
|
30
|
+
mainnet: {
|
|
31
|
+
apiUrl: "https://arb-mainnet.g.alchemy.com/v2/demo",
|
|
32
|
+
explorerUrl: "https://arbiscan.io",
|
|
33
|
+
chainId: "42161",
|
|
34
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
35
|
+
nativeToken: "ETH",
|
|
36
|
+
blockTime: 1
|
|
37
|
+
},
|
|
38
|
+
testnet: {
|
|
39
|
+
apiUrl: "https://arb-sepolia.g.alchemy.com/v2/demo",
|
|
40
|
+
explorerUrl: "https://sepolia.arbiscan.io",
|
|
41
|
+
chainId: "421614",
|
|
42
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
43
|
+
nativeToken: "ETH",
|
|
44
|
+
blockTime: 1
|
|
45
|
+
},
|
|
46
|
+
devnet: {
|
|
47
|
+
apiUrl: "http://localhost:8545",
|
|
48
|
+
explorerUrl: "http://localhost:4000",
|
|
49
|
+
chainId: "1337",
|
|
50
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
51
|
+
nativeToken: "ETH",
|
|
52
|
+
blockTime: 1
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
base: {
|
|
56
|
+
mainnet: {
|
|
57
|
+
apiUrl: "https://mainnet.base.org",
|
|
58
|
+
explorerUrl: "https://basescan.org",
|
|
59
|
+
chainId: "8453",
|
|
60
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
61
|
+
nativeToken: "ETH",
|
|
62
|
+
blockTime: 2
|
|
63
|
+
},
|
|
64
|
+
testnet: {
|
|
65
|
+
apiUrl: "https://sepolia.base.org",
|
|
66
|
+
explorerUrl: "https://sepolia.basescan.org",
|
|
67
|
+
chainId: "84532",
|
|
68
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
69
|
+
nativeToken: "ETH",
|
|
70
|
+
blockTime: 2
|
|
71
|
+
},
|
|
72
|
+
devnet: {
|
|
73
|
+
apiUrl: "http://localhost:8545",
|
|
74
|
+
explorerUrl: "http://localhost:4000",
|
|
75
|
+
chainId: "1337",
|
|
76
|
+
registryAddress: "0x0000000000000000000000000000000000000000",
|
|
77
|
+
nativeToken: "ETH",
|
|
78
|
+
blockTime: 2
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
var DEFAULT_CHAIN = "ethereum";
|
|
83
|
+
var getEvmChainConfig = (chain = DEFAULT_CHAIN, env) => {
|
|
84
|
+
const chainConfigs = EVM_CHAIN_CONFIGS[chain];
|
|
85
|
+
if (!chainConfigs) {
|
|
86
|
+
throw new Error(`Unsupported EVM chain: ${chain}`);
|
|
87
|
+
}
|
|
88
|
+
const config = chainConfigs[env];
|
|
89
|
+
if (!config) {
|
|
90
|
+
throw new Error(`Unsupported environment ${env} for chain ${chain}`);
|
|
91
|
+
}
|
|
92
|
+
return config;
|
|
93
|
+
};
|
|
94
|
+
var getEvmApiUrl = (env, chain = DEFAULT_CHAIN) => {
|
|
95
|
+
return getEvmChainConfig(chain, env).apiUrl;
|
|
96
|
+
};
|
|
97
|
+
var getEvmExplorerUrl = (env, chain = DEFAULT_CHAIN) => {
|
|
98
|
+
return getEvmChainConfig(chain, env).explorerUrl;
|
|
99
|
+
};
|
|
100
|
+
var getEvmChainId = (env, chain = DEFAULT_CHAIN) => {
|
|
101
|
+
return getEvmChainConfig(chain, env).chainId;
|
|
102
|
+
};
|
|
103
|
+
var getEvmRegistryAddress = (env, chain = DEFAULT_CHAIN) => {
|
|
104
|
+
return getEvmChainConfig(chain, env).registryAddress;
|
|
105
|
+
};
|
|
106
|
+
var getEvmNativeToken = (env, chain = DEFAULT_CHAIN) => {
|
|
107
|
+
return getEvmChainConfig(chain, env).nativeToken;
|
|
108
|
+
};
|
|
109
|
+
var getEvmBlockTime = (env, chain = DEFAULT_CHAIN) => {
|
|
110
|
+
return getEvmChainConfig(chain, env).blockTime || 12;
|
|
111
|
+
};
|
|
112
|
+
var getSupportedEvmChains = () => {
|
|
113
|
+
return Object.keys(EVM_CHAIN_CONFIGS);
|
|
114
|
+
};
|
|
115
|
+
var getSupportedEnvironments = (chain) => {
|
|
116
|
+
const chainConfigs = EVM_CHAIN_CONFIGS[chain];
|
|
117
|
+
if (!chainConfigs) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
return Object.keys(chainConfigs);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// src/constants.ts
|
|
124
|
+
var WarpEvmConstants = {
|
|
125
|
+
ChainName: "evm",
|
|
126
|
+
ChainPrefix: "evm",
|
|
127
|
+
Ether: {
|
|
128
|
+
Identifier: "ETH",
|
|
129
|
+
DisplayName: "Ether",
|
|
130
|
+
Decimals: 18
|
|
131
|
+
},
|
|
132
|
+
GasLimit: {
|
|
133
|
+
Default: 21e3,
|
|
134
|
+
ContractCall: 1e5,
|
|
135
|
+
ContractDeploy: 5e5,
|
|
136
|
+
Transfer: 21e3,
|
|
137
|
+
Approve: 46e3,
|
|
138
|
+
Swap: 2e5
|
|
139
|
+
},
|
|
140
|
+
GasPrice: {
|
|
141
|
+
Default: "20000000000",
|
|
142
|
+
// 20 gwei
|
|
143
|
+
Low: "10000000000",
|
|
144
|
+
// 10 gwei
|
|
145
|
+
Medium: "20000000000",
|
|
146
|
+
// 20 gwei
|
|
147
|
+
High: "50000000000"
|
|
148
|
+
// 50 gwei
|
|
149
|
+
},
|
|
150
|
+
Network: {
|
|
151
|
+
Ethereum: {
|
|
152
|
+
ChainId: "1",
|
|
153
|
+
Name: "Ethereum",
|
|
154
|
+
BlockTime: 12
|
|
155
|
+
},
|
|
156
|
+
Arbitrum: {
|
|
157
|
+
ChainId: "42161",
|
|
158
|
+
Name: "Arbitrum",
|
|
159
|
+
BlockTime: 1
|
|
160
|
+
},
|
|
161
|
+
Base: {
|
|
162
|
+
ChainId: "8453",
|
|
163
|
+
Name: "Base",
|
|
164
|
+
BlockTime: 2
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
Validation: {
|
|
168
|
+
AddressLength: 42,
|
|
169
|
+
HexPrefix: "0x",
|
|
170
|
+
MinGasLimit: 21e3,
|
|
171
|
+
MaxGasLimit: 3e7
|
|
172
|
+
},
|
|
173
|
+
Timeouts: {
|
|
174
|
+
DefaultRpcTimeout: 3e4,
|
|
175
|
+
// 30 seconds
|
|
176
|
+
GasEstimationTimeout: 1e4,
|
|
177
|
+
// 10 seconds
|
|
178
|
+
QueryTimeout: 15e3
|
|
179
|
+
// 15 seconds
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/WarpEvmBuilder.ts
|
|
184
|
+
import { ethers } from "ethers";
|
|
185
|
+
var WarpEvmBuilder = class {
|
|
186
|
+
constructor(config) {
|
|
187
|
+
this.config = config;
|
|
188
|
+
this.warp = {};
|
|
189
|
+
this.actions = [];
|
|
190
|
+
}
|
|
191
|
+
async createFromRaw(encoded) {
|
|
192
|
+
try {
|
|
193
|
+
const decoded = JSON.parse(encoded);
|
|
194
|
+
return decoded;
|
|
195
|
+
} catch (error) {
|
|
196
|
+
throw new Error(`Failed to decode warp from raw data: ${error}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
setTitle(title) {
|
|
200
|
+
this.warp.title = title;
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
setDescription(description) {
|
|
204
|
+
this.warp.description = description;
|
|
205
|
+
return this;
|
|
206
|
+
}
|
|
207
|
+
setPreview(preview) {
|
|
208
|
+
this.warp.preview = preview;
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
setActions(actions) {
|
|
212
|
+
this.actions = actions;
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
addAction(action) {
|
|
216
|
+
this.actions.push(action);
|
|
217
|
+
return this;
|
|
218
|
+
}
|
|
219
|
+
async build() {
|
|
220
|
+
if (!this.warp.title) {
|
|
221
|
+
throw new Error("Warp title is required");
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
protocol: "warp",
|
|
225
|
+
name: this.warp.name || "evm-warp",
|
|
226
|
+
title: this.warp.title,
|
|
227
|
+
description: this.warp.description || null,
|
|
228
|
+
preview: this.warp.preview || null,
|
|
229
|
+
actions: this.actions,
|
|
230
|
+
meta: {
|
|
231
|
+
chain: "evm",
|
|
232
|
+
hash: ethers.keccak256(ethers.toUtf8Bytes(this.warp.title)),
|
|
233
|
+
creator: this.config.user?.wallets?.evm || "",
|
|
234
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
createInscriptionTransaction(warp) {
|
|
239
|
+
const warpData = JSON.stringify(warp);
|
|
240
|
+
const data = ethers.toUtf8Bytes(warpData);
|
|
241
|
+
return {
|
|
242
|
+
data: ethers.hexlify(data)
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async createFromTransaction(tx, validate) {
|
|
246
|
+
if (!tx.data || tx.data === "0x") {
|
|
247
|
+
throw new Error("Transaction has no data");
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const data = ethers.toUtf8String(tx.data);
|
|
251
|
+
const warp = JSON.parse(data);
|
|
252
|
+
if (validate) {
|
|
253
|
+
if (!warp.protocol || warp.protocol !== "warp") {
|
|
254
|
+
throw new Error("Invalid warp protocol");
|
|
255
|
+
}
|
|
256
|
+
if (!warp.title) {
|
|
257
|
+
throw new Error("Warp title is required");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return warp;
|
|
261
|
+
} catch (error) {
|
|
262
|
+
throw new Error(`Failed to create warp from transaction: ${error}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async createFromTransactionHash(hash, cache) {
|
|
266
|
+
try {
|
|
267
|
+
const provider = new ethers.JsonRpcProvider(getEvmApiUrl(this.config.env));
|
|
268
|
+
const tx = await provider.getTransaction(hash);
|
|
269
|
+
if (!tx) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
return await this.createFromTransaction(tx);
|
|
273
|
+
} catch (error) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// src/WarpEvmExecutor.ts
|
|
280
|
+
import {
|
|
281
|
+
applyResultsToMessages,
|
|
282
|
+
getNextInfo,
|
|
283
|
+
getWarpActionByIndex
|
|
284
|
+
} from "@vleap/warps";
|
|
285
|
+
import { ethers as ethers3 } from "ethers";
|
|
286
|
+
|
|
287
|
+
// src/WarpEvmResults.ts
|
|
288
|
+
import {
|
|
289
|
+
evaluateResultsCommon,
|
|
290
|
+
parseResultsOutIndex,
|
|
291
|
+
WarpConstants as WarpConstants2
|
|
292
|
+
} from "@vleap/warps";
|
|
293
|
+
|
|
294
|
+
// src/WarpEvmSerializer.ts
|
|
295
|
+
import {
|
|
296
|
+
WarpConstants,
|
|
297
|
+
WarpSerializer
|
|
298
|
+
} from "@vleap/warps";
|
|
299
|
+
import { ethers as ethers2 } from "ethers";
|
|
300
|
+
var SplitParamsRegex = new RegExp(`${WarpConstants.ArgParamsSeparator}(.*)`);
|
|
301
|
+
var WarpEvmSerializer = class {
|
|
302
|
+
constructor() {
|
|
303
|
+
this.coreSerializer = new WarpSerializer();
|
|
304
|
+
}
|
|
305
|
+
typedToString(value) {
|
|
306
|
+
if (typeof value === "string") {
|
|
307
|
+
if (ethers2.isAddress(value)) {
|
|
308
|
+
return `address:${value}`;
|
|
309
|
+
}
|
|
310
|
+
if (ethers2.isHexString(value) && !ethers2.isAddress(value)) {
|
|
311
|
+
return `hex:${value}`;
|
|
312
|
+
}
|
|
313
|
+
return `string:${value}`;
|
|
314
|
+
}
|
|
315
|
+
if (typeof value === "number") {
|
|
316
|
+
if (Number.isInteger(value)) {
|
|
317
|
+
if (value >= 0 && value <= 255) return `uint8:${value}`;
|
|
318
|
+
if (value >= 0 && value <= 65535) return `uint16:${value}`;
|
|
319
|
+
if (value >= 0 && value <= 4294967295) return `uint32:${value}`;
|
|
320
|
+
return `uint64:${value}`;
|
|
321
|
+
}
|
|
322
|
+
return `string:${value}`;
|
|
323
|
+
}
|
|
324
|
+
if (typeof value === "bigint") {
|
|
325
|
+
return `biguint:${value.toString()}`;
|
|
326
|
+
}
|
|
327
|
+
if (typeof value === "boolean") {
|
|
328
|
+
return `boolean:${value}`;
|
|
329
|
+
}
|
|
330
|
+
if (Array.isArray(value)) {
|
|
331
|
+
if (value.length === 0) return `list:string:`;
|
|
332
|
+
const types = value.map((item) => this.typedToString(item).split(WarpConstants.ArgParamsSeparator)[0]);
|
|
333
|
+
const type = types[0];
|
|
334
|
+
const values = value.map((item) => this.typedToString(item).split(WarpConstants.ArgParamsSeparator)[1]);
|
|
335
|
+
return `list:${type}:${values.join(",")}`;
|
|
336
|
+
}
|
|
337
|
+
if (value === null || value === void 0) {
|
|
338
|
+
return `string:null`;
|
|
339
|
+
}
|
|
340
|
+
return `string:${String(value)}`;
|
|
341
|
+
}
|
|
342
|
+
typedToNative(value) {
|
|
343
|
+
const stringValue = this.typedToString(value);
|
|
344
|
+
const [type, ...valueParts] = stringValue.split(WarpConstants.ArgParamsSeparator);
|
|
345
|
+
const nativeValue = valueParts.join(WarpConstants.ArgParamsSeparator);
|
|
346
|
+
return [type, this.parseNativeValue(type, nativeValue)];
|
|
347
|
+
}
|
|
348
|
+
nativeToTyped(type, value) {
|
|
349
|
+
switch (type) {
|
|
350
|
+
case "string":
|
|
351
|
+
return String(value);
|
|
352
|
+
case "uint8":
|
|
353
|
+
case "uint16":
|
|
354
|
+
case "uint32":
|
|
355
|
+
case "uint64":
|
|
356
|
+
return BigInt(value);
|
|
357
|
+
case "biguint":
|
|
358
|
+
return BigInt(value);
|
|
359
|
+
case "boolean":
|
|
360
|
+
return Boolean(value);
|
|
361
|
+
case "address":
|
|
362
|
+
return String(value);
|
|
363
|
+
case "hex":
|
|
364
|
+
return String(value);
|
|
365
|
+
default:
|
|
366
|
+
if (type.startsWith("list:")) {
|
|
367
|
+
const [, itemType, itemsStr] = type.split(":");
|
|
368
|
+
if (!itemsStr) return [];
|
|
369
|
+
const items = itemsStr.split(",");
|
|
370
|
+
return items.map((item) => this.nativeToTyped(itemType, item));
|
|
371
|
+
}
|
|
372
|
+
return String(value);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
nativeToType(type) {
|
|
376
|
+
switch (type) {
|
|
377
|
+
case "string":
|
|
378
|
+
return "string";
|
|
379
|
+
case "uint8":
|
|
380
|
+
case "uint16":
|
|
381
|
+
case "uint32":
|
|
382
|
+
case "uint64":
|
|
383
|
+
case "biguint":
|
|
384
|
+
return "bigint";
|
|
385
|
+
case "boolean":
|
|
386
|
+
return "boolean";
|
|
387
|
+
case "address":
|
|
388
|
+
return "string";
|
|
389
|
+
case "hex":
|
|
390
|
+
return "string";
|
|
391
|
+
default:
|
|
392
|
+
return "string";
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
stringToTyped(value) {
|
|
396
|
+
const parts = value.split(WarpConstants.ArgParamsSeparator, 2);
|
|
397
|
+
if (parts.length < 2) {
|
|
398
|
+
return value;
|
|
399
|
+
}
|
|
400
|
+
const [type, stringValue] = parts;
|
|
401
|
+
switch (type) {
|
|
402
|
+
case "string":
|
|
403
|
+
return stringValue;
|
|
404
|
+
case "uint8":
|
|
405
|
+
case "uint16":
|
|
406
|
+
case "uint32":
|
|
407
|
+
case "uint64":
|
|
408
|
+
return BigInt(stringValue);
|
|
409
|
+
case "biguint":
|
|
410
|
+
return BigInt(stringValue);
|
|
411
|
+
case "boolean":
|
|
412
|
+
return stringValue === "true";
|
|
413
|
+
case "address":
|
|
414
|
+
return stringValue;
|
|
415
|
+
case "hex":
|
|
416
|
+
return stringValue;
|
|
417
|
+
default:
|
|
418
|
+
if (type.startsWith("list:")) {
|
|
419
|
+
const [, itemType, itemsStr] = type.split(":");
|
|
420
|
+
if (!itemsStr) return [];
|
|
421
|
+
const items = itemsStr.split(",");
|
|
422
|
+
return items.map((item) => this.stringToTyped(`${itemType}:${item}`));
|
|
423
|
+
}
|
|
424
|
+
return stringValue;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
parseNativeValue(type, value) {
|
|
428
|
+
switch (type) {
|
|
429
|
+
case "string":
|
|
430
|
+
return value;
|
|
431
|
+
case "uint8":
|
|
432
|
+
case "uint16":
|
|
433
|
+
case "uint32":
|
|
434
|
+
case "uint64":
|
|
435
|
+
case "biguint":
|
|
436
|
+
return BigInt(value);
|
|
437
|
+
case "boolean":
|
|
438
|
+
return value === "true";
|
|
439
|
+
case "address":
|
|
440
|
+
return value;
|
|
441
|
+
case "hex":
|
|
442
|
+
return value;
|
|
443
|
+
default:
|
|
444
|
+
return value;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// src/WarpEvmResults.ts
|
|
450
|
+
var WarpEvmResults = class {
|
|
451
|
+
constructor(config) {
|
|
452
|
+
this.config = config;
|
|
453
|
+
this.serializer = new WarpEvmSerializer();
|
|
454
|
+
}
|
|
455
|
+
async getTransactionExecutionResults(warp, tx) {
|
|
456
|
+
const success = tx.status === 1;
|
|
457
|
+
const gasUsed = tx.gasUsed?.toString() || "0";
|
|
458
|
+
const gasPrice = tx.gasPrice?.toString() || "0";
|
|
459
|
+
const blockNumber = tx.blockNumber?.toString() || "0";
|
|
460
|
+
const transactionHash = tx.hash;
|
|
461
|
+
const logs = tx.logs.map((log) => ({
|
|
462
|
+
address: log.address,
|
|
463
|
+
topics: log.topics,
|
|
464
|
+
data: log.data,
|
|
465
|
+
blockNumber: log.blockNumber?.toString() || "0",
|
|
466
|
+
transactionHash: log.transactionHash,
|
|
467
|
+
index: log.index?.toString() || "0"
|
|
468
|
+
}));
|
|
469
|
+
return {
|
|
470
|
+
success,
|
|
471
|
+
warp,
|
|
472
|
+
action: 0,
|
|
473
|
+
user: this.config.user?.wallets?.evm || null,
|
|
474
|
+
txHash: transactionHash,
|
|
475
|
+
next: null,
|
|
476
|
+
values: [transactionHash, blockNumber, gasUsed, gasPrice, ...logs.length > 0 ? logs : []],
|
|
477
|
+
results: {},
|
|
478
|
+
messages: {}
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
async extractQueryResults(warp, typedValues, actionIndex, inputs) {
|
|
482
|
+
const values = typedValues.map((t) => this.serializer.typedToString(t));
|
|
483
|
+
const valuesRaw = typedValues.map((t) => this.serializer.typedToNative(t)[1]);
|
|
484
|
+
let results = {};
|
|
485
|
+
if (!warp.results) return { values, results };
|
|
486
|
+
const getNestedValue = (path) => {
|
|
487
|
+
const indices = path.split(".").slice(1).map((i) => parseInt(i) - 1);
|
|
488
|
+
if (indices.length === 0) return void 0;
|
|
489
|
+
let value = valuesRaw[indices[0]];
|
|
490
|
+
for (let i = 1; i < indices.length; i++) {
|
|
491
|
+
if (value === void 0 || value === null) return void 0;
|
|
492
|
+
value = value[indices[i]];
|
|
493
|
+
}
|
|
494
|
+
return value;
|
|
495
|
+
};
|
|
496
|
+
for (const [key, path] of Object.entries(warp.results)) {
|
|
497
|
+
if (path.startsWith(WarpConstants2.Transform.Prefix)) continue;
|
|
498
|
+
const currentActionIndex = parseResultsOutIndex(path);
|
|
499
|
+
if (currentActionIndex !== null && currentActionIndex !== actionIndex) {
|
|
500
|
+
results[key] = null;
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
if (path.startsWith("out.") || path === "out" || path.startsWith("out[")) {
|
|
504
|
+
results[key] = getNestedValue(path) || null;
|
|
505
|
+
} else {
|
|
506
|
+
results[key] = path;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return { values, results: await evaluateResultsCommon(warp, results, actionIndex, inputs) };
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
// src/WarpEvmExecutor.ts
|
|
514
|
+
var WarpEvmExecutor = class {
|
|
515
|
+
constructor(config) {
|
|
516
|
+
this.config = config;
|
|
517
|
+
this.serializer = new WarpEvmSerializer();
|
|
518
|
+
this.provider = new ethers3.JsonRpcProvider(getEvmApiUrl(config.env));
|
|
519
|
+
this.results = new WarpEvmResults(config);
|
|
520
|
+
}
|
|
521
|
+
async createTransaction(executable) {
|
|
522
|
+
const action = getWarpActionByIndex(executable.warp, executable.action);
|
|
523
|
+
let tx = null;
|
|
524
|
+
if (action.type === "transfer") {
|
|
525
|
+
tx = await this.createTransferTransaction(executable);
|
|
526
|
+
} else if (action.type === "contract") {
|
|
527
|
+
tx = await this.createContractCallTransaction(executable);
|
|
528
|
+
} else if (action.type === "query") {
|
|
529
|
+
throw new Error("WarpEvmExecutor: Invalid action type for createTransaction; Use executeQuery instead");
|
|
530
|
+
} else if (action.type === "collect") {
|
|
531
|
+
throw new Error("WarpEvmExecutor: Invalid action type for createTransaction; Use executeCollect instead");
|
|
532
|
+
}
|
|
533
|
+
if (!tx) throw new Error(`WarpEvmExecutor: Invalid action type (${action.type})`);
|
|
534
|
+
return tx;
|
|
535
|
+
}
|
|
536
|
+
async createTransferTransaction(executable) {
|
|
537
|
+
const userWallet = this.config.user?.wallets?.[executable.chain.name];
|
|
538
|
+
if (!userWallet) throw new Error("WarpEvmExecutor: createTransfer - user address not set");
|
|
539
|
+
if (!ethers3.isAddress(executable.destination)) {
|
|
540
|
+
throw new Error(`WarpEvmExecutor: Invalid destination address: ${executable.destination}`);
|
|
541
|
+
}
|
|
542
|
+
if (executable.value < 0) {
|
|
543
|
+
throw new Error(`WarpEvmExecutor: Transfer value cannot be negative: ${executable.value}`);
|
|
544
|
+
}
|
|
545
|
+
const tx = {
|
|
546
|
+
to: executable.destination,
|
|
547
|
+
value: executable.value,
|
|
548
|
+
data: executable.data ? this.serializer.stringToTyped(executable.data) : "0x"
|
|
549
|
+
};
|
|
550
|
+
return this.estimateGasAndSetDefaults(tx, userWallet);
|
|
551
|
+
}
|
|
552
|
+
async createContractCallTransaction(executable) {
|
|
553
|
+
const userWallet = this.config.user?.wallets?.[executable.chain.name];
|
|
554
|
+
if (!userWallet) throw new Error("WarpEvmExecutor: createContractCall - user address not set");
|
|
555
|
+
const action = getWarpActionByIndex(executable.warp, executable.action);
|
|
556
|
+
if (!action || !("func" in action) || !action.func) {
|
|
557
|
+
throw new Error("WarpEvmExecutor: Contract action must have a function name");
|
|
558
|
+
}
|
|
559
|
+
if (!ethers3.isAddress(executable.destination)) {
|
|
560
|
+
throw new Error(`WarpEvmExecutor: Invalid contract address: ${executable.destination}`);
|
|
561
|
+
}
|
|
562
|
+
if (executable.value < 0) {
|
|
563
|
+
throw new Error(`WarpEvmExecutor: Contract call value cannot be negative: ${executable.value}`);
|
|
564
|
+
}
|
|
565
|
+
try {
|
|
566
|
+
const iface = new ethers3.Interface([`function ${action.func}`]);
|
|
567
|
+
const encodedData = iface.encodeFunctionData(action.func, executable.args);
|
|
568
|
+
const tx = {
|
|
569
|
+
to: executable.destination,
|
|
570
|
+
value: executable.value,
|
|
571
|
+
data: encodedData
|
|
572
|
+
};
|
|
573
|
+
return this.estimateGasAndSetDefaults(tx, userWallet);
|
|
574
|
+
} catch (error) {
|
|
575
|
+
throw new Error(`WarpEvmExecutor: Failed to encode function data for ${action.func}: ${error}`);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
async executeQuery(executable) {
|
|
579
|
+
const action = getWarpActionByIndex(executable.warp, executable.action);
|
|
580
|
+
if (action.type !== "query") {
|
|
581
|
+
throw new Error(`WarpEvmExecutor: Invalid action type for executeQuery: ${action.type}`);
|
|
582
|
+
}
|
|
583
|
+
if (!action.func) {
|
|
584
|
+
throw new Error("WarpEvmExecutor: Query action must have a function name");
|
|
585
|
+
}
|
|
586
|
+
if (!ethers3.isAddress(executable.destination)) {
|
|
587
|
+
throw new Error(`WarpEvmExecutor: Invalid contract address for query: ${executable.destination}`);
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
const iface = new ethers3.Interface([`function ${action.func}`]);
|
|
591
|
+
const encodedData = iface.encodeFunctionData(action.func, executable.args);
|
|
592
|
+
const result = await this.provider.call({
|
|
593
|
+
to: executable.destination,
|
|
594
|
+
data: encodedData
|
|
595
|
+
});
|
|
596
|
+
const decodedResult = iface.decodeFunctionResult(action.func, result);
|
|
597
|
+
const isSuccess = true;
|
|
598
|
+
const { values, results } = await this.results.extractQueryResults(
|
|
599
|
+
executable.warp,
|
|
600
|
+
decodedResult,
|
|
601
|
+
executable.action,
|
|
602
|
+
executable.resolvedInputs
|
|
603
|
+
);
|
|
604
|
+
const adapter = getEvmAdapter(this.config);
|
|
605
|
+
const next = getNextInfo(this.config, adapter, executable.warp, executable.action, results);
|
|
606
|
+
return {
|
|
607
|
+
success: isSuccess,
|
|
608
|
+
warp: executable.warp,
|
|
609
|
+
action: executable.action,
|
|
610
|
+
user: this.config.user?.wallets?.[executable.chain.name] || null,
|
|
611
|
+
txHash: null,
|
|
612
|
+
next,
|
|
613
|
+
values,
|
|
614
|
+
results,
|
|
615
|
+
messages: applyResultsToMessages(executable.warp, results)
|
|
616
|
+
};
|
|
617
|
+
} catch (error) {
|
|
618
|
+
return {
|
|
619
|
+
success: false,
|
|
620
|
+
warp: executable.warp,
|
|
621
|
+
action: executable.action,
|
|
622
|
+
user: this.config.user?.wallets?.[executable.chain.name] || null,
|
|
623
|
+
txHash: null,
|
|
624
|
+
next: null,
|
|
625
|
+
values: [],
|
|
626
|
+
results: {},
|
|
627
|
+
messages: {}
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
async preprocessInput(chain, input, type, value) {
|
|
632
|
+
const typedValue = this.serializer.stringToTyped(value);
|
|
633
|
+
switch (type) {
|
|
634
|
+
case "address":
|
|
635
|
+
if (!ethers3.isAddress(typedValue)) {
|
|
636
|
+
throw new Error(`Invalid address format: ${typedValue}`);
|
|
637
|
+
}
|
|
638
|
+
return ethers3.getAddress(typedValue);
|
|
639
|
+
case "hex":
|
|
640
|
+
if (!ethers3.isHexString(typedValue)) {
|
|
641
|
+
throw new Error(`Invalid hex format: ${typedValue}`);
|
|
642
|
+
}
|
|
643
|
+
return typedValue;
|
|
644
|
+
case "uint8":
|
|
645
|
+
case "uint16":
|
|
646
|
+
case "uint32":
|
|
647
|
+
case "uint64":
|
|
648
|
+
case "biguint":
|
|
649
|
+
const bigIntValue = BigInt(typedValue);
|
|
650
|
+
if (bigIntValue < 0) {
|
|
651
|
+
throw new Error(`Negative value not allowed for type ${type}: ${typedValue}`);
|
|
652
|
+
}
|
|
653
|
+
return bigIntValue.toString();
|
|
654
|
+
default:
|
|
655
|
+
return String(typedValue);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
async estimateGasAndSetDefaults(tx, from) {
|
|
659
|
+
try {
|
|
660
|
+
const gasEstimate = await this.provider.estimateGas({
|
|
661
|
+
...tx,
|
|
662
|
+
from
|
|
663
|
+
});
|
|
664
|
+
if (gasEstimate < BigInt(WarpEvmConstants.Validation.MinGasLimit)) {
|
|
665
|
+
throw new Error(`Gas estimate too low: ${gasEstimate}`);
|
|
666
|
+
}
|
|
667
|
+
if (gasEstimate > BigInt(WarpEvmConstants.Validation.MaxGasLimit)) {
|
|
668
|
+
throw new Error(`Gas estimate too high: ${gasEstimate}`);
|
|
669
|
+
}
|
|
670
|
+
const feeData = await this.provider.getFeeData();
|
|
671
|
+
if (feeData.maxFeePerGas && feeData.maxPriorityFeePerGas) {
|
|
672
|
+
return {
|
|
673
|
+
...tx,
|
|
674
|
+
gasLimit: gasEstimate,
|
|
675
|
+
maxFeePerGas: feeData.maxFeePerGas,
|
|
676
|
+
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
|
|
677
|
+
};
|
|
678
|
+
} else if (feeData.gasPrice) {
|
|
679
|
+
return {
|
|
680
|
+
...tx,
|
|
681
|
+
gasLimit: gasEstimate,
|
|
682
|
+
gasPrice: feeData.gasPrice
|
|
683
|
+
};
|
|
684
|
+
} else {
|
|
685
|
+
return {
|
|
686
|
+
...tx,
|
|
687
|
+
gasLimit: gasEstimate,
|
|
688
|
+
gasPrice: ethers3.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
} catch (error) {
|
|
692
|
+
let defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.Default);
|
|
693
|
+
if (tx.data && tx.data !== "0x") {
|
|
694
|
+
defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.ContractCall);
|
|
695
|
+
} else {
|
|
696
|
+
defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.Transfer);
|
|
697
|
+
}
|
|
698
|
+
return {
|
|
699
|
+
...tx,
|
|
700
|
+
gasLimit: defaultGasLimit,
|
|
701
|
+
gasPrice: ethers3.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
async signMessage(message, privateKey) {
|
|
706
|
+
throw new Error("Not implemented");
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
// src/WarpEvmExplorer.ts
|
|
711
|
+
var WarpEvmExplorer = class {
|
|
712
|
+
constructor(chainInfo, chainName = "ethereum") {
|
|
713
|
+
this.chainInfo = chainInfo;
|
|
714
|
+
this.chainName = chainName;
|
|
715
|
+
}
|
|
716
|
+
getAccountUrl(address) {
|
|
717
|
+
const baseUrl = this.chainInfo.explorerUrl || getEvmExplorerUrl("mainnet", this.chainName);
|
|
718
|
+
return `${baseUrl}/address/${address}`;
|
|
719
|
+
}
|
|
720
|
+
getTransactionUrl(hash) {
|
|
721
|
+
const baseUrl = this.chainInfo.explorerUrl || getEvmExplorerUrl("mainnet", this.chainName);
|
|
722
|
+
return `${baseUrl}/tx/${hash}`;
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
// src/main.ts
|
|
727
|
+
var getEvmAdapter = (config, fallback) => {
|
|
728
|
+
if (!fallback) throw new Error("EVM adapter requires a fallback adapter");
|
|
729
|
+
return {
|
|
730
|
+
chain: WarpEvmConstants.ChainName,
|
|
731
|
+
prefix: WarpEvmConstants.ChainPrefix,
|
|
732
|
+
builder: () => new WarpEvmBuilder(config),
|
|
733
|
+
executor: new WarpEvmExecutor(config),
|
|
734
|
+
results: new WarpEvmResults(config),
|
|
735
|
+
serializer: new WarpEvmSerializer(),
|
|
736
|
+
registry: fallback.registry,
|
|
737
|
+
explorer: (chainInfo) => new WarpEvmExplorer(chainInfo),
|
|
738
|
+
abiBuilder: () => fallback.abiBuilder(),
|
|
739
|
+
brandBuilder: () => fallback.brandBuilder()
|
|
740
|
+
};
|
|
741
|
+
};
|
|
742
|
+
export {
|
|
743
|
+
EVM_CHAIN_CONFIGS,
|
|
744
|
+
WarpEvmBuilder,
|
|
745
|
+
WarpEvmConstants,
|
|
746
|
+
WarpEvmExecutor,
|
|
747
|
+
WarpEvmExplorer,
|
|
748
|
+
WarpEvmResults,
|
|
749
|
+
WarpEvmSerializer,
|
|
750
|
+
getEvmAdapter,
|
|
751
|
+
getEvmApiUrl,
|
|
752
|
+
getEvmBlockTime,
|
|
753
|
+
getEvmChainConfig,
|
|
754
|
+
getEvmChainId,
|
|
755
|
+
getEvmExplorerUrl,
|
|
756
|
+
getEvmNativeToken,
|
|
757
|
+
getEvmRegistryAddress,
|
|
758
|
+
getSupportedEnvironments,
|
|
759
|
+
getSupportedEvmChains
|
|
760
|
+
};
|
|
761
|
+
//# sourceMappingURL=index.mjs.map
|