@pioneer-platform/pioneer-sdk 8.15.14 → 8.15.15
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 +546 -648
- package/dist/index.es.js +546 -648
- package/dist/index.js +546 -648
- package/package.json +2 -2
- package/src/index.ts +222 -915
- package/src/utils/fee-reserves.ts +162 -0
- package/src/utils/network-helpers.ts +85 -0
- package/src/utils/path-discovery.ts +68 -0
- package/src/utils/portfolio-helpers.ts +209 -0
- package/src/utils/pubkey-management.ts +124 -0
- package/src/utils/pubkey-sync.ts +86 -0
- package/src/utils/sync-state.ts +93 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Pubkey synchronization utilities for blockchain wallets
|
|
2
|
+
|
|
3
|
+
import { addressNListToBIP32 } from '@pioneer-platform/pioneer-coins';
|
|
4
|
+
import { matchesNetwork, normalizeNetworkId } from './network-helpers.js';
|
|
5
|
+
|
|
6
|
+
const log = require('@pioneer-platform/loggerdog')();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Synchronize pubkeys for all blockchains
|
|
10
|
+
* Fetches missing pubkeys from hardware wallet
|
|
11
|
+
*/
|
|
12
|
+
export async function syncPubkeysForBlockchains(
|
|
13
|
+
blockchains: string[],
|
|
14
|
+
paths: any[],
|
|
15
|
+
existingPubkeys: any[],
|
|
16
|
+
keepKeySdk: any,
|
|
17
|
+
context: string,
|
|
18
|
+
getPubkeyFn: (blockchain: string, path: any, sdk: any, ctx: string) => Promise<any>,
|
|
19
|
+
addPubkeyCallback: (pubkey: any) => void,
|
|
20
|
+
tag: string
|
|
21
|
+
): Promise<void> {
|
|
22
|
+
for (const blockchain of blockchains) {
|
|
23
|
+
const networkId = normalizeNetworkId(blockchain);
|
|
24
|
+
const pathsForChain = paths.filter(path => matchesNetwork(path, networkId));
|
|
25
|
+
|
|
26
|
+
if (pathsForChain.length === 0) {
|
|
27
|
+
const availablePaths = paths.map(p => p.note || p.path || 'unnamed').join(', ');
|
|
28
|
+
throw new Error(
|
|
29
|
+
`No paths found for ${networkId}. ` +
|
|
30
|
+
`Available paths: ${availablePaths || 'none'}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
log.info(tag, `Syncing ${pathsForChain.length} pubkeys for ${networkId}...`);
|
|
35
|
+
|
|
36
|
+
for (const path of pathsForChain) {
|
|
37
|
+
const pathBip32 = addressNListToBIP32(path.addressNListMaster);
|
|
38
|
+
const existingPubkey = existingPubkeys.find(p => p.pathMaster === pathBip32);
|
|
39
|
+
|
|
40
|
+
if (!existingPubkey) {
|
|
41
|
+
log.debug(tag, `Fetching pubkey for path ${pathBip32}...`);
|
|
42
|
+
const newPubkey = await getPubkeyFn(blockchain, path, keepKeySdk, context);
|
|
43
|
+
|
|
44
|
+
if (!newPubkey) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Pubkey fetch failed for ${networkId} at path ${pathBip32}. ` +
|
|
47
|
+
`Ensure hardware wallet is connected and unlocked.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
addPubkeyCallback(newPubkey);
|
|
52
|
+
log.debug(tag, `✓ Added pubkey for ${pathBip32}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
log.info(tag, `✅ Pubkey sync complete. Total pubkeys: ${existingPubkeys.length}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Count missing pubkeys for blockchains
|
|
62
|
+
* Useful for progress estimation
|
|
63
|
+
*/
|
|
64
|
+
export function countMissingPubkeys(
|
|
65
|
+
blockchains: string[],
|
|
66
|
+
paths: any[],
|
|
67
|
+
existingPubkeys: any[]
|
|
68
|
+
): number {
|
|
69
|
+
let missingCount = 0;
|
|
70
|
+
|
|
71
|
+
for (const blockchain of blockchains) {
|
|
72
|
+
const networkId = normalizeNetworkId(blockchain);
|
|
73
|
+
const pathsForChain = paths.filter(path => matchesNetwork(path, networkId));
|
|
74
|
+
|
|
75
|
+
for (const path of pathsForChain) {
|
|
76
|
+
const pathBip32 = addressNListToBIP32(path.addressNListMaster);
|
|
77
|
+
const existingPubkey = existingPubkeys.find(p => p.pathMaster === pathBip32);
|
|
78
|
+
|
|
79
|
+
if (!existingPubkey) {
|
|
80
|
+
missingCount++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return missingCount;
|
|
86
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Sync state management and asset info utilities
|
|
2
|
+
|
|
3
|
+
const log = require('@pioneer-platform/loggerdog')();
|
|
4
|
+
const TAG = ' | sync-state | ';
|
|
5
|
+
|
|
6
|
+
export interface SyncState {
|
|
7
|
+
isSynced: boolean; // Has fresh data from full sync?
|
|
8
|
+
isInitialSync: boolean; // First sync (no cache)?
|
|
9
|
+
cacheAge: number; // Seconds since last cache update
|
|
10
|
+
syncProgress: number; // 0-100 percentage of completion
|
|
11
|
+
syncedChains: number; // Number of chains synced
|
|
12
|
+
totalChains: number; // Total chains to sync
|
|
13
|
+
lastSyncTime: number | null; // Timestamp of last successful sync
|
|
14
|
+
syncSource: 'cache' | 'fresh' | 'none'; // Where data came from
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolve asset info from multiple sources
|
|
19
|
+
* Priority: assetsMap > assetData discovery > placeholder
|
|
20
|
+
*/
|
|
21
|
+
export function resolveAssetInfo(
|
|
22
|
+
assetsMap: Map<string, any>,
|
|
23
|
+
assetData: any,
|
|
24
|
+
asset: any,
|
|
25
|
+
): any {
|
|
26
|
+
const tag = TAG + ' | resolveAssetInfo | ';
|
|
27
|
+
|
|
28
|
+
// Try to find the asset in the local assetsMap
|
|
29
|
+
let assetInfo = assetsMap.get(asset.caip.toLowerCase());
|
|
30
|
+
log.debug(tag, 'assetInfo from assetsMap:', assetInfo);
|
|
31
|
+
|
|
32
|
+
// Check discovery
|
|
33
|
+
const assetInfoDiscovery = assetData[asset.caip];
|
|
34
|
+
log.debug(tag, 'assetInfoDiscovery:', assetInfoDiscovery);
|
|
35
|
+
if (assetInfoDiscovery) {
|
|
36
|
+
assetInfo = assetInfoDiscovery;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// If the asset is not found, create a placeholder object
|
|
40
|
+
if (!assetInfo) {
|
|
41
|
+
log.debug(tag, 'Building placeholder asset for', asset.caip);
|
|
42
|
+
assetInfo = {
|
|
43
|
+
caip: asset.caip.toLowerCase(),
|
|
44
|
+
networkId: asset.networkId,
|
|
45
|
+
symbol: asset.symbol || 'UNKNOWN',
|
|
46
|
+
name: asset.name || 'Unknown Asset',
|
|
47
|
+
icon: asset.icon || 'https://pioneers.dev/coins/ethereum.png',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return assetInfo;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function createInitialSyncState(totalChains: number): SyncState {
|
|
55
|
+
return {
|
|
56
|
+
isSynced: false,
|
|
57
|
+
isInitialSync: true,
|
|
58
|
+
cacheAge: 0,
|
|
59
|
+
syncProgress: 0,
|
|
60
|
+
syncedChains: 0,
|
|
61
|
+
totalChains,
|
|
62
|
+
lastSyncTime: null,
|
|
63
|
+
syncSource: 'none'
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function createCacheSyncState(lastUpdated: number, totalChains: number): SyncState {
|
|
68
|
+
const cacheAge = lastUpdated ? Math.floor((Date.now() - lastUpdated) / 1000) : 0;
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
isSynced: true,
|
|
72
|
+
isInitialSync: false,
|
|
73
|
+
cacheAge,
|
|
74
|
+
syncProgress: 100,
|
|
75
|
+
syncedChains: totalChains,
|
|
76
|
+
totalChains,
|
|
77
|
+
lastSyncTime: lastUpdated || Date.now(),
|
|
78
|
+
syncSource: 'cache'
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function createFreshSyncState(totalChains: number): SyncState {
|
|
83
|
+
return {
|
|
84
|
+
isSynced: true,
|
|
85
|
+
isInitialSync: false,
|
|
86
|
+
cacheAge: 0,
|
|
87
|
+
syncProgress: 100,
|
|
88
|
+
syncedChains: totalChains,
|
|
89
|
+
totalChains,
|
|
90
|
+
lastSyncTime: Date.now(),
|
|
91
|
+
syncSource: 'fresh'
|
|
92
|
+
};
|
|
93
|
+
}
|