@pioneer-platform/pioneer-sdk 8.11.10 → 8.11.14
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 +383 -745
- package/dist/index.es.js +383 -745
- package/dist/index.js +383 -745
- package/package.json +2 -2
- package/src/charts/cosmos-staking.ts +32 -22
- package/src/charts/evm.ts +104 -37
- package/src/charts/maya.ts +9 -6
- package/src/index.ts +165 -14
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "highlander",
|
|
3
3
|
"name": "@pioneer-platform/pioneer-sdk",
|
|
4
|
-
"version": "8.11.
|
|
4
|
+
"version": "8.11.14",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@keepkey/keepkey-sdk": "^0.2.62",
|
|
7
7
|
"@pioneer-platform/loggerdog": "^8.11.0",
|
|
8
8
|
"@pioneer-platform/pioneer-caip": "^9.10.0",
|
|
9
9
|
"@pioneer-platform/pioneer-client": "^9.10.10",
|
|
10
10
|
"@pioneer-platform/pioneer-coins": "^9.11.0",
|
|
11
|
-
"@pioneer-platform/pioneer-discovery": "^8.11.
|
|
11
|
+
"@pioneer-platform/pioneer-discovery": "^8.11.14",
|
|
12
12
|
"@pioneer-platform/pioneer-events": "^8.11.0",
|
|
13
13
|
"coinselect": "^3.1.13",
|
|
14
14
|
"eventemitter3": "^5.0.1",
|
|
@@ -8,6 +8,18 @@ export async function getCosmosStakingCharts(params: ChartParams): Promise<Chart
|
|
|
8
8
|
const balances: ChartBalance[] = [];
|
|
9
9
|
|
|
10
10
|
try {
|
|
11
|
+
// Fast-path: skip staking in test/e2e or when explicitly requested
|
|
12
|
+
try {
|
|
13
|
+
const fastFlag = typeof process !== 'undefined' && process.env && process.env.PIONEER_FAST === '1';
|
|
14
|
+
const isTestContext = typeof context === 'string' && /test|e2e/i.test(context);
|
|
15
|
+
if (fastFlag || isTestContext) {
|
|
16
|
+
console.log(tag, 'Fast mode detected (test/e2e). Skipping cosmos staking fetch.');
|
|
17
|
+
return balances;
|
|
18
|
+
}
|
|
19
|
+
} catch (_) {
|
|
20
|
+
// ignore
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
console.log(tag, 'Adding Cosmos staking positions to charts...');
|
|
12
24
|
|
|
13
25
|
// Find cosmos pubkeys that could have staking positions
|
|
@@ -27,31 +39,29 @@ export async function getCosmosStakingCharts(params: ChartParams): Promise<Chart
|
|
|
27
39
|
|
|
28
40
|
console.log(tag, 'Found cosmos pubkeys for staking:', cosmosPubkeys.length);
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
42
|
+
await Promise.allSettled(
|
|
43
|
+
cosmosPubkeys.map(async (cosmosPubkey: any) => {
|
|
44
|
+
if (!cosmosPubkey.address) return;
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
46
|
+
const cosmosNetworks = cosmosPubkey.networks.filter(
|
|
47
|
+
(n: string) => n.includes('cosmos:cosmoshub') || n.includes('cosmos:osmosis'),
|
|
48
|
+
);
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
await Promise.allSettled(
|
|
51
|
+
cosmosNetworks
|
|
52
|
+
.filter((networkId: string) => blockchains.includes(networkId))
|
|
53
|
+
.map(async (networkId: string) => {
|
|
54
|
+
await fetchStakingPositionsForNetwork(
|
|
55
|
+
networkId,
|
|
56
|
+
cosmosPubkey.address,
|
|
57
|
+
context,
|
|
58
|
+
pioneer,
|
|
59
|
+
balances
|
|
60
|
+
);
|
|
61
|
+
})
|
|
52
62
|
);
|
|
53
|
-
}
|
|
54
|
-
|
|
63
|
+
})
|
|
64
|
+
);
|
|
55
65
|
} catch (e) {
|
|
56
66
|
console.error(tag, 'Error adding cosmos staking positions:', e);
|
|
57
67
|
}
|
package/src/charts/evm.ts
CHANGED
|
@@ -18,31 +18,72 @@ export async function getEvmCharts(params: ChartParams): Promise<ChartBalance[]>
|
|
|
18
18
|
console.log(tag, 'Total pubkeys available:', pubkeys.length);
|
|
19
19
|
console.log(tag, 'Blockchains to process:', blockchains);
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
// Build pubkeys array for batch request
|
|
22
|
+
// Map all pubkeys to { pubkey, caip } format for each supported blockchain
|
|
23
|
+
const pubkeysForBatch: { pubkey: string; caip: string }[] = [];
|
|
24
|
+
|
|
25
|
+
for (const pubkey of pubkeys) {
|
|
26
|
+
const address = pubkey.address || pubkey.master || pubkey.pubkey;
|
|
27
|
+
if (!address) continue;
|
|
28
|
+
|
|
29
|
+
// Get networks this pubkey supports
|
|
30
|
+
const supportedNetworks = pubkey.networks || [];
|
|
31
|
+
|
|
32
|
+
// For each blockchain we're processing
|
|
33
|
+
for (const blockchain of blockchains) {
|
|
34
|
+
// Check if this pubkey supports this blockchain
|
|
35
|
+
// Networks can be specific (eip155:1) or wildcard (eip155:*)
|
|
36
|
+
const supportsNetwork = supportedNetworks.some((net: string) =>
|
|
37
|
+
net === blockchain ||
|
|
38
|
+
(net.endsWith(':*') && blockchain.startsWith(net.replace(':*', ':')))
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (supportsNetwork) {
|
|
42
|
+
// Build the CAIP for this combination
|
|
43
|
+
// For EVM chains, use slip44:60 for ETH asset
|
|
44
|
+
// For non-EVM chains, we'd need different logic (not implemented yet)
|
|
45
|
+
let caip: string;
|
|
46
|
+
if (blockchain.startsWith('eip155:')) {
|
|
47
|
+
caip = `${blockchain}/slip44:60`;
|
|
48
|
+
} else {
|
|
49
|
+
// For non-EVM chains, use generic format
|
|
50
|
+
// TODO: Implement proper CAIP construction for other chains
|
|
51
|
+
caip = `${blockchain}/slip44:0`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
pubkeysForBatch.push({
|
|
55
|
+
pubkey: address,
|
|
56
|
+
caip: caip
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
28
60
|
}
|
|
29
61
|
|
|
30
|
-
console.log(tag,
|
|
62
|
+
console.log(tag, `Built ${pubkeysForBatch.length} pubkey-chain combinations for batch request`);
|
|
63
|
+
|
|
64
|
+
// Only call portfolio endpoint if we have pubkeys to query
|
|
65
|
+
if (pubkeysForBatch.length === 0) {
|
|
66
|
+
console.log(tag, 'No pubkeys to query, skipping portfolio lookup');
|
|
67
|
+
return balances;
|
|
68
|
+
}
|
|
31
69
|
|
|
32
70
|
// REDUNDANCY: Fetch stable coins from dedicated endpoint for ALL EVM networks
|
|
33
|
-
// This ensures USDC/USDT balances are always available even if
|
|
34
|
-
|
|
71
|
+
// This ensures USDC/USDT balances are always available even if cache is empty
|
|
72
|
+
if (primaryAddress) {
|
|
73
|
+
await fetchStableCoins(pioneer, primaryAddress, blockchains, balances, context);
|
|
74
|
+
}
|
|
35
75
|
|
|
36
76
|
// CUSTOM TOKENS: Fetch user-defined custom tokens from MongoDB-backed endpoint
|
|
37
77
|
// This ensures user's custom tokens are always included in their portfolio
|
|
38
78
|
await fetchCustomTokens({ blockchains, pioneer, pubkeys, context }, balances);
|
|
39
79
|
|
|
40
80
|
try {
|
|
41
|
-
//
|
|
42
|
-
//
|
|
81
|
+
// BATCH + NON-BLOCKING: Call portfolio endpoint with ALL pubkeys in one request
|
|
82
|
+
// The endpoint returns immediately from cache, never blocks waiting for blockchain APIs
|
|
83
|
+
console.log(tag, `Calling GetPortfolio with ${pubkeysForBatch.length} pubkeys (batch + non-blocking)`);
|
|
84
|
+
|
|
43
85
|
let portfolio = await pioneer.GetPortfolio({
|
|
44
|
-
|
|
45
|
-
address: primaryAddress
|
|
86
|
+
pubkeys: pubkeysForBatch
|
|
46
87
|
});
|
|
47
88
|
|
|
48
89
|
// Handle double-wrapped response from Swagger client
|
|
@@ -73,10 +114,10 @@ export async function getEvmCharts(params: ChartParams): Promise<ChartBalance[]>
|
|
|
73
114
|
}
|
|
74
115
|
console.log(tag, `Processed ${processedCount} balances, skipped ${skippedCount}`);
|
|
75
116
|
|
|
76
|
-
// Process tokens from portfolio (
|
|
117
|
+
// Process tokens from portfolio.tokens array (returned by backend with blocking token fetch)
|
|
77
118
|
if (portfolio.tokens && portfolio.tokens.length > 0) {
|
|
78
119
|
console.log(tag, 'Processing portfolio.tokens:', portfolio.tokens.length);
|
|
79
|
-
|
|
120
|
+
|
|
80
121
|
for (const token of portfolio.tokens) {
|
|
81
122
|
const processedToken = processPortfolioToken(token, primaryAddress, context, blockchains);
|
|
82
123
|
if (processedToken && !checkDuplicateBalance(balances, processedToken.caip, processedToken.pubkey)) {
|
|
@@ -84,6 +125,8 @@ export async function getEvmCharts(params: ChartParams): Promise<ChartBalance[]>
|
|
|
84
125
|
}
|
|
85
126
|
}
|
|
86
127
|
}
|
|
128
|
+
|
|
129
|
+
console.log(tag, `Total balances (native + tokens): ${balances.length}`);
|
|
87
130
|
} catch (e) {
|
|
88
131
|
console.error(tag, 'Error fetching portfolio:', e);
|
|
89
132
|
}
|
|
@@ -243,6 +286,18 @@ async function fetchStableCoins(
|
|
|
243
286
|
): Promise<void> {
|
|
244
287
|
console.log(tag, 'Fetching stable coins for redundancy...');
|
|
245
288
|
|
|
289
|
+
// Fast-path: skip redundancy in test/e2e or when explicitly requested
|
|
290
|
+
try {
|
|
291
|
+
const fastFlag = typeof process !== 'undefined' && process.env && process.env.PIONEER_FAST === '1';
|
|
292
|
+
const isTestContext = typeof context === 'string' && /test|e2e/i.test(context);
|
|
293
|
+
if (fastFlag || isTestContext) {
|
|
294
|
+
console.log(tag, 'Fast mode detected (test/e2e). Skipping stable coin redundancy.');
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
} catch (_) {
|
|
298
|
+
// no-op if process/env not available
|
|
299
|
+
}
|
|
300
|
+
|
|
246
301
|
// Networks that support stable coins endpoint
|
|
247
302
|
const supportedNetworks = ['eip155:1', 'eip155:137', 'eip155:8453', 'eip155:56'];
|
|
248
303
|
|
|
@@ -256,30 +311,42 @@ async function fetchStableCoins(
|
|
|
256
311
|
|
|
257
312
|
console.log(tag, `Checking stable coins on ${networksToCheck.length} networks`);
|
|
258
313
|
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
// Process each stable coin
|
|
268
|
-
for (const token of stableCoins) {
|
|
269
|
-
// Convert to ChartBalance format
|
|
270
|
-
const chartBalance = processPortfolioToken(token, primaryAddress, context, blockchains);
|
|
314
|
+
// Helper: timeout a promise
|
|
315
|
+
const withTimeout = <T>(p: Promise<T>, ms: number): Promise<T> => {
|
|
316
|
+
return new Promise<T>((resolve, reject) => {
|
|
317
|
+
const t = setTimeout(() => reject(new Error(`timeout ${ms}ms`)), ms);
|
|
318
|
+
p.then((v) => { clearTimeout(t); resolve(v); })
|
|
319
|
+
.catch((e) => { clearTimeout(t); reject(e); });
|
|
320
|
+
});
|
|
321
|
+
};
|
|
271
322
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
323
|
+
// Fetch stable coins for each network in parallel with short timeouts
|
|
324
|
+
const results = await Promise.allSettled(
|
|
325
|
+
networksToCheck.map(async (networkId) => {
|
|
326
|
+
try {
|
|
327
|
+
const response = await withTimeout(
|
|
328
|
+
pioneer.GetStableCoins({ networkId, address: primaryAddress }),
|
|
329
|
+
2000
|
|
330
|
+
);
|
|
331
|
+
const stableCoins = response?.data?.tokens || [];
|
|
332
|
+
console.log(tag, `Found ${stableCoins.length} stable coins on ${networkId}`);
|
|
333
|
+
|
|
334
|
+
for (const token of stableCoins) {
|
|
335
|
+
const chartBalance = processPortfolioToken(token, primaryAddress, context, blockchains);
|
|
336
|
+
if (chartBalance && !checkDuplicateBalance(balances, chartBalance.caip, chartBalance.pubkey)) {
|
|
337
|
+
balances.push(chartBalance);
|
|
338
|
+
console.log(tag, `Added stable coin: ${chartBalance.symbol} = ${chartBalance.balance}`);
|
|
339
|
+
}
|
|
276
340
|
}
|
|
341
|
+
} catch (error: any) {
|
|
342
|
+
console.error(tag, `Error fetching stable coins for ${networkId}:`, error?.message || error);
|
|
277
343
|
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
344
|
+
})
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
// Optional: log aggregate failures (for diagnostics only)
|
|
348
|
+
const failures = results.filter(r => r.status === 'rejected').length;
|
|
349
|
+
if (failures > 0) console.log(tag, `Stable coin fetch had ${failures} failures (non-blocking)`);
|
|
283
350
|
|
|
284
351
|
console.log(tag, `Stable coin redundancy complete. Total balances: ${balances.length}`);
|
|
285
352
|
}
|
package/src/charts/maya.ts
CHANGED
|
@@ -45,12 +45,15 @@ export async function getMayaCharts(
|
|
|
45
45
|
|
|
46
46
|
// Try to get MAYA token balance via a separate call
|
|
47
47
|
// This is a workaround for the portfolio API not returning MAYA tokens
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
// FIX: Wrap in object with pubkeys field to match server API
|
|
49
|
+
const mayaBalanceResponse = await pioneer.GetPortfolioBalances({
|
|
50
|
+
pubkeys: [
|
|
51
|
+
{
|
|
52
|
+
caip: 'cosmos:mayachain-mainnet-v1/denom:maya',
|
|
53
|
+
pubkey: mayaPubkey.address,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
});
|
|
54
57
|
|
|
55
58
|
console.log(
|
|
56
59
|
tag,
|
package/src/index.ts
CHANGED
|
@@ -1678,6 +1678,47 @@ export class SDK {
|
|
|
1678
1678
|
if (duplicatesRemoved > 0) {
|
|
1679
1679
|
}
|
|
1680
1680
|
|
|
1681
|
+
// FIX 1: Validate that all pubkeys have networks field
|
|
1682
|
+
const pubkeysWithoutNetworks = this.pubkeys.filter(
|
|
1683
|
+
pk => !pk.networks || !Array.isArray(pk.networks) || pk.networks.length === 0
|
|
1684
|
+
);
|
|
1685
|
+
|
|
1686
|
+
if (pubkeysWithoutNetworks.length > 0) {
|
|
1687
|
+
console.error(tag, 'ERROR: Some pubkeys missing networks field!');
|
|
1688
|
+
console.error(tag, 'Affected pubkeys:', pubkeysWithoutNetworks.length);
|
|
1689
|
+
|
|
1690
|
+
// Log details
|
|
1691
|
+
pubkeysWithoutNetworks.forEach(pk => {
|
|
1692
|
+
console.error(tag, ` - ${pk.note || pk.pubkey}: networks=${pk.networks}`);
|
|
1693
|
+
});
|
|
1694
|
+
|
|
1695
|
+
// Try to fix by matching with paths
|
|
1696
|
+
for (const pubkey of pubkeysWithoutNetworks) {
|
|
1697
|
+
const matchingPath = this.paths.find(p =>
|
|
1698
|
+
JSON.stringify(p.addressNList) === JSON.stringify(pubkey.addressNList)
|
|
1699
|
+
);
|
|
1700
|
+
|
|
1701
|
+
if (matchingPath && matchingPath.networks) {
|
|
1702
|
+
console.warn(tag, ` ⚠️ Auto-fixing: Adding networks from path ${matchingPath.note}`);
|
|
1703
|
+
pubkey.networks = matchingPath.networks;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
// Check if auto-fix worked
|
|
1708
|
+
const stillMissing = this.pubkeys.filter(
|
|
1709
|
+
pk => !pk.networks || !Array.isArray(pk.networks) || pk.networks.length === 0
|
|
1710
|
+
);
|
|
1711
|
+
|
|
1712
|
+
if (stillMissing.length > 0) {
|
|
1713
|
+
console.error(tag, `❌ CRITICAL: ${stillMissing.length} pubkeys still missing networks after auto-fix!`);
|
|
1714
|
+
stillMissing.forEach(pk => {
|
|
1715
|
+
console.error(tag, ` - ${pk.note || pk.pubkey}`);
|
|
1716
|
+
});
|
|
1717
|
+
} else {
|
|
1718
|
+
console.log(tag, `✅ Auto-fix successful: All pubkeys now have networks field`);
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1681
1722
|
// Emit event to notify that pubkeys have been set
|
|
1682
1723
|
this.events.emit('SET_PUBKEYS', this.pubkeys);
|
|
1683
1724
|
|
|
@@ -1701,6 +1742,24 @@ export class SDK {
|
|
|
1701
1742
|
throw new Error('Pioneer client not initialized. Call init() first.');
|
|
1702
1743
|
}
|
|
1703
1744
|
|
|
1745
|
+
// DIAGNOSTIC: Log input
|
|
1746
|
+
console.log('🔍 [DIAGNOSTIC] Input networks:', networkIds);
|
|
1747
|
+
console.log('🔍 [DIAGNOSTIC] Total pubkeys:', this.pubkeys.length);
|
|
1748
|
+
|
|
1749
|
+
// DIAGNOSTIC: Check which pubkeys have networks field
|
|
1750
|
+
const pubkeysWithNetworks = this.pubkeys.filter(p => p.networks && Array.isArray(p.networks));
|
|
1751
|
+
const pubkeysWithoutNetworks = this.pubkeys.filter(p => !p.networks || !Array.isArray(p.networks));
|
|
1752
|
+
|
|
1753
|
+
console.log('🔍 [DIAGNOSTIC] Pubkeys WITH networks:', pubkeysWithNetworks.length);
|
|
1754
|
+
console.log('🔍 [DIAGNOSTIC] Pubkeys WITHOUT networks:', pubkeysWithoutNetworks.length);
|
|
1755
|
+
|
|
1756
|
+
if (pubkeysWithoutNetworks.length > 0) {
|
|
1757
|
+
console.warn('⚠️ [WARNING] Some pubkeys missing networks field:');
|
|
1758
|
+
pubkeysWithoutNetworks.forEach(pk => {
|
|
1759
|
+
console.warn(` - ${pk.note || pk.pubkey.slice(0, 10)}: networks=${pk.networks}`);
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1704
1763
|
const assetQuery: { caip: string; pubkey: string }[] = [];
|
|
1705
1764
|
|
|
1706
1765
|
for (const networkId of networkIds) {
|
|
@@ -1711,7 +1770,7 @@ export class SDK {
|
|
|
1711
1770
|
}
|
|
1712
1771
|
|
|
1713
1772
|
const isEip155 = adjustedNetworkId.includes('eip155');
|
|
1714
|
-
|
|
1773
|
+
let pubkeys = this.pubkeys.filter(
|
|
1715
1774
|
(pubkey) =>
|
|
1716
1775
|
pubkey.networks &&
|
|
1717
1776
|
Array.isArray(pubkey.networks) &&
|
|
@@ -1721,21 +1780,73 @@ export class SDK {
|
|
|
1721
1780
|
}),
|
|
1722
1781
|
);
|
|
1723
1782
|
|
|
1783
|
+
// FIX 2: Fallback query for missing networks
|
|
1784
|
+
if (pubkeys.length === 0) {
|
|
1785
|
+
console.warn(tag, `⚠️ No pubkeys found for ${networkId} with networks field`);
|
|
1786
|
+
console.warn(tag, 'Attempting fallback: finding pubkeys by path matching');
|
|
1787
|
+
|
|
1788
|
+
// Find paths for this network
|
|
1789
|
+
const pathsForNetwork = this.paths.filter(p =>
|
|
1790
|
+
p.networks?.includes(networkId) ||
|
|
1791
|
+
(networkId.startsWith('eip155:') && p.networks?.includes('eip155:*'))
|
|
1792
|
+
);
|
|
1793
|
+
|
|
1794
|
+
// Find pubkeys matching those paths
|
|
1795
|
+
for (const path of pathsForNetwork) {
|
|
1796
|
+
const matchingPubkey = this.pubkeys.find(pk =>
|
|
1797
|
+
JSON.stringify(pk.addressNList) === JSON.stringify(path.addressNList)
|
|
1798
|
+
);
|
|
1799
|
+
|
|
1800
|
+
if (matchingPubkey) {
|
|
1801
|
+
console.warn(tag, ` ✓ Found pubkey via path matching: ${matchingPubkey.note || matchingPubkey.pubkey.slice(0, 10)}`);
|
|
1802
|
+
pubkeys.push(matchingPubkey);
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
if (pubkeys.length > 0) {
|
|
1807
|
+
console.warn(tag, ` ✅ Fallback successful: Found ${pubkeys.length} pubkeys for ${networkId}`);
|
|
1808
|
+
} else {
|
|
1809
|
+
console.error(tag, ` ❌ Fallback failed: No pubkeys found for ${networkId}`);
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1724
1813
|
const caipNative = await networkIdToCaip(networkId);
|
|
1725
1814
|
for (const pubkey of pubkeys) {
|
|
1726
1815
|
assetQuery.push({ caip: caipNative, pubkey: pubkey.pubkey });
|
|
1727
1816
|
}
|
|
1728
1817
|
}
|
|
1729
1818
|
|
|
1819
|
+
// DIAGNOSTIC: Log assetQuery before API call
|
|
1820
|
+
console.log('🔍 [DIAGNOSTIC] Built assetQuery with', assetQuery.length, 'entries');
|
|
1821
|
+
console.log('🔍 [DIAGNOSTIC] Sample queries:', assetQuery.slice(0, 5));
|
|
1822
|
+
|
|
1823
|
+
// Group by CAIP to see which chains are included
|
|
1824
|
+
const caipCounts = new Map<string, number>();
|
|
1825
|
+
for (const query of assetQuery) {
|
|
1826
|
+
caipCounts.set(query.caip, (caipCounts.get(query.caip) || 0) + 1);
|
|
1827
|
+
}
|
|
1828
|
+
console.log('🔍 [DIAGNOSTIC] Queries by chain:');
|
|
1829
|
+
caipCounts.forEach((count, caip) => {
|
|
1830
|
+
console.log(` - ${caip}: ${count} queries`);
|
|
1831
|
+
});
|
|
1832
|
+
|
|
1833
|
+
console.log(`⏱️ [PERF] Starting GetPortfolioBalances API call...`);
|
|
1834
|
+
const apiCallStart = performance.now();
|
|
1730
1835
|
console.time('GetPortfolioBalances Response Time');
|
|
1731
1836
|
|
|
1732
1837
|
try {
|
|
1733
|
-
|
|
1838
|
+
// FIX: Wrap assetQuery in object with pubkeys field to match server API
|
|
1839
|
+
let marketInfo = await this.pioneer.GetPortfolioBalances({ pubkeys: assetQuery });
|
|
1840
|
+
const apiCallTime = performance.now() - apiCallStart;
|
|
1734
1841
|
console.timeEnd('GetPortfolioBalances Response Time');
|
|
1842
|
+
console.log(`⏱️ [PERF] API call completed in ${apiCallTime.toFixed(0)}ms`);
|
|
1735
1843
|
|
|
1844
|
+
const enrichStart = performance.now();
|
|
1736
1845
|
let balances = marketInfo.data;
|
|
1846
|
+
console.log(`⏱️ [PERF] Received ${balances?.length || 0} balances from server`);
|
|
1737
1847
|
|
|
1738
1848
|
// Enrich balances with asset info
|
|
1849
|
+
console.log(`⏱️ [PERF] Starting balance enrichment...`);
|
|
1739
1850
|
for (let balance of balances) {
|
|
1740
1851
|
const assetInfo = this.assetsMap.get(balance.caip.toLowerCase()) || this.assetsMap.get(balance.caip);
|
|
1741
1852
|
if (!assetInfo) continue;
|
|
@@ -1751,8 +1862,12 @@ export class SDK {
|
|
|
1751
1862
|
color, // Add color from mapping
|
|
1752
1863
|
});
|
|
1753
1864
|
}
|
|
1865
|
+
const enrichTime = performance.now() - enrichStart;
|
|
1866
|
+
console.log(`⏱️ [PERF] Enrichment completed in ${enrichTime.toFixed(0)}ms`);
|
|
1867
|
+
|
|
1754
1868
|
this.balances = balances;
|
|
1755
1869
|
this.events.emit('SET_BALANCES', this.balances);
|
|
1870
|
+
console.log(`⏱️ [PERF] Total getBalancesForNetworks: ${(performance.now() - apiCallStart).toFixed(0)}ms`);
|
|
1756
1871
|
return this.balances;
|
|
1757
1872
|
} catch (apiError: any) {
|
|
1758
1873
|
console.error(tag, 'GetPortfolioBalances API call failed:', apiError);
|
|
@@ -1834,32 +1949,68 @@ export class SDK {
|
|
|
1834
1949
|
this.getCharts = async function () {
|
|
1835
1950
|
const tag = `${TAG} | getCharts | `;
|
|
1836
1951
|
try {
|
|
1837
|
-
console.log(tag, 'Fetching charts');
|
|
1952
|
+
console.log(tag, 'Fetching charts from batch endpoint');
|
|
1838
1953
|
|
|
1839
|
-
//
|
|
1840
|
-
const
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1954
|
+
// Build pubkeys array for batch request
|
|
1955
|
+
const pubkeysForBatch: { pubkey: string; caip: string }[] = [];
|
|
1956
|
+
|
|
1957
|
+
for (const pubkey of this.pubkeys) {
|
|
1958
|
+
const address = pubkey.address || pubkey.master || pubkey.pubkey;
|
|
1959
|
+
if (!address) continue;
|
|
1960
|
+
|
|
1961
|
+
// Get networks this pubkey supports
|
|
1962
|
+
const supportedNetworks = pubkey.networks || [];
|
|
1963
|
+
|
|
1964
|
+
// For each blockchain we're processing
|
|
1965
|
+
for (const blockchain of this.blockchains) {
|
|
1966
|
+
// Check if this pubkey supports this blockchain
|
|
1967
|
+
const supportsNetwork = supportedNetworks.some((net: string) =>
|
|
1968
|
+
net === blockchain ||
|
|
1969
|
+
(net.endsWith(':*') && blockchain.startsWith(net.replace(':*', ':')))
|
|
1970
|
+
);
|
|
1971
|
+
|
|
1972
|
+
if (supportsNetwork) {
|
|
1973
|
+
// Build the CAIP for this combination
|
|
1974
|
+
let caip: string;
|
|
1975
|
+
if (blockchain.startsWith('eip155:')) {
|
|
1976
|
+
caip = `${blockchain}/slip44:60`;
|
|
1977
|
+
} else {
|
|
1978
|
+
caip = `${blockchain}/slip44:0`; // Fallback for non-EVM
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
pubkeysForBatch.push({
|
|
1982
|
+
pubkey: address,
|
|
1983
|
+
caip: caip
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
console.log(tag, `Calling batch GetCharts with ${pubkeysForBatch.length} pubkeys`);
|
|
1990
|
+
|
|
1991
|
+
// Single batch call to get ALL charts data
|
|
1992
|
+
const chartsResponse = await this.pioneer.GetCharts({
|
|
1993
|
+
pubkeys: pubkeysForBatch
|
|
1994
|
+
});
|
|
1995
|
+
|
|
1996
|
+
const newBalances = chartsResponse?.data?.balances || [];
|
|
1997
|
+
console.log(tag, `Received ${newBalances.length} balances from batch endpoint`);
|
|
1847
1998
|
|
|
1848
1999
|
// Deduplicate balances using a Map with `identifier` as the key
|
|
1849
2000
|
const uniqueBalances = new Map(
|
|
1850
2001
|
[...this.balances, ...newBalances].map((balance: any) => [
|
|
1851
|
-
balance.identifier
|
|
2002
|
+
balance.identifier || `${balance.caip}:${balance.pubkey}`,
|
|
1852
2003
|
{
|
|
1853
2004
|
...balance,
|
|
1854
2005
|
type: balance.type || 'balance',
|
|
1855
2006
|
},
|
|
1856
2007
|
]),
|
|
1857
2008
|
);
|
|
1858
|
-
console.log(tag, 'uniqueBalances: ', uniqueBalances);
|
|
2009
|
+
console.log(tag, 'uniqueBalances: ', uniqueBalances.size);
|
|
1859
2010
|
|
|
1860
2011
|
// Convert Map back to array and set this.balances
|
|
1861
2012
|
this.balances = Array.from(uniqueBalances.values());
|
|
1862
|
-
console.log(tag, 'Updated this.balances: ', this.balances);
|
|
2013
|
+
console.log(tag, 'Updated this.balances: ', this.balances.length);
|
|
1863
2014
|
|
|
1864
2015
|
return this.balances;
|
|
1865
2016
|
} catch (e) {
|