@pioneer-platform/pioneer-sdk 8.15.31 → 8.15.33
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 +229 -46
- package/dist/index.es.js +229 -46
- package/dist/index.js +229 -46
- package/package.json +6 -6
- package/src/fees/index.ts +1 -0
- package/src/index.ts +85 -8
- package/src/txbuilder/createUnsignedUxtoTx.ts +20 -3
- package/src/utils/build-dashboard.ts +86 -46
- package/src/utils/portfolio-helpers.ts +135 -1
package/dist/index.js
CHANGED
|
@@ -2823,7 +2823,21 @@ async function createUnsignedUxtoTx(caip, to, amount, memo, pubkeys, pioneer, pu
|
|
|
2823
2823
|
}
|
|
2824
2824
|
} catch (error) {
|
|
2825
2825
|
console.error(`${tag}: Failed to get fee rates from Pioneer API:`, error.message || error);
|
|
2826
|
-
|
|
2826
|
+
const defaultFees = {
|
|
2827
|
+
"bip122:000000000019d6689c085ae165831e93": { slow: 3, average: 5, fast: 10, fastest: 15 },
|
|
2828
|
+
"bip122:12a765e31ffd4059bada1e25190f6e98": { slow: 2, average: 3, fast: 5, fastest: 10 },
|
|
2829
|
+
"bip122:00000000001a91e3dace36e2be3bf030": { slow: 1, average: 1, fast: 2, fastest: 3 },
|
|
2830
|
+
"bip122:000000000000000000651ef99cb9fcbe": { slow: 1, average: 1, fast: 2, fastest: 3 },
|
|
2831
|
+
"bip122:000007d91d1254d60e2dd1ae58038307": { slow: 1, average: 1, fast: 2, fastest: 3 },
|
|
2832
|
+
"bip122:4da631f2ac1bed857bd968c67c913978": { slow: 75, average: 80, fast: 100, fastest: 120 },
|
|
2833
|
+
"bip122:00040fe8ec8471911baa1db1266ea15d": { slow: 1, average: 1, fast: 2, fastest: 3 }
|
|
2834
|
+
};
|
|
2835
|
+
if (defaultFees[networkId]) {
|
|
2836
|
+
console.warn(`${tag}: Using default fee rates for ${networkId}`);
|
|
2837
|
+
feeRateFromNode = defaultFees[networkId];
|
|
2838
|
+
} else {
|
|
2839
|
+
throw new Error(`Unable to get fee rate for network ${networkId}: ${error.message || "API unavailable"}`);
|
|
2840
|
+
}
|
|
2827
2841
|
}
|
|
2828
2842
|
}
|
|
2829
2843
|
let effectiveFeeRate;
|
|
@@ -3539,6 +3553,7 @@ function getNetworkName(networkId) {
|
|
|
3539
3553
|
"bip122:00000000001a91e3dace36e2be3bf030": "Dogecoin",
|
|
3540
3554
|
"bip122:000000000000000000651ef99cb9fcbe": "Bitcoin Cash",
|
|
3541
3555
|
"bip122:000007d91d1254d60e2dd1ae58038307": "Dash",
|
|
3556
|
+
"bip122:00040fe8ec8471911baa1db1266ea15d": "Zcash",
|
|
3542
3557
|
"bip122:4da631f2ac1bed857bd968c67c913978": "DigiByte",
|
|
3543
3558
|
"eip155:1": "Ethereum",
|
|
3544
3559
|
"eip155:56": "BNB Smart Chain",
|
|
@@ -4110,7 +4125,7 @@ function buildDashboardFromBalances(balances, blockchains, assetsMap) {
|
|
|
4110
4125
|
totalValueUsd: 0,
|
|
4111
4126
|
networkPercentages: []
|
|
4112
4127
|
};
|
|
4113
|
-
let
|
|
4128
|
+
let totalPortfolioValueCents = 0;
|
|
4114
4129
|
const networksTemp = [];
|
|
4115
4130
|
for (const blockchain of blockchains) {
|
|
4116
4131
|
const filteredBalances = balances.filter((b2) => {
|
|
@@ -4118,50 +4133,46 @@ function buildDashboardFromBalances(balances, blockchains, assetsMap) {
|
|
|
4118
4133
|
return networkId === blockchain || blockchain === "eip155:*" && networkId.startsWith("eip155:");
|
|
4119
4134
|
});
|
|
4120
4135
|
const balanceMap = new Map;
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
} else {
|
|
4137
|
-
balances2.forEach((balance) => {
|
|
4138
|
-
const key = `${balance.caip}_${balance.pubkey || "default"}`;
|
|
4139
|
-
balanceMap.set(key, balance);
|
|
4140
|
-
});
|
|
4141
|
-
}
|
|
4136
|
+
filteredBalances.forEach((balance) => {
|
|
4137
|
+
const key = `${balance.caip}_${balance.pubkey || "default"}`;
|
|
4138
|
+
if (!balanceMap.has(key) || parseFloat(balance.valueUsd || "0") > parseFloat(balanceMap.get(key).valueUsd || "0")) {
|
|
4139
|
+
balanceMap.set(key, balance);
|
|
4140
|
+
} else {
|
|
4141
|
+
const existing = balanceMap.get(key);
|
|
4142
|
+
const existingValue = parseFloat(existing.valueUsd || "0");
|
|
4143
|
+
const newValue = parseFloat(balance.valueUsd || "0");
|
|
4144
|
+
console.log(`⚠️ [BUILD-DASHBOARD] ${blockchain} dedup skipped (same caip+pubkey):`, {
|
|
4145
|
+
caip: balance.caip,
|
|
4146
|
+
pubkey: (balance.pubkey || "default").substring(0, 20),
|
|
4147
|
+
existing: existingValue,
|
|
4148
|
+
new: newValue,
|
|
4149
|
+
diff: Math.abs(existingValue - newValue)
|
|
4150
|
+
});
|
|
4142
4151
|
}
|
|
4143
|
-
}
|
|
4144
|
-
filteredBalances.forEach((balance) => {
|
|
4145
|
-
const key = `${balance.caip}_${balance.pubkey || "default"}`;
|
|
4146
|
-
if (!balanceMap.has(key) || parseFloat(balance.valueUsd || "0") > parseFloat(balanceMap.get(key).valueUsd || "0")) {
|
|
4147
|
-
balanceMap.set(key, balance);
|
|
4148
|
-
}
|
|
4149
|
-
});
|
|
4150
|
-
}
|
|
4152
|
+
});
|
|
4151
4153
|
const networkBalances = Array.from(balanceMap.values());
|
|
4152
|
-
const
|
|
4153
|
-
|
|
4154
|
+
const networkTotalCents = networkBalances.reduce((sumCents, balance, idx) => {
|
|
4155
|
+
let valueUsd = typeof balance.valueUsd === "string" ? parseFloat(balance.valueUsd) : balance.valueUsd || 0;
|
|
4156
|
+
if (isNaN(valueUsd)) {
|
|
4157
|
+
console.warn(`⚠️ [BUILD-DASHBOARD] NaN value detected for ${balance.caip}:`, balance.valueUsd);
|
|
4158
|
+
return sumCents;
|
|
4159
|
+
}
|
|
4160
|
+
balance.valueUsd = valueUsd;
|
|
4161
|
+
const valueCents = Math.round(valueUsd * 100 * 1000) / 1000;
|
|
4154
4162
|
if (idx < 2) {
|
|
4155
4163
|
console.log(`\uD83D\uDCB0 [BUILD-DASHBOARD] ${blockchain} balance #${idx}:`, {
|
|
4156
4164
|
caip: balance.caip,
|
|
4157
4165
|
balance: balance.balance,
|
|
4158
4166
|
valueUsd: balance.valueUsd,
|
|
4167
|
+
valueUsdType: typeof balance.valueUsd,
|
|
4159
4168
|
parsedValueUsd: valueUsd,
|
|
4160
|
-
|
|
4169
|
+
valueCents,
|
|
4170
|
+
runningSumCents: sumCents + valueCents
|
|
4161
4171
|
});
|
|
4162
4172
|
}
|
|
4163
|
-
return
|
|
4173
|
+
return sumCents + valueCents;
|
|
4164
4174
|
}, 0);
|
|
4175
|
+
const networkTotal = networkTotalCents / 100;
|
|
4165
4176
|
console.log(`\uD83D\uDCB0 [BUILD-DASHBOARD] ${blockchain} totals:`, {
|
|
4166
4177
|
balancesCount: networkBalances.length,
|
|
4167
4178
|
networkTotal,
|
|
@@ -4184,8 +4195,9 @@ function buildDashboardFromBalances(balances, blockchains, assetsMap) {
|
|
|
4184
4195
|
color: gasAsset?.color || assetInfo?.color || null,
|
|
4185
4196
|
totalNativeBalance
|
|
4186
4197
|
});
|
|
4187
|
-
|
|
4198
|
+
totalPortfolioValueCents += networkTotalCents;
|
|
4188
4199
|
}
|
|
4200
|
+
const totalPortfolioValue = totalPortfolioValueCents / 100;
|
|
4189
4201
|
dashboardData.networks = networksTemp.sort((a2, b2) => b2.totalValueUsd - a2.totalValueUsd);
|
|
4190
4202
|
dashboardData.totalValueUsd = totalPortfolioValue;
|
|
4191
4203
|
dashboardData.networkPercentages = dashboardData.networks.map((network) => ({
|
|
@@ -4193,6 +4205,26 @@ function buildDashboardFromBalances(balances, blockchains, assetsMap) {
|
|
|
4193
4205
|
percentage: totalPortfolioValue > 0 ? Number((network.totalValueUsd / totalPortfolioValue * 100).toFixed(2)) : 0
|
|
4194
4206
|
})).filter((entry) => entry.percentage > 0);
|
|
4195
4207
|
console.log(`[FAST DASHBOARD] ✅ Built dashboard: ${dashboardData.networks.length} networks, $${totalPortfolioValue.toFixed(2)} total`);
|
|
4208
|
+
const inputBalancesTotal = balances.reduce((sum, b2) => {
|
|
4209
|
+
const value = typeof b2.valueUsd === "string" ? parseFloat(b2.valueUsd) : b2.valueUsd || 0;
|
|
4210
|
+
return sum + (isNaN(value) ? 0 : value);
|
|
4211
|
+
}, 0);
|
|
4212
|
+
const difference = Math.abs(inputBalancesTotal - totalPortfolioValue);
|
|
4213
|
+
if (difference > 0.01) {
|
|
4214
|
+
console.error(`\uD83D\uDEA8 [BUILD-DASHBOARD] BALANCE MISMATCH DETECTED!`);
|
|
4215
|
+
console.error(` Input balances total: $${inputBalancesTotal.toFixed(2)} USD`);
|
|
4216
|
+
console.error(` Dashboard total: $${totalPortfolioValue.toFixed(2)} USD`);
|
|
4217
|
+
console.error(` Difference: $${difference.toFixed(2)} USD`);
|
|
4218
|
+
console.error(` This indicates lost balances during dashboard aggregation!`);
|
|
4219
|
+
console.error(` Network breakdown:`);
|
|
4220
|
+
dashboardData.networks.forEach((network) => {
|
|
4221
|
+
console.error(` ${network.networkId}: $${network.totalValueUsd.toFixed(2)}`);
|
|
4222
|
+
});
|
|
4223
|
+
} else if (difference > 0.001) {
|
|
4224
|
+
console.warn(`⚠️ [BUILD-DASHBOARD] Minor balance rounding difference: $${difference.toFixed(4)} USD`);
|
|
4225
|
+
} else {
|
|
4226
|
+
console.log(`✅ [BUILD-DASHBOARD] Balance reconciliation passed (diff: $${difference.toFixed(4)})`);
|
|
4227
|
+
}
|
|
4196
4228
|
return dashboardData;
|
|
4197
4229
|
}
|
|
4198
4230
|
|
|
@@ -4327,6 +4359,80 @@ function filterPubkeysForAsset(pubkeys, caip, caipToNetworkId7) {
|
|
|
4327
4359
|
|
|
4328
4360
|
// src/utils/portfolio-helpers.ts
|
|
4329
4361
|
var TAG9 = " | portfolio-helpers | ";
|
|
4362
|
+
var EXPLORER_BASE_URLS = {
|
|
4363
|
+
"eip155:1": {
|
|
4364
|
+
address: "https://etherscan.io/address/",
|
|
4365
|
+
tx: "https://etherscan.io/tx/"
|
|
4366
|
+
},
|
|
4367
|
+
"eip155:137": {
|
|
4368
|
+
address: "https://polygonscan.com/address/",
|
|
4369
|
+
tx: "https://polygonscan.com/tx/"
|
|
4370
|
+
},
|
|
4371
|
+
"eip155:8453": {
|
|
4372
|
+
address: "https://basescan.org/address/",
|
|
4373
|
+
tx: "https://basescan.org/tx/"
|
|
4374
|
+
},
|
|
4375
|
+
"eip155:56": {
|
|
4376
|
+
address: "https://bscscan.com/address/",
|
|
4377
|
+
tx: "https://bscscan.com/tx/"
|
|
4378
|
+
},
|
|
4379
|
+
"eip155:41454": {
|
|
4380
|
+
address: "https://explorer.monad.xyz/address/",
|
|
4381
|
+
tx: "https://explorer.monad.xyz/tx/"
|
|
4382
|
+
},
|
|
4383
|
+
"eip155:2868": {
|
|
4384
|
+
address: "https://app.hyperliquid.xyz/explorer/address/",
|
|
4385
|
+
tx: "https://app.hyperliquid.xyz/explorer/tx/"
|
|
4386
|
+
},
|
|
4387
|
+
"bip122:000000000019d6689c085ae165831e93": {
|
|
4388
|
+
address: "https://blockstream.info/address/",
|
|
4389
|
+
tx: "https://blockstream.info/tx/"
|
|
4390
|
+
},
|
|
4391
|
+
"bip122:12a765e31ffd4059bada1e25190f6e98": {
|
|
4392
|
+
address: "https://blockchair.com/litecoin/address/",
|
|
4393
|
+
tx: "https://blockchair.com/litecoin/transaction/"
|
|
4394
|
+
},
|
|
4395
|
+
"bip122:00000000001a91e3dace36e2be3bf030": {
|
|
4396
|
+
address: "https://dogechain.info/address/",
|
|
4397
|
+
tx: "https://dogechain.info/tx/"
|
|
4398
|
+
},
|
|
4399
|
+
"bip122:000000000000000000651ef99cb9fcbe": {
|
|
4400
|
+
address: "https://blockchair.com/bitcoin-cash/address/",
|
|
4401
|
+
tx: "https://blockchair.com/bitcoin-cash/transaction/"
|
|
4402
|
+
},
|
|
4403
|
+
"bip122:000007d91d1254d60e2dd1ae58038307": {
|
|
4404
|
+
address: "https://chainz.cryptoid.info/dash/address.dws?",
|
|
4405
|
+
tx: "https://chainz.cryptoid.info/dash/tx.dws?"
|
|
4406
|
+
},
|
|
4407
|
+
"bip122:4da631f2ac1bed857bd968c67c913978": {
|
|
4408
|
+
address: "https://digiexplorer.info/address/",
|
|
4409
|
+
tx: "https://digiexplorer.info/tx/"
|
|
4410
|
+
},
|
|
4411
|
+
"bip122:00040fe8ec8471911baa1db1266ea15d": {
|
|
4412
|
+
address: "https://explorer.zcha.in/accounts/",
|
|
4413
|
+
tx: "https://explorer.zcha.in/transactions/"
|
|
4414
|
+
},
|
|
4415
|
+
"cosmos:cosmoshub-4": {
|
|
4416
|
+
address: "https://www.mintscan.io/cosmos/address/",
|
|
4417
|
+
tx: "https://www.mintscan.io/cosmos/tx/"
|
|
4418
|
+
},
|
|
4419
|
+
"cosmos:osmosis-1": {
|
|
4420
|
+
address: "https://www.mintscan.io/osmosis/address/",
|
|
4421
|
+
tx: "https://www.mintscan.io/osmosis/tx/"
|
|
4422
|
+
},
|
|
4423
|
+
"cosmos:thorchain-mainnet-v1": {
|
|
4424
|
+
address: "https://thorchain.net/address/",
|
|
4425
|
+
tx: "https://thorchain.net/tx/"
|
|
4426
|
+
},
|
|
4427
|
+
"cosmos:mayachain-mainnet-v1": {
|
|
4428
|
+
address: "https://www.mayascan.org/address/",
|
|
4429
|
+
tx: "https://www.mayascan.org/tx/"
|
|
4430
|
+
},
|
|
4431
|
+
"ripple:4109c6f2045fc7eff4cde8f9905d19c2": {
|
|
4432
|
+
address: "https://xrpscan.com/account/",
|
|
4433
|
+
tx: "https://xrpscan.com/tx/"
|
|
4434
|
+
}
|
|
4435
|
+
};
|
|
4330
4436
|
function isCacheDataValid(portfolioData) {
|
|
4331
4437
|
if (!portfolioData.networks || !Array.isArray(portfolioData.networks)) {
|
|
4332
4438
|
console.warn("[CACHE VALIDATION] Networks is not an array");
|
|
@@ -4465,14 +4571,37 @@ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
|
|
|
4465
4571
|
console.warn(tag, `Missing AssetInfo for CAIP: "${balance.caip}" - skipping this balance`);
|
|
4466
4572
|
continue;
|
|
4467
4573
|
}
|
|
4574
|
+
if (typeof balance.valueUsd === "string") {
|
|
4575
|
+
balance.valueUsd = parseFloat(balance.valueUsd) || 0;
|
|
4576
|
+
} else if (typeof balance.valueUsd !== "number") {
|
|
4577
|
+
balance.valueUsd = 0;
|
|
4578
|
+
}
|
|
4579
|
+
if (typeof balance.balance === "string") {
|
|
4580
|
+
balance.balance = balance.balance;
|
|
4581
|
+
}
|
|
4582
|
+
if (typeof balance.priceUsd === "string") {
|
|
4583
|
+
balance.priceUsd = parseFloat(balance.priceUsd) || 0;
|
|
4584
|
+
} else if (typeof balance.priceUsd !== "number") {
|
|
4585
|
+
balance.priceUsd = 0;
|
|
4586
|
+
}
|
|
4587
|
+
const networkId = caipToNetworkId7(balance.caip);
|
|
4588
|
+
const explorerUrls = EXPLORER_BASE_URLS[networkId];
|
|
4589
|
+
const explorerAddressLink = explorerUrls && balance.pubkey ? explorerUrls.address + balance.pubkey : undefined;
|
|
4590
|
+
const explorerTxLink = explorerUrls?.tx;
|
|
4468
4591
|
Object.assign(balance, assetInfo, {
|
|
4469
4592
|
type: balance.type || assetInfo.type,
|
|
4470
4593
|
isNative: balance.isNative ?? assetInfo.isNative,
|
|
4471
|
-
networkId
|
|
4594
|
+
networkId,
|
|
4472
4595
|
icon: assetInfo.icon || "https://pioneers.dev/coins/etherum.png",
|
|
4473
4596
|
identifier: `${balance.caip}:${balance.pubkey}`,
|
|
4474
4597
|
updated: Date.now(),
|
|
4475
|
-
color: assetInfo.color
|
|
4598
|
+
color: assetInfo.color,
|
|
4599
|
+
decimals: assetInfo.decimals || balance.decimals || 8,
|
|
4600
|
+
explorerAddressLink,
|
|
4601
|
+
explorerTxLink,
|
|
4602
|
+
explorer: explorerUrls?.address,
|
|
4603
|
+
valueUsd: balance.valueUsd,
|
|
4604
|
+
priceUsd: balance.priceUsd
|
|
4476
4605
|
});
|
|
4477
4606
|
enrichedBalances.push(balance);
|
|
4478
4607
|
}
|
|
@@ -5007,6 +5136,20 @@ class SDK {
|
|
|
5007
5136
|
this.balances[index] = balance;
|
|
5008
5137
|
}
|
|
5009
5138
|
this.events.emit("BALANCE_UPDATE", balance);
|
|
5139
|
+
console.log(tag7, "\uD83D\uDD04 Rebuilding dashboard after balance update...");
|
|
5140
|
+
const previousTotal = this.dashboard?.totalValueUsd || 0;
|
|
5141
|
+
this.dashboard = this.buildDashboardFromBalances();
|
|
5142
|
+
const newTotal = this.dashboard?.totalValueUsd || 0;
|
|
5143
|
+
if (Math.abs(newTotal - previousTotal) > 0.01) {
|
|
5144
|
+
console.log(tag7, `\uD83D\uDCB0 Portfolio value changed: $${previousTotal.toFixed(2)} → $${newTotal.toFixed(2)}`);
|
|
5145
|
+
}
|
|
5146
|
+
this.events.emit("DASHBOARD_UPDATE", {
|
|
5147
|
+
dashboard: this.dashboard,
|
|
5148
|
+
trigger: "balance_update",
|
|
5149
|
+
affectedAsset: balance.caip,
|
|
5150
|
+
previousTotal,
|
|
5151
|
+
newTotal
|
|
5152
|
+
});
|
|
5010
5153
|
} catch (e) {
|
|
5011
5154
|
console.error(tag7, "Error processing balance update:", e);
|
|
5012
5155
|
}
|
|
@@ -5884,7 +6027,7 @@ class SDK {
|
|
|
5884
6027
|
const pubkeysForNetwork = findPubkeysForNetwork(this.pubkeys, asset.networkId);
|
|
5885
6028
|
console.log(tag6, `✅ Validated: Found ${pubkeysForNetwork.length} addresses for ${asset.networkId}`);
|
|
5886
6029
|
const freshPriceUsd = await fetchMarketPrice(this.pioneer, asset.caip);
|
|
5887
|
-
let assetInfo = resolveAssetInfo(this.assetsMap,
|
|
6030
|
+
let assetInfo = resolveAssetInfo(this.assetsMap, this.assets, asset);
|
|
5888
6031
|
const matchingBalances = this.balances.filter((b2) => b2.caip === asset.caip);
|
|
5889
6032
|
if (matchingBalances.length > 0) {
|
|
5890
6033
|
const priceValue = extractPriceFromBalances(matchingBalances);
|
|
@@ -5900,14 +6043,47 @@ class SDK {
|
|
|
5900
6043
|
assetInfo.balance = totalBalance.toString();
|
|
5901
6044
|
assetInfo.valueUsd = totalValueUsd.toFixed(2);
|
|
5902
6045
|
}
|
|
6046
|
+
const EXPLORER_BASE_URLS2 = {
|
|
6047
|
+
"eip155:1": { address: "https://etherscan.io/address/", tx: "https://etherscan.io/tx/" },
|
|
6048
|
+
"eip155:137": { address: "https://polygonscan.com/address/", tx: "https://polygonscan.com/tx/" },
|
|
6049
|
+
"eip155:8453": { address: "https://basescan.org/address/", tx: "https://basescan.org/tx/" },
|
|
6050
|
+
"eip155:56": { address: "https://bscscan.com/address/", tx: "https://bscscan.com/tx/" },
|
|
6051
|
+
"eip155:41454": { address: "https://explorer.monad.xyz/address/", tx: "https://explorer.monad.xyz/tx/" },
|
|
6052
|
+
"eip155:2868": { address: "https://app.hyperliquid.xyz/explorer/address/", tx: "https://app.hyperliquid.xyz/explorer/tx/" },
|
|
6053
|
+
"bip122:000000000019d6689c085ae165831e93": { address: "https://blockstream.info/address/", tx: "https://blockstream.info/tx/" },
|
|
6054
|
+
"bip122:12a765e31ffd4059bada1e25190f6e98": { address: "https://blockchair.com/litecoin/address/", tx: "https://blockchair.com/litecoin/transaction/" },
|
|
6055
|
+
"bip122:00000000001a91e3dace36e2be3bf030": { address: "https://dogechain.info/address/", tx: "https://dogechain.info/tx/" },
|
|
6056
|
+
"bip122:000000000000000000651ef99cb9fcbe": { address: "https://blockchair.com/bitcoin-cash/address/", tx: "https://blockchair.com/bitcoin-cash/transaction/" },
|
|
6057
|
+
"bip122:000007d91d1254d60e2dd1ae58038307": { address: "https://chainz.cryptoid.info/dash/address.dws?", tx: "https://chainz.cryptoid.info/dash/tx.dws?" },
|
|
6058
|
+
"bip122:4da631f2ac1bed857bd968c67c913978": { address: "https://digiexplorer.info/address/", tx: "https://digiexplorer.info/tx/" },
|
|
6059
|
+
"bip122:00040fe8ec8471911baa1db1266ea15d": { address: "https://explorer.zcha.in/accounts/", tx: "https://explorer.zcha.in/transactions/" },
|
|
6060
|
+
"cosmos:cosmoshub-4": { address: "https://www.mintscan.io/cosmos/address/", tx: "https://www.mintscan.io/cosmos/tx/" },
|
|
6061
|
+
"cosmos:osmosis-1": { address: "https://www.mintscan.io/osmosis/address/", tx: "https://www.mintscan.io/osmosis/tx/" },
|
|
6062
|
+
"cosmos:thorchain-mainnet-v1": { address: "https://thorchain.net/address/", tx: "https://thorchain.net/tx/" },
|
|
6063
|
+
"cosmos:mayachain-mainnet-v1": { address: "https://www.mayascan.org/address/", tx: "https://www.mayascan.org/tx/" },
|
|
6064
|
+
"ripple:4109c6f2045fc7eff4cde8f9905d19c2": { address: "https://xrpscan.com/account/", tx: "https://xrpscan.com/tx/" }
|
|
6065
|
+
};
|
|
6066
|
+
const networkId = caipToNetworkId7(asset.caip);
|
|
6067
|
+
const explorerUrls = EXPLORER_BASE_URLS2[networkId];
|
|
6068
|
+
const firstPubkey = pubkeysForNetwork && pubkeysForNetwork.length > 0 ? pubkeysForNetwork[0].address || pubkeysForNetwork[0].pubkey : null;
|
|
6069
|
+
if (explorerUrls && firstPubkey) {
|
|
6070
|
+
assetInfo.explorerAddressLink = explorerUrls.address + firstPubkey;
|
|
6071
|
+
assetInfo.explorerTxLink = explorerUrls.tx;
|
|
6072
|
+
assetInfo.explorer = explorerUrls.address;
|
|
6073
|
+
}
|
|
5903
6074
|
const assetBalances = this.balances.filter((b2) => b2.caip === asset.caip);
|
|
5904
6075
|
const assetPubkeys = filterPubkeysForAsset(this.pubkeys, asset.caip, caipToNetworkId7);
|
|
6076
|
+
const criticalFields = ["decimals", "precision", "explorerAddressLink", "explorerTxLink", "explorer"];
|
|
5905
6077
|
const finalAssetContext = {
|
|
5906
6078
|
...assetInfo,
|
|
5907
|
-
...asset,
|
|
6079
|
+
...Object.fromEntries(Object.entries(asset).filter(([k, v2]) => v2 !== undefined && !criticalFields.includes(k))),
|
|
5908
6080
|
pubkeys: assetPubkeys,
|
|
5909
6081
|
balances: assetBalances
|
|
5910
6082
|
};
|
|
6083
|
+
if (assetInfo.decimals !== undefined) {
|
|
6084
|
+
finalAssetContext.decimals = assetInfo.decimals;
|
|
6085
|
+
finalAssetContext.precision = assetInfo.decimals;
|
|
6086
|
+
}
|
|
5911
6087
|
if ((!asset.priceUsd || asset.priceUsd === 0) && assetInfo.priceUsd && assetInfo.priceUsd > 0) {
|
|
5912
6088
|
finalAssetContext.priceUsd = assetInfo.priceUsd;
|
|
5913
6089
|
}
|
|
@@ -5916,15 +6092,22 @@ class SDK {
|
|
|
5916
6092
|
}
|
|
5917
6093
|
this.assetContext = finalAssetContext;
|
|
5918
6094
|
if (asset.isToken || asset.type === "token" || assetInfo.isToken || assetInfo.type === "token") {
|
|
5919
|
-
const
|
|
5920
|
-
|
|
5921
|
-
|
|
6095
|
+
const networkId2 = asset.networkId || assetInfo.networkId;
|
|
6096
|
+
try {
|
|
6097
|
+
const nativeCaip = networkIdToCaip2(networkId2);
|
|
6098
|
+
const nativeAssetInfo = assetData2[nativeCaip];
|
|
6099
|
+
const nativeSymbol = nativeAssetInfo?.symbol || "GAS";
|
|
6100
|
+
this.assetContext.nativeSymbol = nativeSymbol;
|
|
5922
6101
|
const nativeBalance = this.balances.find((b2) => b2.caip === nativeCaip);
|
|
5923
6102
|
if (nativeBalance) {
|
|
5924
6103
|
this.assetContext.nativeBalance = nativeBalance.balance || "0";
|
|
5925
6104
|
} else {
|
|
5926
6105
|
this.assetContext.nativeBalance = "0";
|
|
5927
6106
|
}
|
|
6107
|
+
} catch (error) {
|
|
6108
|
+
console.error(`[Pioneer SDK] Unable to get native asset for networkId ${networkId2}:`, error);
|
|
6109
|
+
this.assetContext.nativeSymbol = "GAS";
|
|
6110
|
+
this.assetContext.nativeBalance = "0";
|
|
5928
6111
|
}
|
|
5929
6112
|
}
|
|
5930
6113
|
if (asset.caip) {
|
|
@@ -5933,8 +6116,8 @@ class SDK {
|
|
|
5933
6116
|
this.blockchainContext = asset.networkId;
|
|
5934
6117
|
}
|
|
5935
6118
|
if (assetPubkeys && assetPubkeys.length > 0) {
|
|
5936
|
-
const
|
|
5937
|
-
const currentContextValid = this.pubkeyContext?.networks?.includes(
|
|
6119
|
+
const networkId2 = caipToNetworkId7(asset.caip || asset.networkId);
|
|
6120
|
+
const currentContextValid = this.pubkeyContext?.networks?.includes(networkId2);
|
|
5938
6121
|
if (!this.pubkeyContext || !currentContextValid) {
|
|
5939
6122
|
this.pubkeyContext = assetPubkeys[0];
|
|
5940
6123
|
console.log(tag6, "Auto-set pubkey context for network:", this.pubkeyContext.address || this.pubkeyContext.pubkey);
|
|
@@ -5985,7 +6168,7 @@ class SDK {
|
|
|
5985
6168
|
if (!pubkey)
|
|
5986
6169
|
throw Error("Invalid network! missing pubkey for network! " + asset.networkId);
|
|
5987
6170
|
const freshPriceUsd = await fetchMarketPrice(this.pioneer, asset.caip);
|
|
5988
|
-
let assetInfo = resolveAssetInfo(this.assetsMap,
|
|
6171
|
+
let assetInfo = resolveAssetInfo(this.assetsMap, this.assets, asset);
|
|
5989
6172
|
const matchingBalances = this.balances.filter((b2) => b2.caip === asset.caip);
|
|
5990
6173
|
if (matchingBalances.length > 0) {
|
|
5991
6174
|
const priceValue = extractPriceFromBalances(matchingBalances);
|
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.33",
|
|
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.10",
|
|
8
|
+
"@pioneer-platform/pioneer-client": "^9.10.16",
|
|
9
|
+
"@pioneer-platform/pioneer-coins": "^9.11.10",
|
|
10
|
+
"@pioneer-platform/pioneer-discovery": "^8.15.33",
|
|
11
|
+
"@pioneer-platform/pioneer-events": "^8.12.5",
|
|
12
12
|
"coinselect": "^3.1.13",
|
|
13
13
|
"eventemitter3": "^5.0.1",
|
|
14
14
|
"neotraverse": "^0.6.8",
|
package/src/fees/index.ts
CHANGED
|
@@ -48,6 +48,7 @@ function getNetworkName(networkId: string): string {
|
|
|
48
48
|
'bip122:00000000001a91e3dace36e2be3bf030': 'Dogecoin',
|
|
49
49
|
'bip122:000000000000000000651ef99cb9fcbe': 'Bitcoin Cash',
|
|
50
50
|
'bip122:000007d91d1254d60e2dd1ae58038307': 'Dash',
|
|
51
|
+
'bip122:00040fe8ec8471911baa1db1266ea15d': 'Zcash',
|
|
51
52
|
'bip122:4da631f2ac1bed857bd968c67c913978': 'DigiByte',
|
|
52
53
|
'eip155:1': 'Ethereum',
|
|
53
54
|
'eip155:56': 'BNB Smart Chain',
|
package/src/index.ts
CHANGED
|
@@ -552,6 +552,25 @@ export class SDK {
|
|
|
552
552
|
|
|
553
553
|
// Emit SDK event for UI updates
|
|
554
554
|
this.events.emit('BALANCE_UPDATE', balance);
|
|
555
|
+
|
|
556
|
+
// CRITICAL FIX: Rebuild dashboard when balance changes
|
|
557
|
+
console.log(tag, '🔄 Rebuilding dashboard after balance update...');
|
|
558
|
+
const previousTotal = this.dashboard?.totalValueUsd || 0;
|
|
559
|
+
this.dashboard = this.buildDashboardFromBalances();
|
|
560
|
+
const newTotal = this.dashboard?.totalValueUsd || 0;
|
|
561
|
+
|
|
562
|
+
if (Math.abs(newTotal - previousTotal) > 0.01) {
|
|
563
|
+
console.log(tag, `💰 Portfolio value changed: $${previousTotal.toFixed(2)} → $${newTotal.toFixed(2)}`);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Emit dashboard update event for real-time UI updates
|
|
567
|
+
this.events.emit('DASHBOARD_UPDATE', {
|
|
568
|
+
dashboard: this.dashboard,
|
|
569
|
+
trigger: 'balance_update',
|
|
570
|
+
affectedAsset: balance.caip,
|
|
571
|
+
previousTotal,
|
|
572
|
+
newTotal
|
|
573
|
+
});
|
|
555
574
|
} catch (e) {
|
|
556
575
|
console.error(tag, 'Error processing balance update:', e);
|
|
557
576
|
}
|
|
@@ -1813,7 +1832,7 @@ export class SDK {
|
|
|
1813
1832
|
const freshPriceUsd = await fetchMarketPrice(this.pioneer, asset.caip);
|
|
1814
1833
|
|
|
1815
1834
|
// Resolve asset info from multiple sources
|
|
1816
|
-
let assetInfo = resolveAssetInfo(this.assetsMap,
|
|
1835
|
+
let assetInfo = resolveAssetInfo(this.assetsMap, this.assets, asset);
|
|
1817
1836
|
|
|
1818
1837
|
// Get matching balances
|
|
1819
1838
|
const matchingBalances = this.balances.filter((b) => b.caip === asset.caip);
|
|
@@ -1837,18 +1856,63 @@ export class SDK {
|
|
|
1837
1856
|
assetInfo.valueUsd = totalValueUsd.toFixed(2);
|
|
1838
1857
|
}
|
|
1839
1858
|
|
|
1859
|
+
// CAIP-based explorer URL mapping
|
|
1860
|
+
const EXPLORER_BASE_URLS: Record<string, { address: string; tx: string }> = {
|
|
1861
|
+
'eip155:1': { address: 'https://etherscan.io/address/', tx: 'https://etherscan.io/tx/' },
|
|
1862
|
+
'eip155:137': { address: 'https://polygonscan.com/address/', tx: 'https://polygonscan.com/tx/' },
|
|
1863
|
+
'eip155:8453': { address: 'https://basescan.org/address/', tx: 'https://basescan.org/tx/' },
|
|
1864
|
+
'eip155:56': { address: 'https://bscscan.com/address/', tx: 'https://bscscan.com/tx/' },
|
|
1865
|
+
'eip155:41454': { address: 'https://explorer.monad.xyz/address/', tx: 'https://explorer.monad.xyz/tx/' },
|
|
1866
|
+
'eip155:2868': { address: 'https://app.hyperliquid.xyz/explorer/address/', tx: 'https://app.hyperliquid.xyz/explorer/tx/' },
|
|
1867
|
+
'bip122:000000000019d6689c085ae165831e93': { address: 'https://blockstream.info/address/', tx: 'https://blockstream.info/tx/' },
|
|
1868
|
+
'bip122:12a765e31ffd4059bada1e25190f6e98': { address: 'https://blockchair.com/litecoin/address/', tx: 'https://blockchair.com/litecoin/transaction/' },
|
|
1869
|
+
'bip122:00000000001a91e3dace36e2be3bf030': { address: 'https://dogechain.info/address/', tx: 'https://dogechain.info/tx/' },
|
|
1870
|
+
'bip122:000000000000000000651ef99cb9fcbe': { address: 'https://blockchair.com/bitcoin-cash/address/', tx: 'https://blockchair.com/bitcoin-cash/transaction/' },
|
|
1871
|
+
'bip122:000007d91d1254d60e2dd1ae58038307': { address: 'https://chainz.cryptoid.info/dash/address.dws?', tx: 'https://chainz.cryptoid.info/dash/tx.dws?' },
|
|
1872
|
+
'bip122:4da631f2ac1bed857bd968c67c913978': { address: 'https://digiexplorer.info/address/', tx: 'https://digiexplorer.info/tx/' },
|
|
1873
|
+
'bip122:00040fe8ec8471911baa1db1266ea15d': { address: 'https://explorer.zcha.in/accounts/', tx: 'https://explorer.zcha.in/transactions/' },
|
|
1874
|
+
'cosmos:cosmoshub-4': { address: 'https://www.mintscan.io/cosmos/address/', tx: 'https://www.mintscan.io/cosmos/tx/' },
|
|
1875
|
+
'cosmos:osmosis-1': { address: 'https://www.mintscan.io/osmosis/address/', tx: 'https://www.mintscan.io/osmosis/tx/' },
|
|
1876
|
+
'cosmos:thorchain-mainnet-v1': { address: 'https://thorchain.net/address/', tx: 'https://thorchain.net/tx/' },
|
|
1877
|
+
'cosmos:mayachain-mainnet-v1': { address: 'https://www.mayascan.org/address/', tx: 'https://www.mayascan.org/tx/' },
|
|
1878
|
+
'ripple:4109c6f2045fc7eff4cde8f9905d19c2': { address: 'https://xrpscan.com/account/', tx: 'https://xrpscan.com/tx/' },
|
|
1879
|
+
};
|
|
1880
|
+
|
|
1881
|
+
// Generate explorer links for this asset
|
|
1882
|
+
const networkId = caipToNetworkId(asset.caip);
|
|
1883
|
+
const explorerUrls = EXPLORER_BASE_URLS[networkId];
|
|
1884
|
+
|
|
1885
|
+
// Get the first pubkey for this asset to generate explorer link
|
|
1886
|
+
const firstPubkey = pubkeysForNetwork && pubkeysForNetwork.length > 0
|
|
1887
|
+
? (pubkeysForNetwork[0].address || pubkeysForNetwork[0].pubkey)
|
|
1888
|
+
: null;
|
|
1889
|
+
|
|
1890
|
+
if (explorerUrls && firstPubkey) {
|
|
1891
|
+
assetInfo.explorerAddressLink = explorerUrls.address + firstPubkey;
|
|
1892
|
+
assetInfo.explorerTxLink = explorerUrls.tx;
|
|
1893
|
+
assetInfo.explorer = explorerUrls.address;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1840
1896
|
// Filter balances and pubkeys for this asset
|
|
1841
1897
|
const assetBalances = this.balances.filter((b) => b.caip === asset.caip);
|
|
1842
1898
|
const assetPubkeys = filterPubkeysForAsset(this.pubkeys, asset.caip, caipToNetworkId);
|
|
1843
1899
|
|
|
1844
1900
|
// Combine the user-provided asset with any additional info we have
|
|
1901
|
+
// CRITICAL: Preserve decimals, precision, and explorer links from assetInfo
|
|
1902
|
+
const criticalFields = ['decimals', 'precision', 'explorerAddressLink', 'explorerTxLink', 'explorer'];
|
|
1845
1903
|
const finalAssetContext = {
|
|
1846
1904
|
...assetInfo,
|
|
1847
|
-
...asset,
|
|
1905
|
+
...Object.fromEntries(Object.entries(asset).filter(([k, v]) => v !== undefined && !criticalFields.includes(k))),
|
|
1848
1906
|
pubkeys: assetPubkeys,
|
|
1849
1907
|
balances: assetBalances,
|
|
1850
1908
|
};
|
|
1851
1909
|
|
|
1910
|
+
// Ensure precision matches decimals from assetInfo (for backward compatibility)
|
|
1911
|
+
if (assetInfo.decimals !== undefined) {
|
|
1912
|
+
finalAssetContext.decimals = assetInfo.decimals;
|
|
1913
|
+
finalAssetContext.precision = assetInfo.decimals;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1852
1916
|
// If input has priceUsd of 0 but we found a valid price, use the found price
|
|
1853
1917
|
if ((!asset.priceUsd || asset.priceUsd === 0) && assetInfo.priceUsd && assetInfo.priceUsd > 0) {
|
|
1854
1918
|
finalAssetContext.priceUsd = assetInfo.priceUsd;
|
|
@@ -1868,19 +1932,32 @@ export class SDK {
|
|
|
1868
1932
|
assetInfo.isToken ||
|
|
1869
1933
|
assetInfo.type === 'token'
|
|
1870
1934
|
) {
|
|
1871
|
-
// Get the native asset for this network
|
|
1935
|
+
// Get the native asset for this network using the proper CAIP utility
|
|
1872
1936
|
const networkId = asset.networkId || assetInfo.networkId;
|
|
1873
|
-
// Set the native symbol
|
|
1874
|
-
this.assetContext.nativeSymbol = nativeSymbol;
|
|
1875
1937
|
|
|
1876
|
-
|
|
1877
|
-
|
|
1938
|
+
try {
|
|
1939
|
+
// Use networkIdToCaip to get the native asset CAIP
|
|
1940
|
+
const nativeCaip = networkIdToCaip(networkId);
|
|
1941
|
+
|
|
1942
|
+
// Look up the native asset info from assetData
|
|
1943
|
+
const nativeAssetInfo = assetData[nativeCaip];
|
|
1944
|
+
const nativeSymbol = nativeAssetInfo?.symbol || 'GAS';
|
|
1945
|
+
|
|
1946
|
+
// Set the native symbol
|
|
1947
|
+
this.assetContext.nativeSymbol = nativeSymbol;
|
|
1948
|
+
|
|
1949
|
+
// Try to find the native balance
|
|
1878
1950
|
const nativeBalance = this.balances.find((b) => b.caip === nativeCaip);
|
|
1879
1951
|
if (nativeBalance) {
|
|
1880
1952
|
this.assetContext.nativeBalance = nativeBalance.balance || '0';
|
|
1881
1953
|
} else {
|
|
1882
1954
|
this.assetContext.nativeBalance = '0';
|
|
1883
1955
|
}
|
|
1956
|
+
} catch (error) {
|
|
1957
|
+
console.error(`[Pioneer SDK] Unable to get native asset for networkId ${networkId}:`, error);
|
|
1958
|
+
// Fallback to 'GAS' if we can't determine the native asset
|
|
1959
|
+
this.assetContext.nativeSymbol = 'GAS';
|
|
1960
|
+
this.assetContext.nativeBalance = '0';
|
|
1884
1961
|
}
|
|
1885
1962
|
}
|
|
1886
1963
|
|
|
@@ -1988,7 +2065,7 @@ export class SDK {
|
|
|
1988
2065
|
const freshPriceUsd = await fetchMarketPrice(this.pioneer, asset.caip);
|
|
1989
2066
|
|
|
1990
2067
|
// Resolve asset info from multiple sources
|
|
1991
|
-
let assetInfo = resolveAssetInfo(this.assetsMap,
|
|
2068
|
+
let assetInfo = resolveAssetInfo(this.assetsMap, this.assets, asset);
|
|
1992
2069
|
|
|
1993
2070
|
// Get matching balances
|
|
1994
2071
|
const matchingBalances = this.balances.filter((b) => b.caip === asset.caip);
|
|
@@ -287,9 +287,26 @@ export async function createUnsignedUxtoTx(
|
|
|
287
287
|
}
|
|
288
288
|
} catch (error: any) {
|
|
289
289
|
console.error(`${tag}: Failed to get fee rates from Pioneer API:`, error.message || error);
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
|
|
291
|
+
// Fallback to hardcoded default fees for known networks
|
|
292
|
+
const defaultFees: Record<string, { slow: number; average: number; fast: number; fastest: number }> = {
|
|
293
|
+
'bip122:000000000019d6689c085ae165831e93': { slow: 3, average: 5, fast: 10, fastest: 15 }, // BTC
|
|
294
|
+
'bip122:12a765e31ffd4059bada1e25190f6e98': { slow: 2, average: 3, fast: 5, fastest: 10 }, // LTC
|
|
295
|
+
'bip122:00000000001a91e3dace36e2be3bf030': { slow: 1, average: 1, fast: 2, fastest: 3 }, // DOGE
|
|
296
|
+
'bip122:000000000000000000651ef99cb9fcbe': { slow: 1, average: 1, fast: 2, fastest: 3 }, // BCH
|
|
297
|
+
'bip122:000007d91d1254d60e2dd1ae58038307': { slow: 1, average: 1, fast: 2, fastest: 3 }, // DASH
|
|
298
|
+
'bip122:4da631f2ac1bed857bd968c67c913978': { slow: 75, average: 80, fast: 100, fastest: 120 }, // DGB
|
|
299
|
+
'bip122:00040fe8ec8471911baa1db1266ea15d': { slow: 1, average: 1, fast: 2, fastest: 3 }, // ZEC
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
if (defaultFees[networkId]) {
|
|
303
|
+
console.warn(`${tag}: Using default fee rates for ${networkId}`);
|
|
304
|
+
feeRateFromNode = defaultFees[networkId];
|
|
305
|
+
} else {
|
|
306
|
+
throw new Error(
|
|
307
|
+
`Unable to get fee rate for network ${networkId}: ${error.message || 'API unavailable'}`,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
293
310
|
}
|
|
294
311
|
}
|
|
295
312
|
|