@vleap/warps-adapter-evm 0.2.0-alpha.3 → 0.2.0-alpha.30

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.mjs CHANGED
@@ -1,298 +1,551 @@
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
1
+ // src/chains/arbitrum.ts
2
+ import { WarpChainName as WarpChainName6 } from "@vleap/warps";
3
+
4
+ // src/WarpEvmDataLoader.ts
5
+ import {
6
+ CacheTtl as CacheTtl2,
7
+ getProviderUrl,
8
+ WarpCache as WarpCache2,
9
+ WarpCacheKey
10
+ } from "@vleap/warps";
11
+ import { ethers } from "ethers";
12
+
13
+ // src/providers/UniswapService.ts
14
+ import { CacheTtl } from "@vleap/warps";
15
+ var _UniswapService = class _UniswapService {
16
+ constructor(cache, chainId) {
17
+ this.cache = cache;
18
+ this.chainId = chainId;
19
+ }
20
+ async getTokenList() {
21
+ try {
22
+ const response = await fetch(_UniswapService.UNISWAP_TOKEN_LIST_URL);
23
+ if (!response.ok) {
24
+ throw new Error(`Failed to fetch Uniswap token list: ${response.status}`);
25
+ }
26
+ const tokenList = await response.json();
27
+ return tokenList;
28
+ } catch (error) {
29
+ throw new Error(`Failed to fetch Uniswap token list: ${error}`);
27
30
  }
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
31
+ }
32
+ async findToken(address) {
33
+ const normalizedAddress = address.toLowerCase();
34
+ const cacheKey = `uniswap:token:${this.chainId}:${normalizedAddress}`;
35
+ const cachedToken = this.cache.get(cacheKey);
36
+ if (cachedToken) {
37
+ return cachedToken;
53
38
  }
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
39
+ try {
40
+ const tokenList = await this.getTokenList();
41
+ const token = tokenList.tokens.find((token2) => token2.address.toLowerCase() === normalizedAddress) || null;
42
+ if (token && token.chainId !== this.chainId) {
43
+ return null;
44
+ }
45
+ if (token) {
46
+ this.cache.set(cacheKey, token, CacheTtl.OneHour);
47
+ } else {
48
+ this.cache.set(cacheKey, null, CacheTtl.OneMinute * 5);
49
+ }
50
+ return token;
51
+ } catch (error) {
52
+ return null;
79
53
  }
80
54
  }
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}`);
55
+ async getTokenMetadata(address) {
56
+ const normalizedAddress = address.toLowerCase();
57
+ const cacheKey = `uniswap:metadata:${this.chainId}:${normalizedAddress}`;
58
+ const cachedMetadata = this.cache.get(cacheKey);
59
+ if (cachedMetadata !== null) {
60
+ return cachedMetadata;
61
+ }
62
+ const token = await this.findToken(address);
63
+ if (!token) {
64
+ this.cache.set(cacheKey, null, CacheTtl.OneMinute * 5);
65
+ return null;
66
+ }
67
+ const metadata = {
68
+ name: token.name,
69
+ symbol: token.symbol,
70
+ decimals: token.decimals,
71
+ logoUrl: token.logoURI
72
+ };
73
+ this.cache.set(cacheKey, metadata, CacheTtl.OneHour);
74
+ return metadata;
91
75
  }
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 [];
76
+ async getBridgeInfo(address) {
77
+ const normalizedAddress = address.toLowerCase();
78
+ const cacheKey = `uniswap:bridge:${this.chainId}:${normalizedAddress}`;
79
+ const cachedBridgeInfo = this.cache.get(cacheKey);
80
+ if (cachedBridgeInfo !== null) {
81
+ return cachedBridgeInfo;
82
+ }
83
+ const token = await this.findToken(address);
84
+ if (!token?.extensions?.bridgeInfo) {
85
+ this.cache.set(cacheKey, null, CacheTtl.OneMinute * 5);
86
+ return null;
87
+ }
88
+ const bridgeInfo = {};
89
+ for (const [chainId, info] of Object.entries(token.extensions.bridgeInfo)) {
90
+ bridgeInfo[chainId] = info.tokenAddress;
91
+ }
92
+ this.cache.set(cacheKey, bridgeInfo, CacheTtl.OneHour);
93
+ return bridgeInfo;
119
94
  }
120
- return Object.keys(chainConfigs);
121
95
  };
96
+ _UniswapService.UNISWAP_TOKEN_LIST_URL = "https://tokens.uniswap.org";
97
+ var UniswapService = _UniswapService;
122
98
 
123
- // src/constants.ts
124
- var WarpEvmConstants = {
125
- // Native token configuration
126
- Ether: {
127
- Identifier: "ETH",
128
- DisplayName: "Ether",
129
- Decimals: 18
99
+ // src/tokens/arbitrum.ts
100
+ import { WarpChainName } from "@vleap/warps";
101
+ var ArbitrumChain = WarpChainName.Arbitrum;
102
+ var ArbitrumTokens = [
103
+ {
104
+ chain: ArbitrumChain,
105
+ identifier: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
106
+ name: "USD Coin",
107
+ symbol: "USDC",
108
+ decimals: 6,
109
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
130
110
  },
131
- // Gas configuration
132
- GasLimit: {
133
- Default: 21e3,
134
- ContractCall: 1e5,
135
- ContractDeploy: 5e5,
136
- Transfer: 21e3,
137
- Approve: 46e3,
138
- Swap: 2e5
111
+ {
112
+ chain: ArbitrumChain,
113
+ identifier: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
114
+ name: "Tether USD",
115
+ symbol: "USDT",
116
+ decimals: 6,
117
+ logoUrl: "https://assets.coingecko.com/coins/images/325/small/Tether.png"
139
118
  },
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
119
+ {
120
+ chain: ArbitrumChain,
121
+ identifier: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
122
+ name: "Wrapped Ether",
123
+ symbol: "WETH",
124
+ decimals: 18,
125
+ logoUrl: "https://assets.coingecko.com/coins/images/2518/small/weth.png"
126
+ }
127
+ ];
128
+
129
+ // src/tokens/base.ts
130
+ import { WarpChainName as WarpChainName2 } from "@vleap/warps";
131
+ var BaseChain = WarpChainName2.Base;
132
+ var BaseTokens = [
133
+ {
134
+ chain: BaseChain,
135
+ identifier: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
136
+ name: "USD Coin",
137
+ symbol: "USDC",
138
+ decimals: 6,
139
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
149
140
  },
150
- // Supported networks
151
- Networks: {
152
- Ethereum: {
153
- ChainId: "1",
154
- Name: "Ethereum",
155
- BlockTime: 12
156
- },
157
- Arbitrum: {
158
- ChainId: "42161",
159
- Name: "Arbitrum",
160
- BlockTime: 1
161
- },
162
- Base: {
163
- ChainId: "8453",
164
- Name: "Base",
165
- BlockTime: 2
166
- }
141
+ {
142
+ chain: BaseChain,
143
+ identifier: "0x4200000000000000000000000000000000000006",
144
+ name: "Wrapped Ether",
145
+ symbol: "WETH",
146
+ decimals: 18,
147
+ logoUrl: "https://assets.coingecko.com/coins/images/2518/small/weth.png"
167
148
  },
168
- // Validation rules
169
- Validation: {
170
- AddressLength: 42,
171
- HexPrefix: "0x",
172
- MinGasLimit: 21e3,
173
- MaxGasLimit: 3e7
149
+ {
150
+ chain: BaseChain,
151
+ identifier: "0x808456652fdb597867f38412077A9182bf77359F",
152
+ name: "Euro",
153
+ symbol: "EURC",
154
+ decimals: 6,
155
+ logoUrl: "https://assets.coingecko.com/coins/images/26045/standard/euro.png"
174
156
  },
175
- // Timeout configuration
176
- Timeouts: {
177
- DefaultRpcTimeout: 3e4,
178
- // 30 seconds
179
- GasEstimationTimeout: 1e4,
180
- // 10 seconds
181
- QueryTimeout: 15e3
182
- // 15 seconds
157
+ {
158
+ chain: BaseChain,
159
+ fidentifier: "0xcbB7C0006F23900c38EB856149F799620fcb8A4a",
160
+ name: "Coinbase Wrapped BTC",
161
+ symbol: "CBETH",
162
+ decimals: 8,
163
+ logoUrl: "https://assets.coingecko.com/coins/images/7598/small/wrapped_bitcoin_wbtc.png"
183
164
  }
184
- };
165
+ ];
185
166
 
186
- // src/WarpEvmBuilder.ts
187
- import { ethers } from "ethers";
188
- var WarpEvmBuilder = class {
189
- constructor(config) {
190
- this.config = config;
191
- this.warp = {};
192
- this.actions = [];
193
- }
194
- async createFromRaw(encoded) {
195
- try {
196
- const decoded = JSON.parse(encoded);
197
- return decoded;
198
- } catch (error) {
199
- throw new Error(`Failed to decode warp from raw data: ${error}`);
200
- }
201
- }
202
- setTitle(title) {
203
- this.warp.title = title;
204
- return this;
205
- }
206
- setDescription(description) {
207
- this.warp.description = description;
208
- return this;
167
+ // src/tokens/base-sepolia.ts
168
+ import { WarpChainName as WarpChainName3 } from "@vleap/warps";
169
+ var BaseChain2 = WarpChainName3.Base;
170
+ var BaseSepoliaTokens = [
171
+ {
172
+ chain: BaseChain2,
173
+ identifier: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
174
+ name: "USD",
175
+ symbol: "USDC",
176
+ decimals: 6,
177
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
178
+ },
179
+ {
180
+ chain: BaseChain2,
181
+ identifier: "0x808456652fdb597867f38412077A9182bf77359F",
182
+ name: "Euro",
183
+ symbol: "EURC",
184
+ decimals: 6,
185
+ logoUrl: "https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420"
186
+ },
187
+ {
188
+ chain: BaseChain2,
189
+ identifier: "0xcbB7C0006F23900c38EB856149F799620fcb8A4a",
190
+ name: "Wrapped Bitcoin",
191
+ symbol: "WBTC",
192
+ decimals: 8,
193
+ logoUrl: "https://assets.coingecko.com/coins/images/7598/small/wrapped_bitcoin_wbtc.png"
209
194
  }
210
- setPreview(preview) {
211
- this.warp.preview = preview;
212
- return this;
195
+ ];
196
+
197
+ // src/tokens/ethereum.ts
198
+ import { WarpChainName as WarpChainName4 } from "@vleap/warps";
199
+ var EthereumChain = WarpChainName4.Ethereum;
200
+ var EthereumTokens = [
201
+ {
202
+ chain: EthereumChain,
203
+ identifier: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
204
+ name: "USD Coin",
205
+ symbol: "USDC",
206
+ decimals: 6,
207
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
208
+ },
209
+ {
210
+ chain: EthereumChain,
211
+ identifier: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
212
+ name: "Tether USD",
213
+ symbol: "USDT",
214
+ decimals: 6,
215
+ logoUrl: "https://assets.coingecko.com/coins/images/325/small/Tether.png"
216
+ },
217
+ {
218
+ chain: EthereumChain,
219
+ identifier: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
220
+ name: "Wrapped Bitcoin",
221
+ symbol: "WBTC",
222
+ decimals: 8,
223
+ logoUrl: "https://assets.coingecko.com/coins/images/7598/small/wrapped_bitcoin_wbtc.png"
224
+ },
225
+ {
226
+ chain: EthereumChain,
227
+ identifier: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
228
+ name: "Wrapped Ether",
229
+ symbol: "WETH",
230
+ decimals: 18,
231
+ logoUrl: "https://assets.coingecko.com/coins/images/2518/small/weth.png"
232
+ },
233
+ {
234
+ chain: EthereumChain,
235
+ identifier: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
236
+ name: "Dai Stablecoin",
237
+ symbol: "DAI",
238
+ decimals: 18,
239
+ logoUrl: "https://assets.coingecko.com/coins/images/9956/small/4943.png"
213
240
  }
214
- setActions(actions) {
215
- this.actions = actions;
216
- return this;
241
+ ];
242
+
243
+ // src/tokens/ethereum-sepolia.ts
244
+ import { WarpChainName as WarpChainName5 } from "@vleap/warps";
245
+ var EthereumChain2 = WarpChainName5.Ethereum;
246
+ var EthereumSepoliaTokens = [
247
+ {
248
+ chain: EthereumChain2,
249
+ identifier: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
250
+ name: "USD Coin",
251
+ symbol: "USDC",
252
+ decimals: 6,
253
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
254
+ },
255
+ {
256
+ chain: EthereumChain2,
257
+ identifier: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06",
258
+ name: "Tether USD",
259
+ symbol: "USDT",
260
+ decimals: 6,
261
+ logoUrl: "https://assets.coingecko.com/coins/images/325/small/Tether.png"
262
+ },
263
+ {
264
+ chain: EthereumChain2,
265
+ identifier: "0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9",
266
+ name: "Wrapped Ether",
267
+ symbol: "WETH",
268
+ decimals: 18,
269
+ logoUrl: "https://assets.coingecko.com/coins/images/2518/small/weth.png"
217
270
  }
218
- addAction(action) {
219
- this.actions.push(action);
220
- return this;
271
+ ];
272
+
273
+ // src/tokens.ts
274
+ var KnownTokens = {
275
+ ethereum: {
276
+ mainnet: EthereumTokens,
277
+ testnet: EthereumSepoliaTokens,
278
+ devnet: EthereumSepoliaTokens
279
+ },
280
+ base: {
281
+ mainnet: BaseTokens,
282
+ testnet: BaseSepoliaTokens,
283
+ devnet: BaseSepoliaTokens
284
+ },
285
+ arbitrum: {
286
+ mainnet: ArbitrumTokens
221
287
  }
222
- async build() {
223
- if (!this.warp.title) {
224
- throw new Error("Warp title is required");
225
- }
226
- return {
227
- protocol: "warp",
228
- name: this.warp.name || "evm-warp",
229
- title: this.warp.title,
230
- description: this.warp.description || null,
231
- preview: this.warp.preview || null,
232
- actions: this.actions,
233
- meta: {
234
- chain: "evm",
235
- hash: ethers.keccak256(ethers.toUtf8Bytes(this.warp.title)),
236
- creator: this.config.user?.wallets?.evm || "",
237
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
238
- }
239
- };
288
+ };
289
+ var findKnownTokenById = (chain, env, id) => {
290
+ const chainTokens = KnownTokens[chain]?.[env] || [];
291
+ return chainTokens.find((token) => token.identifier === id) || null;
292
+ };
293
+ var getKnownTokensForChain = (chainName, env = "mainnet") => {
294
+ return KnownTokens[chainName]?.[env] || [];
295
+ };
296
+
297
+ // src/WarpEvmDataLoader.ts
298
+ var ERC20_ABI = [
299
+ "function balanceOf(address owner) view returns (uint256)",
300
+ "function decimals() view returns (uint8)",
301
+ "function name() view returns (string)",
302
+ "function symbol() view returns (string)",
303
+ "function totalSupply() view returns (uint256)"
304
+ ];
305
+ var WarpEvmDataLoader = class {
306
+ constructor(config, chain) {
307
+ this.config = config;
308
+ this.chain = chain;
309
+ const apiUrl = getProviderUrl(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
310
+ const network = new ethers.Network(this.chain.name, parseInt(this.chain.chainId));
311
+ this.provider = new ethers.JsonRpcProvider(apiUrl, network);
312
+ this.cache = new WarpCache2(config.cache?.type);
313
+ this.uniswapService = new UniswapService(this.cache, parseInt(this.chain.chainId));
240
314
  }
241
- createInscriptionTransaction(warp) {
242
- const warpData = JSON.stringify(warp);
243
- const data = ethers.toUtf8Bytes(warpData);
315
+ async getAccount(address) {
316
+ const balance = await this.provider.getBalance(address);
244
317
  return {
245
- data: ethers.hexlify(data)
318
+ chain: this.chain.name,
319
+ address,
320
+ balance
246
321
  };
247
322
  }
248
- async createFromTransaction(tx, validate) {
249
- if (!tx.data || tx.data === "0x") {
250
- throw new Error("Transaction has no data");
323
+ async getAccountAssets(address) {
324
+ const account = await this.getAccount(address);
325
+ const tokenBalances = await this.getERC20TokenBalances(address);
326
+ let assets = account.balance > 0 ? [{ ...this.chain.nativeToken, amount: account.balance }] : [];
327
+ for (const tokenBalance of tokenBalances) {
328
+ if (tokenBalance.balance > 0n) {
329
+ assets.push({
330
+ chain: this.chain.name,
331
+ identifier: tokenBalance.tokenAddress,
332
+ name: tokenBalance.name,
333
+ symbol: tokenBalance.symbol,
334
+ amount: tokenBalance.balance,
335
+ decimals: tokenBalance.decimals,
336
+ logoUrl: tokenBalance.logoUrl || ""
337
+ });
338
+ }
251
339
  }
340
+ return assets;
341
+ }
342
+ async getAsset(identifier) {
252
343
  try {
253
- const data = ethers.toUtf8String(tx.data);
254
- const warp = JSON.parse(data);
255
- if (validate) {
256
- if (!warp.protocol || warp.protocol !== "warp") {
257
- throw new Error("Invalid warp protocol");
258
- }
259
- if (!warp.title) {
260
- throw new Error("Warp title is required");
261
- }
344
+ if (identifier === this.chain.nativeToken.identifier) {
345
+ return this.chain.nativeToken;
346
+ }
347
+ const cacheKey = WarpCacheKey.Asset(this.config.env, this.chain.name, identifier);
348
+ const cachedAsset = this.cache.get(cacheKey);
349
+ if (cachedAsset) {
350
+ return cachedAsset;
351
+ }
352
+ const knownToken = findKnownTokenById(this.chain.name, this.config.env, identifier);
353
+ if (knownToken) {
354
+ return {
355
+ chain: this.chain.name,
356
+ identifier,
357
+ name: knownToken.name,
358
+ symbol: knownToken.symbol,
359
+ amount: 0n,
360
+ decimals: knownToken.decimals,
361
+ logoUrl: knownToken.logoUrl
362
+ };
262
363
  }
263
- return warp;
364
+ const metadata = await this.getTokenMetadata(identifier);
365
+ const asset = {
366
+ chain: this.chain.name,
367
+ identifier,
368
+ name: metadata.name,
369
+ symbol: metadata.symbol,
370
+ amount: 0n,
371
+ decimals: metadata.decimals,
372
+ logoUrl: metadata.logoUrl || ""
373
+ };
374
+ this.cache.set(cacheKey, asset, CacheTtl2.OneHour);
375
+ return asset;
264
376
  } catch (error) {
265
- throw new Error(`Failed to create warp from transaction: ${error}`);
377
+ return null;
266
378
  }
267
379
  }
268
- async createFromTransactionHash(hash, cache) {
380
+ async getAction(identifier, awaitCompleted = false) {
269
381
  try {
270
- const provider = new ethers.JsonRpcProvider(getEvmApiUrl(this.config.env));
271
- const tx = await provider.getTransaction(hash);
272
- if (!tx) {
273
- return null;
274
- }
275
- return await this.createFromTransaction(tx);
382
+ const tx = await this.provider.getTransaction(identifier);
383
+ if (!tx) return null;
384
+ const receipt = await this.provider.getTransactionReceipt(identifier);
385
+ const block = await this.provider.getBlock(tx.blockNumber || "latest");
386
+ return {
387
+ chain: this.chain.name,
388
+ id: tx.hash || identifier,
389
+ receiver: tx.to || "",
390
+ sender: tx.from,
391
+ value: tx.value,
392
+ function: tx.data && tx.data !== "0x" ? "contract_call" : "",
393
+ status: receipt?.status === 1 ? "success" : receipt?.status === 0 ? "failed" : "pending",
394
+ createdAt: block?.timestamp ? new Date(Number(block.timestamp) * 1e3).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
395
+ error: receipt?.status === 0 ? "Transaction failed" : null,
396
+ tx: {
397
+ hash: tx.hash || "",
398
+ from: tx.from,
399
+ to: tx.to || "",
400
+ value: tx.value.toString(),
401
+ data: tx.data || "0x",
402
+ gasLimit: tx.gasLimit?.toString() || "0",
403
+ gasPrice: tx.gasPrice?.toString() || "0",
404
+ blockNumber: tx.blockNumber || 0,
405
+ blockHash: tx.blockHash || "",
406
+ transactionIndex: tx.index || 0
407
+ }
408
+ };
276
409
  } catch (error) {
277
410
  return null;
278
411
  }
279
412
  }
413
+ async getAccountActions(address, options) {
414
+ return [];
415
+ }
416
+ async getERC20TokenBalances(address) {
417
+ const env = this.config.env === "mainnet" ? "mainnet" : "testnet";
418
+ const tokens = getKnownTokensForChain(this.chain.name, env);
419
+ const balanceReqs = tokens.map((token) => this.getTokenBalance(address, token.identifier).catch(() => 0n));
420
+ const balances = await Promise.all(balanceReqs);
421
+ return balances.map((balance, index) => ({ balance, token: tokens[index] })).filter(({ balance }) => balance > 0n).map(({ balance, token }) => ({
422
+ tokenAddress: token.identifier,
423
+ balance,
424
+ name: token.name,
425
+ symbol: token.symbol,
426
+ decimals: token.decimals || 18,
427
+ logoUrl: token.logoUrl || ""
428
+ }));
429
+ }
430
+ async getTokenBalance(address, tokenAddress) {
431
+ const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);
432
+ const balance = await contract.balanceOf(address);
433
+ return balance;
434
+ }
435
+ async getTokenMetadata(tokenAddress) {
436
+ const uniswapMetadata = await this.uniswapService.getTokenMetadata(tokenAddress);
437
+ if (uniswapMetadata) {
438
+ return uniswapMetadata;
439
+ }
440
+ const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider);
441
+ const [name, symbol, decimals] = await Promise.all([
442
+ contract.name().catch(() => "Unknown Token"),
443
+ contract.symbol().catch(() => "UNKNOWN"),
444
+ contract.decimals().catch(() => 18)
445
+ ]);
446
+ return {
447
+ name: name || "Unknown Token",
448
+ symbol: symbol || "UNKNOWN",
449
+ decimals: decimals || 18,
450
+ logoUrl: ""
451
+ };
452
+ }
280
453
  };
281
454
 
282
455
  // src/WarpEvmExecutor.ts
283
456
  import {
284
457
  applyResultsToMessages,
285
458
  getNextInfo,
286
- getWarpActionByIndex
459
+ getProviderUrl as getProviderUrl3,
460
+ getWarpActionByIndex,
461
+ getWarpWalletAddressFromConfig as getWarpWalletAddressFromConfig2
287
462
  } from "@vleap/warps";
288
- import { ethers as ethers3 } from "ethers";
463
+ import { ethers as ethers4 } from "ethers";
464
+
465
+ // src/constants.ts
466
+ var WarpEvmConstants = {
467
+ GasLimit: {
468
+ Default: 21e3,
469
+ ContractCall: 1e5,
470
+ ContractDeploy: 5e5,
471
+ Transfer: 21e3,
472
+ TokenTransfer: 65e3,
473
+ // ERC-20 transfer gas limit
474
+ Approve: 46e3,
475
+ Swap: 2e5
476
+ },
477
+ GasPrice: {
478
+ Default: "20000000000"
479
+ },
480
+ Validation: {
481
+ MinGasLimit: 21e3,
482
+ MaxGasLimit: 3e7
483
+ }
484
+ };
485
+ var EthereumExplorers = /* @__PURE__ */ ((EthereumExplorers2) => {
486
+ EthereumExplorers2["Etherscan"] = "etherscan";
487
+ EthereumExplorers2["EtherscanSepolia"] = "etherscan_sepolia";
488
+ EthereumExplorers2["Ethplorer"] = "ethplorer";
489
+ EthereumExplorers2["Blockscout"] = "blockscout";
490
+ EthereumExplorers2["BlockscoutSepolia"] = "blockscout_sepolia";
491
+ return EthereumExplorers2;
492
+ })(EthereumExplorers || {});
493
+ var ArbitrumExplorers = /* @__PURE__ */ ((ArbitrumExplorers2) => {
494
+ ArbitrumExplorers2["Arbiscan"] = "arbiscan";
495
+ ArbitrumExplorers2["ArbiscanSepolia"] = "arbiscan_sepolia";
496
+ ArbitrumExplorers2["BlockscoutArbitrum"] = "blockscout_arbitrum";
497
+ ArbitrumExplorers2["BlockscoutArbitrumSepolia"] = "blockscout_arbitrum_sepolia";
498
+ return ArbitrumExplorers2;
499
+ })(ArbitrumExplorers || {});
500
+ var BaseExplorers = /* @__PURE__ */ ((BaseExplorers2) => {
501
+ BaseExplorers2["Basescan"] = "basescan";
502
+ BaseExplorers2["BasescanSepolia"] = "basescan_sepolia";
503
+ BaseExplorers2["BlockscoutBase"] = "blockscout_base";
504
+ BaseExplorers2["BlockscoutBaseSepolia"] = "blockscout_base_sepolia";
505
+ return BaseExplorers2;
506
+ })(BaseExplorers || {});
507
+ var EvmExplorers = {
508
+ ethereum: {
509
+ mainnet: ["etherscan" /* Etherscan */, "ethplorer" /* Ethplorer */, "blockscout" /* Blockscout */],
510
+ testnet: ["etherscan_sepolia" /* EtherscanSepolia */, "blockscout_sepolia" /* BlockscoutSepolia */],
511
+ devnet: ["etherscan_sepolia" /* EtherscanSepolia */, "blockscout_sepolia" /* BlockscoutSepolia */]
512
+ },
513
+ arbitrum: {
514
+ mainnet: ["arbiscan" /* Arbiscan */, "blockscout_arbitrum" /* BlockscoutArbitrum */],
515
+ testnet: ["arbiscan_sepolia" /* ArbiscanSepolia */, "blockscout_arbitrum_sepolia" /* BlockscoutArbitrumSepolia */],
516
+ devnet: ["arbiscan_sepolia" /* ArbiscanSepolia */, "blockscout_arbitrum_sepolia" /* BlockscoutArbitrumSepolia */]
517
+ },
518
+ base: {
519
+ mainnet: ["basescan" /* Basescan */, "blockscout_base" /* BlockscoutBase */],
520
+ testnet: ["basescan_sepolia" /* BasescanSepolia */, "blockscout_base_sepolia" /* BlockscoutBaseSepolia */],
521
+ devnet: ["basescan_sepolia" /* BasescanSepolia */, "blockscout_base_sepolia" /* BlockscoutBaseSepolia */]
522
+ }
523
+ };
524
+ var ExplorerUrls = {
525
+ ["etherscan" /* Etherscan */]: "https://etherscan.io",
526
+ ["etherscan_sepolia" /* EtherscanSepolia */]: "https://sepolia.etherscan.io",
527
+ ["ethplorer" /* Ethplorer */]: "https://ethplorer.io",
528
+ ["blockscout" /* Blockscout */]: "https://eth.blockscout.com",
529
+ ["blockscout_sepolia" /* BlockscoutSepolia */]: "https://sepolia.blockscout.com",
530
+ ["arbiscan" /* Arbiscan */]: "https://arbiscan.io",
531
+ ["arbiscan_sepolia" /* ArbiscanSepolia */]: "https://sepolia.arbiscan.io",
532
+ ["blockscout_arbitrum" /* BlockscoutArbitrum */]: "https://arbitrum.blockscout.com",
533
+ ["blockscout_arbitrum_sepolia" /* BlockscoutArbitrumSepolia */]: "https://sepolia.blockscout.com",
534
+ ["basescan" /* Basescan */]: "https://basescan.org",
535
+ ["basescan_sepolia" /* BasescanSepolia */]: "https://sepolia.basescan.org",
536
+ ["blockscout_base" /* BlockscoutBase */]: "https://base.blockscout.com",
537
+ ["blockscout_base_sepolia" /* BlockscoutBaseSepolia */]: "https://sepolia.blockscout.com"
538
+ };
289
539
 
290
540
  // src/WarpEvmResults.ts
291
541
  import {
292
542
  evaluateResultsCommon,
543
+ getProviderUrl as getProviderUrl2,
544
+ getWarpWalletAddressFromConfig,
293
545
  parseResultsOutIndex,
294
546
  WarpConstants as WarpConstants2
295
547
  } from "@vleap/warps";
548
+ import { ethers as ethers3 } from "ethers";
296
549
 
297
550
  // src/WarpEvmSerializer.ts
298
551
  import {
@@ -451,9 +704,19 @@ var WarpEvmSerializer = class {
451
704
 
452
705
  // src/WarpEvmResults.ts
453
706
  var WarpEvmResults = class {
454
- constructor(config) {
707
+ constructor(config, chain) {
455
708
  this.config = config;
709
+ this.chain = chain;
456
710
  this.serializer = new WarpEvmSerializer();
711
+ if (this.chain) {
712
+ const apiUrl = getProviderUrl2(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
713
+ const network = new ethers3.Network(this.chain.name, parseInt(this.chain.chainId));
714
+ this.provider = new ethers3.JsonRpcProvider(apiUrl, network);
715
+ } else {
716
+ const apiUrl = getProviderUrl2(this.config, "ethereum", this.config.env, "https://ethereum-rpc.publicnode.com");
717
+ const network = new ethers3.Network("ethereum", 1);
718
+ this.provider = new ethers3.JsonRpcProvider(apiUrl, network);
719
+ }
457
720
  }
458
721
  async getTransactionExecutionResults(warp, tx) {
459
722
  const success = tx.status === 1;
@@ -473,10 +736,12 @@ var WarpEvmResults = class {
473
736
  success,
474
737
  warp,
475
738
  action: 0,
476
- user: this.config.user?.wallets?.evm || null,
739
+ user: getWarpWalletAddressFromConfig(this.config, "evm"),
477
740
  txHash: transactionHash,
741
+ tx,
478
742
  next: null,
479
743
  values: [transactionHash, blockNumber, gasUsed, gasPrice, ...logs.length > 0 ? logs : []],
744
+ valuesRaw: [transactionHash, blockNumber, gasUsed, gasPrice, ...logs.length > 0 ? logs : []],
480
745
  results: {},
481
746
  messages: {}
482
747
  };
@@ -485,7 +750,7 @@ var WarpEvmResults = class {
485
750
  const values = typedValues.map((t) => this.serializer.typedToString(t));
486
751
  const valuesRaw = typedValues.map((t) => this.serializer.typedToNative(t)[1]);
487
752
  let results = {};
488
- if (!warp.results) return { values, results };
753
+ if (!warp.results) return { values, valuesRaw, results };
489
754
  const getNestedValue = (path) => {
490
755
  const indices = path.split(".").slice(1).map((i) => parseInt(i) - 1);
491
756
  if (indices.length === 0) return void 0;
@@ -509,17 +774,42 @@ var WarpEvmResults = class {
509
774
  results[key] = path;
510
775
  }
511
776
  }
512
- return { values, results: await evaluateResultsCommon(warp, results, actionIndex, inputs) };
777
+ return { values, valuesRaw, results: await evaluateResultsCommon(warp, results, actionIndex, inputs) };
778
+ }
779
+ async getTransactionStatus(txHash) {
780
+ try {
781
+ const receipt = await this.provider.getTransactionReceipt(txHash);
782
+ if (!receipt) {
783
+ return { status: "pending" };
784
+ }
785
+ return {
786
+ status: receipt.status === 1 ? "confirmed" : "failed",
787
+ blockNumber: receipt.blockNumber,
788
+ gasUsed: receipt.gasUsed
789
+ };
790
+ } catch (error) {
791
+ throw new Error(`Failed to get transaction status: ${error}`);
792
+ }
793
+ }
794
+ async getTransactionReceipt(txHash) {
795
+ try {
796
+ return await this.provider.getTransactionReceipt(txHash);
797
+ } catch (error) {
798
+ return null;
799
+ }
513
800
  }
514
801
  };
515
802
 
516
803
  // src/WarpEvmExecutor.ts
517
804
  var WarpEvmExecutor = class {
518
- constructor(config) {
805
+ constructor(config, chain) {
519
806
  this.config = config;
807
+ this.chain = chain;
520
808
  this.serializer = new WarpEvmSerializer();
521
- this.provider = new ethers3.JsonRpcProvider(getEvmApiUrl(config.env));
522
- this.results = new WarpEvmResults(config);
809
+ const apiUrl = getProviderUrl3(this.config, chain.name, this.config.env, this.chain.defaultApiUrl);
810
+ const network = new ethers4.Network(this.chain.name, parseInt(this.chain.chainId));
811
+ this.provider = new ethers4.JsonRpcProvider(apiUrl, network);
812
+ this.results = new WarpEvmResults(config, this.chain);
523
813
  }
524
814
  async createTransaction(executable) {
525
815
  const action = getWarpActionByIndex(executable.warp, executable.action);
@@ -537,13 +827,13 @@ var WarpEvmExecutor = class {
537
827
  return tx;
538
828
  }
539
829
  async createTransferTransaction(executable) {
540
- const userWallet = this.config.user?.wallets?.[executable.chain.name];
830
+ const userWallet = getWarpWalletAddressFromConfig2(this.config, executable.chain.name);
541
831
  if (!userWallet) throw new Error("WarpEvmExecutor: createTransfer - user address not set");
542
- if (!ethers3.isAddress(executable.destination)) {
832
+ if (!ethers4.isAddress(executable.destination)) {
543
833
  throw new Error(`WarpEvmExecutor: Invalid destination address: ${executable.destination}`);
544
834
  }
545
- if (executable.value < 0) {
546
- throw new Error(`WarpEvmExecutor: Transfer value cannot be negative: ${executable.value}`);
835
+ if (executable.transfers && executable.transfers.length > 0) {
836
+ return this.createTokenTransferTransaction(executable, userWallet);
547
837
  }
548
838
  const tx = {
549
839
  to: executable.destination,
@@ -553,20 +843,17 @@ var WarpEvmExecutor = class {
553
843
  return this.estimateGasAndSetDefaults(tx, userWallet);
554
844
  }
555
845
  async createContractCallTransaction(executable) {
556
- const userWallet = this.config.user?.wallets?.[executable.chain.name];
846
+ const userWallet = getWarpWalletAddressFromConfig2(this.config, executable.chain.name);
557
847
  if (!userWallet) throw new Error("WarpEvmExecutor: createContractCall - user address not set");
558
848
  const action = getWarpActionByIndex(executable.warp, executable.action);
559
849
  if (!action || !("func" in action) || !action.func) {
560
850
  throw new Error("WarpEvmExecutor: Contract action must have a function name");
561
851
  }
562
- if (!ethers3.isAddress(executable.destination)) {
852
+ if (!ethers4.isAddress(executable.destination)) {
563
853
  throw new Error(`WarpEvmExecutor: Invalid contract address: ${executable.destination}`);
564
854
  }
565
- if (executable.value < 0) {
566
- throw new Error(`WarpEvmExecutor: Contract call value cannot be negative: ${executable.value}`);
567
- }
568
855
  try {
569
- const iface = new ethers3.Interface([`function ${action.func}`]);
856
+ const iface = new ethers4.Interface([`function ${action.func}`]);
570
857
  const encodedData = iface.encodeFunctionData(action.func, executable.args);
571
858
  const tx = {
572
859
  to: executable.destination,
@@ -578,6 +865,50 @@ var WarpEvmExecutor = class {
578
865
  throw new Error(`WarpEvmExecutor: Failed to encode function data for ${action.func}: ${error}`);
579
866
  }
580
867
  }
868
+ async createTokenTransferTransaction(executable, userWallet) {
869
+ if (executable.transfers.length === 0) {
870
+ throw new Error("WarpEvmExecutor: No transfers provided");
871
+ }
872
+ if (!this.chain.nativeToken?.identifier) {
873
+ throw new Error("WarpEvmExecutor: No native token defined for this chain");
874
+ }
875
+ const nativeTokenTransfers = executable.transfers.filter((transfer) => transfer.identifier === this.chain.nativeToken.identifier);
876
+ const erc20Transfers = executable.transfers.filter((transfer) => transfer.identifier !== this.chain.nativeToken.identifier);
877
+ if (nativeTokenTransfers.length === 1 && erc20Transfers.length === 0) {
878
+ const transfer = nativeTokenTransfers[0];
879
+ if (transfer.amount <= 0n) {
880
+ throw new Error("WarpEvmExecutor: Native token transfer amount must be positive");
881
+ }
882
+ const tx = {
883
+ to: executable.destination,
884
+ value: transfer.amount,
885
+ data: "0x"
886
+ };
887
+ return this.estimateGasAndSetDefaults(tx, userWallet);
888
+ }
889
+ if (nativeTokenTransfers.length === 0 && erc20Transfers.length === 1) {
890
+ return this.createSingleTokenTransfer(executable, erc20Transfers[0], userWallet);
891
+ }
892
+ if (executable.transfers.length > 1) {
893
+ throw new Error("WarpEvmExecutor: Multiple token transfers not yet supported");
894
+ }
895
+ throw new Error("WarpEvmExecutor: Invalid transfer configuration");
896
+ }
897
+ async createSingleTokenTransfer(executable, transfer, userWallet) {
898
+ if (!ethers4.isAddress(transfer.identifier)) {
899
+ throw new Error(`WarpEvmExecutor: Invalid token address: ${transfer.identifier}`);
900
+ }
901
+ const transferInterface = new ethers4.Interface(["function transfer(address to, uint256 amount) returns (bool)"]);
902
+ const encodedData = transferInterface.encodeFunctionData("transfer", [executable.destination, transfer.amount]);
903
+ const tx = {
904
+ to: transfer.identifier,
905
+ // Token contract address
906
+ value: 0n,
907
+ // No native token value for ERC-20 transfers
908
+ data: encodedData
909
+ };
910
+ return this.estimateGasAndSetDefaults(tx, userWallet);
911
+ }
581
912
  async executeQuery(executable) {
582
913
  const action = getWarpActionByIndex(executable.warp, executable.action);
583
914
  if (action.type !== "query") {
@@ -586,11 +917,11 @@ var WarpEvmExecutor = class {
586
917
  if (!action.func) {
587
918
  throw new Error("WarpEvmExecutor: Query action must have a function name");
588
919
  }
589
- if (!ethers3.isAddress(executable.destination)) {
920
+ if (!ethers4.isAddress(executable.destination)) {
590
921
  throw new Error(`WarpEvmExecutor: Invalid contract address for query: ${executable.destination}`);
591
922
  }
592
923
  try {
593
- const iface = new ethers3.Interface([`function ${action.func}`]);
924
+ const iface = new ethers4.Interface([`function ${action.func}`]);
594
925
  const encodedData = iface.encodeFunctionData(action.func, executable.args);
595
926
  const result = await this.provider.call({
596
927
  to: executable.destination,
@@ -598,33 +929,23 @@ var WarpEvmExecutor = class {
598
929
  });
599
930
  const decodedResult = iface.decodeFunctionResult(action.func, result);
600
931
  const isSuccess = true;
601
- const { values, results } = await this.results.extractQueryResults(
932
+ const { values, valuesRaw, results } = await this.results.extractQueryResults(
602
933
  executable.warp,
603
934
  decodedResult,
604
935
  executable.action,
605
936
  executable.resolvedInputs
606
937
  );
607
- const mockAdapter = {
608
- chain: "ethereum",
609
- prefix: "eth",
610
- builder: () => ({}),
611
- executor: {},
612
- results: {},
613
- serializer: {},
614
- registry: {},
615
- explorer: () => ({}),
616
- abiBuilder: () => ({}),
617
- brandBuilder: () => ({})
618
- };
619
- const next = getNextInfo(this.config, mockAdapter, executable.warp, executable.action, results);
938
+ const next = getNextInfo(this.config, [], executable.warp, executable.action, results);
620
939
  return {
621
940
  success: isSuccess,
622
941
  warp: executable.warp,
623
942
  action: executable.action,
624
- user: this.config.user?.wallets?.[executable.chain.name] || null,
943
+ user: getWarpWalletAddressFromConfig2(this.config, executable.chain.name),
625
944
  txHash: null,
945
+ tx: null,
626
946
  next,
627
947
  values,
948
+ valuesRaw,
628
949
  results,
629
950
  messages: applyResultsToMessages(executable.warp, results)
630
951
  };
@@ -633,42 +954,17 @@ var WarpEvmExecutor = class {
633
954
  success: false,
634
955
  warp: executable.warp,
635
956
  action: executable.action,
636
- user: this.config.user?.wallets?.[executable.chain.name] || null,
957
+ user: getWarpWalletAddressFromConfig2(this.config, executable.chain.name),
637
958
  txHash: null,
959
+ tx: null,
638
960
  next: null,
639
961
  values: [],
962
+ valuesRaw: [],
640
963
  results: {},
641
964
  messages: {}
642
965
  };
643
966
  }
644
967
  }
645
- async preprocessInput(chain, input, type, value) {
646
- const typedValue = this.serializer.stringToTyped(value);
647
- switch (type) {
648
- case "address":
649
- if (!ethers3.isAddress(typedValue)) {
650
- throw new Error(`Invalid address format: ${typedValue}`);
651
- }
652
- return ethers3.getAddress(typedValue);
653
- case "hex":
654
- if (!ethers3.isHexString(typedValue)) {
655
- throw new Error(`Invalid hex format: ${typedValue}`);
656
- }
657
- return typedValue;
658
- case "uint8":
659
- case "uint16":
660
- case "uint32":
661
- case "uint64":
662
- case "biguint":
663
- const bigIntValue = BigInt(typedValue);
664
- if (bigIntValue < 0) {
665
- throw new Error(`Negative value not allowed for type ${type}: ${typedValue}`);
666
- }
667
- return bigIntValue.toString();
668
- default:
669
- return String(typedValue);
670
- }
671
- }
672
968
  async estimateGasAndSetDefaults(tx, from) {
673
969
  try {
674
970
  const gasEstimate = await this.provider.estimateGas({
@@ -685,6 +981,7 @@ var WarpEvmExecutor = class {
685
981
  if (feeData.maxFeePerGas && feeData.maxPriorityFeePerGas) {
686
982
  return {
687
983
  ...tx,
984
+ chainId: BigInt(this.chain.chainId),
688
985
  gasLimit: gasEstimate,
689
986
  maxFeePerGas: feeData.maxFeePerGas,
690
987
  maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
@@ -692,97 +989,482 @@ var WarpEvmExecutor = class {
692
989
  } else if (feeData.gasPrice) {
693
990
  return {
694
991
  ...tx,
992
+ chainId: BigInt(this.chain.chainId),
695
993
  gasLimit: gasEstimate,
696
994
  gasPrice: feeData.gasPrice
697
995
  };
698
996
  } else {
699
997
  return {
700
998
  ...tx,
999
+ chainId: BigInt(this.chain.chainId),
701
1000
  gasLimit: gasEstimate,
702
- gasPrice: ethers3.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
1001
+ gasPrice: ethers4.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
703
1002
  };
704
1003
  }
705
1004
  } catch (error) {
706
1005
  let defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.Default);
707
1006
  if (tx.data && tx.data !== "0x") {
708
- defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.ContractCall);
1007
+ if (tx.data.startsWith("0xa9059cbb")) {
1008
+ defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.TokenTransfer);
1009
+ } else {
1010
+ defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.ContractCall);
1011
+ }
709
1012
  } else {
710
1013
  defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.Transfer);
711
1014
  }
712
1015
  return {
713
1016
  ...tx,
1017
+ chainId: BigInt(this.chain.chainId),
714
1018
  gasLimit: defaultGasLimit,
715
- gasPrice: ethers3.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
1019
+ gasPrice: ethers4.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
716
1020
  };
717
1021
  }
718
1022
  }
719
1023
  async signMessage(message, privateKey) {
720
- throw new Error("Not implemented");
1024
+ try {
1025
+ const wallet = new ethers4.Wallet(privateKey);
1026
+ const signature = await wallet.signMessage(message);
1027
+ return signature;
1028
+ } catch (error) {
1029
+ throw new Error(`Failed to sign message: ${error}`);
1030
+ }
1031
+ }
1032
+ async verifyMessage(message, signature) {
1033
+ try {
1034
+ const recoveredAddress = ethers4.verifyMessage(message, signature);
1035
+ return recoveredAddress;
1036
+ } catch (error) {
1037
+ throw new Error(`Failed to verify message: ${error}`);
1038
+ }
721
1039
  }
722
1040
  };
723
1041
 
724
1042
  // src/WarpEvmExplorer.ts
725
1043
  var WarpEvmExplorer = class {
726
- constructor(chainInfo, chainName = "ethereum") {
727
- this.chainInfo = chainInfo;
728
- this.chainName = chainName;
1044
+ constructor(chain, config) {
1045
+ this.chain = chain;
1046
+ this.config = config;
729
1047
  }
730
- getAccountUrl(address) {
731
- const baseUrl = this.chainInfo.explorerUrl || getEvmExplorerUrl("mainnet", this.chainName);
1048
+ getExplorers() {
1049
+ const chainExplorers = EvmExplorers[this.chain.name];
1050
+ if (!chainExplorers) {
1051
+ return ["Default"];
1052
+ }
1053
+ const explorers = chainExplorers[this.config.env];
1054
+ if (!explorers) {
1055
+ return ["Default"];
1056
+ }
1057
+ return explorers;
1058
+ }
1059
+ getPrimaryExplorer() {
1060
+ const explorers = this.getExplorers();
1061
+ return explorers[0];
1062
+ }
1063
+ getExplorerUrlByName(explorer) {
1064
+ const userPreference = this.config.preferences?.explorers?.[this.chain.name];
1065
+ if (userPreference && !explorer) {
1066
+ const url2 = ExplorerUrls[userPreference];
1067
+ if (url2) return url2;
1068
+ }
1069
+ if (explorer) {
1070
+ const url2 = ExplorerUrls[explorer];
1071
+ if (url2) return url2;
1072
+ }
1073
+ const primaryExplorer = this.getPrimaryExplorer();
1074
+ const url = ExplorerUrls[primaryExplorer];
1075
+ return url || ExplorerUrls[primaryExplorer];
1076
+ }
1077
+ getAccountUrl(address, explorer) {
1078
+ const baseUrl = this.getExplorerUrlByName(explorer);
732
1079
  return `${baseUrl}/address/${address}`;
733
1080
  }
734
- getTransactionUrl(hash) {
735
- const baseUrl = this.chainInfo.explorerUrl || getEvmExplorerUrl("mainnet", this.chainName);
1081
+ getTransactionUrl(hash, explorer) {
1082
+ const baseUrl = this.getExplorerUrlByName(explorer);
736
1083
  return `${baseUrl}/tx/${hash}`;
737
1084
  }
1085
+ getBlockUrl(blockNumber, explorer) {
1086
+ const baseUrl = this.getExplorerUrlByName(explorer);
1087
+ return `${baseUrl}/block/${blockNumber}`;
1088
+ }
1089
+ getAssetUrl(identifier, explorer) {
1090
+ const baseUrl = this.getExplorerUrlByName(explorer);
1091
+ return `${baseUrl}/token/${identifier}`;
1092
+ }
1093
+ getContractUrl(address, explorer) {
1094
+ const baseUrl = this.getExplorerUrlByName(explorer);
1095
+ return `${baseUrl}/address/${address}`;
1096
+ }
1097
+ getAllExplorers() {
1098
+ return this.getExplorers();
1099
+ }
1100
+ getExplorerByName(name) {
1101
+ const explorers = this.getExplorers();
1102
+ return explorers.find((explorer) => explorer.toLowerCase() === name.toLowerCase());
1103
+ }
1104
+ getAccountUrls(address) {
1105
+ const explorers = this.getAllExplorers();
1106
+ const urls = {};
1107
+ explorers.forEach((explorer) => {
1108
+ const url = ExplorerUrls[explorer];
1109
+ if (url) {
1110
+ urls[explorer] = `${url}/address/${address}`;
1111
+ }
1112
+ });
1113
+ return urls;
1114
+ }
1115
+ getTransactionUrls(hash) {
1116
+ const explorers = this.getAllExplorers();
1117
+ const urls = {};
1118
+ explorers.forEach((explorer) => {
1119
+ const url = ExplorerUrls[explorer];
1120
+ if (url) {
1121
+ urls[explorer] = `${url}/tx/${hash}`;
1122
+ }
1123
+ });
1124
+ return urls;
1125
+ }
1126
+ getAssetUrls(identifier) {
1127
+ const explorers = this.getAllExplorers();
1128
+ const urls = {};
1129
+ explorers.forEach((explorer) => {
1130
+ const url = ExplorerUrls[explorer];
1131
+ if (url) {
1132
+ urls[explorer] = `${url}/token/${identifier}`;
1133
+ }
1134
+ });
1135
+ return urls;
1136
+ }
1137
+ getContractUrls(address) {
1138
+ const explorers = this.getAllExplorers();
1139
+ const urls = {};
1140
+ explorers.forEach((explorer) => {
1141
+ const url = ExplorerUrls[explorer];
1142
+ if (url) {
1143
+ urls[explorer] = `${url}/address/${address}`;
1144
+ }
1145
+ });
1146
+ return urls;
1147
+ }
1148
+ getBlockUrls(blockNumber) {
1149
+ const explorers = this.getAllExplorers();
1150
+ const urls = {};
1151
+ explorers.forEach((explorer) => {
1152
+ const url = ExplorerUrls[explorer];
1153
+ if (url) {
1154
+ urls[explorer] = `${url}/block/${blockNumber}`;
1155
+ }
1156
+ });
1157
+ return urls;
1158
+ }
738
1159
  };
739
1160
 
740
- // src/main.ts
741
- var getEthereumAdapter = createEvmAdapter("ethereum", "eth");
742
- var getArbitrumAdapter = createEvmAdapter("arbitrum", "arb");
743
- var getBaseAdapter = createEvmAdapter("base", "base");
744
- var getAllEvmAdapters = (config, fallback) => [
745
- getEthereumAdapter(config, fallback),
746
- getArbitrumAdapter(config, fallback),
747
- getBaseAdapter(config, fallback)
748
- ];
749
- function createEvmAdapter(chainName, chainPrefix) {
1161
+ // src/WarpEvmWallet.ts
1162
+ import { getWarpWalletPrivateKeyFromConfig } from "@vleap/warps";
1163
+ import { ethers as ethers5 } from "ethers";
1164
+ var WarpEvmWallet = class {
1165
+ constructor(config, chain) {
1166
+ this.config = config;
1167
+ this.chain = chain;
1168
+ this.wallet = null;
1169
+ this.provider = new ethers5.JsonRpcProvider(chain.defaultApiUrl || "https://rpc.sepolia.org");
1170
+ }
1171
+ async signTransaction(tx) {
1172
+ if (!tx || typeof tx !== "object") {
1173
+ throw new Error("Invalid transaction object");
1174
+ }
1175
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1176
+ if (!privateKey) throw new Error("Wallet not initialized - no private key provided");
1177
+ const wallet = new ethers5.Wallet(privateKey);
1178
+ const txRequest = {
1179
+ to: tx.to,
1180
+ data: tx.data,
1181
+ value: tx.value || 0,
1182
+ gasLimit: tx.gasLimit,
1183
+ maxFeePerGas: tx.maxFeePerGas,
1184
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
1185
+ nonce: tx.nonce,
1186
+ chainId: tx.chainId
1187
+ };
1188
+ const signedTx = await wallet.signTransaction(txRequest);
1189
+ return { ...tx, signature: signedTx };
1190
+ }
1191
+ async signMessage(message) {
1192
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1193
+ if (!privateKey) throw new Error("Wallet not initialized - no private key provided");
1194
+ const wallet = new ethers5.Wallet(privateKey);
1195
+ return await wallet.signMessage(message);
1196
+ }
1197
+ async sendTransaction(tx) {
1198
+ if (!tx || typeof tx !== "object") {
1199
+ throw new Error("Invalid transaction object");
1200
+ }
1201
+ if (!tx.signature) {
1202
+ throw new Error("Transaction must be signed before sending");
1203
+ }
1204
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1205
+ if (!privateKey) throw new Error("Wallet not initialized - no private key provided");
1206
+ const wallet = new ethers5.Wallet(privateKey).connect(this.provider);
1207
+ const txResponse = await wallet.sendTransaction(tx);
1208
+ return txResponse.hash;
1209
+ }
1210
+ create(mnemonic) {
1211
+ const wallet = ethers5.Wallet.fromPhrase(mnemonic);
1212
+ return { address: wallet.address, privateKey: wallet.privateKey, mnemonic };
1213
+ }
1214
+ generate() {
1215
+ const wallet = ethers5.Wallet.createRandom();
1216
+ return { address: wallet.address, privateKey: wallet.privateKey, mnemonic: wallet.mnemonic?.phrase || "" };
1217
+ }
1218
+ getAddress() {
1219
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1220
+ if (!privateKey) return null;
1221
+ const wallet = new ethers5.Wallet(privateKey);
1222
+ return wallet.address;
1223
+ }
1224
+ };
1225
+
1226
+ // src/chains/common.ts
1227
+ var createEvmAdapter = (chainName, chainPrefix, chainInfos) => {
750
1228
  return (config, fallback) => {
751
1229
  if (!fallback) throw new Error(`${chainName} adapter requires a fallback adapter`);
752
1230
  return {
753
1231
  chain: chainName,
1232
+ chainInfo: chainInfos[config.env],
754
1233
  prefix: chainPrefix,
755
- builder: () => new WarpEvmBuilder(config),
756
- executor: new WarpEvmExecutor(config),
757
- results: new WarpEvmResults(config),
1234
+ builder: () => fallback.builder(),
1235
+ executor: new WarpEvmExecutor(config, chainInfos[config.env]),
1236
+ results: new WarpEvmResults(config, chainInfos[config.env]),
758
1237
  serializer: new WarpEvmSerializer(),
759
1238
  registry: fallback.registry,
760
- explorer: (chainInfo) => new WarpEvmExplorer(chainInfo),
1239
+ explorer: new WarpEvmExplorer(chainInfos[config.env], config),
761
1240
  abiBuilder: () => fallback.abiBuilder(),
762
- brandBuilder: () => fallback.brandBuilder()
1241
+ brandBuilder: () => fallback.brandBuilder(),
1242
+ dataLoader: new WarpEvmDataLoader(config, chainInfos[config.env]),
1243
+ wallet: new WarpEvmWallet(config, chainInfos[config.env])
763
1244
  };
764
1245
  };
765
- }
1246
+ };
1247
+
1248
+ // src/chains/arbitrum.ts
1249
+ var NativeTokenArb = {
1250
+ chain: WarpChainName6.Arbitrum,
1251
+ identifier: "ARB",
1252
+ symbol: "ARB",
1253
+ name: "Arbitrum",
1254
+ decimals: 18,
1255
+ logoUrl: "https://vleap.ai/images/tokens/arb.svg"
1256
+ };
1257
+ var getArbitrumAdapter = createEvmAdapter(WarpChainName6.Arbitrum, "arb", {
1258
+ mainnet: {
1259
+ name: WarpChainName6.Arbitrum,
1260
+ displayName: "Arbitrum",
1261
+ chainId: "42161",
1262
+ blockTime: 1e3,
1263
+ addressHrp: "0x",
1264
+ defaultApiUrl: "https://arb1.arbitrum.io/rpc",
1265
+ logoUrl: "https://vleap.ai/images/chains/arbitrum.svg",
1266
+ nativeToken: NativeTokenArb
1267
+ },
1268
+ testnet: {
1269
+ name: WarpChainName6.Arbitrum,
1270
+ displayName: "Arbitrum Sepolia",
1271
+ chainId: "421614",
1272
+ blockTime: 1e3,
1273
+ addressHrp: "0x",
1274
+ defaultApiUrl: "https://sepolia-rollup.arbitrum.io/rpc",
1275
+ logoUrl: "https://vleap.ai/images/chains/arbitrum.svg",
1276
+ nativeToken: NativeTokenArb
1277
+ },
1278
+ devnet: {
1279
+ name: WarpChainName6.Arbitrum,
1280
+ displayName: "Arbitrum Sepolia",
1281
+ chainId: "421614",
1282
+ blockTime: 1e3,
1283
+ addressHrp: "0x",
1284
+ defaultApiUrl: "https://sepolia-rollup.arbitrum.io/rpc",
1285
+ logoUrl: "https://vleap.ai/images/chains/arbitrum.svg",
1286
+ nativeToken: NativeTokenArb
1287
+ }
1288
+ });
1289
+
1290
+ // src/chains/base.ts
1291
+ import { WarpChainName as WarpChainName7 } from "@vleap/warps";
1292
+ var NativeTokenBase = {
1293
+ chain: WarpChainName7.Base,
1294
+ identifier: "ETH",
1295
+ name: "Ether",
1296
+ symbol: "ETH",
1297
+ decimals: 18,
1298
+ logoUrl: "https://vleap.ai/images/tokens/eth.svg"
1299
+ };
1300
+ var getBaseAdapter = createEvmAdapter(WarpChainName7.Base, "base", {
1301
+ mainnet: {
1302
+ name: WarpChainName7.Base,
1303
+ displayName: "Base",
1304
+ chainId: "8453",
1305
+ blockTime: 2e3,
1306
+ addressHrp: "0x",
1307
+ defaultApiUrl: "https://mainnet.base.org",
1308
+ logoUrl: "https://vleap.ai/images/chains/base.svg",
1309
+ nativeToken: NativeTokenBase
1310
+ },
1311
+ testnet: {
1312
+ name: WarpChainName7.Base,
1313
+ displayName: "Base Sepolia",
1314
+ chainId: "84532",
1315
+ blockTime: 2e3,
1316
+ addressHrp: "0x",
1317
+ defaultApiUrl: "https://sepolia.base.org",
1318
+ logoUrl: "https://vleap.ai/images/chains/base.svg",
1319
+ nativeToken: NativeTokenBase
1320
+ },
1321
+ devnet: {
1322
+ name: WarpChainName7.Base,
1323
+ displayName: "Base Sepolia",
1324
+ chainId: "84532",
1325
+ blockTime: 2e3,
1326
+ addressHrp: "0x",
1327
+ defaultApiUrl: "https://sepolia.base.org",
1328
+ logoUrl: "https://vleap.ai/images/chains/base.svg",
1329
+ nativeToken: NativeTokenBase
1330
+ }
1331
+ });
1332
+
1333
+ // src/chains/combined.ts
1334
+ import { WarpChainName as WarpChainName10 } from "@vleap/warps";
1335
+
1336
+ // src/chains/ethereum.ts
1337
+ import { WarpChainName as WarpChainName8 } from "@vleap/warps";
1338
+ var NativeTokenEth = {
1339
+ chain: WarpChainName8.Ethereum,
1340
+ identifier: "ETH",
1341
+ symbol: "ETH",
1342
+ name: "Ether",
1343
+ decimals: 18,
1344
+ logoUrl: "https://vleap.ai/images/tokens/eth.svg"
1345
+ };
1346
+ var getEthereumAdapter = createEvmAdapter(WarpChainName8.Ethereum, "eth", {
1347
+ mainnet: {
1348
+ name: WarpChainName8.Ethereum,
1349
+ displayName: "Ethereum Mainnet",
1350
+ chainId: "1",
1351
+ blockTime: 12e3,
1352
+ addressHrp: "0x",
1353
+ defaultApiUrl: "https://ethereum-rpc.publicnode.com",
1354
+ logoUrl: "https://vleap.ai/images/chains/ethereum.svg",
1355
+ nativeToken: NativeTokenEth
1356
+ },
1357
+ testnet: {
1358
+ name: WarpChainName8.Ethereum,
1359
+ displayName: "Ethereum Sepolia",
1360
+ chainId: "11155111",
1361
+ blockTime: 12e3,
1362
+ addressHrp: "0x",
1363
+ defaultApiUrl: "https://ethereum-sepolia-rpc.publicnode.com",
1364
+ logoUrl: "https://vleap.ai/images/chains/ethereum.svg",
1365
+ nativeToken: NativeTokenEth
1366
+ },
1367
+ devnet: {
1368
+ name: WarpChainName8.Ethereum,
1369
+ displayName: "Ethereum Sepolia",
1370
+ chainId: "11155111",
1371
+ blockTime: 12e3,
1372
+ addressHrp: "0x",
1373
+ defaultApiUrl: "https://ethereum-sepolia-rpc.publicnode.com",
1374
+ logoUrl: "https://vleap.ai/images/chains/ethereum.svg",
1375
+ nativeToken: NativeTokenEth
1376
+ }
1377
+ });
1378
+
1379
+ // src/chains/somnia.ts
1380
+ import { WarpChainName as WarpChainName9 } from "@vleap/warps";
1381
+ var NativeTokenSomi = {
1382
+ chain: WarpChainName9.Somnia,
1383
+ identifier: "SOMI",
1384
+ symbol: "SOMI",
1385
+ name: "Somnia",
1386
+ decimals: 18,
1387
+ logoUrl: "https://assets.coingecko.com/coins/images/68061/standard/somniacg.png?1754641117"
1388
+ };
1389
+ var NativeTokenStt = {
1390
+ chain: WarpChainName9.Somnia,
1391
+ identifier: "STT",
1392
+ symbol: "STT",
1393
+ name: "Somnia Testnet Token",
1394
+ decimals: 18,
1395
+ logoUrl: "https://assets.coingecko.com/coins/images/68061/standard/somniacg.png?1754641117"
1396
+ };
1397
+ var getSomniaAdapter = createEvmAdapter(WarpChainName9.Somnia, "eth", {
1398
+ mainnet: {
1399
+ name: WarpChainName9.Somnia,
1400
+ displayName: "Somnia Mainnet",
1401
+ chainId: "5031",
1402
+ blockTime: 100,
1403
+ addressHrp: "0x",
1404
+ defaultApiUrl: "https://api.infra.mainnet.somnia.network/",
1405
+ logoUrl: "https://vleap.ai/images/chains/somnia.png",
1406
+ nativeToken: NativeTokenSomi
1407
+ },
1408
+ testnet: {
1409
+ name: WarpChainName9.Somnia,
1410
+ displayName: "Somnia Testnet",
1411
+ chainId: "50312",
1412
+ blockTime: 100,
1413
+ addressHrp: "0x",
1414
+ defaultApiUrl: "https://dream-rpc.somnia.network/",
1415
+ logoUrl: "https://vleap.ai/images/chains/somnia.png",
1416
+ nativeToken: NativeTokenStt
1417
+ },
1418
+ devnet: {
1419
+ name: WarpChainName9.Somnia,
1420
+ displayName: "Somnia Testnet",
1421
+ chainId: "50312",
1422
+ blockTime: 100,
1423
+ addressHrp: "0x",
1424
+ defaultApiUrl: "https://dream-rpc.somnia.network",
1425
+ logoUrl: "https://vleap.ai/images/chains/somnia.png",
1426
+ nativeToken: NativeTokenStt
1427
+ }
1428
+ });
1429
+
1430
+ // src/chains/combined.ts
1431
+ var getAllEvmAdapters = (config, fallback) => [
1432
+ getEthereumAdapter(config, fallback),
1433
+ getBaseAdapter(config, fallback),
1434
+ getArbitrumAdapter(config, fallback),
1435
+ getSomniaAdapter(config, fallback)
1436
+ ];
1437
+ var getAllEvmChainNames = () => [
1438
+ WarpChainName10.Ethereum,
1439
+ WarpChainName10.Base,
1440
+ WarpChainName10.Arbitrum,
1441
+ WarpChainName10.Somnia
1442
+ ];
766
1443
  export {
767
- EVM_CHAIN_CONFIGS,
768
- WarpEvmBuilder,
1444
+ ArbitrumExplorers,
1445
+ BaseExplorers,
1446
+ EthereumExplorers,
1447
+ EvmExplorers,
1448
+ ExplorerUrls,
1449
+ KnownTokens,
1450
+ NativeTokenArb,
1451
+ NativeTokenBase,
1452
+ NativeTokenEth,
1453
+ UniswapService,
769
1454
  WarpEvmConstants,
1455
+ WarpEvmDataLoader,
770
1456
  WarpEvmExecutor,
771
1457
  WarpEvmExplorer,
772
1458
  WarpEvmResults,
773
1459
  WarpEvmSerializer,
1460
+ WarpEvmWallet,
1461
+ createEvmAdapter,
1462
+ findKnownTokenById,
774
1463
  getAllEvmAdapters,
1464
+ getAllEvmChainNames,
775
1465
  getArbitrumAdapter,
776
1466
  getBaseAdapter,
777
1467
  getEthereumAdapter,
778
- getEvmApiUrl,
779
- getEvmBlockTime,
780
- getEvmChainConfig,
781
- getEvmChainId,
782
- getEvmExplorerUrl,
783
- getEvmNativeToken,
784
- getEvmRegistryAddress,
785
- getSupportedEnvironments,
786
- getSupportedEvmChains
1468
+ getKnownTokensForChain
787
1469
  };
788
1470
  //# sourceMappingURL=index.mjs.map