@hawksightco/hawk-sdk 1.3.265 → 1.3.267
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/addresses.d.ts +37 -0
- package/dist/addresses.d.ts.map +1 -0
- package/dist/addresses.js +84 -0
- package/dist/anchor.d.ts +22 -0
- package/dist/anchor.d.ts.map +1 -0
- package/dist/anchor.js +121 -0
- package/dist/classes/AltStorage.d.ts +29 -0
- package/dist/classes/AltStorage.d.ts.map +1 -0
- package/dist/classes/AltStorage.js +58 -0
- package/dist/classes/Atomicity.d.ts +34 -0
- package/dist/classes/Atomicity.d.ts.map +1 -0
- package/dist/classes/Atomicity.js +110 -0
- package/dist/classes/Client.d.ts +35 -0
- package/dist/classes/Client.d.ts.map +1 -0
- package/dist/classes/Client.js +66 -0
- package/dist/classes/CombineTransactions.d.ts +11 -0
- package/dist/classes/CombineTransactions.d.ts.map +1 -0
- package/dist/classes/CombineTransactions.js +58 -0
- package/dist/classes/CreateTxMetadata.d.ts +100 -0
- package/dist/classes/CreateTxMetadata.d.ts.map +1 -0
- package/dist/classes/CreateTxMetadata.js +415 -0
- package/dist/classes/General.d.ts +87 -0
- package/dist/classes/General.d.ts.map +1 -0
- package/dist/classes/General.js +176 -0
- package/dist/classes/GeneralUtility.d.ts +79 -0
- package/dist/classes/GeneralUtility.d.ts.map +1 -0
- package/dist/classes/GeneralUtility.js +121 -0
- package/dist/classes/HawkAPI.d.ts +122 -0
- package/dist/classes/HawkAPI.d.ts.map +1 -0
- package/dist/classes/HawkAPI.js +169 -0
- package/dist/classes/Health.d.ts +29 -0
- package/dist/classes/Health.d.ts.map +1 -0
- package/dist/classes/Health.js +48 -0
- package/dist/classes/JupiterAlts.d.ts +37 -0
- package/dist/classes/JupiterAlts.d.ts.map +1 -0
- package/dist/classes/JupiterAlts.js +114 -0
- package/dist/classes/JupiterSwap.d.ts +21 -0
- package/dist/classes/JupiterSwap.d.ts.map +1 -0
- package/dist/classes/JupiterSwap.js +40 -0
- package/dist/classes/Logging.d.ts +13 -0
- package/dist/classes/Logging.d.ts.map +1 -0
- package/dist/classes/Logging.js +50 -0
- package/dist/classes/MultiTransaction.d.ts +75 -0
- package/dist/classes/MultiTransaction.d.ts.map +1 -0
- package/dist/classes/MultiTransaction.js +296 -0
- package/dist/classes/RaydiumSDK.d.ts +67 -0
- package/dist/classes/RaydiumSDK.d.ts.map +1 -0
- package/dist/classes/RaydiumSDK.js +206 -0
- package/dist/classes/Search.d.ts +100 -0
- package/dist/classes/Search.d.ts.map +1 -0
- package/dist/classes/Search.js +216 -0
- package/dist/classes/SimpleIxGenerator.d.ts +57 -0
- package/dist/classes/SimpleIxGenerator.d.ts.map +1 -0
- package/dist/classes/SimpleIxGenerator.js +62 -0
- package/dist/classes/SimplePdaGenerator.d.ts +28 -0
- package/dist/classes/SimplePdaGenerator.d.ts.map +1 -0
- package/dist/classes/SimplePdaGenerator.js +33 -0
- package/dist/classes/Transaction.d.ts +229 -0
- package/dist/classes/Transaction.d.ts.map +1 -0
- package/dist/classes/Transaction.js +643 -0
- package/dist/classes/Transaction2.d.ts +107 -0
- package/dist/classes/Transaction2.d.ts.map +1 -0
- package/dist/classes/Transaction2.js +249 -0
- package/dist/classes/Transaction3.d.ts +165 -0
- package/dist/classes/Transaction3.d.ts.map +1 -0
- package/dist/classes/Transaction3.js +416 -0
- package/dist/classes/TransactionBatchExecute.d.ts +163 -0
- package/dist/classes/TransactionBatchExecute.d.ts.map +1 -0
- package/dist/classes/TransactionBatchExecute.js +466 -0
- package/dist/classes/TransactionBatchExecute2.d.ts +99 -0
- package/dist/classes/TransactionBatchExecute2.d.ts.map +1 -0
- package/dist/classes/TransactionBatchExecute2.js +357 -0
- package/dist/classes/Transactions.d.ts +586 -0
- package/dist/classes/Transactions.d.ts.map +1 -0
- package/dist/classes/Transactions.js +7667 -0
- package/dist/classes/TxGenerator.d.ts +350 -0
- package/dist/classes/TxGenerator.d.ts.map +1 -0
- package/dist/classes/TxGenerator.js +1957 -0
- package/dist/classes/TxGeneratorAutomations.d.ts +186 -0
- package/dist/classes/TxGeneratorAutomations.d.ts.map +1 -0
- package/dist/classes/TxGeneratorAutomations.js +897 -0
- package/dist/classes/Util.d.ts +87 -0
- package/dist/classes/Util.d.ts.map +1 -0
- package/dist/classes/Util.js +148 -0
- package/dist/classes/account-cache/AccountCache.d.ts +54 -0
- package/dist/classes/account-cache/AccountCache.d.ts.map +1 -0
- package/dist/classes/account-cache/AccountCache.js +143 -0
- package/dist/classes/account-cache/MintCache.d.ts +33 -0
- package/dist/classes/account-cache/MintCache.d.ts.map +1 -0
- package/dist/classes/account-cache/MintCache.js +47 -0
- package/dist/classes/account-cache/TokenCache.d.ts +33 -0
- package/dist/classes/account-cache/TokenCache.d.ts.map +1 -0
- package/dist/classes/account-cache/TokenCache.js +47 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +96 -0
- package/dist/functions.d.ts +514 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +1636 -0
- package/dist/hawksight.d.ts +53 -0
- package/dist/hawksight.d.ts.map +1 -0
- package/dist/hawksight.js +328 -0
- package/dist/hsToMeteora.d.ts +31 -0
- package/dist/hsToMeteora.d.ts.map +1 -0
- package/dist/hsToMeteora.js +3175 -0
- package/dist/idl/iyf-extension-idl.d.ts +14583 -0
- package/dist/idl/iyf-extension-idl.d.ts.map +1 -0
- package/dist/idl/iyf-extension-idl.js +14578 -0
- package/dist/idl/iyf-extension-wrapper.d.ts +112 -0
- package/dist/idl/iyf-extension-wrapper.d.ts.map +1 -0
- package/dist/idl/iyf-extension-wrapper.js +2 -0
- package/dist/idl/iyf-main-idl.d.ts +12078 -0
- package/dist/idl/iyf-main-idl.d.ts.map +1 -0
- package/dist/idl/iyf-main-idl.js +12073 -0
- package/dist/idl/iyf-main-wrapper.d.ts +112 -0
- package/dist/idl/iyf-main-wrapper.d.ts.map +1 -0
- package/dist/idl/iyf-main-wrapper.js +2 -0
- package/dist/idl/jupiter-idl.d.ts +3063 -0
- package/dist/idl/jupiter-idl.d.ts.map +1 -0
- package/dist/idl/jupiter-idl.js +3061 -0
- package/dist/idl/meteora-idl.d.ts +7371 -0
- package/dist/idl/meteora-idl.d.ts.map +1 -0
- package/dist/idl/meteora-idl.js +7372 -0
- package/dist/idl/orca-idl.d.ts +3833 -0
- package/dist/idl/orca-idl.d.ts.map +1 -0
- package/dist/idl/orca-idl.js +3834 -0
- package/dist/idl/raydium-idl.d.ts +3054 -0
- package/dist/idl/raydium-idl.d.ts.map +1 -0
- package/dist/idl/raydium-idl.js +3055 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/ixGenerator/IyfExtensionIxGenerator.d.ts +126 -0
- package/dist/ixGenerator/IyfExtensionIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/IyfExtensionIxGenerator.js +467 -0
- package/dist/ixGenerator/IyfMainIxGenerator.d.ts +330 -0
- package/dist/ixGenerator/IyfMainIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/IyfMainIxGenerator.js +1239 -0
- package/dist/ixGenerator/MeteoraDlmmIxGenerator.d.ts +685 -0
- package/dist/ixGenerator/MeteoraDlmmIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/MeteoraDlmmIxGenerator.js +3008 -0
- package/dist/ixGenerator/OrcaIxGenerator.d.ts +119 -0
- package/dist/ixGenerator/OrcaIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/OrcaIxGenerator.js +438 -0
- package/dist/ixGenerator/RaydiumIxGenerator.d.ts +99 -0
- package/dist/ixGenerator/RaydiumIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/RaydiumIxGenerator.js +558 -0
- package/dist/ixGenerator/UtilIxGenerator.d.ts +20 -0
- package/dist/ixGenerator/UtilIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/UtilIxGenerator.js +25 -0
- package/dist/meteora/index.d.ts +2 -0
- package/dist/meteora/index.d.ts.map +1 -0
- package/dist/meteora/index.js +17 -0
- package/dist/meteora/liquidityStrategy.d.ts +408 -0
- package/dist/meteora/liquidityStrategy.d.ts.map +1 -0
- package/dist/meteora/liquidityStrategy.js +1325 -0
- package/dist/meteora.d.ts +669 -0
- package/dist/meteora.d.ts.map +1 -0
- package/dist/meteora.js +1932 -0
- package/dist/orca.d.ts +57 -0
- package/dist/orca.d.ts.map +1 -0
- package/dist/orca.js +123 -0
- package/dist/pdaGenerator/HawksightPdaGenerator.d.ts +29 -0
- package/dist/pdaGenerator/HawksightPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/HawksightPdaGenerator.js +75 -0
- package/dist/pdaGenerator/MeteoraPdaGenerator.d.ts +76 -0
- package/dist/pdaGenerator/MeteoraPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/MeteoraPdaGenerator.js +166 -0
- package/dist/pdaGenerator/OrcaPdaGenerator.d.ts +23 -0
- package/dist/pdaGenerator/OrcaPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/OrcaPdaGenerator.js +68 -0
- package/dist/pdaGenerator/RaydiumPdaGenerator.d.ts +49 -0
- package/dist/pdaGenerator/RaydiumPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/RaydiumPdaGenerator.js +114 -0
- package/dist/pdaGenerator/UtilPdaGenerator.d.ts +8 -0
- package/dist/pdaGenerator/UtilPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/UtilPdaGenerator.js +51 -0
- package/dist/types.d.ts +1104 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +95 -0
- package/package.json +6 -5
|
@@ -0,0 +1,1636 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.benchmark = exports.METEORA_API_URL = void 0;
|
|
49
|
+
exports.createTxMetadata = createTxMetadata;
|
|
50
|
+
exports.createTxMetadataWithActions = createTxMetadataWithActions;
|
|
51
|
+
exports.createTxMetadata2 = createTxMetadata2;
|
|
52
|
+
exports.resultOrError = resultOrError;
|
|
53
|
+
exports.getFeeEstimate = getFeeEstimate;
|
|
54
|
+
exports.getMeteoraPool = getMeteoraPool;
|
|
55
|
+
exports.createTransactionMeta = createTransactionMeta;
|
|
56
|
+
exports.createTransactionMeta2 = createTransactionMeta2;
|
|
57
|
+
exports.legacyTxMetadata = legacyTxMetadata;
|
|
58
|
+
exports.generateUserPda = generateUserPda;
|
|
59
|
+
exports.generateUserPdaLamport = generateUserPdaLamport;
|
|
60
|
+
exports.generateAta = generateAta;
|
|
61
|
+
exports.generateLimitToken = generateLimitToken;
|
|
62
|
+
exports.generateFuelAccount = generateFuelAccount;
|
|
63
|
+
exports.generateAta2022 = generateAta2022;
|
|
64
|
+
exports.generateOrcaPositionPDA = generateOrcaPositionPDA;
|
|
65
|
+
exports.generateUserPdaStorageAccount = generateUserPdaStorageAccount;
|
|
66
|
+
exports.getIxs = getIxs;
|
|
67
|
+
exports.sighashMatch = sighashMatch;
|
|
68
|
+
exports.sighash = sighash;
|
|
69
|
+
exports.tokenAccountExists = tokenAccountExists;
|
|
70
|
+
exports.parseTokenAccountData = parseTokenAccountData;
|
|
71
|
+
exports.createAtaIdempotentIxs = createAtaIdempotentIxs;
|
|
72
|
+
exports.getMintsFromInstruction = getMintsFromInstruction;
|
|
73
|
+
exports.wrapSolIfMintIsWsol = wrapSolIfMintIsWsol;
|
|
74
|
+
exports.wrapSolIfMintIsWsolLabeled = wrapSolIfMintIsWsolLabeled;
|
|
75
|
+
exports.createSourceAtasIdempotent = createSourceAtasIdempotent;
|
|
76
|
+
exports.createSourceAtasIdempotentLabeled = createSourceAtasIdempotentLabeled;
|
|
77
|
+
exports.wrapSolToWsol = wrapSolToWsol;
|
|
78
|
+
exports.wrapSolToWsolLabeled = wrapSolToWsolLabeled;
|
|
79
|
+
exports.unwrapSolIfMintIsWsol = unwrapSolIfMintIsWsol;
|
|
80
|
+
exports.unwrapWsolToSol = unwrapWsolToSol;
|
|
81
|
+
exports.unwrapSolIfMintIsWsolLabeled = unwrapSolIfMintIsWsolLabeled;
|
|
82
|
+
exports.unwrapWsolToSolLabeled = unwrapWsolToSolLabeled;
|
|
83
|
+
exports.inputTokenExists = inputTokenExists;
|
|
84
|
+
exports.getJupiterRouteIxParams = getJupiterRouteIxParams;
|
|
85
|
+
exports.toVersionedTransaction = toVersionedTransaction;
|
|
86
|
+
exports.ixStrToWeb3Ix = ixStrToWeb3Ix;
|
|
87
|
+
exports.stringToAlt = stringToAlt;
|
|
88
|
+
exports.getPriorityFeeEstimate = getPriorityFeeEstimate;
|
|
89
|
+
exports.getPriorityFeeEstimate2 = getPriorityFeeEstimate2;
|
|
90
|
+
exports.mid = mid;
|
|
91
|
+
exports.generateNonceAddressFromIndex = generateNonceAddressFromIndex;
|
|
92
|
+
exports.generateNonceAddressesOwnedBy = generateNonceAddressesOwnedBy;
|
|
93
|
+
exports.findNonceOwnedBy = findNonceOwnedBy;
|
|
94
|
+
exports.tokenizer = tokenizer;
|
|
95
|
+
exports.deserializeParametersFromIDL = deserializeParametersFromIDL;
|
|
96
|
+
exports.extractValue = extractValue;
|
|
97
|
+
exports.resolveStruct = resolveStruct;
|
|
98
|
+
exports.resolveEnum = resolveEnum;
|
|
99
|
+
exports.resolveOption = resolveOption;
|
|
100
|
+
exports.resolveVec = resolveVec;
|
|
101
|
+
exports.resolveArray = resolveArray;
|
|
102
|
+
exports.resolveDefined = resolveDefined;
|
|
103
|
+
exports.extractPrimitives = extractPrimitives;
|
|
104
|
+
exports.simulateTransaction = simulateTransaction;
|
|
105
|
+
exports.createAssociatedTokenAccountIdempotentInstruction = createAssociatedTokenAccountIdempotentInstruction;
|
|
106
|
+
exports.raydiumStartTickIndex = raydiumStartTickIndex;
|
|
107
|
+
exports.i32ToBeBuffer = i32ToBeBuffer;
|
|
108
|
+
exports.findUserAlts = findUserAlts;
|
|
109
|
+
exports.pubkeysInAlt = pubkeysInAlt;
|
|
110
|
+
exports.getBatchedMultipleAccountsInfo = getBatchedMultipleAccountsInfo;
|
|
111
|
+
exports.getTokenProgramForMints = getTokenProgramForMints;
|
|
112
|
+
exports.getTokenProgramMapForMints = getTokenProgramMapForMints;
|
|
113
|
+
exports.getMeteoraStrategyType = getMeteoraStrategyType;
|
|
114
|
+
exports.generateHawksightFeeAccounts = generateHawksightFeeAccounts;
|
|
115
|
+
exports.fetchRemainingAccountsInfo = fetchRemainingAccountsInfo;
|
|
116
|
+
exports.fetchRemainingAccountsInfoForReward = fetchRemainingAccountsInfoForReward;
|
|
117
|
+
const client = __importStar(require("@hawksightco/swagger-client"));
|
|
118
|
+
const web3 = __importStar(require("@solana/web3.js"));
|
|
119
|
+
const axios_1 = __importDefault(require("axios"));
|
|
120
|
+
const types_1 = require("./types");
|
|
121
|
+
const CreateTxMetadata_1 = require("./classes/CreateTxMetadata");
|
|
122
|
+
const addresses_1 = require("./addresses");
|
|
123
|
+
const errors_1 = require("./errors");
|
|
124
|
+
const lodash_1 = require("lodash");
|
|
125
|
+
const js_sha256_1 = require("js-sha256");
|
|
126
|
+
const bn_js_1 = __importDefault(require("bn.js"));
|
|
127
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
128
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
129
|
+
const Logging_1 = require("./classes/Logging");
|
|
130
|
+
const jupiter_idl_1 = require("./idl/jupiter-idl");
|
|
131
|
+
const MintCache_1 = require("./classes/account-cache/MintCache");
|
|
132
|
+
exports.METEORA_API_URL = "https://dlmm.datapi.meteora.ag";
|
|
133
|
+
/**
|
|
134
|
+
* Asynchronously creates transaction metadata based on the provided transaction parameters and network state.
|
|
135
|
+
* This includes constructing a transaction with given instructions, calculating fees, and optionally handling priority fees.
|
|
136
|
+
*
|
|
137
|
+
* @param connection The active Solana blockchain connection used to fetch state and simulate the transaction.
|
|
138
|
+
* @param payer The public key (as a string) of the payer for the transaction, responsible for fees.
|
|
139
|
+
* @param data An object containing necessary information to construct the transaction, such as:
|
|
140
|
+
* - addressLookupTableAddresses: Array of addresses for lookup tables.
|
|
141
|
+
* - computeBudgetInstructions: Array of instructions for setting compute budget.
|
|
142
|
+
* - description: Description of the transaction.
|
|
143
|
+
* - estimatedFeeInSOL: Estimated fee in SOL units.
|
|
144
|
+
* @returns A promise resolving to an object containing the transaction metadata including the description,
|
|
145
|
+
* estimated fee, and the transaction object itself.
|
|
146
|
+
* @throws Error if there is an issue in constructing the transaction or during simulation which includes logs of errors.
|
|
147
|
+
*/
|
|
148
|
+
function createTxMetadata(generalUtility, connection, payer, data) {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
return yield CreateTxMetadata_1.CreateTxMetadata.instance().createTxMetadata(generalUtility, connection, payer, data);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function createTxMetadataWithActions(generalUtility, connection, payer, data) {
|
|
154
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
return yield CreateTxMetadata_1.CreateTxMetadata.instance().createTxMetadataWithActions(generalUtility, connection, payer, data);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Designed for splitting transactions into multiple transactions dynamically
|
|
160
|
+
* based on the size of the transaction by measuring each raw instructions.
|
|
161
|
+
*
|
|
162
|
+
* @param generalUtility
|
|
163
|
+
* @param connection
|
|
164
|
+
* @param payer
|
|
165
|
+
* @param data
|
|
166
|
+
* @returns
|
|
167
|
+
*/
|
|
168
|
+
function createTxMetadata2(generalUtility, connection, payer, data) {
|
|
169
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
170
|
+
return yield CreateTxMetadata_1.CreateTxMetadata.instance().createTxMetadata2(generalUtility, connection, payer, data);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Wraps the result of an API call or operation in an object containing status information.
|
|
175
|
+
* If the result status is 200, applies a success function to the data.
|
|
176
|
+
* @param result The result object containing the HTTP status code and response data.
|
|
177
|
+
* @param successFn A function to be applied to the response data in case of success.
|
|
178
|
+
* @returns A promise that resolves to an object containing status information and the transformed or original response data.
|
|
179
|
+
* The response data may be of type Out if the success function is applied, or type Response if not.
|
|
180
|
+
*/
|
|
181
|
+
function resultOrError(result, successFn) {
|
|
182
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
183
|
+
if (result.status === 200) {
|
|
184
|
+
// If the status is 200, apply the success function to the data
|
|
185
|
+
return {
|
|
186
|
+
status: result.status,
|
|
187
|
+
data: yield successFn(result.data),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
console.error(`Error:`);
|
|
192
|
+
console.error(result.data);
|
|
193
|
+
throw new Error();
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Retrieves an estimate of the priority fee for a transaction using the provided connection.
|
|
199
|
+
*
|
|
200
|
+
* @param connection The web3 connection object used for interacting with the blockchain.
|
|
201
|
+
* @param priorityLevel The priority level of the transaction.
|
|
202
|
+
* @param versionedTransaction The versioned transaction object for which the fee estimate is needed.
|
|
203
|
+
* @returns A Promise resolving to the estimated priority fee for the transaction.
|
|
204
|
+
*/
|
|
205
|
+
function getFeeEstimate(generalUtility, priority, transaction) {
|
|
206
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
const response = yield generalUtility.getPriorityFeeEstimate({
|
|
208
|
+
priority,
|
|
209
|
+
transaction,
|
|
210
|
+
});
|
|
211
|
+
return (yield resultOrError(response, (result) => __awaiter(this, void 0, void 0, function* () {
|
|
212
|
+
let priorityFee;
|
|
213
|
+
if (priority === client.PriorityLevel.Default || priority === client.PriorityLevel.Medium) {
|
|
214
|
+
priorityFee = result.feeLevels._default;
|
|
215
|
+
}
|
|
216
|
+
else if (priority === client.PriorityLevel.High) {
|
|
217
|
+
priorityFee = result.feeLevels.high;
|
|
218
|
+
}
|
|
219
|
+
else if (priority === client.PriorityLevel.VeryHigh) {
|
|
220
|
+
priorityFee = result.feeLevels.high;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
const max = result.feeLevels._default;
|
|
224
|
+
const min = result.feeLevels.low;
|
|
225
|
+
priorityFee = min + ((max - min) / 2);
|
|
226
|
+
}
|
|
227
|
+
return result.priorityFeeEstimate;
|
|
228
|
+
}))).data;
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Returns a meteora pool
|
|
233
|
+
*
|
|
234
|
+
* @param poolAddress Address of the meteora pool
|
|
235
|
+
* @returns {Promise<MeteoraPoolInfo>}A promise that resolves to an object of Meteora pool information.
|
|
236
|
+
*/
|
|
237
|
+
function getMeteoraPool(poolAddress) {
|
|
238
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
try {
|
|
240
|
+
const response = yield axios_1.default.get(`${exports.METEORA_API_URL}/pools/${poolAddress}`);
|
|
241
|
+
const poolInfo = response.data;
|
|
242
|
+
return poolInfo;
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error(`Failed to fetch Meteora pool info for address ${poolAddress}:`, error);
|
|
246
|
+
throw new Error('Could not retrieve Meteora pool information.');
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Generate transaction meta object
|
|
252
|
+
*
|
|
253
|
+
* @param params
|
|
254
|
+
* @returns
|
|
255
|
+
*/
|
|
256
|
+
function createTransactionMeta(params) {
|
|
257
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
258
|
+
const addressLookupTableAddresses = [];
|
|
259
|
+
const pubkeys = [];
|
|
260
|
+
const mainInstructions = params.mainInstructions.map((ix) => {
|
|
261
|
+
return {
|
|
262
|
+
accounts: ix.keys.map((account) => {
|
|
263
|
+
const pubkey = account.pubkey.toString();
|
|
264
|
+
pubkeys.push(pubkey);
|
|
265
|
+
return {
|
|
266
|
+
isSigner: account.isSigner,
|
|
267
|
+
isWritable: account.isWritable,
|
|
268
|
+
pubkey,
|
|
269
|
+
};
|
|
270
|
+
}),
|
|
271
|
+
data: ix.data.toString("base64"),
|
|
272
|
+
programId: ix.programId.toString(),
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
addressLookupTableAddresses.push(...params.addressLookupTableAddresses);
|
|
276
|
+
const signature = "";
|
|
277
|
+
return {
|
|
278
|
+
description: params.description,
|
|
279
|
+
estimatedFeeInSOL: "",
|
|
280
|
+
addressLookupTableAddresses,
|
|
281
|
+
computeBudgetInstructions: [],
|
|
282
|
+
mainInstructions,
|
|
283
|
+
payer: params.payer.toString(),
|
|
284
|
+
signature,
|
|
285
|
+
};
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Generate transaction with labels per instruction
|
|
290
|
+
*
|
|
291
|
+
* @param params
|
|
292
|
+
* @returns
|
|
293
|
+
*/
|
|
294
|
+
function createTransactionMeta2(params) {
|
|
295
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
const addressLookupTableAddresses = [];
|
|
297
|
+
const pubkeys = [];
|
|
298
|
+
const mainInstructions = params.mainInstructions.map((ix) => {
|
|
299
|
+
return {
|
|
300
|
+
accounts: ix.instruction.keys.map((account) => {
|
|
301
|
+
const pubkey = account.pubkey.toString();
|
|
302
|
+
pubkeys.push(pubkey);
|
|
303
|
+
return {
|
|
304
|
+
isSigner: account.isSigner,
|
|
305
|
+
isWritable: account.isWritable,
|
|
306
|
+
pubkey,
|
|
307
|
+
};
|
|
308
|
+
}),
|
|
309
|
+
data: ix.instruction.data.toString("base64"),
|
|
310
|
+
programId: ix.instruction.programId.toString(),
|
|
311
|
+
};
|
|
312
|
+
});
|
|
313
|
+
const actions = params.mainInstructions.map(ix => ix.label);
|
|
314
|
+
addressLookupTableAddresses.push(...params.addressLookupTableAddresses);
|
|
315
|
+
return {
|
|
316
|
+
actions,
|
|
317
|
+
addressLookupTableAddresses,
|
|
318
|
+
computeBudgetInstructions: [],
|
|
319
|
+
mainInstructions,
|
|
320
|
+
payer: params.payer.toString(),
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
function legacyTxMetadata(_a) {
|
|
325
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, generalUtility, payer, description, ixs, additionalAlt, }) {
|
|
326
|
+
// Create transaction meta
|
|
327
|
+
const result = yield createTransactionMeta({
|
|
328
|
+
payer,
|
|
329
|
+
description,
|
|
330
|
+
addressLookupTableAddresses: [...addresses_1.GLOBAL_ALT, ...(additionalAlt || [])],
|
|
331
|
+
mainInstructions: ixs,
|
|
332
|
+
});
|
|
333
|
+
return {
|
|
334
|
+
status: 200,
|
|
335
|
+
data: yield createTxMetadata(generalUtility, connection, payer.toString(), result),
|
|
336
|
+
};
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Generate UserPDA
|
|
341
|
+
*
|
|
342
|
+
* @param userWallet
|
|
343
|
+
* @param farm
|
|
344
|
+
* @returns
|
|
345
|
+
*/
|
|
346
|
+
function generateUserPda(userWallet, farm = new web3.PublicKey("7jLQhREMxXjKdpwVuN6gwsWt3BNfAg9WqbepffPbi4ww")) {
|
|
347
|
+
const [pda] = web3.PublicKey.findProgramAddressSync([Buffer.from("multi-user"), farm.toBuffer(), userWallet.toBuffer()], new web3.PublicKey("FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P"));
|
|
348
|
+
return pda;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Generate UserPDA Lamport Account
|
|
352
|
+
*
|
|
353
|
+
* @param userWallet
|
|
354
|
+
* @param farm
|
|
355
|
+
* @returns
|
|
356
|
+
*/
|
|
357
|
+
function generateUserPdaLamport(userWallet, farm = new web3.PublicKey("7jLQhREMxXjKdpwVuN6gwsWt3BNfAg9WqbepffPbi4ww")) {
|
|
358
|
+
const userPda = generateUserPda(userWallet, farm);
|
|
359
|
+
const [pda] = web3.PublicKey.findProgramAddressSync([Buffer.from("user-pda-lamport"), userPda.toBuffer()], new web3.PublicKey("FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P"));
|
|
360
|
+
return pda;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Generate ATA
|
|
364
|
+
*
|
|
365
|
+
* @param owner Owner of the ATA
|
|
366
|
+
* @param mint Mint of the ATA
|
|
367
|
+
* @param programId Defaults to Token Program. Program ID is used to support token 2022
|
|
368
|
+
* @returns ATA address
|
|
369
|
+
*/
|
|
370
|
+
function generateAta(owner, mint, programId = addresses_1.TOKEN_PROGRAM_ID) {
|
|
371
|
+
const [pda] = web3.PublicKey.findProgramAddressSync([
|
|
372
|
+
owner.toBuffer(),
|
|
373
|
+
programId.toBuffer(),
|
|
374
|
+
mint.toBuffer(),
|
|
375
|
+
], new web3.PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"));
|
|
376
|
+
return pda;
|
|
377
|
+
}
|
|
378
|
+
function generateLimitToken(userPda, mint) {
|
|
379
|
+
const [pda] = web3.PublicKey.findProgramAddressSync([
|
|
380
|
+
Buffer.from("limit-token", "utf-8"),
|
|
381
|
+
mint.toBuffer(),
|
|
382
|
+
userPda.toBuffer(),
|
|
383
|
+
], new web3.PublicKey("FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P"));
|
|
384
|
+
return pda;
|
|
385
|
+
}
|
|
386
|
+
function generateFuelAccount(userWallet) {
|
|
387
|
+
const [pda] = web3.PublicKey.findProgramAddressSync([
|
|
388
|
+
Buffer.from("fuel", "utf-8"),
|
|
389
|
+
userWallet.toBuffer(),
|
|
390
|
+
], new web3.PublicKey("FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P"));
|
|
391
|
+
return pda;
|
|
392
|
+
}
|
|
393
|
+
function generateAta2022(owner, mint) {
|
|
394
|
+
return generateAta(owner, mint, addresses_1.TOKEN_2022);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Generate Orca Position PDA
|
|
398
|
+
*
|
|
399
|
+
* @param userWallet
|
|
400
|
+
* @param farm
|
|
401
|
+
* @returns
|
|
402
|
+
*/
|
|
403
|
+
function generateOrcaPositionPDA(positionMint) {
|
|
404
|
+
const [pda] = web3.PublicKey.findProgramAddressSync([Buffer.from("position", "utf-8"), positionMint.toBuffer()], addresses_1.ORCA_WHIRLPOOL_PROGRAM);
|
|
405
|
+
return pda;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Generate the PDA for the userPda's storage account
|
|
409
|
+
*
|
|
410
|
+
* @param userPda
|
|
411
|
+
* @param mint
|
|
412
|
+
* @returns Storage Account owned by the user pda
|
|
413
|
+
*/
|
|
414
|
+
function generateUserPdaStorageAccount(userPda, mint) {
|
|
415
|
+
const [storageAccount] = web3.PublicKey.findProgramAddressSync([Buffer.from("storage-token"), mint.toBuffer(), userPda.toBuffer()], addresses_1.IYF_MAIN);
|
|
416
|
+
return storageAccount;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Convert transaction to instructions
|
|
420
|
+
*
|
|
421
|
+
* @param txns
|
|
422
|
+
* @returns
|
|
423
|
+
*/
|
|
424
|
+
function getIxs(txns) {
|
|
425
|
+
const ixs = [];
|
|
426
|
+
if (typeof txns.length === "number") {
|
|
427
|
+
const txs = txns;
|
|
428
|
+
for (const tx of txs) {
|
|
429
|
+
ixs.push(...tx.instructions);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
const txs = txns;
|
|
434
|
+
ixs.push(...txs.instructions);
|
|
435
|
+
}
|
|
436
|
+
return ixs;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Check if anchor instruction matches
|
|
440
|
+
*
|
|
441
|
+
* @param data
|
|
442
|
+
* @param compareTo
|
|
443
|
+
*/
|
|
444
|
+
function sighashMatch(data, compareTo, prefix, noSnakeCase, skipDataLengthCheck) {
|
|
445
|
+
if (typeof compareTo === "string") {
|
|
446
|
+
compareTo = sighash(compareTo, prefix, noSnakeCase);
|
|
447
|
+
}
|
|
448
|
+
if (data.length < 8) {
|
|
449
|
+
if (skipDataLengthCheck) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
throw new errors_1.AppError(`Data is not an anchor instruction`, `sighashMatch`);
|
|
453
|
+
}
|
|
454
|
+
if (compareTo.length < 8) {
|
|
455
|
+
throw new errors_1.AppError(`compareTo is not a valid sighash`, `sighashMatch`);
|
|
456
|
+
}
|
|
457
|
+
for (let i = 0; i < 8; i++) {
|
|
458
|
+
if (data[i] !== compareTo[i]) {
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Anchor sighash function
|
|
466
|
+
*
|
|
467
|
+
* @param ixName
|
|
468
|
+
* @returns
|
|
469
|
+
*/
|
|
470
|
+
function sighash(ixName, prefix = "global", noSnakeCase = false) {
|
|
471
|
+
const name = noSnakeCase ? ixName : (0, lodash_1.snakeCase)(ixName);
|
|
472
|
+
const preimage = `${prefix}:${name}`;
|
|
473
|
+
return Buffer.from(js_sha256_1.sha256.digest(preimage)).subarray(0, 8);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Determine whether given token account exists
|
|
477
|
+
* @param publicKeys
|
|
478
|
+
*/
|
|
479
|
+
function tokenAccountExists(connection, params) {
|
|
480
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
481
|
+
const tokenKeys = params.map((p) => {
|
|
482
|
+
if (p.tokenType === types_1.TokenType.STA || p.isSta) {
|
|
483
|
+
return generateUserPdaStorageAccount(p.owner, p.mint);
|
|
484
|
+
}
|
|
485
|
+
else if (p.tokenType === types_1.TokenType.LTA) {
|
|
486
|
+
return generateLimitToken(p.owner, p.mint);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
return generateAta(p.owner, p.mint, p.tokenProgram);
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
const accountInfos = yield connection.getMultipleAccountsInfo(tokenKeys);
|
|
493
|
+
const result = accountInfos.map((accountInfo, index) => {
|
|
494
|
+
if (accountInfo === null || accountInfo.data.length !== 165) {
|
|
495
|
+
return { mint: params[index].mint, tokenKey: tokenKeys[index], exists: false };
|
|
496
|
+
}
|
|
497
|
+
// Get the expected token program for this specific account
|
|
498
|
+
const expectedTokenProgram = params[index].tokenProgram || addresses_1.TOKEN_PROGRAM_ID;
|
|
499
|
+
return {
|
|
500
|
+
mint: params[index].mint,
|
|
501
|
+
tokenKey: tokenKeys[index],
|
|
502
|
+
exists: accountInfo.owner.equals(expectedTokenProgram),
|
|
503
|
+
};
|
|
504
|
+
});
|
|
505
|
+
return result;
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Decodes a buffer into an object describing the token account.
|
|
510
|
+
* @param data - The buffer containing raw account data.
|
|
511
|
+
* @returns An object with mint, owner, and amount properties.
|
|
512
|
+
*/
|
|
513
|
+
function parseTokenAccountData(data) {
|
|
514
|
+
return {
|
|
515
|
+
mint: new web3.PublicKey(data.subarray(0, 32)),
|
|
516
|
+
owner: new web3.PublicKey(data.subarray(32, 64)),
|
|
517
|
+
amount: new bn_js_1.default(data.subarray(64, 72), "le"),
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Creates an array of idempotent associated token account creation instructions.
|
|
522
|
+
*
|
|
523
|
+
* This function generates instructions to create associated token accounts (ATAs) for the provided accounts.
|
|
524
|
+
* The instructions are idempotent, meaning they can be safely executed multiple times without changing the result beyond the initial application.
|
|
525
|
+
*
|
|
526
|
+
* @param {CreateAtaIdempotentParams} params - The parameters for creating ATA instructions.
|
|
527
|
+
* @param {Array<{ payer: web3.PublicKey, owner: web3.PublicKey, mint: web3.PublicKey }>} params.accounts - An array of objects containing:
|
|
528
|
+
* - `payer`: The public key of the account paying for the transaction.
|
|
529
|
+
* - `owner`: The public key of the account owner.
|
|
530
|
+
* - `mint`: The public key of the mint (token) for which the ATA is being created.
|
|
531
|
+
*
|
|
532
|
+
* @returns {web3.TransactionInstruction[]} An array of transaction instructions for creating the associated token accounts.
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* const accounts = [
|
|
536
|
+
* { payer: payerPublicKey, owner: ownerPublicKey, mint: mintPublicKey },
|
|
537
|
+
* { payer: anotherPayerPublicKey, owner: anotherOwnerPublicKey, mint: anotherMintPublicKey }
|
|
538
|
+
* ];
|
|
539
|
+
* const instructions = createAtaIdempotent({ accounts });
|
|
540
|
+
* Log(instructions); // Logs an array of TransactionInstruction objects.
|
|
541
|
+
*/
|
|
542
|
+
function createAtaIdempotentIxs({ accounts, }) {
|
|
543
|
+
const result = [];
|
|
544
|
+
for (const account of accounts) {
|
|
545
|
+
const { payer, owner, mint, programId } = account;
|
|
546
|
+
const ata = generateAta(owner, mint, programId);
|
|
547
|
+
const ataIx = createAssociatedTokenAccountIdempotentInstruction(payer, ata, owner, mint, programId);
|
|
548
|
+
result.push(ataIx);
|
|
549
|
+
}
|
|
550
|
+
return result;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Extracts unique mint addresses from a list of Solana instructions based on specific criteria.
|
|
554
|
+
*
|
|
555
|
+
* @param {GetMintsFromInstructionParams} params - The parameters for extracting mint addresses.
|
|
556
|
+
* @param {web3.TransactionInstruction[]} params.instructions - An array of Solana instructions to search through.
|
|
557
|
+
* @param {Record<string, { programId: string, mintIndices: number[] }>} params.find - A record where each key is a string identifier and the value is an object containing:
|
|
558
|
+
* - programId: The program ID to match against the instruction's program ID.
|
|
559
|
+
* - mintIndices: An array of indices that point to the mint addresses within the instruction's keys.
|
|
560
|
+
*
|
|
561
|
+
* @returns {web3.PublicKey[]} An array of unique mint addresses (as PublicKey objects) found in the provided instructions.
|
|
562
|
+
*
|
|
563
|
+
* @example
|
|
564
|
+
* const instructions = [/* array of web3.TransactionInstruction objects * /];
|
|
565
|
+
* const findCriteria = {
|
|
566
|
+
* "exampleProgram": {
|
|
567
|
+
* programId: "ExampleProgramId123456789",
|
|
568
|
+
* mintIndices: [0, 2]
|
|
569
|
+
* }
|
|
570
|
+
* };
|
|
571
|
+
* const mints = getMintsFromInstruction({ instructions, find: findCriteria });
|
|
572
|
+
* Log(mints); // Logs an array of unique PublicKey objects.
|
|
573
|
+
*/
|
|
574
|
+
function getMintsFromInstruction({ instructions, find, }) {
|
|
575
|
+
const mints = {};
|
|
576
|
+
// Iterate through each instruction
|
|
577
|
+
for (const ix of instructions) {
|
|
578
|
+
// Iterate through each key in the find record
|
|
579
|
+
for (const id in find) {
|
|
580
|
+
// Check if the instruction data matches the sighash and the program ID matches
|
|
581
|
+
try {
|
|
582
|
+
const _sighash = sighash(id, undefined, find[id].manualSnakeCase);
|
|
583
|
+
if (sighashMatch(ix.data, _sighash) &&
|
|
584
|
+
ix.programId.toBase58() == find[id].programId) {
|
|
585
|
+
// Iterate through each mint index specified in the find record
|
|
586
|
+
for (const index of find[id].mintIndices) {
|
|
587
|
+
const address = ix.keys[index].pubkey.toString();
|
|
588
|
+
mints[address] = true; // Mark the address as found
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
catch (_a) { }
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
// Convert the unique mint addresses to web3.PublicKey objects
|
|
596
|
+
const result = [];
|
|
597
|
+
for (const mint in mints) {
|
|
598
|
+
result.push(new web3.PublicKey(mint));
|
|
599
|
+
}
|
|
600
|
+
return result;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Creates instructions to wrap SOL to wSOL if the provided mint matches the wrapped SOL mint.
|
|
604
|
+
*
|
|
605
|
+
* This function takes a user's wallet public key and an array of mint-amount pairs. It filters the pairs to find those
|
|
606
|
+
* where the mint is the wrapped SOL mint (`So11111111111111111111111111111111111111112`). For each of these pairs, it
|
|
607
|
+
* generates instructions to wrap SOL to wSOL, owned by the target wallet.
|
|
608
|
+
*
|
|
609
|
+
* If no pairs match the wrapped SOL mint, the function will return an empty array.
|
|
610
|
+
*
|
|
611
|
+
* @param {web3.PublicKey} userWallet - The public key of the user's wallet.
|
|
612
|
+
* @param {web3.PublicKey} payer - The public key of transaction payer.
|
|
613
|
+
* @param {Array<{mint: web3.PublicKey, amount: BN}>} params - An array of objects, each containing:
|
|
614
|
+
* - `mint`: The public key of the mint.
|
|
615
|
+
* - `amount`: The amount of the token to be wrapped.
|
|
616
|
+
*
|
|
617
|
+
* @returns {Array<web3.TransactionInstruction>} - An array of transaction instructions to wrap SOL to wSOL.
|
|
618
|
+
* If no mint matches the wrapped SOL mint, the function returns an empty array.
|
|
619
|
+
*/
|
|
620
|
+
function wrapSolIfMintIsWsol(userWallet, payer, params) {
|
|
621
|
+
return params
|
|
622
|
+
.filter((v) => v.mint.toBase58() === "So11111111111111111111111111111111111111112")
|
|
623
|
+
.map((v) => wrapSolToWsol({ payer, owner: userWallet, amount: v.amount }))
|
|
624
|
+
.flat();
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Creates instructions to wrap SOL to wSOL if the provided mint matches the wrapped SOL mint. (Labeled version)
|
|
628
|
+
*
|
|
629
|
+
* This function takes a user's wallet public key and an array of mint-amount pairs. It filters the pairs to find those
|
|
630
|
+
* where the mint is the wrapped SOL mint (`So11111111111111111111111111111111111111112`). For each of these pairs, it
|
|
631
|
+
* generates instructions to wrap SOL to wSOL, owned by the target wallet.
|
|
632
|
+
*
|
|
633
|
+
* If no pairs match the wrapped SOL mint, the function will return an empty array.
|
|
634
|
+
*
|
|
635
|
+
* @param {web3.PublicKey} userWallet - The public key of the user's wallet.
|
|
636
|
+
* @param {web3.PublicKey} payer - The public key of transaction payer.
|
|
637
|
+
* @param {Array<{mint: web3.PublicKey, amount: BN}>} params - An array of objects, each containing:
|
|
638
|
+
* - `mint`: The public key of the mint.
|
|
639
|
+
* - `amount`: The amount of the token to be wrapped.
|
|
640
|
+
*
|
|
641
|
+
* @returns {Array<LabeledInstruction>} - An array of labeled transaction instructions to wrap SOL to wSOL.
|
|
642
|
+
* If no mint matches the wrapped SOL mint, the function returns an empty array.
|
|
643
|
+
*/
|
|
644
|
+
function wrapSolIfMintIsWsolLabeled(userWallet, payer, params) {
|
|
645
|
+
return params
|
|
646
|
+
.filter((v) => v.mint.toBase58() === "So11111111111111111111111111111111111111112")
|
|
647
|
+
.map((v) => wrapSolToWsolLabeled({ payer, owner: userWallet, amount: v.amount }))
|
|
648
|
+
.flat();
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* H-2106: Ensure the user-wallet associated token accounts for every non-wSOL mint
|
|
652
|
+
* referenced by a deposit-multi-token flow exist on chain. Symmetric to
|
|
653
|
+
* `wrapSolIfMintIsWsol` -- that helper guarantees the wSOL ATA via wrap, this
|
|
654
|
+
* one guarantees every other source ATA via createIdempotent. Without this,
|
|
655
|
+
* `depositMultipleTokenWithToken2022` references a non-existent user-wallet ATA
|
|
656
|
+
* as the Token Program transfer source and the on-chain handler fails with
|
|
657
|
+
* `InvalidAccountData`. Token program is resolved per-mint via the cached
|
|
658
|
+
* MintCache so both legacy SPL Token and Token-2022 mints derive correctly.
|
|
659
|
+
*/
|
|
660
|
+
function createSourceAtasIdempotent(connection, userWallet, payer, params) {
|
|
661
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
662
|
+
const nonWsol = params.filter((v) => v.mint.toBase58() !== "So11111111111111111111111111111111111111112");
|
|
663
|
+
if (nonWsol.length === 0)
|
|
664
|
+
return [];
|
|
665
|
+
const tokenProgramMap = yield getTokenProgramMapForMints(connection, nonWsol.map((v) => v.mint));
|
|
666
|
+
return nonWsol.map((v) => {
|
|
667
|
+
const tokenProgram = tokenProgramMap[v.mint.toString()];
|
|
668
|
+
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(v.mint, userWallet, false, tokenProgram);
|
|
669
|
+
return createAssociatedTokenAccountIdempotentInstruction(payer, ata, userWallet, v.mint, tokenProgram);
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
/** Labeled variant of `createSourceAtasIdempotent`. */
|
|
674
|
+
function createSourceAtasIdempotentLabeled(connection, userWallet, payer, params) {
|
|
675
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
676
|
+
const ixs = yield createSourceAtasIdempotent(connection, userWallet, payer, params);
|
|
677
|
+
return ixs.map((instruction) => ({
|
|
678
|
+
instruction,
|
|
679
|
+
label: `Create source token account in user wallet`,
|
|
680
|
+
class: `createSourceAtasIdempotentLabeled`,
|
|
681
|
+
}));
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
function wrapSolToWsol({ payer, owner, amount, }) {
|
|
685
|
+
const wSolAccount = generateAta(owner, addresses_1.WSOL_MINT);
|
|
686
|
+
// Step 1: Create ATA account IX
|
|
687
|
+
const ataIx = createAssociatedTokenAccountIdempotentInstruction(payer, wSolAccount, owner, addresses_1.WSOL_MINT);
|
|
688
|
+
if (amount !== undefined) {
|
|
689
|
+
console.log(`Amount is not undefined. Transferring ${amount.toString()} lamports from ${payer.toBase58()} to ${wSolAccount.toBase58()} and wrapping to wSOL.`);
|
|
690
|
+
// Step 1: Transfer lamports from authority to wSolAccount
|
|
691
|
+
const transferIx = web3.SystemProgram.transfer({
|
|
692
|
+
/** Account that will transfer lamports */
|
|
693
|
+
fromPubkey: payer,
|
|
694
|
+
/** Account that will receive transferred lamports */
|
|
695
|
+
toPubkey: wSolAccount,
|
|
696
|
+
/** Amount of lamports to transfer */
|
|
697
|
+
lamports: BigInt(amount.toString()),
|
|
698
|
+
});
|
|
699
|
+
// Step 2: Convert wSolAccount into wrapped sol account
|
|
700
|
+
const wrapSolIx = (0, spl_token_1.createSyncNativeInstruction)(wSolAccount);
|
|
701
|
+
// Return instructions
|
|
702
|
+
return [ataIx, transferIx, wrapSolIx];
|
|
703
|
+
}
|
|
704
|
+
// Just return ATA creation
|
|
705
|
+
return [ataIx];
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Generate a labeled version of wrapSolToWsol instructions, which includes descriptive
|
|
709
|
+
* labels for each instruction to enhance readability and debugging.
|
|
710
|
+
*
|
|
711
|
+
* @param param0
|
|
712
|
+
* @returns
|
|
713
|
+
*/
|
|
714
|
+
function wrapSolToWsolLabeled({ payer, owner, amount, }) {
|
|
715
|
+
const wSolAccount = generateAta(owner, addresses_1.WSOL_MINT);
|
|
716
|
+
// Step 1: Create ATA account IX
|
|
717
|
+
const ataIx = {
|
|
718
|
+
label: `Create ATA for wSOL`,
|
|
719
|
+
class: `wrapSolToWsolLabeled`,
|
|
720
|
+
instruction: createAssociatedTokenAccountIdempotentInstruction(payer, wSolAccount, owner, addresses_1.WSOL_MINT),
|
|
721
|
+
};
|
|
722
|
+
if (amount !== undefined) {
|
|
723
|
+
console.log(`Amount is not undefined. Transferring ${amount.toString()} lamports from ${payer.toBase58()} to ${wSolAccount.toBase58()} and wrapping to wSOL.`);
|
|
724
|
+
// Step 1: Transfer lamports from authority to wSolAccount
|
|
725
|
+
const transferIx = {
|
|
726
|
+
label: `Transfer lamports to wSOL account`,
|
|
727
|
+
class: `wrapSolToWsolLabeled`,
|
|
728
|
+
instruction: web3.SystemProgram.transfer({
|
|
729
|
+
/** Account that will transfer lamports */
|
|
730
|
+
fromPubkey: payer,
|
|
731
|
+
/** Account that will receive transferred lamports */
|
|
732
|
+
toPubkey: wSolAccount,
|
|
733
|
+
/** Amount of lamports to transfer */
|
|
734
|
+
lamports: BigInt(amount.toString()),
|
|
735
|
+
})
|
|
736
|
+
};
|
|
737
|
+
// Step 2: Convert wSolAccount into wrapped sol account
|
|
738
|
+
const wrapSolIx = {
|
|
739
|
+
label: `Sync native to wrap SOL`,
|
|
740
|
+
class: `wrapSolToWsolLabeled`,
|
|
741
|
+
instruction: (0, spl_token_1.createSyncNativeInstruction)(wSolAccount),
|
|
742
|
+
};
|
|
743
|
+
// Return instructions
|
|
744
|
+
return [ataIx, transferIx, wrapSolIx];
|
|
745
|
+
}
|
|
746
|
+
// Just return ATA creation
|
|
747
|
+
return [ataIx];
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Creates instructions to unwrap wSOL to SOL if the provided mint matches the wrapped SOL mint.
|
|
751
|
+
*
|
|
752
|
+
* This function takes a user's wallet public key and an array of mint public keys. It filters the array to find mints
|
|
753
|
+
* that match the wrapped SOL mint (`So11111111111111111111111111111111111111112`). For each of these mints, it
|
|
754
|
+
* generates instructions to unwrap wSOL to SOL, with the user's wallet as the authority.
|
|
755
|
+
*
|
|
756
|
+
* If no mints match the wrapped SOL mint, the function will return an empty array.
|
|
757
|
+
*
|
|
758
|
+
* @param {web3.PublicKey} userWallet - The public key of the user's wallet.
|
|
759
|
+
* @param {web3.PublicKey[]} mints - An array of public keys representing the mints.
|
|
760
|
+
*
|
|
761
|
+
* @returns {web3.TransactionInstruction[]} - An array of transaction instructions to unwrap wSOL to SOL.
|
|
762
|
+
* If no mint matches the wrapped SOL mint, the function returns an empty array.
|
|
763
|
+
*/
|
|
764
|
+
function unwrapSolIfMintIsWsol(userWallet, mints) {
|
|
765
|
+
return mints
|
|
766
|
+
.filter((mint) => mint.toBase58() === "So11111111111111111111111111111111111111112")
|
|
767
|
+
.map(() => unwrapWsolToSol({ authority: userWallet }))
|
|
768
|
+
.flat();
|
|
769
|
+
}
|
|
770
|
+
function unwrapWsolToSol({ authority, }) {
|
|
771
|
+
const wSolAccount = generateAta(authority, addresses_1.WSOL_MINT);
|
|
772
|
+
// account: PublicKey,
|
|
773
|
+
// destination: PublicKey,
|
|
774
|
+
// authority: PublicKey,
|
|
775
|
+
// multiSigners: (Signer | PublicKey)[] = [],
|
|
776
|
+
// programId = TOKEN_PROGRAM_ID
|
|
777
|
+
// Create close account instruction (transfers native SOL to authority)
|
|
778
|
+
const closeIx = (0, spl_token_1.createCloseAccountInstruction)(wSolAccount, authority, authority);
|
|
779
|
+
// Return instructions
|
|
780
|
+
return closeIx;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Creates instructions to unwrap wSOL to SOL if the provided mint matches the wrapped SOL mint. (Labeled version)
|
|
784
|
+
*
|
|
785
|
+
* This function takes a user's wallet public key and an array of mint public keys. It filters the array to find mints
|
|
786
|
+
* that match the wrapped SOL mint (`So11111111111111111111111111111111111111112`). For each of these mints, it
|
|
787
|
+
* generates instructions to unwrap wSOL to SOL, with the user's wallet as the authority.
|
|
788
|
+
*
|
|
789
|
+
* If no mints match the wrapped SOL mint, the function will return an empty array.
|
|
790
|
+
*
|
|
791
|
+
* @param {web3.PublicKey} userWallet - The public key of the user's wallet.
|
|
792
|
+
* @param {web3.PublicKey[]} mints - An array of public keys representing the mints.
|
|
793
|
+
*
|
|
794
|
+
* @returns {web3.TransactionInstruction[]} - An array of transaction instructions to unwrap wSOL to SOL.
|
|
795
|
+
* If no mint matches the wrapped SOL mint, the function returns an empty array.
|
|
796
|
+
*/
|
|
797
|
+
function unwrapSolIfMintIsWsolLabeled(userWallet, mints) {
|
|
798
|
+
return mints
|
|
799
|
+
.filter((mint) => mint.toBase58() === "So11111111111111111111111111111111111111112")
|
|
800
|
+
.map(() => unwrapWsolToSolLabeled({ authority: userWallet }))
|
|
801
|
+
.flat();
|
|
802
|
+
}
|
|
803
|
+
function unwrapWsolToSolLabeled({ authority, }) {
|
|
804
|
+
const wSolAccount = generateAta(authority, addresses_1.WSOL_MINT);
|
|
805
|
+
// account: PublicKey,
|
|
806
|
+
// destination: PublicKey,
|
|
807
|
+
// authority: PublicKey,
|
|
808
|
+
// multiSigners: (Signer | PublicKey)[] = [],
|
|
809
|
+
// programId = TOKEN_PROGRAM_ID
|
|
810
|
+
// Create close account instruction (transfers native SOL to authority)
|
|
811
|
+
const closeIx = (0, spl_token_1.createCloseAccountInstruction)(wSolAccount, authority, authority);
|
|
812
|
+
// Return instructions
|
|
813
|
+
return {
|
|
814
|
+
label: `Unwrap wSOL to SOL`,
|
|
815
|
+
class: `unwrapWsolToSolLabeled`,
|
|
816
|
+
instruction: closeIx,
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Checks if token accounts for specified mints exist for a given user wallet.
|
|
821
|
+
*
|
|
822
|
+
* This function takes a user's wallet public key and an array of mint public keys. It maps these mints to token seeds
|
|
823
|
+
* (objects containing mint and owner information) and checks if the token accounts exist using the `tokenAccountExists` function.
|
|
824
|
+
*
|
|
825
|
+
* If a mint corresponds to wrapped SOL (`So11111111111111111111111111111111111111112`) and the token account does not exist,
|
|
826
|
+
* it will not throw an error. For other mints, if the token account does not exist, the function will throw an error.
|
|
827
|
+
*
|
|
828
|
+
* @param {web3.PublicKey} userWallet - The public key of the user's wallet.
|
|
829
|
+
* @param {web3.PublicKey[]} mints - An array of public keys representing the mints.
|
|
830
|
+
*
|
|
831
|
+
* @returns {Promise<void>} - A promise that resolves if all non-wrapped SOL token accounts exist, otherwise it throws an error.
|
|
832
|
+
*
|
|
833
|
+
* @throws {Error} - Throws an error if a token account for a mint (other than wrapped SOL) does not exist.
|
|
834
|
+
*/
|
|
835
|
+
function inputTokenExists(connection, userWallet, mints) {
|
|
836
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
837
|
+
const tokenSeeds = mints.map((mint) => {
|
|
838
|
+
return { mint, owner: userWallet };
|
|
839
|
+
});
|
|
840
|
+
const resultMap = yield tokenAccountExists(connection, tokenSeeds);
|
|
841
|
+
resultMap.map((result, index) => {
|
|
842
|
+
const tokenKey = result.tokenKey;
|
|
843
|
+
const token = tokenSeeds[index];
|
|
844
|
+
const tokenIsWsol = token.mint.toString() === "So11111111111111111111111111111111111111112";
|
|
845
|
+
if (tokenIsWsol && !result.exists) {
|
|
846
|
+
}
|
|
847
|
+
else if (!result.exists) {
|
|
848
|
+
throw new Error(`Token: ${tokenKey} owned by ${token.owner} does not exist. Mint: ${token.mint}`);
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Get Jupiter route ix parameters
|
|
855
|
+
*
|
|
856
|
+
* @param data
|
|
857
|
+
*/
|
|
858
|
+
function getJupiterRouteIxParams(data) {
|
|
859
|
+
const result = deserializeParametersFromIDL(jupiter_idl_1.IDL, 'route', data);
|
|
860
|
+
const routePlan = result.params['route_plan'];
|
|
861
|
+
const quotedOutAmount = new bn_js_1.default(result.params['quoted_out_amount']);
|
|
862
|
+
const slippageBps = result.params['slippage_bps'].readUInt16LE();
|
|
863
|
+
const platformFeeBps = result.params['platform_fee_bps'].readUInt8();
|
|
864
|
+
return {
|
|
865
|
+
routePlan,
|
|
866
|
+
quotedOutAmount,
|
|
867
|
+
slippageBps,
|
|
868
|
+
platformFeeBps,
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Converts tx metadata to versioned transaction
|
|
873
|
+
*
|
|
874
|
+
* @param txMessage
|
|
875
|
+
*/
|
|
876
|
+
function toVersionedTransaction(connection, txMessage) {
|
|
877
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
878
|
+
const alts = yield stringToAlt(connection, txMessage.addressLookupTableAddresses);
|
|
879
|
+
const result = new web3.VersionedTransaction(new web3.TransactionMessage({
|
|
880
|
+
instructions: txMessage.mainInstructions.map((ix) => ixStrToWeb3Ix(ix)),
|
|
881
|
+
payerKey: new web3.PublicKey(txMessage.payer),
|
|
882
|
+
recentBlockhash: web3.PublicKey.default.toString(),
|
|
883
|
+
}).compileToV0Message(alts));
|
|
884
|
+
return result;
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
function ixStrToWeb3Ix(ix) {
|
|
888
|
+
return {
|
|
889
|
+
keys: ix.accounts.map((account) => {
|
|
890
|
+
return {
|
|
891
|
+
isSigner: account.isSigner,
|
|
892
|
+
isWritable: account.isWritable,
|
|
893
|
+
pubkey: new web3.PublicKey(account.pubkey),
|
|
894
|
+
};
|
|
895
|
+
}),
|
|
896
|
+
data: Buffer.from(ix.data, "base64"),
|
|
897
|
+
programId: new web3.PublicKey(ix.programId),
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
function stringToAlt(connection, alts) {
|
|
901
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
902
|
+
const c = CreateTxMetadata_1.CreateTxMetadata.instance();
|
|
903
|
+
c.setConnection(connection);
|
|
904
|
+
return yield c.stringToAlt(alts);
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
let previousHeliusFeeLevels = {
|
|
908
|
+
priorityFeeLevels: {
|
|
909
|
+
high: 9327508,
|
|
910
|
+
low: 500000,
|
|
911
|
+
medium: 2675228,
|
|
912
|
+
min: 500000,
|
|
913
|
+
unsafeMax: 2368000000,
|
|
914
|
+
veryHigh: 28631588,
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
function getPriorityFeeEstimate(priorityLevel, transaction, rpcUrl) {
|
|
918
|
+
const tx = bs58_1.default.encode(transaction.serialize());
|
|
919
|
+
const heliusFeeLevels = getPriorityFeeEstimate2(tx, { includeAllPriorityFeeLevels: true }, rpcUrl);
|
|
920
|
+
heliusFeeLevels.then(feeLevels => {
|
|
921
|
+
previousHeliusFeeLevels = feeLevels;
|
|
922
|
+
});
|
|
923
|
+
const m = {
|
|
924
|
+
Min: "min",
|
|
925
|
+
Low: "low",
|
|
926
|
+
Default: "medium",
|
|
927
|
+
Medium: "medium",
|
|
928
|
+
High: "high",
|
|
929
|
+
VeryHigh: "veryHigh",
|
|
930
|
+
UnsafeMax: "unsafeMax",
|
|
931
|
+
};
|
|
932
|
+
const feeLevels = {
|
|
933
|
+
low: previousHeliusFeeLevels.priorityFeeLevels.medium * 2,
|
|
934
|
+
default: mid(previousHeliusFeeLevels.priorityFeeLevels.medium, previousHeliusFeeLevels.priorityFeeLevels.high),
|
|
935
|
+
high: previousHeliusFeeLevels.priorityFeeLevels.high,
|
|
936
|
+
veryHigh: previousHeliusFeeLevels.priorityFeeLevels.veryHigh * 3,
|
|
937
|
+
};
|
|
938
|
+
return {
|
|
939
|
+
priorityFeeEstimate: previousHeliusFeeLevels.priorityFeeLevels[m[priorityLevel]],
|
|
940
|
+
feeLevels,
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
function getPriorityFeeEstimate2(transaction, options, url) {
|
|
944
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
945
|
+
const response = yield fetch(url, {
|
|
946
|
+
method: "POST",
|
|
947
|
+
headers: { "Content-Type": "application/json" },
|
|
948
|
+
body: JSON.stringify({
|
|
949
|
+
jsonrpc: "2.0",
|
|
950
|
+
id: "1",
|
|
951
|
+
method: "getPriorityFeeEstimate",
|
|
952
|
+
params: [
|
|
953
|
+
{
|
|
954
|
+
transaction,
|
|
955
|
+
options,
|
|
956
|
+
},
|
|
957
|
+
],
|
|
958
|
+
}),
|
|
959
|
+
});
|
|
960
|
+
const data = yield response.json();
|
|
961
|
+
return data.result;
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
function mid(min, max) {
|
|
965
|
+
return min + (max - min) / 2;
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Find all nonce pubkey owned by given owner and index
|
|
969
|
+
*
|
|
970
|
+
* @param owner
|
|
971
|
+
*/
|
|
972
|
+
function generateNonceAddressFromIndex(owner, index) {
|
|
973
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
974
|
+
return yield web3.PublicKey.createWithSeed(owner, `hs-nonce-${index}`, web3.SystemProgram.programId);
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Find all nonce pubkey owned by given owner
|
|
979
|
+
*
|
|
980
|
+
* @param owner
|
|
981
|
+
*/
|
|
982
|
+
function generateNonceAddressesOwnedBy(owner, count) {
|
|
983
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
984
|
+
const nonceAddresses = [];
|
|
985
|
+
for (let i = 0; i < count; i++) {
|
|
986
|
+
nonceAddresses.push(yield generateNonceAddressFromIndex(owner, i));
|
|
987
|
+
}
|
|
988
|
+
return nonceAddresses;
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Find all nonce pubkey owned by given owner
|
|
993
|
+
*
|
|
994
|
+
* TODO: Put this into a class and the class must serve as cache of nonce accounts (so that we don't query nonce account multiple times)
|
|
995
|
+
*
|
|
996
|
+
* @param owner
|
|
997
|
+
*/
|
|
998
|
+
function findNonceOwnedBy(connection, owner, count) {
|
|
999
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1000
|
+
const nonceAddresses = yield generateNonceAddressesOwnedBy(owner, count);
|
|
1001
|
+
const infos = yield connection.getMultipleAccountsInfo(nonceAddresses);
|
|
1002
|
+
const result = infos.filter(info => info !== null).map(info => {
|
|
1003
|
+
const result = {
|
|
1004
|
+
/** `true` if this account's data contains a loaded program */
|
|
1005
|
+
executable: info.executable,
|
|
1006
|
+
/** Identifier of the program that owns the account */
|
|
1007
|
+
owner: info.owner,
|
|
1008
|
+
/** Number of lamports assigned to the account */
|
|
1009
|
+
lamports: info.lamports,
|
|
1010
|
+
/** Optional data assigned to the account */
|
|
1011
|
+
data: web3.NonceAccount.fromAccountData(info.data),
|
|
1012
|
+
/** Optional rent epoch info for account */
|
|
1013
|
+
rentEpoch: info.rentEpoch,
|
|
1014
|
+
};
|
|
1015
|
+
return result;
|
|
1016
|
+
});
|
|
1017
|
+
return result;
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
exports.benchmark = (() => {
|
|
1021
|
+
let startTime;
|
|
1022
|
+
return ({ end, name, msg }) => {
|
|
1023
|
+
if (end) {
|
|
1024
|
+
(0, Logging_1.Log)(`${name}: ${msg} elapsed time: ${new Date().getTime() / 1000 - startTime}`);
|
|
1025
|
+
}
|
|
1026
|
+
else {
|
|
1027
|
+
startTime = new Date().getTime() / 1000;
|
|
1028
|
+
(0, Logging_1.Log)(`${name}: Benchmarking ${msg}`);
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
})();
|
|
1032
|
+
function tokenizer(buffer) {
|
|
1033
|
+
let clone = buffer.map(v => v);
|
|
1034
|
+
let currentIndex = 0;
|
|
1035
|
+
return {
|
|
1036
|
+
readBuffer: (length) => {
|
|
1037
|
+
currentIndex += length;
|
|
1038
|
+
const result = clone.subarray(0, length);
|
|
1039
|
+
clone = clone.subarray(length);
|
|
1040
|
+
return Buffer.from(result);
|
|
1041
|
+
},
|
|
1042
|
+
currentIndex: () => {
|
|
1043
|
+
return currentIndex;
|
|
1044
|
+
},
|
|
1045
|
+
remainingBytes: () => {
|
|
1046
|
+
return clone;
|
|
1047
|
+
},
|
|
1048
|
+
debug: () => {
|
|
1049
|
+
const hexValues = Buffer.from(clone).toString('hex');
|
|
1050
|
+
return `currentIndex: ${currentIndex}, remainingBytes: ${hexValues}`;
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
function deserializeParametersFromIDL(idl, instruction, data) {
|
|
1055
|
+
const tokens = tokenizer(data);
|
|
1056
|
+
const discriminator = tokens.readBuffer(8);
|
|
1057
|
+
const params = {};
|
|
1058
|
+
const ixDefinition = idl.instructions.find((ix) => ix.name === instruction);
|
|
1059
|
+
if (!discriminator.equals(Uint8Array.from(ixDefinition.discriminator))) {
|
|
1060
|
+
throw new Error(`deserializeParametersFromIDL: Discriminator mismatch.`);
|
|
1061
|
+
}
|
|
1062
|
+
for (const arg of ixDefinition.args) {
|
|
1063
|
+
const value = extractValue(idl, arg.type, tokens);
|
|
1064
|
+
params[arg.name] = value;
|
|
1065
|
+
}
|
|
1066
|
+
return {
|
|
1067
|
+
discriminator,
|
|
1068
|
+
params,
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
function extractValue(idl, type, tokens) {
|
|
1072
|
+
if (typeof type === 'object') {
|
|
1073
|
+
if (typeof type.option !== 'undefined') {
|
|
1074
|
+
return resolveOption(idl, type.option, tokens);
|
|
1075
|
+
}
|
|
1076
|
+
else if (typeof type.vec !== 'undefined') {
|
|
1077
|
+
return resolveVec(idl, type.vec, tokens);
|
|
1078
|
+
}
|
|
1079
|
+
else if (typeof type.array !== 'undefined') {
|
|
1080
|
+
return resolveArray(idl, type.array, tokens);
|
|
1081
|
+
}
|
|
1082
|
+
else if (typeof type.defined !== 'undefined') {
|
|
1083
|
+
return resolveDefined(idl, type.defined.name, tokens);
|
|
1084
|
+
}
|
|
1085
|
+
else {
|
|
1086
|
+
const k = Object.keys(type);
|
|
1087
|
+
throw new Error(`extractValue: Unexpected error: Unexpected type key: ${k[0]}, debug: ${tokens.debug()}`);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
else if (typeof type === 'string') {
|
|
1091
|
+
const value = extractPrimitives(type, tokens);
|
|
1092
|
+
if (value === undefined) {
|
|
1093
|
+
throw new Error(`extractValue: Unexpected error: Unable to extract value from type: ${type}, debug: ${tokens.debug()}`);
|
|
1094
|
+
}
|
|
1095
|
+
return value;
|
|
1096
|
+
}
|
|
1097
|
+
else {
|
|
1098
|
+
throw new Error(`extractValue: Unexpected error: Unexpected type: ${type}, debug: ${tokens.debug()}`);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
function resolveStruct(idl, fields, tokens) {
|
|
1102
|
+
const values = [];
|
|
1103
|
+
for (let i = 0; i < fields.length; i++) {
|
|
1104
|
+
const field = fields[i];
|
|
1105
|
+
const value = extractValue(idl, field.type, tokens);
|
|
1106
|
+
values.push(new Uint8Array(value));
|
|
1107
|
+
}
|
|
1108
|
+
return Buffer.concat(values);
|
|
1109
|
+
}
|
|
1110
|
+
function resolveEnum(idl, variants, tokens) {
|
|
1111
|
+
let index;
|
|
1112
|
+
const values = [];
|
|
1113
|
+
if (variants.length <= 256) {
|
|
1114
|
+
const buffer = tokens.readBuffer(1);
|
|
1115
|
+
index = buffer.readUint8();
|
|
1116
|
+
values.push(new Uint8Array(buffer));
|
|
1117
|
+
}
|
|
1118
|
+
else if (variants.length <= 65536) {
|
|
1119
|
+
const buffer = tokens.readBuffer(2);
|
|
1120
|
+
index = buffer.readUint16LE();
|
|
1121
|
+
values.push(new Uint8Array(buffer));
|
|
1122
|
+
}
|
|
1123
|
+
else {
|
|
1124
|
+
throw new Error(`resolveEnum: Unsupported enum. Debug: ${tokens.debug()}`);
|
|
1125
|
+
}
|
|
1126
|
+
if (typeof variants[index].fields !== 'undefined') {
|
|
1127
|
+
for (let i = 0; i < variants[index].fields.length; i++) {
|
|
1128
|
+
const field = variants[index].fields[i];
|
|
1129
|
+
const value = extractValue(idl, field.type, tokens);
|
|
1130
|
+
values.push(new Uint8Array(value));
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
return Buffer.concat(values);
|
|
1134
|
+
}
|
|
1135
|
+
function resolveOption(idl, type, tokens) {
|
|
1136
|
+
const isSet = tokens.readBuffer(1);
|
|
1137
|
+
if (isSet[0] === 0) {
|
|
1138
|
+
return Buffer.from([0]);
|
|
1139
|
+
}
|
|
1140
|
+
else if (isSet[0] === 1) {
|
|
1141
|
+
return Buffer.concat([isSet, extractValue(idl, type, tokens)]);
|
|
1142
|
+
}
|
|
1143
|
+
else {
|
|
1144
|
+
throw new Error(`resolveOption: Value can only be 1 or 0. Actual value: ${isSet[0]}, debug: ${tokens.debug()}`);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
function resolveVec(idl, type, tokens) {
|
|
1148
|
+
const vectorSize = tokens.readBuffer(4);
|
|
1149
|
+
const size = vectorSize.readUint32LE();
|
|
1150
|
+
const values = [];
|
|
1151
|
+
values.push(new Uint8Array(vectorSize));
|
|
1152
|
+
for (let i = 0; i < size; i++) {
|
|
1153
|
+
values.push(new Uint8Array(extractValue(idl, type, tokens)));
|
|
1154
|
+
}
|
|
1155
|
+
return Buffer.concat(values);
|
|
1156
|
+
}
|
|
1157
|
+
function resolveArray(idl, type, tokens) {
|
|
1158
|
+
const _type = type[0];
|
|
1159
|
+
const count = type[1];
|
|
1160
|
+
const values = [];
|
|
1161
|
+
if (typeof _type === 'object' && typeof _type.defined === 'object' && typeof _type.defined.name === 'string') {
|
|
1162
|
+
for (let i = 0; i < count; i++) {
|
|
1163
|
+
values.push(new Uint8Array(resolveDefined(idl, _type.defined.name, tokens)));
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
else if (typeof _type === 'string') {
|
|
1167
|
+
for (let i = 0; i < count; i++) {
|
|
1168
|
+
const value = extractPrimitives(_type, tokens);
|
|
1169
|
+
if (value === undefined) {
|
|
1170
|
+
throw new Error(`resolveArray: Unexpected error: Unresolvable value ${_type}, debug: ${tokens.debug()}`);
|
|
1171
|
+
}
|
|
1172
|
+
values.push(new Uint8Array(value));
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
throw new Error(`resolveArray: Unexpected error: Unresolvable type: ${_type}, debug: ${tokens.debug()}`);
|
|
1177
|
+
}
|
|
1178
|
+
return Buffer.concat(values);
|
|
1179
|
+
}
|
|
1180
|
+
function resolveDefined(idl, typeName, tokens) {
|
|
1181
|
+
const type = idl.types.find((t) => t.name === typeName);
|
|
1182
|
+
if (type === undefined) {
|
|
1183
|
+
throw new Error(`resolveDefined: Unexpected error: Cannot find type: ${typeName}`);
|
|
1184
|
+
}
|
|
1185
|
+
if (type.type.kind === 'struct') {
|
|
1186
|
+
return resolveStruct(idl, type.type.fields, tokens);
|
|
1187
|
+
}
|
|
1188
|
+
else if (type.type.kind === 'enum') {
|
|
1189
|
+
return resolveEnum(idl, type.type.variants, tokens);
|
|
1190
|
+
}
|
|
1191
|
+
else {
|
|
1192
|
+
throw new Error(`resolveDefined: Unexpected error: Unexpected type: ${type.type.kind}, debug: ${tokens.debug()}`);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
function extractPrimitives(type, tokens) {
|
|
1196
|
+
if (type === 'u8' || type === 'i8' || type === 'bool') {
|
|
1197
|
+
return tokens.readBuffer(1);
|
|
1198
|
+
}
|
|
1199
|
+
else if (type === 'u16' || type === 'i16') {
|
|
1200
|
+
return tokens.readBuffer(2);
|
|
1201
|
+
}
|
|
1202
|
+
else if (type === 'u32' || type === 'i32') {
|
|
1203
|
+
return tokens.readBuffer(4);
|
|
1204
|
+
}
|
|
1205
|
+
else if (type === 'u64' || type === '164') {
|
|
1206
|
+
return tokens.readBuffer(8);
|
|
1207
|
+
}
|
|
1208
|
+
else if (type === 'u128' || type === 'i128') {
|
|
1209
|
+
return tokens.readBuffer(16);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
function simulateTransaction(_a) {
|
|
1213
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, instructions, payerKey, alts, signers, addresses, }) {
|
|
1214
|
+
const testVersionedTxn = new web3.VersionedTransaction(new web3.TransactionMessage({
|
|
1215
|
+
instructions,
|
|
1216
|
+
payerKey,
|
|
1217
|
+
recentBlockhash: web3.PublicKey.default.toString(),
|
|
1218
|
+
}).compileToV0Message(alts));
|
|
1219
|
+
if (signers.length > 0) {
|
|
1220
|
+
testVersionedTxn.sign(signers);
|
|
1221
|
+
}
|
|
1222
|
+
const simulation = yield connection.simulateTransaction(testVersionedTxn, {
|
|
1223
|
+
replaceRecentBlockhash: true,
|
|
1224
|
+
sigVerify: false,
|
|
1225
|
+
accounts: {
|
|
1226
|
+
encoding: 'base64',
|
|
1227
|
+
addresses,
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
if (simulation.value.unitsConsumed === undefined) {
|
|
1231
|
+
throw new Error("Unable to calculate compute budget.");
|
|
1232
|
+
}
|
|
1233
|
+
return {
|
|
1234
|
+
err: simulation.value.err,
|
|
1235
|
+
logs: simulation.value.logs,
|
|
1236
|
+
accounts: simulation.value.accounts,
|
|
1237
|
+
unitsConsumed: simulation.value.unitsConsumed,
|
|
1238
|
+
returnData: simulation.value.returnData,
|
|
1239
|
+
};
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
/**
|
|
1243
|
+
* Construct a CreateAssociatedTokenAccountIdempotent instruction
|
|
1244
|
+
*
|
|
1245
|
+
* @param payer Payer of the initialization fees
|
|
1246
|
+
* @param associatedToken New associated token account
|
|
1247
|
+
* @param owner Owner of the new account
|
|
1248
|
+
* @param mint Token mint account
|
|
1249
|
+
* @param programId SPL Token program account
|
|
1250
|
+
* @param associatedTokenProgramId SPL Associated Token program account
|
|
1251
|
+
*
|
|
1252
|
+
* @return Instruction to add to a transaction
|
|
1253
|
+
*/
|
|
1254
|
+
function createAssociatedTokenAccountIdempotentInstruction(payer, associatedToken, owner, mint, programId = addresses_1.TOKEN_PROGRAM_ID, associatedTokenProgramId = addresses_1.ASSOCIATED_TOKEN_PROGRAM) {
|
|
1255
|
+
return buildAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, Buffer.from([1]), programId, associatedTokenProgramId);
|
|
1256
|
+
}
|
|
1257
|
+
function buildAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, instructionData, programId = addresses_1.TOKEN_PROGRAM_ID, associatedTokenProgramId = addresses_1.ASSOCIATED_TOKEN_PROGRAM) {
|
|
1258
|
+
const keys = [
|
|
1259
|
+
{ pubkey: payer, isSigner: true, isWritable: true },
|
|
1260
|
+
{ pubkey: associatedToken, isSigner: false, isWritable: true },
|
|
1261
|
+
{ pubkey: owner, isSigner: false, isWritable: false },
|
|
1262
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
1263
|
+
{ pubkey: web3.SystemProgram.programId, isSigner: false, isWritable: false },
|
|
1264
|
+
{ pubkey: programId, isSigner: false, isWritable: false },
|
|
1265
|
+
];
|
|
1266
|
+
return new web3.TransactionInstruction({
|
|
1267
|
+
keys,
|
|
1268
|
+
programId: associatedTokenProgramId,
|
|
1269
|
+
data: instructionData,
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
// pub fn check_tick_array_start_index(
|
|
1273
|
+
// tick_array_start_index: i32,
|
|
1274
|
+
// tick_index: i32,
|
|
1275
|
+
// tick_spacing: u16,
|
|
1276
|
+
// ) -> Result<()> {
|
|
1277
|
+
// require!(
|
|
1278
|
+
// tick_index >= tick_math::MIN_TICK,
|
|
1279
|
+
// ErrorCode::TickLowerOverflow
|
|
1280
|
+
// );
|
|
1281
|
+
// require!(
|
|
1282
|
+
// tick_index <= tick_math::MAX_TICK,
|
|
1283
|
+
// ErrorCode::TickUpperOverflow
|
|
1284
|
+
// );
|
|
1285
|
+
// require_eq!(0, tick_index % i32::from(tick_spacing));
|
|
1286
|
+
// let expect_start_index = TickArrayState::get_array_start_index(tick_index, tick_spacing);
|
|
1287
|
+
// require_eq!(tick_array_start_index, expect_start_index);
|
|
1288
|
+
// Ok(())
|
|
1289
|
+
// }
|
|
1290
|
+
function raydiumStartTickIndex(tick_index, tick_spacing) {
|
|
1291
|
+
const TICK_ARRAY_SIZE = 60;
|
|
1292
|
+
const tick_count = TICK_ARRAY_SIZE * tick_spacing;
|
|
1293
|
+
const start_index = tick_index / tick_count;
|
|
1294
|
+
if (tick_index < 0 && tick_index % tick_count != 0) {
|
|
1295
|
+
return (Math.ceil(start_index) - 1) * tick_count;
|
|
1296
|
+
}
|
|
1297
|
+
else {
|
|
1298
|
+
return Math.floor(start_index) * tick_count;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
function i32ToBeBuffer(value) {
|
|
1302
|
+
// Let's manually convert a number to a buffer (4-bytes)
|
|
1303
|
+
// Input is signed 32-bit integer
|
|
1304
|
+
// Output is 4-bytes buffer in big-endian order
|
|
1305
|
+
const buffer = Buffer.alloc(4);
|
|
1306
|
+
buffer.writeInt32BE(value, 0);
|
|
1307
|
+
return buffer;
|
|
1308
|
+
}
|
|
1309
|
+
function findUserAlts(userWallet_1, connection_1) {
|
|
1310
|
+
return __awaiter(this, arguments, void 0, function* (userWallet, connection, filterDeactivated = true) {
|
|
1311
|
+
const alts = yield connection.getProgramAccounts(web3.AddressLookupTableProgram.programId, {
|
|
1312
|
+
filters: [{
|
|
1313
|
+
memcmp: {
|
|
1314
|
+
offset: 4 + 8 + 8 + 1 + 1,
|
|
1315
|
+
bytes: userWallet.toString(),
|
|
1316
|
+
}
|
|
1317
|
+
}]
|
|
1318
|
+
});
|
|
1319
|
+
const _alts = alts.map((alt) => {
|
|
1320
|
+
return new web3.AddressLookupTableAccount({
|
|
1321
|
+
key: alt.pubkey,
|
|
1322
|
+
state: web3.AddressLookupTableAccount.deserialize(new Uint8Array(alt.account.data))
|
|
1323
|
+
});
|
|
1324
|
+
});
|
|
1325
|
+
return filterDeactivated ? _alts.filter(alt => alt.isActive()) : _alts;
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* Filters the list of pubkeys to only include pubkeys that are in the alt.
|
|
1330
|
+
*
|
|
1331
|
+
* @param pubkeys - List of pubkeys to filter
|
|
1332
|
+
* @param alt - Alt to filter pubkeys by
|
|
1333
|
+
* @returns List of pubkeys that are in the alt
|
|
1334
|
+
*/
|
|
1335
|
+
function pubkeysInAlt(pubkeys, alt) {
|
|
1336
|
+
const pubkeysInAlt = pubkeys.filter(pubkey => {
|
|
1337
|
+
const address = alt.state.addresses.find(address => {
|
|
1338
|
+
if (address.toString() === pubkey) {
|
|
1339
|
+
return address;
|
|
1340
|
+
}
|
|
1341
|
+
});
|
|
1342
|
+
if (address) {
|
|
1343
|
+
return true;
|
|
1344
|
+
}
|
|
1345
|
+
else {
|
|
1346
|
+
return false;
|
|
1347
|
+
}
|
|
1348
|
+
});
|
|
1349
|
+
return pubkeysInAlt;
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* The goal of this function is to batch 100 accounts at a time as it is the max number of accounts that can be fetched at once.
|
|
1353
|
+
* @param pubkeys - The accounts to fetch.
|
|
1354
|
+
* @returns - A promise that resolves to an array of TokenAccountInfo objects.
|
|
1355
|
+
*/
|
|
1356
|
+
function getBatchedMultipleAccountsInfo(connection_1, pubkeys_1) {
|
|
1357
|
+
return __awaiter(this, arguments, void 0, function* (connection, pubkeys, commitment = "confirmed") {
|
|
1358
|
+
const batchSize = 100;
|
|
1359
|
+
const batches = [];
|
|
1360
|
+
for (let i = 0; i < pubkeys.length; i += batchSize) {
|
|
1361
|
+
batches.push(pubkeys.slice(i, i + batchSize));
|
|
1362
|
+
}
|
|
1363
|
+
const batch = yield Promise.all(batches.map(batch => connection.getMultipleAccountsInfo(batch, commitment)));
|
|
1364
|
+
return batch.flat();
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
function getTokenProgramForMints(connection, mints) {
|
|
1368
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1369
|
+
const mintCache = yield MintCache_1.MintCache
|
|
1370
|
+
.instance(connection)
|
|
1371
|
+
.getBatchedMultipleAccountsInfo(mints)
|
|
1372
|
+
.waitForResult();
|
|
1373
|
+
let tokenProgram = null;
|
|
1374
|
+
for (let i = 0; i < mints.length; i++) {
|
|
1375
|
+
const pubkey = mints[i];
|
|
1376
|
+
const mintAccount = mintCache[pubkey.toString()].info;
|
|
1377
|
+
const _tokenProgram = mintAccount.owner;
|
|
1378
|
+
// Make sure that all tokens are owned by the same program.
|
|
1379
|
+
if (tokenProgram === null) {
|
|
1380
|
+
tokenProgram = _tokenProgram;
|
|
1381
|
+
}
|
|
1382
|
+
else {
|
|
1383
|
+
// Make sure that all tokens are owned by the same program.
|
|
1384
|
+
if (_tokenProgram.toString() !== tokenProgram.toString()) {
|
|
1385
|
+
throw new Error(`Token program mismatch for mint: ${pubkey}. It should be owned by program: ${tokenProgram}`);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
if (tokenProgram === null) {
|
|
1390
|
+
throw new Error(`No mints were passed in the parameter.`);
|
|
1391
|
+
}
|
|
1392
|
+
return tokenProgram;
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
function getTokenProgramMapForMints(connection, mints) {
|
|
1396
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1397
|
+
if (mints.length === 0) {
|
|
1398
|
+
throw new Error(`No mints were passed in the parameter.`);
|
|
1399
|
+
}
|
|
1400
|
+
const mintCache = yield MintCache_1.MintCache
|
|
1401
|
+
.instance(connection)
|
|
1402
|
+
.getBatchedMultipleAccountsInfo(mints)
|
|
1403
|
+
.waitForResult();
|
|
1404
|
+
let tokenProgramMap = {};
|
|
1405
|
+
for (let i = 0; i < mints.length; i++) {
|
|
1406
|
+
const pubkey = mints[i];
|
|
1407
|
+
const mintAccount = mintCache[pubkey.toString()].info;
|
|
1408
|
+
const _tokenProgram = mintAccount.owner;
|
|
1409
|
+
tokenProgramMap[pubkey.toString()] = _tokenProgram;
|
|
1410
|
+
}
|
|
1411
|
+
return tokenProgramMap;
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
function getMeteoraStrategyType(strategyType, totalXAmount, totalYAmount) {
|
|
1415
|
+
let singleSidedX;
|
|
1416
|
+
const [_strategyType, oneSide] = types_1.StrategyTypeMap2[strategyType];
|
|
1417
|
+
if (oneSide) {
|
|
1418
|
+
if (totalXAmount.gt(new bn_js_1.default(0)) && totalYAmount.eq(new bn_js_1.default(0))) {
|
|
1419
|
+
singleSidedX = true;
|
|
1420
|
+
}
|
|
1421
|
+
else if (totalXAmount.eq(new bn_js_1.default(0)) && totalYAmount.gt(new bn_js_1.default(0))) {
|
|
1422
|
+
singleSidedX = false;
|
|
1423
|
+
}
|
|
1424
|
+
else {
|
|
1425
|
+
throw new errors_1.AppError("Total X or Y amount must be greater than 0 when adding liquidity one-sided", `getMeteoraStrategyType`);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
return [_strategyType, singleSidedX];
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Generate Hawksight fee accounts for X and Y tokens
|
|
1432
|
+
*/
|
|
1433
|
+
function generateHawksightFeeAccounts(tokenXMint, tokenYMint, tokenXProgram, tokenYProgram) {
|
|
1434
|
+
return {
|
|
1435
|
+
ownerFeeX: generateAta(addresses_1.SITE_FEE_OWNER, tokenXMint, tokenXProgram),
|
|
1436
|
+
ownerFeeY: generateAta(addresses_1.SITE_FEE_OWNER, tokenYMint, tokenYProgram),
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Fetch RemainingAccountsInfo for Token2022 tokens with transfer hooks.
|
|
1441
|
+
*
|
|
1442
|
+
* This function checks if the provided token mints have transfer hook extensions
|
|
1443
|
+
* and fetches the required extra account metas if they do.
|
|
1444
|
+
*
|
|
1445
|
+
* For standard SPL tokens or Token2022 tokens without transfer hooks, returns
|
|
1446
|
+
* empty slices and accounts (which is the default/no-op case).
|
|
1447
|
+
*
|
|
1448
|
+
* @param connection - Solana connection
|
|
1449
|
+
* @param tokenXMint - Token X mint address
|
|
1450
|
+
* @param tokenYMint - Token Y mint address
|
|
1451
|
+
* @param tokenXProgram - Token X program (TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID)
|
|
1452
|
+
* @param tokenYProgram - Token Y program (TOKEN_PROGRAM_ID or TOKEN_2022_PROGRAM_ID)
|
|
1453
|
+
* @returns RemainingAccountsInfo with slices and accounts for transfer hooks
|
|
1454
|
+
*/
|
|
1455
|
+
/**
|
|
1456
|
+
* Gets the transfer hook program ID from a Token2022 mint.
|
|
1457
|
+
* Parses TLV extensions to find the TransferHook extension (type 14).
|
|
1458
|
+
*
|
|
1459
|
+
* @param connection - Solana connection
|
|
1460
|
+
* @param mint - The mint to check for transfer hook
|
|
1461
|
+
* @returns The transfer hook program ID, or null if none exists
|
|
1462
|
+
*/
|
|
1463
|
+
function getTransferHookProgramId(connection, mint) {
|
|
1464
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1465
|
+
try {
|
|
1466
|
+
const mintInfo = yield connection.getAccountInfo(mint);
|
|
1467
|
+
if (!mintInfo || mintInfo.data.length < 165) {
|
|
1468
|
+
return null; // Not a valid mint or no extensions
|
|
1469
|
+
}
|
|
1470
|
+
// Token2022 mint structure:
|
|
1471
|
+
// - Base mint data: 82 bytes
|
|
1472
|
+
// - Account type: 1 byte (should be 1 for mint)
|
|
1473
|
+
// - Extensions follow after base data
|
|
1474
|
+
//
|
|
1475
|
+
// TransferHook extension has type 14 and contains:
|
|
1476
|
+
// - authority: 32 bytes
|
|
1477
|
+
// - programId: 32 bytes (the transfer hook program)
|
|
1478
|
+
const data = mintInfo.data;
|
|
1479
|
+
// Check if this is a Token2022 mint with extensions
|
|
1480
|
+
// The extension data starts at offset 165 (after base mint + account type)
|
|
1481
|
+
if (data.length <= 165) {
|
|
1482
|
+
return null;
|
|
1483
|
+
}
|
|
1484
|
+
// Parse TLV (Type-Length-Value) extensions
|
|
1485
|
+
let offset = 165; // Start of extensions
|
|
1486
|
+
while (offset + 4 <= data.length) {
|
|
1487
|
+
const extensionType = data.readUInt16LE(offset);
|
|
1488
|
+
const extensionLength = data.readUInt16LE(offset + 2);
|
|
1489
|
+
// TransferHook extension type is 14
|
|
1490
|
+
if (extensionType === 14 && extensionLength >= 64) {
|
|
1491
|
+
// Skip authority (32 bytes), read programId (32 bytes)
|
|
1492
|
+
const programIdBytes = data.subarray(offset + 4 + 32, offset + 4 + 64);
|
|
1493
|
+
const programId = new web3.PublicKey(programIdBytes);
|
|
1494
|
+
// Check if programId is not default (all zeros)
|
|
1495
|
+
if (!programId.equals(web3.PublicKey.default)) {
|
|
1496
|
+
return programId;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
offset += 4 + extensionLength;
|
|
1500
|
+
}
|
|
1501
|
+
return null;
|
|
1502
|
+
}
|
|
1503
|
+
catch (error) {
|
|
1504
|
+
(0, Logging_1.Log)(`Error fetching transfer hook for mint ${mint.toString()}: ${error}`);
|
|
1505
|
+
return null;
|
|
1506
|
+
}
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Gets extra account metas for a transfer hook program.
|
|
1511
|
+
* Parses the ExtraAccountMetas PDA to extract required accounts.
|
|
1512
|
+
*
|
|
1513
|
+
* @param connection - Solana connection
|
|
1514
|
+
* @param mint - The mint with the transfer hook
|
|
1515
|
+
* @param transferHookProgramId - The transfer hook program ID
|
|
1516
|
+
* @returns Array of AccountMeta for the transfer hook
|
|
1517
|
+
*/
|
|
1518
|
+
function getTransferHookExtraAccountMetas(connection, mint, transferHookProgramId) {
|
|
1519
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1520
|
+
try {
|
|
1521
|
+
// Derive the extra account metas PDA
|
|
1522
|
+
const [extraAccountMetasPda] = web3.PublicKey.findProgramAddressSync([Buffer.from('extra-account-metas'), mint.toBuffer()], transferHookProgramId);
|
|
1523
|
+
const accountInfo = yield connection.getAccountInfo(extraAccountMetasPda);
|
|
1524
|
+
if (!accountInfo) {
|
|
1525
|
+
return [];
|
|
1526
|
+
}
|
|
1527
|
+
// Parse the extra account metas
|
|
1528
|
+
// Format: u64 instruction_discriminator + u32 length + ExtraAccountMeta[]
|
|
1529
|
+
// Each ExtraAccountMeta: u8 discriminator + 32 bytes addressConfig + bool isSigner + bool isWritable
|
|
1530
|
+
const data = accountInfo.data;
|
|
1531
|
+
if (data.length < 12) {
|
|
1532
|
+
return [];
|
|
1533
|
+
}
|
|
1534
|
+
const count = data.readUInt32LE(8); // Length is at offset 8 (after u64 discriminator)
|
|
1535
|
+
const extraMetas = [];
|
|
1536
|
+
let offset = 12; // Start of extra accounts array
|
|
1537
|
+
for (let i = 0; i < count && offset + 35 <= data.length; i++) {
|
|
1538
|
+
const discriminator = data.readUInt8(offset);
|
|
1539
|
+
const addressConfig = data.subarray(offset + 1, offset + 33);
|
|
1540
|
+
const isSigner = data.readUInt8(offset + 33) === 1;
|
|
1541
|
+
const isWritable = data.readUInt8(offset + 34) === 1;
|
|
1542
|
+
// Discriminator 0 means literal address
|
|
1543
|
+
if (discriminator === 0) {
|
|
1544
|
+
extraMetas.push({
|
|
1545
|
+
pubkey: new web3.PublicKey(addressConfig),
|
|
1546
|
+
isSigner,
|
|
1547
|
+
isWritable,
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
// Other discriminators require more complex resolution (seeds, etc.)
|
|
1551
|
+
// For now, we only support literal addresses
|
|
1552
|
+
offset += 35;
|
|
1553
|
+
}
|
|
1554
|
+
return extraMetas;
|
|
1555
|
+
}
|
|
1556
|
+
catch (error) {
|
|
1557
|
+
(0, Logging_1.Log)(`Error fetching extra account metas: ${error}`);
|
|
1558
|
+
return [];
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
function fetchRemainingAccountsInfo(connection, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram) {
|
|
1563
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1564
|
+
const slices = [];
|
|
1565
|
+
const accounts = [];
|
|
1566
|
+
// Only Token2022 tokens can have transfer hooks
|
|
1567
|
+
// Standard SPL tokens (TOKEN_PROGRAM_ID) never have transfer hooks
|
|
1568
|
+
const hasToken2022X = tokenXProgram.equals(addresses_1.TOKEN_2022);
|
|
1569
|
+
const hasToken2022Y = tokenYProgram.equals(addresses_1.TOKEN_2022);
|
|
1570
|
+
// If neither token is Token2022, return empty (no transfer hooks possible)
|
|
1571
|
+
if (!hasToken2022X && !hasToken2022Y) {
|
|
1572
|
+
return { slices, accounts };
|
|
1573
|
+
}
|
|
1574
|
+
// Check token X for transfer hook
|
|
1575
|
+
if (hasToken2022X) {
|
|
1576
|
+
const hookProgramIdX = yield getTransferHookProgramId(connection, tokenXMint);
|
|
1577
|
+
if (hookProgramIdX) {
|
|
1578
|
+
const extraAccountsX = yield getTransferHookExtraAccountMetas(connection, tokenXMint, hookProgramIdX);
|
|
1579
|
+
if (extraAccountsX.length > 0) {
|
|
1580
|
+
slices.push({
|
|
1581
|
+
accountsType: types_1.RemainingAccountsType.TransferHookX,
|
|
1582
|
+
length: extraAccountsX.length,
|
|
1583
|
+
});
|
|
1584
|
+
accounts.push(...extraAccountsX);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
// Check token Y for transfer hook
|
|
1589
|
+
if (hasToken2022Y) {
|
|
1590
|
+
const hookProgramIdY = yield getTransferHookProgramId(connection, tokenYMint);
|
|
1591
|
+
if (hookProgramIdY) {
|
|
1592
|
+
const extraAccountsY = yield getTransferHookExtraAccountMetas(connection, tokenYMint, hookProgramIdY);
|
|
1593
|
+
if (extraAccountsY.length > 0) {
|
|
1594
|
+
slices.push({
|
|
1595
|
+
accountsType: types_1.RemainingAccountsType.TransferHookY,
|
|
1596
|
+
length: extraAccountsY.length,
|
|
1597
|
+
});
|
|
1598
|
+
accounts.push(...extraAccountsY);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
return { slices, accounts };
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
/**
|
|
1606
|
+
* Fetches remainingAccountsInfo for a reward mint's transfer hook (Token2022).
|
|
1607
|
+
* Used for claim_reward2 instructions where we only need transfer hooks for the reward token.
|
|
1608
|
+
*
|
|
1609
|
+
* @param connection - Solana connection
|
|
1610
|
+
* @param rewardMint - The reward token mint
|
|
1611
|
+
* @param rewardTokenProgram - The token program for the reward mint
|
|
1612
|
+
* @returns RemainingAccountsInfo with transfer hook accounts for the reward token
|
|
1613
|
+
*/
|
|
1614
|
+
function fetchRemainingAccountsInfoForReward(connection, rewardMint, rewardTokenProgram) {
|
|
1615
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1616
|
+
const slices = [];
|
|
1617
|
+
const accounts = [];
|
|
1618
|
+
// Only Token2022 tokens can have transfer hooks
|
|
1619
|
+
if (!rewardTokenProgram.equals(addresses_1.TOKEN_2022)) {
|
|
1620
|
+
return { slices, accounts };
|
|
1621
|
+
}
|
|
1622
|
+
// Check reward mint for transfer hook
|
|
1623
|
+
const hookProgramId = yield getTransferHookProgramId(connection, rewardMint);
|
|
1624
|
+
if (hookProgramId) {
|
|
1625
|
+
const extraAccounts = yield getTransferHookExtraAccountMetas(connection, rewardMint, hookProgramId);
|
|
1626
|
+
if (extraAccounts.length > 0) {
|
|
1627
|
+
slices.push({
|
|
1628
|
+
accountsType: types_1.RemainingAccountsType.TransferHookReward,
|
|
1629
|
+
length: extraAccounts.length,
|
|
1630
|
+
});
|
|
1631
|
+
accounts.push(...extraAccounts);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
return { slices, accounts };
|
|
1635
|
+
});
|
|
1636
|
+
}
|