@pioneer-platform/pioneer-sdk 4.21.1 → 4.21.3
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 +464 -446
- package/dist/index.es.js +464 -446
- package/dist/index.js +464 -446
- package/package.json +2 -2
- package/src/charts/custom-tokens.ts +144 -0
- package/src/charts/evm.ts +5 -0
- package/src/index.ts +28 -18
- package/src/utils/build-dashboard.ts +7 -0
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "highlander",
|
|
3
3
|
"name": "@pioneer-platform/pioneer-sdk",
|
|
4
|
-
"version": "4.21.
|
|
4
|
+
"version": "4.21.3",
|
|
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
|
-
"@pioneer-platform/pioneer-client": "^9.10.
|
|
9
|
+
"@pioneer-platform/pioneer-client": "^9.10.7",
|
|
10
10
|
"@pioneer-platform/pioneer-coins": "^9.11.0",
|
|
11
11
|
"@pioneer-platform/pioneer-discovery": "^0.8.0",
|
|
12
12
|
"@pioneer-platform/pioneer-events": "^8.11.0",
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Tokens Chart Module
|
|
3
|
+
*
|
|
4
|
+
* Fetches user-defined custom token balances from MongoDB-backed server endpoint
|
|
5
|
+
* Follows the stablecoin chart pattern for network-specific token discovery
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ChartBalance, ChartParams, PortfolioToken } from './types';
|
|
9
|
+
import { hydrateAssetData, checkDuplicateBalance, createBalanceIdentifier } from './utils';
|
|
10
|
+
|
|
11
|
+
const tag = '| charts-custom-tokens |';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fetch custom tokens for a user address across all EVM networks
|
|
15
|
+
*
|
|
16
|
+
* This function queries the server for user-defined custom tokens and fetches their balances.
|
|
17
|
+
* Custom tokens are stored in MongoDB per user address with network-specific configuration.
|
|
18
|
+
*
|
|
19
|
+
* @param params Chart parameters including pioneer client, pubkeys, and blockchains
|
|
20
|
+
* @param balances Existing balances array (to check for duplicates)
|
|
21
|
+
* @returns Promise that resolves when custom tokens are added to balances array
|
|
22
|
+
*/
|
|
23
|
+
export async function fetchCustomTokens(
|
|
24
|
+
params: ChartParams,
|
|
25
|
+
balances: ChartBalance[]
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
const { pioneer, pubkeys, blockchains, context } = params;
|
|
28
|
+
|
|
29
|
+
console.log(tag, 'Fetching custom tokens...');
|
|
30
|
+
|
|
31
|
+
// Find the primary EVM address
|
|
32
|
+
const evmPubkey = pubkeys.find(
|
|
33
|
+
(e: any) => e.networks && Array.isArray(e.networks) && e.networks.includes('eip155:*')
|
|
34
|
+
);
|
|
35
|
+
const primaryAddress = evmPubkey?.address || evmPubkey?.master;
|
|
36
|
+
|
|
37
|
+
if (!primaryAddress) {
|
|
38
|
+
console.log(tag, 'No EVM address found, skipping custom tokens');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(tag, 'Using EVM address for custom tokens:', primaryAddress);
|
|
43
|
+
|
|
44
|
+
// Networks that support custom tokens endpoint (all EVM networks)
|
|
45
|
+
const supportedNetworks = blockchains.filter((net: string) => net.startsWith('eip155:'));
|
|
46
|
+
|
|
47
|
+
if (supportedNetworks.length === 0) {
|
|
48
|
+
console.log(tag, 'No EVM networks for custom tokens');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log(tag, `Checking custom tokens on ${supportedNetworks.length} networks`);
|
|
53
|
+
|
|
54
|
+
// Fetch custom tokens for each network
|
|
55
|
+
for (const networkId of supportedNetworks) {
|
|
56
|
+
try {
|
|
57
|
+
const response = await pioneer.GetCustomTokens({ networkId, address: primaryAddress });
|
|
58
|
+
const customTokens = response?.data?.tokens || [];
|
|
59
|
+
|
|
60
|
+
console.log(tag, `Found ${customTokens.length} custom tokens on ${networkId}`);
|
|
61
|
+
|
|
62
|
+
// Process each custom token
|
|
63
|
+
for (const token of customTokens) {
|
|
64
|
+
// Convert to ChartBalance format
|
|
65
|
+
const chartBalance = processCustomToken(token, primaryAddress, context, blockchains);
|
|
66
|
+
|
|
67
|
+
// Add if not already in balances (avoid duplicates)
|
|
68
|
+
if (chartBalance && !checkDuplicateBalance(balances, chartBalance.caip, chartBalance.pubkey)) {
|
|
69
|
+
balances.push(chartBalance);
|
|
70
|
+
console.log(tag, `Added custom token: ${chartBalance.symbol} = ${chartBalance.balance}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch (error: any) {
|
|
74
|
+
console.error(tag, `Error fetching custom tokens for ${networkId}:`, error.message);
|
|
75
|
+
// Continue with other networks even if one fails
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log(tag, `Custom tokens complete. Total balances: ${balances.length}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Process a custom token into ChartBalance format
|
|
84
|
+
* Follows the same pattern as processPortfolioToken in evm.ts
|
|
85
|
+
*/
|
|
86
|
+
function processCustomToken(
|
|
87
|
+
token: PortfolioToken,
|
|
88
|
+
primaryAddress: string,
|
|
89
|
+
context: string,
|
|
90
|
+
blockchains: string[]
|
|
91
|
+
): ChartBalance | null {
|
|
92
|
+
if (!token.assetCaip || !token.networkId) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Extract the networkId from the assetCaip
|
|
97
|
+
let extractedNetworkId = token.networkId;
|
|
98
|
+
|
|
99
|
+
// For tokens with special formats, extract network part
|
|
100
|
+
if (token.assetCaip.includes('/denom:')) {
|
|
101
|
+
const parts = token.assetCaip.split('/denom:');
|
|
102
|
+
if (parts.length > 0) {
|
|
103
|
+
extractedNetworkId = parts[0];
|
|
104
|
+
}
|
|
105
|
+
} else if (token.networkId && token.networkId.includes('/')) {
|
|
106
|
+
extractedNetworkId = token.networkId.split('/')[0];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Accept ALL EIP155 chains (since we have eip155:* pubkey)
|
|
110
|
+
const isEip155 = extractedNetworkId.startsWith('eip155:');
|
|
111
|
+
if (!isEip155 && !blockchains.includes(extractedNetworkId)) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Hydrate token with assetData
|
|
116
|
+
const tokenAssetInfo = hydrateAssetData(token.assetCaip);
|
|
117
|
+
|
|
118
|
+
// Use consistent pubkey
|
|
119
|
+
const tokenPubkey = token.pubkey || primaryAddress;
|
|
120
|
+
|
|
121
|
+
const chartBalance: ChartBalance = {
|
|
122
|
+
context,
|
|
123
|
+
chart: 'pioneer',
|
|
124
|
+
contextType: context.split(':')[0],
|
|
125
|
+
name: tokenAssetInfo?.name || token.token?.name || 'Unknown Custom Token',
|
|
126
|
+
caip: token.assetCaip,
|
|
127
|
+
icon: tokenAssetInfo?.icon || token.token?.icon || '',
|
|
128
|
+
pubkey: tokenPubkey,
|
|
129
|
+
ticker: tokenAssetInfo?.symbol || token.token?.symbol || 'UNK',
|
|
130
|
+
ref: `${context}${token.assetCaip}`,
|
|
131
|
+
identifier: createBalanceIdentifier(token.assetCaip, tokenPubkey),
|
|
132
|
+
networkId: extractedNetworkId,
|
|
133
|
+
symbol: tokenAssetInfo?.symbol || token.token?.symbol || 'UNK',
|
|
134
|
+
type: tokenAssetInfo?.type || 'erc20',
|
|
135
|
+
token: true, // Custom tokens are always tokens
|
|
136
|
+
decimal: tokenAssetInfo?.decimal || token.token?.decimal,
|
|
137
|
+
balance: token.token?.balance?.toString() || '0',
|
|
138
|
+
priceUsd: token.token?.price || 0,
|
|
139
|
+
valueUsd: token.token?.balanceUSD || 0,
|
|
140
|
+
updated: new Date().getTime(),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return chartBalance;
|
|
144
|
+
}
|
package/src/charts/evm.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ChartBalance, ChartParams, PortfolioBalance, PortfolioToken } from './types';
|
|
2
2
|
import { hydrateAssetData, checkDuplicateBalance, createBalanceIdentifier } from './utils';
|
|
3
|
+
import { fetchCustomTokens } from './custom-tokens';
|
|
3
4
|
|
|
4
5
|
const tag = '| charts-evm |';
|
|
5
6
|
|
|
@@ -32,6 +33,10 @@ export async function getEvmCharts(params: ChartParams): Promise<ChartBalance[]>
|
|
|
32
33
|
// This ensures USDC/USDT balances are always available even if Zapper fails
|
|
33
34
|
await fetchStableCoins(pioneer, primaryAddress, blockchains, balances, context);
|
|
34
35
|
|
|
36
|
+
// CUSTOM TOKENS: Fetch user-defined custom tokens from MongoDB-backed endpoint
|
|
37
|
+
// This ensures user's custom tokens are always included in their portfolio
|
|
38
|
+
await fetchCustomTokens({ blockchains, pioneer, pubkeys, context }, balances);
|
|
39
|
+
|
|
35
40
|
try {
|
|
36
41
|
// NOTE: Zapper API returns portfolio data across ALL networks for a given address
|
|
37
42
|
// We use eip155:1 as the networkId parameter, but Zapper will return data for all EVM chains
|
package/src/index.ts
CHANGED
|
@@ -188,14 +188,6 @@ export class SDK {
|
|
|
188
188
|
if (config.blockchains && config.blockchains.length !== this.blockchains.length) {
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
// Initialize pubkeys with deduplication if provided in config
|
|
192
|
-
if (config.pubkeys && config.pubkeys.length > 0) {
|
|
193
|
-
this.setPubkeys(config.pubkeys);
|
|
194
|
-
} else {
|
|
195
|
-
this.pubkeys = [];
|
|
196
|
-
this.pubkeySet.clear();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
191
|
this.balances = config.balances || [];
|
|
200
192
|
this.nodes = config.nodes || [];
|
|
201
193
|
this.charts = ['covalent', 'zapper'];
|
|
@@ -288,6 +280,15 @@ export class SDK {
|
|
|
288
280
|
}
|
|
289
281
|
};
|
|
290
282
|
|
|
283
|
+
// Initialize pubkeys with deduplication if provided in config
|
|
284
|
+
// IMPORTANT: This must come AFTER setPubkeys is defined above
|
|
285
|
+
if (config.pubkeys && config.pubkeys.length > 0) {
|
|
286
|
+
this.setPubkeys(config.pubkeys);
|
|
287
|
+
} else {
|
|
288
|
+
this.pubkeys = [];
|
|
289
|
+
this.pubkeySet.clear();
|
|
290
|
+
}
|
|
291
|
+
|
|
291
292
|
// Fast portfolio loading from kkapi:// cache
|
|
292
293
|
this.getUnifiedPortfolio = async function () {
|
|
293
294
|
const tag = `${TAG} | getUnifiedPortfolio | `;
|
|
@@ -952,7 +953,7 @@ export class SDK {
|
|
|
952
953
|
throw e;
|
|
953
954
|
}
|
|
954
955
|
};
|
|
955
|
-
this.signTx = async function (unsignedTx: any) {
|
|
956
|
+
this.signTx = async function (caip: string, unsignedTx: any) {
|
|
956
957
|
let tag = TAG + ' | signTx | ';
|
|
957
958
|
try {
|
|
958
959
|
const transactionDependencies = {
|
|
@@ -966,7 +967,7 @@ export class SDK {
|
|
|
966
967
|
keepKeySdk: this.keepKeySdk,
|
|
967
968
|
};
|
|
968
969
|
let txManager = new TransactionManager(transactionDependencies, this.events);
|
|
969
|
-
let signedTx = await txManager.sign(unsignedTx);
|
|
970
|
+
let signedTx = await txManager.sign({ caip, unsignedTx });
|
|
970
971
|
return signedTx;
|
|
971
972
|
} catch (e) {
|
|
972
973
|
console.error(e);
|
|
@@ -1119,13 +1120,12 @@ export class SDK {
|
|
|
1119
1120
|
}
|
|
1120
1121
|
|
|
1121
1122
|
let quote = {
|
|
1122
|
-
|
|
1123
|
-
sellAsset: this.assetContext,
|
|
1123
|
+
sellAsset: this.assetContext.caip, // Send CAIP string, not object
|
|
1124
1124
|
sellAmount: inputAmount.toPrecision(8),
|
|
1125
|
-
buyAsset: this.outboundAssetContext,
|
|
1125
|
+
buyAsset: this.outboundAssetContext.caip, // Send CAIP string, not object
|
|
1126
1126
|
recipientAddress, // Fill this based on your logic
|
|
1127
1127
|
senderAddress, // Fill this based on your logic
|
|
1128
|
-
slippage:
|
|
1128
|
+
slippage: swapPayload.slippagePercentage || 3,
|
|
1129
1129
|
};
|
|
1130
1130
|
|
|
1131
1131
|
let result: any;
|
|
@@ -1134,10 +1134,13 @@ export class SDK {
|
|
|
1134
1134
|
result = result.data;
|
|
1135
1135
|
} catch (e) {
|
|
1136
1136
|
console.error(tag, 'Failed to get quote: ', e);
|
|
1137
|
+
throw Error(
|
|
1138
|
+
'Quote API failed for path: ' + quote.sellAsset + ' -> ' + quote.buyAsset + '. Error: ' + e,
|
|
1139
|
+
);
|
|
1137
1140
|
}
|
|
1138
|
-
if (result.length === 0)
|
|
1141
|
+
if (!result || result.length === 0)
|
|
1139
1142
|
throw Error(
|
|
1140
|
-
'No quotes available! path: ' + quote.sellAsset
|
|
1143
|
+
'No quotes available! path: ' + quote.sellAsset + ' -> ' + quote.buyAsset,
|
|
1141
1144
|
);
|
|
1142
1145
|
//TODO let user handle selecting quote?
|
|
1143
1146
|
let selected = result[0];
|
|
@@ -1145,12 +1148,14 @@ export class SDK {
|
|
|
1145
1148
|
if (!txs) throw Error('invalid quote!');
|
|
1146
1149
|
for (let i = 0; i < txs.length; i++) {
|
|
1147
1150
|
let tx = txs[i];
|
|
1151
|
+
|
|
1148
1152
|
const transactionDependencies = {
|
|
1149
1153
|
context: this.context,
|
|
1150
1154
|
assetContext: this.assetContext,
|
|
1151
1155
|
balances: this.balances,
|
|
1152
1156
|
pioneer: this.pioneer,
|
|
1153
1157
|
pubkeys: this.pubkeys,
|
|
1158
|
+
pubkeyContext: this.pubkeyContext,
|
|
1154
1159
|
nodes: this.nodes,
|
|
1155
1160
|
keepKeySdk: this.keepKeySdk,
|
|
1156
1161
|
};
|
|
@@ -1161,7 +1166,7 @@ export class SDK {
|
|
|
1161
1166
|
|
|
1162
1167
|
let unsignedTx;
|
|
1163
1168
|
if (tx.type === 'deposit') {
|
|
1164
|
-
//build deposit tx
|
|
1169
|
+
//build deposit tx (Tendermint chains)
|
|
1165
1170
|
unsignedTx = await createUnsignedTendermintTx(
|
|
1166
1171
|
caip,
|
|
1167
1172
|
tx.type,
|
|
@@ -1169,11 +1174,16 @@ export class SDK {
|
|
|
1169
1174
|
tx.txParams.memo,
|
|
1170
1175
|
this.pubkeys,
|
|
1171
1176
|
this.pioneer,
|
|
1172
|
-
this.
|
|
1177
|
+
this.pubkeyContext,
|
|
1173
1178
|
false,
|
|
1174
1179
|
undefined,
|
|
1175
1180
|
);
|
|
1181
|
+
} else if (tx.type === 'EVM' || tx.type === 'evm') {
|
|
1182
|
+
//EVM transaction - use the pre-built transaction from integration
|
|
1183
|
+
console.log(tag, 'Using pre-built EVM transaction from integration');
|
|
1184
|
+
unsignedTx = tx.txParams;
|
|
1176
1185
|
} else {
|
|
1186
|
+
//transfer transaction (UTXO chains) - requires memo
|
|
1177
1187
|
if (!tx.txParams.memo) throw Error('memo required on swaps!');
|
|
1178
1188
|
const sendPayload: any = {
|
|
1179
1189
|
caip,
|
|
@@ -146,6 +146,13 @@ export function buildDashboardFromBalances(balances: any[], blockchains: string[
|
|
|
146
146
|
// Get colors from assetMap since balances don't have them
|
|
147
147
|
const assetInfo = nativeAssetCaip ? assetsMap.get(nativeAssetCaip) : null;
|
|
148
148
|
|
|
149
|
+
// Debug logging
|
|
150
|
+
console.log(TAG, `[DEBUG] Network: ${blockchain}`);
|
|
151
|
+
console.log(TAG, `[DEBUG] nativeAssetCaip: ${nativeAssetCaip}`);
|
|
152
|
+
console.log(TAG, `[DEBUG] assetInfo:`, assetInfo);
|
|
153
|
+
console.log(TAG, `[DEBUG] gasAsset:`, gasAsset);
|
|
154
|
+
console.log(TAG, `[DEBUG] Resolved name: ${gasAsset?.name || assetInfo?.name || 'NO NAME'}`);
|
|
155
|
+
|
|
149
156
|
networksTemp.push({
|
|
150
157
|
networkId: blockchain,
|
|
151
158
|
totalValueUsd: networkTotal,
|