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

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
+ identifier: "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,13 @@ 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
+ const apiUrl = getProviderUrl2(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
712
+ const network = new ethers3.Network(this.chain.name, parseInt(this.chain.chainId));
713
+ this.provider = new ethers3.JsonRpcProvider(apiUrl, network);
457
714
  }
458
715
  async getTransactionExecutionResults(warp, tx) {
459
716
  const success = tx.status === 1;
@@ -473,10 +730,12 @@ var WarpEvmResults = class {
473
730
  success,
474
731
  warp,
475
732
  action: 0,
476
- user: this.config.user?.wallets?.evm || null,
733
+ user: getWarpWalletAddressFromConfig(this.config, "evm"),
477
734
  txHash: transactionHash,
735
+ tx,
478
736
  next: null,
479
737
  values: [transactionHash, blockNumber, gasUsed, gasPrice, ...logs.length > 0 ? logs : []],
738
+ valuesRaw: [transactionHash, blockNumber, gasUsed, gasPrice, ...logs.length > 0 ? logs : []],
480
739
  results: {},
481
740
  messages: {}
482
741
  };
@@ -485,7 +744,7 @@ var WarpEvmResults = class {
485
744
  const values = typedValues.map((t) => this.serializer.typedToString(t));
486
745
  const valuesRaw = typedValues.map((t) => this.serializer.typedToNative(t)[1]);
487
746
  let results = {};
488
- if (!warp.results) return { values, results };
747
+ if (!warp.results) return { values, valuesRaw, results };
489
748
  const getNestedValue = (path) => {
490
749
  const indices = path.split(".").slice(1).map((i) => parseInt(i) - 1);
491
750
  if (indices.length === 0) return void 0;
@@ -509,17 +768,42 @@ var WarpEvmResults = class {
509
768
  results[key] = path;
510
769
  }
511
770
  }
512
- return { values, results: await evaluateResultsCommon(warp, results, actionIndex, inputs) };
771
+ return { values, valuesRaw, results: await evaluateResultsCommon(warp, results, actionIndex, inputs) };
772
+ }
773
+ async getTransactionStatus(txHash) {
774
+ try {
775
+ const receipt = await this.provider.getTransactionReceipt(txHash);
776
+ if (!receipt) {
777
+ return { status: "pending" };
778
+ }
779
+ return {
780
+ status: receipt.status === 1 ? "confirmed" : "failed",
781
+ blockNumber: receipt.blockNumber,
782
+ gasUsed: receipt.gasUsed
783
+ };
784
+ } catch (error) {
785
+ throw new Error(`Failed to get transaction status: ${error}`);
786
+ }
787
+ }
788
+ async getTransactionReceipt(txHash) {
789
+ try {
790
+ return await this.provider.getTransactionReceipt(txHash);
791
+ } catch (error) {
792
+ return null;
793
+ }
513
794
  }
514
795
  };
515
796
 
516
797
  // src/WarpEvmExecutor.ts
517
798
  var WarpEvmExecutor = class {
518
- constructor(config) {
799
+ constructor(config, chain) {
519
800
  this.config = config;
801
+ this.chain = chain;
520
802
  this.serializer = new WarpEvmSerializer();
521
- this.provider = new ethers3.JsonRpcProvider(getEvmApiUrl(config.env));
522
- this.results = new WarpEvmResults(config);
803
+ const apiUrl = getProviderUrl3(this.config, chain.name, this.config.env, this.chain.defaultApiUrl);
804
+ const network = new ethers4.Network(this.chain.name, parseInt(this.chain.chainId));
805
+ this.provider = new ethers4.JsonRpcProvider(apiUrl, network);
806
+ this.results = new WarpEvmResults(config, this.chain);
523
807
  }
524
808
  async createTransaction(executable) {
525
809
  const action = getWarpActionByIndex(executable.warp, executable.action);
@@ -537,13 +821,13 @@ var WarpEvmExecutor = class {
537
821
  return tx;
538
822
  }
539
823
  async createTransferTransaction(executable) {
540
- const userWallet = this.config.user?.wallets?.[executable.chain.name];
824
+ const userWallet = getWarpWalletAddressFromConfig2(this.config, executable.chain.name);
541
825
  if (!userWallet) throw new Error("WarpEvmExecutor: createTransfer - user address not set");
542
- if (!ethers3.isAddress(executable.destination)) {
826
+ if (!ethers4.isAddress(executable.destination)) {
543
827
  throw new Error(`WarpEvmExecutor: Invalid destination address: ${executable.destination}`);
544
828
  }
545
- if (executable.value < 0) {
546
- throw new Error(`WarpEvmExecutor: Transfer value cannot be negative: ${executable.value}`);
829
+ if (executable.transfers && executable.transfers.length > 0) {
830
+ return this.createTokenTransferTransaction(executable, userWallet);
547
831
  }
548
832
  const tx = {
549
833
  to: executable.destination,
@@ -553,20 +837,17 @@ var WarpEvmExecutor = class {
553
837
  return this.estimateGasAndSetDefaults(tx, userWallet);
554
838
  }
555
839
  async createContractCallTransaction(executable) {
556
- const userWallet = this.config.user?.wallets?.[executable.chain.name];
840
+ const userWallet = getWarpWalletAddressFromConfig2(this.config, executable.chain.name);
557
841
  if (!userWallet) throw new Error("WarpEvmExecutor: createContractCall - user address not set");
558
842
  const action = getWarpActionByIndex(executable.warp, executable.action);
559
843
  if (!action || !("func" in action) || !action.func) {
560
844
  throw new Error("WarpEvmExecutor: Contract action must have a function name");
561
845
  }
562
- if (!ethers3.isAddress(executable.destination)) {
846
+ if (!ethers4.isAddress(executable.destination)) {
563
847
  throw new Error(`WarpEvmExecutor: Invalid contract address: ${executable.destination}`);
564
848
  }
565
- if (executable.value < 0) {
566
- throw new Error(`WarpEvmExecutor: Contract call value cannot be negative: ${executable.value}`);
567
- }
568
849
  try {
569
- const iface = new ethers3.Interface([`function ${action.func}`]);
850
+ const iface = new ethers4.Interface([`function ${action.func}`]);
570
851
  const encodedData = iface.encodeFunctionData(action.func, executable.args);
571
852
  const tx = {
572
853
  to: executable.destination,
@@ -578,6 +859,50 @@ var WarpEvmExecutor = class {
578
859
  throw new Error(`WarpEvmExecutor: Failed to encode function data for ${action.func}: ${error}`);
579
860
  }
580
861
  }
862
+ async createTokenTransferTransaction(executable, userWallet) {
863
+ if (executable.transfers.length === 0) {
864
+ throw new Error("WarpEvmExecutor: No transfers provided");
865
+ }
866
+ if (!this.chain.nativeToken?.identifier) {
867
+ throw new Error("WarpEvmExecutor: No native token defined for this chain");
868
+ }
869
+ const nativeTokenTransfers = executable.transfers.filter((transfer) => transfer.identifier === this.chain.nativeToken.identifier);
870
+ const erc20Transfers = executable.transfers.filter((transfer) => transfer.identifier !== this.chain.nativeToken.identifier);
871
+ if (nativeTokenTransfers.length === 1 && erc20Transfers.length === 0) {
872
+ const transfer = nativeTokenTransfers[0];
873
+ if (transfer.amount <= 0n) {
874
+ throw new Error("WarpEvmExecutor: Native token transfer amount must be positive");
875
+ }
876
+ const tx = {
877
+ to: executable.destination,
878
+ value: transfer.amount,
879
+ data: "0x"
880
+ };
881
+ return this.estimateGasAndSetDefaults(tx, userWallet);
882
+ }
883
+ if (nativeTokenTransfers.length === 0 && erc20Transfers.length === 1) {
884
+ return this.createSingleTokenTransfer(executable, erc20Transfers[0], userWallet);
885
+ }
886
+ if (executable.transfers.length > 1) {
887
+ throw new Error("WarpEvmExecutor: Multiple token transfers not yet supported");
888
+ }
889
+ throw new Error("WarpEvmExecutor: Invalid transfer configuration");
890
+ }
891
+ async createSingleTokenTransfer(executable, transfer, userWallet) {
892
+ if (!ethers4.isAddress(transfer.identifier)) {
893
+ throw new Error(`WarpEvmExecutor: Invalid token address: ${transfer.identifier}`);
894
+ }
895
+ const transferInterface = new ethers4.Interface(["function transfer(address to, uint256 amount) returns (bool)"]);
896
+ const encodedData = transferInterface.encodeFunctionData("transfer", [executable.destination, transfer.amount]);
897
+ const tx = {
898
+ to: transfer.identifier,
899
+ // Token contract address
900
+ value: 0n,
901
+ // No native token value for ERC-20 transfers
902
+ data: encodedData
903
+ };
904
+ return this.estimateGasAndSetDefaults(tx, userWallet);
905
+ }
581
906
  async executeQuery(executable) {
582
907
  const action = getWarpActionByIndex(executable.warp, executable.action);
583
908
  if (action.type !== "query") {
@@ -586,11 +911,11 @@ var WarpEvmExecutor = class {
586
911
  if (!action.func) {
587
912
  throw new Error("WarpEvmExecutor: Query action must have a function name");
588
913
  }
589
- if (!ethers3.isAddress(executable.destination)) {
914
+ if (!ethers4.isAddress(executable.destination)) {
590
915
  throw new Error(`WarpEvmExecutor: Invalid contract address for query: ${executable.destination}`);
591
916
  }
592
917
  try {
593
- const iface = new ethers3.Interface([`function ${action.func}`]);
918
+ const iface = new ethers4.Interface([`function ${action.func}`]);
594
919
  const encodedData = iface.encodeFunctionData(action.func, executable.args);
595
920
  const result = await this.provider.call({
596
921
  to: executable.destination,
@@ -598,33 +923,23 @@ var WarpEvmExecutor = class {
598
923
  });
599
924
  const decodedResult = iface.decodeFunctionResult(action.func, result);
600
925
  const isSuccess = true;
601
- const { values, results } = await this.results.extractQueryResults(
926
+ const { values, valuesRaw, results } = await this.results.extractQueryResults(
602
927
  executable.warp,
603
928
  decodedResult,
604
929
  executable.action,
605
930
  executable.resolvedInputs
606
931
  );
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);
932
+ const next = getNextInfo(this.config, [], executable.warp, executable.action, results);
620
933
  return {
621
934
  success: isSuccess,
622
935
  warp: executable.warp,
623
936
  action: executable.action,
624
- user: this.config.user?.wallets?.[executable.chain.name] || null,
937
+ user: getWarpWalletAddressFromConfig2(this.config, executable.chain.name),
625
938
  txHash: null,
939
+ tx: null,
626
940
  next,
627
941
  values,
942
+ valuesRaw,
628
943
  results,
629
944
  messages: applyResultsToMessages(executable.warp, results)
630
945
  };
@@ -633,42 +948,17 @@ var WarpEvmExecutor = class {
633
948
  success: false,
634
949
  warp: executable.warp,
635
950
  action: executable.action,
636
- user: this.config.user?.wallets?.[executable.chain.name] || null,
951
+ user: getWarpWalletAddressFromConfig2(this.config, executable.chain.name),
637
952
  txHash: null,
953
+ tx: null,
638
954
  next: null,
639
955
  values: [],
956
+ valuesRaw: [],
640
957
  results: {},
641
958
  messages: {}
642
959
  };
643
960
  }
644
961
  }
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
962
  async estimateGasAndSetDefaults(tx, from) {
673
963
  try {
674
964
  const gasEstimate = await this.provider.estimateGas({
@@ -685,6 +975,7 @@ var WarpEvmExecutor = class {
685
975
  if (feeData.maxFeePerGas && feeData.maxPriorityFeePerGas) {
686
976
  return {
687
977
  ...tx,
978
+ chainId: BigInt(this.chain.chainId),
688
979
  gasLimit: gasEstimate,
689
980
  maxFeePerGas: feeData.maxFeePerGas,
690
981
  maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
@@ -692,97 +983,482 @@ var WarpEvmExecutor = class {
692
983
  } else if (feeData.gasPrice) {
693
984
  return {
694
985
  ...tx,
986
+ chainId: BigInt(this.chain.chainId),
695
987
  gasLimit: gasEstimate,
696
988
  gasPrice: feeData.gasPrice
697
989
  };
698
990
  } else {
699
991
  return {
700
992
  ...tx,
993
+ chainId: BigInt(this.chain.chainId),
701
994
  gasLimit: gasEstimate,
702
- gasPrice: ethers3.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
995
+ gasPrice: ethers4.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
703
996
  };
704
997
  }
705
998
  } catch (error) {
706
999
  let defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.Default);
707
1000
  if (tx.data && tx.data !== "0x") {
708
- defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.ContractCall);
1001
+ if (tx.data.startsWith("0xa9059cbb")) {
1002
+ defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.TokenTransfer);
1003
+ } else {
1004
+ defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.ContractCall);
1005
+ }
709
1006
  } else {
710
1007
  defaultGasLimit = BigInt(WarpEvmConstants.GasLimit.Transfer);
711
1008
  }
712
1009
  return {
713
1010
  ...tx,
1011
+ chainId: BigInt(this.chain.chainId),
714
1012
  gasLimit: defaultGasLimit,
715
- gasPrice: ethers3.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
1013
+ gasPrice: ethers4.parseUnits(WarpEvmConstants.GasPrice.Default, "wei")
716
1014
  };
717
1015
  }
718
1016
  }
719
1017
  async signMessage(message, privateKey) {
720
- throw new Error("Not implemented");
1018
+ try {
1019
+ const wallet = new ethers4.Wallet(privateKey);
1020
+ const signature = await wallet.signMessage(message);
1021
+ return signature;
1022
+ } catch (error) {
1023
+ throw new Error(`Failed to sign message: ${error}`);
1024
+ }
1025
+ }
1026
+ async verifyMessage(message, signature) {
1027
+ try {
1028
+ const recoveredAddress = ethers4.verifyMessage(message, signature);
1029
+ return recoveredAddress;
1030
+ } catch (error) {
1031
+ throw new Error(`Failed to verify message: ${error}`);
1032
+ }
721
1033
  }
722
1034
  };
723
1035
 
724
1036
  // src/WarpEvmExplorer.ts
725
1037
  var WarpEvmExplorer = class {
726
- constructor(chainInfo, chainName = "ethereum") {
727
- this.chainInfo = chainInfo;
728
- this.chainName = chainName;
1038
+ constructor(chain, config) {
1039
+ this.chain = chain;
1040
+ this.config = config;
1041
+ }
1042
+ getExplorers() {
1043
+ const chainExplorers = EvmExplorers[this.chain.name];
1044
+ if (!chainExplorers) {
1045
+ return ["Default"];
1046
+ }
1047
+ const explorers = chainExplorers[this.config.env];
1048
+ if (!explorers) {
1049
+ return ["Default"];
1050
+ }
1051
+ return explorers;
1052
+ }
1053
+ getPrimaryExplorer() {
1054
+ const explorers = this.getExplorers();
1055
+ return explorers[0];
1056
+ }
1057
+ getExplorerUrlByName(explorer) {
1058
+ const userPreference = this.config.preferences?.explorers?.[this.chain.name];
1059
+ if (userPreference && !explorer) {
1060
+ const url2 = ExplorerUrls[userPreference];
1061
+ if (url2) return url2;
1062
+ }
1063
+ if (explorer) {
1064
+ const url2 = ExplorerUrls[explorer];
1065
+ if (url2) return url2;
1066
+ }
1067
+ const primaryExplorer = this.getPrimaryExplorer();
1068
+ const url = ExplorerUrls[primaryExplorer];
1069
+ return url || ExplorerUrls[primaryExplorer];
729
1070
  }
730
- getAccountUrl(address) {
731
- const baseUrl = this.chainInfo.explorerUrl || getEvmExplorerUrl("mainnet", this.chainName);
1071
+ getAccountUrl(address, explorer) {
1072
+ const baseUrl = this.getExplorerUrlByName(explorer);
732
1073
  return `${baseUrl}/address/${address}`;
733
1074
  }
734
- getTransactionUrl(hash) {
735
- const baseUrl = this.chainInfo.explorerUrl || getEvmExplorerUrl("mainnet", this.chainName);
1075
+ getTransactionUrl(hash, explorer) {
1076
+ const baseUrl = this.getExplorerUrlByName(explorer);
736
1077
  return `${baseUrl}/tx/${hash}`;
737
1078
  }
1079
+ getBlockUrl(blockNumber, explorer) {
1080
+ const baseUrl = this.getExplorerUrlByName(explorer);
1081
+ return `${baseUrl}/block/${blockNumber}`;
1082
+ }
1083
+ getAssetUrl(identifier, explorer) {
1084
+ const baseUrl = this.getExplorerUrlByName(explorer);
1085
+ return `${baseUrl}/token/${identifier}`;
1086
+ }
1087
+ getContractUrl(address, explorer) {
1088
+ const baseUrl = this.getExplorerUrlByName(explorer);
1089
+ return `${baseUrl}/address/${address}`;
1090
+ }
1091
+ getAllExplorers() {
1092
+ return this.getExplorers();
1093
+ }
1094
+ getExplorerByName(name) {
1095
+ const explorers = this.getExplorers();
1096
+ return explorers.find((explorer) => explorer.toLowerCase() === name.toLowerCase());
1097
+ }
1098
+ getAccountUrls(address) {
1099
+ const explorers = this.getAllExplorers();
1100
+ const urls = {};
1101
+ explorers.forEach((explorer) => {
1102
+ const url = ExplorerUrls[explorer];
1103
+ if (url) {
1104
+ urls[explorer] = `${url}/address/${address}`;
1105
+ }
1106
+ });
1107
+ return urls;
1108
+ }
1109
+ getTransactionUrls(hash) {
1110
+ const explorers = this.getAllExplorers();
1111
+ const urls = {};
1112
+ explorers.forEach((explorer) => {
1113
+ const url = ExplorerUrls[explorer];
1114
+ if (url) {
1115
+ urls[explorer] = `${url}/tx/${hash}`;
1116
+ }
1117
+ });
1118
+ return urls;
1119
+ }
1120
+ getAssetUrls(identifier) {
1121
+ const explorers = this.getAllExplorers();
1122
+ const urls = {};
1123
+ explorers.forEach((explorer) => {
1124
+ const url = ExplorerUrls[explorer];
1125
+ if (url) {
1126
+ urls[explorer] = `${url}/token/${identifier}`;
1127
+ }
1128
+ });
1129
+ return urls;
1130
+ }
1131
+ getContractUrls(address) {
1132
+ const explorers = this.getAllExplorers();
1133
+ const urls = {};
1134
+ explorers.forEach((explorer) => {
1135
+ const url = ExplorerUrls[explorer];
1136
+ if (url) {
1137
+ urls[explorer] = `${url}/address/${address}`;
1138
+ }
1139
+ });
1140
+ return urls;
1141
+ }
1142
+ getBlockUrls(blockNumber) {
1143
+ const explorers = this.getAllExplorers();
1144
+ const urls = {};
1145
+ explorers.forEach((explorer) => {
1146
+ const url = ExplorerUrls[explorer];
1147
+ if (url) {
1148
+ urls[explorer] = `${url}/block/${blockNumber}`;
1149
+ }
1150
+ });
1151
+ return urls;
1152
+ }
738
1153
  };
739
1154
 
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) {
1155
+ // src/WarpEvmWallet.ts
1156
+ import { getWarpWalletPrivateKeyFromConfig } from "@vleap/warps";
1157
+ import { ethers as ethers5 } from "ethers";
1158
+ var WarpEvmWallet = class {
1159
+ constructor(config, chain) {
1160
+ this.config = config;
1161
+ this.chain = chain;
1162
+ this.wallet = null;
1163
+ this.provider = new ethers5.JsonRpcProvider(chain.defaultApiUrl || "https://rpc.sepolia.org");
1164
+ }
1165
+ async signTransaction(tx) {
1166
+ if (!tx || typeof tx !== "object") {
1167
+ throw new Error("Invalid transaction object");
1168
+ }
1169
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1170
+ if (!privateKey) throw new Error("Wallet not initialized - no private key provided");
1171
+ const wallet = new ethers5.Wallet(privateKey);
1172
+ const txRequest = {
1173
+ to: tx.to,
1174
+ data: tx.data,
1175
+ value: tx.value || 0,
1176
+ gasLimit: tx.gasLimit,
1177
+ maxFeePerGas: tx.maxFeePerGas,
1178
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
1179
+ nonce: tx.nonce,
1180
+ chainId: tx.chainId
1181
+ };
1182
+ const signedTx = await wallet.signTransaction(txRequest);
1183
+ return { ...tx, signature: signedTx };
1184
+ }
1185
+ async signMessage(message) {
1186
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1187
+ if (!privateKey) throw new Error("Wallet not initialized - no private key provided");
1188
+ const wallet = new ethers5.Wallet(privateKey);
1189
+ return await wallet.signMessage(message);
1190
+ }
1191
+ async sendTransaction(tx) {
1192
+ if (!tx || typeof tx !== "object") {
1193
+ throw new Error("Invalid transaction object");
1194
+ }
1195
+ if (!tx.signature) {
1196
+ throw new Error("Transaction must be signed before sending");
1197
+ }
1198
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1199
+ if (!privateKey) throw new Error("Wallet not initialized - no private key provided");
1200
+ const wallet = new ethers5.Wallet(privateKey).connect(this.provider);
1201
+ const txResponse = await wallet.sendTransaction(tx);
1202
+ return txResponse.hash;
1203
+ }
1204
+ create(mnemonic) {
1205
+ const wallet = ethers5.Wallet.fromPhrase(mnemonic);
1206
+ return { address: wallet.address, privateKey: wallet.privateKey, mnemonic };
1207
+ }
1208
+ generate() {
1209
+ const wallet = ethers5.Wallet.createRandom();
1210
+ return { address: wallet.address, privateKey: wallet.privateKey, mnemonic: wallet.mnemonic?.phrase || "" };
1211
+ }
1212
+ getAddress() {
1213
+ const privateKey = getWarpWalletPrivateKeyFromConfig(this.config, this.chain.name);
1214
+ if (!privateKey) return null;
1215
+ const wallet = new ethers5.Wallet(privateKey);
1216
+ return wallet.address;
1217
+ }
1218
+ };
1219
+
1220
+ // src/chains/common.ts
1221
+ var createEvmAdapter = (chainName, chainPrefix, chainInfos) => {
750
1222
  return (config, fallback) => {
751
1223
  if (!fallback) throw new Error(`${chainName} adapter requires a fallback adapter`);
752
1224
  return {
753
1225
  chain: chainName,
1226
+ chainInfo: chainInfos[config.env],
754
1227
  prefix: chainPrefix,
755
- builder: () => new WarpEvmBuilder(config),
756
- executor: new WarpEvmExecutor(config),
757
- results: new WarpEvmResults(config),
1228
+ builder: () => fallback.builder(),
1229
+ executor: new WarpEvmExecutor(config, chainInfos[config.env]),
1230
+ results: new WarpEvmResults(config, chainInfos[config.env]),
758
1231
  serializer: new WarpEvmSerializer(),
759
1232
  registry: fallback.registry,
760
- explorer: (chainInfo) => new WarpEvmExplorer(chainInfo),
1233
+ explorer: new WarpEvmExplorer(chainInfos[config.env], config),
761
1234
  abiBuilder: () => fallback.abiBuilder(),
762
- brandBuilder: () => fallback.brandBuilder()
1235
+ brandBuilder: () => fallback.brandBuilder(),
1236
+ dataLoader: new WarpEvmDataLoader(config, chainInfos[config.env]),
1237
+ wallet: new WarpEvmWallet(config, chainInfos[config.env])
763
1238
  };
764
1239
  };
765
- }
1240
+ };
1241
+
1242
+ // src/chains/arbitrum.ts
1243
+ var NativeTokenArb = {
1244
+ chain: WarpChainName6.Arbitrum,
1245
+ identifier: "ARB",
1246
+ symbol: "ARB",
1247
+ name: "Arbitrum",
1248
+ decimals: 18,
1249
+ logoUrl: "https://vleap.ai/images/tokens/arb.svg"
1250
+ };
1251
+ var getArbitrumAdapter = createEvmAdapter(WarpChainName6.Arbitrum, "arb", {
1252
+ mainnet: {
1253
+ name: WarpChainName6.Arbitrum,
1254
+ displayName: "Arbitrum",
1255
+ chainId: "42161",
1256
+ blockTime: 1e3,
1257
+ addressHrp: "0x",
1258
+ defaultApiUrl: "https://arb1.arbitrum.io/rpc",
1259
+ logoUrl: "https://vleap.ai/images/chains/arbitrum.svg",
1260
+ nativeToken: NativeTokenArb
1261
+ },
1262
+ testnet: {
1263
+ name: WarpChainName6.Arbitrum,
1264
+ displayName: "Arbitrum Sepolia",
1265
+ chainId: "421614",
1266
+ blockTime: 1e3,
1267
+ addressHrp: "0x",
1268
+ defaultApiUrl: "https://sepolia-rollup.arbitrum.io/rpc",
1269
+ logoUrl: "https://vleap.ai/images/chains/arbitrum.svg",
1270
+ nativeToken: NativeTokenArb
1271
+ },
1272
+ devnet: {
1273
+ name: WarpChainName6.Arbitrum,
1274
+ displayName: "Arbitrum Sepolia",
1275
+ chainId: "421614",
1276
+ blockTime: 1e3,
1277
+ addressHrp: "0x",
1278
+ defaultApiUrl: "https://sepolia-rollup.arbitrum.io/rpc",
1279
+ logoUrl: "https://vleap.ai/images/chains/arbitrum.svg",
1280
+ nativeToken: NativeTokenArb
1281
+ }
1282
+ });
1283
+
1284
+ // src/chains/base.ts
1285
+ import { WarpChainName as WarpChainName7 } from "@vleap/warps";
1286
+ var NativeTokenBase = {
1287
+ chain: WarpChainName7.Base,
1288
+ identifier: "ETH",
1289
+ name: "Ether",
1290
+ symbol: "ETH",
1291
+ decimals: 18,
1292
+ logoUrl: "https://vleap.ai/images/tokens/eth.svg"
1293
+ };
1294
+ var getBaseAdapter = createEvmAdapter(WarpChainName7.Base, "base", {
1295
+ mainnet: {
1296
+ name: WarpChainName7.Base,
1297
+ displayName: "Base",
1298
+ chainId: "8453",
1299
+ blockTime: 2e3,
1300
+ addressHrp: "0x",
1301
+ defaultApiUrl: "https://mainnet.base.org",
1302
+ logoUrl: "https://vleap.ai/images/chains/base.svg",
1303
+ nativeToken: NativeTokenBase
1304
+ },
1305
+ testnet: {
1306
+ name: WarpChainName7.Base,
1307
+ displayName: "Base Sepolia",
1308
+ chainId: "84532",
1309
+ blockTime: 2e3,
1310
+ addressHrp: "0x",
1311
+ defaultApiUrl: "https://sepolia.base.org",
1312
+ logoUrl: "https://vleap.ai/images/chains/base.svg",
1313
+ nativeToken: NativeTokenBase
1314
+ },
1315
+ devnet: {
1316
+ name: WarpChainName7.Base,
1317
+ displayName: "Base Sepolia",
1318
+ chainId: "84532",
1319
+ blockTime: 2e3,
1320
+ addressHrp: "0x",
1321
+ defaultApiUrl: "https://sepolia.base.org",
1322
+ logoUrl: "https://vleap.ai/images/chains/base.svg",
1323
+ nativeToken: NativeTokenBase
1324
+ }
1325
+ });
1326
+
1327
+ // src/chains/combined.ts
1328
+ import { WarpChainName as WarpChainName10 } from "@vleap/warps";
1329
+
1330
+ // src/chains/ethereum.ts
1331
+ import { WarpChainName as WarpChainName8 } from "@vleap/warps";
1332
+ var NativeTokenEth = {
1333
+ chain: WarpChainName8.Ethereum,
1334
+ identifier: "ETH",
1335
+ symbol: "ETH",
1336
+ name: "Ether",
1337
+ decimals: 18,
1338
+ logoUrl: "https://vleap.ai/images/tokens/eth.svg"
1339
+ };
1340
+ var getEthereumAdapter = createEvmAdapter(WarpChainName8.Ethereum, "eth", {
1341
+ mainnet: {
1342
+ name: WarpChainName8.Ethereum,
1343
+ displayName: "Ethereum Mainnet",
1344
+ chainId: "1",
1345
+ blockTime: 12e3,
1346
+ addressHrp: "0x",
1347
+ defaultApiUrl: "https://ethereum-rpc.publicnode.com",
1348
+ logoUrl: "https://vleap.ai/images/chains/ethereum.svg",
1349
+ nativeToken: NativeTokenEth
1350
+ },
1351
+ testnet: {
1352
+ name: WarpChainName8.Ethereum,
1353
+ displayName: "Ethereum Sepolia",
1354
+ chainId: "11155111",
1355
+ blockTime: 12e3,
1356
+ addressHrp: "0x",
1357
+ defaultApiUrl: "https://ethereum-sepolia-rpc.publicnode.com",
1358
+ logoUrl: "https://vleap.ai/images/chains/ethereum.svg",
1359
+ nativeToken: NativeTokenEth
1360
+ },
1361
+ devnet: {
1362
+ name: WarpChainName8.Ethereum,
1363
+ displayName: "Ethereum Sepolia",
1364
+ chainId: "11155111",
1365
+ blockTime: 12e3,
1366
+ addressHrp: "0x",
1367
+ defaultApiUrl: "https://ethereum-sepolia-rpc.publicnode.com",
1368
+ logoUrl: "https://vleap.ai/images/chains/ethereum.svg",
1369
+ nativeToken: NativeTokenEth
1370
+ }
1371
+ });
1372
+
1373
+ // src/chains/somnia.ts
1374
+ import { WarpChainName as WarpChainName9 } from "@vleap/warps";
1375
+ var NativeTokenSomi = {
1376
+ chain: WarpChainName9.Somnia,
1377
+ identifier: "SOMI",
1378
+ symbol: "SOMI",
1379
+ name: "Somnia",
1380
+ decimals: 18,
1381
+ logoUrl: "https://assets.coingecko.com/coins/images/68061/standard/somniacg.png?1754641117"
1382
+ };
1383
+ var NativeTokenStt = {
1384
+ chain: WarpChainName9.Somnia,
1385
+ identifier: "STT",
1386
+ symbol: "STT",
1387
+ name: "Somnia Testnet Token",
1388
+ decimals: 18,
1389
+ logoUrl: "https://assets.coingecko.com/coins/images/68061/standard/somniacg.png?1754641117"
1390
+ };
1391
+ var getSomniaAdapter = createEvmAdapter(WarpChainName9.Somnia, "eth", {
1392
+ mainnet: {
1393
+ name: WarpChainName9.Somnia,
1394
+ displayName: "Somnia Mainnet",
1395
+ chainId: "5031",
1396
+ blockTime: 100,
1397
+ addressHrp: "0x",
1398
+ defaultApiUrl: "https://api.infra.mainnet.somnia.network/",
1399
+ logoUrl: "https://vleap.ai/images/chains/somnia.png",
1400
+ nativeToken: NativeTokenSomi
1401
+ },
1402
+ testnet: {
1403
+ name: WarpChainName9.Somnia,
1404
+ displayName: "Somnia Testnet",
1405
+ chainId: "50312",
1406
+ blockTime: 100,
1407
+ addressHrp: "0x",
1408
+ defaultApiUrl: "https://dream-rpc.somnia.network/",
1409
+ logoUrl: "https://vleap.ai/images/chains/somnia.png",
1410
+ nativeToken: NativeTokenStt
1411
+ },
1412
+ devnet: {
1413
+ name: WarpChainName9.Somnia,
1414
+ displayName: "Somnia Testnet",
1415
+ chainId: "50312",
1416
+ blockTime: 100,
1417
+ addressHrp: "0x",
1418
+ defaultApiUrl: "https://dream-rpc.somnia.network",
1419
+ logoUrl: "https://vleap.ai/images/chains/somnia.png",
1420
+ nativeToken: NativeTokenStt
1421
+ }
1422
+ });
1423
+
1424
+ // src/chains/combined.ts
1425
+ var getAllEvmAdapters = (config, fallback) => [
1426
+ getEthereumAdapter(config, fallback),
1427
+ getBaseAdapter(config, fallback),
1428
+ getArbitrumAdapter(config, fallback),
1429
+ getSomniaAdapter(config, fallback)
1430
+ ];
1431
+ var getAllEvmChainNames = () => [
1432
+ WarpChainName10.Ethereum,
1433
+ WarpChainName10.Base,
1434
+ WarpChainName10.Arbitrum,
1435
+ WarpChainName10.Somnia
1436
+ ];
766
1437
  export {
767
- EVM_CHAIN_CONFIGS,
768
- WarpEvmBuilder,
1438
+ ArbitrumExplorers,
1439
+ BaseExplorers,
1440
+ EthereumExplorers,
1441
+ EvmExplorers,
1442
+ ExplorerUrls,
1443
+ KnownTokens,
1444
+ NativeTokenArb,
1445
+ NativeTokenBase,
1446
+ NativeTokenEth,
1447
+ UniswapService,
769
1448
  WarpEvmConstants,
1449
+ WarpEvmDataLoader,
770
1450
  WarpEvmExecutor,
771
1451
  WarpEvmExplorer,
772
1452
  WarpEvmResults,
773
1453
  WarpEvmSerializer,
1454
+ WarpEvmWallet,
1455
+ createEvmAdapter,
1456
+ findKnownTokenById,
774
1457
  getAllEvmAdapters,
1458
+ getAllEvmChainNames,
775
1459
  getArbitrumAdapter,
776
1460
  getBaseAdapter,
777
1461
  getEthereumAdapter,
778
- getEvmApiUrl,
779
- getEvmBlockTime,
780
- getEvmChainConfig,
781
- getEvmChainId,
782
- getEvmExplorerUrl,
783
- getEvmNativeToken,
784
- getEvmRegistryAddress,
785
- getSupportedEnvironments,
786
- getSupportedEvmChains
1462
+ getKnownTokensForChain
787
1463
  };
788
1464
  //# sourceMappingURL=index.mjs.map