@pioneer-platform/pioneer-sdk 8.15.40 → 8.15.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +156 -10
- package/dist/index.es.js +156 -10
- package/dist/index.js +156 -10
- package/package.json +6 -6
- package/src/index.ts +240 -10
- package/src/utils/portfolio-helpers.ts +2 -2
package/dist/index.cjs
CHANGED
|
@@ -4264,8 +4264,8 @@ var EXPLORER_BASE_URLS = {
|
|
|
4264
4264
|
tx: "https://blockchair.com/bitcoin-cash/transaction/"
|
|
4265
4265
|
},
|
|
4266
4266
|
"bip122:000007d91d1254d60e2dd1ae58038307": {
|
|
4267
|
-
address: "https://
|
|
4268
|
-
tx: "https://
|
|
4267
|
+
address: "https://explorer.dash.org/insight/address/",
|
|
4268
|
+
tx: "https://explorer.dash.org/insight/tx/"
|
|
4269
4269
|
},
|
|
4270
4270
|
"bip122:4da631f2ac1bed857bd968c67c913978": {
|
|
4271
4271
|
address: "https://digiexplorer.info/address/",
|
|
@@ -4702,6 +4702,7 @@ class SDK {
|
|
|
4702
4702
|
assetsMap;
|
|
4703
4703
|
dashboard;
|
|
4704
4704
|
nfts;
|
|
4705
|
+
pendingTransactions;
|
|
4705
4706
|
events;
|
|
4706
4707
|
pairWallet;
|
|
4707
4708
|
setContext;
|
|
@@ -4781,6 +4782,7 @@ class SDK {
|
|
|
4781
4782
|
this.nodes = config.nodes || [];
|
|
4782
4783
|
this.charts = ["covalent", "zapper"];
|
|
4783
4784
|
this.nfts = [];
|
|
4785
|
+
this.pendingTransactions = [];
|
|
4784
4786
|
this.isPioneer = null;
|
|
4785
4787
|
this.pioneer = null;
|
|
4786
4788
|
this.context = "";
|
|
@@ -5188,6 +5190,29 @@ class SDK {
|
|
|
5188
5190
|
let txManager = new TransactionManager(transactionDependencies, this.events);
|
|
5189
5191
|
let unsignedTx = await txManager.transfer(sendPayload);
|
|
5190
5192
|
console.log(tag6, "unsignedTx: ", unsignedTx);
|
|
5193
|
+
if (this.assetContext && sendPayload) {
|
|
5194
|
+
this.assetContext.sendAmount = sendPayload.amount;
|
|
5195
|
+
this.assetContext.sendTo = sendPayload.to;
|
|
5196
|
+
this.assetContext.sendMemo = sendPayload.memo;
|
|
5197
|
+
let estimatedFee = "0";
|
|
5198
|
+
if (unsignedTx) {
|
|
5199
|
+
if (unsignedTx.fee) {
|
|
5200
|
+
estimatedFee = typeof unsignedTx.fee === "string" ? unsignedTx.fee : unsignedTx.fee.toString();
|
|
5201
|
+
} else if (unsignedTx.gasPrice && unsignedTx.gasLimit) {
|
|
5202
|
+
const gasPrice = parseFloat(unsignedTx.gasPrice);
|
|
5203
|
+
const gasLimit = parseFloat(unsignedTx.gasLimit);
|
|
5204
|
+
estimatedFee = (gasPrice * gasLimit / 1e9).toFixed(8);
|
|
5205
|
+
} else if (unsignedTx.fee && unsignedTx.fee.amount && Array.isArray(unsignedTx.fee.amount)) {
|
|
5206
|
+
estimatedFee = unsignedTx.fee.amount[0]?.amount || "0";
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5209
|
+
this.assetContext.sendFee = estimatedFee;
|
|
5210
|
+
console.log(tag6, "\uD83D\uDCBE Stored transaction details for optimistic update:", {
|
|
5211
|
+
amount: this.assetContext.sendAmount,
|
|
5212
|
+
fee: this.assetContext.sendFee,
|
|
5213
|
+
to: this.assetContext.sendTo
|
|
5214
|
+
});
|
|
5215
|
+
}
|
|
5191
5216
|
return unsignedTx;
|
|
5192
5217
|
} catch (e) {
|
|
5193
5218
|
console.error(e);
|
|
@@ -5292,12 +5317,101 @@ class SDK {
|
|
|
5292
5317
|
serialized: signedTx
|
|
5293
5318
|
};
|
|
5294
5319
|
let txid = await txManager.broadcast(payload);
|
|
5320
|
+
if (txid && !txid.error) {
|
|
5321
|
+
const amount = this.assetContext?.sendAmount || "0";
|
|
5322
|
+
const fee = this.assetContext?.sendFee || "0";
|
|
5323
|
+
const to = this.assetContext?.sendTo || "";
|
|
5324
|
+
const from = this.pubkeyContext?.address || this.pubkeyContext?.master || "";
|
|
5325
|
+
if (amount !== "0" && parseFloat(amount) > 0) {
|
|
5326
|
+
console.log(tag6, "\uD83D\uDCB0 Performing optimistic balance update:", {
|
|
5327
|
+
caip,
|
|
5328
|
+
amount,
|
|
5329
|
+
fee,
|
|
5330
|
+
from,
|
|
5331
|
+
to
|
|
5332
|
+
});
|
|
5333
|
+
this.debitBalance(caip, amount, fee);
|
|
5334
|
+
this.addPendingTransaction({
|
|
5335
|
+
txid,
|
|
5336
|
+
caip,
|
|
5337
|
+
amount,
|
|
5338
|
+
to,
|
|
5339
|
+
from,
|
|
5340
|
+
fee,
|
|
5341
|
+
broadcastTime: Date.now(),
|
|
5342
|
+
status: "pending"
|
|
5343
|
+
});
|
|
5344
|
+
}
|
|
5345
|
+
}
|
|
5295
5346
|
return txid;
|
|
5296
5347
|
} catch (e) {
|
|
5297
5348
|
console.error(e);
|
|
5298
5349
|
throw e;
|
|
5299
5350
|
}
|
|
5300
5351
|
};
|
|
5352
|
+
this.addPendingTransaction = function(txData) {
|
|
5353
|
+
const tag6 = TAG12 + " | addPendingTransaction | ";
|
|
5354
|
+
console.log(tag6, "Adding pending transaction:", txData);
|
|
5355
|
+
this.pendingTransactions.unshift({
|
|
5356
|
+
...txData,
|
|
5357
|
+
status: txData.status || "pending",
|
|
5358
|
+
addedAt: Date.now()
|
|
5359
|
+
});
|
|
5360
|
+
if (this.pendingTransactions.length > 50) {
|
|
5361
|
+
this.pendingTransactions = this.pendingTransactions.slice(0, 50);
|
|
5362
|
+
}
|
|
5363
|
+
this.events.emit("PENDING_TX_ADDED", txData);
|
|
5364
|
+
this.events.emit("PENDING_TXS_UPDATED", this.pendingTransactions);
|
|
5365
|
+
console.log(tag6, `Pending transactions count: ${this.pendingTransactions.length}`);
|
|
5366
|
+
return txData;
|
|
5367
|
+
};
|
|
5368
|
+
this.debitBalance = function(caip, amount, fee = "0") {
|
|
5369
|
+
const tag6 = TAG12 + " | debitBalance | ";
|
|
5370
|
+
console.log(tag6, "Debiting balance:", { caip, amount, fee });
|
|
5371
|
+
const balanceIndex = this.balances.findIndex((b) => b.caip === caip);
|
|
5372
|
+
if (balanceIndex === -1) {
|
|
5373
|
+
console.warn(tag6, "Balance not found for CAIP:", caip);
|
|
5374
|
+
return null;
|
|
5375
|
+
}
|
|
5376
|
+
const currentBalance = this.balances[balanceIndex];
|
|
5377
|
+
const currentBalanceNum = parseFloat(currentBalance.balance || "0");
|
|
5378
|
+
const amountNum = parseFloat(amount);
|
|
5379
|
+
const feeNum = parseFloat(fee);
|
|
5380
|
+
const totalDebit = amountNum + feeNum;
|
|
5381
|
+
const newBalanceNum = currentBalanceNum - totalDebit;
|
|
5382
|
+
if (newBalanceNum < 0) {
|
|
5383
|
+
console.warn(tag6, "Cannot debit - would result in negative balance:", {
|
|
5384
|
+
current: currentBalanceNum,
|
|
5385
|
+
debit: totalDebit,
|
|
5386
|
+
result: newBalanceNum
|
|
5387
|
+
});
|
|
5388
|
+
return null;
|
|
5389
|
+
}
|
|
5390
|
+
const updatedBalance = {
|
|
5391
|
+
...currentBalance,
|
|
5392
|
+
balance: newBalanceNum.toFixed(8),
|
|
5393
|
+
valueUsd: newBalanceNum * (parseFloat(currentBalance.priceUsd) || 0),
|
|
5394
|
+
updated: Date.now(),
|
|
5395
|
+
optimistic: true,
|
|
5396
|
+
previousBalance: currentBalanceNum
|
|
5397
|
+
};
|
|
5398
|
+
this.balances[balanceIndex] = updatedBalance;
|
|
5399
|
+
console.log(tag6, "✅ Balance updated:", {
|
|
5400
|
+
previous: currentBalanceNum.toFixed(8),
|
|
5401
|
+
new: newBalanceNum.toFixed(8),
|
|
5402
|
+
deducted: totalDebit.toFixed(8)
|
|
5403
|
+
});
|
|
5404
|
+
this.events.emit("BALANCES_UPDATED", this.balances);
|
|
5405
|
+
this.events.emit("SET_BALANCES", this.balances);
|
|
5406
|
+
try {
|
|
5407
|
+
this.dashboard = this.buildDashboardFromBalances();
|
|
5408
|
+
this.events.emit("SET_DASHBOARD", this.dashboard);
|
|
5409
|
+
console.log(tag6, "✅ Dashboard rebuilt with updated balance");
|
|
5410
|
+
} catch (dashboardError) {
|
|
5411
|
+
console.error(tag6, "Error rebuilding dashboard:", dashboardError);
|
|
5412
|
+
}
|
|
5413
|
+
return updatedBalance;
|
|
5414
|
+
};
|
|
5301
5415
|
this.swap = async function(swapPayload) {
|
|
5302
5416
|
let tag6 = `${TAG12} | swap | `;
|
|
5303
5417
|
try {
|
|
@@ -5763,6 +5877,14 @@ class SDK {
|
|
|
5763
5877
|
const assetQuery = [];
|
|
5764
5878
|
for (const networkId of networkIds) {
|
|
5765
5879
|
const pubkeys = findPubkeysForNetwork(this.pubkeys, networkId, this.paths, tag6);
|
|
5880
|
+
console.log(`\uD83D\uDD0D [DIAGNOSTIC] ${networkId}: Found ${pubkeys.length} pubkeys`);
|
|
5881
|
+
if (networkId.startsWith("bip122:000000000019")) {
|
|
5882
|
+
console.log("\uD83D\uDD0D [BITCOIN DIAGNOSTIC] Bitcoin pubkeys:", pubkeys.map((p) => ({
|
|
5883
|
+
pubkey: p.pubkey?.substring(0, 20) + "...",
|
|
5884
|
+
networks: p.networks,
|
|
5885
|
+
symbol: p.symbol
|
|
5886
|
+
})));
|
|
5887
|
+
}
|
|
5766
5888
|
const caip = await import_pioneer_caip8.networkIdToCaip(networkId);
|
|
5767
5889
|
assetQuery.push(...buildAssetQuery(pubkeys, caip));
|
|
5768
5890
|
}
|
|
@@ -5777,7 +5899,18 @@ class SDK {
|
|
|
5777
5899
|
console.log(`⏱️ [PERF] Enriching ${marketInfo.data?.length || 0} balances...`);
|
|
5778
5900
|
const balances = enrichBalancesWithAssetInfo(marketInfo.data, this.assetsMap, import_pioneer_caip8.caipToNetworkId);
|
|
5779
5901
|
console.log(`⏱️ [PERF] Enrichment completed in ${(performance.now() - enrichStart).toFixed(0)}ms`);
|
|
5780
|
-
|
|
5902
|
+
console.log(tag6, `⚙️ Merging balances: ${balances.length} new + ${this.balances.length} existing`);
|
|
5903
|
+
const uniqueBalances = new Map([...this.balances, ...balances].map((balance) => [
|
|
5904
|
+
balance.identifier || `${balance.caip}:${balance.pubkey}`,
|
|
5905
|
+
balance
|
|
5906
|
+
]));
|
|
5907
|
+
const beforeCount = [...this.balances, ...balances].length;
|
|
5908
|
+
this.balances = Array.from(uniqueBalances.values());
|
|
5909
|
+
const duplicatesRemoved = beforeCount - this.balances.length;
|
|
5910
|
+
if (duplicatesRemoved > 0) {
|
|
5911
|
+
console.log(tag6, `\uD83D\uDD27 Removed ${duplicatesRemoved} duplicate balances`);
|
|
5912
|
+
}
|
|
5913
|
+
console.log(tag6, `✅ Final balance count: ${this.balances.length} unique balances`);
|
|
5781
5914
|
this.events.emit("SET_BALANCES", this.balances);
|
|
5782
5915
|
const dashStart = performance.now();
|
|
5783
5916
|
this.dashboard = this.buildDashboardFromBalances();
|
|
@@ -5791,16 +5924,29 @@ class SDK {
|
|
|
5791
5924
|
throw e;
|
|
5792
5925
|
}
|
|
5793
5926
|
};
|
|
5794
|
-
this.getBalances = async function(
|
|
5927
|
+
this.getBalances = async function(forceRefreshOrOptions, caip) {
|
|
5795
5928
|
const tag6 = `${TAG12} | getBalances | `;
|
|
5796
5929
|
try {
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5930
|
+
let forceRefresh = false;
|
|
5931
|
+
let networkId;
|
|
5932
|
+
if (typeof forceRefreshOrOptions === "object") {
|
|
5933
|
+
networkId = forceRefreshOrOptions.networkId;
|
|
5934
|
+
forceRefresh = forceRefreshOrOptions.forceRefresh ?? false;
|
|
5935
|
+
console.log(tag6, `\uD83D\uDCCD New signature - networkId: ${networkId}, forceRefresh: ${forceRefresh}`);
|
|
5936
|
+
} else {
|
|
5937
|
+
forceRefresh = forceRefreshOrOptions ?? false;
|
|
5938
|
+
if (caip) {
|
|
5939
|
+
console.log(tag6, `\uD83C\uDFAF Old signature - Refreshing single asset: ${caip}`);
|
|
5940
|
+
networkId = caip.split("/")[0];
|
|
5941
|
+
console.log(tag6, `\uD83D\uDCCD Extracted networkId: ${networkId}`);
|
|
5942
|
+
}
|
|
5943
|
+
}
|
|
5944
|
+
if (networkId) {
|
|
5945
|
+
console.log(tag6, `\uD83C\uDFAF Refreshing specific network: ${networkId}`);
|
|
5801
5946
|
const results = await this.getBalancesForNetworks([networkId], forceRefresh);
|
|
5802
|
-
return results.filter((b) => b.
|
|
5947
|
+
return results.filter((b) => b.networkId === networkId || b.caip?.startsWith(networkId));
|
|
5803
5948
|
}
|
|
5949
|
+
console.log(tag6, `\uD83C\uDF10 Refreshing all blockchains (${this.blockchains.length} networks)`);
|
|
5804
5950
|
return await this.getBalancesForNetworks(this.blockchains, forceRefresh);
|
|
5805
5951
|
} catch (e) {
|
|
5806
5952
|
console.error(tag6, "Error in getBalances: ", e);
|
|
@@ -5941,7 +6087,7 @@ class SDK {
|
|
|
5941
6087
|
"bip122:12a765e31ffd4059bada1e25190f6e98": { address: "https://blockchair.com/litecoin/address/", tx: "https://blockchair.com/litecoin/transaction/" },
|
|
5942
6088
|
"bip122:00000000001a91e3dace36e2be3bf030": { address: "https://dogechain.info/address/", tx: "https://dogechain.info/tx/" },
|
|
5943
6089
|
"bip122:000000000000000000651ef99cb9fcbe": { address: "https://blockchair.com/bitcoin-cash/address/", tx: "https://blockchair.com/bitcoin-cash/transaction/" },
|
|
5944
|
-
"bip122:000007d91d1254d60e2dd1ae58038307": { address: "https://
|
|
6090
|
+
"bip122:000007d91d1254d60e2dd1ae58038307": { address: "https://explorer.dash.org/insight/address/", tx: "https://explorer.dash.org/insight/tx/" },
|
|
5945
6091
|
"bip122:4da631f2ac1bed857bd968c67c913978": { address: "https://digiexplorer.info/address/", tx: "https://digiexplorer.info/tx/" },
|
|
5946
6092
|
"bip122:00040fe8ec8471911baa1db1266ea15d": { address: "https://explorer.zcha.in/accounts/", tx: "https://explorer.zcha.in/transactions/" },
|
|
5947
6093
|
"cosmos:cosmoshub-4": { address: "https://www.mintscan.io/cosmos/address/", tx: "https://www.mintscan.io/cosmos/tx/" },
|
package/dist/index.es.js
CHANGED
|
@@ -4448,8 +4448,8 @@ var EXPLORER_BASE_URLS = {
|
|
|
4448
4448
|
tx: "https://blockchair.com/bitcoin-cash/transaction/"
|
|
4449
4449
|
},
|
|
4450
4450
|
"bip122:000007d91d1254d60e2dd1ae58038307": {
|
|
4451
|
-
address: "https://
|
|
4452
|
-
tx: "https://
|
|
4451
|
+
address: "https://explorer.dash.org/insight/address/",
|
|
4452
|
+
tx: "https://explorer.dash.org/insight/tx/"
|
|
4453
4453
|
},
|
|
4454
4454
|
"bip122:4da631f2ac1bed857bd968c67c913978": {
|
|
4455
4455
|
address: "https://digiexplorer.info/address/",
|
|
@@ -4886,6 +4886,7 @@ class SDK {
|
|
|
4886
4886
|
assetsMap;
|
|
4887
4887
|
dashboard;
|
|
4888
4888
|
nfts;
|
|
4889
|
+
pendingTransactions;
|
|
4889
4890
|
events;
|
|
4890
4891
|
pairWallet;
|
|
4891
4892
|
setContext;
|
|
@@ -4965,6 +4966,7 @@ class SDK {
|
|
|
4965
4966
|
this.nodes = config.nodes || [];
|
|
4966
4967
|
this.charts = ["covalent", "zapper"];
|
|
4967
4968
|
this.nfts = [];
|
|
4969
|
+
this.pendingTransactions = [];
|
|
4968
4970
|
this.isPioneer = null;
|
|
4969
4971
|
this.pioneer = null;
|
|
4970
4972
|
this.context = "";
|
|
@@ -5372,6 +5374,29 @@ class SDK {
|
|
|
5372
5374
|
let txManager = new TransactionManager(transactionDependencies, this.events);
|
|
5373
5375
|
let unsignedTx = await txManager.transfer(sendPayload);
|
|
5374
5376
|
console.log(tag6, "unsignedTx: ", unsignedTx);
|
|
5377
|
+
if (this.assetContext && sendPayload) {
|
|
5378
|
+
this.assetContext.sendAmount = sendPayload.amount;
|
|
5379
|
+
this.assetContext.sendTo = sendPayload.to;
|
|
5380
|
+
this.assetContext.sendMemo = sendPayload.memo;
|
|
5381
|
+
let estimatedFee = "0";
|
|
5382
|
+
if (unsignedTx) {
|
|
5383
|
+
if (unsignedTx.fee) {
|
|
5384
|
+
estimatedFee = typeof unsignedTx.fee === "string" ? unsignedTx.fee : unsignedTx.fee.toString();
|
|
5385
|
+
} else if (unsignedTx.gasPrice && unsignedTx.gasLimit) {
|
|
5386
|
+
const gasPrice = parseFloat(unsignedTx.gasPrice);
|
|
5387
|
+
const gasLimit = parseFloat(unsignedTx.gasLimit);
|
|
5388
|
+
estimatedFee = (gasPrice * gasLimit / 1e9).toFixed(8);
|
|
5389
|
+
} else if (unsignedTx.fee && unsignedTx.fee.amount && Array.isArray(unsignedTx.fee.amount)) {
|
|
5390
|
+
estimatedFee = unsignedTx.fee.amount[0]?.amount || "0";
|
|
5391
|
+
}
|
|
5392
|
+
}
|
|
5393
|
+
this.assetContext.sendFee = estimatedFee;
|
|
5394
|
+
console.log(tag6, "\uD83D\uDCBE Stored transaction details for optimistic update:", {
|
|
5395
|
+
amount: this.assetContext.sendAmount,
|
|
5396
|
+
fee: this.assetContext.sendFee,
|
|
5397
|
+
to: this.assetContext.sendTo
|
|
5398
|
+
});
|
|
5399
|
+
}
|
|
5375
5400
|
return unsignedTx;
|
|
5376
5401
|
} catch (e) {
|
|
5377
5402
|
console.error(e);
|
|
@@ -5476,12 +5501,101 @@ class SDK {
|
|
|
5476
5501
|
serialized: signedTx
|
|
5477
5502
|
};
|
|
5478
5503
|
let txid = await txManager.broadcast(payload);
|
|
5504
|
+
if (txid && !txid.error) {
|
|
5505
|
+
const amount = this.assetContext?.sendAmount || "0";
|
|
5506
|
+
const fee = this.assetContext?.sendFee || "0";
|
|
5507
|
+
const to = this.assetContext?.sendTo || "";
|
|
5508
|
+
const from = this.pubkeyContext?.address || this.pubkeyContext?.master || "";
|
|
5509
|
+
if (amount !== "0" && parseFloat(amount) > 0) {
|
|
5510
|
+
console.log(tag6, "\uD83D\uDCB0 Performing optimistic balance update:", {
|
|
5511
|
+
caip,
|
|
5512
|
+
amount,
|
|
5513
|
+
fee,
|
|
5514
|
+
from,
|
|
5515
|
+
to
|
|
5516
|
+
});
|
|
5517
|
+
this.debitBalance(caip, amount, fee);
|
|
5518
|
+
this.addPendingTransaction({
|
|
5519
|
+
txid,
|
|
5520
|
+
caip,
|
|
5521
|
+
amount,
|
|
5522
|
+
to,
|
|
5523
|
+
from,
|
|
5524
|
+
fee,
|
|
5525
|
+
broadcastTime: Date.now(),
|
|
5526
|
+
status: "pending"
|
|
5527
|
+
});
|
|
5528
|
+
}
|
|
5529
|
+
}
|
|
5479
5530
|
return txid;
|
|
5480
5531
|
} catch (e) {
|
|
5481
5532
|
console.error(e);
|
|
5482
5533
|
throw e;
|
|
5483
5534
|
}
|
|
5484
5535
|
};
|
|
5536
|
+
this.addPendingTransaction = function(txData) {
|
|
5537
|
+
const tag6 = TAG12 + " | addPendingTransaction | ";
|
|
5538
|
+
console.log(tag6, "Adding pending transaction:", txData);
|
|
5539
|
+
this.pendingTransactions.unshift({
|
|
5540
|
+
...txData,
|
|
5541
|
+
status: txData.status || "pending",
|
|
5542
|
+
addedAt: Date.now()
|
|
5543
|
+
});
|
|
5544
|
+
if (this.pendingTransactions.length > 50) {
|
|
5545
|
+
this.pendingTransactions = this.pendingTransactions.slice(0, 50);
|
|
5546
|
+
}
|
|
5547
|
+
this.events.emit("PENDING_TX_ADDED", txData);
|
|
5548
|
+
this.events.emit("PENDING_TXS_UPDATED", this.pendingTransactions);
|
|
5549
|
+
console.log(tag6, `Pending transactions count: ${this.pendingTransactions.length}`);
|
|
5550
|
+
return txData;
|
|
5551
|
+
};
|
|
5552
|
+
this.debitBalance = function(caip, amount, fee = "0") {
|
|
5553
|
+
const tag6 = TAG12 + " | debitBalance | ";
|
|
5554
|
+
console.log(tag6, "Debiting balance:", { caip, amount, fee });
|
|
5555
|
+
const balanceIndex = this.balances.findIndex((b2) => b2.caip === caip);
|
|
5556
|
+
if (balanceIndex === -1) {
|
|
5557
|
+
console.warn(tag6, "Balance not found for CAIP:", caip);
|
|
5558
|
+
return null;
|
|
5559
|
+
}
|
|
5560
|
+
const currentBalance = this.balances[balanceIndex];
|
|
5561
|
+
const currentBalanceNum = parseFloat(currentBalance.balance || "0");
|
|
5562
|
+
const amountNum = parseFloat(amount);
|
|
5563
|
+
const feeNum = parseFloat(fee);
|
|
5564
|
+
const totalDebit = amountNum + feeNum;
|
|
5565
|
+
const newBalanceNum = currentBalanceNum - totalDebit;
|
|
5566
|
+
if (newBalanceNum < 0) {
|
|
5567
|
+
console.warn(tag6, "Cannot debit - would result in negative balance:", {
|
|
5568
|
+
current: currentBalanceNum,
|
|
5569
|
+
debit: totalDebit,
|
|
5570
|
+
result: newBalanceNum
|
|
5571
|
+
});
|
|
5572
|
+
return null;
|
|
5573
|
+
}
|
|
5574
|
+
const updatedBalance = {
|
|
5575
|
+
...currentBalance,
|
|
5576
|
+
balance: newBalanceNum.toFixed(8),
|
|
5577
|
+
valueUsd: newBalanceNum * (parseFloat(currentBalance.priceUsd) || 0),
|
|
5578
|
+
updated: Date.now(),
|
|
5579
|
+
optimistic: true,
|
|
5580
|
+
previousBalance: currentBalanceNum
|
|
5581
|
+
};
|
|
5582
|
+
this.balances[balanceIndex] = updatedBalance;
|
|
5583
|
+
console.log(tag6, "✅ Balance updated:", {
|
|
5584
|
+
previous: currentBalanceNum.toFixed(8),
|
|
5585
|
+
new: newBalanceNum.toFixed(8),
|
|
5586
|
+
deducted: totalDebit.toFixed(8)
|
|
5587
|
+
});
|
|
5588
|
+
this.events.emit("BALANCES_UPDATED", this.balances);
|
|
5589
|
+
this.events.emit("SET_BALANCES", this.balances);
|
|
5590
|
+
try {
|
|
5591
|
+
this.dashboard = this.buildDashboardFromBalances();
|
|
5592
|
+
this.events.emit("SET_DASHBOARD", this.dashboard);
|
|
5593
|
+
console.log(tag6, "✅ Dashboard rebuilt with updated balance");
|
|
5594
|
+
} catch (dashboardError) {
|
|
5595
|
+
console.error(tag6, "Error rebuilding dashboard:", dashboardError);
|
|
5596
|
+
}
|
|
5597
|
+
return updatedBalance;
|
|
5598
|
+
};
|
|
5485
5599
|
this.swap = async function(swapPayload) {
|
|
5486
5600
|
let tag6 = `${TAG12} | swap | `;
|
|
5487
5601
|
try {
|
|
@@ -5947,6 +6061,14 @@ class SDK {
|
|
|
5947
6061
|
const assetQuery = [];
|
|
5948
6062
|
for (const networkId of networkIds) {
|
|
5949
6063
|
const pubkeys = findPubkeysForNetwork(this.pubkeys, networkId, this.paths, tag6);
|
|
6064
|
+
console.log(`\uD83D\uDD0D [DIAGNOSTIC] ${networkId}: Found ${pubkeys.length} pubkeys`);
|
|
6065
|
+
if (networkId.startsWith("bip122:000000000019")) {
|
|
6066
|
+
console.log("\uD83D\uDD0D [BITCOIN DIAGNOSTIC] Bitcoin pubkeys:", pubkeys.map((p) => ({
|
|
6067
|
+
pubkey: p.pubkey?.substring(0, 20) + "...",
|
|
6068
|
+
networks: p.networks,
|
|
6069
|
+
symbol: p.symbol
|
|
6070
|
+
})));
|
|
6071
|
+
}
|
|
5950
6072
|
const caip = await networkIdToCaip2(networkId);
|
|
5951
6073
|
assetQuery.push(...buildAssetQuery(pubkeys, caip));
|
|
5952
6074
|
}
|
|
@@ -5961,7 +6083,18 @@ class SDK {
|
|
|
5961
6083
|
console.log(`⏱️ [PERF] Enriching ${marketInfo.data?.length || 0} balances...`);
|
|
5962
6084
|
const balances = enrichBalancesWithAssetInfo(marketInfo.data, this.assetsMap, caipToNetworkId7);
|
|
5963
6085
|
console.log(`⏱️ [PERF] Enrichment completed in ${(performance.now() - enrichStart).toFixed(0)}ms`);
|
|
5964
|
-
|
|
6086
|
+
console.log(tag6, `⚙️ Merging balances: ${balances.length} new + ${this.balances.length} existing`);
|
|
6087
|
+
const uniqueBalances = new Map([...this.balances, ...balances].map((balance) => [
|
|
6088
|
+
balance.identifier || `${balance.caip}:${balance.pubkey}`,
|
|
6089
|
+
balance
|
|
6090
|
+
]));
|
|
6091
|
+
const beforeCount = [...this.balances, ...balances].length;
|
|
6092
|
+
this.balances = Array.from(uniqueBalances.values());
|
|
6093
|
+
const duplicatesRemoved = beforeCount - this.balances.length;
|
|
6094
|
+
if (duplicatesRemoved > 0) {
|
|
6095
|
+
console.log(tag6, `\uD83D\uDD27 Removed ${duplicatesRemoved} duplicate balances`);
|
|
6096
|
+
}
|
|
6097
|
+
console.log(tag6, `✅ Final balance count: ${this.balances.length} unique balances`);
|
|
5965
6098
|
this.events.emit("SET_BALANCES", this.balances);
|
|
5966
6099
|
const dashStart = performance.now();
|
|
5967
6100
|
this.dashboard = this.buildDashboardFromBalances();
|
|
@@ -5975,16 +6108,29 @@ class SDK {
|
|
|
5975
6108
|
throw e;
|
|
5976
6109
|
}
|
|
5977
6110
|
};
|
|
5978
|
-
this.getBalances = async function(
|
|
6111
|
+
this.getBalances = async function(forceRefreshOrOptions, caip) {
|
|
5979
6112
|
const tag6 = `${TAG12} | getBalances | `;
|
|
5980
6113
|
try {
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
6114
|
+
let forceRefresh = false;
|
|
6115
|
+
let networkId;
|
|
6116
|
+
if (typeof forceRefreshOrOptions === "object") {
|
|
6117
|
+
networkId = forceRefreshOrOptions.networkId;
|
|
6118
|
+
forceRefresh = forceRefreshOrOptions.forceRefresh ?? false;
|
|
6119
|
+
console.log(tag6, `\uD83D\uDCCD New signature - networkId: ${networkId}, forceRefresh: ${forceRefresh}`);
|
|
6120
|
+
} else {
|
|
6121
|
+
forceRefresh = forceRefreshOrOptions ?? false;
|
|
6122
|
+
if (caip) {
|
|
6123
|
+
console.log(tag6, `\uD83C\uDFAF Old signature - Refreshing single asset: ${caip}`);
|
|
6124
|
+
networkId = caip.split("/")[0];
|
|
6125
|
+
console.log(tag6, `\uD83D\uDCCD Extracted networkId: ${networkId}`);
|
|
6126
|
+
}
|
|
6127
|
+
}
|
|
6128
|
+
if (networkId) {
|
|
6129
|
+
console.log(tag6, `\uD83C\uDFAF Refreshing specific network: ${networkId}`);
|
|
5985
6130
|
const results = await this.getBalancesForNetworks([networkId], forceRefresh);
|
|
5986
|
-
return results.filter((b2) => b2.
|
|
6131
|
+
return results.filter((b2) => b2.networkId === networkId || b2.caip?.startsWith(networkId));
|
|
5987
6132
|
}
|
|
6133
|
+
console.log(tag6, `\uD83C\uDF10 Refreshing all blockchains (${this.blockchains.length} networks)`);
|
|
5988
6134
|
return await this.getBalancesForNetworks(this.blockchains, forceRefresh);
|
|
5989
6135
|
} catch (e) {
|
|
5990
6136
|
console.error(tag6, "Error in getBalances: ", e);
|
|
@@ -6125,7 +6271,7 @@ class SDK {
|
|
|
6125
6271
|
"bip122:12a765e31ffd4059bada1e25190f6e98": { address: "https://blockchair.com/litecoin/address/", tx: "https://blockchair.com/litecoin/transaction/" },
|
|
6126
6272
|
"bip122:00000000001a91e3dace36e2be3bf030": { address: "https://dogechain.info/address/", tx: "https://dogechain.info/tx/" },
|
|
6127
6273
|
"bip122:000000000000000000651ef99cb9fcbe": { address: "https://blockchair.com/bitcoin-cash/address/", tx: "https://blockchair.com/bitcoin-cash/transaction/" },
|
|
6128
|
-
"bip122:000007d91d1254d60e2dd1ae58038307": { address: "https://
|
|
6274
|
+
"bip122:000007d91d1254d60e2dd1ae58038307": { address: "https://explorer.dash.org/insight/address/", tx: "https://explorer.dash.org/insight/tx/" },
|
|
6129
6275
|
"bip122:4da631f2ac1bed857bd968c67c913978": { address: "https://digiexplorer.info/address/", tx: "https://digiexplorer.info/tx/" },
|
|
6130
6276
|
"bip122:00040fe8ec8471911baa1db1266ea15d": { address: "https://explorer.zcha.in/accounts/", tx: "https://explorer.zcha.in/transactions/" },
|
|
6131
6277
|
"cosmos:cosmoshub-4": { address: "https://www.mintscan.io/cosmos/address/", tx: "https://www.mintscan.io/cosmos/tx/" },
|
package/dist/index.js
CHANGED
|
@@ -4448,8 +4448,8 @@ var EXPLORER_BASE_URLS = {
|
|
|
4448
4448
|
tx: "https://blockchair.com/bitcoin-cash/transaction/"
|
|
4449
4449
|
},
|
|
4450
4450
|
"bip122:000007d91d1254d60e2dd1ae58038307": {
|
|
4451
|
-
address: "https://
|
|
4452
|
-
tx: "https://
|
|
4451
|
+
address: "https://explorer.dash.org/insight/address/",
|
|
4452
|
+
tx: "https://explorer.dash.org/insight/tx/"
|
|
4453
4453
|
},
|
|
4454
4454
|
"bip122:4da631f2ac1bed857bd968c67c913978": {
|
|
4455
4455
|
address: "https://digiexplorer.info/address/",
|
|
@@ -4886,6 +4886,7 @@ class SDK {
|
|
|
4886
4886
|
assetsMap;
|
|
4887
4887
|
dashboard;
|
|
4888
4888
|
nfts;
|
|
4889
|
+
pendingTransactions;
|
|
4889
4890
|
events;
|
|
4890
4891
|
pairWallet;
|
|
4891
4892
|
setContext;
|
|
@@ -4965,6 +4966,7 @@ class SDK {
|
|
|
4965
4966
|
this.nodes = config.nodes || [];
|
|
4966
4967
|
this.charts = ["covalent", "zapper"];
|
|
4967
4968
|
this.nfts = [];
|
|
4969
|
+
this.pendingTransactions = [];
|
|
4968
4970
|
this.isPioneer = null;
|
|
4969
4971
|
this.pioneer = null;
|
|
4970
4972
|
this.context = "";
|
|
@@ -5372,6 +5374,29 @@ class SDK {
|
|
|
5372
5374
|
let txManager = new TransactionManager(transactionDependencies, this.events);
|
|
5373
5375
|
let unsignedTx = await txManager.transfer(sendPayload);
|
|
5374
5376
|
console.log(tag6, "unsignedTx: ", unsignedTx);
|
|
5377
|
+
if (this.assetContext && sendPayload) {
|
|
5378
|
+
this.assetContext.sendAmount = sendPayload.amount;
|
|
5379
|
+
this.assetContext.sendTo = sendPayload.to;
|
|
5380
|
+
this.assetContext.sendMemo = sendPayload.memo;
|
|
5381
|
+
let estimatedFee = "0";
|
|
5382
|
+
if (unsignedTx) {
|
|
5383
|
+
if (unsignedTx.fee) {
|
|
5384
|
+
estimatedFee = typeof unsignedTx.fee === "string" ? unsignedTx.fee : unsignedTx.fee.toString();
|
|
5385
|
+
} else if (unsignedTx.gasPrice && unsignedTx.gasLimit) {
|
|
5386
|
+
const gasPrice = parseFloat(unsignedTx.gasPrice);
|
|
5387
|
+
const gasLimit = parseFloat(unsignedTx.gasLimit);
|
|
5388
|
+
estimatedFee = (gasPrice * gasLimit / 1e9).toFixed(8);
|
|
5389
|
+
} else if (unsignedTx.fee && unsignedTx.fee.amount && Array.isArray(unsignedTx.fee.amount)) {
|
|
5390
|
+
estimatedFee = unsignedTx.fee.amount[0]?.amount || "0";
|
|
5391
|
+
}
|
|
5392
|
+
}
|
|
5393
|
+
this.assetContext.sendFee = estimatedFee;
|
|
5394
|
+
console.log(tag6, "\uD83D\uDCBE Stored transaction details for optimistic update:", {
|
|
5395
|
+
amount: this.assetContext.sendAmount,
|
|
5396
|
+
fee: this.assetContext.sendFee,
|
|
5397
|
+
to: this.assetContext.sendTo
|
|
5398
|
+
});
|
|
5399
|
+
}
|
|
5375
5400
|
return unsignedTx;
|
|
5376
5401
|
} catch (e) {
|
|
5377
5402
|
console.error(e);
|
|
@@ -5476,12 +5501,101 @@ class SDK {
|
|
|
5476
5501
|
serialized: signedTx
|
|
5477
5502
|
};
|
|
5478
5503
|
let txid = await txManager.broadcast(payload);
|
|
5504
|
+
if (txid && !txid.error) {
|
|
5505
|
+
const amount = this.assetContext?.sendAmount || "0";
|
|
5506
|
+
const fee = this.assetContext?.sendFee || "0";
|
|
5507
|
+
const to = this.assetContext?.sendTo || "";
|
|
5508
|
+
const from = this.pubkeyContext?.address || this.pubkeyContext?.master || "";
|
|
5509
|
+
if (amount !== "0" && parseFloat(amount) > 0) {
|
|
5510
|
+
console.log(tag6, "\uD83D\uDCB0 Performing optimistic balance update:", {
|
|
5511
|
+
caip,
|
|
5512
|
+
amount,
|
|
5513
|
+
fee,
|
|
5514
|
+
from,
|
|
5515
|
+
to
|
|
5516
|
+
});
|
|
5517
|
+
this.debitBalance(caip, amount, fee);
|
|
5518
|
+
this.addPendingTransaction({
|
|
5519
|
+
txid,
|
|
5520
|
+
caip,
|
|
5521
|
+
amount,
|
|
5522
|
+
to,
|
|
5523
|
+
from,
|
|
5524
|
+
fee,
|
|
5525
|
+
broadcastTime: Date.now(),
|
|
5526
|
+
status: "pending"
|
|
5527
|
+
});
|
|
5528
|
+
}
|
|
5529
|
+
}
|
|
5479
5530
|
return txid;
|
|
5480
5531
|
} catch (e) {
|
|
5481
5532
|
console.error(e);
|
|
5482
5533
|
throw e;
|
|
5483
5534
|
}
|
|
5484
5535
|
};
|
|
5536
|
+
this.addPendingTransaction = function(txData) {
|
|
5537
|
+
const tag6 = TAG12 + " | addPendingTransaction | ";
|
|
5538
|
+
console.log(tag6, "Adding pending transaction:", txData);
|
|
5539
|
+
this.pendingTransactions.unshift({
|
|
5540
|
+
...txData,
|
|
5541
|
+
status: txData.status || "pending",
|
|
5542
|
+
addedAt: Date.now()
|
|
5543
|
+
});
|
|
5544
|
+
if (this.pendingTransactions.length > 50) {
|
|
5545
|
+
this.pendingTransactions = this.pendingTransactions.slice(0, 50);
|
|
5546
|
+
}
|
|
5547
|
+
this.events.emit("PENDING_TX_ADDED", txData);
|
|
5548
|
+
this.events.emit("PENDING_TXS_UPDATED", this.pendingTransactions);
|
|
5549
|
+
console.log(tag6, `Pending transactions count: ${this.pendingTransactions.length}`);
|
|
5550
|
+
return txData;
|
|
5551
|
+
};
|
|
5552
|
+
this.debitBalance = function(caip, amount, fee = "0") {
|
|
5553
|
+
const tag6 = TAG12 + " | debitBalance | ";
|
|
5554
|
+
console.log(tag6, "Debiting balance:", { caip, amount, fee });
|
|
5555
|
+
const balanceIndex = this.balances.findIndex((b2) => b2.caip === caip);
|
|
5556
|
+
if (balanceIndex === -1) {
|
|
5557
|
+
console.warn(tag6, "Balance not found for CAIP:", caip);
|
|
5558
|
+
return null;
|
|
5559
|
+
}
|
|
5560
|
+
const currentBalance = this.balances[balanceIndex];
|
|
5561
|
+
const currentBalanceNum = parseFloat(currentBalance.balance || "0");
|
|
5562
|
+
const amountNum = parseFloat(amount);
|
|
5563
|
+
const feeNum = parseFloat(fee);
|
|
5564
|
+
const totalDebit = amountNum + feeNum;
|
|
5565
|
+
const newBalanceNum = currentBalanceNum - totalDebit;
|
|
5566
|
+
if (newBalanceNum < 0) {
|
|
5567
|
+
console.warn(tag6, "Cannot debit - would result in negative balance:", {
|
|
5568
|
+
current: currentBalanceNum,
|
|
5569
|
+
debit: totalDebit,
|
|
5570
|
+
result: newBalanceNum
|
|
5571
|
+
});
|
|
5572
|
+
return null;
|
|
5573
|
+
}
|
|
5574
|
+
const updatedBalance = {
|
|
5575
|
+
...currentBalance,
|
|
5576
|
+
balance: newBalanceNum.toFixed(8),
|
|
5577
|
+
valueUsd: newBalanceNum * (parseFloat(currentBalance.priceUsd) || 0),
|
|
5578
|
+
updated: Date.now(),
|
|
5579
|
+
optimistic: true,
|
|
5580
|
+
previousBalance: currentBalanceNum
|
|
5581
|
+
};
|
|
5582
|
+
this.balances[balanceIndex] = updatedBalance;
|
|
5583
|
+
console.log(tag6, "✅ Balance updated:", {
|
|
5584
|
+
previous: currentBalanceNum.toFixed(8),
|
|
5585
|
+
new: newBalanceNum.toFixed(8),
|
|
5586
|
+
deducted: totalDebit.toFixed(8)
|
|
5587
|
+
});
|
|
5588
|
+
this.events.emit("BALANCES_UPDATED", this.balances);
|
|
5589
|
+
this.events.emit("SET_BALANCES", this.balances);
|
|
5590
|
+
try {
|
|
5591
|
+
this.dashboard = this.buildDashboardFromBalances();
|
|
5592
|
+
this.events.emit("SET_DASHBOARD", this.dashboard);
|
|
5593
|
+
console.log(tag6, "✅ Dashboard rebuilt with updated balance");
|
|
5594
|
+
} catch (dashboardError) {
|
|
5595
|
+
console.error(tag6, "Error rebuilding dashboard:", dashboardError);
|
|
5596
|
+
}
|
|
5597
|
+
return updatedBalance;
|
|
5598
|
+
};
|
|
5485
5599
|
this.swap = async function(swapPayload) {
|
|
5486
5600
|
let tag6 = `${TAG12} | swap | `;
|
|
5487
5601
|
try {
|
|
@@ -5947,6 +6061,14 @@ class SDK {
|
|
|
5947
6061
|
const assetQuery = [];
|
|
5948
6062
|
for (const networkId of networkIds) {
|
|
5949
6063
|
const pubkeys = findPubkeysForNetwork(this.pubkeys, networkId, this.paths, tag6);
|
|
6064
|
+
console.log(`\uD83D\uDD0D [DIAGNOSTIC] ${networkId}: Found ${pubkeys.length} pubkeys`);
|
|
6065
|
+
if (networkId.startsWith("bip122:000000000019")) {
|
|
6066
|
+
console.log("\uD83D\uDD0D [BITCOIN DIAGNOSTIC] Bitcoin pubkeys:", pubkeys.map((p) => ({
|
|
6067
|
+
pubkey: p.pubkey?.substring(0, 20) + "...",
|
|
6068
|
+
networks: p.networks,
|
|
6069
|
+
symbol: p.symbol
|
|
6070
|
+
})));
|
|
6071
|
+
}
|
|
5950
6072
|
const caip = await networkIdToCaip2(networkId);
|
|
5951
6073
|
assetQuery.push(...buildAssetQuery(pubkeys, caip));
|
|
5952
6074
|
}
|
|
@@ -5961,7 +6083,18 @@ class SDK {
|
|
|
5961
6083
|
console.log(`⏱️ [PERF] Enriching ${marketInfo.data?.length || 0} balances...`);
|
|
5962
6084
|
const balances = enrichBalancesWithAssetInfo(marketInfo.data, this.assetsMap, caipToNetworkId7);
|
|
5963
6085
|
console.log(`⏱️ [PERF] Enrichment completed in ${(performance.now() - enrichStart).toFixed(0)}ms`);
|
|
5964
|
-
|
|
6086
|
+
console.log(tag6, `⚙️ Merging balances: ${balances.length} new + ${this.balances.length} existing`);
|
|
6087
|
+
const uniqueBalances = new Map([...this.balances, ...balances].map((balance) => [
|
|
6088
|
+
balance.identifier || `${balance.caip}:${balance.pubkey}`,
|
|
6089
|
+
balance
|
|
6090
|
+
]));
|
|
6091
|
+
const beforeCount = [...this.balances, ...balances].length;
|
|
6092
|
+
this.balances = Array.from(uniqueBalances.values());
|
|
6093
|
+
const duplicatesRemoved = beforeCount - this.balances.length;
|
|
6094
|
+
if (duplicatesRemoved > 0) {
|
|
6095
|
+
console.log(tag6, `\uD83D\uDD27 Removed ${duplicatesRemoved} duplicate balances`);
|
|
6096
|
+
}
|
|
6097
|
+
console.log(tag6, `✅ Final balance count: ${this.balances.length} unique balances`);
|
|
5965
6098
|
this.events.emit("SET_BALANCES", this.balances);
|
|
5966
6099
|
const dashStart = performance.now();
|
|
5967
6100
|
this.dashboard = this.buildDashboardFromBalances();
|
|
@@ -5975,16 +6108,29 @@ class SDK {
|
|
|
5975
6108
|
throw e;
|
|
5976
6109
|
}
|
|
5977
6110
|
};
|
|
5978
|
-
this.getBalances = async function(
|
|
6111
|
+
this.getBalances = async function(forceRefreshOrOptions, caip) {
|
|
5979
6112
|
const tag6 = `${TAG12} | getBalances | `;
|
|
5980
6113
|
try {
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
6114
|
+
let forceRefresh = false;
|
|
6115
|
+
let networkId;
|
|
6116
|
+
if (typeof forceRefreshOrOptions === "object") {
|
|
6117
|
+
networkId = forceRefreshOrOptions.networkId;
|
|
6118
|
+
forceRefresh = forceRefreshOrOptions.forceRefresh ?? false;
|
|
6119
|
+
console.log(tag6, `\uD83D\uDCCD New signature - networkId: ${networkId}, forceRefresh: ${forceRefresh}`);
|
|
6120
|
+
} else {
|
|
6121
|
+
forceRefresh = forceRefreshOrOptions ?? false;
|
|
6122
|
+
if (caip) {
|
|
6123
|
+
console.log(tag6, `\uD83C\uDFAF Old signature - Refreshing single asset: ${caip}`);
|
|
6124
|
+
networkId = caip.split("/")[0];
|
|
6125
|
+
console.log(tag6, `\uD83D\uDCCD Extracted networkId: ${networkId}`);
|
|
6126
|
+
}
|
|
6127
|
+
}
|
|
6128
|
+
if (networkId) {
|
|
6129
|
+
console.log(tag6, `\uD83C\uDFAF Refreshing specific network: ${networkId}`);
|
|
5985
6130
|
const results = await this.getBalancesForNetworks([networkId], forceRefresh);
|
|
5986
|
-
return results.filter((b2) => b2.
|
|
6131
|
+
return results.filter((b2) => b2.networkId === networkId || b2.caip?.startsWith(networkId));
|
|
5987
6132
|
}
|
|
6133
|
+
console.log(tag6, `\uD83C\uDF10 Refreshing all blockchains (${this.blockchains.length} networks)`);
|
|
5988
6134
|
return await this.getBalancesForNetworks(this.blockchains, forceRefresh);
|
|
5989
6135
|
} catch (e) {
|
|
5990
6136
|
console.error(tag6, "Error in getBalances: ", e);
|
|
@@ -6125,7 +6271,7 @@ class SDK {
|
|
|
6125
6271
|
"bip122:12a765e31ffd4059bada1e25190f6e98": { address: "https://blockchair.com/litecoin/address/", tx: "https://blockchair.com/litecoin/transaction/" },
|
|
6126
6272
|
"bip122:00000000001a91e3dace36e2be3bf030": { address: "https://dogechain.info/address/", tx: "https://dogechain.info/tx/" },
|
|
6127
6273
|
"bip122:000000000000000000651ef99cb9fcbe": { address: "https://blockchair.com/bitcoin-cash/address/", tx: "https://blockchair.com/bitcoin-cash/transaction/" },
|
|
6128
|
-
"bip122:000007d91d1254d60e2dd1ae58038307": { address: "https://
|
|
6274
|
+
"bip122:000007d91d1254d60e2dd1ae58038307": { address: "https://explorer.dash.org/insight/address/", tx: "https://explorer.dash.org/insight/tx/" },
|
|
6129
6275
|
"bip122:4da631f2ac1bed857bd968c67c913978": { address: "https://digiexplorer.info/address/", tx: "https://digiexplorer.info/tx/" },
|
|
6130
6276
|
"bip122:00040fe8ec8471911baa1db1266ea15d": { address: "https://explorer.zcha.in/accounts/", tx: "https://explorer.zcha.in/transactions/" },
|
|
6131
6277
|
"cosmos:cosmoshub-4": { address: "https://www.mintscan.io/cosmos/address/", tx: "https://www.mintscan.io/cosmos/tx/" },
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "highlander",
|
|
3
3
|
"name": "@pioneer-platform/pioneer-sdk",
|
|
4
|
-
"version": "8.15.
|
|
4
|
+
"version": "8.15.44",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@keepkey/keepkey-sdk": "^0.2.62",
|
|
7
|
-
"@pioneer-platform/pioneer-caip": "^9.10.
|
|
8
|
-
"@pioneer-platform/pioneer-client": "^9.10.
|
|
9
|
-
"@pioneer-platform/pioneer-coins": "^9.11.
|
|
10
|
-
"@pioneer-platform/pioneer-discovery": "^8.15.
|
|
11
|
-
"@pioneer-platform/pioneer-events": "^8.12.
|
|
7
|
+
"@pioneer-platform/pioneer-caip": "^9.10.21",
|
|
8
|
+
"@pioneer-platform/pioneer-client": "^9.10.24",
|
|
9
|
+
"@pioneer-platform/pioneer-coins": "^9.11.21",
|
|
10
|
+
"@pioneer-platform/pioneer-discovery": "^8.15.44",
|
|
11
|
+
"@pioneer-platform/pioneer-events": "^8.12.13",
|
|
12
12
|
"coinselect": "^3.1.13",
|
|
13
13
|
"eventemitter3": "^5.0.1",
|
|
14
14
|
"neotraverse": "^0.6.8",
|
package/src/index.ts
CHANGED
|
@@ -128,6 +128,7 @@ export class SDK {
|
|
|
128
128
|
public assetsMap: any;
|
|
129
129
|
public dashboard: any;
|
|
130
130
|
public nfts: any[];
|
|
131
|
+
public pendingTransactions: any[]; // Track recent/pending transactions
|
|
131
132
|
public events: any;
|
|
132
133
|
public pairWallet: (options: any) => Promise<any>;
|
|
133
134
|
public setContext: (context: string) => Promise<{ success: boolean }>;
|
|
@@ -236,6 +237,7 @@ export class SDK {
|
|
|
236
237
|
this.nodes = config.nodes || [];
|
|
237
238
|
this.charts = ['covalent', 'zapper'];
|
|
238
239
|
this.nfts = [];
|
|
240
|
+
this.pendingTransactions = []; // Initialize empty pending transactions array
|
|
239
241
|
this.isPioneer = null;
|
|
240
242
|
this.pioneer = null;
|
|
241
243
|
this.context = '';
|
|
@@ -814,6 +816,46 @@ export class SDK {
|
|
|
814
816
|
let txManager = new TransactionManager(transactionDependencies, this.events);
|
|
815
817
|
let unsignedTx = await txManager.transfer(sendPayload);
|
|
816
818
|
console.log(tag, 'unsignedTx: ', unsignedTx);
|
|
819
|
+
|
|
820
|
+
// CRITICAL: Store transaction details in assetContext for optimistic balance update
|
|
821
|
+
// These will be used by broadcastTx to debit the balance immediately
|
|
822
|
+
if (this.assetContext && sendPayload) {
|
|
823
|
+
this.assetContext.sendAmount = sendPayload.amount;
|
|
824
|
+
this.assetContext.sendTo = sendPayload.to;
|
|
825
|
+
this.assetContext.sendMemo = sendPayload.memo;
|
|
826
|
+
|
|
827
|
+
// Extract fee from unsignedTx if available
|
|
828
|
+
// Different chains have different fee structures
|
|
829
|
+
let estimatedFee = '0';
|
|
830
|
+
if (unsignedTx) {
|
|
831
|
+
// UTXO chains
|
|
832
|
+
if (unsignedTx.fee) {
|
|
833
|
+
estimatedFee = typeof unsignedTx.fee === 'string'
|
|
834
|
+
? unsignedTx.fee
|
|
835
|
+
: unsignedTx.fee.toString();
|
|
836
|
+
}
|
|
837
|
+
// EVM chains
|
|
838
|
+
else if (unsignedTx.gasPrice && unsignedTx.gasLimit) {
|
|
839
|
+
const gasPrice = parseFloat(unsignedTx.gasPrice);
|
|
840
|
+
const gasLimit = parseFloat(unsignedTx.gasLimit);
|
|
841
|
+
// Convert from gwei to native token (rough estimate)
|
|
842
|
+
estimatedFee = ((gasPrice * gasLimit) / 1000000000).toFixed(8);
|
|
843
|
+
}
|
|
844
|
+
// Tendermint chains
|
|
845
|
+
else if (unsignedTx.fee && unsignedTx.fee.amount && Array.isArray(unsignedTx.fee.amount)) {
|
|
846
|
+
estimatedFee = unsignedTx.fee.amount[0]?.amount || '0';
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
this.assetContext.sendFee = estimatedFee;
|
|
851
|
+
|
|
852
|
+
console.log(tag, '💾 Stored transaction details for optimistic update:', {
|
|
853
|
+
amount: this.assetContext.sendAmount,
|
|
854
|
+
fee: this.assetContext.sendFee,
|
|
855
|
+
to: this.assetContext.sendTo
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
|
|
817
859
|
return unsignedTx;
|
|
818
860
|
} catch (e) {
|
|
819
861
|
console.error(e);
|
|
@@ -943,12 +985,149 @@ export class SDK {
|
|
|
943
985
|
serialized: signedTx,
|
|
944
986
|
};
|
|
945
987
|
let txid = await txManager.broadcast(payload);
|
|
988
|
+
|
|
989
|
+
// OPTIMISTIC UPDATE: Debit balance immediately after successful broadcast
|
|
990
|
+
if (txid && !txid.error) {
|
|
991
|
+
// Extract transaction details from assetContext (set during buildTx)
|
|
992
|
+
const amount = this.assetContext?.sendAmount || '0';
|
|
993
|
+
const fee = this.assetContext?.sendFee || '0';
|
|
994
|
+
const to = this.assetContext?.sendTo || '';
|
|
995
|
+
const from = this.pubkeyContext?.address || this.pubkeyContext?.master || '';
|
|
996
|
+
|
|
997
|
+
// Only perform optimistic update if we have valid transaction details
|
|
998
|
+
if (amount !== '0' && parseFloat(amount) > 0) {
|
|
999
|
+
console.log(tag, '💰 Performing optimistic balance update:', {
|
|
1000
|
+
caip,
|
|
1001
|
+
amount,
|
|
1002
|
+
fee,
|
|
1003
|
+
from,
|
|
1004
|
+
to
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
// Debit the balance optimistically
|
|
1008
|
+
this.debitBalance(caip, amount, fee);
|
|
1009
|
+
|
|
1010
|
+
// Track pending transaction
|
|
1011
|
+
this.addPendingTransaction({
|
|
1012
|
+
txid,
|
|
1013
|
+
caip,
|
|
1014
|
+
amount,
|
|
1015
|
+
to,
|
|
1016
|
+
from,
|
|
1017
|
+
fee,
|
|
1018
|
+
broadcastTime: Date.now(),
|
|
1019
|
+
status: 'pending'
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
946
1024
|
return txid;
|
|
947
1025
|
} catch (e) {
|
|
948
1026
|
console.error(e);
|
|
949
1027
|
throw e;
|
|
950
1028
|
}
|
|
951
1029
|
};
|
|
1030
|
+
|
|
1031
|
+
// Add pending transaction to tracking array
|
|
1032
|
+
this.addPendingTransaction = function (txData: {
|
|
1033
|
+
txid: string;
|
|
1034
|
+
caip: string;
|
|
1035
|
+
amount: string;
|
|
1036
|
+
to: string;
|
|
1037
|
+
from: string;
|
|
1038
|
+
fee: string;
|
|
1039
|
+
broadcastTime: number;
|
|
1040
|
+
status: 'pending' | 'confirmed' | 'failed';
|
|
1041
|
+
}) {
|
|
1042
|
+
const tag = TAG + ' | addPendingTransaction | ';
|
|
1043
|
+
console.log(tag, 'Adding pending transaction:', txData);
|
|
1044
|
+
|
|
1045
|
+
// Add to pending transactions array (most recent first)
|
|
1046
|
+
this.pendingTransactions.unshift({
|
|
1047
|
+
...txData,
|
|
1048
|
+
status: txData.status || 'pending',
|
|
1049
|
+
addedAt: Date.now()
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
// Keep only last 50 pending transactions to avoid memory bloat
|
|
1053
|
+
if (this.pendingTransactions.length > 50) {
|
|
1054
|
+
this.pendingTransactions = this.pendingTransactions.slice(0, 50);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// Emit events for UI updates
|
|
1058
|
+
this.events.emit('PENDING_TX_ADDED', txData);
|
|
1059
|
+
this.events.emit('PENDING_TXS_UPDATED', this.pendingTransactions);
|
|
1060
|
+
|
|
1061
|
+
console.log(tag, `Pending transactions count: ${this.pendingTransactions.length}`);
|
|
1062
|
+
|
|
1063
|
+
return txData;
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
// Optimistically debit balance after broadcast (before confirmation)
|
|
1067
|
+
this.debitBalance = function (caip: string, amount: string, fee: string = '0') {
|
|
1068
|
+
const tag = TAG + ' | debitBalance | ';
|
|
1069
|
+
console.log(tag, 'Debiting balance:', { caip, amount, fee });
|
|
1070
|
+
|
|
1071
|
+
// Find the balance entry for this asset
|
|
1072
|
+
const balanceIndex = this.balances.findIndex((b: any) => b.caip === caip);
|
|
1073
|
+
|
|
1074
|
+
if (balanceIndex === -1) {
|
|
1075
|
+
console.warn(tag, 'Balance not found for CAIP:', caip);
|
|
1076
|
+
return null;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
const currentBalance = this.balances[balanceIndex];
|
|
1080
|
+
const currentBalanceNum = parseFloat(currentBalance.balance || '0');
|
|
1081
|
+
const amountNum = parseFloat(amount);
|
|
1082
|
+
const feeNum = parseFloat(fee);
|
|
1083
|
+
const totalDebit = amountNum + feeNum;
|
|
1084
|
+
|
|
1085
|
+
// Calculate new balance
|
|
1086
|
+
const newBalanceNum = currentBalanceNum - totalDebit;
|
|
1087
|
+
|
|
1088
|
+
// Safety check: don't allow negative balance
|
|
1089
|
+
if (newBalanceNum < 0) {
|
|
1090
|
+
console.warn(tag, 'Cannot debit - would result in negative balance:', {
|
|
1091
|
+
current: currentBalanceNum,
|
|
1092
|
+
debit: totalDebit,
|
|
1093
|
+
result: newBalanceNum
|
|
1094
|
+
});
|
|
1095
|
+
return null;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
// Update the balance with optimistic flag
|
|
1099
|
+
const updatedBalance = {
|
|
1100
|
+
...currentBalance,
|
|
1101
|
+
balance: newBalanceNum.toFixed(8),
|
|
1102
|
+
valueUsd: newBalanceNum * (parseFloat(currentBalance.priceUsd) || 0),
|
|
1103
|
+
updated: Date.now(),
|
|
1104
|
+
optimistic: true, // Mark as optimistic update (will be replaced by real data on next sync)
|
|
1105
|
+
previousBalance: currentBalanceNum // Store previous balance for rollback if needed
|
|
1106
|
+
};
|
|
1107
|
+
|
|
1108
|
+
this.balances[balanceIndex] = updatedBalance;
|
|
1109
|
+
|
|
1110
|
+
console.log(tag, '✅ Balance updated:', {
|
|
1111
|
+
previous: currentBalanceNum.toFixed(8),
|
|
1112
|
+
new: newBalanceNum.toFixed(8),
|
|
1113
|
+
deducted: totalDebit.toFixed(8)
|
|
1114
|
+
});
|
|
1115
|
+
|
|
1116
|
+
// Emit balance update events
|
|
1117
|
+
this.events.emit('BALANCES_UPDATED', this.balances);
|
|
1118
|
+
this.events.emit('SET_BALANCES', this.balances);
|
|
1119
|
+
|
|
1120
|
+
// Rebuild dashboard with updated balances
|
|
1121
|
+
try {
|
|
1122
|
+
this.dashboard = this.buildDashboardFromBalances();
|
|
1123
|
+
this.events.emit('SET_DASHBOARD', this.dashboard);
|
|
1124
|
+
console.log(tag, '✅ Dashboard rebuilt with updated balance');
|
|
1125
|
+
} catch (dashboardError) {
|
|
1126
|
+
console.error(tag, 'Error rebuilding dashboard:', dashboardError);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
return updatedBalance;
|
|
1130
|
+
};
|
|
952
1131
|
this.swap = async function (swapPayload) {
|
|
953
1132
|
let tag = `${TAG} | swap | `;
|
|
954
1133
|
try {
|
|
@@ -1622,6 +1801,14 @@ export class SDK {
|
|
|
1622
1801
|
const assetQuery: { caip: string; pubkey: string }[] = [];
|
|
1623
1802
|
for (const networkId of networkIds) {
|
|
1624
1803
|
const pubkeys = findPubkeysForNetwork(this.pubkeys, networkId, this.paths, tag);
|
|
1804
|
+
console.log(`🔍 [DIAGNOSTIC] ${networkId}: Found ${pubkeys.length} pubkeys`);
|
|
1805
|
+
if (networkId.startsWith('bip122:000000000019')) {
|
|
1806
|
+
console.log('🔍 [BITCOIN DIAGNOSTIC] Bitcoin pubkeys:', pubkeys.map((p: any) => ({
|
|
1807
|
+
pubkey: p.pubkey?.substring(0, 20) + '...',
|
|
1808
|
+
networks: p.networks,
|
|
1809
|
+
symbol: p.symbol
|
|
1810
|
+
})));
|
|
1811
|
+
}
|
|
1625
1812
|
const caip = await networkIdToCaip(networkId);
|
|
1626
1813
|
assetQuery.push(...buildAssetQuery(pubkeys, caip));
|
|
1627
1814
|
}
|
|
@@ -1653,8 +1840,30 @@ export class SDK {
|
|
|
1653
1840
|
|
|
1654
1841
|
console.log(`⏱️ [PERF] Enrichment completed in ${(performance.now() - enrichStart).toFixed(0)}ms`);
|
|
1655
1842
|
|
|
1656
|
-
//
|
|
1657
|
-
|
|
1843
|
+
// CRITICAL: Deduplicate balances BEFORE setting
|
|
1844
|
+
// Merge new balances with existing balances, deduplicating by identifier (caip:pubkey)
|
|
1845
|
+
console.log(tag, `⚙️ Merging balances: ${balances.length} new + ${this.balances.length} existing`);
|
|
1846
|
+
|
|
1847
|
+
// Create a Map with identifier as key to deduplicate
|
|
1848
|
+
// Put NEW balances LAST so they override stale cached data
|
|
1849
|
+
const uniqueBalances = new Map(
|
|
1850
|
+
[...this.balances, ...balances].map((balance: any) => [
|
|
1851
|
+
balance.identifier || `${balance.caip}:${balance.pubkey}`,
|
|
1852
|
+
balance
|
|
1853
|
+
])
|
|
1854
|
+
);
|
|
1855
|
+
|
|
1856
|
+
const beforeCount = [...this.balances, ...balances].length;
|
|
1857
|
+
this.balances = Array.from(uniqueBalances.values());
|
|
1858
|
+
const duplicatesRemoved = beforeCount - this.balances.length;
|
|
1859
|
+
|
|
1860
|
+
if (duplicatesRemoved > 0) {
|
|
1861
|
+
console.log(tag, `🔧 Removed ${duplicatesRemoved} duplicate balances`);
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
console.log(tag, `✅ Final balance count: ${this.balances.length} unique balances`);
|
|
1865
|
+
|
|
1866
|
+
// Emit events
|
|
1658
1867
|
this.events.emit('SET_BALANCES', this.balances);
|
|
1659
1868
|
|
|
1660
1869
|
// Build and emit dashboard
|
|
@@ -1672,20 +1881,41 @@ export class SDK {
|
|
|
1672
1881
|
throw e;
|
|
1673
1882
|
}
|
|
1674
1883
|
};
|
|
1675
|
-
this.getBalances = async function (
|
|
1884
|
+
this.getBalances = async function (
|
|
1885
|
+
forceRefreshOrOptions?: boolean | { networkId?: string; forceRefresh?: boolean },
|
|
1886
|
+
caip?: string
|
|
1887
|
+
) {
|
|
1676
1888
|
const tag = `${TAG} | getBalances | `;
|
|
1677
1889
|
try {
|
|
1678
|
-
//
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1890
|
+
// Parse parameters - support both old and new signatures
|
|
1891
|
+
let forceRefresh = false;
|
|
1892
|
+
let networkId: string | undefined;
|
|
1893
|
+
|
|
1894
|
+
if (typeof forceRefreshOrOptions === 'object') {
|
|
1895
|
+
// New signature: getBalances({ networkId, forceRefresh })
|
|
1896
|
+
networkId = forceRefreshOrOptions.networkId;
|
|
1897
|
+
forceRefresh = forceRefreshOrOptions.forceRefresh ?? false;
|
|
1898
|
+
console.log(tag, `📍 New signature - networkId: ${networkId}, forceRefresh: ${forceRefresh}`);
|
|
1899
|
+
} else {
|
|
1900
|
+
// Old signature: getBalances(forceRefresh, caip)
|
|
1901
|
+
forceRefresh = forceRefreshOrOptions ?? false;
|
|
1902
|
+
|
|
1903
|
+
if (caip) {
|
|
1904
|
+
console.log(tag, `🎯 Old signature - Refreshing single asset: ${caip}`);
|
|
1905
|
+
networkId = caip.split('/')[0];
|
|
1906
|
+
console.log(tag, `📍 Extracted networkId: ${networkId}`);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1683
1909
|
|
|
1910
|
+
// If networkId is provided, refresh only that network
|
|
1911
|
+
if (networkId) {
|
|
1912
|
+
console.log(tag, `🎯 Refreshing specific network: ${networkId}`);
|
|
1684
1913
|
const results = await this.getBalancesForNetworks([networkId], forceRefresh);
|
|
1685
|
-
return results.filter((b) => b.
|
|
1914
|
+
return results.filter((b) => b.networkId === networkId || b.caip?.startsWith(networkId));
|
|
1686
1915
|
}
|
|
1687
1916
|
|
|
1688
1917
|
// Default: refresh all blockchains
|
|
1918
|
+
console.log(tag, `🌐 Refreshing all blockchains (${this.blockchains.length} networks)`);
|
|
1689
1919
|
return await this.getBalancesForNetworks(this.blockchains, forceRefresh);
|
|
1690
1920
|
} catch (e) {
|
|
1691
1921
|
console.error(tag, 'Error in getBalances: ', e);
|
|
@@ -1881,7 +2111,7 @@ export class SDK {
|
|
|
1881
2111
|
'bip122:12a765e31ffd4059bada1e25190f6e98': { address: 'https://blockchair.com/litecoin/address/', tx: 'https://blockchair.com/litecoin/transaction/' },
|
|
1882
2112
|
'bip122:00000000001a91e3dace36e2be3bf030': { address: 'https://dogechain.info/address/', tx: 'https://dogechain.info/tx/' },
|
|
1883
2113
|
'bip122:000000000000000000651ef99cb9fcbe': { address: 'https://blockchair.com/bitcoin-cash/address/', tx: 'https://blockchair.com/bitcoin-cash/transaction/' },
|
|
1884
|
-
'bip122:000007d91d1254d60e2dd1ae58038307': { address: 'https://
|
|
2114
|
+
'bip122:000007d91d1254d60e2dd1ae58038307': { address: 'https://explorer.dash.org/insight/address/', tx: 'https://explorer.dash.org/insight/tx/' },
|
|
1885
2115
|
'bip122:4da631f2ac1bed857bd968c67c913978': { address: 'https://digiexplorer.info/address/', tx: 'https://digiexplorer.info/tx/' },
|
|
1886
2116
|
'bip122:00040fe8ec8471911baa1db1266ea15d': { address: 'https://explorer.zcha.in/accounts/', tx: 'https://explorer.zcha.in/transactions/' },
|
|
1887
2117
|
'cosmos:cosmoshub-4': { address: 'https://www.mintscan.io/cosmos/address/', tx: 'https://www.mintscan.io/cosmos/tx/' },
|
|
@@ -57,8 +57,8 @@ const EXPLORER_BASE_URLS: Record<string, { address: string; tx: string }> = {
|
|
|
57
57
|
},
|
|
58
58
|
// Dash
|
|
59
59
|
'bip122:000007d91d1254d60e2dd1ae58038307': {
|
|
60
|
-
address: 'https://
|
|
61
|
-
tx: 'https://
|
|
60
|
+
address: 'https://explorer.dash.org/insight/address/',
|
|
61
|
+
tx: 'https://explorer.dash.org/insight/tx/'
|
|
62
62
|
},
|
|
63
63
|
// DigiByte
|
|
64
64
|
'bip122:4da631f2ac1bed857bd968c67c913978': {
|