@wallfree-dev/solana 0.13.43-beta.10 → 0.13.43-beta.12
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/.npm-cache/_logs/{2026-01-07T06_55_02_009Z-debug-0.log → 2026-01-16T16_53_49_411Z-debug-0.log} +2 -2
- package/package.json +4 -4
- package/v1/module/SPLTokens.js +1 -1
- package/v1/module/SPLTokens.js.map +1 -1
- package/v1/protocol/SolanaProtocol.d.ts +13 -1
- package/v1/protocol/SolanaProtocol.js +373 -70
- package/v1/protocol/SolanaProtocol.js.map +1 -1
- package/v1/protocol/SolanaSPLTokenProtocol.d.ts +11 -1
- package/v1/protocol/SolanaSPLTokenProtocol.js +616 -199
- package/v1/protocol/SolanaSPLTokenProtocol.js.map +1 -1
- package/v1/types/protocol.d.ts +20 -0
|
@@ -99,7 +99,100 @@ exports.SOLANA_UNITS_METADATA = {
|
|
|
99
99
|
var SolanaProtocol = /** @class */ (function () {
|
|
100
100
|
function SolanaProtocol(options) {
|
|
101
101
|
this.options = options;
|
|
102
|
+
// Caches
|
|
103
|
+
this.priorityFeeCache = { data: null, timestamp: 0 };
|
|
104
|
+
this.rentExemptionCache = new Map();
|
|
102
105
|
}
|
|
106
|
+
// Get minimum balance for rent exemption dynamically
|
|
107
|
+
// dataSize: size of account data in bytes
|
|
108
|
+
SolanaProtocol.prototype.getMinimumBalanceForRentExemption = function (dataSize) {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
110
|
+
var cached, now, rentExemption, e_1;
|
|
111
|
+
var _this = this;
|
|
112
|
+
return __generator(this, function (_a) {
|
|
113
|
+
switch (_a.label) {
|
|
114
|
+
case 0:
|
|
115
|
+
cached = this.rentExemptionCache.get(dataSize);
|
|
116
|
+
now = Date.now();
|
|
117
|
+
if (cached && (now - cached.timestamp) < SolanaProtocol.RENT_EXEMPTION_CACHE_TTL) {
|
|
118
|
+
return [2 /*return*/, cached.value];
|
|
119
|
+
}
|
|
120
|
+
_a.label = 1;
|
|
121
|
+
case 1:
|
|
122
|
+
_a.trys.push([1, 3, , 4]);
|
|
123
|
+
return [4 /*yield*/, this.withFallback(function (connection) { return __awaiter(_this, void 0, void 0, function () {
|
|
124
|
+
return __generator(this, function (_a) {
|
|
125
|
+
return [2 /*return*/, connection.getMinimumBalanceForRentExemption(dataSize)];
|
|
126
|
+
});
|
|
127
|
+
}); })];
|
|
128
|
+
case 2:
|
|
129
|
+
rentExemption = _a.sent();
|
|
130
|
+
this.rentExemptionCache.set(dataSize, { value: rentExemption, timestamp: now });
|
|
131
|
+
return [2 /*return*/, rentExemption];
|
|
132
|
+
case 3:
|
|
133
|
+
e_1 = _a.sent();
|
|
134
|
+
console.warn('[solana][getMinimumBalanceForRentExemption] Failed, using estimate:', e_1);
|
|
135
|
+
// Fallback calculation: ~6.96 lamports per byte + base overhead
|
|
136
|
+
// This is approximate and may not be accurate
|
|
137
|
+
return [2 /*return*/, Math.ceil(dataSize * 6.96 + 128 * 6.96)];
|
|
138
|
+
case 4: return [2 /*return*/];
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
// Simulate a transaction to get actual compute units consumed
|
|
144
|
+
SolanaProtocol.prototype.simulateTransaction = function (transaction) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
146
|
+
var result, e_2;
|
|
147
|
+
var _this = this;
|
|
148
|
+
return __generator(this, function (_a) {
|
|
149
|
+
switch (_a.label) {
|
|
150
|
+
case 0:
|
|
151
|
+
_a.trys.push([0, 2, , 3]);
|
|
152
|
+
return [4 /*yield*/, this.withFallback(function (connection) { return __awaiter(_this, void 0, void 0, function () {
|
|
153
|
+
var blockhash;
|
|
154
|
+
return __generator(this, function (_a) {
|
|
155
|
+
switch (_a.label) {
|
|
156
|
+
case 0:
|
|
157
|
+
if (!!transaction.recentBlockhash) return [3 /*break*/, 2];
|
|
158
|
+
return [4 /*yield*/, connection.getLatestBlockhash()];
|
|
159
|
+
case 1:
|
|
160
|
+
blockhash = (_a.sent()).blockhash;
|
|
161
|
+
transaction.recentBlockhash = blockhash;
|
|
162
|
+
_a.label = 2;
|
|
163
|
+
case 2:
|
|
164
|
+
// For legacy Transaction, use the simple overload without config
|
|
165
|
+
// Pass undefined for signers to skip signature verification
|
|
166
|
+
return [2 /*return*/, connection.simulateTransaction(transaction)];
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}); })];
|
|
170
|
+
case 1:
|
|
171
|
+
result = _a.sent();
|
|
172
|
+
if (result.value.err) {
|
|
173
|
+
return [2 /*return*/, {
|
|
174
|
+
success: false,
|
|
175
|
+
unitsConsumed: 0,
|
|
176
|
+
error: JSON.stringify(result.value.err)
|
|
177
|
+
}];
|
|
178
|
+
}
|
|
179
|
+
return [2 /*return*/, {
|
|
180
|
+
success: true,
|
|
181
|
+
unitsConsumed: result.value.unitsConsumed || 0
|
|
182
|
+
}];
|
|
183
|
+
case 2:
|
|
184
|
+
e_2 = _a.sent();
|
|
185
|
+
console.warn('[solana][simulateTransaction] Simulation failed:', e_2);
|
|
186
|
+
return [2 /*return*/, {
|
|
187
|
+
success: false,
|
|
188
|
+
unitsConsumed: 0,
|
|
189
|
+
error: String(e_2)
|
|
190
|
+
}];
|
|
191
|
+
case 3: return [2 /*return*/];
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
};
|
|
103
196
|
// Helper for RPC calls with fallback to backup endpoints
|
|
104
197
|
SolanaProtocol.prototype.withFallback = function (fn, maxRetries) {
|
|
105
198
|
var _a, _b, _c, _d, _e;
|
|
@@ -116,7 +209,7 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
116
209
|
if (!(_i < allUrls_1.length)) return [3 /*break*/, 6];
|
|
117
210
|
rpcUrl = allUrls_1[_i];
|
|
118
211
|
_loop_1 = function (retry) {
|
|
119
|
-
var connection, _g,
|
|
212
|
+
var connection, _g, e_3, isTemporaryError;
|
|
120
213
|
return __generator(this, function (_h) {
|
|
121
214
|
switch (_h.label) {
|
|
122
215
|
case 0:
|
|
@@ -126,13 +219,13 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
126
219
|
return [4 /*yield*/, fn(connection)];
|
|
127
220
|
case 1: return [2 /*return*/, (_g.value = _h.sent(), _g)];
|
|
128
221
|
case 2:
|
|
129
|
-
|
|
130
|
-
lastError =
|
|
131
|
-
isTemporaryError = ((_a =
|
|
132
|
-
((_b =
|
|
133
|
-
((_c =
|
|
134
|
-
((_d =
|
|
135
|
-
((_e =
|
|
222
|
+
e_3 = _h.sent();
|
|
223
|
+
lastError = e_3;
|
|
224
|
+
isTemporaryError = ((_a = e_3 === null || e_3 === void 0 ? void 0 : e_3.message) === null || _a === void 0 ? void 0 : _a.includes('500')) ||
|
|
225
|
+
((_b = e_3 === null || e_3 === void 0 ? void 0 : e_3.message) === null || _b === void 0 ? void 0 : _b.includes('502')) ||
|
|
226
|
+
((_c = e_3 === null || e_3 === void 0 ? void 0 : e_3.message) === null || _c === void 0 ? void 0 : _c.includes('503')) ||
|
|
227
|
+
((_d = e_3 === null || e_3 === void 0 ? void 0 : e_3.message) === null || _d === void 0 ? void 0 : _d.includes('code":19')) ||
|
|
228
|
+
((_e = e_3 === null || e_3 === void 0 ? void 0 : e_3.message) === null || _e === void 0 ? void 0 : _e.includes('Temporary'));
|
|
136
229
|
if (!isTemporaryError) {
|
|
137
230
|
return [2 /*return*/, "break"];
|
|
138
231
|
}
|
|
@@ -169,6 +262,95 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
169
262
|
});
|
|
170
263
|
});
|
|
171
264
|
};
|
|
265
|
+
// Get recent priority fees from the network
|
|
266
|
+
// Returns percentile-based estimates for different priority levels
|
|
267
|
+
SolanaProtocol.prototype.getRecentPriorityFees = function () {
|
|
268
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
269
|
+
var now, recentFees, allFeeValues, hasNonZeroFees, feeValues, getPercentile, estimate, e_4;
|
|
270
|
+
var _this = this;
|
|
271
|
+
return __generator(this, function (_a) {
|
|
272
|
+
switch (_a.label) {
|
|
273
|
+
case 0:
|
|
274
|
+
now = Date.now();
|
|
275
|
+
// Use cached value if available
|
|
276
|
+
if (this.priorityFeeCache.data && (now - this.priorityFeeCache.timestamp) < SolanaProtocol.PRIORITY_FEE_CACHE_TTL) {
|
|
277
|
+
return [2 /*return*/, this.priorityFeeCache.data];
|
|
278
|
+
}
|
|
279
|
+
_a.label = 1;
|
|
280
|
+
case 1:
|
|
281
|
+
_a.trys.push([1, 3, , 4]);
|
|
282
|
+
return [4 /*yield*/, this.withFallback(function (connection) { return __awaiter(_this, void 0, void 0, function () {
|
|
283
|
+
return __generator(this, function (_a) {
|
|
284
|
+
// Get recent prioritization fees
|
|
285
|
+
// This returns fees from recent slots (typically last 150 slots)
|
|
286
|
+
return [2 /*return*/, connection.getRecentPrioritizationFees()];
|
|
287
|
+
});
|
|
288
|
+
}); })];
|
|
289
|
+
case 2:
|
|
290
|
+
recentFees = _a.sent();
|
|
291
|
+
if (!recentFees || recentFees.length === 0) {
|
|
292
|
+
// No recent fees data, return defaults
|
|
293
|
+
return [2 /*return*/, this.getDefaultPriorityFees()];
|
|
294
|
+
}
|
|
295
|
+
allFeeValues = recentFees.map(function (f) { return f.prioritizationFee; });
|
|
296
|
+
hasNonZeroFees = allFeeValues.some(function (f) { return f > 0; });
|
|
297
|
+
if (!hasNonZeroFees) {
|
|
298
|
+
// Network is idle, return zeros (no priority fee needed for fast confirmation)
|
|
299
|
+
return [2 /*return*/, {
|
|
300
|
+
none: 0,
|
|
301
|
+
low: 0,
|
|
302
|
+
medium: 0,
|
|
303
|
+
high: 0,
|
|
304
|
+
veryHigh: 0
|
|
305
|
+
}];
|
|
306
|
+
}
|
|
307
|
+
feeValues = allFeeValues
|
|
308
|
+
.filter(function (f) { return f > 0; })
|
|
309
|
+
.sort(function (a, b) { return a - b; });
|
|
310
|
+
if (feeValues.length === 0) {
|
|
311
|
+
// Shouldn't reach here due to hasNonZeroFees check, but just in case
|
|
312
|
+
return [2 /*return*/, this.getDefaultPriorityFees()];
|
|
313
|
+
}
|
|
314
|
+
getPercentile = function (arr, p) {
|
|
315
|
+
var index = Math.ceil((p / 100) * arr.length) - 1;
|
|
316
|
+
return arr[Math.max(0, Math.min(index, arr.length - 1))];
|
|
317
|
+
};
|
|
318
|
+
estimate = {
|
|
319
|
+
none: 0,
|
|
320
|
+
low: getPercentile(feeValues, 25),
|
|
321
|
+
medium: getPercentile(feeValues, 50),
|
|
322
|
+
high: getPercentile(feeValues, 75),
|
|
323
|
+
veryHigh: getPercentile(feeValues, 90)
|
|
324
|
+
};
|
|
325
|
+
// Cache the result
|
|
326
|
+
this.priorityFeeCache = { data: estimate, timestamp: now };
|
|
327
|
+
return [2 /*return*/, estimate];
|
|
328
|
+
case 3:
|
|
329
|
+
e_4 = _a.sent();
|
|
330
|
+
console.warn('[solana][getRecentPriorityFees] Failed to get priority fees:', e_4);
|
|
331
|
+
return [2 /*return*/, this.getDefaultPriorityFees()];
|
|
332
|
+
case 4: return [2 /*return*/];
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
// Default priority fees when network data is unavailable
|
|
338
|
+
SolanaProtocol.prototype.getDefaultPriorityFees = function () {
|
|
339
|
+
return {
|
|
340
|
+
none: 0,
|
|
341
|
+
low: 1000,
|
|
342
|
+
medium: 10000,
|
|
343
|
+
high: 100000,
|
|
344
|
+
veryHigh: 1000000 // 1000000 micro-lamports per CU
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
// Calculate total fee including priority fee
|
|
348
|
+
// priorityFeePerCU is in micro-lamports (1 lamport = 1,000,000 micro-lamports)
|
|
349
|
+
SolanaProtocol.prototype.calculateTotalFee = function (baseFee, priorityFeePerCU, computeUnits) {
|
|
350
|
+
// Priority fee = (computeUnits * priorityFeePerCU) / 1,000,000
|
|
351
|
+
var priorityFeeLamports = Math.ceil((computeUnits * priorityFeePerCU) / 1000000);
|
|
352
|
+
return baseFee + priorityFeeLamports;
|
|
353
|
+
};
|
|
172
354
|
SolanaProtocol.prototype.getMetadata = function () {
|
|
173
355
|
return __awaiter(this, void 0, void 0, function () {
|
|
174
356
|
return __generator(this, function (_a) {
|
|
@@ -258,7 +440,7 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
258
440
|
};
|
|
259
441
|
SolanaProtocol.prototype.getBalanceOfAddress = function (address) {
|
|
260
442
|
return __awaiter(this, void 0, void 0, function () {
|
|
261
|
-
var pubKey, balance,
|
|
443
|
+
var pubKey, balance, e_5;
|
|
262
444
|
var _this = this;
|
|
263
445
|
return __generator(this, function (_a) {
|
|
264
446
|
switch (_a.label) {
|
|
@@ -278,8 +460,8 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
278
460
|
total: (0, module_kit_1.newAmount)(balance, 'Lamports')
|
|
279
461
|
}];
|
|
280
462
|
case 3:
|
|
281
|
-
|
|
282
|
-
console.error('[solana][balance][error]',
|
|
463
|
+
e_5 = _a.sent();
|
|
464
|
+
console.error('[solana][balance][error]', e_5);
|
|
283
465
|
return [2 /*return*/, { total: (0, module_kit_1.newAmount)(0, 'Lamports') }];
|
|
284
466
|
case 4: return [2 /*return*/];
|
|
285
467
|
}
|
|
@@ -302,7 +484,7 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
302
484
|
SolanaProtocol.prototype.getDetailsFromTransaction = function (transaction, publicKey) {
|
|
303
485
|
var _a;
|
|
304
486
|
return __awaiter(this, void 0, void 0, function () {
|
|
305
|
-
var tx, fallbackFeePayer, _b, _c, _d, feePayer, firstIx, decoded, amountLamports, fromAddress, toAddress, fee, connection, feeInfo,
|
|
487
|
+
var tx, fallbackFeePayer, _b, _c, _d, feePayer, firstIx, decoded, amountLamports, fromAddress, toAddress, fee, connection, feeInfo, e_6, e_7, fallbackTx;
|
|
306
488
|
return __generator(this, function (_e) {
|
|
307
489
|
switch (_e.label) {
|
|
308
490
|
case 0:
|
|
@@ -342,7 +524,7 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
342
524
|
fee = (0, module_kit_1.newAmount)((_a = feeInfo === null || feeInfo === void 0 ? void 0 : feeInfo.value) !== null && _a !== void 0 ? _a : 5000, 'Lamports');
|
|
343
525
|
return [3 /*break*/, 7];
|
|
344
526
|
case 6:
|
|
345
|
-
|
|
527
|
+
e_6 = _e.sent();
|
|
346
528
|
// Network unavailable (e.g., offline vault), use default fee
|
|
347
529
|
console.warn('[solana][getDetailsFromTransaction] Network unavailable, using default fee');
|
|
348
530
|
return [3 /*break*/, 7];
|
|
@@ -357,8 +539,8 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
357
539
|
}
|
|
358
540
|
]];
|
|
359
541
|
case 8:
|
|
360
|
-
|
|
361
|
-
console.error('[solana][getDetailsFromTransaction] Failed to parse transaction:',
|
|
542
|
+
e_7 = _e.sent();
|
|
543
|
+
console.error('[solana][getDetailsFromTransaction] Failed to parse transaction:', e_7);
|
|
362
544
|
fallbackTx = {
|
|
363
545
|
from: [],
|
|
364
546
|
to: [],
|
|
@@ -512,14 +694,14 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
512
694
|
});
|
|
513
695
|
};
|
|
514
696
|
SolanaProtocol.prototype.getTransactionsForAddress = function (address, limit, cursor) {
|
|
515
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
697
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
516
698
|
return __awaiter(this, void 0, void 0, function () {
|
|
517
|
-
var effectiveLimit, queryOptions_1, signatures, txs, _loop_2, this_1, _i, signatures_1, sigInfo, hasNext, lastSignature, newCursor,
|
|
699
|
+
var effectiveLimit, queryOptions_1, signatures, txs, _loop_2, this_1, _i, signatures_1, sigInfo, hasNext, lastSignature, newCursor, e_8;
|
|
518
700
|
var _this = this;
|
|
519
|
-
return __generator(this, function (
|
|
520
|
-
switch (
|
|
701
|
+
return __generator(this, function (_1) {
|
|
702
|
+
switch (_1.label) {
|
|
521
703
|
case 0:
|
|
522
|
-
|
|
704
|
+
_1.trys.push([0, 6, , 7]);
|
|
523
705
|
effectiveLimit = limit || SolanaProtocol.DEFAULT_TX_LIMIT;
|
|
524
706
|
queryOptions_1 = {
|
|
525
707
|
limit: effectiveLimit
|
|
@@ -534,19 +716,19 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
534
716
|
});
|
|
535
717
|
}); })];
|
|
536
718
|
case 1:
|
|
537
|
-
signatures =
|
|
719
|
+
signatures = _1.sent();
|
|
538
720
|
txs = [];
|
|
539
721
|
_loop_2 = function (sigInfo) {
|
|
540
|
-
var parsed, amount, fee, from, to, instructions,
|
|
541
|
-
return __generator(this, function (
|
|
542
|
-
switch (
|
|
722
|
+
var parsed, amount, fee, from, to, foundRelevantTransfer, instructions, _2, instructions_1, ix, parsedIx, info, source, destination, accountKeys, preBalances, postBalances, ourBalanceChange, ourAddressIndex, i, pubkeyStr, totalSpent, txFee, sentAmount, i, diff, pubkeyStr, i, diff, pubkeyStr, isInbound, isOutbound, feePayerKey, feePayerStr, blockTime, timestamp, e_9;
|
|
723
|
+
return __generator(this, function (_3) {
|
|
724
|
+
switch (_3.label) {
|
|
543
725
|
case 0:
|
|
544
726
|
if (!sigInfo.signature) {
|
|
545
727
|
return [2 /*return*/, "continue"];
|
|
546
728
|
}
|
|
547
|
-
|
|
729
|
+
_3.label = 1;
|
|
548
730
|
case 1:
|
|
549
|
-
|
|
731
|
+
_3.trys.push([1, 3, , 4]);
|
|
550
732
|
return [4 /*yield*/, this_1.withFallback(function (connection) { return __awaiter(_this, void 0, void 0, function () {
|
|
551
733
|
return __generator(this, function (_a) {
|
|
552
734
|
return [2 /*return*/, connection.getParsedTransaction(sigInfo.signature, {
|
|
@@ -556,7 +738,7 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
556
738
|
});
|
|
557
739
|
}); })];
|
|
558
740
|
case 2:
|
|
559
|
-
parsed =
|
|
741
|
+
parsed = _3.sent();
|
|
560
742
|
if (!parsed) {
|
|
561
743
|
return [2 /*return*/, "continue"];
|
|
562
744
|
}
|
|
@@ -564,50 +746,125 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
564
746
|
fee = (0, module_kit_1.newAmount)((_b = (_a = parsed.meta) === null || _a === void 0 ? void 0 : _a.fee) !== null && _b !== void 0 ? _b : 0, 'Lamports');
|
|
565
747
|
from = [];
|
|
566
748
|
to = [];
|
|
749
|
+
foundRelevantTransfer = false;
|
|
567
750
|
instructions = ((_d = (_c = parsed.transaction) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.instructions) || [];
|
|
568
|
-
for (
|
|
569
|
-
ix = instructions_1[
|
|
751
|
+
for (_2 = 0, instructions_1 = instructions; _2 < instructions_1.length; _2++) {
|
|
752
|
+
ix = instructions_1[_2];
|
|
570
753
|
// Check if it's a parsed instruction (has 'parsed' property)
|
|
571
754
|
if ('parsed' in ix && ix.parsed) {
|
|
572
755
|
parsedIx = ix;
|
|
573
756
|
if (parsedIx.program === 'system' && ((_e = parsedIx.parsed) === null || _e === void 0 ? void 0 : _e.type) === 'transfer') {
|
|
574
757
|
info = parsedIx.parsed.info;
|
|
575
758
|
if (info) {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
759
|
+
source = info.source || '';
|
|
760
|
+
destination = info.destination || '';
|
|
761
|
+
// Only include transfers that involve our address
|
|
762
|
+
if (source === address || destination === address) {
|
|
763
|
+
foundRelevantTransfer = true;
|
|
764
|
+
amount = (0, module_kit_1.newAmount)(((_f = info.lamports) === null || _f === void 0 ? void 0 : _f.toString()) || '0', 'Lamports');
|
|
765
|
+
from = source ? [source] : [];
|
|
766
|
+
to = destination ? [destination] : [];
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
580
769
|
}
|
|
581
770
|
}
|
|
582
771
|
}
|
|
583
772
|
}
|
|
584
773
|
// Fallback: try to extract from preBalances/postBalances if transfer info not found
|
|
585
|
-
if (
|
|
774
|
+
if (!foundRelevantTransfer && parsed.meta) {
|
|
586
775
|
accountKeys = ((_h = (_g = parsed.transaction) === null || _g === void 0 ? void 0 : _g.message) === null || _h === void 0 ? void 0 : _h.accountKeys) || [];
|
|
587
776
|
preBalances = parsed.meta.preBalances || [];
|
|
588
777
|
postBalances = parsed.meta.postBalances || [];
|
|
778
|
+
ourBalanceChange = 0;
|
|
779
|
+
ourAddressIndex = -1;
|
|
589
780
|
for (i = 0; i < accountKeys.length; i++) {
|
|
590
781
|
pubkeyStr = typeof accountKeys[i] === 'string'
|
|
591
782
|
? accountKeys[i]
|
|
592
|
-
: ((_j = accountKeys[i].pubkey) === null || _j === void 0 ? void 0 : _j.toString()) || accountKeys[i].toString();
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
783
|
+
: ((_k = (_j = accountKeys[i].pubkey) === null || _j === void 0 ? void 0 : _j.toBase58) === null || _k === void 0 ? void 0 : _k.call(_j)) || ((_l = accountKeys[i].pubkey) === null || _l === void 0 ? void 0 : _l.toString()) || accountKeys[i].toString();
|
|
784
|
+
if (pubkeyStr === address) {
|
|
785
|
+
ourAddressIndex = i;
|
|
786
|
+
ourBalanceChange = (postBalances[i] || 0) - (preBalances[i] || 0);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
// If our SOL balance didn't change, this transaction is not relevant for SOL history
|
|
790
|
+
// (e.g., we're just an ATA owner in someone else's token transfer)
|
|
791
|
+
if (ourAddressIndex >= 0 && ourBalanceChange === 0) {
|
|
792
|
+
return [2 /*return*/, "continue"];
|
|
793
|
+
}
|
|
794
|
+
// Only consider this transaction relevant if our balance actually changed
|
|
795
|
+
if (ourAddressIndex >= 0 && ourBalanceChange !== 0) {
|
|
796
|
+
foundRelevantTransfer = true;
|
|
797
|
+
if (ourBalanceChange < 0) {
|
|
798
|
+
totalSpent = Math.abs(ourBalanceChange);
|
|
799
|
+
txFee = ((_m = parsed.meta) === null || _m === void 0 ? void 0 : _m.fee) || 0;
|
|
800
|
+
sentAmount = totalSpent - txFee;
|
|
801
|
+
// We are the sender
|
|
802
|
+
from = [address];
|
|
803
|
+
if (sentAmount > 0) {
|
|
804
|
+
// There was an actual SOL transfer beyond the fee
|
|
805
|
+
amount = (0, module_kit_1.newAmount)(sentAmount.toString(), 'Lamports');
|
|
806
|
+
// Find who received the SOL
|
|
807
|
+
for (i = 0; i < accountKeys.length; i++) {
|
|
808
|
+
if (i === ourAddressIndex)
|
|
809
|
+
continue;
|
|
810
|
+
diff = (postBalances[i] || 0) - (preBalances[i] || 0);
|
|
811
|
+
if (diff > 0) {
|
|
812
|
+
pubkeyStr = typeof accountKeys[i] === 'string'
|
|
813
|
+
? accountKeys[i]
|
|
814
|
+
: ((_p = (_o = accountKeys[i].pubkey) === null || _o === void 0 ? void 0 : _o.toBase58) === null || _p === void 0 ? void 0 : _p.call(_o)) || ((_q = accountKeys[i].pubkey) === null || _q === void 0 ? void 0 : _q.toString()) || accountKeys[i].toString();
|
|
815
|
+
to.push(pubkeyStr);
|
|
816
|
+
}
|
|
601
817
|
}
|
|
602
818
|
}
|
|
819
|
+
else {
|
|
820
|
+
// Only fee was spent (e.g., token transfer, ATA creation)
|
|
821
|
+
// Show the transaction with amount = total spent (including fee)
|
|
822
|
+
amount = (0, module_kit_1.newAmount)(totalSpent.toString(), 'Lamports');
|
|
823
|
+
// No specific recipient for fee-only transactions
|
|
824
|
+
}
|
|
603
825
|
}
|
|
604
|
-
else
|
|
605
|
-
//
|
|
606
|
-
|
|
826
|
+
else {
|
|
827
|
+
// We received SOL (ourBalanceChange > 0)
|
|
828
|
+
amount = (0, module_kit_1.newAmount)(ourBalanceChange.toString(), 'Lamports');
|
|
829
|
+
to = [address];
|
|
830
|
+
// Find who sent us the SOL
|
|
831
|
+
for (i = 0; i < accountKeys.length; i++) {
|
|
832
|
+
if (i === ourAddressIndex)
|
|
833
|
+
continue;
|
|
834
|
+
diff = (postBalances[i] || 0) - (preBalances[i] || 0);
|
|
835
|
+
if (diff < 0) {
|
|
836
|
+
pubkeyStr = typeof accountKeys[i] === 'string'
|
|
837
|
+
? accountKeys[i]
|
|
838
|
+
: ((_s = (_r = accountKeys[i].pubkey) === null || _r === void 0 ? void 0 : _r.toBase58) === null || _s === void 0 ? void 0 : _s.call(_r)) || ((_t = accountKeys[i].pubkey) === null || _t === void 0 ? void 0 : _t.toString()) || accountKeys[i].toString();
|
|
839
|
+
from.push(pubkeyStr);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
607
842
|
}
|
|
608
843
|
}
|
|
609
844
|
}
|
|
610
|
-
|
|
845
|
+
// Skip transactions that don't involve our address in a meaningful way
|
|
846
|
+
if (!foundRelevantTransfer) {
|
|
847
|
+
return [2 /*return*/, "continue"];
|
|
848
|
+
}
|
|
849
|
+
isInbound = to.includes(address);
|
|
850
|
+
isOutbound = from.includes(address);
|
|
851
|
+
// If neither contains our address, add it based on fee payment
|
|
852
|
+
// (fee payer is always in the transaction, so this ensures visibility)
|
|
853
|
+
if (!isInbound && !isOutbound) {
|
|
854
|
+
feePayerKey = (_w = (_v = (_u = parsed.transaction) === null || _u === void 0 ? void 0 : _u.message) === null || _v === void 0 ? void 0 : _v.accountKeys) === null || _w === void 0 ? void 0 : _w[0];
|
|
855
|
+
feePayerStr = typeof feePayerKey === 'string'
|
|
856
|
+
? feePayerKey
|
|
857
|
+
: ((_y = (_x = feePayerKey === null || feePayerKey === void 0 ? void 0 : feePayerKey.pubkey) === null || _x === void 0 ? void 0 : _x.toBase58) === null || _y === void 0 ? void 0 : _y.call(_x)) || ((_z = feePayerKey === null || feePayerKey === void 0 ? void 0 : feePayerKey.pubkey) === null || _z === void 0 ? void 0 : _z.toString()) || (feePayerKey === null || feePayerKey === void 0 ? void 0 : feePayerKey.toString());
|
|
858
|
+
if (feePayerStr === address) {
|
|
859
|
+
from.push(address);
|
|
860
|
+
}
|
|
861
|
+
else {
|
|
862
|
+
// Transaction involves our address somehow, keep it visible
|
|
863
|
+
// This handles edge cases where address format doesn't match
|
|
864
|
+
from.push(address);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
blockTime = (_0 = sigInfo.blockTime) !== null && _0 !== void 0 ? _0 : parsed.blockTime;
|
|
611
868
|
timestamp = blockTime ? blockTime : Math.floor(Date.now() / 1000);
|
|
612
869
|
txs.push({
|
|
613
870
|
hash: sigInfo.signature,
|
|
@@ -617,12 +874,12 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
617
874
|
fee: fee,
|
|
618
875
|
from: from,
|
|
619
876
|
to: to,
|
|
620
|
-
isInbound:
|
|
877
|
+
isInbound: isInbound,
|
|
621
878
|
network: this_1.options.network
|
|
622
879
|
});
|
|
623
880
|
return [3 /*break*/, 4];
|
|
624
881
|
case 3:
|
|
625
|
-
|
|
882
|
+
e_9 = _3.sent();
|
|
626
883
|
console.warn('[solana][getTransactionsForAddress] Failed to parse transaction:', sigInfo.signature);
|
|
627
884
|
return [3 /*break*/, 4];
|
|
628
885
|
case 4: return [2 /*return*/];
|
|
@@ -631,19 +888,19 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
631
888
|
};
|
|
632
889
|
this_1 = this;
|
|
633
890
|
_i = 0, signatures_1 = signatures;
|
|
634
|
-
|
|
891
|
+
_1.label = 2;
|
|
635
892
|
case 2:
|
|
636
893
|
if (!(_i < signatures_1.length)) return [3 /*break*/, 5];
|
|
637
894
|
sigInfo = signatures_1[_i];
|
|
638
895
|
return [5 /*yield**/, _loop_2(sigInfo)];
|
|
639
896
|
case 3:
|
|
640
|
-
|
|
641
|
-
|
|
897
|
+
_1.sent();
|
|
898
|
+
_1.label = 4;
|
|
642
899
|
case 4:
|
|
643
900
|
_i++;
|
|
644
901
|
return [3 /*break*/, 2];
|
|
645
902
|
case 5:
|
|
646
|
-
hasNext = signatures.length
|
|
903
|
+
hasNext = signatures.length > 0;
|
|
647
904
|
lastSignature = signatures.length > 0 ? signatures[signatures.length - 1].signature : undefined;
|
|
648
905
|
newCursor = {
|
|
649
906
|
hasNext: hasNext,
|
|
@@ -654,8 +911,8 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
654
911
|
cursor: newCursor
|
|
655
912
|
}];
|
|
656
913
|
case 6:
|
|
657
|
-
|
|
658
|
-
console.error('[solana][getTransactionsForAddress] Failed:',
|
|
914
|
+
e_8 = _1.sent();
|
|
915
|
+
console.error('[solana][getTransactionsForAddress] Failed:', e_8);
|
|
659
916
|
return [2 /*return*/, {
|
|
660
917
|
transactions: [],
|
|
661
918
|
cursor: { hasNext: false }
|
|
@@ -728,7 +985,7 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
728
985
|
};
|
|
729
986
|
SolanaProtocol.prototype.getTransactionFeeWithPublicKey = function (publicKey, details, configuration) {
|
|
730
987
|
return __awaiter(this, void 0, void 0, function () {
|
|
731
|
-
var fromAddress, fromPubkey, transaction, _i, details_1, detail,
|
|
988
|
+
var fromAddress, fromPubkey, transaction, _i, details_1, detail, baseFee, feeResult, e_10, computeUnits, simulation, e_11, priorityFees, lowFee, mediumFee, highFee;
|
|
732
989
|
var _this = this;
|
|
733
990
|
return __generator(this, function (_a) {
|
|
734
991
|
switch (_a.label) {
|
|
@@ -746,28 +1003,67 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
746
1003
|
}));
|
|
747
1004
|
}
|
|
748
1005
|
transaction.feePayer = fromPubkey;
|
|
1006
|
+
baseFee = SolanaProtocol.DEFAULT_BASE_FEE_LAMPORTS;
|
|
1007
|
+
_a.label = 2;
|
|
1008
|
+
case 2:
|
|
1009
|
+
_a.trys.push([2, 4, , 5]);
|
|
749
1010
|
return [4 /*yield*/, this.withFallback(function (connection) { return __awaiter(_this, void 0, void 0, function () {
|
|
750
|
-
var
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
switch (_b.label) {
|
|
1011
|
+
var blockhash, feeForMessage;
|
|
1012
|
+
return __generator(this, function (_a) {
|
|
1013
|
+
switch (_a.label) {
|
|
754
1014
|
case 0: return [4 /*yield*/, connection.getLatestBlockhash()];
|
|
755
1015
|
case 1:
|
|
756
|
-
|
|
757
|
-
transaction.recentBlockhash =
|
|
1016
|
+
blockhash = (_a.sent()).blockhash;
|
|
1017
|
+
transaction.recentBlockhash = blockhash;
|
|
758
1018
|
return [4 /*yield*/, connection.getFeeForMessage(transaction.compileMessage())];
|
|
759
1019
|
case 2:
|
|
760
|
-
feeForMessage =
|
|
761
|
-
return [2 /*return*/,
|
|
1020
|
+
feeForMessage = _a.sent();
|
|
1021
|
+
return [2 /*return*/, feeForMessage === null || feeForMessage === void 0 ? void 0 : feeForMessage.value];
|
|
762
1022
|
}
|
|
763
1023
|
});
|
|
764
|
-
}); })
|
|
765
|
-
case
|
|
766
|
-
|
|
1024
|
+
}); })];
|
|
1025
|
+
case 3:
|
|
1026
|
+
feeResult = _a.sent();
|
|
1027
|
+
if (feeResult && feeResult > 0) {
|
|
1028
|
+
baseFee = feeResult;
|
|
1029
|
+
}
|
|
1030
|
+
return [3 /*break*/, 5];
|
|
1031
|
+
case 4:
|
|
1032
|
+
e_10 = _a.sent();
|
|
1033
|
+
console.warn('[solana][getTransactionFeeWithPublicKey] Failed to get base fee from network:', e_10);
|
|
1034
|
+
return [3 /*break*/, 5];
|
|
1035
|
+
case 5:
|
|
1036
|
+
computeUnits = details.length * SolanaProtocol.DEFAULT_SOL_TRANSFER_CU // Fallback
|
|
1037
|
+
;
|
|
1038
|
+
_a.label = 6;
|
|
1039
|
+
case 6:
|
|
1040
|
+
_a.trys.push([6, 8, , 9]);
|
|
1041
|
+
return [4 /*yield*/, this.simulateTransaction(transaction)];
|
|
1042
|
+
case 7:
|
|
1043
|
+
simulation = _a.sent();
|
|
1044
|
+
if (simulation.success && simulation.unitsConsumed > 0) {
|
|
1045
|
+
computeUnits = simulation.unitsConsumed;
|
|
1046
|
+
}
|
|
1047
|
+
return [3 /*break*/, 9];
|
|
1048
|
+
case 8:
|
|
1049
|
+
e_11 = _a.sent();
|
|
1050
|
+
console.warn('[solana][getTransactionFeeWithPublicKey] Simulation failed, using default CU:', e_11);
|
|
1051
|
+
return [3 /*break*/, 9];
|
|
1052
|
+
case 9: return [4 /*yield*/, this.getRecentPriorityFees()
|
|
1053
|
+
// Calculate total fees for each tier
|
|
1054
|
+
// low: base fee only (no priority fee) - may be slow during congestion
|
|
1055
|
+
// medium: base fee + median priority fee - reasonable confirmation time
|
|
1056
|
+
// high: base fee + 75th percentile priority fee - fast confirmation
|
|
1057
|
+
];
|
|
1058
|
+
case 10:
|
|
1059
|
+
priorityFees = _a.sent();
|
|
1060
|
+
lowFee = baseFee;
|
|
1061
|
+
mediumFee = this.calculateTotalFee(baseFee, priorityFees.medium, computeUnits);
|
|
1062
|
+
highFee = this.calculateTotalFee(baseFee, priorityFees.high, computeUnits);
|
|
767
1063
|
return [2 /*return*/, {
|
|
768
|
-
low: (0, module_kit_1.newAmount)(
|
|
769
|
-
medium: (0, module_kit_1.newAmount)(
|
|
770
|
-
high: (0, module_kit_1.newAmount)(
|
|
1064
|
+
low: (0, module_kit_1.newAmount)(lowFee, 'Lamports'),
|
|
1065
|
+
medium: (0, module_kit_1.newAmount)(mediumFee, 'Lamports'),
|
|
1066
|
+
high: (0, module_kit_1.newAmount)(highFee, 'Lamports')
|
|
771
1067
|
}];
|
|
772
1068
|
}
|
|
773
1069
|
});
|
|
@@ -847,6 +1143,13 @@ var SolanaProtocol = /** @class */ (function () {
|
|
|
847
1143
|
SolanaProtocol.FALLBACK_RPC_URLS = [
|
|
848
1144
|
'https://solana.drpc.org'
|
|
849
1145
|
];
|
|
1146
|
+
// Default fee constants (fallback when network queries fail)
|
|
1147
|
+
// These are only used as fallbacks - actual values are fetched from network
|
|
1148
|
+
SolanaProtocol.DEFAULT_BASE_FEE_LAMPORTS = 5000;
|
|
1149
|
+
SolanaProtocol.DEFAULT_SOL_TRANSFER_CU = 450; // Fallback CU for SOL transfer
|
|
1150
|
+
// Cache configuration
|
|
1151
|
+
SolanaProtocol.PRIORITY_FEE_CACHE_TTL = 30000; // 30 seconds
|
|
1152
|
+
SolanaProtocol.RENT_EXEMPTION_CACHE_TTL = 300000; // 5 minutes (rarely changes)
|
|
850
1153
|
// Default number of transactions to fetch per page
|
|
851
1154
|
SolanaProtocol.DEFAULT_TX_LIMIT = 10;
|
|
852
1155
|
return SolanaProtocol;
|