@pioneer-platform/pioneer-cache 1.5.0 → 1.7.0
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/CHANGELOG.md +12 -0
- package/dist/stores/portfolio-cache.js +83 -65
- package/package.json +1 -1
- package/src/stores/portfolio-cache.ts +32 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @pioneer-platform/pioneer-cache
|
|
2
2
|
|
|
3
|
+
## 1.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- chore: chore: chore: chore: chore: feat(pioneer): implement end-to-end Solana transaction signing
|
|
8
|
+
|
|
9
|
+
## 1.6.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- chore: chore: chore: chore: feat(pioneer): implement end-to-end Solana transaction signing
|
|
14
|
+
|
|
3
15
|
## 1.5.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -207,76 +207,94 @@ class PortfolioCache extends base_cache_1.BaseCache {
|
|
|
207
207
|
const { pubkeys } = params;
|
|
208
208
|
log.info(tag, `Fetching portfolio for ${pubkeys.length} pubkeys`);
|
|
209
209
|
const charts = [];
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
// Skip zero balances
|
|
224
|
-
const balanceNum = parseFloat(balanceInfo.balance);
|
|
225
|
-
if (isNaN(balanceNum) || balanceNum === 0) {
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
// Get asset metadata
|
|
229
|
-
const assetData = require('@pioneer-platform/pioneer-discovery').assetData;
|
|
230
|
-
const normalizedCaip = item.caip.toLowerCase();
|
|
231
|
-
let assetInfo = assetData[normalizedCaip] || assetData[item.caip.toUpperCase()] || assetData[item.caip] || {};
|
|
232
|
-
// EXPLICIT FIX: Force XRP to always be native (prevents token misclassification)
|
|
233
|
-
// GitHub Issue: XRP incorrectly showing as requiring BNB gas for sending
|
|
234
|
-
if (normalizedCaip === 'ripple:4109c6f2045fc7eff4cde8f9905d19c2/slip44:144') {
|
|
235
|
-
// Clone assetInfo and force type to native
|
|
236
|
-
assetInfo = { ...assetInfo, type: 'native' };
|
|
237
|
-
if (!assetInfo.symbol) {
|
|
238
|
-
log.warn(tag, `XRP asset lookup failed! Using fallback with forced native type.`);
|
|
239
|
-
assetInfo.symbol = 'XRP';
|
|
240
|
-
assetInfo.name = 'Ripple';
|
|
241
|
-
}
|
|
242
|
-
log.debug(tag, `XRP explicitly set to type: native`);
|
|
243
|
-
}
|
|
244
|
-
// Get price
|
|
245
|
-
let priceUsd = 0;
|
|
210
|
+
// BATCHING FIX: Process pubkeys in batches to prevent thundering herd
|
|
211
|
+
// Instead of 100+ parallel requests, process 10 at a time
|
|
212
|
+
const BATCH_SIZE = 10;
|
|
213
|
+
const BATCH_DELAY_MS = 100; // 100ms delay between batches
|
|
214
|
+
log.info(tag, `Using batched fetching: ${BATCH_SIZE} pubkeys per batch with ${BATCH_DELAY_MS}ms delay`);
|
|
215
|
+
for (let i = 0; i < pubkeys.length; i += BATCH_SIZE) {
|
|
216
|
+
const batch = pubkeys.slice(i, i + BATCH_SIZE);
|
|
217
|
+
const batchNum = Math.floor(i / BATCH_SIZE) + 1;
|
|
218
|
+
const totalBatches = Math.ceil(pubkeys.length / BATCH_SIZE);
|
|
219
|
+
log.debug(tag, `Processing batch ${batchNum}/${totalBatches} (${batch.length} pubkeys)`);
|
|
220
|
+
// Process this batch in parallel
|
|
221
|
+
const balancePromises = batch.map(async (item) => {
|
|
246
222
|
try {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
223
|
+
// Extract networkId from CAIP
|
|
224
|
+
const networkId = item.caip.split('/')[0];
|
|
225
|
+
// Fetch balance
|
|
226
|
+
const asset = { caip: item.caip };
|
|
227
|
+
const owner = { pubkey: item.pubkey };
|
|
228
|
+
const balanceInfo = await this.balanceModule.getBalance(asset, owner);
|
|
229
|
+
if (!balanceInfo || !balanceInfo.balance) {
|
|
230
|
+
log.debug(tag, `No balance for ${item.caip}/${item.pubkey.substring(0, 10)}...`);
|
|
231
|
+
return null;
|
|
250
232
|
}
|
|
233
|
+
// Skip zero balances
|
|
234
|
+
const balanceNum = parseFloat(balanceInfo.balance);
|
|
235
|
+
if (isNaN(balanceNum) || balanceNum === 0) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
// Get asset metadata
|
|
239
|
+
const assetData = require('@pioneer-platform/pioneer-discovery').assetData;
|
|
240
|
+
const normalizedCaip = item.caip.toLowerCase();
|
|
241
|
+
let assetInfo = assetData[normalizedCaip] || assetData[item.caip.toUpperCase()] || assetData[item.caip] || {};
|
|
242
|
+
// EXPLICIT FIX: Force XRP to always be native (prevents token misclassification)
|
|
243
|
+
// GitHub Issue: XRP incorrectly showing as requiring BNB gas for sending
|
|
244
|
+
if (normalizedCaip === 'ripple:4109c6f2045fc7eff4cde8f9905d19c2/slip44:144') {
|
|
245
|
+
// Clone assetInfo and force type to native
|
|
246
|
+
assetInfo = { ...assetInfo, type: 'native' };
|
|
247
|
+
if (!assetInfo.symbol) {
|
|
248
|
+
log.warn(tag, `XRP asset lookup failed! Using fallback with forced native type.`);
|
|
249
|
+
assetInfo.symbol = 'XRP';
|
|
250
|
+
assetInfo.name = 'Ripple';
|
|
251
|
+
}
|
|
252
|
+
log.debug(tag, `XRP explicitly set to type: native`);
|
|
253
|
+
}
|
|
254
|
+
// Get price
|
|
255
|
+
let priceUsd = 0;
|
|
256
|
+
try {
|
|
257
|
+
priceUsd = await this.marketsModule.getAssetPriceByCaip(item.caip);
|
|
258
|
+
if (isNaN(priceUsd) || priceUsd < 0) {
|
|
259
|
+
priceUsd = 0;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch (priceError) {
|
|
263
|
+
log.warn(tag, `Error fetching price for ${item.caip}:`, priceError);
|
|
264
|
+
}
|
|
265
|
+
const valueUsd = balanceNum * priceUsd;
|
|
266
|
+
const chartData = {
|
|
267
|
+
caip: item.caip,
|
|
268
|
+
pubkey: item.pubkey,
|
|
269
|
+
networkId,
|
|
270
|
+
symbol: assetInfo.symbol || 'UNKNOWN',
|
|
271
|
+
name: assetInfo.name || 'Unknown Asset',
|
|
272
|
+
balance: balanceInfo.balance,
|
|
273
|
+
priceUsd,
|
|
274
|
+
valueUsd,
|
|
275
|
+
icon: assetInfo.icon || '',
|
|
276
|
+
type: assetInfo.type || 'native',
|
|
277
|
+
decimal: assetInfo.decimal
|
|
278
|
+
};
|
|
279
|
+
return chartData;
|
|
251
280
|
}
|
|
252
|
-
catch (
|
|
253
|
-
log.
|
|
281
|
+
catch (error) {
|
|
282
|
+
log.error(tag, `Error fetching balance for ${item.caip}/${item.pubkey}:`, error);
|
|
283
|
+
return null;
|
|
254
284
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
icon: assetInfo.icon || '',
|
|
266
|
-
type: assetInfo.type || 'native',
|
|
267
|
-
decimal: assetInfo.decimal
|
|
268
|
-
};
|
|
269
|
-
return chartData;
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
log.error(tag, `Error fetching balance for ${item.caip}/${item.pubkey}:`, error);
|
|
273
|
-
return null;
|
|
285
|
+
});
|
|
286
|
+
// Await this batch
|
|
287
|
+
const results = await Promise.all(balancePromises);
|
|
288
|
+
// Filter out nulls and add to charts
|
|
289
|
+
const validCharts = results.filter((c) => c !== null);
|
|
290
|
+
charts.push(...validCharts);
|
|
291
|
+
log.debug(tag, `Batch ${batchNum}/${totalBatches} complete: ${validCharts.length}/${batch.length} successful`);
|
|
292
|
+
// Add delay between batches to prevent rate limiting
|
|
293
|
+
if (i + BATCH_SIZE < pubkeys.length) {
|
|
294
|
+
await new Promise(resolve => setTimeout(resolve, BATCH_DELAY_MS));
|
|
274
295
|
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Filter out nulls
|
|
278
|
-
const validCharts = results.filter((c) => c !== null);
|
|
279
|
-
charts.push(...validCharts);
|
|
296
|
+
}
|
|
297
|
+
log.info(tag, `Batched fetching complete: ${charts.length}/${pubkeys.length} assets fetched`);
|
|
280
298
|
// INTEGRATED: Fetch stable coins for EVM addresses (background operation)
|
|
281
299
|
// This ensures stable coins are ALWAYS in the cache and available instantly
|
|
282
300
|
const evmPubkey = pubkeys.find((p) => p.caip && p.caip.startsWith('eip155:'));
|
package/package.json
CHANGED
|
@@ -279,8 +279,22 @@ export class PortfolioCache extends BaseCache<PortfolioData> {
|
|
|
279
279
|
|
|
280
280
|
const charts: ChartData[] = [];
|
|
281
281
|
|
|
282
|
-
//
|
|
283
|
-
|
|
282
|
+
// BATCHING FIX: Process pubkeys in batches to prevent thundering herd
|
|
283
|
+
// Instead of 100+ parallel requests, process 10 at a time
|
|
284
|
+
const BATCH_SIZE = 10;
|
|
285
|
+
const BATCH_DELAY_MS = 100; // 100ms delay between batches
|
|
286
|
+
|
|
287
|
+
log.info(tag, `Using batched fetching: ${BATCH_SIZE} pubkeys per batch with ${BATCH_DELAY_MS}ms delay`);
|
|
288
|
+
|
|
289
|
+
for (let i = 0; i < pubkeys.length; i += BATCH_SIZE) {
|
|
290
|
+
const batch = pubkeys.slice(i, i + BATCH_SIZE);
|
|
291
|
+
const batchNum = Math.floor(i / BATCH_SIZE) + 1;
|
|
292
|
+
const totalBatches = Math.ceil(pubkeys.length / BATCH_SIZE);
|
|
293
|
+
|
|
294
|
+
log.debug(tag, `Processing batch ${batchNum}/${totalBatches} (${batch.length} pubkeys)`);
|
|
295
|
+
|
|
296
|
+
// Process this batch in parallel
|
|
297
|
+
const balancePromises = batch.map(async (item: { pubkey: string; caip: string }) => {
|
|
284
298
|
try {
|
|
285
299
|
// Extract networkId from CAIP
|
|
286
300
|
const networkId = item.caip.split('/')[0];
|
|
@@ -352,13 +366,24 @@ export class PortfolioCache extends BaseCache<PortfolioData> {
|
|
|
352
366
|
log.error(tag, `Error fetching balance for ${item.caip}/${item.pubkey}:`, error);
|
|
353
367
|
return null;
|
|
354
368
|
}
|
|
355
|
-
|
|
369
|
+
});
|
|
356
370
|
|
|
357
|
-
|
|
371
|
+
// Await this batch
|
|
372
|
+
const results = await Promise.all(balancePromises);
|
|
373
|
+
|
|
374
|
+
// Filter out nulls and add to charts
|
|
375
|
+
const validCharts = results.filter((c): c is ChartData => c !== null);
|
|
376
|
+
charts.push(...validCharts);
|
|
377
|
+
|
|
378
|
+
log.debug(tag, `Batch ${batchNum}/${totalBatches} complete: ${validCharts.length}/${batch.length} successful`);
|
|
379
|
+
|
|
380
|
+
// Add delay between batches to prevent rate limiting
|
|
381
|
+
if (i + BATCH_SIZE < pubkeys.length) {
|
|
382
|
+
await new Promise(resolve => setTimeout(resolve, BATCH_DELAY_MS));
|
|
383
|
+
}
|
|
384
|
+
}
|
|
358
385
|
|
|
359
|
-
|
|
360
|
-
const validCharts = results.filter((c): c is ChartData => c !== null);
|
|
361
|
-
charts.push(...validCharts);
|
|
386
|
+
log.info(tag, `Batched fetching complete: ${charts.length}/${pubkeys.length} assets fetched`);
|
|
362
387
|
|
|
363
388
|
// INTEGRATED: Fetch stable coins for EVM addresses (background operation)
|
|
364
389
|
// This ensures stable coins are ALWAYS in the cache and available instantly
|