@pioneer-platform/pioneer-cache 3.0.4 → 3.0.7
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/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
> @pioneer-platform/pioneer-cache@3.0.
|
|
3
|
+
> @pioneer-platform/pioneer-cache@3.0.7 build /Users/highlander/WebstormProjects/keepkey-stack/projects/pioneer/modules/pioneer/pioneer-cache
|
|
4
4
|
> tsc
|
|
5
5
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @pioneer-platform/pioneer-cache
|
|
2
2
|
|
|
3
|
+
## 3.0.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [5df7310]
|
|
8
|
+
- @pioneer-platform/pioneer-discovery@10.0.9
|
|
9
|
+
|
|
10
|
+
## 3.0.6
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- chore: chore: chore: chore: chore: version bump pioneer-sdk and pioneer-server for perf fixes
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
- @pioneer-platform/pioneer-discovery@10.0.8
|
|
17
|
+
|
|
18
|
+
## 3.0.5
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- chore: chore: chore: chore: chore: version bump pioneer-sdk and pioneer-server for perf fixes
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @pioneer-platform/pioneer-discovery@10.0.7
|
|
25
|
+
|
|
3
26
|
## 3.0.4
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
|
@@ -66,6 +66,11 @@ export declare class PortfolioCache extends BaseCache<PortfolioData> {
|
|
|
66
66
|
* INTEGRATED: Part of portfolio background refresh, no direct blockchain queries from endpoints
|
|
67
67
|
*/
|
|
68
68
|
private fetchCustomTokens;
|
|
69
|
+
/**
|
|
70
|
+
* Fetch SPL token balances for a Solana address
|
|
71
|
+
* INTEGRATED: Part of portfolio background refresh
|
|
72
|
+
*/
|
|
73
|
+
private fetchSplTokens;
|
|
69
74
|
/**
|
|
70
75
|
* Fetch portfolio from blockchain APIs
|
|
71
76
|
*
|
|
@@ -295,6 +295,88 @@ class PortfolioCache extends base_cache_1.BaseCache {
|
|
|
295
295
|
return customCharts;
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Fetch SPL token balances for a Solana address
|
|
300
|
+
* INTEGRATED: Part of portfolio background refresh
|
|
301
|
+
*/
|
|
302
|
+
async fetchSplTokens(address) {
|
|
303
|
+
const tag = this.TAG + 'fetchSplTokens | ';
|
|
304
|
+
const splCharts = [];
|
|
305
|
+
try {
|
|
306
|
+
// Get Solana network module (from global or require)
|
|
307
|
+
const globalNetworks = global.pioneerNetworks;
|
|
308
|
+
const solana = globalNetworks?.solana || require('@pioneer-platform/solana-network');
|
|
309
|
+
if (!solana || !solana.getTokenBalances) {
|
|
310
|
+
log.warn(tag, 'Solana network module not available, skipping SPL token fetch');
|
|
311
|
+
return splCharts;
|
|
312
|
+
}
|
|
313
|
+
const tokenAccounts = await Promise.race([
|
|
314
|
+
solana.getTokenBalances(address),
|
|
315
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 10000))
|
|
316
|
+
]).catch((err) => {
|
|
317
|
+
log.warn(tag, `SPL token fetch failed: ${err.message}`);
|
|
318
|
+
return [];
|
|
319
|
+
});
|
|
320
|
+
if (!tokenAccounts || tokenAccounts.length === 0) {
|
|
321
|
+
log.debug(tag, 'No SPL token accounts found');
|
|
322
|
+
return splCharts;
|
|
323
|
+
}
|
|
324
|
+
log.info(tag, `Found ${tokenAccounts.length} SPL token accounts, enriching with metadata...`);
|
|
325
|
+
const assetData = require('@pioneer-platform/pioneer-discovery').assetData;
|
|
326
|
+
const SOLANA_NETWORK_ID = 'solana:5eykt4usfv8p8njdtrepy1vzqkqzkvdp';
|
|
327
|
+
for (const token of tokenAccounts) {
|
|
328
|
+
// Skip zero-balance tokens
|
|
329
|
+
if (!token.balance || token.balance === 0)
|
|
330
|
+
continue;
|
|
331
|
+
const tokenCaip = `${SOLANA_NETWORK_ID}/token:${token.mint}`;
|
|
332
|
+
// Look up metadata from pioneer-discovery
|
|
333
|
+
const tokenInfo = assetData[tokenCaip] || assetData[tokenCaip.toLowerCase()] || {};
|
|
334
|
+
// Get price from markets module
|
|
335
|
+
let priceUsd = 0;
|
|
336
|
+
try {
|
|
337
|
+
priceUsd = await this.marketsModule.getAssetPriceByCaip(tokenCaip);
|
|
338
|
+
if (isNaN(priceUsd) || priceUsd < 0)
|
|
339
|
+
priceUsd = 0;
|
|
340
|
+
}
|
|
341
|
+
catch (priceError) {
|
|
342
|
+
// Try with lowercase CAIP
|
|
343
|
+
try {
|
|
344
|
+
priceUsd = await this.marketsModule.getAssetPriceByCaip(tokenCaip.toLowerCase());
|
|
345
|
+
if (isNaN(priceUsd) || priceUsd < 0)
|
|
346
|
+
priceUsd = 0;
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// No price available
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const balanceStr = token.uiAmountString || String(token.balance);
|
|
353
|
+
const balanceNum = parseFloat(balanceStr);
|
|
354
|
+
const valueUsd = balanceNum * priceUsd;
|
|
355
|
+
const chartData = {
|
|
356
|
+
caip: tokenCaip,
|
|
357
|
+
pubkey: address,
|
|
358
|
+
networkId: SOLANA_NETWORK_ID,
|
|
359
|
+
symbol: tokenInfo.symbol || token.mint.substring(0, 6),
|
|
360
|
+
name: tokenInfo.name || `SPL Token (${token.mint.substring(0, 8)}...)`,
|
|
361
|
+
balance: balanceStr,
|
|
362
|
+
priceUsd,
|
|
363
|
+
valueUsd,
|
|
364
|
+
icon: tokenInfo.icon || '',
|
|
365
|
+
type: 'token',
|
|
366
|
+
decimal: token.decimals ?? tokenInfo.decimals
|
|
367
|
+
};
|
|
368
|
+
splCharts.push(chartData);
|
|
369
|
+
log.debug(tag, `SPL: ${chartData.symbol} = ${balanceStr} ($${valueUsd.toFixed(2)})`);
|
|
370
|
+
}
|
|
371
|
+
log.info(tag, `Fetched ${splCharts.length} non-zero SPL token balances`);
|
|
372
|
+
return splCharts;
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
const errorMsg = error.message || String(error);
|
|
376
|
+
log.error(tag, `Error fetching SPL tokens: ${errorMsg}`);
|
|
377
|
+
return splCharts;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
298
380
|
/**
|
|
299
381
|
* Fetch portfolio from blockchain APIs
|
|
300
382
|
*
|
|
@@ -410,6 +492,22 @@ class PortfolioCache extends base_cache_1.BaseCache {
|
|
|
410
492
|
}
|
|
411
493
|
}
|
|
412
494
|
log.info(tag, `Batched fetching complete: ${charts.length}/${pubkeys.length} assets fetched`);
|
|
495
|
+
// INTEGRATED: Fetch SPL token balances for Solana addresses (background operation)
|
|
496
|
+
// SPL tokens are returned as splTokens[] from the balance module's SOLANA case
|
|
497
|
+
const solPubkey = pubkeys.find((p) => p.caip && p.caip.startsWith('solana:') && p.caip.includes('/slip44:501'));
|
|
498
|
+
if (solPubkey) {
|
|
499
|
+
const solAddress = solPubkey.pubkey;
|
|
500
|
+
log.info(tag, `Fetching SPL tokens for Solana address: ${solAddress.substring(0, 10)}...`);
|
|
501
|
+
const splCharts = await this.fetchSplTokens(solAddress);
|
|
502
|
+
// Add SPL tokens to charts (deduplicate by CAIP+pubkey)
|
|
503
|
+
for (const splToken of splCharts) {
|
|
504
|
+
const isDuplicate = charts.some(c => c.caip === splToken.caip && c.pubkey === splToken.pubkey);
|
|
505
|
+
if (!isDuplicate) {
|
|
506
|
+
charts.push(splToken);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
log.info(tag, `Added ${splCharts.length} SPL tokens to portfolio`);
|
|
510
|
+
}
|
|
413
511
|
// INTEGRATED: Fetch stable coins for EVM addresses (background operation)
|
|
414
512
|
// This ensures stable coins are ALWAYS in the cache and available instantly
|
|
415
513
|
const evmPubkey = pubkeys.find((p) => p.caip && p.caip.startsWith('eip155:'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pioneer-platform/pioneer-cache",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.7",
|
|
4
4
|
"description": "Unified caching system for Pioneer platform with Redis backend",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@pioneer-platform/loggerdog": "8.11.0",
|
|
18
|
+
"@pioneer-platform/pioneer-caip": "9.27.10",
|
|
18
19
|
"@pioneer-platform/redis-queue": "8.12.21",
|
|
19
20
|
"@pioneer-platform/default-redis": "8.11.11",
|
|
20
|
-
"@pioneer-platform/pioneer-discovery": "10.0.
|
|
21
|
-
"@pioneer-platform/pioneer-caip": "9.27.10"
|
|
21
|
+
"@pioneer-platform/pioneer-discovery": "10.0.9"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/jest": "^29.5.0",
|
|
@@ -387,6 +387,98 @@ export class PortfolioCache extends BaseCache<PortfolioData> {
|
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Fetch SPL token balances for a Solana address
|
|
392
|
+
* INTEGRATED: Part of portfolio background refresh
|
|
393
|
+
*/
|
|
394
|
+
private async fetchSplTokens(address: string): Promise<ChartData[]> {
|
|
395
|
+
const tag = this.TAG + 'fetchSplTokens | ';
|
|
396
|
+
const splCharts: ChartData[] = [];
|
|
397
|
+
|
|
398
|
+
try {
|
|
399
|
+
// Get Solana network module (from global or require)
|
|
400
|
+
const globalNetworks = (global as any).pioneerNetworks;
|
|
401
|
+
const solana = globalNetworks?.solana || require('@pioneer-platform/solana-network');
|
|
402
|
+
|
|
403
|
+
if (!solana || !solana.getTokenBalances) {
|
|
404
|
+
log.warn(tag, 'Solana network module not available, skipping SPL token fetch');
|
|
405
|
+
return splCharts;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const tokenAccounts = await Promise.race([
|
|
409
|
+
solana.getTokenBalances(address),
|
|
410
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 10000))
|
|
411
|
+
]).catch((err: any) => {
|
|
412
|
+
log.warn(tag, `SPL token fetch failed: ${err.message}`);
|
|
413
|
+
return [];
|
|
414
|
+
}) as any[];
|
|
415
|
+
|
|
416
|
+
if (!tokenAccounts || tokenAccounts.length === 0) {
|
|
417
|
+
log.debug(tag, 'No SPL token accounts found');
|
|
418
|
+
return splCharts;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
log.info(tag, `Found ${tokenAccounts.length} SPL token accounts, enriching with metadata...`);
|
|
422
|
+
|
|
423
|
+
const assetData = require('@pioneer-platform/pioneer-discovery').assetData;
|
|
424
|
+
const SOLANA_NETWORK_ID = 'solana:5eykt4usfv8p8njdtrepy1vzqkqzkvdp';
|
|
425
|
+
|
|
426
|
+
for (const token of tokenAccounts) {
|
|
427
|
+
// Skip zero-balance tokens
|
|
428
|
+
if (!token.balance || token.balance === 0) continue;
|
|
429
|
+
|
|
430
|
+
const tokenCaip = `${SOLANA_NETWORK_ID}/token:${token.mint}`;
|
|
431
|
+
|
|
432
|
+
// Look up metadata from pioneer-discovery
|
|
433
|
+
const tokenInfo = assetData[tokenCaip] || assetData[tokenCaip.toLowerCase()] || {};
|
|
434
|
+
|
|
435
|
+
// Get price from markets module
|
|
436
|
+
let priceUsd = 0;
|
|
437
|
+
try {
|
|
438
|
+
priceUsd = await this.marketsModule.getAssetPriceByCaip(tokenCaip);
|
|
439
|
+
if (isNaN(priceUsd) || priceUsd < 0) priceUsd = 0;
|
|
440
|
+
} catch (priceError) {
|
|
441
|
+
// Try with lowercase CAIP
|
|
442
|
+
try {
|
|
443
|
+
priceUsd = await this.marketsModule.getAssetPriceByCaip(tokenCaip.toLowerCase());
|
|
444
|
+
if (isNaN(priceUsd) || priceUsd < 0) priceUsd = 0;
|
|
445
|
+
} catch {
|
|
446
|
+
// No price available
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const balanceStr = token.uiAmountString || String(token.balance);
|
|
451
|
+
const balanceNum = parseFloat(balanceStr);
|
|
452
|
+
const valueUsd = balanceNum * priceUsd;
|
|
453
|
+
|
|
454
|
+
const chartData: ChartData = {
|
|
455
|
+
caip: tokenCaip,
|
|
456
|
+
pubkey: address,
|
|
457
|
+
networkId: SOLANA_NETWORK_ID,
|
|
458
|
+
symbol: tokenInfo.symbol || token.mint.substring(0, 6),
|
|
459
|
+
name: tokenInfo.name || `SPL Token (${token.mint.substring(0, 8)}...)`,
|
|
460
|
+
balance: balanceStr,
|
|
461
|
+
priceUsd,
|
|
462
|
+
valueUsd,
|
|
463
|
+
icon: tokenInfo.icon || '',
|
|
464
|
+
type: 'token',
|
|
465
|
+
decimal: token.decimals ?? tokenInfo.decimals
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
splCharts.push(chartData);
|
|
469
|
+
log.debug(tag, `SPL: ${chartData.symbol} = ${balanceStr} ($${valueUsd.toFixed(2)})`);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
log.info(tag, `Fetched ${splCharts.length} non-zero SPL token balances`);
|
|
473
|
+
return splCharts;
|
|
474
|
+
|
|
475
|
+
} catch (error: any) {
|
|
476
|
+
const errorMsg = error.message || String(error);
|
|
477
|
+
log.error(tag, `Error fetching SPL tokens: ${errorMsg}`);
|
|
478
|
+
return splCharts;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
390
482
|
/**
|
|
391
483
|
* Fetch portfolio from blockchain APIs
|
|
392
484
|
*
|
|
@@ -523,6 +615,28 @@ export class PortfolioCache extends BaseCache<PortfolioData> {
|
|
|
523
615
|
|
|
524
616
|
log.info(tag, `Batched fetching complete: ${charts.length}/${pubkeys.length} assets fetched`);
|
|
525
617
|
|
|
618
|
+
// INTEGRATED: Fetch SPL token balances for Solana addresses (background operation)
|
|
619
|
+
// SPL tokens are returned as splTokens[] from the balance module's SOLANA case
|
|
620
|
+
const solPubkey = pubkeys.find(
|
|
621
|
+
(p: any) => p.caip && p.caip.startsWith('solana:') && p.caip.includes('/slip44:501')
|
|
622
|
+
);
|
|
623
|
+
if (solPubkey) {
|
|
624
|
+
const solAddress = solPubkey.pubkey;
|
|
625
|
+
log.info(tag, `Fetching SPL tokens for Solana address: ${solAddress.substring(0, 10)}...`);
|
|
626
|
+
const splCharts = await this.fetchSplTokens(solAddress);
|
|
627
|
+
|
|
628
|
+
// Add SPL tokens to charts (deduplicate by CAIP+pubkey)
|
|
629
|
+
for (const splToken of splCharts) {
|
|
630
|
+
const isDuplicate = charts.some(c =>
|
|
631
|
+
c.caip === splToken.caip && c.pubkey === splToken.pubkey
|
|
632
|
+
);
|
|
633
|
+
if (!isDuplicate) {
|
|
634
|
+
charts.push(splToken);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
log.info(tag, `Added ${splCharts.length} SPL tokens to portfolio`);
|
|
638
|
+
}
|
|
639
|
+
|
|
526
640
|
// INTEGRATED: Fetch stable coins for EVM addresses (background operation)
|
|
527
641
|
// This ensures stable coins are ALWAYS in the cache and available instantly
|
|
528
642
|
const evmPubkey = pubkeys.find(
|