@vleap/warps-adapter-solana 0.1.0-beta.1

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,1549 @@
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
+ SolanaExplorerMap: () => SolanaExplorerMap,
37
+ SolanaExplorerNames: () => SolanaExplorerNames,
38
+ SolanaExplorerUrls: () => SolanaExplorerUrls,
39
+ SolanaExplorers: () => SolanaExplorers,
40
+ WarpSolanaConstants: () => WarpSolanaConstants,
41
+ WarpSolanaDataLoader: () => WarpSolanaDataLoader,
42
+ WarpSolanaExecutor: () => WarpSolanaExecutor,
43
+ WarpSolanaExplorer: () => WarpSolanaExplorer,
44
+ WarpSolanaOutput: () => WarpSolanaOutput,
45
+ WarpSolanaSerializer: () => WarpSolanaSerializer,
46
+ WarpSolanaWallet: () => WarpSolanaWallet,
47
+ findKnownTokenById: () => findKnownTokenById,
48
+ getKnownTokensForChain: () => getKnownTokensForChain,
49
+ getSolanaAdapter: () => getSolanaAdapter
50
+ });
51
+ module.exports = __toCommonJS(index_exports);
52
+
53
+ // src/WarpSolanaDataLoader.ts
54
+ var import_warps = require("@vleap/warps");
55
+ var import_web3 = require("@solana/web3.js");
56
+ var import_spl_token = require("@solana/spl-token");
57
+
58
+ // src/constants.ts
59
+ var WarpSolanaConstants = {
60
+ ComputeUnitLimit: {
61
+ Default: 2e5,
62
+ Transfer: 5e3,
63
+ TokenTransfer: 1e4,
64
+ ContractCall: 2e5
65
+ },
66
+ PriorityFee: {
67
+ Default: 1e3
68
+ },
69
+ Validation: {
70
+ MinComputeUnits: 1e3,
71
+ MaxComputeUnits: 14e5
72
+ },
73
+ Programs: {
74
+ TokenProgram: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
75
+ SystemProgram: "11111111111111111111111111111111"
76
+ },
77
+ NativeToken: {
78
+ Identifier: "SOL",
79
+ Decimals: 9
80
+ }
81
+ };
82
+ var SolanaExplorers = /* @__PURE__ */ ((SolanaExplorers2) => {
83
+ SolanaExplorers2["Solscan"] = "solscan";
84
+ SolanaExplorers2["SolscanMainnet"] = "solscan_mainnet";
85
+ SolanaExplorers2["SolscanDevnet"] = "solscan_devnet";
86
+ SolanaExplorers2["SolanaExplorer"] = "solana_explorer";
87
+ SolanaExplorers2["SolanaExplorerMainnet"] = "solana_explorer_mainnet";
88
+ SolanaExplorers2["SolanaExplorerDevnet"] = "solana_explorer_devnet";
89
+ return SolanaExplorers2;
90
+ })(SolanaExplorers || {});
91
+ var SolanaExplorerMap = {
92
+ solana: {
93
+ mainnet: ["solscan_mainnet" /* SolscanMainnet */, "solana_explorer_mainnet" /* SolanaExplorerMainnet */],
94
+ testnet: ["solscan" /* Solscan */, "solana_explorer" /* SolanaExplorer */],
95
+ devnet: ["solscan_devnet" /* SolscanDevnet */, "solana_explorer_devnet" /* SolanaExplorerDevnet */]
96
+ }
97
+ };
98
+ var ExplorerUrls = {
99
+ ["solscan" /* Solscan */]: "https://solscan.io",
100
+ ["solscan_mainnet" /* SolscanMainnet */]: "https://solscan.io",
101
+ ["solscan_devnet" /* SolscanDevnet */]: "https://solscan.io/?cluster=devnet",
102
+ ["solana_explorer" /* SolanaExplorer */]: "https://explorer.solana.com",
103
+ ["solana_explorer_mainnet" /* SolanaExplorerMainnet */]: "https://explorer.solana.com",
104
+ ["solana_explorer_devnet" /* SolanaExplorerDevnet */]: "https://explorer.solana.com/?cluster=devnet"
105
+ };
106
+ var SolanaExplorerNames = {
107
+ mainnet: ["solscan_mainnet" /* SolscanMainnet */, "solana_explorer_mainnet" /* SolanaExplorerMainnet */],
108
+ testnet: ["solscan" /* Solscan */, "solana_explorer" /* SolanaExplorer */],
109
+ devnet: ["solscan_devnet" /* SolscanDevnet */, "solana_explorer_devnet" /* SolanaExplorerDevnet */]
110
+ };
111
+ var SolanaExplorerUrls = ExplorerUrls;
112
+
113
+ // src/tokens/solana.ts
114
+ var SolanaChain = "solana";
115
+ var SolanaTokens = [
116
+ {
117
+ chain: SolanaChain,
118
+ identifier: "SOL",
119
+ name: "Solana",
120
+ symbol: "SOL",
121
+ decimals: 9,
122
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
123
+ },
124
+ {
125
+ chain: SolanaChain,
126
+ identifier: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
127
+ name: "USD Coin",
128
+ symbol: "USDC",
129
+ decimals: 6,
130
+ logoUrl: "https://assets.coingecko.com/coins/images/6319/small/USD_Coin_icon.png"
131
+ },
132
+ {
133
+ chain: SolanaChain,
134
+ identifier: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
135
+ name: "Tether USD",
136
+ symbol: "USDT",
137
+ decimals: 6,
138
+ logoUrl: "https://assets.coingecko.com/coins/images/325/small/Tether.png"
139
+ },
140
+ {
141
+ chain: SolanaChain,
142
+ identifier: "So11111111111111111111111111111111111111112",
143
+ name: "Wrapped SOL",
144
+ symbol: "WSOL",
145
+ decimals: 9,
146
+ logoUrl: "https://assets.coingecko.com/coins/images/4128/small/solana.png"
147
+ }
148
+ ];
149
+
150
+ // src/tokens.ts
151
+ var KnownTokens = {
152
+ solana: {
153
+ mainnet: SolanaTokens,
154
+ testnet: SolanaTokens,
155
+ devnet: SolanaTokens
156
+ }
157
+ };
158
+ var findKnownTokenById = (chain, env, id) => {
159
+ const chainTokens = KnownTokens[chain]?.[env] || [];
160
+ return chainTokens.find((token) => token.identifier === id) || null;
161
+ };
162
+ var getKnownTokensForChain = (chainName, env = "mainnet") => {
163
+ return KnownTokens[chainName]?.[env] || [];
164
+ };
165
+
166
+ // src/WarpSolanaDataLoader.ts
167
+ var WarpSolanaDataLoader = class {
168
+ constructor(config, chain) {
169
+ this.config = config;
170
+ this.chain = chain;
171
+ const providerConfig = (0, import_warps.getProviderConfig)(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
172
+ this.connection = new import_web3.Connection(providerConfig.url, "confirmed");
173
+ this.cache = new import_warps.WarpCache(config.cache?.type);
174
+ }
175
+ async getAccount(address) {
176
+ try {
177
+ const publicKey = new import_web3.PublicKey(address);
178
+ const balance = await this.connection.getBalance(publicKey);
179
+ return {
180
+ chain: this.chain.name,
181
+ address,
182
+ balance: BigInt(balance)
183
+ };
184
+ } catch (error) {
185
+ throw new Error(`Failed to get account: ${error}`);
186
+ }
187
+ }
188
+ async getAccountAssets(address) {
189
+ try {
190
+ const account = await this.getAccount(address);
191
+ const tokenBalances = await this.getTokenBalances(address);
192
+ let assets = account.balance > 0n ? [{ ...this.chain.nativeToken, amount: account.balance }] : [];
193
+ for (const tokenBalance of tokenBalances) {
194
+ if (tokenBalance.balance > 0n) {
195
+ assets.push({
196
+ chain: this.chain.name,
197
+ identifier: tokenBalance.tokenAddress,
198
+ name: tokenBalance.metadata.name,
199
+ symbol: tokenBalance.metadata.symbol,
200
+ amount: tokenBalance.balance,
201
+ decimals: tokenBalance.metadata.decimals,
202
+ logoUrl: tokenBalance.metadata.logoUrl || ""
203
+ });
204
+ }
205
+ }
206
+ return assets;
207
+ } catch (error) {
208
+ return [];
209
+ }
210
+ }
211
+ async getAsset(identifier) {
212
+ try {
213
+ if (identifier === this.chain.nativeToken.identifier || identifier === "SOL") {
214
+ return this.chain.nativeToken;
215
+ }
216
+ const cacheKey = import_warps.WarpCacheKey.Asset(this.config.env, this.chain.name, identifier);
217
+ const cachedAsset = this.cache.get(cacheKey);
218
+ if (cachedAsset) {
219
+ return cachedAsset;
220
+ }
221
+ const env = this.config.env === "mainnet" ? "mainnet" : this.config.env === "devnet" ? "devnet" : "testnet";
222
+ const knownToken = findKnownTokenById(this.chain.name, env, identifier);
223
+ if (knownToken) {
224
+ return {
225
+ chain: this.chain.name,
226
+ identifier,
227
+ name: knownToken.name,
228
+ symbol: knownToken.symbol,
229
+ amount: 0n,
230
+ decimals: knownToken.decimals,
231
+ logoUrl: knownToken.logoUrl
232
+ };
233
+ }
234
+ const metadata = await this.getTokenMetadata(identifier);
235
+ const asset = {
236
+ chain: this.chain.name,
237
+ identifier,
238
+ name: metadata.name,
239
+ symbol: metadata.symbol,
240
+ amount: 0n,
241
+ decimals: metadata.decimals,
242
+ logoUrl: metadata.logoUrl
243
+ };
244
+ this.cache.set(cacheKey, asset, import_warps.CacheTtl.OneHour);
245
+ return asset;
246
+ } catch (error) {
247
+ return null;
248
+ }
249
+ }
250
+ async getAction(identifier, awaitCompleted = false) {
251
+ try {
252
+ const signature = identifier;
253
+ const tx = await this.connection.getTransaction(signature, {
254
+ commitment: "confirmed",
255
+ maxSupportedTransactionVersion: 0
256
+ });
257
+ if (!tx) return null;
258
+ const slot = tx.slot;
259
+ const blockTime = tx.blockTime ? new Date(tx.blockTime * 1e3).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
260
+ const message = tx.transaction.message;
261
+ let accountKeys = [];
262
+ if ("staticAccountKeys" in message) {
263
+ accountKeys = message.staticAccountKeys || [];
264
+ } else {
265
+ try {
266
+ const allKeys = message.getAccountKeys?.();
267
+ if (allKeys) {
268
+ accountKeys = allKeys.keySegments().flat() || [];
269
+ }
270
+ } catch {
271
+ accountKeys = [];
272
+ }
273
+ }
274
+ const sender = accountKeys[0]?.toBase58() || "";
275
+ const receiver = accountKeys.length > 1 ? accountKeys[1]?.toBase58() || "" : "";
276
+ const preBalances = tx.meta?.preBalances || [];
277
+ const postBalances = tx.meta?.postBalances || [];
278
+ const value = preBalances.length > 0 && postBalances.length > 0 ? BigInt(Math.abs(postBalances[0] - preBalances[0])) : 0n;
279
+ const status = tx.meta?.err ? "failed" : "success";
280
+ let compiledInstructions = [];
281
+ if ("compiledInstructions" in message && Array.isArray(message.compiledInstructions)) {
282
+ compiledInstructions = message.compiledInstructions;
283
+ }
284
+ const hasInstructions = compiledInstructions.length > 0;
285
+ return {
286
+ chain: this.chain.name,
287
+ id: signature,
288
+ receiver,
289
+ sender,
290
+ value,
291
+ function: hasInstructions ? compiledInstructions[0]?.programIdIndex !== void 0 ? "contract_call" : "transfer" : "transfer",
292
+ status,
293
+ createdAt: blockTime,
294
+ error: tx.meta?.err ? JSON.stringify(tx.meta.err) : null,
295
+ tx: {
296
+ signature,
297
+ slot,
298
+ blockTime,
299
+ err: tx.meta?.err || null
300
+ }
301
+ };
302
+ } catch (error) {
303
+ return null;
304
+ }
305
+ }
306
+ async getAccountActions(address, options) {
307
+ return [];
308
+ }
309
+ async getTokenBalances(address) {
310
+ try {
311
+ const publicKey = new import_web3.PublicKey(address);
312
+ const tokenAccounts = await this.connection.getParsedTokenAccountsByOwner(publicKey, {
313
+ programId: new import_web3.PublicKey(WarpSolanaConstants.Programs.TokenProgram)
314
+ });
315
+ const env = this.config.env === "mainnet" ? "mainnet" : this.config.env === "devnet" ? "devnet" : "testnet";
316
+ const knownTokens = getKnownTokensForChain(this.chain.name, env);
317
+ const balances = await Promise.all(
318
+ tokenAccounts.value.map(async (tokenAccount) => {
319
+ const mintAddress = tokenAccount.account.data.parsed.info.mint;
320
+ const balance = BigInt(tokenAccount.account.data.parsed.info.tokenAmount.amount);
321
+ const decimals = tokenAccount.account.data.parsed.info.tokenAmount.decimals;
322
+ const knownToken = knownTokens.find((token) => token.identifier === mintAddress);
323
+ if (knownToken) {
324
+ return {
325
+ tokenAddress: mintAddress,
326
+ balance,
327
+ metadata: {
328
+ name: knownToken.name,
329
+ symbol: knownToken.symbol,
330
+ decimals: knownToken.decimals,
331
+ logoUrl: knownToken.logoUrl || ""
332
+ }
333
+ };
334
+ }
335
+ const metadata = await this.getTokenMetadata(mintAddress);
336
+ return {
337
+ tokenAddress: mintAddress,
338
+ balance,
339
+ metadata: {
340
+ name: metadata.name,
341
+ symbol: metadata.symbol,
342
+ decimals: metadata.decimals || decimals,
343
+ logoUrl: metadata.logoUrl
344
+ }
345
+ };
346
+ })
347
+ );
348
+ return balances.filter((b) => b.balance > 0n);
349
+ } catch (error) {
350
+ return [];
351
+ }
352
+ }
353
+ async getTokenMetadata(tokenAddress) {
354
+ try {
355
+ const mintPublicKey = new import_web3.PublicKey(tokenAddress);
356
+ const mintInfo = await (0, import_spl_token.getMint)(this.connection, mintPublicKey);
357
+ return {
358
+ name: "Unknown Token",
359
+ symbol: "UNKNOWN",
360
+ decimals: mintInfo.decimals,
361
+ logoUrl: ""
362
+ };
363
+ } catch (error) {
364
+ return {
365
+ name: "Unknown Token",
366
+ symbol: "UNKNOWN",
367
+ decimals: WarpSolanaConstants.NativeToken.Decimals,
368
+ logoUrl: ""
369
+ };
370
+ }
371
+ }
372
+ };
373
+
374
+ // src/WarpSolanaExecutor.ts
375
+ var import_warps4 = require("@vleap/warps");
376
+ var import_web34 = require("@solana/web3.js");
377
+ var import_spl_token2 = require("@solana/spl-token");
378
+
379
+ // src/WarpSolanaOutput.ts
380
+ var import_warps3 = require("@vleap/warps");
381
+ var import_web33 = require("@solana/web3.js");
382
+
383
+ // src/WarpSolanaSerializer.ts
384
+ var import_warps2 = require("@vleap/warps");
385
+ var import_web32 = require("@solana/web3.js");
386
+ var import_bs58 = __toESM(require("bs58"), 1);
387
+ var WarpSolanaSerializer = class {
388
+ constructor() {
389
+ this.coreSerializer = new import_warps2.WarpSerializer();
390
+ }
391
+ typedToString(value) {
392
+ if (value && typeof value === "object" && "toBase58" in value && typeof value.toBase58 === "function") {
393
+ return `address:${value.toBase58()}`;
394
+ }
395
+ if (typeof value === "string") {
396
+ if (value.length >= 32 && value.length <= 44) {
397
+ try {
398
+ const pubkey = new import_web32.PublicKey(value);
399
+ if (pubkey.toBase58() === value && /^[1-9A-HJ-NP-Za-km-z]+$/.test(value)) {
400
+ return `address:${value}`;
401
+ }
402
+ } catch {
403
+ }
404
+ }
405
+ if (value.startsWith("0x") || /^[0-9a-fA-F]+$/.test(value)) {
406
+ return `hex:${value}`;
407
+ }
408
+ return `string:${value}`;
409
+ }
410
+ if (typeof value === "number") {
411
+ if (Number.isInteger(value)) {
412
+ if (value >= 0 && value <= 255) return `uint8:${value}`;
413
+ if (value >= 0 && value <= 65535) return `uint16:${value}`;
414
+ if (value >= 0 && value <= 4294967295) return `uint32:${value}`;
415
+ return `uint64:${value}`;
416
+ }
417
+ return `string:${value}`;
418
+ }
419
+ if (typeof value === "bigint") {
420
+ return `biguint:${value.toString()}`;
421
+ }
422
+ if (typeof value === "boolean") {
423
+ return `boolean:${value}`;
424
+ }
425
+ if (value instanceof import_web32.PublicKey) {
426
+ return `address:${value.toBase58()}`;
427
+ }
428
+ if (value instanceof Uint8Array) {
429
+ return `hex:${import_bs58.default.encode(value)}`;
430
+ }
431
+ if (typeof value === "object" && value !== null && "identifier" in value && "amount" in value) {
432
+ const asset = value;
433
+ if (asset.decimals !== void 0) {
434
+ return `asset:${asset.identifier}${import_warps2.WarpConstants.ArgCompositeSeparator}${asset.amount.toString()}${import_warps2.WarpConstants.ArgCompositeSeparator}${asset.decimals}`;
435
+ }
436
+ return `asset:${asset.identifier}${import_warps2.WarpConstants.ArgCompositeSeparator}${asset.amount.toString()}`;
437
+ }
438
+ if (Array.isArray(value)) {
439
+ if (value.length === 0) return `list:string:`;
440
+ const types = value.map((item) => this.typedToString(item).split(import_warps2.WarpConstants.ArgParamsSeparator)[0]);
441
+ const type = types[0];
442
+ const values = value.map((item) => this.typedToString(item).split(import_warps2.WarpConstants.ArgParamsSeparator)[1]);
443
+ return `list:${type}:${values.join(",")}`;
444
+ }
445
+ if (value === null || value === void 0) {
446
+ return `string:null`;
447
+ }
448
+ return `string:${String(value)}`;
449
+ }
450
+ typedToNative(value) {
451
+ const stringValue = this.typedToString(value);
452
+ const [type, ...valueParts] = stringValue.split(import_warps2.WarpConstants.ArgParamsSeparator);
453
+ const nativeValue = valueParts.join(import_warps2.WarpConstants.ArgParamsSeparator);
454
+ return [type, this.parseNativeValue(type, nativeValue)];
455
+ }
456
+ nativeToTyped(type, value) {
457
+ switch (type) {
458
+ case "string":
459
+ return String(value);
460
+ case "uint8":
461
+ case "uint16":
462
+ case "uint32":
463
+ case "uint64":
464
+ return BigInt(value);
465
+ case "biguint":
466
+ return BigInt(value);
467
+ case "boolean":
468
+ return Boolean(value);
469
+ case "address":
470
+ return String(value);
471
+ case "hex":
472
+ return String(value);
473
+ case "asset":
474
+ if (typeof value === "object" && value !== null && "identifier" in value && "amount" in value) {
475
+ return value;
476
+ }
477
+ return value;
478
+ default:
479
+ if (type.startsWith("list:")) {
480
+ const [, itemType, itemsStr] = type.split(":");
481
+ if (!itemsStr) return [];
482
+ const items = itemsStr.split(",");
483
+ return items.map((item) => this.nativeToTyped(itemType, item));
484
+ }
485
+ return String(value);
486
+ }
487
+ }
488
+ nativeToType(type) {
489
+ switch (type) {
490
+ case "string":
491
+ return "string";
492
+ case "uint8":
493
+ case "uint16":
494
+ case "uint32":
495
+ case "uint64":
496
+ case "biguint":
497
+ return "bigint";
498
+ case "boolean":
499
+ return "boolean";
500
+ case "address":
501
+ return "string";
502
+ case "hex":
503
+ return "string";
504
+ default:
505
+ return "string";
506
+ }
507
+ }
508
+ stringToTyped(value) {
509
+ const parts = value.split(import_warps2.WarpConstants.ArgParamsSeparator, 2);
510
+ if (parts.length < 2) {
511
+ return value;
512
+ }
513
+ const [type, stringValue] = parts;
514
+ switch (type) {
515
+ case "string":
516
+ return stringValue;
517
+ case "uint8":
518
+ case "uint16":
519
+ case "uint32":
520
+ case "uint64":
521
+ return BigInt(stringValue);
522
+ case "biguint":
523
+ return BigInt(stringValue);
524
+ case "boolean":
525
+ return stringValue === "true";
526
+ case "address":
527
+ return stringValue;
528
+ case "hex":
529
+ return stringValue;
530
+ case "asset":
531
+ const assetParts = stringValue.split(import_warps2.WarpConstants.ArgCompositeSeparator);
532
+ const identifier = assetParts[0] || "";
533
+ const amount = assetParts[1] ? BigInt(assetParts[1]) : 0n;
534
+ const decimals = assetParts[2] ? parseInt(assetParts[2], 10) : void 0;
535
+ return { identifier, amount, decimals };
536
+ default:
537
+ if (type.startsWith("list:")) {
538
+ const [, itemType, itemsStr] = type.split(":");
539
+ if (!itemsStr) return [];
540
+ const items = itemsStr.split(",");
541
+ return items.map((item) => this.stringToTyped(`${itemType}:${item}`));
542
+ }
543
+ return stringValue;
544
+ }
545
+ }
546
+ parseNativeValue(type, value) {
547
+ switch (type) {
548
+ case "string":
549
+ return value;
550
+ case "uint8":
551
+ case "uint16":
552
+ case "uint32":
553
+ case "uint64":
554
+ case "biguint":
555
+ return BigInt(value);
556
+ case "boolean":
557
+ return value === "true";
558
+ case "address":
559
+ return value;
560
+ case "hex":
561
+ return value;
562
+ default:
563
+ return value;
564
+ }
565
+ }
566
+ };
567
+
568
+ // src/WarpSolanaOutput.ts
569
+ var WarpSolanaOutput = class {
570
+ constructor(config, chain) {
571
+ this.config = config;
572
+ this.chain = chain;
573
+ this.serializer = new WarpSolanaSerializer();
574
+ const providerConfig = (0, import_warps3.getProviderConfig)(this.config, this.chain.name, this.config.env, this.chain.defaultApiUrl);
575
+ this.connection = new import_web33.Connection(providerConfig.url, "confirmed");
576
+ this.cache = new import_warps3.WarpCache(config.cache?.type);
577
+ }
578
+ async getActionExecution(warp, actionIndex, tx) {
579
+ const inputs = this.cache.get(import_warps3.WarpCacheKey.WarpExecutable(this.config.env, warp.meta?.hash || "", actionIndex)) ?? [];
580
+ const resolvedInputs = (0, import_warps3.extractResolvedInputValues)(inputs);
581
+ if (!tx) {
582
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
583
+ }
584
+ if ("status" in tx && typeof tx.status === "string") {
585
+ return this.handleWarpChainAction(warp, actionIndex, tx, resolvedInputs);
586
+ }
587
+ if (typeof tx === "string") {
588
+ return this.handleTransactionSignature(warp, actionIndex, tx, resolvedInputs);
589
+ }
590
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
591
+ }
592
+ createFailedExecution(warp, actionIndex, resolvedInputs = []) {
593
+ return {
594
+ status: "error",
595
+ warp,
596
+ action: actionIndex,
597
+ user: (0, import_warps3.getWarpWalletAddressFromConfig)(this.config, this.chain.name),
598
+ txHash: "",
599
+ tx: null,
600
+ next: null,
601
+ values: { string: [], native: [], mapped: {} },
602
+ output: {},
603
+ messages: {},
604
+ destination: null,
605
+ resolvedInputs
606
+ };
607
+ }
608
+ handleWarpChainAction(warp, actionIndex, tx, resolvedInputs = []) {
609
+ const success = tx.status === "success";
610
+ const transactionHash = tx.id || tx.tx?.signature || "";
611
+ const slot = tx.tx?.slot || 0;
612
+ const blockTime = tx.tx?.blockTime || 0;
613
+ const rawValues = [transactionHash, slot.toString(), blockTime.toString()];
614
+ const stringValues = rawValues.map(String);
615
+ return {
616
+ status: success ? "success" : "error",
617
+ warp,
618
+ action: actionIndex,
619
+ user: (0, import_warps3.getWarpWalletAddressFromConfig)(this.config, this.chain.name),
620
+ txHash: transactionHash,
621
+ tx,
622
+ next: null,
623
+ values: { string: stringValues, native: rawValues, mapped: {} },
624
+ output: {},
625
+ messages: {},
626
+ destination: null,
627
+ resolvedInputs
628
+ };
629
+ }
630
+ async handleTransactionSignature(warp, actionIndex, signature, resolvedInputs = []) {
631
+ try {
632
+ const tx = await this.connection.getTransaction(signature, {
633
+ commitment: "confirmed",
634
+ maxSupportedTransactionVersion: 0
635
+ });
636
+ if (!tx) {
637
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
638
+ }
639
+ const success = !tx.meta?.err;
640
+ const slot = tx.slot;
641
+ const blockTime = tx.blockTime || 0;
642
+ const fee = tx.meta?.fee || 0;
643
+ const rawValues = [signature, slot.toString(), blockTime.toString(), fee.toString()];
644
+ const stringValues = rawValues.map(String);
645
+ return {
646
+ status: success ? "success" : "error",
647
+ warp,
648
+ action: actionIndex,
649
+ user: (0, import_warps3.getWarpWalletAddressFromConfig)(this.config, this.chain.name),
650
+ txHash: signature,
651
+ tx: {
652
+ signature,
653
+ slot,
654
+ blockTime,
655
+ fee,
656
+ err: tx.meta?.err || null
657
+ },
658
+ next: null,
659
+ values: { string: stringValues, native: rawValues, mapped: {} },
660
+ output: {},
661
+ messages: {},
662
+ destination: null,
663
+ resolvedInputs
664
+ };
665
+ } catch (error) {
666
+ return this.createFailedExecution(warp, actionIndex, resolvedInputs);
667
+ }
668
+ }
669
+ async extractQueryOutput(warp, typedValues, actionIndex, inputs) {
670
+ const stringValues = typedValues.map((t) => this.serializer.typedToString(t));
671
+ const nativeValues = typedValues.map((t) => this.serializer.typedToNative(t)[1]);
672
+ const values = { string: stringValues, native: nativeValues, mapped: {} };
673
+ let output = {};
674
+ if (!warp.output) return { values, output };
675
+ const getNestedValue = (path) => {
676
+ const indices = path.split(".").slice(1).map((i) => parseInt(i) - 1);
677
+ if (indices.length === 0) return void 0;
678
+ let value = nativeValues[indices[0]];
679
+ for (let i = 1; i < indices.length; i++) {
680
+ if (value === void 0 || value === null) return void 0;
681
+ value = value[indices[i]];
682
+ }
683
+ return value;
684
+ };
685
+ for (const [key, path] of Object.entries(warp.output)) {
686
+ if (path.startsWith(import_warps3.WarpConstants.Transform.Prefix)) continue;
687
+ const currentActionIndex = (0, import_warps3.parseOutputOutIndex)(path);
688
+ if (currentActionIndex !== null && currentActionIndex !== actionIndex) {
689
+ output[key] = null;
690
+ continue;
691
+ }
692
+ if (path.startsWith("out.") || path === "out" || path.startsWith("out[")) {
693
+ output[key] = getNestedValue(path) || null;
694
+ } else {
695
+ output[key] = path;
696
+ }
697
+ }
698
+ return { values, output: await (0, import_warps3.evaluateOutputCommon)(warp, output, actionIndex, inputs, this.serializer.coreSerializer, this.config) };
699
+ }
700
+ async getTransactionStatus(txHash) {
701
+ try {
702
+ const tx = await this.connection.getTransaction(txHash, {
703
+ commitment: "confirmed",
704
+ maxSupportedTransactionVersion: 0
705
+ });
706
+ if (!tx) {
707
+ return { status: "pending" };
708
+ }
709
+ return {
710
+ status: tx.meta?.err ? "failed" : "confirmed",
711
+ blockNumber: tx.slot,
712
+ gasUsed: BigInt(tx.meta?.fee || 0)
713
+ };
714
+ } catch (error) {
715
+ throw new Error(`Failed to get transaction status: ${error}`);
716
+ }
717
+ }
718
+ async getTransactionReceipt(txHash) {
719
+ try {
720
+ const tx = await this.connection.getTransaction(txHash, {
721
+ commitment: "confirmed",
722
+ maxSupportedTransactionVersion: 0
723
+ });
724
+ if (!tx) {
725
+ return null;
726
+ }
727
+ return {
728
+ signature: txHash,
729
+ slot: tx.slot,
730
+ blockTime: tx.blockTime,
731
+ fee: tx.meta?.fee || 0,
732
+ err: tx.meta?.err || null
733
+ };
734
+ } catch (error) {
735
+ return null;
736
+ }
737
+ }
738
+ };
739
+
740
+ // src/WarpSolanaExecutor.ts
741
+ var WarpSolanaExecutor = class {
742
+ constructor(config, chain) {
743
+ this.config = config;
744
+ this.chain = chain;
745
+ this.serializer = new WarpSolanaSerializer();
746
+ const providerConfig = (0, import_warps4.getProviderConfig)(this.config, chain.name, this.config.env, this.chain.defaultApiUrl);
747
+ this.connection = new import_web34.Connection(providerConfig.url, "confirmed");
748
+ this.output = new WarpSolanaOutput(config, this.chain);
749
+ }
750
+ async createTransaction(executable) {
751
+ const action = (0, import_warps4.getWarpActionByIndex)(executable.warp, executable.action);
752
+ let tx = null;
753
+ if (action.type === "transfer") {
754
+ tx = await this.createTransferTransaction(executable);
755
+ } else if (action.type === "contract") {
756
+ tx = await this.createContractCallTransaction(executable);
757
+ } else if (action.type === "query") {
758
+ throw new Error("WarpSolanaExecutor: Invalid action type for createTransaction; Use executeQuery instead");
759
+ } else if (action.type === "collect") {
760
+ throw new Error("WarpSolanaExecutor: Invalid action type for createTransaction; Use executeCollect instead");
761
+ }
762
+ if (!tx) throw new Error(`WarpSolanaExecutor: Invalid action type (${action.type})`);
763
+ return tx;
764
+ }
765
+ async createTransferTransaction(executable) {
766
+ const userWallet = (0, import_warps4.getWarpWalletAddressFromConfig)(this.config, executable.chain.name);
767
+ if (!userWallet) throw new Error("WarpSolanaExecutor: createTransfer - user address not set");
768
+ let destinationPubkey;
769
+ try {
770
+ if (!executable.destination) throw new Error("WarpSolanaExecutor: Destination address is required");
771
+ destinationPubkey = new import_web34.PublicKey(executable.destination);
772
+ } catch {
773
+ throw new Error(`WarpSolanaExecutor: Invalid destination address: ${executable.destination}`);
774
+ }
775
+ if (executable.transfers && executable.transfers.length > 0) {
776
+ return this.createTokenTransferTransaction(executable, userWallet, destinationPubkey);
777
+ }
778
+ const fromPubkey = new import_web34.PublicKey(userWallet);
779
+ const transaction = new import_web34.Transaction();
780
+ if (executable.value > 0n) {
781
+ transaction.add(
782
+ import_web34.SystemProgram.transfer({
783
+ fromPubkey,
784
+ toPubkey: destinationPubkey,
785
+ lamports: Number(executable.value)
786
+ })
787
+ );
788
+ }
789
+ if (executable.data) {
790
+ const data = this.serializer.stringToTyped(executable.data);
791
+ if (data && typeof data === "string") {
792
+ const dataBuffer = Buffer.from(data, "base64");
793
+ const instruction = new import_web34.TransactionInstruction({
794
+ keys: [
795
+ { pubkey: fromPubkey, isSigner: true, isWritable: true },
796
+ { pubkey: destinationPubkey, isSigner: false, isWritable: true }
797
+ ],
798
+ programId: destinationPubkey,
799
+ data: dataBuffer
800
+ });
801
+ transaction.add(instruction);
802
+ }
803
+ }
804
+ return this.setTransactionDefaults(transaction, fromPubkey);
805
+ }
806
+ async createContractCallTransaction(executable) {
807
+ const userWallet = (0, import_warps4.getWarpWalletAddressFromConfig)(this.config, executable.chain.name);
808
+ if (!userWallet) throw new Error("WarpSolanaExecutor: createContractCall - user address not set");
809
+ const action = (0, import_warps4.getWarpActionByIndex)(executable.warp, executable.action);
810
+ if (!action || !("func" in action) || !action.func) throw new Error("WarpSolanaExecutor: Contract action must have a function name");
811
+ let programId;
812
+ try {
813
+ if (!executable.destination) throw new Error("WarpSolanaExecutor: Contract address is required");
814
+ programId = new import_web34.PublicKey(executable.destination);
815
+ } catch {
816
+ throw new Error(`WarpSolanaExecutor: Invalid contract address: ${executable.destination}`);
817
+ }
818
+ const fromPubkey = new import_web34.PublicKey(userWallet);
819
+ const transaction = new import_web34.Transaction();
820
+ try {
821
+ const nativeArgs = executable.args.map((arg) => this.serializer.coreSerializer.stringToNative(arg)[1]);
822
+ let instructionData = Buffer.alloc(0);
823
+ if (action.abi && typeof action.abi === "string") {
824
+ try {
825
+ const abi = JSON.parse(action.abi);
826
+ if (abi.instructions && abi.instructions[action.func]) {
827
+ const instructionDef = abi.instructions[action.func];
828
+ instructionData = this.encodeInstructionData(instructionDef, nativeArgs, action.func);
829
+ } else if (abi.accounts || abi.types) {
830
+ instructionData = this.encodeBasicInstructionData(nativeArgs, action.func);
831
+ }
832
+ } catch {
833
+ instructionData = this.encodeBasicInstructionData(nativeArgs, action.func);
834
+ }
835
+ } else {
836
+ instructionData = this.encodeBasicInstructionData(nativeArgs, action.func);
837
+ }
838
+ const accounts = this.buildInstructionAccounts(action, executable, fromPubkey, programId);
839
+ const instruction = new import_web34.TransactionInstruction({
840
+ keys: accounts,
841
+ programId,
842
+ data: instructionData
843
+ });
844
+ transaction.add(instruction);
845
+ if (executable.value > 0n) {
846
+ transaction.add(
847
+ import_web34.SystemProgram.transfer({
848
+ fromPubkey,
849
+ toPubkey: programId,
850
+ lamports: Number(executable.value)
851
+ })
852
+ );
853
+ }
854
+ return this.setTransactionDefaults(transaction, fromPubkey);
855
+ } catch (error) {
856
+ const errorMessage = error instanceof Error ? error.message : String(error);
857
+ throw new Error(`WarpSolanaExecutor: Failed to create contract call: ${errorMessage}`);
858
+ }
859
+ }
860
+ encodeInstructionData(instructionDef, args, funcName) {
861
+ try {
862
+ const data = Buffer.alloc(8);
863
+ if (instructionDef.discriminator && Buffer.isBuffer(instructionDef.discriminator)) {
864
+ instructionDef.discriminator.copy(data, 0);
865
+ } else {
866
+ const hash = Buffer.from(funcName).slice(0, 8);
867
+ hash.copy(data, 0);
868
+ }
869
+ if (args.length > 0 && instructionDef.args) {
870
+ const encodedArgs = this.encodeArgs(args, instructionDef.args);
871
+ return Buffer.concat([data, encodedArgs]);
872
+ }
873
+ return data;
874
+ } catch {
875
+ return this.encodeBasicInstructionData(args, funcName);
876
+ }
877
+ }
878
+ encodeBasicInstructionData(args, funcName) {
879
+ const funcHash = Buffer.from(funcName).slice(0, 8);
880
+ const data = Buffer.alloc(8);
881
+ funcHash.copy(data, 0);
882
+ if (args.length > 0) {
883
+ const encodedArgs = args.map((arg) => {
884
+ if (typeof arg === "string") {
885
+ return Buffer.from(arg, "utf8");
886
+ } else if (typeof arg === "number" || typeof arg === "bigint") {
887
+ const num = typeof arg === "bigint" ? Number(arg) : arg;
888
+ const buf = Buffer.alloc(8);
889
+ buf.writeBigUInt64LE(BigInt(num), 0);
890
+ return buf;
891
+ } else if (Buffer.isBuffer(arg)) {
892
+ return arg;
893
+ } else if (arg instanceof Uint8Array) {
894
+ return Buffer.from(arg);
895
+ }
896
+ return Buffer.from(String(arg), "utf8");
897
+ });
898
+ return Buffer.concat([data, ...encodedArgs]);
899
+ }
900
+ return data;
901
+ }
902
+ encodeArgs(args, argDefs) {
903
+ const buffers = [];
904
+ for (let i = 0; i < Math.min(args.length, argDefs.length); i++) {
905
+ const arg = args[i];
906
+ const def = argDefs[i];
907
+ if (def.type === "u64" || def.type === "u128") {
908
+ const num = typeof arg === "bigint" ? arg : BigInt(arg);
909
+ const size = def.type === "u128" ? 16 : 8;
910
+ const buf = Buffer.alloc(size);
911
+ if (size === 16) {
912
+ buf.writeBigUInt64LE(num & 0xFFFFFFFFFFFFFFFFn, 0);
913
+ buf.writeBigUInt64LE(num >> 64n, 8);
914
+ } else {
915
+ buf.writeBigUInt64LE(num, 0);
916
+ }
917
+ buffers.push(buf);
918
+ } else if (def.type === "string") {
919
+ buffers.push(Buffer.from(String(arg), "utf8"));
920
+ } else if (def.type === "publicKey" || def.type === "pubkey") {
921
+ try {
922
+ const pubkey = new import_web34.PublicKey(arg);
923
+ buffers.push(pubkey.toBuffer());
924
+ } catch {
925
+ buffers.push(Buffer.from(String(arg), "utf8"));
926
+ }
927
+ } else {
928
+ buffers.push(Buffer.from(String(arg), "utf8"));
929
+ }
930
+ }
931
+ return Buffer.concat(buffers);
932
+ }
933
+ buildInstructionAccounts(action, executable, fromPubkey, programId) {
934
+ const accounts = [
935
+ { pubkey: fromPubkey, isSigner: true, isWritable: true }
936
+ ];
937
+ if (action.accounts && Array.isArray(action.accounts)) {
938
+ for (const accountDef of action.accounts) {
939
+ try {
940
+ const pubkey = new import_web34.PublicKey(accountDef.address || accountDef.pubkey || executable.destination);
941
+ accounts.push({
942
+ pubkey,
943
+ isSigner: accountDef.signer === true,
944
+ isWritable: accountDef.writable !== false
945
+ });
946
+ } catch {
947
+ continue;
948
+ }
949
+ }
950
+ }
951
+ if (!accounts.some((acc) => acc.pubkey.equals(programId))) {
952
+ accounts.push({ pubkey: programId, isSigner: false, isWritable: false });
953
+ }
954
+ return accounts;
955
+ }
956
+ async createTokenTransferTransaction(executable, userWallet, destinationPubkey) {
957
+ if (executable.transfers.length === 0) throw new Error("WarpSolanaExecutor: No transfers provided");
958
+ if (!this.chain.nativeToken?.identifier) throw new Error("WarpSolanaExecutor: No native token defined for this chain");
959
+ const nativeTokenTransfers = executable.transfers.filter(
960
+ (transfer) => transfer.identifier === this.chain.nativeToken.identifier || transfer.identifier === WarpSolanaConstants.NativeToken.Identifier
961
+ );
962
+ const splTokenTransfers = executable.transfers.filter(
963
+ (transfer) => transfer.identifier !== this.chain.nativeToken.identifier && transfer.identifier !== WarpSolanaConstants.NativeToken.Identifier
964
+ );
965
+ if (nativeTokenTransfers.length === 1 && splTokenTransfers.length === 0) {
966
+ const transfer = nativeTokenTransfers[0];
967
+ if (transfer.amount <= 0n) throw new Error("WarpSolanaExecutor: Native token transfer amount must be positive");
968
+ const fromPubkey = new import_web34.PublicKey(userWallet);
969
+ const transaction = new import_web34.Transaction();
970
+ transaction.add(
971
+ import_web34.SystemProgram.transfer({
972
+ fromPubkey,
973
+ toPubkey: destinationPubkey,
974
+ lamports: Number(transfer.amount)
975
+ })
976
+ );
977
+ return this.setTransactionDefaults(transaction, fromPubkey);
978
+ }
979
+ if (nativeTokenTransfers.length === 0 && splTokenTransfers.length === 1) {
980
+ return this.createSingleTokenTransfer(executable, splTokenTransfers[0], userWallet, destinationPubkey);
981
+ }
982
+ if (executable.transfers.length > 1) throw new Error("WarpSolanaExecutor: Multiple token transfers not yet supported");
983
+ throw new Error("WarpSolanaExecutor: Invalid transfer configuration");
984
+ }
985
+ async createSingleTokenTransfer(executable, transfer, userWallet, destinationPubkey) {
986
+ let mintAddress;
987
+ try {
988
+ mintAddress = new import_web34.PublicKey(transfer.identifier);
989
+ } catch {
990
+ throw new Error(`WarpSolanaExecutor: Invalid token address: ${transfer.identifier}`);
991
+ }
992
+ const fromPubkey = new import_web34.PublicKey(userWallet);
993
+ const transaction = new import_web34.Transaction();
994
+ const sourceTokenAccount = await (0, import_spl_token2.getAssociatedTokenAddress)(mintAddress, fromPubkey);
995
+ const destinationTokenAccount = await (0, import_spl_token2.getAssociatedTokenAddress)(mintAddress, destinationPubkey);
996
+ const sourceAccountInfo = await this.connection.getAccountInfo(sourceTokenAccount);
997
+ if (!sourceAccountInfo) {
998
+ throw new Error("WarpSolanaExecutor: Source token account does not exist");
999
+ }
1000
+ const destinationAccountInfo = await this.connection.getAccountInfo(destinationTokenAccount);
1001
+ if (!destinationAccountInfo) {
1002
+ transaction.add(
1003
+ (0, import_spl_token2.createAssociatedTokenAccountInstruction)(
1004
+ fromPubkey,
1005
+ destinationTokenAccount,
1006
+ destinationPubkey,
1007
+ mintAddress
1008
+ )
1009
+ );
1010
+ }
1011
+ transaction.add(
1012
+ (0, import_spl_token2.createTransferInstruction)(
1013
+ sourceTokenAccount,
1014
+ destinationTokenAccount,
1015
+ fromPubkey,
1016
+ Number(transfer.amount)
1017
+ )
1018
+ );
1019
+ return this.setTransactionDefaults(transaction, fromPubkey);
1020
+ }
1021
+ async executeQuery(executable) {
1022
+ const action = (0, import_warps4.getWarpActionByIndex)(executable.warp, executable.action);
1023
+ if (action.type !== "query") throw new Error(`WarpSolanaExecutor: Invalid action type for executeQuery: ${action.type}`);
1024
+ if (!action.func) throw new Error("WarpSolanaExecutor: Query action must have a function name");
1025
+ let queryAddress;
1026
+ try {
1027
+ if (!executable.destination) throw new Error("WarpSolanaExecutor: Query address is required");
1028
+ queryAddress = new import_web34.PublicKey(executable.destination);
1029
+ } catch {
1030
+ throw new Error(`WarpSolanaExecutor: Invalid address for query: ${executable.destination}`);
1031
+ }
1032
+ try {
1033
+ const nativeArgs = executable.args.map((arg) => this.serializer.coreSerializer.stringToNative(arg)[1]);
1034
+ let decodedResult = [];
1035
+ let isSuccess = true;
1036
+ if (action.func === "getAccount" || action.func === "getAccountInfo") {
1037
+ const accountInfo = await this.connection.getAccountInfo(queryAddress);
1038
+ if (!accountInfo) {
1039
+ throw new Error("Account not found");
1040
+ }
1041
+ decodedResult = [
1042
+ accountInfo.lamports,
1043
+ accountInfo.owner.toBase58(),
1044
+ accountInfo.executable,
1045
+ accountInfo.rentEpoch,
1046
+ accountInfo.data.toString("base64")
1047
+ ];
1048
+ } else if (action.func === "getBalance") {
1049
+ const balance = await this.connection.getBalance(queryAddress);
1050
+ decodedResult = [balance.toString()];
1051
+ } else if (action.func === "getProgramAccounts") {
1052
+ const accounts = await this.connection.getProgramAccounts(queryAddress);
1053
+ decodedResult = accounts.map((acc) => ({
1054
+ pubkey: acc.pubkey.toBase58(),
1055
+ account: {
1056
+ lamports: acc.account.lamports,
1057
+ owner: acc.account.owner.toBase58(),
1058
+ data: acc.account.data.toString("base64")
1059
+ }
1060
+ }));
1061
+ } else {
1062
+ const accountInfo = await this.connection.getAccountInfo(queryAddress);
1063
+ if (!accountInfo) {
1064
+ throw new Error("Account not found");
1065
+ }
1066
+ decodedResult = [accountInfo.data.toString("base64")];
1067
+ }
1068
+ const { values, output } = await this.output.extractQueryOutput(
1069
+ executable.warp,
1070
+ decodedResult,
1071
+ executable.action,
1072
+ executable.resolvedInputs
1073
+ );
1074
+ const next = (0, import_warps4.getNextInfo)(this.config, [], executable.warp, executable.action, output);
1075
+ const destinationInput = executable.resolvedInputs.find(
1076
+ (i) => i.input.position === "receiver" || i.input.position === "destination"
1077
+ );
1078
+ const destination = destinationInput?.value || executable.destination;
1079
+ const resolvedInputs = (0, import_warps4.extractResolvedInputValues)(executable.resolvedInputs);
1080
+ return {
1081
+ status: isSuccess ? "success" : "error",
1082
+ warp: executable.warp,
1083
+ action: executable.action,
1084
+ user: (0, import_warps4.getWarpWalletAddressFromConfig)(this.config, executable.chain.name),
1085
+ txHash: null,
1086
+ tx: null,
1087
+ next,
1088
+ values,
1089
+ output: { ...output, _DATA: decodedResult },
1090
+ messages: (0, import_warps4.applyOutputToMessages)(executable.warp, output, this.config),
1091
+ destination,
1092
+ resolvedInputs
1093
+ };
1094
+ } catch (error) {
1095
+ const errorMessage = error instanceof Error ? error.message : String(error);
1096
+ const destinationInput = executable.resolvedInputs.find(
1097
+ (i) => i.input.position === "receiver" || i.input.position === "destination"
1098
+ );
1099
+ const destination = destinationInput?.value || executable.destination;
1100
+ const resolvedInputs = (0, import_warps4.extractResolvedInputValues)(executable.resolvedInputs);
1101
+ return {
1102
+ status: "error",
1103
+ warp: executable.warp,
1104
+ action: executable.action,
1105
+ user: (0, import_warps4.getWarpWalletAddressFromConfig)(this.config, executable.chain.name),
1106
+ txHash: null,
1107
+ tx: null,
1108
+ next: null,
1109
+ values: { string: [], native: [], mapped: {} },
1110
+ output: { _DATA: errorMessage, _ERROR: errorMessage },
1111
+ messages: {},
1112
+ destination,
1113
+ resolvedInputs
1114
+ };
1115
+ }
1116
+ }
1117
+ async verifyMessage(message, signature) {
1118
+ try {
1119
+ const messageBytes = new TextEncoder().encode(message);
1120
+ const signatureBytes = Buffer.from(signature, "base64");
1121
+ return "";
1122
+ } catch (error) {
1123
+ throw new Error(`Failed to verify message: ${error}`);
1124
+ }
1125
+ }
1126
+ async setTransactionDefaults(transaction, fromPubkey) {
1127
+ try {
1128
+ const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash("confirmed");
1129
+ transaction.recentBlockhash = blockhash;
1130
+ if (fromPubkey) {
1131
+ transaction.feePayer = fromPubkey;
1132
+ }
1133
+ const instructions = transaction.instructions;
1134
+ const hasTransfer = instructions.some(
1135
+ (ix) => ix.programId.equals(import_web34.SystemProgram.programId) && ix.data.length === 4
1136
+ );
1137
+ const hasTokenTransfer = instructions.some(
1138
+ (ix) => ix.programId.toBase58() === WarpSolanaConstants.Programs.TokenProgram
1139
+ );
1140
+ let computeUnits = WarpSolanaConstants.ComputeUnitLimit.Default;
1141
+ if (hasTransfer && !hasTokenTransfer) {
1142
+ computeUnits = WarpSolanaConstants.ComputeUnitLimit.Transfer;
1143
+ } else if (hasTokenTransfer) {
1144
+ computeUnits = WarpSolanaConstants.ComputeUnitLimit.TokenTransfer;
1145
+ } else {
1146
+ computeUnits = WarpSolanaConstants.ComputeUnitLimit.ContractCall;
1147
+ }
1148
+ transaction.add(
1149
+ import_web34.ComputeBudgetProgram.setComputeUnitLimit({
1150
+ units: computeUnits
1151
+ })
1152
+ );
1153
+ transaction.add(
1154
+ import_web34.ComputeBudgetProgram.setComputeUnitPrice({
1155
+ microLamports: WarpSolanaConstants.PriorityFee.Default
1156
+ })
1157
+ );
1158
+ return transaction;
1159
+ } catch (error) {
1160
+ const errorMessage = error instanceof Error ? error.message : String(error);
1161
+ throw new Error(`WarpSolanaExecutor: Failed to set transaction defaults: ${errorMessage}`);
1162
+ }
1163
+ }
1164
+ };
1165
+
1166
+ // src/WarpSolanaExplorer.ts
1167
+ var WarpSolanaExplorer = class {
1168
+ constructor(chain, config) {
1169
+ this.chain = chain;
1170
+ this.config = config;
1171
+ }
1172
+ getExplorers() {
1173
+ const explorers = SolanaExplorerNames[this.config.env];
1174
+ if (!explorers) {
1175
+ return ["solscan_mainnet" /* SolscanMainnet */];
1176
+ }
1177
+ return explorers;
1178
+ }
1179
+ getPrimaryExplorer() {
1180
+ const explorers = this.getExplorers();
1181
+ return explorers[0];
1182
+ }
1183
+ getExplorerUrlByName(explorer) {
1184
+ const userPreference = this.config.preferences?.explorers?.[this.chain.name];
1185
+ if (userPreference && !explorer) {
1186
+ const url2 = SolanaExplorerUrls[userPreference];
1187
+ if (url2) return url2;
1188
+ }
1189
+ if (explorer) {
1190
+ const url2 = SolanaExplorerUrls[explorer];
1191
+ if (url2) return url2;
1192
+ }
1193
+ const primaryExplorer = this.getPrimaryExplorer();
1194
+ const url = SolanaExplorerUrls[primaryExplorer];
1195
+ return url || SolanaExplorerUrls[primaryExplorer];
1196
+ }
1197
+ getAccountUrl(address, explorer) {
1198
+ const baseUrl = this.getExplorerUrlByName(explorer);
1199
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1200
+ return `${baseUrl}/account/${address}${cluster}`;
1201
+ }
1202
+ getTransactionUrl(hash, explorer) {
1203
+ const baseUrl = this.getExplorerUrlByName(explorer);
1204
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1205
+ return `${baseUrl}/tx/${hash}${cluster}`;
1206
+ }
1207
+ getBlockUrl(blockNumber, explorer) {
1208
+ const baseUrl = this.getExplorerUrlByName(explorer);
1209
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1210
+ return `${baseUrl}/block/${blockNumber}${cluster}`;
1211
+ }
1212
+ getAssetUrl(identifier, explorer) {
1213
+ const baseUrl = this.getExplorerUrlByName(explorer);
1214
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1215
+ return `${baseUrl}/token/${identifier}${cluster}`;
1216
+ }
1217
+ getContractUrl(address, explorer) {
1218
+ const baseUrl = this.getExplorerUrlByName(explorer);
1219
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1220
+ return `${baseUrl}/account/${address}${cluster}`;
1221
+ }
1222
+ getAllExplorers() {
1223
+ return this.getExplorers();
1224
+ }
1225
+ getExplorerByName(name) {
1226
+ const explorers = this.getExplorers();
1227
+ return explorers.find((explorer) => explorer.toLowerCase() === name.toLowerCase());
1228
+ }
1229
+ getAccountUrls(address) {
1230
+ const explorers = this.getAllExplorers();
1231
+ const urls = {};
1232
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1233
+ explorers.forEach((explorer) => {
1234
+ const url = SolanaExplorerUrls[explorer];
1235
+ if (url) {
1236
+ urls[explorer] = `${url}/account/${address}${cluster}`;
1237
+ }
1238
+ });
1239
+ return urls;
1240
+ }
1241
+ getTransactionUrls(hash) {
1242
+ const explorers = this.getAllExplorers();
1243
+ const urls = {};
1244
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1245
+ explorers.forEach((explorer) => {
1246
+ const url = SolanaExplorerUrls[explorer];
1247
+ if (url) {
1248
+ urls[explorer] = `${url}/tx/${hash}${cluster}`;
1249
+ }
1250
+ });
1251
+ return urls;
1252
+ }
1253
+ getAssetUrls(identifier) {
1254
+ const explorers = this.getAllExplorers();
1255
+ const urls = {};
1256
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1257
+ explorers.forEach((explorer) => {
1258
+ const url = SolanaExplorerUrls[explorer];
1259
+ if (url) {
1260
+ urls[explorer] = `${url}/token/${identifier}${cluster}`;
1261
+ }
1262
+ });
1263
+ return urls;
1264
+ }
1265
+ getContractUrls(address) {
1266
+ const explorers = this.getAllExplorers();
1267
+ const urls = {};
1268
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1269
+ explorers.forEach((explorer) => {
1270
+ const url = SolanaExplorerUrls[explorer];
1271
+ if (url) {
1272
+ urls[explorer] = `${url}/account/${address}${cluster}`;
1273
+ }
1274
+ });
1275
+ return urls;
1276
+ }
1277
+ getBlockUrls(blockNumber) {
1278
+ const explorers = this.getAllExplorers();
1279
+ const urls = {};
1280
+ const cluster = this.config.env === "mainnet" ? "" : `?cluster=${this.config.env}`;
1281
+ explorers.forEach((explorer) => {
1282
+ const url = SolanaExplorerUrls[explorer];
1283
+ if (url) {
1284
+ urls[explorer] = `${url}/block/${blockNumber}${cluster}`;
1285
+ }
1286
+ });
1287
+ return urls;
1288
+ }
1289
+ };
1290
+
1291
+ // src/WarpSolanaWallet.ts
1292
+ var import_warps5 = require("@vleap/warps");
1293
+ var import_web35 = require("@solana/web3.js");
1294
+ var bip39 = __toESM(require("@scure/bip39"), 1);
1295
+ var import_english = require("@scure/bip39/wordlists/english");
1296
+ var import_bs582 = __toESM(require("bs58"), 1);
1297
+ var WarpSolanaWallet = class {
1298
+ constructor(config, chain) {
1299
+ this.config = config;
1300
+ this.chain = chain;
1301
+ const providerConfig = (0, import_warps5.getProviderConfig)(config, chain.name, config.env, chain.defaultApiUrl);
1302
+ this.connection = new import_web35.Connection(providerConfig.url, "confirmed");
1303
+ }
1304
+ async signTransaction(tx) {
1305
+ if (!tx || typeof tx !== "object") throw new Error("Invalid transaction object");
1306
+ const keypair = this.getKeypair();
1307
+ if (tx instanceof import_web35.VersionedTransaction) {
1308
+ tx.sign([keypair]);
1309
+ return tx;
1310
+ }
1311
+ if (tx instanceof import_web35.Transaction) {
1312
+ tx.sign(keypair);
1313
+ return tx;
1314
+ }
1315
+ if (tx.transaction) {
1316
+ if (tx.transaction instanceof import_web35.Transaction) {
1317
+ tx.transaction.sign(keypair);
1318
+ return { ...tx, transaction: tx.transaction.serialize() };
1319
+ }
1320
+ if (typeof tx.transaction === "object") {
1321
+ try {
1322
+ const transaction = import_web35.Transaction.from(tx.transaction);
1323
+ transaction.sign(keypair);
1324
+ return { ...tx, transaction: transaction.serialize(), signature: transaction.signature };
1325
+ } catch {
1326
+ throw new Error("Invalid transaction format");
1327
+ }
1328
+ }
1329
+ }
1330
+ throw new Error("Invalid transaction format");
1331
+ }
1332
+ async signTransactions(txs) {
1333
+ if (txs.length === 0) return [];
1334
+ const keypair = this.getKeypair();
1335
+ return Promise.all(
1336
+ txs.map(async (tx) => {
1337
+ if (tx instanceof import_web35.VersionedTransaction) {
1338
+ tx.sign([keypair]);
1339
+ return tx;
1340
+ }
1341
+ if (tx instanceof import_web35.Transaction) {
1342
+ tx.sign(keypair);
1343
+ return tx;
1344
+ }
1345
+ if (tx.transaction && typeof tx.transaction === "object") {
1346
+ const transaction = import_web35.Transaction.from(tx.transaction);
1347
+ transaction.sign(keypair);
1348
+ return { ...tx, transaction: transaction.serialize() };
1349
+ }
1350
+ throw new Error("Invalid transaction format");
1351
+ })
1352
+ );
1353
+ }
1354
+ async signMessage(message) {
1355
+ const keypair = this.getKeypair();
1356
+ const messageBytes = new TextEncoder().encode(message);
1357
+ const nacl = await import("tweetnacl");
1358
+ const secretKey = keypair.secretKey;
1359
+ if (secretKey.length !== 64) {
1360
+ throw new Error(`Invalid secret key length: expected 64, got ${secretKey.length}`);
1361
+ }
1362
+ const privateKeySlice = secretKey.slice(0, 32);
1363
+ const privateKeyBytes = new Uint8Array(privateKeySlice);
1364
+ if (privateKeyBytes.length !== 32) {
1365
+ throw new Error(`Invalid private key length: expected 32, got ${privateKeyBytes.length}`);
1366
+ }
1367
+ const signature = nacl.sign.detached(messageBytes, privateKeyBytes);
1368
+ return import_bs582.default.encode(signature);
1369
+ }
1370
+ async sendTransaction(tx) {
1371
+ if (!tx || typeof tx !== "object") throw new Error("Invalid transaction object");
1372
+ let transaction;
1373
+ if (tx instanceof import_web35.VersionedTransaction) {
1374
+ transaction = tx;
1375
+ } else if (tx instanceof import_web35.Transaction) {
1376
+ transaction = tx;
1377
+ } else if (tx.transaction) {
1378
+ if (tx.transaction instanceof import_web35.Transaction) {
1379
+ transaction = tx.transaction;
1380
+ } else if (tx.transaction instanceof import_web35.VersionedTransaction) {
1381
+ transaction = tx.transaction;
1382
+ } else if (typeof tx.transaction === "object") {
1383
+ try {
1384
+ transaction = import_web35.Transaction.from(tx.transaction);
1385
+ } catch {
1386
+ throw new Error("Invalid transaction format");
1387
+ }
1388
+ } else if (Buffer.isBuffer(tx.transaction) || typeof tx.transaction === "string") {
1389
+ transaction = import_web35.Transaction.from(tx.transaction);
1390
+ } else {
1391
+ throw new Error("Transaction must be signed before sending");
1392
+ }
1393
+ } else {
1394
+ throw new Error("Transaction must be signed before sending");
1395
+ }
1396
+ const signature = await this.connection.sendRawTransaction(transaction.serialize(), {
1397
+ skipPreflight: true,
1398
+ maxRetries: 3
1399
+ });
1400
+ return signature;
1401
+ }
1402
+ async sendTransactions(txs) {
1403
+ return Promise.all(txs.map(async (tx) => this.sendTransaction(tx)));
1404
+ }
1405
+ create(mnemonic) {
1406
+ const seed = bip39.mnemonicToSeedSync(mnemonic);
1407
+ const keypair = import_web35.Keypair.fromSeed(seed.slice(0, 32));
1408
+ return {
1409
+ address: keypair.publicKey.toBase58(),
1410
+ privateKey: import_bs582.default.encode(keypair.secretKey),
1411
+ mnemonic
1412
+ };
1413
+ }
1414
+ generate() {
1415
+ const keypair = import_web35.Keypair.generate();
1416
+ const entropy = keypair.secretKey.slice(0, 16);
1417
+ const mnemonic = bip39.entropyToMnemonic(entropy, import_english.wordlist);
1418
+ return {
1419
+ address: keypair.publicKey.toBase58(),
1420
+ privateKey: import_bs582.default.encode(keypair.secretKey),
1421
+ mnemonic
1422
+ };
1423
+ }
1424
+ getAddress() {
1425
+ try {
1426
+ const keypair = this.getKeypair();
1427
+ return keypair.publicKey.toBase58();
1428
+ } catch {
1429
+ return null;
1430
+ }
1431
+ }
1432
+ getPublicKey() {
1433
+ try {
1434
+ const keypair = this.getKeypair();
1435
+ return keypair.publicKey.toBase58();
1436
+ } catch {
1437
+ return null;
1438
+ }
1439
+ }
1440
+ getKeypair() {
1441
+ const privateKey = (0, import_warps5.getWarpWalletPrivateKeyFromConfig)(this.config, this.chain.name);
1442
+ if (privateKey) {
1443
+ try {
1444
+ const secretKey = import_bs582.default.decode(privateKey);
1445
+ if (secretKey.length === 64) {
1446
+ return import_web35.Keypair.fromSecretKey(secretKey);
1447
+ } else if (secretKey.length === 32) {
1448
+ return import_web35.Keypair.fromSeed(secretKey);
1449
+ } else {
1450
+ throw new Error(`Invalid private key length: expected 32 or 64 bytes, got ${secretKey.length}`);
1451
+ }
1452
+ } catch (error) {
1453
+ if (error instanceof Error) {
1454
+ throw new Error(`Invalid private key format: ${error.message}`);
1455
+ }
1456
+ throw new Error("Invalid private key format");
1457
+ }
1458
+ }
1459
+ const mnemonic = (0, import_warps5.getWarpWalletMnemonicFromConfig)(this.config, this.chain.name);
1460
+ if (mnemonic) {
1461
+ const seed = bip39.mnemonicToSeedSync(mnemonic);
1462
+ return import_web35.Keypair.fromSeed(seed.slice(0, 32));
1463
+ }
1464
+ throw new Error("No private key or mnemonic provided");
1465
+ }
1466
+ };
1467
+
1468
+ // src/chains/common.ts
1469
+ var createSolanaAdapter = (chainName, chainInfos) => {
1470
+ return (config, fallback) => {
1471
+ if (!fallback) throw new Error(`${chainName} adapter requires a fallback adapter`);
1472
+ return {
1473
+ chainInfo: chainInfos[config.env],
1474
+ builder: () => fallback.builder(),
1475
+ executor: new WarpSolanaExecutor(config, chainInfos[config.env]),
1476
+ output: new WarpSolanaOutput(config, chainInfos[config.env]),
1477
+ serializer: new WarpSolanaSerializer(),
1478
+ registry: fallback.registry,
1479
+ explorer: new WarpSolanaExplorer(chainInfos[config.env], config),
1480
+ abiBuilder: () => fallback.abiBuilder(),
1481
+ brandBuilder: () => fallback.brandBuilder(),
1482
+ dataLoader: new WarpSolanaDataLoader(config, chainInfos[config.env]),
1483
+ wallet: new WarpSolanaWallet(config, chainInfos[config.env])
1484
+ };
1485
+ };
1486
+ };
1487
+
1488
+ // src/chains/solana.ts
1489
+ var NativeTokenSol = {
1490
+ chain: "solana",
1491
+ identifier: "SOL",
1492
+ symbol: "SOL",
1493
+ name: "Solana",
1494
+ decimals: 9,
1495
+ logoUrl: "https://vleap.ai/images/tokens/sol.svg"
1496
+ };
1497
+ var getSolanaAdapter = createSolanaAdapter("solana", {
1498
+ mainnet: {
1499
+ name: "solana",
1500
+ displayName: "Solana Mainnet",
1501
+ chainId: "101",
1502
+ blockTime: 400,
1503
+ addressHrp: "",
1504
+ defaultApiUrl: "https://api.mainnet-beta.solana.com",
1505
+ logoUrl: "https://vleap.ai/images/chains/solana.svg",
1506
+ nativeToken: NativeTokenSol
1507
+ },
1508
+ testnet: {
1509
+ name: "solana",
1510
+ displayName: "Solana Testnet",
1511
+ chainId: "103",
1512
+ blockTime: 400,
1513
+ addressHrp: "",
1514
+ defaultApiUrl: "https://api.testnet.solana.com",
1515
+ logoUrl: "https://vleap.ai/images/chains/solana.svg",
1516
+ nativeToken: NativeTokenSol
1517
+ },
1518
+ devnet: {
1519
+ name: "solana",
1520
+ displayName: "Solana Devnet",
1521
+ chainId: "103",
1522
+ blockTime: 400,
1523
+ addressHrp: "",
1524
+ defaultApiUrl: "https://api.devnet.solana.com",
1525
+ logoUrl: "https://vleap.ai/images/chains/solana.svg",
1526
+ nativeToken: NativeTokenSol
1527
+ }
1528
+ });
1529
+ // Annotate the CommonJS export names for ESM import in node:
1530
+ 0 && (module.exports = {
1531
+ ExplorerUrls,
1532
+ KnownTokens,
1533
+ NativeTokenSol,
1534
+ SolanaExplorerMap,
1535
+ SolanaExplorerNames,
1536
+ SolanaExplorerUrls,
1537
+ SolanaExplorers,
1538
+ WarpSolanaConstants,
1539
+ WarpSolanaDataLoader,
1540
+ WarpSolanaExecutor,
1541
+ WarpSolanaExplorer,
1542
+ WarpSolanaOutput,
1543
+ WarpSolanaSerializer,
1544
+ WarpSolanaWallet,
1545
+ findKnownTokenById,
1546
+ getKnownTokensForChain,
1547
+ getSolanaAdapter
1548
+ });
1549
+ //# sourceMappingURL=index.js.map