@joai/warps-adapter-solana 1.0.0-beta.23

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.js ADDED
@@ -0,0 +1,2319 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ExplorerUrls: () => ExplorerUrls,
34
+ KnownTokens: () => KnownTokens,
35
+ NativeTokenSol: () => NativeTokenSol,
36
+ SolanaAdapter: () => SolanaAdapter,
37
+ SolanaExplorerMap: () => SolanaExplorerMap,
38
+ SolanaExplorerNames: () => SolanaExplorerNames,
39
+ SolanaExplorerUrls: () => SolanaExplorerUrls,
40
+ SolanaExplorers: () => SolanaExplorers,
41
+ SupportedX402SolanaNetworks: () => SupportedX402SolanaNetworks,
42
+ WarpSolanaConstants: () => WarpSolanaConstants,
43
+ WarpSolanaDataLoader: () => WarpSolanaDataLoader,
44
+ WarpSolanaExecutor: () => WarpSolanaExecutor,
45
+ WarpSolanaExplorer: () => WarpSolanaExplorer,
46
+ WarpSolanaOutput: () => WarpSolanaOutput,
47
+ WarpSolanaSerializer: () => WarpSolanaSerializer,
48
+ WarpSolanaWallet: () => WarpSolanaWallet,
49
+ X402SolanaNetworkIdentifiers: () => X402SolanaNetworkIdentifiers,
50
+ findKnownTokenById: () => findKnownTokenById,
51
+ getKnownTokensForChain: () => getKnownTokensForChain
52
+ });
53
+ module.exports = __toCommonJS(index_exports);
54
+
55
+ // src/chains/solana.ts
56
+ var import_warps13 = require("@joai/warps");
57
+
58
+ // src/WarpSolanaDataLoader.ts
59
+ var import_warps5 = require("@joai/warps");
60
+ var import_web3 = require("@solana/web3.js");
61
+ var import_spl_token = require("@solana/spl-token");
62
+
63
+ // src/constants.ts
64
+ var WarpSolanaConstants = {
65
+ ComputeUnitLimit: {
66
+ Default: 2e5,
67
+ Transfer: 5e3,
68
+ TokenTransfer: 1e4,
69
+ ContractCall: 2e5
70
+ },
71
+ PriorityFee: {
72
+ Default: 1e3
73
+ },
74
+ Validation: {
75
+ MinComputeUnits: 1e3,
76
+ MaxComputeUnits: 14e5
77
+ },
78
+ Programs: {
79
+ TokenProgram: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
80
+ SystemProgram: "11111111111111111111111111111111"
81
+ },
82
+ NativeToken: {
83
+ Identifier: "SOL",
84
+ Decimals: 9
85
+ }
86
+ };
87
+ var SolanaExplorers = /* @__PURE__ */ ((SolanaExplorers2) => {
88
+ SolanaExplorers2["Solscan"] = "solscan";
89
+ SolanaExplorers2["SolscanMainnet"] = "solscan_mainnet";
90
+ SolanaExplorers2["SolscanDevnet"] = "solscan_devnet";
91
+ SolanaExplorers2["SolanaExplorer"] = "solana_explorer";
92
+ SolanaExplorers2["SolanaExplorerMainnet"] = "solana_explorer_mainnet";
93
+ SolanaExplorers2["SolanaExplorerDevnet"] = "solana_explorer_devnet";
94
+ return SolanaExplorers2;
95
+ })(SolanaExplorers || {});
96
+ var SolanaExplorerMap = {
97
+ solana: {
98
+ mainnet: ["solscan_mainnet" /* SolscanMainnet */, "solana_explorer_mainnet" /* SolanaExplorerMainnet */],
99
+ testnet: ["solscan" /* Solscan */, "solana_explorer" /* SolanaExplorer */],
100
+ devnet: ["solscan_devnet" /* SolscanDevnet */, "solana_explorer_devnet" /* SolanaExplorerDevnet */]
101
+ }
102
+ };
103
+ var ExplorerUrls = {
104
+ ["solscan" /* Solscan */]: "https://solscan.io",
105
+ ["solscan_mainnet" /* SolscanMainnet */]: "https://solscan.io",
106
+ ["solscan_devnet" /* SolscanDevnet */]: "https://solscan.io",
107
+ ["solana_explorer" /* SolanaExplorer */]: "https://explorer.solana.com",
108
+ ["solana_explorer_mainnet" /* SolanaExplorerMainnet */]: "https://explorer.solana.com",
109
+ ["solana_explorer_devnet" /* SolanaExplorerDevnet */]: "https://explorer.solana.com"
110
+ };
111
+ var SolanaExplorerNames = {
112
+ mainnet: ["solscan_mainnet" /* SolscanMainnet */, "solana_explorer_mainnet" /* SolanaExplorerMainnet */],
113
+ testnet: ["solscan" /* Solscan */, "solana_explorer" /* SolanaExplorer */],
114
+ devnet: ["solscan_devnet" /* SolscanDevnet */, "solana_explorer_devnet" /* SolanaExplorerDevnet */]
115
+ };
116
+ var SolanaExplorerUrls = ExplorerUrls;
117
+ var X402SolanaNetworkIdentifiers = {
118
+ Mainnet: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
119
+ Devnet: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
120
+ };
121
+ var SupportedX402SolanaNetworks = [X402SolanaNetworkIdentifiers.Mainnet, X402SolanaNetworkIdentifiers.Devnet];
122
+
123
+ // src/tokens.ts
124
+ var import_warps4 = require("@joai/warps");
125
+
126
+ // src/tokens/solana-mainnet.ts
127
+ var import_warps = require("@joai/warps");
128
+ var SolanaChain = import_warps.WarpChainName.Solana;
129
+ var SolanaMainnetTokens = [
130
+ {
131
+ chain: SolanaChain,
132
+ identifier: "SOL",
133
+ name: "SOL",
134
+ symbol: "SOL",
135
+ decimals: 9,
136
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
137
+ },
138
+ {
139
+ chain: SolanaChain,
140
+ identifier: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
141
+ name: "USD Coin",
142
+ symbol: "USDC",
143
+ decimals: 6,
144
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
145
+ },
146
+ {
147
+ chain: SolanaChain,
148
+ identifier: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
149
+ name: "Tether USD",
150
+ symbol: "USDT",
151
+ decimals: 6,
152
+ logoUrl: "https://assets.coingecko.com/coins/images/325/small/Tether.png"
153
+ },
154
+ {
155
+ chain: SolanaChain,
156
+ identifier: "So11111111111111111111111111111111111111112",
157
+ name: "Wrapped SOL",
158
+ symbol: "WSOL",
159
+ decimals: 9,
160
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
161
+ },
162
+ {
163
+ chain: SolanaChain,
164
+ identifier: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh",
165
+ name: "Wrapped Bitcoin",
166
+ symbol: "WBTC",
167
+ decimals: 8,
168
+ logoUrl: "https://assets.coingecko.com/coins/images/7598/small/wrapped_bitcoin_wbtc.png"
169
+ },
170
+ {
171
+ chain: SolanaChain,
172
+ identifier: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
173
+ name: "Ethereum (Wormhole)",
174
+ symbol: "ETH",
175
+ decimals: 8,
176
+ logoUrl: "https://assets.coingecko.com/coins/images/279/small/ethereum.png"
177
+ },
178
+ {
179
+ chain: SolanaChain,
180
+ identifier: "7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj",
181
+ name: "Orca",
182
+ symbol: "ORCA",
183
+ decimals: 6,
184
+ logoUrl: "https://assets.coingecko.com/coins/images/17547/small/orca.png"
185
+ },
186
+ {
187
+ chain: SolanaChain,
188
+ identifier: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
189
+ name: "Marinade SOL",
190
+ symbol: "mSOL",
191
+ decimals: 9,
192
+ logoUrl: "https://assets.coingecko.com/coins/images/17752/small/mSOL.png"
193
+ },
194
+ {
195
+ chain: SolanaChain,
196
+ identifier: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
197
+ name: "JitoSOL",
198
+ symbol: "JitoSOL",
199
+ decimals: 9,
200
+ logoUrl: "https://assets.coingecko.com/coins/images/30168/small/jitosol.png"
201
+ },
202
+ {
203
+ chain: SolanaChain,
204
+ identifier: "bSo13r4TkiE4KumL71LsHTPpL2suBYJxqsd4P6Bwv11",
205
+ name: "bSOL",
206
+ symbol: "bSOL",
207
+ decimals: 9,
208
+ logoUrl: "https://assets.coingecko.com/coins/images/30167/small/bsol.png"
209
+ },
210
+ {
211
+ chain: SolanaChain,
212
+ identifier: "7kbnvuGBxxj8AG9qp8Scn56muWGaRaFqxg1FsRp3PaFT",
213
+ name: "UXD Stablecoin",
214
+ symbol: "UXD",
215
+ decimals: 6,
216
+ logoUrl: "https://assets.coingecko.com/coins/images/25342/small/uxd.png"
217
+ },
218
+ {
219
+ chain: SolanaChain,
220
+ identifier: "A9mUU4qviSctJVPJdBJWkb28deg915LYJKrzQ19ji3FM",
221
+ name: "USD Coin (Wormhole)",
222
+ symbol: "USDCet",
223
+ decimals: 6,
224
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
225
+ }
226
+ ];
227
+
228
+ // src/tokens/solana-devnet.ts
229
+ var import_warps2 = require("@joai/warps");
230
+ var SolanaChain2 = import_warps2.WarpChainName.Solana;
231
+ var SolanaDevnetTokens = [
232
+ {
233
+ chain: SolanaChain2,
234
+ identifier: "SOL",
235
+ name: "SOL",
236
+ symbol: "SOL",
237
+ decimals: 9,
238
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
239
+ },
240
+ {
241
+ chain: SolanaChain2,
242
+ identifier: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
243
+ name: "USD Coin",
244
+ symbol: "USDC",
245
+ decimals: 6,
246
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
247
+ },
248
+ {
249
+ chain: SolanaChain2,
250
+ identifier: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
251
+ name: "Tether USD",
252
+ symbol: "USDT",
253
+ decimals: 6,
254
+ logoUrl: "https://assets.coingecko.com/coins/images/325/small/Tether.png"
255
+ },
256
+ {
257
+ chain: SolanaChain2,
258
+ identifier: "So11111111111111111111111111111111111111112",
259
+ name: "Wrapped SOL",
260
+ symbol: "WSOL",
261
+ decimals: 9,
262
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
263
+ }
264
+ ];
265
+
266
+ // src/tokens/solana-testnet.ts
267
+ var import_warps3 = require("@joai/warps");
268
+ var SolanaChain3 = import_warps3.WarpChainName.Solana;
269
+ var SolanaTestnetTokens = [
270
+ {
271
+ chain: SolanaChain3,
272
+ identifier: "SOL",
273
+ name: "SOL",
274
+ symbol: "SOL",
275
+ decimals: 9,
276
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
277
+ },
278
+ {
279
+ chain: SolanaChain3,
280
+ identifier: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
281
+ name: "USD Coin",
282
+ symbol: "USDC",
283
+ decimals: 6,
284
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
285
+ },
286
+ {
287
+ chain: SolanaChain3,
288
+ identifier: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
289
+ name: "Tether USD",
290
+ symbol: "USDT",
291
+ decimals: 6,
292
+ logoUrl: "https://assets.coingecko.com/coins/images/325/small/Tether.png"
293
+ },
294
+ {
295
+ chain: SolanaChain3,
296
+ identifier: "So11111111111111111111111111111111111111112",
297
+ name: "Wrapped SOL",
298
+ symbol: "WSOL",
299
+ decimals: 9,
300
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
301
+ }
302
+ ];
303
+
304
+ // src/tokens.ts
305
+ var KnownTokens = {
306
+ [import_warps4.WarpChainName.Solana]: {
307
+ mainnet: SolanaMainnetTokens,
308
+ testnet: SolanaTestnetTokens,
309
+ devnet: SolanaDevnetTokens
310
+ }
311
+ };
312
+ var findKnownTokenById = (chain, env, id) => {
313
+ const chainTokens = KnownTokens[chain]?.[env] || [];
314
+ return chainTokens.find((token) => token.identifier === id) || null;
315
+ };
316
+ var getKnownTokensForChain = (chainName, env) => {
317
+ return KnownTokens[chainName]?.[env] || [];
318
+ };
319
+
320
+ // src/WarpSolanaDataLoader.ts
321
+ var WarpSolanaDataLoader = class {
322
+ constructor(config, chain) {
323
+ this.config = config;
324
+ this.chain = chain;
325
+ const providerConfig = (0, import_warps5.getProviderConfig)(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
326
+ this.connection = new import_web3.Connection(providerConfig.url, "confirmed");
327
+ this.cache = new import_warps5.WarpCache(config.env, config.cache);
328
+ }
329
+ async getAccount(address) {
330
+ try {
331
+ const publicKey = new import_web3.PublicKey(address);
332
+ const balance = await this.connection.getBalance(publicKey);
333
+ return {
334
+ chain: this.chain.name,
335
+ address,
336
+ balance: BigInt(balance)
337
+ };
338
+ } catch (error) {
339
+ throw new Error(`Failed to get account: ${error}`);
340
+ }
341
+ }
342
+ async getAccountAssets(address) {
343
+ try {
344
+ const account = await this.getAccount(address);
345
+ const tokenBalances = await this.getTokenBalances(address);
346
+ let assets = account.balance > 0n ? [{ ...this.chain.nativeToken, amount: account.balance }] : [];
347
+ for (const tokenBalance of tokenBalances) {
348
+ if (tokenBalance.balance > 0n) {
349
+ assets.push({
350
+ chain: this.chain.name,
351
+ identifier: tokenBalance.tokenAddress,
352
+ name: tokenBalance.metadata.name,
353
+ symbol: tokenBalance.metadata.symbol,
354
+ amount: tokenBalance.balance,
355
+ decimals: tokenBalance.metadata.decimals,
356
+ logoUrl: tokenBalance.metadata.logoUrl || ""
357
+ });
358
+ }
359
+ }
360
+ return assets;
361
+ } catch (error) {
362
+ return [];
363
+ }
364
+ }
365
+ async getAsset(identifier) {
366
+ try {
367
+ if (identifier === this.chain.nativeToken.identifier || identifier === "SOL") {
368
+ return this.chain.nativeToken;
369
+ }
370
+ const cacheKey = import_warps5.WarpCacheKey.Asset(this.config.env, this.chain.name, identifier);
371
+ const cachedAsset = this.cache.get(cacheKey);
372
+ if (cachedAsset) {
373
+ return cachedAsset;
374
+ }
375
+ const env = this.config.env === "mainnet" ? "mainnet" : this.config.env === "devnet" ? "devnet" : "testnet";
376
+ const knownToken = findKnownTokenById(this.chain.name, env, identifier);
377
+ if (knownToken) {
378
+ return {
379
+ chain: this.chain.name,
380
+ identifier,
381
+ name: knownToken.name,
382
+ symbol: knownToken.symbol,
383
+ amount: 0n,
384
+ decimals: knownToken.decimals,
385
+ logoUrl: knownToken.logoUrl
386
+ };
387
+ }
388
+ const metadata = await this.getTokenMetadata(identifier);
389
+ const asset = {
390
+ chain: this.chain.name,
391
+ identifier,
392
+ name: metadata.name,
393
+ symbol: metadata.symbol,
394
+ amount: 0n,
395
+ decimals: metadata.decimals,
396
+ logoUrl: metadata.logoUrl
397
+ };
398
+ this.cache.set(cacheKey, asset, import_warps5.CacheTtl.OneHour);
399
+ return asset;
400
+ } catch (error) {
401
+ return null;
402
+ }
403
+ }
404
+ async getAction(identifier, awaitCompleted = false) {
405
+ const signature = identifier;
406
+ if (awaitCompleted) {
407
+ const tx = await this.waitForTransaction(signature);
408
+ if (!tx) {
409
+ return this.createFailedAction(signature, "Transaction not found after waiting for completion");
410
+ }
411
+ return this.parseTransactionToAction(tx, signature);
412
+ }
413
+ try {
414
+ const tx = await this.connection.getTransaction(signature, {
415
+ commitment: "confirmed",
416
+ maxSupportedTransactionVersion: 0
417
+ });
418
+ if (!tx) return null;
419
+ return this.parseTransactionToAction(tx, signature);
420
+ } catch {
421
+ return null;
422
+ }
423
+ }
424
+ async getAccountActions(address, options) {
425
+ return [];
426
+ }
427
+ async getTokenBalances(address) {
428
+ try {
429
+ const publicKey = new import_web3.PublicKey(address);
430
+ const tokenAccounts = await this.connection.getParsedTokenAccountsByOwner(publicKey, {
431
+ programId: new import_web3.PublicKey(WarpSolanaConstants.Programs.TokenProgram)
432
+ });
433
+ const env = this.config.env === "mainnet" ? "mainnet" : this.config.env === "devnet" ? "devnet" : "testnet";
434
+ const knownTokens = getKnownTokensForChain(this.chain.name, env);
435
+ const balances = await Promise.all(
436
+ tokenAccounts.value.map(async (tokenAccount) => {
437
+ const mintAddress = tokenAccount.account.data.parsed.info.mint;
438
+ const balance = BigInt(tokenAccount.account.data.parsed.info.tokenAmount.amount);
439
+ const decimals = tokenAccount.account.data.parsed.info.tokenAmount.decimals;
440
+ const knownToken = knownTokens.find((token) => token.identifier === mintAddress);
441
+ if (knownToken) {
442
+ return {
443
+ tokenAddress: mintAddress,
444
+ balance,
445
+ metadata: {
446
+ name: knownToken.name,
447
+ symbol: knownToken.symbol,
448
+ decimals: knownToken.decimals,
449
+ logoUrl: (0, import_warps5.getWarpChainAssetLogoUrl)(knownToken, this.config) || ""
450
+ }
451
+ };
452
+ }
453
+ const metadata = await this.getTokenMetadata(mintAddress);
454
+ return {
455
+ tokenAddress: mintAddress,
456
+ balance,
457
+ metadata: {
458
+ name: metadata.name,
459
+ symbol: metadata.symbol,
460
+ decimals: metadata.decimals || decimals,
461
+ logoUrl: metadata.logoUrl
462
+ }
463
+ };
464
+ })
465
+ );
466
+ return balances.filter((b) => b.balance > 0n);
467
+ } catch (error) {
468
+ return [];
469
+ }
470
+ }
471
+ async getTokenMetadata(tokenAddress) {
472
+ try {
473
+ const mintPublicKey = new import_web3.PublicKey(tokenAddress);
474
+ const mintInfo = await (0, import_spl_token.getMint)(this.connection, mintPublicKey);
475
+ return {
476
+ name: "Unknown Token",
477
+ symbol: "UNKNOWN",
478
+ decimals: mintInfo.decimals,
479
+ logoUrl: ""
480
+ };
481
+ } catch (error) {
482
+ return {
483
+ name: "Unknown Token",
484
+ symbol: "UNKNOWN",
485
+ decimals: WarpSolanaConstants.NativeToken.Decimals,
486
+ logoUrl: ""
487
+ };
488
+ }
489
+ }
490
+ async waitForTransaction(signature) {
491
+ const maxWaitTime = 3e5;
492
+ const startTime = Date.now();
493
+ let delay = 1e3;
494
+ let lastError = null;
495
+ let attempts = 0;
496
+ while (Date.now() - startTime < maxWaitTime) {
497
+ attempts++;
498
+ try {
499
+ const tx = await this.tryFetchTransaction(signature);
500
+ if (tx) return tx;
501
+ } catch (err) {
502
+ lastError = err;
503
+ }
504
+ if (Date.now() - startTime < maxWaitTime) {
505
+ delay = this.calculateBackoffDelay(delay, attempts, lastError);
506
+ await new Promise((resolve) => setTimeout(resolve, delay));
507
+ }
508
+ }
509
+ try {
510
+ return await this.connection.getTransaction(signature, { commitment: "confirmed", maxSupportedTransactionVersion: 0 });
511
+ } catch {
512
+ return null;
513
+ }
514
+ }
515
+ async tryFetchTransaction(signature) {
516
+ try {
517
+ const confirmation = await Promise.race([
518
+ this.connection.confirmTransaction(signature, "finalized"),
519
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), 6e4))
520
+ ]);
521
+ if (confirmation) {
522
+ const tx = await this.connection.getTransaction(signature, { commitment: "finalized", maxSupportedTransactionVersion: 0 });
523
+ if (tx) return tx;
524
+ }
525
+ } catch {
526
+ }
527
+ try {
528
+ const tx = await this.connection.getTransaction(signature, { commitment: "finalized", maxSupportedTransactionVersion: 0 });
529
+ if (tx) return tx;
530
+ } catch {
531
+ }
532
+ try {
533
+ return await this.connection.getTransaction(signature, { commitment: "confirmed", maxSupportedTransactionVersion: 0 });
534
+ } catch {
535
+ return null;
536
+ }
537
+ }
538
+ calculateBackoffDelay(currentDelay, attempts, lastError) {
539
+ if (lastError?.message?.includes("429") || lastError?.message?.includes("rate limit")) {
540
+ return Math.min(currentDelay * 2, 3e4);
541
+ }
542
+ if (attempts % 10 === 0) {
543
+ return 2e3;
544
+ }
545
+ return Math.min(currentDelay * 1.1, 15e3);
546
+ }
547
+ createFailedAction(signature, error) {
548
+ return {
549
+ chain: this.chain.name,
550
+ id: signature,
551
+ receiver: "",
552
+ sender: "",
553
+ value: 0n,
554
+ function: "",
555
+ status: "failed",
556
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
557
+ error,
558
+ tx: {
559
+ signature,
560
+ slot: 0,
561
+ blockTime: null,
562
+ err: { message: error }
563
+ }
564
+ };
565
+ }
566
+ parseTransactionToAction(tx, signature) {
567
+ const slot = tx.slot;
568
+ const blockTime = tx.blockTime ? new Date(tx.blockTime * 1e3).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
569
+ const accountKeys = this.extractAccountKeys(tx.transaction.message);
570
+ const sender = accountKeys[0]?.toBase58() || "";
571
+ const receiver = accountKeys.length > 1 ? accountKeys[1]?.toBase58() || "" : "";
572
+ const value = this.calculateTransactionValue(tx.meta);
573
+ const status = tx.meta?.err ? "failed" : "success";
574
+ const functionName = this.determineFunctionName(tx.transaction.message);
575
+ return {
576
+ chain: this.chain.name,
577
+ id: signature,
578
+ receiver,
579
+ sender,
580
+ value,
581
+ function: functionName,
582
+ status,
583
+ createdAt: blockTime,
584
+ error: tx.meta?.err ? JSON.stringify(tx.meta.err) : null,
585
+ tx: {
586
+ signature,
587
+ slot,
588
+ blockTime,
589
+ err: tx.meta?.err || null
590
+ }
591
+ };
592
+ }
593
+ extractAccountKeys(message) {
594
+ if ("staticAccountKeys" in message) {
595
+ return message.staticAccountKeys || [];
596
+ }
597
+ try {
598
+ const allKeys = message.getAccountKeys?.();
599
+ if (allKeys) {
600
+ return allKeys.keySegments().flat() || [];
601
+ }
602
+ } catch {
603
+ }
604
+ return [];
605
+ }
606
+ calculateTransactionValue(meta) {
607
+ const preBalances = meta?.preBalances || [];
608
+ const postBalances = meta?.postBalances || [];
609
+ if (preBalances.length === 0 || postBalances.length === 0) return 0n;
610
+ return BigInt(Math.abs(postBalances[0] - preBalances[0]));
611
+ }
612
+ determineFunctionName(message) {
613
+ let compiledInstructions = [];
614
+ if ("compiledInstructions" in message && Array.isArray(message.compiledInstructions)) {
615
+ compiledInstructions = message.compiledInstructions;
616
+ }
617
+ if (compiledInstructions.length === 0) return "transfer";
618
+ return compiledInstructions[0]?.programIdIndex !== void 0 ? "contract_call" : "transfer";
619
+ }
620
+ };
621
+
622
+ // src/WarpSolanaExecutor.ts
623
+ var import_spl_token2 = require("@solana/spl-token");
624
+ var import_web34 = require("@solana/web3.js");
625
+ var import_warps8 = require("@joai/warps");
626
+
627
+ // src/WarpSolanaOutput.ts
628
+ var import_warps7 = require("@joai/warps");
629
+ var import_web33 = require("@solana/web3.js");
630
+
631
+ // src/WarpSolanaSerializer.ts
632
+ var import_warps6 = require("@joai/warps");
633
+ var import_web32 = require("@solana/web3.js");
634
+ var import_bs58 = __toESM(require("bs58"), 1);
635
+ var WarpSolanaSerializer = class {
636
+ constructor() {
637
+ this.coreSerializer = new import_warps6.WarpSerializer();
638
+ }
639
+ typedToString(value) {
640
+ if (value && typeof value === "object" && "toBase58" in value && typeof value.toBase58 === "function") {
641
+ return `address:${value.toBase58()}`;
642
+ }
643
+ if (typeof value === "string") {
644
+ if (value.length >= 32 && value.length <= 44) {
645
+ try {
646
+ const pubkey = new import_web32.PublicKey(value);
647
+ if (pubkey.toBase58() === value && /^[1-9A-HJ-NP-Za-km-z]+$/.test(value)) {
648
+ return `address:${value}`;
649
+ }
650
+ } catch {
651
+ }
652
+ }
653
+ if (value.startsWith("0x") || /^[0-9a-fA-F]+$/.test(value)) {
654
+ return `hex:${value}`;
655
+ }
656
+ return `string:${value}`;
657
+ }
658
+ if (typeof value === "number") {
659
+ if (Number.isInteger(value)) {
660
+ if (value >= 0 && value <= 255) return `uint8:${value}`;
661
+ if (value >= 0 && value <= 65535) return `uint16:${value}`;
662
+ if (value >= 0 && value <= 4294967295) return `uint32:${value}`;
663
+ return `uint64:${value}`;
664
+ }
665
+ return `string:${value}`;
666
+ }
667
+ if (typeof value === "bigint") {
668
+ return `biguint:${value.toString()}`;
669
+ }
670
+ if (typeof value === "boolean") {
671
+ return `boolean:${value}`;
672
+ }
673
+ if (value instanceof import_web32.PublicKey) {
674
+ return `address:${value.toBase58()}`;
675
+ }
676
+ if (value instanceof Uint8Array) {
677
+ return `hex:${import_bs58.default.encode(value)}`;
678
+ }
679
+ if (typeof value === "object" && value !== null && "identifier" in value && "amount" in value) {
680
+ const asset = value;
681
+ if (asset.decimals !== void 0) {
682
+ return `asset:${asset.identifier}${import_warps6.WarpConstants.ArgCompositeSeparator}${asset.amount.toString()}${import_warps6.WarpConstants.ArgCompositeSeparator}${asset.decimals}`;
683
+ }
684
+ return `asset:${asset.identifier}${import_warps6.WarpConstants.ArgCompositeSeparator}${asset.amount.toString()}`;
685
+ }
686
+ if (Array.isArray(value)) {
687
+ if (value.length === 0) return `list:string:`;
688
+ const types = value.map((item) => this.typedToString(item).split(import_warps6.WarpConstants.ArgParamsSeparator)[0]);
689
+ const type = types[0];
690
+ const values = value.map((item) => this.typedToString(item).split(import_warps6.WarpConstants.ArgParamsSeparator)[1]);
691
+ return `list:${type}:${values.join(",")}`;
692
+ }
693
+ if (value === null || value === void 0) {
694
+ return `string:null`;
695
+ }
696
+ return `string:${String(value)}`;
697
+ }
698
+ typedToNative(value) {
699
+ const stringValue = this.typedToString(value);
700
+ const [type, ...valueParts] = stringValue.split(import_warps6.WarpConstants.ArgParamsSeparator);
701
+ const nativeValue = valueParts.join(import_warps6.WarpConstants.ArgParamsSeparator);
702
+ return [type, this.parseNativeValue(type, nativeValue)];
703
+ }
704
+ nativeToTyped(type, value) {
705
+ switch (type) {
706
+ case "string":
707
+ return String(value);
708
+ case "uint8":
709
+ case "uint16":
710
+ case "uint32":
711
+ case "uint64":
712
+ return BigInt(value);
713
+ case "biguint":
714
+ return BigInt(value);
715
+ case "boolean":
716
+ return Boolean(value);
717
+ case "address":
718
+ return String(value);
719
+ case "hex":
720
+ return String(value);
721
+ case "asset":
722
+ if (typeof value === "object" && value !== null && "identifier" in value && "amount" in value) {
723
+ return value;
724
+ }
725
+ return value;
726
+ default:
727
+ if (type.startsWith("list:")) {
728
+ const [, itemType, itemsStr] = type.split(":");
729
+ if (!itemsStr) return [];
730
+ const items = itemsStr.split(",");
731
+ return items.map((item) => this.nativeToTyped(itemType, item));
732
+ }
733
+ return String(value);
734
+ }
735
+ }
736
+ nativeToType(type) {
737
+ switch (type) {
738
+ case "string":
739
+ return "string";
740
+ case "uint8":
741
+ case "uint16":
742
+ case "uint32":
743
+ case "uint64":
744
+ case "biguint":
745
+ return "bigint";
746
+ case "boolean":
747
+ return "boolean";
748
+ case "address":
749
+ return "string";
750
+ case "hex":
751
+ return "string";
752
+ default:
753
+ return "string";
754
+ }
755
+ }
756
+ stringToTyped(value) {
757
+ const parts = value.split(import_warps6.WarpConstants.ArgParamsSeparator, 2);
758
+ if (parts.length < 2) {
759
+ return value;
760
+ }
761
+ const [type, stringValue] = parts;
762
+ switch (type) {
763
+ case "string":
764
+ return stringValue;
765
+ case "uint8":
766
+ case "uint16":
767
+ case "uint32":
768
+ case "uint64":
769
+ return BigInt(stringValue);
770
+ case "biguint":
771
+ return BigInt(stringValue);
772
+ case "boolean":
773
+ return stringValue === "true";
774
+ case "address":
775
+ return stringValue;
776
+ case "hex":
777
+ return stringValue;
778
+ case "asset":
779
+ const assetParts = stringValue.split(import_warps6.WarpConstants.ArgCompositeSeparator);
780
+ const identifier = assetParts[0] || "";
781
+ const amount = assetParts[1] ? BigInt(assetParts[1]) : 0n;
782
+ const decimals = assetParts[2] ? parseInt(assetParts[2], 10) : void 0;
783
+ return { identifier, amount, decimals };
784
+ default:
785
+ if (type.startsWith("list:")) {
786
+ const [, itemType, itemsStr] = type.split(":");
787
+ if (!itemsStr) return [];
788
+ const items = itemsStr.split(",");
789
+ return items.map((item) => this.stringToTyped(`${itemType}:${item}`));
790
+ }
791
+ return stringValue;
792
+ }
793
+ }
794
+ parseNativeValue(type, value) {
795
+ switch (type) {
796
+ case "string":
797
+ return value;
798
+ case "uint8":
799
+ case "uint16":
800
+ case "uint32":
801
+ case "uint64":
802
+ case "biguint":
803
+ return BigInt(value);
804
+ case "boolean":
805
+ return value === "true";
806
+ case "address":
807
+ return value;
808
+ case "hex":
809
+ return value;
810
+ default:
811
+ return value;
812
+ }
813
+ }
814
+ };
815
+
816
+ // src/WarpSolanaOutput.ts
817
+ var WarpSolanaOutput = class {
818
+ constructor(config, chain) {
819
+ this.config = config;
820
+ this.chain = chain;
821
+ this.serializer = new WarpSolanaSerializer();
822
+ const providerConfig = (0, import_warps7.getProviderConfig)(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
823
+ this.connection = new import_web33.Connection(providerConfig.url, "confirmed");
824
+ this.cache = new import_warps7.WarpCache(config.env, config.cache);
825
+ }
826
+ async getActionExecution(warp, actionIndex, tx) {
827
+ const inputs = this.cache.get(import_warps7.WarpCacheKey.WarpExecutable(this.config.env, warp.meta?.hash || "", actionIndex)) ?? [];
828
+ const resolvedInputs = (0, import_warps7.extractResolvedInputValues)(inputs);
829
+ if (!tx) {
830
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
831
+ }
832
+ if ("status" in tx && typeof tx.status === "string") {
833
+ return this.handleWarpChainAction(warp, actionIndex, tx, resolvedInputs);
834
+ }
835
+ if (typeof tx === "string") {
836
+ return this.handleTransactionSignature(warp, actionIndex, tx, resolvedInputs);
837
+ }
838
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
839
+ }
840
+ createFailedExecution(warp, actionIndex, resolvedInputs = []) {
841
+ return {
842
+ status: "error",
843
+ warp,
844
+ action: actionIndex,
845
+ user: (0, import_warps7.getWarpWalletAddressFromConfig)(this.config, this.chain.name),
846
+ txHash: "",
847
+ tx: null,
848
+ next: null,
849
+ values: { string: [], native: [], mapped: {} },
850
+ output: {},
851
+ messages: {},
852
+ destination: null,
853
+ resolvedInputs
854
+ };
855
+ }
856
+ async handleWarpChainAction(warp, actionIndex, tx, resolvedInputs = []) {
857
+ const isPending = tx.status === "pending";
858
+ const success = tx.status === "success";
859
+ const transactionHash = tx.id || tx.tx?.signature || "";
860
+ if (isPending) {
861
+ throw new Error(`Transaction ${transactionHash} is still pending. Execution should only proceed after finalization.`);
862
+ }
863
+ const slot = tx.tx?.slot || 0;
864
+ const blockTime = tx.tx?.blockTime || 0;
865
+ const rawValues = [transactionHash, slot.toString(), blockTime.toString()];
866
+ const stringValues = rawValues.map(String);
867
+ return {
868
+ status: success ? "success" : "error",
869
+ warp,
870
+ action: actionIndex,
871
+ user: (0, import_warps7.getWarpWalletAddressFromConfig)(this.config, this.chain.name),
872
+ txHash: transactionHash,
873
+ tx,
874
+ next: null,
875
+ values: { string: stringValues, native: rawValues, mapped: {} },
876
+ output: {},
877
+ messages: {},
878
+ destination: null,
879
+ resolvedInputs
880
+ };
881
+ }
882
+ async handleTransactionSignature(warp, actionIndex, signature, resolvedInputs = []) {
883
+ try {
884
+ const tx = await this.connection.getTransaction(signature, {
885
+ commitment: "confirmed",
886
+ maxSupportedTransactionVersion: 0
887
+ });
888
+ if (!tx) {
889
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
890
+ }
891
+ const success = !tx.meta?.err;
892
+ const slot = tx.slot;
893
+ const blockTime = tx.blockTime || 0;
894
+ const fee = tx.meta?.fee || 0;
895
+ const rawValues = [signature, slot.toString(), blockTime.toString(), fee.toString()];
896
+ const stringValues = rawValues.map(String);
897
+ return {
898
+ status: success ? "success" : "error",
899
+ warp,
900
+ action: actionIndex,
901
+ user: (0, import_warps7.getWarpWalletAddressFromConfig)(this.config, this.chain.name),
902
+ txHash: signature,
903
+ tx: {
904
+ signature,
905
+ slot,
906
+ blockTime,
907
+ fee,
908
+ err: tx.meta?.err || null
909
+ },
910
+ next: null,
911
+ values: { string: stringValues, native: rawValues, mapped: {} },
912
+ output: {},
913
+ messages: {},
914
+ destination: null,
915
+ resolvedInputs
916
+ };
917
+ } catch (error) {
918
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
919
+ }
920
+ }
921
+ async extractQueryOutput(warp, typedValues, actionIndex, inputs) {
922
+ const stringValues = typedValues.map((t) => this.serializer.typedToString(t));
923
+ const nativeValues = typedValues.map((t) => this.serializer.typedToNative(t)[1]);
924
+ const values = { string: stringValues, native: nativeValues, mapped: {} };
925
+ let output = {};
926
+ if (!warp.output) return { values, output };
927
+ const getNestedValue = (path) => {
928
+ const indices = path.split(".").slice(1).map((i) => parseInt(i) - 1);
929
+ if (indices.length === 0) return void 0;
930
+ let value = nativeValues[indices[0]];
931
+ for (let i = 1; i < indices.length; i++) {
932
+ if (value === void 0 || value === null) return void 0;
933
+ value = value[indices[i]];
934
+ }
935
+ return value;
936
+ };
937
+ for (const [key, path] of Object.entries(warp.output)) {
938
+ if (path.startsWith(import_warps7.WarpConstants.Transform.Prefix)) continue;
939
+ const currentActionIndex = (0, import_warps7.parseOutputOutIndex)(path);
940
+ if (currentActionIndex !== null && currentActionIndex !== actionIndex) {
941
+ output[key] = null;
942
+ continue;
943
+ }
944
+ if (path.startsWith("out.") || path === "out" || path.startsWith("out[")) {
945
+ output[key] = getNestedValue(path) || null;
946
+ } else {
947
+ output[key] = path;
948
+ }
949
+ }
950
+ return { values, output: await (0, import_warps7.evaluateOutputCommon)(warp, output, actionIndex, inputs, this.serializer.coreSerializer, this.config) };
951
+ }
952
+ async getTransactionStatus(txHash) {
953
+ try {
954
+ const tx = await this.connection.getTransaction(txHash, {
955
+ commitment: "confirmed",
956
+ maxSupportedTransactionVersion: 0
957
+ });
958
+ if (!tx) {
959
+ return { status: "pending" };
960
+ }
961
+ return {
962
+ status: tx.meta?.err ? "failed" : "confirmed",
963
+ blockNumber: tx.slot,
964
+ gasUsed: BigInt(tx.meta?.fee || 0)
965
+ };
966
+ } catch (error) {
967
+ throw new Error(`Failed to get transaction status: ${error}`);
968
+ }
969
+ }
970
+ async getTransactionReceipt(txHash) {
971
+ try {
972
+ const tx = await this.connection.getTransaction(txHash, {
973
+ commitment: "confirmed",
974
+ maxSupportedTransactionVersion: 0
975
+ });
976
+ if (!tx) {
977
+ return null;
978
+ }
979
+ return {
980
+ signature: txHash,
981
+ slot: tx.slot,
982
+ blockTime: tx.blockTime,
983
+ fee: tx.meta?.fee || 0,
984
+ err: tx.meta?.err || null
985
+ };
986
+ } catch (error) {
987
+ return null;
988
+ }
989
+ }
990
+ };
991
+
992
+ // src/WarpSolanaExecutor.ts
993
+ var WarpSolanaExecutor = class {
994
+ constructor(config, chain) {
995
+ this.config = config;
996
+ this.chain = chain;
997
+ this.serializer = new WarpSolanaSerializer();
998
+ const providerConfig = (0, import_warps8.getProviderConfig)(this.config, chain.name, this.config.env, this.chain.defaultApiUrl);
999
+ this.connection = new import_web34.Connection(providerConfig.url, "confirmed");
1000
+ this.output = new WarpSolanaOutput(config, this.chain);
1001
+ }
1002
+ async createTransaction(executable) {
1003
+ const action = (0, import_warps8.getWarpActionByIndex)(executable.warp, executable.action);
1004
+ let tx = null;
1005
+ if (action.type === "transfer") {
1006
+ tx = await this.createTransferTransaction(executable);
1007
+ } else if (action.type === "contract") {
1008
+ tx = await this.createContractCallTransaction(executable);
1009
+ } else if (action.type === "query") {
1010
+ throw new Error("WarpSolanaExecutor: Invalid action type for createTransaction; Use executeQuery instead");
1011
+ } else if (action.type === "collect") {
1012
+ throw new Error("WarpSolanaExecutor: Invalid action type for createTransaction; Use executeCollect instead");
1013
+ }
1014
+ if (!tx) throw new Error(`WarpSolanaExecutor: Invalid action type (${action.type})`);
1015
+ return tx;
1016
+ }
1017
+ async createTransferTransaction(executable) {
1018
+ const userWallet = (0, import_warps8.getWarpWalletAddressFromConfig)(this.config, executable.chain.name);
1019
+ if (!userWallet) throw new Error("WarpSolanaExecutor: createTransfer - user address not set");
1020
+ if (!executable.destination) throw new Error("WarpSolanaExecutor: Destination address is required");
1021
+ const destinationPubkey = this.toPublicKey(executable.destination, "Invalid destination address");
1022
+ const fromPubkey = this.toPublicKey(userWallet, "Invalid user wallet address");
1023
+ if (executable.transfers && executable.transfers.length > 0) {
1024
+ return this.createTokenTransferTransaction(executable, userWallet, destinationPubkey);
1025
+ }
1026
+ const instructions = [];
1027
+ if (executable.value > 0n) {
1028
+ instructions.push(import_web34.SystemProgram.transfer({ fromPubkey, toPubkey: destinationPubkey, lamports: Number(executable.value) }));
1029
+ }
1030
+ if (executable.data) {
1031
+ const data = this.serializer.stringToTyped(executable.data);
1032
+ if (data && typeof data === "string") {
1033
+ const dataBuffer = Buffer.from(data, "base64");
1034
+ instructions.push(
1035
+ new import_web34.TransactionInstruction({
1036
+ keys: [
1037
+ { pubkey: fromPubkey, isSigner: true, isWritable: true },
1038
+ { pubkey: destinationPubkey, isSigner: false, isWritable: true }
1039
+ ],
1040
+ programId: destinationPubkey,
1041
+ data: dataBuffer
1042
+ })
1043
+ );
1044
+ }
1045
+ }
1046
+ return this.setTransactionDefaults(instructions, fromPubkey);
1047
+ }
1048
+ async createContractCallTransaction(executable) {
1049
+ const userWallet = (0, import_warps8.getWarpWalletAddressFromConfig)(this.config, executable.chain.name);
1050
+ if (!userWallet) throw new Error("WarpSolanaExecutor: createContractCall - user address not set");
1051
+ const action = (0, import_warps8.getWarpActionByIndex)(executable.warp, executable.action);
1052
+ if (!action || !("func" in action) || !action.func) throw new Error("WarpSolanaExecutor: Contract action must have a function name");
1053
+ if (!executable.destination) throw new Error("WarpSolanaExecutor: Contract address is required");
1054
+ const programId = this.toPublicKey(executable.destination, "Invalid contract address");
1055
+ const fromPubkey = this.toPublicKey(userWallet, "Invalid user wallet address");
1056
+ const instructions = [];
1057
+ const argsToUse = this.extractContractArgs(executable);
1058
+ const nativeArgs = argsToUse.map((arg) => this.serializer.coreSerializer.stringToNative(arg)[1]);
1059
+ const instructionData = this.buildInstructionData(action, nativeArgs);
1060
+ const accounts = await this.buildInstructionAccounts(action, executable, fromPubkey, programId);
1061
+ await this.ensureATAs(action, accounts, fromPubkey, instructions);
1062
+ instructions.push(new import_web34.TransactionInstruction({ keys: accounts, programId, data: instructionData }));
1063
+ if (executable.value > 0n) {
1064
+ instructions.push(import_web34.SystemProgram.transfer({ fromPubkey, toPubkey: programId, lamports: Number(executable.value) }));
1065
+ }
1066
+ return this.setTransactionDefaults(instructions, fromPubkey);
1067
+ }
1068
+ async ensureATAs(action, accounts, fromPubkey, instructions) {
1069
+ if (!action.accounts || !Array.isArray(action.accounts)) return;
1070
+ const createdATAs = /* @__PURE__ */ new Set();
1071
+ for (let idx = 0; idx < action.accounts.length; idx++) {
1072
+ const accountDef = action.accounts[idx];
1073
+ const accountStr = typeof accountDef === "string" ? accountDef : JSON.stringify(accountDef);
1074
+ if (accountStr.includes("{{USER_ATA:")) {
1075
+ const match = accountStr.match(/USER_ATA[:\s]*([^"}\s]+)/);
1076
+ if (match) {
1077
+ const mintAddress = match[1];
1078
+ try {
1079
+ const mintPubkey = new import_web34.PublicKey(mintAddress);
1080
+ const expectedAta = await (0, import_spl_token2.getAssociatedTokenAddress)(mintPubkey, fromPubkey);
1081
+ const ataKey = expectedAta.toBase58();
1082
+ if (!createdATAs.has(ataKey)) {
1083
+ createdATAs.add(ataKey);
1084
+ const ataInfo = await this.connection.getAccountInfo(expectedAta);
1085
+ if (!ataInfo) {
1086
+ instructions.push((0, import_spl_token2.createAssociatedTokenAccountInstruction)(fromPubkey, expectedAta, fromPubkey, mintPubkey));
1087
+ }
1088
+ }
1089
+ } catch {
1090
+ continue;
1091
+ }
1092
+ }
1093
+ }
1094
+ if (accountStr.includes("{{RECEIVER_ATA:")) {
1095
+ const match = accountStr.match(/RECEIVER_ATA[:\s]*([^"}\s:]+)[:\s]*([^"}\s]+)/);
1096
+ if (match) {
1097
+ const mintAddress = match[1];
1098
+ const receiverAddress = match[2];
1099
+ try {
1100
+ const mintPubkey = new import_web34.PublicKey(mintAddress);
1101
+ const receiverPubkey = new import_web34.PublicKey(receiverAddress);
1102
+ const expectedAta = await (0, import_spl_token2.getAssociatedTokenAddress)(mintPubkey, receiverPubkey);
1103
+ const ataKey = expectedAta.toBase58();
1104
+ if (!createdATAs.has(ataKey)) {
1105
+ createdATAs.add(ataKey);
1106
+ const ataInfo = await this.connection.getAccountInfo(expectedAta);
1107
+ if (!ataInfo) {
1108
+ instructions.push((0, import_spl_token2.createAssociatedTokenAccountInstruction)(fromPubkey, expectedAta, receiverPubkey, mintPubkey));
1109
+ }
1110
+ }
1111
+ } catch {
1112
+ continue;
1113
+ }
1114
+ }
1115
+ }
1116
+ }
1117
+ }
1118
+ encodeInstructionData(instructionDef, args, funcName) {
1119
+ try {
1120
+ let discriminatorBuffer;
1121
+ if (instructionDef.discriminator) {
1122
+ if (Buffer.isBuffer(instructionDef.discriminator)) {
1123
+ discriminatorBuffer = instructionDef.discriminator;
1124
+ } else if (Array.isArray(instructionDef.discriminator)) {
1125
+ discriminatorBuffer = Buffer.from(instructionDef.discriminator);
1126
+ } else {
1127
+ discriminatorBuffer = Buffer.from(funcName).slice(0, 8);
1128
+ }
1129
+ } else {
1130
+ discriminatorBuffer = Buffer.from(funcName).slice(0, 8);
1131
+ }
1132
+ if (args.length > 0 && instructionDef.args && instructionDef.args.length > 0) {
1133
+ const encodedArgs = this.encodeArgs(args, instructionDef.args);
1134
+ return Buffer.concat([discriminatorBuffer, encodedArgs]);
1135
+ }
1136
+ return discriminatorBuffer;
1137
+ } catch {
1138
+ return this.encodeBasicInstructionData(args, funcName);
1139
+ }
1140
+ }
1141
+ encodeBasicInstructionData(args, funcName) {
1142
+ const funcHash = Buffer.from(funcName).slice(0, 8);
1143
+ const data = Buffer.alloc(8);
1144
+ data.set(funcHash, 0);
1145
+ if (args.length > 0) {
1146
+ const encodedArgs = args.map((arg) => {
1147
+ if (typeof arg === "string") {
1148
+ return Buffer.from(arg, "utf8");
1149
+ } else if (typeof arg === "number" || typeof arg === "bigint") {
1150
+ const num = typeof arg === "bigint" ? Number(arg) : arg;
1151
+ const buf = Buffer.alloc(8);
1152
+ buf.writeBigUInt64LE(BigInt(num), 0);
1153
+ return buf;
1154
+ } else if (Buffer.isBuffer(arg)) {
1155
+ return arg;
1156
+ } else if (arg instanceof Uint8Array) {
1157
+ return Buffer.from(arg);
1158
+ }
1159
+ return Buffer.from(String(arg), "utf8");
1160
+ });
1161
+ return Buffer.concat([data, ...encodedArgs]);
1162
+ }
1163
+ return data;
1164
+ }
1165
+ encodeArgs(args, argDefs) {
1166
+ const buffers = [];
1167
+ for (let i = 0; i < Math.min(args.length, argDefs.length); i++) {
1168
+ const arg = args[i];
1169
+ const def = argDefs[i];
1170
+ if (def.type === "u64" || def.type === "u128") {
1171
+ const num = typeof arg === "bigint" ? arg : BigInt(arg);
1172
+ const size = def.type === "u128" ? 16 : 8;
1173
+ const buf = Buffer.alloc(size);
1174
+ if (size === 16) {
1175
+ buf.writeBigUInt64LE(num & 0xffffffffffffffffn, 0);
1176
+ buf.writeBigUInt64LE(num >> 64n, 8);
1177
+ } else {
1178
+ buf.writeBigUInt64LE(num, 0);
1179
+ }
1180
+ buffers.push(buf);
1181
+ } else if (def.type === "string") {
1182
+ buffers.push(Buffer.from(String(arg), "utf8"));
1183
+ } else if (def.type === "publicKey" || def.type === "pubkey") {
1184
+ try {
1185
+ const pubkey = new import_web34.PublicKey(arg);
1186
+ buffers.push(Buffer.from(pubkey.toBuffer()));
1187
+ } catch {
1188
+ buffers.push(Buffer.from(String(arg), "utf8"));
1189
+ }
1190
+ } else {
1191
+ buffers.push(Buffer.from(String(arg), "utf8"));
1192
+ }
1193
+ }
1194
+ return Buffer.concat(buffers);
1195
+ }
1196
+ async buildInstructionAccounts(action, executable, fromPubkey, programId) {
1197
+ const accounts = [];
1198
+ const accountInputs = this.extractAccountInputs(action, executable);
1199
+ if (accountInputs.length > 0) {
1200
+ for (const accountInput of accountInputs) {
1201
+ while (accounts.length < accountInput.index) {
1202
+ accounts.push({ pubkey: fromPubkey, isSigner: true, isWritable: true });
1203
+ }
1204
+ const address = await this.resolveAccountFromInput(accountInput, executable, fromPubkey);
1205
+ const { isSigner, isWritable } = this.determineAccountFlags(accountInput.input, address, fromPubkey);
1206
+ accounts.push({ pubkey: address, isSigner, isWritable });
1207
+ }
1208
+ return accounts;
1209
+ }
1210
+ if (!action.accounts || !Array.isArray(action.accounts)) return accounts;
1211
+ for (let idx = 0; idx < action.accounts.length; idx++) {
1212
+ const accountDef = action.accounts[idx];
1213
+ let address = this.extractAccountAddress(accountDef);
1214
+ if (address === "[object Object]" || typeof accountDef === "string" && accountDef === "[object Object]") {
1215
+ address = fromPubkey.toBase58();
1216
+ } else if (!address || address.length === 0) {
1217
+ throw new Error(`Invalid account definition at index ${idx}: ${JSON.stringify(accountDef)}`);
1218
+ }
1219
+ if (address === "{{USER_WALLET}}" || typeof address === "string" && address.includes("{{USER_WALLET}}")) {
1220
+ address = fromPubkey.toBase58();
1221
+ } else if (typeof address === "string" && address.includes("{{")) {
1222
+ const originalAddress = address;
1223
+ let maxIterations = 10;
1224
+ while (address.includes("{{") && maxIterations-- > 0) {
1225
+ const beforeInterpolation = address;
1226
+ address = this.interpolateAccountAddress(address, executable.resolvedInputs);
1227
+ if (address === beforeInterpolation) break;
1228
+ }
1229
+ if (!address || address.includes("{{") && !address.startsWith("{{USER_ATA:") && !address.startsWith("{{RECEIVER_ATA:")) {
1230
+ throw new Error(`Failed to interpolate account address at index ${idx}: ${originalAddress} -> ${address}. ResolvedInputs: ${JSON.stringify(executable.resolvedInputs.map((r) => ({ as: r.input?.as, value: r.value })))}`);
1231
+ }
1232
+ }
1233
+ const pubkey = await this.resolveAccountPubkey(address, fromPubkey);
1234
+ const { isSigner, isWritable } = this.determineAccountFlags(accountDef, pubkey, fromPubkey);
1235
+ accounts.push({ pubkey, isSigner, isWritable });
1236
+ }
1237
+ return accounts;
1238
+ }
1239
+ extractAccountInputs(action, executable) {
1240
+ if (!action.inputs || !Array.isArray(action.inputs)) return [];
1241
+ const accountInputs = [];
1242
+ for (const input of action.inputs) {
1243
+ if (input.position && typeof input.position === "string" && input.position.startsWith("account:")) {
1244
+ const index = parseInt(input.position.split(":")[1] || "0", 10);
1245
+ accountInputs.push({ input, index });
1246
+ }
1247
+ }
1248
+ return accountInputs.sort((a, b) => a.index - b.index);
1249
+ }
1250
+ async resolveAccountFromInput(accountInput, executable, fromPubkey) {
1251
+ const resolved = executable.resolvedInputs.find((r) => r.input === accountInput.input || r.input?.as === accountInput.input.as);
1252
+ if (!resolved) {
1253
+ throw new Error(`Account input at index ${accountInput.index} not resolved: ${accountInput.input.as || accountInput.input.name}`);
1254
+ }
1255
+ let address = resolved.value;
1256
+ if (typeof address === "string" && address.includes(":")) {
1257
+ address = address.split(":")[1];
1258
+ }
1259
+ if (!address || typeof address !== "string") {
1260
+ throw new Error(`Invalid address for account input at index ${accountInput.index}: ${accountInput.input.as || accountInput.input.name}`);
1261
+ }
1262
+ if (accountInput.input.as === "USER_WALLET") {
1263
+ return fromPubkey;
1264
+ }
1265
+ if (accountInput.input.as?.startsWith("USER_ATA:") || accountInput.input.as?.startsWith("RECEIVER_ATA:")) {
1266
+ return await this.resolveAccountPubkey(`{{${accountInput.input.as}}}`, fromPubkey);
1267
+ }
1268
+ return new import_web34.PublicKey(address);
1269
+ }
1270
+ interpolateAccountAddress(address, resolvedInputs) {
1271
+ if (!address.includes("{{")) return address;
1272
+ for (const resolved of resolvedInputs) {
1273
+ if (!resolved.input?.as) continue;
1274
+ const placeholder = `{{${resolved.input.as.toUpperCase()}}}`;
1275
+ if (address === placeholder || address.includes(placeholder)) {
1276
+ let value = resolved.value;
1277
+ if (typeof value === "string" && value.includes(":")) {
1278
+ value = value.split(":")[1];
1279
+ }
1280
+ if (value) {
1281
+ return address.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), String(value));
1282
+ }
1283
+ }
1284
+ }
1285
+ for (const resolved of resolvedInputs) {
1286
+ if (!resolved.input?.name) continue;
1287
+ const placeholder = `{{${resolved.input.name.toUpperCase().replace(/\s+/g, "_")}}}`;
1288
+ if (address === placeholder || address.includes(placeholder)) {
1289
+ let value = resolved.value;
1290
+ if (typeof value === "string" && value.includes(":")) {
1291
+ value = value.split(":")[1];
1292
+ }
1293
+ if (value) {
1294
+ return address.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), String(value));
1295
+ }
1296
+ }
1297
+ }
1298
+ return address;
1299
+ }
1300
+ async createTokenTransferTransaction(executable, userWallet, destinationPubkey) {
1301
+ if (executable.transfers.length === 0) throw new Error("WarpSolanaExecutor: No transfers provided");
1302
+ if (!this.chain.nativeToken?.identifier) throw new Error("WarpSolanaExecutor: No native token defined for this chain");
1303
+ const nativeId = this.chain.nativeToken.identifier;
1304
+ const nativeTokenTransfers = executable.transfers.filter((t) => t.identifier === nativeId || t.identifier === WarpSolanaConstants.NativeToken.Identifier);
1305
+ const splTokenTransfers = executable.transfers.filter((t) => t.identifier !== nativeId && t.identifier !== WarpSolanaConstants.NativeToken.Identifier);
1306
+ if (nativeTokenTransfers.length === 1 && splTokenTransfers.length === 0) {
1307
+ const transfer = nativeTokenTransfers[0];
1308
+ if (transfer.amount <= 0n) throw new Error("WarpSolanaExecutor: Native token transfer amount must be positive");
1309
+ const fromPubkey = new import_web34.PublicKey(userWallet);
1310
+ return this.setTransactionDefaults([import_web34.SystemProgram.transfer({ fromPubkey, toPubkey: destinationPubkey, lamports: Number(transfer.amount) })], fromPubkey);
1311
+ }
1312
+ if (nativeTokenTransfers.length === 0 && splTokenTransfers.length === 1) {
1313
+ return this.createSingleTokenTransfer(executable, splTokenTransfers[0], userWallet, destinationPubkey);
1314
+ }
1315
+ if (executable.transfers.length > 1) throw new Error("WarpSolanaExecutor: Multiple token transfers not yet supported");
1316
+ throw new Error("WarpSolanaExecutor: Invalid transfer configuration");
1317
+ }
1318
+ async createSingleTokenTransfer(executable, transfer, userWallet, destinationPubkey) {
1319
+ const mintAddress = new import_web34.PublicKey(transfer.identifier);
1320
+ const fromPubkey = new import_web34.PublicKey(userWallet);
1321
+ const sourceTokenAccount = await (0, import_spl_token2.getAssociatedTokenAddress)(mintAddress, fromPubkey);
1322
+ const destinationTokenAccount = await (0, import_spl_token2.getAssociatedTokenAddress)(mintAddress, destinationPubkey);
1323
+ if (!await this.connection.getAccountInfo(sourceTokenAccount)) {
1324
+ throw new Error("WarpSolanaExecutor: Source token account does not exist");
1325
+ }
1326
+ const instructions = [];
1327
+ if (!await this.connection.getAccountInfo(destinationTokenAccount)) {
1328
+ instructions.push((0, import_spl_token2.createAssociatedTokenAccountInstruction)(fromPubkey, destinationTokenAccount, destinationPubkey, mintAddress));
1329
+ }
1330
+ instructions.push((0, import_spl_token2.createTransferInstruction)(sourceTokenAccount, destinationTokenAccount, fromPubkey, Number(transfer.amount)));
1331
+ return this.setTransactionDefaults(instructions, fromPubkey);
1332
+ }
1333
+ async executeQuery(executable) {
1334
+ const action = (0, import_warps8.getWarpActionByIndex)(executable.warp, executable.action);
1335
+ if (action.type !== "query") throw new Error(`WarpSolanaExecutor: Invalid action type for executeQuery: ${action.type}`);
1336
+ if (!action.func) throw new Error("WarpSolanaExecutor: Query action must have a function name");
1337
+ if (!executable.destination) throw new Error("WarpSolanaExecutor: Query address is required");
1338
+ const queryAddress = new import_web34.PublicKey(executable.destination);
1339
+ const nativeArgs = executable.args.map((arg) => this.serializer.coreSerializer.stringToNative(arg)[1]);
1340
+ let decodedResult = [];
1341
+ let isSuccess = true;
1342
+ if (action.func === "getAccount" || action.func === "getAccountInfo") {
1343
+ const accountInfo = await this.connection.getAccountInfo(queryAddress);
1344
+ if (!accountInfo) {
1345
+ throw new Error("Account not found");
1346
+ }
1347
+ decodedResult = [
1348
+ accountInfo.lamports,
1349
+ accountInfo.owner.toBase58(),
1350
+ accountInfo.executable,
1351
+ accountInfo.rentEpoch,
1352
+ accountInfo.data.toString("base64")
1353
+ ];
1354
+ } else if (action.func === "getBalance") {
1355
+ const balance = await this.connection.getBalance(queryAddress);
1356
+ decodedResult = [balance.toString()];
1357
+ } else if (action.func === "getProgramAccounts") {
1358
+ const accounts = await this.connection.getProgramAccounts(queryAddress);
1359
+ decodedResult = accounts.map((acc) => ({
1360
+ pubkey: acc.pubkey.toBase58(),
1361
+ account: {
1362
+ lamports: acc.account.lamports,
1363
+ owner: acc.account.owner.toBase58(),
1364
+ data: acc.account.data.toString("base64")
1365
+ }
1366
+ }));
1367
+ } else {
1368
+ const accountInfo = await this.connection.getAccountInfo(queryAddress);
1369
+ if (!accountInfo) {
1370
+ throw new Error("Account not found");
1371
+ }
1372
+ decodedResult = [accountInfo.data.toString("base64")];
1373
+ }
1374
+ const { values, output } = await this.output.extractQueryOutput(executable.warp, decodedResult, executable.action, executable.resolvedInputs);
1375
+ const next = (0, import_warps8.getNextInfo)(this.config, [], executable.warp, executable.action, output);
1376
+ const destinationInput = executable.resolvedInputs.find((i) => i.input.position === "receiver" || i.input.position === "destination");
1377
+ const destination = destinationInput?.value || executable.destination;
1378
+ const resolvedInputs = (0, import_warps8.extractResolvedInputValues)(executable.resolvedInputs);
1379
+ return {
1380
+ status: isSuccess ? "success" : "error",
1381
+ warp: executable.warp,
1382
+ action: executable.action,
1383
+ user: (0, import_warps8.getWarpWalletAddressFromConfig)(this.config, executable.chain.name),
1384
+ txHash: null,
1385
+ tx: null,
1386
+ next,
1387
+ values,
1388
+ output: { ...output, _DATA: decodedResult },
1389
+ messages: (0, import_warps8.applyOutputToMessages)(executable.warp, output, this.config),
1390
+ destination,
1391
+ resolvedInputs
1392
+ };
1393
+ }
1394
+ async verifyMessage(message, signature) {
1395
+ try {
1396
+ const messageBytes = new TextEncoder().encode(message);
1397
+ const signatureBytes = Buffer.from(signature, "base64");
1398
+ return "";
1399
+ } catch (error) {
1400
+ throw new Error(`Failed to verify message: ${error}`);
1401
+ }
1402
+ }
1403
+ async setTransactionDefaults(instructions, fromPubkey) {
1404
+ const { blockhash } = await this.connection.getLatestBlockhash("confirmed");
1405
+ const allInstructions = this.addComputeBudgetInstructions(instructions);
1406
+ const accountMetaMap = this.buildAccountMetaMap(allInstructions, fromPubkey);
1407
+ const { signedAccounts, unsignedAccounts } = this.sortAccounts(accountMetaMap);
1408
+ const { staticAccountKeys, accountIndexMap } = this.buildAccountIndexMap(signedAccounts, unsignedAccounts);
1409
+ const compiledInstructions = this.compileInstructions(allInstructions, accountIndexMap);
1410
+ const messageV0 = this.buildMessageV0(blockhash, signedAccounts, unsignedAccounts, accountMetaMap, staticAccountKeys, compiledInstructions);
1411
+ const versionedTx = new import_web34.VersionedTransaction(messageV0);
1412
+ if (versionedTx.version !== 0) {
1413
+ throw new Error(`Expected VersionedTransaction v0, got version: ${versionedTx.version}`);
1414
+ }
1415
+ return versionedTx;
1416
+ }
1417
+ toPublicKey(address, errorMsg) {
1418
+ try {
1419
+ return new import_web34.PublicKey(address);
1420
+ } catch {
1421
+ throw new Error(`WarpSolanaExecutor: ${errorMsg}`);
1422
+ }
1423
+ }
1424
+ extractContractArgs(executable) {
1425
+ if (executable.args.length > 0) return executable.args;
1426
+ if (executable.resolvedInputs.length === 0) return [];
1427
+ const argInputs = executable.resolvedInputs.filter((ri) => ri.input.position?.toString().startsWith("arg:")).map((ri) => {
1428
+ const index = Math.max(0, parseInt(ri.input.position.toString().split(":")[1] || "0", 10) - 1);
1429
+ return { index, value: ri.value };
1430
+ }).sort((a, b) => a.index - b.index);
1431
+ const maxIndex = Math.max(...argInputs.map((a) => a.index), -1);
1432
+ if (maxIndex < 0) return [];
1433
+ const args = new Array(maxIndex + 1).fill(null);
1434
+ argInputs.forEach(({ index, value }) => {
1435
+ if (value) args[index] = value;
1436
+ });
1437
+ return args.filter((arg) => arg !== null && arg !== void 0);
1438
+ }
1439
+ buildInstructionData(action, nativeArgs) {
1440
+ if (!action.abi || typeof action.abi !== "string") {
1441
+ return this.encodeBasicInstructionData(nativeArgs, action.func);
1442
+ }
1443
+ try {
1444
+ const abi = JSON.parse(action.abi);
1445
+ if (abi.instructions && abi.instructions[action.func]) {
1446
+ return this.encodeInstructionData(abi.instructions[action.func], nativeArgs, action.func);
1447
+ }
1448
+ } catch {
1449
+ }
1450
+ return this.encodeBasicInstructionData(nativeArgs, action.func);
1451
+ }
1452
+ extractAccountAddress(accountDef) {
1453
+ if (typeof accountDef === "string") return accountDef;
1454
+ if (!accountDef || typeof accountDef !== "object") return void 0;
1455
+ const str = JSON.stringify(accountDef);
1456
+ if (str.includes("USER_WALLET") || str.includes("{{USER_WALLET}}")) return "{{USER_WALLET}}";
1457
+ if (str.includes("RECEIVER_ADDRESS") || str.includes("{{RECEIVER_ADDRESS}}")) return "{{RECEIVER_ADDRESS}}";
1458
+ if (str.includes("USER_ATA")) {
1459
+ const match = str.match(/USER_ATA[:\s]*([^"}\s]+)/);
1460
+ if (match) return `{{USER_ATA:${match[1]}}}`;
1461
+ }
1462
+ const addrValue = accountDef.address || accountDef.pubkey || accountDef.value;
1463
+ if (typeof addrValue === "string") return addrValue;
1464
+ if (addrValue?.toBase58) return addrValue.toBase58();
1465
+ if (addrValue?.identifier) return addrValue.identifier;
1466
+ if (addrValue?.value) return addrValue.value;
1467
+ const keys = Object.keys(accountDef);
1468
+ if (keys.length === 1 && typeof accountDef[keys[0]] === "string") return accountDef[keys[0]];
1469
+ return void 0;
1470
+ }
1471
+ async resolveAccountPubkey(address, fromPubkey) {
1472
+ if (address.includes("{{USER_WALLET}}") || address === fromPubkey.toBase58()) {
1473
+ return fromPubkey;
1474
+ }
1475
+ if (address.startsWith("{{USER_ATA:") && address.endsWith("}}")) {
1476
+ const mintAddress = address.slice(11, -2);
1477
+ if (!mintAddress || mintAddress.includes("{{")) {
1478
+ throw new Error(`Invalid USER_ATA placeholder: ${address}. Mint address must be resolved first.`);
1479
+ }
1480
+ const mintPubkey = new import_web34.PublicKey(mintAddress);
1481
+ return await (0, import_spl_token2.getAssociatedTokenAddress)(mintPubkey, fromPubkey);
1482
+ }
1483
+ if (address.startsWith("{{RECEIVER_ATA:") && address.endsWith("}}")) {
1484
+ const content = address.slice(15, -2);
1485
+ const parts = content.split(":");
1486
+ if (parts.length === 2) {
1487
+ let mintAddress = parts[0];
1488
+ let receiverAddress = parts[1];
1489
+ if (mintAddress.includes("{{") || receiverAddress.includes("{{")) {
1490
+ throw new Error(`Invalid RECEIVER_ATA placeholder: ${address}. Mint and receiver addresses must be resolved first.`);
1491
+ }
1492
+ if (mintAddress.includes(":")) mintAddress = mintAddress.split(":")[1];
1493
+ if (receiverAddress.includes(":")) receiverAddress = receiverAddress.split(":")[1];
1494
+ const mintPubkey = new import_web34.PublicKey(mintAddress);
1495
+ const receiverPubkey = new import_web34.PublicKey(receiverAddress);
1496
+ return await (0, import_spl_token2.getAssociatedTokenAddress)(mintPubkey, receiverPubkey);
1497
+ }
1498
+ }
1499
+ return new import_web34.PublicKey(address);
1500
+ }
1501
+ determineAccountFlags(accountDef, pubkey, fromPubkey) {
1502
+ const accountMeta = typeof accountDef === "object" ? accountDef : {};
1503
+ if (pubkey.equals(fromPubkey)) {
1504
+ return { isSigner: true, isWritable: true };
1505
+ }
1506
+ const isSigner = accountMeta.signer === true;
1507
+ const isWritable = typeof accountDef === "object" && accountMeta.writable !== void 0 ? accountMeta.writable !== false : true;
1508
+ return { isSigner, isWritable };
1509
+ }
1510
+ addComputeBudgetInstructions(instructions) {
1511
+ const hasTokenTransfer = instructions.some((ix) => ix.programId.toBase58() === WarpSolanaConstants.Programs.TokenProgram);
1512
+ const computeUnits = hasTokenTransfer ? WarpSolanaConstants.ComputeUnitLimit.TokenTransfer : WarpSolanaConstants.ComputeUnitLimit.Default;
1513
+ const computeUnitLimitIx = import_web34.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits });
1514
+ const computeUnitPriceIx = import_web34.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: WarpSolanaConstants.PriorityFee.Default });
1515
+ return [computeUnitLimitIx, computeUnitPriceIx, ...instructions];
1516
+ }
1517
+ buildAccountMetaMap(instructions, fromPubkey) {
1518
+ const accountMetaMap = /* @__PURE__ */ new Map();
1519
+ if (fromPubkey) {
1520
+ accountMetaMap.set(fromPubkey.toBase58(), { pubkey: fromPubkey, isSigner: true, isWritable: true });
1521
+ }
1522
+ for (const ix of instructions) {
1523
+ const programIdStr = ix.programId.toBase58();
1524
+ if (!accountMetaMap.has(programIdStr)) {
1525
+ accountMetaMap.set(programIdStr, { pubkey: ix.programId, isSigner: false, isWritable: false });
1526
+ }
1527
+ for (const key of ix.keys) {
1528
+ const keyStr = key.pubkey.toBase58();
1529
+ const existing = accountMetaMap.get(keyStr);
1530
+ if (existing) {
1531
+ accountMetaMap.set(keyStr, {
1532
+ pubkey: key.pubkey,
1533
+ isSigner: existing.isSigner || key.isSigner,
1534
+ isWritable: existing.isWritable || key.isWritable
1535
+ });
1536
+ } else {
1537
+ accountMetaMap.set(keyStr, {
1538
+ pubkey: key.pubkey,
1539
+ isSigner: key.isSigner,
1540
+ isWritable: key.isWritable
1541
+ });
1542
+ }
1543
+ }
1544
+ }
1545
+ return accountMetaMap;
1546
+ }
1547
+ sortAccounts(accountMetaMap) {
1548
+ const signedAccounts = [];
1549
+ const unsignedAccounts = [];
1550
+ for (const meta of accountMetaMap.values()) {
1551
+ ;
1552
+ (meta.isSigner ? signedAccounts : unsignedAccounts).push(meta.pubkey);
1553
+ }
1554
+ const sortByWritable = (a, b) => (accountMetaMap.get(a.toBase58()).isWritable ? 0 : 1) - (accountMetaMap.get(b.toBase58()).isWritable ? 0 : 1);
1555
+ signedAccounts.sort(sortByWritable);
1556
+ unsignedAccounts.sort(sortByWritable);
1557
+ return { signedAccounts, unsignedAccounts };
1558
+ }
1559
+ buildAccountIndexMap(signedAccounts, unsignedAccounts) {
1560
+ const staticAccountKeys = [...signedAccounts, ...unsignedAccounts];
1561
+ const accountIndexMap = /* @__PURE__ */ new Map();
1562
+ staticAccountKeys.forEach((key, index) => {
1563
+ accountIndexMap.set(key.toBase58(), index);
1564
+ });
1565
+ return { staticAccountKeys, accountIndexMap };
1566
+ }
1567
+ compileInstructions(instructions, accountIndexMap) {
1568
+ return instructions.map((ix) => {
1569
+ const programIdIndex = accountIndexMap.get(ix.programId.toBase58());
1570
+ const accountKeyIndexes = ix.keys.map((key) => accountIndexMap.get(key.pubkey.toBase58()));
1571
+ return {
1572
+ programIdIndex,
1573
+ accountKeyIndexes,
1574
+ data: Uint8Array.from(ix.data)
1575
+ };
1576
+ });
1577
+ }
1578
+ buildMessageV0(blockhash, signedAccounts, unsignedAccounts, accountMetaMap, staticAccountKeys, compiledInstructions) {
1579
+ const getWritable = (key) => accountMetaMap.get(key.toBase58()).isWritable;
1580
+ return new import_web34.MessageV0({
1581
+ header: {
1582
+ numRequiredSignatures: signedAccounts.length,
1583
+ numReadonlySignedAccounts: signedAccounts.filter((k) => !getWritable(k)).length,
1584
+ numReadonlyUnsignedAccounts: unsignedAccounts.filter((k) => !getWritable(k)).length
1585
+ },
1586
+ staticAccountKeys,
1587
+ recentBlockhash: blockhash,
1588
+ compiledInstructions,
1589
+ addressTableLookups: []
1590
+ });
1591
+ }
1592
+ };
1593
+
1594
+ // src/WarpSolanaExplorer.ts
1595
+ var WarpSolanaExplorer = class {
1596
+ constructor(chain, config) {
1597
+ this.chain = chain;
1598
+ this.config = config;
1599
+ }
1600
+ getExplorers() {
1601
+ const explorers = SolanaExplorerNames[this.config.env];
1602
+ if (!explorers) {
1603
+ return ["solscan_mainnet" /* SolscanMainnet */];
1604
+ }
1605
+ return explorers;
1606
+ }
1607
+ getPrimaryExplorer() {
1608
+ const explorers = this.getExplorers();
1609
+ return explorers[0];
1610
+ }
1611
+ getExplorerUrlByName(explorer) {
1612
+ const userPreference = this.config.preferences?.explorers?.[this.chain.name];
1613
+ if (userPreference && !explorer) {
1614
+ const url2 = SolanaExplorerUrls[userPreference];
1615
+ if (url2) return url2;
1616
+ }
1617
+ if (explorer) {
1618
+ const url2 = SolanaExplorerUrls[explorer];
1619
+ if (url2) return url2;
1620
+ }
1621
+ const primaryExplorer = this.getPrimaryExplorer();
1622
+ const url = SolanaExplorerUrls[primaryExplorer];
1623
+ return url || SolanaExplorerUrls[primaryExplorer];
1624
+ }
1625
+ getAccountUrl(address, explorer) {
1626
+ const baseUrl = this.getExplorerUrlByName(explorer);
1627
+ if (baseUrl.includes("?")) {
1628
+ const cluster2 = this.config.env === "mainnet" ? "" : `&cluster=${this.config.env}`;
1629
+ return `${baseUrl}/account/${address}${cluster2}`;
1630
+ }
1631
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1632
+ return `${baseUrl}/account/${address}${cluster}`;
1633
+ }
1634
+ getTransactionUrl(hash, explorer) {
1635
+ const baseUrl = this.getExplorerUrlByName(explorer);
1636
+ if (baseUrl.includes("?")) {
1637
+ const cluster2 = this.config.env === "mainnet" ? "" : `&cluster=${this.config.env}`;
1638
+ return `${baseUrl}/tx/${hash}${cluster2}`;
1639
+ }
1640
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1641
+ return `${baseUrl}/tx/${hash}${cluster}`;
1642
+ }
1643
+ getBlockUrl(blockNumber, explorer) {
1644
+ const baseUrl = this.getExplorerUrlByName(explorer);
1645
+ if (baseUrl.includes("?")) {
1646
+ const cluster2 = this.config.env === "mainnet" ? "" : `&cluster=${this.config.env}`;
1647
+ return `${baseUrl}/block/${blockNumber}${cluster2}`;
1648
+ }
1649
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1650
+ return `${baseUrl}/block/${blockNumber}${cluster}`;
1651
+ }
1652
+ getAssetUrl(identifier, explorer) {
1653
+ const baseUrl = this.getExplorerUrlByName(explorer);
1654
+ if (baseUrl.includes("?")) {
1655
+ const cluster2 = this.config.env === "mainnet" ? "" : `&cluster=${this.config.env}`;
1656
+ return `${baseUrl}/token/${identifier}${cluster2}`;
1657
+ }
1658
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1659
+ return `${baseUrl}/token/${identifier}${cluster}`;
1660
+ }
1661
+ getContractUrl(address, explorer) {
1662
+ const baseUrl = this.getExplorerUrlByName(explorer);
1663
+ if (baseUrl.includes("?")) {
1664
+ const cluster2 = this.config.env === "mainnet" ? "" : `&cluster=${this.config.env}`;
1665
+ return `${baseUrl}/account/${address}${cluster2}`;
1666
+ }
1667
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1668
+ return `${baseUrl}/account/${address}${cluster}`;
1669
+ }
1670
+ getAllExplorers() {
1671
+ return this.getExplorers();
1672
+ }
1673
+ getExplorerByName(name) {
1674
+ const explorers = this.getExplorers();
1675
+ return explorers.find((explorer) => explorer.toLowerCase() === name.toLowerCase());
1676
+ }
1677
+ getAccountUrls(address) {
1678
+ const explorers = this.getAllExplorers();
1679
+ const urls = {};
1680
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1681
+ explorers.forEach((explorer) => {
1682
+ const url = SolanaExplorerUrls[explorer];
1683
+ if (url) {
1684
+ urls[explorer] = `${url}/account/${address}${cluster}`;
1685
+ }
1686
+ });
1687
+ return urls;
1688
+ }
1689
+ getTransactionUrls(hash) {
1690
+ const explorers = this.getAllExplorers();
1691
+ const urls = {};
1692
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1693
+ explorers.forEach((explorer) => {
1694
+ const url = SolanaExplorerUrls[explorer];
1695
+ if (url) {
1696
+ urls[explorer] = `${url}/tx/${hash}${cluster}`;
1697
+ }
1698
+ });
1699
+ return urls;
1700
+ }
1701
+ getAssetUrls(identifier) {
1702
+ const explorers = this.getAllExplorers();
1703
+ const urls = {};
1704
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1705
+ explorers.forEach((explorer) => {
1706
+ const url = SolanaExplorerUrls[explorer];
1707
+ if (url) {
1708
+ urls[explorer] = `${url}/token/${identifier}${cluster}`;
1709
+ }
1710
+ });
1711
+ return urls;
1712
+ }
1713
+ getContractUrls(address) {
1714
+ const explorers = this.getAllExplorers();
1715
+ const urls = {};
1716
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1717
+ explorers.forEach((explorer) => {
1718
+ const url = SolanaExplorerUrls[explorer];
1719
+ if (url) {
1720
+ urls[explorer] = `${url}/account/${address}${cluster}`;
1721
+ }
1722
+ });
1723
+ return urls;
1724
+ }
1725
+ getBlockUrls(blockNumber) {
1726
+ const explorers = this.getAllExplorers();
1727
+ const urls = {};
1728
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1729
+ explorers.forEach((explorer) => {
1730
+ const url = SolanaExplorerUrls[explorer];
1731
+ if (url) {
1732
+ urls[explorer] = `${url}/block/${blockNumber}${cluster}`;
1733
+ }
1734
+ });
1735
+ return urls;
1736
+ }
1737
+ };
1738
+
1739
+ // src/WarpSolanaWallet.ts
1740
+ var import_kit = require("@solana/kit");
1741
+ var import_web37 = require("@solana/web3.js");
1742
+ var import_warps12 = require("@joai/warps");
1743
+ var import_client = require("@x402/svm/exact/client");
1744
+
1745
+ // src/providers/MnemonicWalletProvider.ts
1746
+ var bip39 = __toESM(require("@scure/bip39"), 1);
1747
+ var import_english = require("@scure/bip39/wordlists/english.js");
1748
+ var import_web35 = require("@solana/web3.js");
1749
+ var import_warps9 = require("@joai/warps");
1750
+ var import_bs582 = __toESM(require("bs58"), 1);
1751
+ var _MnemonicWalletProvider = class _MnemonicWalletProvider {
1752
+ constructor(config, chain) {
1753
+ this.config = config;
1754
+ this.chain = chain;
1755
+ this.keypair = null;
1756
+ }
1757
+ async getAddress() {
1758
+ const address = (0, import_warps9.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
1759
+ if (address) return address;
1760
+ try {
1761
+ const keypair = this.getKeypair();
1762
+ return keypair.publicKey.toBase58();
1763
+ } catch {
1764
+ return null;
1765
+ }
1766
+ }
1767
+ async getPublicKey() {
1768
+ try {
1769
+ const keypair = this.getKeypair();
1770
+ return keypair.publicKey.toBase58();
1771
+ } catch {
1772
+ return null;
1773
+ }
1774
+ }
1775
+ async signTransaction(tx) {
1776
+ const keypair = this.getKeypair();
1777
+ if (tx instanceof import_web35.VersionedTransaction) {
1778
+ tx.sign([keypair]);
1779
+ return tx;
1780
+ }
1781
+ if (tx instanceof import_web35.Transaction) {
1782
+ tx.sign(keypair);
1783
+ return tx;
1784
+ }
1785
+ if (tx.transaction) {
1786
+ if (tx.transaction instanceof import_web35.Transaction) {
1787
+ tx.transaction.sign(keypair);
1788
+ return { ...tx, transaction: tx.transaction.serialize() };
1789
+ }
1790
+ if (typeof tx.transaction === "object") {
1791
+ try {
1792
+ const transaction = import_web35.Transaction.from(tx.transaction);
1793
+ transaction.sign(keypair);
1794
+ return { ...tx, transaction: transaction.serialize(), signature: transaction.signature };
1795
+ } catch {
1796
+ throw new Error("Invalid transaction format");
1797
+ }
1798
+ }
1799
+ }
1800
+ throw new Error("Invalid transaction format");
1801
+ }
1802
+ async signMessage(message) {
1803
+ const keypair = this.getKeypair();
1804
+ const messageBytes = new TextEncoder().encode(message);
1805
+ const nacl = await import("tweetnacl");
1806
+ const secretKey = keypair.secretKey;
1807
+ if (secretKey.length !== 64) {
1808
+ throw new Error(`Invalid secret key length: expected 64, got ${secretKey.length}`);
1809
+ }
1810
+ const privateKeySlice = secretKey.slice(0, 32);
1811
+ const privateKeyBytes = new Uint8Array(privateKeySlice);
1812
+ if (privateKeyBytes.length !== 32) {
1813
+ throw new Error(`Invalid private key length: expected 32, got ${privateKeyBytes.length}`);
1814
+ }
1815
+ const signature = nacl.sign.detached(messageBytes, privateKeyBytes);
1816
+ return import_bs582.default.encode(signature);
1817
+ }
1818
+ getKeypairInstance() {
1819
+ return this.getKeypair();
1820
+ }
1821
+ async importFromMnemonic(mnemonic) {
1822
+ const trimmedMnemonic = (0, import_warps9.normalizeAndValidateMnemonic)(mnemonic);
1823
+ const seed = bip39.mnemonicToSeedSync(trimmedMnemonic);
1824
+ const keypair = import_web35.Keypair.fromSeed(seed.slice(0, 32));
1825
+ const walletDetails = {
1826
+ provider: _MnemonicWalletProvider.PROVIDER_NAME,
1827
+ address: keypair.publicKey.toBase58(),
1828
+ privateKey: import_bs582.default.encode(keypair.secretKey),
1829
+ mnemonic: trimmedMnemonic
1830
+ };
1831
+ (0, import_warps9.setWarpWalletInConfig)(this.config, this.chain.name, walletDetails);
1832
+ return walletDetails;
1833
+ }
1834
+ async importFromPrivateKey(privateKey) {
1835
+ const keypair = import_web35.Keypair.fromSecretKey(import_bs582.default.decode(privateKey));
1836
+ const walletDetails = {
1837
+ provider: _MnemonicWalletProvider.PROVIDER_NAME,
1838
+ address: keypair.publicKey.toBase58(),
1839
+ privateKey: import_bs582.default.encode(keypair.secretKey),
1840
+ mnemonic: null
1841
+ };
1842
+ (0, import_warps9.setWarpWalletInConfig)(this.config, this.chain.name, walletDetails);
1843
+ return walletDetails;
1844
+ }
1845
+ async export() {
1846
+ const keypair = this.getKeypair();
1847
+ const mnemonic = (0, import_warps9.getWarpWalletMnemonicFromConfig)(this.config, this.chain.name);
1848
+ const privateKey = (0, import_warps9.getWarpWalletPrivateKeyFromConfig)(this.config, this.chain.name);
1849
+ return {
1850
+ provider: _MnemonicWalletProvider.PROVIDER_NAME,
1851
+ address: keypair.publicKey.toBase58(),
1852
+ privateKey: privateKey || null,
1853
+ mnemonic: mnemonic || null
1854
+ };
1855
+ }
1856
+ async generate() {
1857
+ const mnemonicRaw = bip39.generateMnemonic(import_english.wordlist, 256);
1858
+ const mnemonic = (0, import_warps9.normalizeMnemonic)(mnemonicRaw);
1859
+ (0, import_warps9.validateMnemonicLength)(mnemonic);
1860
+ const seed = bip39.mnemonicToSeedSync(mnemonic);
1861
+ const keypair = import_web35.Keypair.fromSeed(seed.slice(0, 32));
1862
+ return {
1863
+ provider: _MnemonicWalletProvider.PROVIDER_NAME,
1864
+ address: keypair.publicKey.toBase58(),
1865
+ privateKey: null,
1866
+ mnemonic
1867
+ };
1868
+ }
1869
+ getKeypair() {
1870
+ if (this.keypair) return this.keypair;
1871
+ const mnemonic = (0, import_warps9.getWarpWalletMnemonicFromConfig)(this.config, this.chain.name);
1872
+ if (!mnemonic) throw new Error("No mnemonic provided");
1873
+ const seed = bip39.mnemonicToSeedSync(mnemonic);
1874
+ this.keypair = import_web35.Keypair.fromSeed(seed.slice(0, 32));
1875
+ return this.keypair;
1876
+ }
1877
+ };
1878
+ _MnemonicWalletProvider.PROVIDER_NAME = "mnemonic";
1879
+ var MnemonicWalletProvider = _MnemonicWalletProvider;
1880
+
1881
+ // src/providers/PrivateKeyWalletProvider.ts
1882
+ var import_web36 = require("@solana/web3.js");
1883
+ var import_warps10 = require("@joai/warps");
1884
+ var import_bs583 = __toESM(require("bs58"), 1);
1885
+ var _PrivateKeyWalletProvider = class _PrivateKeyWalletProvider {
1886
+ constructor(config, chain) {
1887
+ this.config = config;
1888
+ this.chain = chain;
1889
+ this.keypair = null;
1890
+ }
1891
+ async getAddress() {
1892
+ const address = (0, import_warps10.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
1893
+ if (address) return address;
1894
+ try {
1895
+ const keypair = this.getKeypair();
1896
+ return keypair.publicKey.toBase58();
1897
+ } catch {
1898
+ return null;
1899
+ }
1900
+ }
1901
+ async getPublicKey() {
1902
+ try {
1903
+ const keypair = this.getKeypair();
1904
+ return keypair.publicKey.toBase58();
1905
+ } catch {
1906
+ return null;
1907
+ }
1908
+ }
1909
+ async signTransaction(tx) {
1910
+ const keypair = this.getKeypair();
1911
+ if (tx instanceof import_web36.VersionedTransaction) {
1912
+ tx.sign([keypair]);
1913
+ return tx;
1914
+ }
1915
+ if (tx instanceof import_web36.Transaction) {
1916
+ tx.sign(keypair);
1917
+ return tx;
1918
+ }
1919
+ if (tx.transaction) {
1920
+ if (tx.transaction instanceof import_web36.Transaction) {
1921
+ tx.transaction.sign(keypair);
1922
+ return { ...tx, transaction: tx.transaction.serialize() };
1923
+ }
1924
+ if (typeof tx.transaction === "object") {
1925
+ try {
1926
+ const transaction = import_web36.Transaction.from(tx.transaction);
1927
+ transaction.sign(keypair);
1928
+ return { ...tx, transaction: transaction.serialize(), signature: transaction.signature };
1929
+ } catch {
1930
+ throw new Error("Invalid transaction format");
1931
+ }
1932
+ }
1933
+ }
1934
+ throw new Error("Invalid transaction format");
1935
+ }
1936
+ async signMessage(message) {
1937
+ const keypair = this.getKeypair();
1938
+ const messageBytes = new TextEncoder().encode(message);
1939
+ const nacl = await import("tweetnacl");
1940
+ const secretKey = keypair.secretKey;
1941
+ if (secretKey.length !== 64) {
1942
+ throw new Error(`Invalid secret key length: expected 64, got ${secretKey.length}`);
1943
+ }
1944
+ const privateKeySlice = secretKey.slice(0, 32);
1945
+ const privateKeyBytes = new Uint8Array(privateKeySlice);
1946
+ if (privateKeyBytes.length !== 32) {
1947
+ throw new Error(`Invalid private key length: expected 32, got ${privateKeyBytes.length}`);
1948
+ }
1949
+ const signature = nacl.sign.detached(messageBytes, privateKeyBytes);
1950
+ return import_bs583.default.encode(signature);
1951
+ }
1952
+ getKeypairInstance() {
1953
+ return this.getKeypair();
1954
+ }
1955
+ async importFromMnemonic(mnemonic) {
1956
+ throw new Error("PrivateKeyWalletProvider does not support importing from mnemonics. Use MnemonicWalletProvider instead.");
1957
+ }
1958
+ async importFromPrivateKey(privateKey) {
1959
+ const keypair = import_web36.Keypair.fromSecretKey(import_bs583.default.decode(privateKey));
1960
+ const walletDetails = {
1961
+ provider: _PrivateKeyWalletProvider.PROVIDER_NAME,
1962
+ address: keypair.publicKey.toBase58(),
1963
+ privateKey: import_bs583.default.encode(keypair.secretKey),
1964
+ mnemonic: null
1965
+ };
1966
+ (0, import_warps10.setWarpWalletInConfig)(this.config, this.chain.name, walletDetails);
1967
+ return walletDetails;
1968
+ }
1969
+ async export() {
1970
+ const keypair = this.getKeypair();
1971
+ const privateKey = (0, import_warps10.getWarpWalletPrivateKeyFromConfig)(this.config, this.chain.name);
1972
+ const mnemonic = (0, import_warps10.getWarpWalletMnemonicFromConfig)(this.config, this.chain.name);
1973
+ return {
1974
+ provider: _PrivateKeyWalletProvider.PROVIDER_NAME,
1975
+ address: keypair.publicKey.toBase58(),
1976
+ privateKey: privateKey || null,
1977
+ mnemonic: mnemonic || null
1978
+ };
1979
+ }
1980
+ async generate() {
1981
+ const keypair = import_web36.Keypair.generate();
1982
+ return {
1983
+ provider: _PrivateKeyWalletProvider.PROVIDER_NAME,
1984
+ address: keypair.publicKey.toBase58(),
1985
+ privateKey: import_bs583.default.encode(keypair.secretKey),
1986
+ mnemonic: null
1987
+ };
1988
+ }
1989
+ getKeypair() {
1990
+ if (this.keypair) return this.keypair;
1991
+ const privateKey = (0, import_warps10.getWarpWalletPrivateKeyFromConfig)(this.config, this.chain.name);
1992
+ if (!privateKey) throw new Error("No private key provided");
1993
+ try {
1994
+ const secretKey = import_bs583.default.decode(privateKey);
1995
+ if (secretKey.length === 64) {
1996
+ this.keypair = import_web36.Keypair.fromSecretKey(secretKey);
1997
+ return this.keypair;
1998
+ } else if (secretKey.length === 32) {
1999
+ this.keypair = import_web36.Keypair.fromSeed(secretKey);
2000
+ return this.keypair;
2001
+ } else {
2002
+ throw new Error(`Invalid private key length: expected 32 or 64 bytes, got ${secretKey.length}`);
2003
+ }
2004
+ } catch (error) {
2005
+ if (error instanceof Error) {
2006
+ throw new Error(`Invalid private key format: ${error.message}`);
2007
+ }
2008
+ throw new Error("Invalid private key format");
2009
+ }
2010
+ }
2011
+ };
2012
+ _PrivateKeyWalletProvider.PROVIDER_NAME = "privateKey";
2013
+ var PrivateKeyWalletProvider = _PrivateKeyWalletProvider;
2014
+
2015
+ // src/providers/ReadOnlyWalletProvider.ts
2016
+ var import_warps11 = require("@joai/warps");
2017
+ var ReadOnlyWalletProvider = class {
2018
+ constructor(config, chain) {
2019
+ this.config = config;
2020
+ this.chain = chain;
2021
+ }
2022
+ async getAddress() {
2023
+ return (0, import_warps11.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
2024
+ }
2025
+ async getPublicKey() {
2026
+ return (0, import_warps11.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
2027
+ }
2028
+ async signTransaction(tx) {
2029
+ const address = await this.getAddress();
2030
+ throw new Error(`Wallet can not be used for signing: ${address}`);
2031
+ }
2032
+ async signMessage(message) {
2033
+ const address = await this.getAddress();
2034
+ throw new Error(`Wallet can not be used for signing: ${address}`);
2035
+ }
2036
+ async importFromMnemonic(mnemonic) {
2037
+ const address = (0, import_warps11.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
2038
+ throw new Error(`Wallet can not be used for signing: ${address}`);
2039
+ }
2040
+ async importFromPrivateKey(privateKey) {
2041
+ const address = (0, import_warps11.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
2042
+ throw new Error(`Wallet can not be used for signing: ${address}`);
2043
+ }
2044
+ async export() {
2045
+ const address = (0, import_warps11.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
2046
+ throw new Error(`Wallet can not be used for signing: ${address}`);
2047
+ }
2048
+ async generate() {
2049
+ const address = (0, import_warps11.getWarpWalletAddressFromConfig)(this.config, this.chain.name);
2050
+ throw new Error(`Wallet can not be used for signing: ${address}`);
2051
+ }
2052
+ };
2053
+
2054
+ // src/WarpSolanaWallet.ts
2055
+ var WarpSolanaWallet = class {
2056
+ constructor(config, chain) {
2057
+ this.config = config;
2058
+ this.chain = chain;
2059
+ this.cachedAddress = null;
2060
+ this.cachedPublicKey = null;
2061
+ const providerConfig = (0, import_warps12.getProviderConfig)(config, chain.name, config.env, chain.defaultApiUrl);
2062
+ this.connection = new import_web37.Connection(providerConfig.url, "confirmed");
2063
+ this.walletProvider = this.createProvider();
2064
+ this.initializeCache();
2065
+ }
2066
+ async signTransaction(tx) {
2067
+ if (!tx || typeof tx !== "object") throw new Error("Invalid transaction object");
2068
+ if (!this.walletProvider) throw new Error("No wallet provider available");
2069
+ if (this.walletProvider instanceof ReadOnlyWalletProvider) throw new Error(`Wallet (${this.chain.name}) is read-only`);
2070
+ return this.walletProvider.signTransaction(tx);
2071
+ }
2072
+ async signTransactions(txs) {
2073
+ return Promise.all(txs.map((tx) => this.signTransaction(tx)));
2074
+ }
2075
+ async signMessage(message) {
2076
+ if (!this.walletProvider) throw new Error("No wallet provider available");
2077
+ if (this.walletProvider instanceof ReadOnlyWalletProvider) throw new Error(`Wallet (${this.chain.name}) is read-only`);
2078
+ return this.walletProvider.signMessage(message);
2079
+ }
2080
+ async sendTransaction(tx) {
2081
+ if (!tx || typeof tx !== "object") throw new Error("Invalid transaction object");
2082
+ const transaction = this.resolveTransaction(tx);
2083
+ if (!transaction.signatures || transaction.signatures.length === 0 || !transaction.signatures.some((sig) => sig.some((b) => b !== 0))) {
2084
+ throw new Error("Transaction must be signed before sending");
2085
+ }
2086
+ try {
2087
+ const shouldSkipPreflight = await this.shouldSkipPreflight(transaction);
2088
+ return await this.sendWithRetry(transaction, shouldSkipPreflight);
2089
+ } catch (simError) {
2090
+ if (simError.message?.includes("MissingRequiredSignature")) {
2091
+ return await this.sendRawTransaction(transaction, { skipPreflight: true });
2092
+ }
2093
+ throw new Error(`Transaction send failed: ${simError?.message || String(simError)}`);
2094
+ }
2095
+ }
2096
+ async sendTransactions(txs) {
2097
+ return Promise.all(txs.map(async (tx) => this.sendTransaction(tx)));
2098
+ }
2099
+ async importFromMnemonic(mnemonic) {
2100
+ const walletProvider = this.createProviderForOperation("mnemonic");
2101
+ return await walletProvider.importFromMnemonic(mnemonic);
2102
+ }
2103
+ async importFromPrivateKey(privateKey) {
2104
+ const walletProvider = this.createProviderForOperation("privateKey");
2105
+ return await walletProvider.importFromPrivateKey(privateKey);
2106
+ }
2107
+ async export(provider) {
2108
+ const walletProvider = this.createProviderForOperation(provider);
2109
+ return await walletProvider.export();
2110
+ }
2111
+ async generate(provider) {
2112
+ const walletProvider = this.createProviderForOperation(provider);
2113
+ return await walletProvider.generate();
2114
+ }
2115
+ getAddress() {
2116
+ return this.cachedAddress;
2117
+ }
2118
+ getPublicKey() {
2119
+ return this.cachedPublicKey;
2120
+ }
2121
+ async registerX402Handlers(client) {
2122
+ if (!this.walletProvider) return {};
2123
+ const provider = this.walletProvider;
2124
+ const getKeypair = provider.getKeypairInstance;
2125
+ if (typeof getKeypair !== "function") return {};
2126
+ const keypair = getKeypair();
2127
+ if (!keypair || !keypair.secretKey) return {};
2128
+ const signer = await (0, import_kit.createKeyPairSignerFromBytes)(keypair.secretKey);
2129
+ const handlers = {};
2130
+ for (const network of SupportedX402SolanaNetworks) {
2131
+ handlers[network] = () => {
2132
+ (0, import_client.registerExactSvmScheme)(client, { signer });
2133
+ };
2134
+ }
2135
+ return handlers;
2136
+ }
2137
+ createProvider() {
2138
+ const wallet = this.config.user?.wallets?.[this.chain.name];
2139
+ if (!wallet) return null;
2140
+ if (typeof wallet === "string") return new ReadOnlyWalletProvider(this.config, this.chain);
2141
+ return this.createProviderForOperation(wallet.provider);
2142
+ }
2143
+ initializeCache() {
2144
+ (0, import_warps12.initializeWalletCache)(this.walletProvider).then((cache) => {
2145
+ this.cachedAddress = cache.address;
2146
+ this.cachedPublicKey = cache.publicKey;
2147
+ });
2148
+ }
2149
+ createProviderForOperation(provider) {
2150
+ const customWalletProviders = this.config.walletProviders?.[this.chain.name];
2151
+ const providerFactory = customWalletProviders?.[provider];
2152
+ if (providerFactory) {
2153
+ const walletProvider = providerFactory(this.config, this.chain);
2154
+ if (!walletProvider) throw new Error(`Custom wallet provider factory returned null for ${provider}`);
2155
+ return walletProvider;
2156
+ }
2157
+ if (provider === "privateKey") return new PrivateKeyWalletProvider(this.config, this.chain);
2158
+ if (provider === "mnemonic") return new MnemonicWalletProvider(this.config, this.chain);
2159
+ throw new Error(`Unsupported wallet provider for ${this.chain.name}: ${provider}`);
2160
+ }
2161
+ resolveTransaction(tx) {
2162
+ if (tx instanceof import_web37.VersionedTransaction) {
2163
+ if (tx.version === void 0 || tx.version === "legacy") {
2164
+ throw new Error("Transaction must be a VersionedTransaction (v0), not legacy");
2165
+ }
2166
+ return tx;
2167
+ }
2168
+ if (tx instanceof import_web37.Transaction) {
2169
+ throw new Error("Legacy Transaction format is not supported. All transactions must use VersionedTransaction (v0).");
2170
+ }
2171
+ if (tx.transaction instanceof import_web37.VersionedTransaction) {
2172
+ if (tx.transaction.version === void 0 || tx.transaction.version === "legacy") {
2173
+ throw new Error("Transaction must be a VersionedTransaction (v0), not legacy");
2174
+ }
2175
+ return tx.transaction;
2176
+ }
2177
+ if (tx.transaction instanceof import_web37.Transaction) {
2178
+ throw new Error("Legacy Transaction format is not supported. All transactions must use VersionedTransaction (v0).");
2179
+ }
2180
+ if (!tx.transaction) {
2181
+ throw new Error("Transaction must be signed before sending");
2182
+ }
2183
+ throw new Error("Invalid transaction format - only VersionedTransaction is supported");
2184
+ }
2185
+ async shouldSkipPreflight(transaction) {
2186
+ if (!transaction.signatures || transaction.signatures.length === 0 || !transaction.signatures.some((sig) => sig.some((b) => b !== 0))) {
2187
+ return false;
2188
+ }
2189
+ try {
2190
+ const simulation = await this.connection.simulateTransaction(transaction, {
2191
+ replaceRecentBlockhash: true,
2192
+ sigVerify: false
2193
+ });
2194
+ if (simulation.value.err) {
2195
+ const errMsg = JSON.stringify(simulation.value.err);
2196
+ if (errMsg.includes('"Custom": 17') || errMsg.includes('"Custom":17') || errMsg.includes("0x11")) {
2197
+ return true;
2198
+ }
2199
+ throw new Error(`Transaction simulation failed: ${errMsg}`);
2200
+ }
2201
+ } catch (error) {
2202
+ if (error.message?.includes("Transaction simulation failed")) throw error;
2203
+ }
2204
+ return false;
2205
+ }
2206
+ async sendWithRetry(transaction, skipPreflight) {
2207
+ if (skipPreflight) {
2208
+ return this.sendRawTransaction(transaction, { skipPreflight: true });
2209
+ }
2210
+ try {
2211
+ return await this.sendRawTransaction(transaction, { skipPreflight: false, preflightCommitment: "confirmed" });
2212
+ } catch (error) {
2213
+ if (this.isSimulationError(error)) {
2214
+ return this.sendRawTransaction(transaction, { skipPreflight: true });
2215
+ }
2216
+ throw error;
2217
+ }
2218
+ }
2219
+ async sendRawTransaction(transaction, options) {
2220
+ const signature = await this.connection.sendRawTransaction(transaction.serialize(), {
2221
+ skipPreflight: options.skipPreflight,
2222
+ maxRetries: options.maxRetries || 3,
2223
+ preflightCommitment: options.preflightCommitment
2224
+ });
2225
+ if (!signature || typeof signature !== "string" || signature.length < 32) {
2226
+ throw new Error("Invalid transaction signature received");
2227
+ }
2228
+ return signature;
2229
+ }
2230
+ isSimulationError(error) {
2231
+ const msg = error?.message?.toLowerCase() || "";
2232
+ return msg.includes("simulation") || msg.includes("preflight") || msg.includes("0x1") || msg.includes("custom program error");
2233
+ }
2234
+ };
2235
+
2236
+ // src/chains/common.ts
2237
+ var createSolanaAdapter = (chainName, chainInfos) => {
2238
+ return (config, fallback) => {
2239
+ if (!fallback) throw new Error(`${chainName} adapter requires a fallback adapter`);
2240
+ return {
2241
+ chainInfo: chainInfos[config.env],
2242
+ builder: () => fallback.builder(),
2243
+ executor: new WarpSolanaExecutor(config, chainInfos[config.env]),
2244
+ output: new WarpSolanaOutput(config, chainInfos[config.env]),
2245
+ serializer: new WarpSolanaSerializer(),
2246
+ registry: fallback.registry,
2247
+ explorer: new WarpSolanaExplorer(chainInfos[config.env], config),
2248
+ abiBuilder: () => fallback.abiBuilder(),
2249
+ brandBuilder: () => fallback.brandBuilder(),
2250
+ dataLoader: new WarpSolanaDataLoader(config, chainInfos[config.env]),
2251
+ wallet: new WarpSolanaWallet(config, chainInfos[config.env])
2252
+ };
2253
+ };
2254
+ };
2255
+
2256
+ // src/chains/solana.ts
2257
+ var NativeTokenSol = {
2258
+ chain: import_warps13.WarpChainName.Solana,
2259
+ identifier: "SOL",
2260
+ symbol: "SOL",
2261
+ name: "SOL",
2262
+ decimals: 9,
2263
+ logoUrl: "https://raw.githubusercontent.com/JoAiHQ/assets/refs/heads/main/tokens/logos/sol.svg"
2264
+ };
2265
+ var SolanaAdapter = createSolanaAdapter(import_warps13.WarpChainName.Solana, {
2266
+ mainnet: {
2267
+ name: import_warps13.WarpChainName.Solana,
2268
+ displayName: "Solana Mainnet",
2269
+ chainId: "101",
2270
+ blockTime: 400,
2271
+ addressHrp: "",
2272
+ defaultApiUrl: "https://api.mainnet-beta.solana.com",
2273
+ logoUrl: "https://raw.githubusercontent.com/JoAiHQ/assets/refs/heads/main/chains/logos/solana.svg",
2274
+ nativeToken: NativeTokenSol
2275
+ },
2276
+ testnet: {
2277
+ name: import_warps13.WarpChainName.Solana,
2278
+ displayName: "Solana Testnet",
2279
+ chainId: "103",
2280
+ blockTime: 400,
2281
+ addressHrp: "",
2282
+ defaultApiUrl: "https://api.testnet.solana.com",
2283
+ logoUrl: "https://raw.githubusercontent.com/JoAiHQ/assets/refs/heads/main/chains/logos/solana.svg",
2284
+ nativeToken: NativeTokenSol
2285
+ },
2286
+ devnet: {
2287
+ name: import_warps13.WarpChainName.Solana,
2288
+ displayName: "Solana Devnet",
2289
+ chainId: "103",
2290
+ blockTime: 400,
2291
+ addressHrp: "",
2292
+ defaultApiUrl: "https://api.devnet.solana.com",
2293
+ logoUrl: "https://raw.githubusercontent.com/JoAiHQ/assets/refs/heads/main/chains/logos/solana.svg",
2294
+ nativeToken: NativeTokenSol
2295
+ }
2296
+ });
2297
+ // Annotate the CommonJS export names for ESM import in node:
2298
+ 0 && (module.exports = {
2299
+ ExplorerUrls,
2300
+ KnownTokens,
2301
+ NativeTokenSol,
2302
+ SolanaAdapter,
2303
+ SolanaExplorerMap,
2304
+ SolanaExplorerNames,
2305
+ SolanaExplorerUrls,
2306
+ SolanaExplorers,
2307
+ SupportedX402SolanaNetworks,
2308
+ WarpSolanaConstants,
2309
+ WarpSolanaDataLoader,
2310
+ WarpSolanaExecutor,
2311
+ WarpSolanaExplorer,
2312
+ WarpSolanaOutput,
2313
+ WarpSolanaSerializer,
2314
+ WarpSolanaWallet,
2315
+ X402SolanaNetworkIdentifiers,
2316
+ findKnownTokenById,
2317
+ getKnownTokensForChain
2318
+ });
2319
+ //# sourceMappingURL=index.js.map