@pioneer-platform/pioneer-sdk 8.15.33 → 8.15.38
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 +70 -5
- package/dist/index.es.js +70 -5
- package/dist/index.js +70 -5
- package/package.json +6 -6
- package/src/charts/evm.ts +46 -3
- package/src/charts/maya.ts +24 -2
- package/src/index.ts +36 -3
- package/src/utils/portfolio-helpers.ts +14 -2
package/dist/index.cjs
CHANGED
|
@@ -436,6 +436,17 @@ function processPortfolioBalance(balance, primaryAddress, context, blockchains)
|
|
|
436
436
|
console.log(tag2, `Calculated price from value/balance: ${calculatedPrice} for ${balance.caip}`);
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
|
+
const decimals = assetInfo?.decimals ?? assetInfo?.decimal ?? balance.decimals ?? balance.decimal;
|
|
440
|
+
if (decimals === undefined || decimals === null) {
|
|
441
|
+
throw new Error(`CRITICAL: Asset ${balance.caip} (${assetInfo?.symbol || balance.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({
|
|
442
|
+
caip: balance.caip,
|
|
443
|
+
symbol: assetInfo?.symbol || balance.symbol,
|
|
444
|
+
hasAssetInfoDecimals: !!assetInfo?.decimals,
|
|
445
|
+
hasAssetInfoDecimal: !!assetInfo?.decimal,
|
|
446
|
+
hasBalanceDecimals: !!balance.decimals,
|
|
447
|
+
hasBalanceDecimal: !!balance.decimal
|
|
448
|
+
})}`);
|
|
449
|
+
}
|
|
439
450
|
const chartBalance = {
|
|
440
451
|
context,
|
|
441
452
|
chart: "pioneer",
|
|
@@ -452,7 +463,9 @@ function processPortfolioBalance(balance, primaryAddress, context, blockchains)
|
|
|
452
463
|
symbol: assetInfo?.symbol || balance.symbol || "UNK",
|
|
453
464
|
type: balanceType,
|
|
454
465
|
token: isToken,
|
|
455
|
-
decimal:
|
|
466
|
+
decimal: decimals,
|
|
467
|
+
decimals,
|
|
468
|
+
precision: decimals,
|
|
456
469
|
balance: balance.balance.toString(),
|
|
457
470
|
price: calculatedPrice,
|
|
458
471
|
priceUsd: calculatedPrice,
|
|
@@ -483,6 +496,17 @@ function processPortfolioToken(token, primaryAddress, context, blockchains) {
|
|
|
483
496
|
}
|
|
484
497
|
const tokenAssetInfo = hydrateAssetData(token.assetCaip);
|
|
485
498
|
const tokenPubkey = token.pubkey || primaryAddress;
|
|
499
|
+
const tokenDecimals = tokenAssetInfo?.decimals ?? tokenAssetInfo?.decimal ?? token.token?.decimals ?? token.token?.decimal;
|
|
500
|
+
if (tokenDecimals === undefined || tokenDecimals === null) {
|
|
501
|
+
throw new Error(`CRITICAL: Token ${token.assetCaip} (${tokenAssetInfo?.symbol || token.token?.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Token data: ${JSON.stringify({
|
|
502
|
+
caip: token.assetCaip,
|
|
503
|
+
symbol: tokenAssetInfo?.symbol || token.token?.symbol,
|
|
504
|
+
hasAssetInfoDecimals: !!tokenAssetInfo?.decimals,
|
|
505
|
+
hasAssetInfoDecimal: !!tokenAssetInfo?.decimal,
|
|
506
|
+
hasTokenDecimals: !!token.token?.decimals,
|
|
507
|
+
hasTokenDecimal: !!token.token?.decimal
|
|
508
|
+
})}`);
|
|
509
|
+
}
|
|
486
510
|
const chartBalance = {
|
|
487
511
|
context,
|
|
488
512
|
chart: "pioneer",
|
|
@@ -498,7 +522,9 @@ function processPortfolioToken(token, primaryAddress, context, blockchains) {
|
|
|
498
522
|
symbol: tokenAssetInfo?.symbol || token.token?.symbol || "UNK",
|
|
499
523
|
type: tokenAssetInfo?.type || "token",
|
|
500
524
|
token: true,
|
|
501
|
-
decimal:
|
|
525
|
+
decimal: tokenDecimals,
|
|
526
|
+
decimals: tokenDecimals,
|
|
527
|
+
precision: tokenDecimals,
|
|
502
528
|
balance: token.token?.balance?.toString() || "0",
|
|
503
529
|
priceUsd: token.token?.price || 0,
|
|
504
530
|
valueUsd: token.token?.balanceUSD || 0,
|
|
@@ -605,6 +631,17 @@ async function getMayaCharts(params, existingBalances) {
|
|
|
605
631
|
}
|
|
606
632
|
const mayaAssetInfo = hydrateAssetData(mayaBalance.caip);
|
|
607
633
|
const isToken = mayaBalance.caip.includes("/denom:") && !mayaBalance.caip.endsWith("/denom:cacao");
|
|
634
|
+
const decimals = mayaAssetInfo?.decimals ?? mayaAssetInfo?.decimal ?? mayaBalance.decimals ?? mayaBalance.decimal;
|
|
635
|
+
if (decimals === undefined || decimals === null) {
|
|
636
|
+
throw new Error(`CRITICAL: Asset ${mayaBalance.caip} (${mayaAssetInfo?.symbol || "MAYA"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({
|
|
637
|
+
caip: mayaBalance.caip,
|
|
638
|
+
symbol: mayaAssetInfo?.symbol,
|
|
639
|
+
hasAssetInfoDecimals: !!mayaAssetInfo?.decimals,
|
|
640
|
+
hasAssetInfoDecimal: !!mayaAssetInfo?.decimal,
|
|
641
|
+
hasBalanceDecimals: !!mayaBalance.decimals,
|
|
642
|
+
hasBalanceDecimal: !!mayaBalance.decimal
|
|
643
|
+
})}`);
|
|
644
|
+
}
|
|
608
645
|
const mayaTokenBalance = {
|
|
609
646
|
context,
|
|
610
647
|
chart: "pioneer",
|
|
@@ -620,7 +657,9 @@ async function getMayaCharts(params, existingBalances) {
|
|
|
620
657
|
symbol: mayaAssetInfo?.symbol || "MAYA",
|
|
621
658
|
type: mayaAssetInfo?.type || "token",
|
|
622
659
|
token: isToken,
|
|
623
|
-
decimal:
|
|
660
|
+
decimal: decimals,
|
|
661
|
+
decimals,
|
|
662
|
+
precision: decimals,
|
|
624
663
|
balance: mayaBalance.balance?.toString() || "0",
|
|
625
664
|
priceUsd: parseFloat(mayaBalance.priceUsd) || 0,
|
|
626
665
|
valueUsd: parseFloat(mayaBalance.valueUsd) || 0,
|
|
@@ -4404,6 +4443,10 @@ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
|
|
|
4404
4443
|
const explorerUrls = EXPLORER_BASE_URLS[networkId];
|
|
4405
4444
|
const explorerAddressLink = explorerUrls && balance.pubkey ? explorerUrls.address + balance.pubkey : undefined;
|
|
4406
4445
|
const explorerTxLink = explorerUrls?.tx;
|
|
4446
|
+
const decimals = assetInfo.decimals ?? balance.decimals;
|
|
4447
|
+
if (decimals === undefined || decimals === null) {
|
|
4448
|
+
throw new Error(`CRITICAL: Asset ${balance.caip} (${assetInfo.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `AssetInfo is incomplete. This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({ caip: balance.caip, symbol: assetInfo.symbol, hasDecimals: !!assetInfo.decimals })}`);
|
|
4449
|
+
}
|
|
4407
4450
|
Object.assign(balance, assetInfo, {
|
|
4408
4451
|
type: balance.type || assetInfo.type,
|
|
4409
4452
|
isNative: balance.isNative ?? assetInfo.isNative,
|
|
@@ -4412,7 +4455,8 @@ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
|
|
|
4412
4455
|
identifier: `${balance.caip}:${balance.pubkey}`,
|
|
4413
4456
|
updated: Date.now(),
|
|
4414
4457
|
color: assetInfo.color,
|
|
4415
|
-
decimals
|
|
4458
|
+
decimals,
|
|
4459
|
+
precision: decimals,
|
|
4416
4460
|
explorerAddressLink,
|
|
4417
4461
|
explorerTxLink,
|
|
4418
4462
|
explorer: explorerUrls?.address,
|
|
@@ -4793,14 +4837,17 @@ class SDK {
|
|
|
4793
4837
|
this.getUnifiedPortfolio = async function() {
|
|
4794
4838
|
const tag6 = `${TAG12} | getUnifiedPortfolio | `;
|
|
4795
4839
|
try {
|
|
4840
|
+
console.log(tag6, " checkpoint 4.0 - getUnifiedPortfolio start");
|
|
4796
4841
|
const startTime = performance.now();
|
|
4797
4842
|
try {
|
|
4798
4843
|
const baseUrl = this.keepkeyEndpoint?.baseUrl || "kkapi://";
|
|
4799
4844
|
const portfolioUrl = `${baseUrl}/api/portfolio`;
|
|
4845
|
+
console.log(tag6, " checkpoint 4.1 - Fetching portfolio from:", portfolioUrl);
|
|
4800
4846
|
const portfolioResponse = await fetch(portfolioUrl, {
|
|
4801
4847
|
method: "GET",
|
|
4802
4848
|
signal: AbortSignal.timeout(2000)
|
|
4803
4849
|
});
|
|
4850
|
+
console.log(tag6, " checkpoint 4.2 - Portfolio fetch returned, status:", portfolioResponse.status);
|
|
4804
4851
|
if (!portfolioResponse.ok) {
|
|
4805
4852
|
console.warn(tag6, "Portfolio endpoint returned", portfolioResponse.status);
|
|
4806
4853
|
return null;
|
|
@@ -4913,7 +4960,9 @@ class SDK {
|
|
|
4913
4960
|
};
|
|
4914
4961
|
console.log("\uD83D\uDD11 [INIT] Initializing KeepKey SDK...");
|
|
4915
4962
|
const keepKeySdk = await import_keepkey_sdk.KeepKeySdk.create(configKeepKey);
|
|
4963
|
+
console.log(tag6, " checkpoint 1.1 - KeepKeySdk created");
|
|
4916
4964
|
const features = await keepKeySdk.system.info.getFeatures();
|
|
4965
|
+
console.log(tag6, " checkpoint 1.2 - features retrieved:", features);
|
|
4917
4966
|
this.keepkeyApiKey = configKeepKey.apiKey;
|
|
4918
4967
|
this.keepKeySdk = keepKeySdk;
|
|
4919
4968
|
this.context = "keepkey:" + features.label + ".json";
|
|
@@ -4927,14 +4976,18 @@ class SDK {
|
|
|
4927
4976
|
console.log("\uD83D\uDC41️ [VIEW-ONLY] Skipping vault endpoint detection");
|
|
4928
4977
|
this.keepkeyEndpoint = null;
|
|
4929
4978
|
}
|
|
4979
|
+
console.log(tag6, " checkpoint 2 - Starting WebSocket initialization");
|
|
4930
4980
|
let configWss = {
|
|
4931
4981
|
username: this.username,
|
|
4932
4982
|
queryKey: this.queryKey,
|
|
4933
4983
|
wss: this.wss
|
|
4934
4984
|
};
|
|
4935
4985
|
let clientEvents = new import_pioneer_events.Events(configWss);
|
|
4986
|
+
console.log(tag6, " checkpoint 2.1 - Events created, calling init()");
|
|
4936
4987
|
await clientEvents.init();
|
|
4988
|
+
console.log(tag6, " checkpoint 2.2 - Events init complete, setting username");
|
|
4937
4989
|
await clientEvents.setUsername(this.username);
|
|
4990
|
+
console.log(tag6, " checkpoint 2.3 - Username set, WebSocket ready");
|
|
4938
4991
|
clientEvents.events.on("message", (request) => {
|
|
4939
4992
|
this.events.emit("message", request);
|
|
4940
4993
|
});
|
|
@@ -5000,11 +5053,14 @@ class SDK {
|
|
|
5000
5053
|
}
|
|
5001
5054
|
});
|
|
5002
5055
|
this.events.emit("SET_STATUS", "init");
|
|
5056
|
+
console.log(tag6, " checkpoint 3 - Starting fast portfolio check");
|
|
5003
5057
|
if (this.keepKeySdk && !skipSync) {
|
|
5004
5058
|
console.log("⚡ [FAST PORTFOLIO] Attempting fast load...");
|
|
5059
|
+
console.log(tag6, " checkpoint 3.1 - Calling getUnifiedPortfolio()");
|
|
5005
5060
|
const fastStart = performance.now();
|
|
5006
5061
|
try {
|
|
5007
5062
|
const unifiedResult = await this.getUnifiedPortfolio();
|
|
5063
|
+
console.log(tag6, " checkpoint 3.2 - getUnifiedPortfolio() returned");
|
|
5008
5064
|
console.log("unifiedResult: ", unifiedResult);
|
|
5009
5065
|
if (unifiedResult && unifiedResult.cached && unifiedResult.totalValueUsd > 0) {
|
|
5010
5066
|
console.log(`✅ [FAST PORTFOLIO] Loaded in ${(performance.now() - fastStart).toFixed(0)}ms`);
|
|
@@ -5935,7 +5991,16 @@ class SDK {
|
|
|
5935
5991
|
const networkId2 = import_pioneer_caip8.caipToNetworkId(asset.caip || asset.networkId);
|
|
5936
5992
|
const currentContextValid = this.pubkeyContext?.networks?.includes(networkId2);
|
|
5937
5993
|
if (!this.pubkeyContext || !currentContextValid) {
|
|
5938
|
-
|
|
5994
|
+
let preferredPubkey = assetPubkeys[0];
|
|
5995
|
+
const isBitcoin = networkId2?.includes("bip122:000000000019d6689c085ae165831e93") || asset.symbol === "BTC" || asset.name?.toLowerCase().includes("bitcoin");
|
|
5996
|
+
if (isBitcoin) {
|
|
5997
|
+
const nativeSegwitPubkey = assetPubkeys.find((pk) => pk.script_type === "p2wpkh" || pk.scriptType === "p2wpkh" || pk.note?.toLowerCase().includes("native") && pk.note?.toLowerCase().includes("segwit") || pk.pathMaster?.includes("84'"));
|
|
5998
|
+
if (nativeSegwitPubkey) {
|
|
5999
|
+
preferredPubkey = nativeSegwitPubkey;
|
|
6000
|
+
console.log(tag6, "Preferring Native Segwit (Bech32) for Bitcoin");
|
|
6001
|
+
}
|
|
6002
|
+
}
|
|
6003
|
+
this.pubkeyContext = preferredPubkey;
|
|
5939
6004
|
console.log(tag6, "Auto-set pubkey context for network:", this.pubkeyContext.address || this.pubkeyContext.pubkey);
|
|
5940
6005
|
} else {
|
|
5941
6006
|
console.log(tag6, "Preserving existing pubkey context for network:", this.pubkeyContext.address || this.pubkeyContext.pubkey, `(addressNList: [${(this.pubkeyContext.addressNList || this.pubkeyContext.addressNListMaster).join(", ")}])`);
|
package/dist/index.es.js
CHANGED
|
@@ -427,6 +427,17 @@ function processPortfolioBalance(balance, primaryAddress, context, blockchains)
|
|
|
427
427
|
console.log(tag2, `Calculated price from value/balance: ${calculatedPrice} for ${balance.caip}`);
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
|
+
const decimals = assetInfo?.decimals ?? assetInfo?.decimal ?? balance.decimals ?? balance.decimal;
|
|
431
|
+
if (decimals === undefined || decimals === null) {
|
|
432
|
+
throw new Error(`CRITICAL: Asset ${balance.caip} (${assetInfo?.symbol || balance.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({
|
|
433
|
+
caip: balance.caip,
|
|
434
|
+
symbol: assetInfo?.symbol || balance.symbol,
|
|
435
|
+
hasAssetInfoDecimals: !!assetInfo?.decimals,
|
|
436
|
+
hasAssetInfoDecimal: !!assetInfo?.decimal,
|
|
437
|
+
hasBalanceDecimals: !!balance.decimals,
|
|
438
|
+
hasBalanceDecimal: !!balance.decimal
|
|
439
|
+
})}`);
|
|
440
|
+
}
|
|
430
441
|
const chartBalance = {
|
|
431
442
|
context,
|
|
432
443
|
chart: "pioneer",
|
|
@@ -443,7 +454,9 @@ function processPortfolioBalance(balance, primaryAddress, context, blockchains)
|
|
|
443
454
|
symbol: assetInfo?.symbol || balance.symbol || "UNK",
|
|
444
455
|
type: balanceType,
|
|
445
456
|
token: isToken,
|
|
446
|
-
decimal:
|
|
457
|
+
decimal: decimals,
|
|
458
|
+
decimals,
|
|
459
|
+
precision: decimals,
|
|
447
460
|
balance: balance.balance.toString(),
|
|
448
461
|
price: calculatedPrice,
|
|
449
462
|
priceUsd: calculatedPrice,
|
|
@@ -474,6 +487,17 @@ function processPortfolioToken(token, primaryAddress, context, blockchains) {
|
|
|
474
487
|
}
|
|
475
488
|
const tokenAssetInfo = hydrateAssetData(token.assetCaip);
|
|
476
489
|
const tokenPubkey = token.pubkey || primaryAddress;
|
|
490
|
+
const tokenDecimals = tokenAssetInfo?.decimals ?? tokenAssetInfo?.decimal ?? token.token?.decimals ?? token.token?.decimal;
|
|
491
|
+
if (tokenDecimals === undefined || tokenDecimals === null) {
|
|
492
|
+
throw new Error(`CRITICAL: Token ${token.assetCaip} (${tokenAssetInfo?.symbol || token.token?.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Token data: ${JSON.stringify({
|
|
493
|
+
caip: token.assetCaip,
|
|
494
|
+
symbol: tokenAssetInfo?.symbol || token.token?.symbol,
|
|
495
|
+
hasAssetInfoDecimals: !!tokenAssetInfo?.decimals,
|
|
496
|
+
hasAssetInfoDecimal: !!tokenAssetInfo?.decimal,
|
|
497
|
+
hasTokenDecimals: !!token.token?.decimals,
|
|
498
|
+
hasTokenDecimal: !!token.token?.decimal
|
|
499
|
+
})}`);
|
|
500
|
+
}
|
|
477
501
|
const chartBalance = {
|
|
478
502
|
context,
|
|
479
503
|
chart: "pioneer",
|
|
@@ -489,7 +513,9 @@ function processPortfolioToken(token, primaryAddress, context, blockchains) {
|
|
|
489
513
|
symbol: tokenAssetInfo?.symbol || token.token?.symbol || "UNK",
|
|
490
514
|
type: tokenAssetInfo?.type || "token",
|
|
491
515
|
token: true,
|
|
492
|
-
decimal:
|
|
516
|
+
decimal: tokenDecimals,
|
|
517
|
+
decimals: tokenDecimals,
|
|
518
|
+
precision: tokenDecimals,
|
|
493
519
|
balance: token.token?.balance?.toString() || "0",
|
|
494
520
|
priceUsd: token.token?.price || 0,
|
|
495
521
|
valueUsd: token.token?.balanceUSD || 0,
|
|
@@ -596,6 +622,17 @@ async function getMayaCharts(params, existingBalances) {
|
|
|
596
622
|
}
|
|
597
623
|
const mayaAssetInfo = hydrateAssetData(mayaBalance.caip);
|
|
598
624
|
const isToken = mayaBalance.caip.includes("/denom:") && !mayaBalance.caip.endsWith("/denom:cacao");
|
|
625
|
+
const decimals = mayaAssetInfo?.decimals ?? mayaAssetInfo?.decimal ?? mayaBalance.decimals ?? mayaBalance.decimal;
|
|
626
|
+
if (decimals === undefined || decimals === null) {
|
|
627
|
+
throw new Error(`CRITICAL: Asset ${mayaBalance.caip} (${mayaAssetInfo?.symbol || "MAYA"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({
|
|
628
|
+
caip: mayaBalance.caip,
|
|
629
|
+
symbol: mayaAssetInfo?.symbol,
|
|
630
|
+
hasAssetInfoDecimals: !!mayaAssetInfo?.decimals,
|
|
631
|
+
hasAssetInfoDecimal: !!mayaAssetInfo?.decimal,
|
|
632
|
+
hasBalanceDecimals: !!mayaBalance.decimals,
|
|
633
|
+
hasBalanceDecimal: !!mayaBalance.decimal
|
|
634
|
+
})}`);
|
|
635
|
+
}
|
|
599
636
|
const mayaTokenBalance = {
|
|
600
637
|
context,
|
|
601
638
|
chart: "pioneer",
|
|
@@ -611,7 +648,9 @@ async function getMayaCharts(params, existingBalances) {
|
|
|
611
648
|
symbol: mayaAssetInfo?.symbol || "MAYA",
|
|
612
649
|
type: mayaAssetInfo?.type || "token",
|
|
613
650
|
token: isToken,
|
|
614
|
-
decimal:
|
|
651
|
+
decimal: decimals,
|
|
652
|
+
decimals,
|
|
653
|
+
precision: decimals,
|
|
615
654
|
balance: mayaBalance.balance?.toString() || "0",
|
|
616
655
|
priceUsd: parseFloat(mayaBalance.priceUsd) || 0,
|
|
617
656
|
valueUsd: parseFloat(mayaBalance.valueUsd) || 0,
|
|
@@ -4588,6 +4627,10 @@ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
|
|
|
4588
4627
|
const explorerUrls = EXPLORER_BASE_URLS[networkId];
|
|
4589
4628
|
const explorerAddressLink = explorerUrls && balance.pubkey ? explorerUrls.address + balance.pubkey : undefined;
|
|
4590
4629
|
const explorerTxLink = explorerUrls?.tx;
|
|
4630
|
+
const decimals = assetInfo.decimals ?? balance.decimals;
|
|
4631
|
+
if (decimals === undefined || decimals === null) {
|
|
4632
|
+
throw new Error(`CRITICAL: Asset ${balance.caip} (${assetInfo.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `AssetInfo is incomplete. This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({ caip: balance.caip, symbol: assetInfo.symbol, hasDecimals: !!assetInfo.decimals })}`);
|
|
4633
|
+
}
|
|
4591
4634
|
Object.assign(balance, assetInfo, {
|
|
4592
4635
|
type: balance.type || assetInfo.type,
|
|
4593
4636
|
isNative: balance.isNative ?? assetInfo.isNative,
|
|
@@ -4596,7 +4639,8 @@ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
|
|
|
4596
4639
|
identifier: `${balance.caip}:${balance.pubkey}`,
|
|
4597
4640
|
updated: Date.now(),
|
|
4598
4641
|
color: assetInfo.color,
|
|
4599
|
-
decimals
|
|
4642
|
+
decimals,
|
|
4643
|
+
precision: decimals,
|
|
4600
4644
|
explorerAddressLink,
|
|
4601
4645
|
explorerTxLink,
|
|
4602
4646
|
explorer: explorerUrls?.address,
|
|
@@ -4977,14 +5021,17 @@ class SDK {
|
|
|
4977
5021
|
this.getUnifiedPortfolio = async function() {
|
|
4978
5022
|
const tag6 = `${TAG12} | getUnifiedPortfolio | `;
|
|
4979
5023
|
try {
|
|
5024
|
+
console.log(tag6, " checkpoint 4.0 - getUnifiedPortfolio start");
|
|
4980
5025
|
const startTime = performance.now();
|
|
4981
5026
|
try {
|
|
4982
5027
|
const baseUrl = this.keepkeyEndpoint?.baseUrl || "kkapi://";
|
|
4983
5028
|
const portfolioUrl = `${baseUrl}/api/portfolio`;
|
|
5029
|
+
console.log(tag6, " checkpoint 4.1 - Fetching portfolio from:", portfolioUrl);
|
|
4984
5030
|
const portfolioResponse = await fetch(portfolioUrl, {
|
|
4985
5031
|
method: "GET",
|
|
4986
5032
|
signal: AbortSignal.timeout(2000)
|
|
4987
5033
|
});
|
|
5034
|
+
console.log(tag6, " checkpoint 4.2 - Portfolio fetch returned, status:", portfolioResponse.status);
|
|
4988
5035
|
if (!portfolioResponse.ok) {
|
|
4989
5036
|
console.warn(tag6, "Portfolio endpoint returned", portfolioResponse.status);
|
|
4990
5037
|
return null;
|
|
@@ -5097,7 +5144,9 @@ class SDK {
|
|
|
5097
5144
|
};
|
|
5098
5145
|
console.log("\uD83D\uDD11 [INIT] Initializing KeepKey SDK...");
|
|
5099
5146
|
const keepKeySdk = await KeepKeySdk.create(configKeepKey);
|
|
5147
|
+
console.log(tag6, " checkpoint 1.1 - KeepKeySdk created");
|
|
5100
5148
|
const features = await keepKeySdk.system.info.getFeatures();
|
|
5149
|
+
console.log(tag6, " checkpoint 1.2 - features retrieved:", features);
|
|
5101
5150
|
this.keepkeyApiKey = configKeepKey.apiKey;
|
|
5102
5151
|
this.keepKeySdk = keepKeySdk;
|
|
5103
5152
|
this.context = "keepkey:" + features.label + ".json";
|
|
@@ -5111,14 +5160,18 @@ class SDK {
|
|
|
5111
5160
|
console.log("\uD83D\uDC41️ [VIEW-ONLY] Skipping vault endpoint detection");
|
|
5112
5161
|
this.keepkeyEndpoint = null;
|
|
5113
5162
|
}
|
|
5163
|
+
console.log(tag6, " checkpoint 2 - Starting WebSocket initialization");
|
|
5114
5164
|
let configWss = {
|
|
5115
5165
|
username: this.username,
|
|
5116
5166
|
queryKey: this.queryKey,
|
|
5117
5167
|
wss: this.wss
|
|
5118
5168
|
};
|
|
5119
5169
|
let clientEvents = new Events(configWss);
|
|
5170
|
+
console.log(tag6, " checkpoint 2.1 - Events created, calling init()");
|
|
5120
5171
|
await clientEvents.init();
|
|
5172
|
+
console.log(tag6, " checkpoint 2.2 - Events init complete, setting username");
|
|
5121
5173
|
await clientEvents.setUsername(this.username);
|
|
5174
|
+
console.log(tag6, " checkpoint 2.3 - Username set, WebSocket ready");
|
|
5122
5175
|
clientEvents.events.on("message", (request) => {
|
|
5123
5176
|
this.events.emit("message", request);
|
|
5124
5177
|
});
|
|
@@ -5184,11 +5237,14 @@ class SDK {
|
|
|
5184
5237
|
}
|
|
5185
5238
|
});
|
|
5186
5239
|
this.events.emit("SET_STATUS", "init");
|
|
5240
|
+
console.log(tag6, " checkpoint 3 - Starting fast portfolio check");
|
|
5187
5241
|
if (this.keepKeySdk && !skipSync) {
|
|
5188
5242
|
console.log("⚡ [FAST PORTFOLIO] Attempting fast load...");
|
|
5243
|
+
console.log(tag6, " checkpoint 3.1 - Calling getUnifiedPortfolio()");
|
|
5189
5244
|
const fastStart = performance.now();
|
|
5190
5245
|
try {
|
|
5191
5246
|
const unifiedResult = await this.getUnifiedPortfolio();
|
|
5247
|
+
console.log(tag6, " checkpoint 3.2 - getUnifiedPortfolio() returned");
|
|
5192
5248
|
console.log("unifiedResult: ", unifiedResult);
|
|
5193
5249
|
if (unifiedResult && unifiedResult.cached && unifiedResult.totalValueUsd > 0) {
|
|
5194
5250
|
console.log(`✅ [FAST PORTFOLIO] Loaded in ${(performance.now() - fastStart).toFixed(0)}ms`);
|
|
@@ -6119,7 +6175,16 @@ class SDK {
|
|
|
6119
6175
|
const networkId2 = caipToNetworkId7(asset.caip || asset.networkId);
|
|
6120
6176
|
const currentContextValid = this.pubkeyContext?.networks?.includes(networkId2);
|
|
6121
6177
|
if (!this.pubkeyContext || !currentContextValid) {
|
|
6122
|
-
|
|
6178
|
+
let preferredPubkey = assetPubkeys[0];
|
|
6179
|
+
const isBitcoin = networkId2?.includes("bip122:000000000019d6689c085ae165831e93") || asset.symbol === "BTC" || asset.name?.toLowerCase().includes("bitcoin");
|
|
6180
|
+
if (isBitcoin) {
|
|
6181
|
+
const nativeSegwitPubkey = assetPubkeys.find((pk) => pk.script_type === "p2wpkh" || pk.scriptType === "p2wpkh" || pk.note?.toLowerCase().includes("native") && pk.note?.toLowerCase().includes("segwit") || pk.pathMaster?.includes("84'"));
|
|
6182
|
+
if (nativeSegwitPubkey) {
|
|
6183
|
+
preferredPubkey = nativeSegwitPubkey;
|
|
6184
|
+
console.log(tag6, "Preferring Native Segwit (Bech32) for Bitcoin");
|
|
6185
|
+
}
|
|
6186
|
+
}
|
|
6187
|
+
this.pubkeyContext = preferredPubkey;
|
|
6123
6188
|
console.log(tag6, "Auto-set pubkey context for network:", this.pubkeyContext.address || this.pubkeyContext.pubkey);
|
|
6124
6189
|
} else {
|
|
6125
6190
|
console.log(tag6, "Preserving existing pubkey context for network:", this.pubkeyContext.address || this.pubkeyContext.pubkey, `(addressNList: [${(this.pubkeyContext.addressNList || this.pubkeyContext.addressNListMaster).join(", ")}])`);
|
package/dist/index.js
CHANGED
|
@@ -427,6 +427,17 @@ function processPortfolioBalance(balance, primaryAddress, context, blockchains)
|
|
|
427
427
|
console.log(tag2, `Calculated price from value/balance: ${calculatedPrice} for ${balance.caip}`);
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
|
+
const decimals = assetInfo?.decimals ?? assetInfo?.decimal ?? balance.decimals ?? balance.decimal;
|
|
431
|
+
if (decimals === undefined || decimals === null) {
|
|
432
|
+
throw new Error(`CRITICAL: Asset ${balance.caip} (${assetInfo?.symbol || balance.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({
|
|
433
|
+
caip: balance.caip,
|
|
434
|
+
symbol: assetInfo?.symbol || balance.symbol,
|
|
435
|
+
hasAssetInfoDecimals: !!assetInfo?.decimals,
|
|
436
|
+
hasAssetInfoDecimal: !!assetInfo?.decimal,
|
|
437
|
+
hasBalanceDecimals: !!balance.decimals,
|
|
438
|
+
hasBalanceDecimal: !!balance.decimal
|
|
439
|
+
})}`);
|
|
440
|
+
}
|
|
430
441
|
const chartBalance = {
|
|
431
442
|
context,
|
|
432
443
|
chart: "pioneer",
|
|
@@ -443,7 +454,9 @@ function processPortfolioBalance(balance, primaryAddress, context, blockchains)
|
|
|
443
454
|
symbol: assetInfo?.symbol || balance.symbol || "UNK",
|
|
444
455
|
type: balanceType,
|
|
445
456
|
token: isToken,
|
|
446
|
-
decimal:
|
|
457
|
+
decimal: decimals,
|
|
458
|
+
decimals,
|
|
459
|
+
precision: decimals,
|
|
447
460
|
balance: balance.balance.toString(),
|
|
448
461
|
price: calculatedPrice,
|
|
449
462
|
priceUsd: calculatedPrice,
|
|
@@ -474,6 +487,17 @@ function processPortfolioToken(token, primaryAddress, context, blockchains) {
|
|
|
474
487
|
}
|
|
475
488
|
const tokenAssetInfo = hydrateAssetData(token.assetCaip);
|
|
476
489
|
const tokenPubkey = token.pubkey || primaryAddress;
|
|
490
|
+
const tokenDecimals = tokenAssetInfo?.decimals ?? tokenAssetInfo?.decimal ?? token.token?.decimals ?? token.token?.decimal;
|
|
491
|
+
if (tokenDecimals === undefined || tokenDecimals === null) {
|
|
492
|
+
throw new Error(`CRITICAL: Token ${token.assetCaip} (${tokenAssetInfo?.symbol || token.token?.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Token data: ${JSON.stringify({
|
|
493
|
+
caip: token.assetCaip,
|
|
494
|
+
symbol: tokenAssetInfo?.symbol || token.token?.symbol,
|
|
495
|
+
hasAssetInfoDecimals: !!tokenAssetInfo?.decimals,
|
|
496
|
+
hasAssetInfoDecimal: !!tokenAssetInfo?.decimal,
|
|
497
|
+
hasTokenDecimals: !!token.token?.decimals,
|
|
498
|
+
hasTokenDecimal: !!token.token?.decimal
|
|
499
|
+
})}`);
|
|
500
|
+
}
|
|
477
501
|
const chartBalance = {
|
|
478
502
|
context,
|
|
479
503
|
chart: "pioneer",
|
|
@@ -489,7 +513,9 @@ function processPortfolioToken(token, primaryAddress, context, blockchains) {
|
|
|
489
513
|
symbol: tokenAssetInfo?.symbol || token.token?.symbol || "UNK",
|
|
490
514
|
type: tokenAssetInfo?.type || "token",
|
|
491
515
|
token: true,
|
|
492
|
-
decimal:
|
|
516
|
+
decimal: tokenDecimals,
|
|
517
|
+
decimals: tokenDecimals,
|
|
518
|
+
precision: tokenDecimals,
|
|
493
519
|
balance: token.token?.balance?.toString() || "0",
|
|
494
520
|
priceUsd: token.token?.price || 0,
|
|
495
521
|
valueUsd: token.token?.balanceUSD || 0,
|
|
@@ -596,6 +622,17 @@ async function getMayaCharts(params, existingBalances) {
|
|
|
596
622
|
}
|
|
597
623
|
const mayaAssetInfo = hydrateAssetData(mayaBalance.caip);
|
|
598
624
|
const isToken = mayaBalance.caip.includes("/denom:") && !mayaBalance.caip.endsWith("/denom:cacao");
|
|
625
|
+
const decimals = mayaAssetInfo?.decimals ?? mayaAssetInfo?.decimal ?? mayaBalance.decimals ?? mayaBalance.decimal;
|
|
626
|
+
if (decimals === undefined || decimals === null) {
|
|
627
|
+
throw new Error(`CRITICAL: Asset ${mayaBalance.caip} (${mayaAssetInfo?.symbol || "MAYA"}) has NO decimals/precision! ` + `This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({
|
|
628
|
+
caip: mayaBalance.caip,
|
|
629
|
+
symbol: mayaAssetInfo?.symbol,
|
|
630
|
+
hasAssetInfoDecimals: !!mayaAssetInfo?.decimals,
|
|
631
|
+
hasAssetInfoDecimal: !!mayaAssetInfo?.decimal,
|
|
632
|
+
hasBalanceDecimals: !!mayaBalance.decimals,
|
|
633
|
+
hasBalanceDecimal: !!mayaBalance.decimal
|
|
634
|
+
})}`);
|
|
635
|
+
}
|
|
599
636
|
const mayaTokenBalance = {
|
|
600
637
|
context,
|
|
601
638
|
chart: "pioneer",
|
|
@@ -611,7 +648,9 @@ async function getMayaCharts(params, existingBalances) {
|
|
|
611
648
|
symbol: mayaAssetInfo?.symbol || "MAYA",
|
|
612
649
|
type: mayaAssetInfo?.type || "token",
|
|
613
650
|
token: isToken,
|
|
614
|
-
decimal:
|
|
651
|
+
decimal: decimals,
|
|
652
|
+
decimals,
|
|
653
|
+
precision: decimals,
|
|
615
654
|
balance: mayaBalance.balance?.toString() || "0",
|
|
616
655
|
priceUsd: parseFloat(mayaBalance.priceUsd) || 0,
|
|
617
656
|
valueUsd: parseFloat(mayaBalance.valueUsd) || 0,
|
|
@@ -4588,6 +4627,10 @@ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
|
|
|
4588
4627
|
const explorerUrls = EXPLORER_BASE_URLS[networkId];
|
|
4589
4628
|
const explorerAddressLink = explorerUrls && balance.pubkey ? explorerUrls.address + balance.pubkey : undefined;
|
|
4590
4629
|
const explorerTxLink = explorerUrls?.tx;
|
|
4630
|
+
const decimals = assetInfo.decimals ?? balance.decimals;
|
|
4631
|
+
if (decimals === undefined || decimals === null) {
|
|
4632
|
+
throw new Error(`CRITICAL: Asset ${balance.caip} (${assetInfo.symbol || "UNKNOWN"}) has NO decimals/precision! ` + `AssetInfo is incomplete. This would cause incorrect balance calculations. ` + `Asset data: ${JSON.stringify({ caip: balance.caip, symbol: assetInfo.symbol, hasDecimals: !!assetInfo.decimals })}`);
|
|
4633
|
+
}
|
|
4591
4634
|
Object.assign(balance, assetInfo, {
|
|
4592
4635
|
type: balance.type || assetInfo.type,
|
|
4593
4636
|
isNative: balance.isNative ?? assetInfo.isNative,
|
|
@@ -4596,7 +4639,8 @@ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
|
|
|
4596
4639
|
identifier: `${balance.caip}:${balance.pubkey}`,
|
|
4597
4640
|
updated: Date.now(),
|
|
4598
4641
|
color: assetInfo.color,
|
|
4599
|
-
decimals
|
|
4642
|
+
decimals,
|
|
4643
|
+
precision: decimals,
|
|
4600
4644
|
explorerAddressLink,
|
|
4601
4645
|
explorerTxLink,
|
|
4602
4646
|
explorer: explorerUrls?.address,
|
|
@@ -4977,14 +5021,17 @@ class SDK {
|
|
|
4977
5021
|
this.getUnifiedPortfolio = async function() {
|
|
4978
5022
|
const tag6 = `${TAG12} | getUnifiedPortfolio | `;
|
|
4979
5023
|
try {
|
|
5024
|
+
console.log(tag6, " checkpoint 4.0 - getUnifiedPortfolio start");
|
|
4980
5025
|
const startTime = performance.now();
|
|
4981
5026
|
try {
|
|
4982
5027
|
const baseUrl = this.keepkeyEndpoint?.baseUrl || "kkapi://";
|
|
4983
5028
|
const portfolioUrl = `${baseUrl}/api/portfolio`;
|
|
5029
|
+
console.log(tag6, " checkpoint 4.1 - Fetching portfolio from:", portfolioUrl);
|
|
4984
5030
|
const portfolioResponse = await fetch(portfolioUrl, {
|
|
4985
5031
|
method: "GET",
|
|
4986
5032
|
signal: AbortSignal.timeout(2000)
|
|
4987
5033
|
});
|
|
5034
|
+
console.log(tag6, " checkpoint 4.2 - Portfolio fetch returned, status:", portfolioResponse.status);
|
|
4988
5035
|
if (!portfolioResponse.ok) {
|
|
4989
5036
|
console.warn(tag6, "Portfolio endpoint returned", portfolioResponse.status);
|
|
4990
5037
|
return null;
|
|
@@ -5097,7 +5144,9 @@ class SDK {
|
|
|
5097
5144
|
};
|
|
5098
5145
|
console.log("\uD83D\uDD11 [INIT] Initializing KeepKey SDK...");
|
|
5099
5146
|
const keepKeySdk = await KeepKeySdk.create(configKeepKey);
|
|
5147
|
+
console.log(tag6, " checkpoint 1.1 - KeepKeySdk created");
|
|
5100
5148
|
const features = await keepKeySdk.system.info.getFeatures();
|
|
5149
|
+
console.log(tag6, " checkpoint 1.2 - features retrieved:", features);
|
|
5101
5150
|
this.keepkeyApiKey = configKeepKey.apiKey;
|
|
5102
5151
|
this.keepKeySdk = keepKeySdk;
|
|
5103
5152
|
this.context = "keepkey:" + features.label + ".json";
|
|
@@ -5111,14 +5160,18 @@ class SDK {
|
|
|
5111
5160
|
console.log("\uD83D\uDC41️ [VIEW-ONLY] Skipping vault endpoint detection");
|
|
5112
5161
|
this.keepkeyEndpoint = null;
|
|
5113
5162
|
}
|
|
5163
|
+
console.log(tag6, " checkpoint 2 - Starting WebSocket initialization");
|
|
5114
5164
|
let configWss = {
|
|
5115
5165
|
username: this.username,
|
|
5116
5166
|
queryKey: this.queryKey,
|
|
5117
5167
|
wss: this.wss
|
|
5118
5168
|
};
|
|
5119
5169
|
let clientEvents = new Events(configWss);
|
|
5170
|
+
console.log(tag6, " checkpoint 2.1 - Events created, calling init()");
|
|
5120
5171
|
await clientEvents.init();
|
|
5172
|
+
console.log(tag6, " checkpoint 2.2 - Events init complete, setting username");
|
|
5121
5173
|
await clientEvents.setUsername(this.username);
|
|
5174
|
+
console.log(tag6, " checkpoint 2.3 - Username set, WebSocket ready");
|
|
5122
5175
|
clientEvents.events.on("message", (request) => {
|
|
5123
5176
|
this.events.emit("message", request);
|
|
5124
5177
|
});
|
|
@@ -5184,11 +5237,14 @@ class SDK {
|
|
|
5184
5237
|
}
|
|
5185
5238
|
});
|
|
5186
5239
|
this.events.emit("SET_STATUS", "init");
|
|
5240
|
+
console.log(tag6, " checkpoint 3 - Starting fast portfolio check");
|
|
5187
5241
|
if (this.keepKeySdk && !skipSync) {
|
|
5188
5242
|
console.log("⚡ [FAST PORTFOLIO] Attempting fast load...");
|
|
5243
|
+
console.log(tag6, " checkpoint 3.1 - Calling getUnifiedPortfolio()");
|
|
5189
5244
|
const fastStart = performance.now();
|
|
5190
5245
|
try {
|
|
5191
5246
|
const unifiedResult = await this.getUnifiedPortfolio();
|
|
5247
|
+
console.log(tag6, " checkpoint 3.2 - getUnifiedPortfolio() returned");
|
|
5192
5248
|
console.log("unifiedResult: ", unifiedResult);
|
|
5193
5249
|
if (unifiedResult && unifiedResult.cached && unifiedResult.totalValueUsd > 0) {
|
|
5194
5250
|
console.log(`✅ [FAST PORTFOLIO] Loaded in ${(performance.now() - fastStart).toFixed(0)}ms`);
|
|
@@ -6119,7 +6175,16 @@ class SDK {
|
|
|
6119
6175
|
const networkId2 = caipToNetworkId7(asset.caip || asset.networkId);
|
|
6120
6176
|
const currentContextValid = this.pubkeyContext?.networks?.includes(networkId2);
|
|
6121
6177
|
if (!this.pubkeyContext || !currentContextValid) {
|
|
6122
|
-
|
|
6178
|
+
let preferredPubkey = assetPubkeys[0];
|
|
6179
|
+
const isBitcoin = networkId2?.includes("bip122:000000000019d6689c085ae165831e93") || asset.symbol === "BTC" || asset.name?.toLowerCase().includes("bitcoin");
|
|
6180
|
+
if (isBitcoin) {
|
|
6181
|
+
const nativeSegwitPubkey = assetPubkeys.find((pk) => pk.script_type === "p2wpkh" || pk.scriptType === "p2wpkh" || pk.note?.toLowerCase().includes("native") && pk.note?.toLowerCase().includes("segwit") || pk.pathMaster?.includes("84'"));
|
|
6182
|
+
if (nativeSegwitPubkey) {
|
|
6183
|
+
preferredPubkey = nativeSegwitPubkey;
|
|
6184
|
+
console.log(tag6, "Preferring Native Segwit (Bech32) for Bitcoin");
|
|
6185
|
+
}
|
|
6186
|
+
}
|
|
6187
|
+
this.pubkeyContext = preferredPubkey;
|
|
6123
6188
|
console.log(tag6, "Auto-set pubkey context for network:", this.pubkeyContext.address || this.pubkeyContext.pubkey);
|
|
6124
6189
|
} else {
|
|
6125
6190
|
console.log(tag6, "Preserving existing pubkey context for network:", this.pubkeyContext.address || this.pubkeyContext.pubkey, `(addressNList: [${(this.pubkeyContext.addressNList || this.pubkeyContext.addressNListMaster).join(", ")}])`);
|
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.38",
|
|
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.15",
|
|
8
|
+
"@pioneer-platform/pioneer-client": "^9.10.21",
|
|
9
|
+
"@pioneer-platform/pioneer-coins": "^9.11.15",
|
|
10
|
+
"@pioneer-platform/pioneer-discovery": "^8.15.38",
|
|
11
|
+
"@pioneer-platform/pioneer-events": "^8.12.10",
|
|
12
12
|
"coinselect": "^3.1.13",
|
|
13
13
|
"eventemitter3": "^5.0.1",
|
|
14
14
|
"neotraverse": "^0.6.8",
|
package/src/charts/evm.ts
CHANGED
|
@@ -178,6 +178,25 @@ function processPortfolioBalance(
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
// CRITICAL: FAIL FAST if decimals/precision is missing
|
|
182
|
+
// Extract decimals from multiple possible sources (assetInfo, balance API response)
|
|
183
|
+
const decimals = assetInfo?.decimals ?? assetInfo?.decimal ?? balance.decimals ?? balance.decimal;
|
|
184
|
+
|
|
185
|
+
if (decimals === undefined || decimals === null) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
`CRITICAL: Asset ${balance.caip} (${assetInfo?.symbol || balance.symbol || 'UNKNOWN'}) has NO decimals/precision! ` +
|
|
188
|
+
`This would cause incorrect balance calculations. ` +
|
|
189
|
+
`Asset data: ${JSON.stringify({
|
|
190
|
+
caip: balance.caip,
|
|
191
|
+
symbol: assetInfo?.symbol || balance.symbol,
|
|
192
|
+
hasAssetInfoDecimals: !!assetInfo?.decimals,
|
|
193
|
+
hasAssetInfoDecimal: !!assetInfo?.decimal,
|
|
194
|
+
hasBalanceDecimals: !!balance.decimals,
|
|
195
|
+
hasBalanceDecimal: !!balance.decimal
|
|
196
|
+
})}`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
181
200
|
const chartBalance: ChartBalance = {
|
|
182
201
|
context,
|
|
183
202
|
chart: 'pioneer',
|
|
@@ -194,7 +213,10 @@ function processPortfolioBalance(
|
|
|
194
213
|
symbol: assetInfo?.symbol || balance.symbol || 'UNK',
|
|
195
214
|
type: balanceType,
|
|
196
215
|
token: isToken,
|
|
197
|
-
|
|
216
|
+
// CRITICAL: Set BOTH decimal (legacy) and decimals/precision (new standard)
|
|
217
|
+
decimal: decimals,
|
|
218
|
+
decimals: decimals,
|
|
219
|
+
precision: decimals,
|
|
198
220
|
balance: balance.balance.toString(),
|
|
199
221
|
price: calculatedPrice,
|
|
200
222
|
priceUsd: calculatedPrice,
|
|
@@ -244,10 +266,28 @@ function processPortfolioToken(
|
|
|
244
266
|
|
|
245
267
|
// Hydrate token with assetData
|
|
246
268
|
const tokenAssetInfo = hydrateAssetData(token.assetCaip);
|
|
247
|
-
|
|
269
|
+
|
|
248
270
|
// CRITICAL FIX: Use consistent pubkey for tokens too
|
|
249
271
|
const tokenPubkey = token.pubkey || primaryAddress;
|
|
250
272
|
|
|
273
|
+
// CRITICAL: FAIL FAST if decimals/precision is missing for tokens
|
|
274
|
+
const tokenDecimals = tokenAssetInfo?.decimals ?? tokenAssetInfo?.decimal ?? token.token?.decimals ?? token.token?.decimal;
|
|
275
|
+
|
|
276
|
+
if (tokenDecimals === undefined || tokenDecimals === null) {
|
|
277
|
+
throw new Error(
|
|
278
|
+
`CRITICAL: Token ${token.assetCaip} (${tokenAssetInfo?.symbol || token.token?.symbol || 'UNKNOWN'}) has NO decimals/precision! ` +
|
|
279
|
+
`This would cause incorrect balance calculations. ` +
|
|
280
|
+
`Token data: ${JSON.stringify({
|
|
281
|
+
caip: token.assetCaip,
|
|
282
|
+
symbol: tokenAssetInfo?.symbol || token.token?.symbol,
|
|
283
|
+
hasAssetInfoDecimals: !!tokenAssetInfo?.decimals,
|
|
284
|
+
hasAssetInfoDecimal: !!tokenAssetInfo?.decimal,
|
|
285
|
+
hasTokenDecimals: !!token.token?.decimals,
|
|
286
|
+
hasTokenDecimal: !!token.token?.decimal
|
|
287
|
+
})}`
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
251
291
|
const chartBalance: ChartBalance = {
|
|
252
292
|
context,
|
|
253
293
|
chart: 'pioneer',
|
|
@@ -263,7 +303,10 @@ function processPortfolioToken(
|
|
|
263
303
|
symbol: tokenAssetInfo?.symbol || token.token?.symbol || 'UNK',
|
|
264
304
|
type: tokenAssetInfo?.type || 'token',
|
|
265
305
|
token: true, // Tokens from portfolio.tokens are always tokens
|
|
266
|
-
|
|
306
|
+
// CRITICAL: Set ALL decimal fields for compatibility
|
|
307
|
+
decimal: tokenDecimals,
|
|
308
|
+
decimals: tokenDecimals,
|
|
309
|
+
precision: tokenDecimals,
|
|
267
310
|
balance: token.token?.balance?.toString() || '0',
|
|
268
311
|
priceUsd: token.token?.price || 0,
|
|
269
312
|
valueUsd: token.token?.balanceUSD || 0,
|
package/src/charts/maya.ts
CHANGED
|
@@ -79,7 +79,26 @@ export async function getMayaCharts(
|
|
|
79
79
|
|
|
80
80
|
// CACAO is the native asset, MAYA is a token on the Maya chain
|
|
81
81
|
const isToken = mayaBalance.caip.includes('/denom:') && !mayaBalance.caip.endsWith('/denom:cacao');
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
// CRITICAL: FAIL FAST if decimals/precision is missing
|
|
84
|
+
// Extract decimals from multiple possible sources (assetInfo, balance API response)
|
|
85
|
+
const decimals = mayaAssetInfo?.decimals ?? mayaAssetInfo?.decimal ?? mayaBalance.decimals ?? mayaBalance.decimal;
|
|
86
|
+
|
|
87
|
+
if (decimals === undefined || decimals === null) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`CRITICAL: Asset ${mayaBalance.caip} (${mayaAssetInfo?.symbol || 'MAYA'}) has NO decimals/precision! ` +
|
|
90
|
+
`This would cause incorrect balance calculations. ` +
|
|
91
|
+
`Asset data: ${JSON.stringify({
|
|
92
|
+
caip: mayaBalance.caip,
|
|
93
|
+
symbol: mayaAssetInfo?.symbol,
|
|
94
|
+
hasAssetInfoDecimals: !!mayaAssetInfo?.decimals,
|
|
95
|
+
hasAssetInfoDecimal: !!mayaAssetInfo?.decimal,
|
|
96
|
+
hasBalanceDecimals: !!mayaBalance.decimals,
|
|
97
|
+
hasBalanceDecimal: !!mayaBalance.decimal
|
|
98
|
+
})}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
83
102
|
const mayaTokenBalance: ChartBalance = {
|
|
84
103
|
context,
|
|
85
104
|
chart: 'pioneer',
|
|
@@ -95,7 +114,10 @@ export async function getMayaCharts(
|
|
|
95
114
|
symbol: mayaAssetInfo?.symbol || 'MAYA',
|
|
96
115
|
type: mayaAssetInfo?.type || 'token',
|
|
97
116
|
token: isToken, // MAYA is a token, CACAO is the native asset
|
|
98
|
-
|
|
117
|
+
// CRITICAL: Set BOTH decimal (legacy) and decimals/precision (new standard)
|
|
118
|
+
decimal: decimals,
|
|
119
|
+
decimals: decimals,
|
|
120
|
+
precision: decimals,
|
|
99
121
|
balance: mayaBalance.balance?.toString() || '0',
|
|
100
122
|
priceUsd: parseFloat(mayaBalance.priceUsd) || 0,
|
|
101
123
|
valueUsd: parseFloat(mayaBalance.valueUsd) || 0,
|
package/src/index.ts
CHANGED
|
@@ -333,6 +333,7 @@ export class SDK {
|
|
|
333
333
|
this.getUnifiedPortfolio = async function () {
|
|
334
334
|
const tag = `${TAG} | getUnifiedPortfolio | `;
|
|
335
335
|
try {
|
|
336
|
+
console.log(tag,' checkpoint 4.0 - getUnifiedPortfolio start')
|
|
336
337
|
const startTime = performance.now();
|
|
337
338
|
|
|
338
339
|
// Check if kkapi is available and use the detected endpoint
|
|
@@ -340,11 +341,13 @@ export class SDK {
|
|
|
340
341
|
// Use the detected endpoint instead of hardcoded kkapi://
|
|
341
342
|
const baseUrl = this.keepkeyEndpoint?.baseUrl || 'kkapi://';
|
|
342
343
|
const portfolioUrl = `${baseUrl}/api/portfolio`;
|
|
344
|
+
console.log(tag,' checkpoint 4.1 - Fetching portfolio from:', portfolioUrl)
|
|
343
345
|
|
|
344
346
|
const portfolioResponse = await fetch(portfolioUrl, {
|
|
345
347
|
method: 'GET',
|
|
346
348
|
signal: AbortSignal.timeout(2000), // 2 second timeout
|
|
347
349
|
});
|
|
350
|
+
console.log(tag,' checkpoint 4.2 - Portfolio fetch returned, status:', portfolioResponse.status)
|
|
348
351
|
|
|
349
352
|
if (!portfolioResponse.ok) {
|
|
350
353
|
console.warn(tag, 'Portfolio endpoint returned', portfolioResponse.status);
|
|
@@ -495,8 +498,9 @@ export class SDK {
|
|
|
495
498
|
|
|
496
499
|
console.log('🔑 [INIT] Initializing KeepKey SDK...');
|
|
497
500
|
const keepKeySdk = await KeepKeySdk.create(configKeepKey);
|
|
501
|
+
console.log(tag,' checkpoint 1.1 - KeepKeySdk created')
|
|
498
502
|
const features = await keepKeySdk.system.info.getFeatures();
|
|
499
|
-
|
|
503
|
+
console.log(tag,' checkpoint 1.2 - features retrieved:', features)
|
|
500
504
|
this.keepkeyApiKey = configKeepKey.apiKey;
|
|
501
505
|
this.keepKeySdk = keepKeySdk;
|
|
502
506
|
this.context = 'keepkey:' + features.label + '.json';
|
|
@@ -512,6 +516,7 @@ export class SDK {
|
|
|
512
516
|
}
|
|
513
517
|
|
|
514
518
|
// Initialize WebSocket events
|
|
519
|
+
console.log(tag,' checkpoint 2 - Starting WebSocket initialization')
|
|
515
520
|
let configWss = {
|
|
516
521
|
username: this.username,
|
|
517
522
|
queryKey: this.queryKey,
|
|
@@ -519,8 +524,11 @@ export class SDK {
|
|
|
519
524
|
};
|
|
520
525
|
|
|
521
526
|
let clientEvents = new Events(configWss);
|
|
527
|
+
console.log(tag,' checkpoint 2.1 - Events created, calling init()')
|
|
522
528
|
await clientEvents.init();
|
|
529
|
+
console.log(tag,' checkpoint 2.2 - Events init complete, setting username')
|
|
523
530
|
await clientEvents.setUsername(this.username);
|
|
531
|
+
console.log(tag,' checkpoint 2.3 - Username set, WebSocket ready')
|
|
524
532
|
|
|
525
533
|
clientEvents.events.on('message', (request) => {
|
|
526
534
|
this.events.emit('message', request);
|
|
@@ -620,12 +628,15 @@ export class SDK {
|
|
|
620
628
|
this.events.emit('SET_STATUS', 'init');
|
|
621
629
|
|
|
622
630
|
// Fast Portfolio Pattern: Try unified portfolio first, then sync if needed
|
|
631
|
+
console.log(tag,' checkpoint 3 - Starting fast portfolio check')
|
|
623
632
|
if (this.keepKeySdk && !skipSync) {
|
|
624
633
|
console.log('⚡ [FAST PORTFOLIO] Attempting fast load...');
|
|
634
|
+
console.log(tag,' checkpoint 3.1 - Calling getUnifiedPortfolio()')
|
|
625
635
|
const fastStart = performance.now();
|
|
626
636
|
|
|
627
637
|
try {
|
|
628
638
|
const unifiedResult = await this.getUnifiedPortfolio();
|
|
639
|
+
console.log(tag,' checkpoint 3.2 - getUnifiedPortfolio() returned')
|
|
629
640
|
console.log('unifiedResult: ', unifiedResult);
|
|
630
641
|
|
|
631
642
|
if (unifiedResult && unifiedResult.cached && unifiedResult.totalValueUsd > 0) {
|
|
@@ -1976,8 +1987,30 @@ export class SDK {
|
|
|
1976
1987
|
const currentContextValid = this.pubkeyContext?.networks?.includes(networkId);
|
|
1977
1988
|
|
|
1978
1989
|
if (!this.pubkeyContext || !currentContextValid) {
|
|
1979
|
-
// No context or wrong network - auto-set to
|
|
1980
|
-
|
|
1990
|
+
// No context or wrong network - auto-set to preferred pubkey
|
|
1991
|
+
// For Bitcoin, prefer Native Segwit (Bech32) over legacy
|
|
1992
|
+
let preferredPubkey = assetPubkeys[0];
|
|
1993
|
+
|
|
1994
|
+
const isBitcoin = networkId?.includes('bip122:000000000019d6689c085ae165831e93') ||
|
|
1995
|
+
asset.symbol === 'BTC' ||
|
|
1996
|
+
asset.name?.toLowerCase().includes('bitcoin');
|
|
1997
|
+
|
|
1998
|
+
if (isBitcoin) {
|
|
1999
|
+
// Find Native Segwit pubkey (script_type: 'p2wpkh', path includes 84')
|
|
2000
|
+
const nativeSegwitPubkey = assetPubkeys.find((pk: any) =>
|
|
2001
|
+
pk.script_type === 'p2wpkh' ||
|
|
2002
|
+
pk.scriptType === 'p2wpkh' ||
|
|
2003
|
+
(pk.note?.toLowerCase().includes('native') && pk.note?.toLowerCase().includes('segwit')) ||
|
|
2004
|
+
pk.pathMaster?.includes("84'")
|
|
2005
|
+
);
|
|
2006
|
+
|
|
2007
|
+
if (nativeSegwitPubkey) {
|
|
2008
|
+
preferredPubkey = nativeSegwitPubkey;
|
|
2009
|
+
console.log(tag, 'Preferring Native Segwit (Bech32) for Bitcoin');
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
this.pubkeyContext = preferredPubkey;
|
|
1981
2014
|
console.log(
|
|
1982
2015
|
tag,
|
|
1983
2016
|
'Auto-set pubkey context for network:',
|
|
@@ -345,6 +345,17 @@ export function enrichBalancesWithAssetInfo(
|
|
|
345
345
|
|
|
346
346
|
const explorerTxLink = explorerUrls?.tx; // Base URL for txs, actual txid added later
|
|
347
347
|
|
|
348
|
+
// CRITICAL: NEVER default decimals to 8 - this causes incorrect balance calculations
|
|
349
|
+
// If decimals is missing, the asset data is incomplete and we should FAIL FAST
|
|
350
|
+
const decimals = assetInfo.decimals ?? balance.decimals;
|
|
351
|
+
if (decimals === undefined || decimals === null) {
|
|
352
|
+
throw new Error(
|
|
353
|
+
`CRITICAL: Asset ${balance.caip} (${assetInfo.symbol || 'UNKNOWN'}) has NO decimals/precision! ` +
|
|
354
|
+
`AssetInfo is incomplete. This would cause incorrect balance calculations. ` +
|
|
355
|
+
`Asset data: ${JSON.stringify({ caip: balance.caip, symbol: assetInfo.symbol, hasDecimals: !!assetInfo.decimals })}`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
348
359
|
Object.assign(balance, assetInfo, {
|
|
349
360
|
type: balance.type || assetInfo.type,
|
|
350
361
|
isNative: balance.isNative ?? assetInfo.isNative,
|
|
@@ -353,8 +364,9 @@ export function enrichBalancesWithAssetInfo(
|
|
|
353
364
|
identifier: `${balance.caip}:${balance.pubkey}`,
|
|
354
365
|
updated: Date.now(),
|
|
355
366
|
color: assetInfo.color,
|
|
356
|
-
// CRITICAL:
|
|
357
|
-
decimals
|
|
367
|
+
// CRITICAL: Use validated decimals
|
|
368
|
+
decimals,
|
|
369
|
+
precision: decimals, // Also set precision for compatibility
|
|
358
370
|
// Add explorer links
|
|
359
371
|
explorerAddressLink,
|
|
360
372
|
explorerTxLink,
|