@pioneer-platform/pioneer-sdk 8.15.14 → 8.15.16

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 CHANGED
@@ -41,6 +41,117 @@ var __export = (target, all) => {
41
41
  };
42
42
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
43
43
 
44
+ // ../../support/loggerdog/lib/index.js
45
+ var require_lib = __commonJS((exports2, module2) => {
46
+ var __spreadArray = exports2 && exports2.__spreadArray || function(to, from, pack) {
47
+ if (pack || arguments.length === 2)
48
+ for (var i = 0, l = from.length, ar;i < l; i++) {
49
+ if (ar || !(i in from)) {
50
+ if (!ar)
51
+ ar = Array.prototype.slice.call(from, 0, i);
52
+ ar[i] = from[i];
53
+ }
54
+ }
55
+ return to.concat(ar || Array.prototype.slice.call(from));
56
+ };
57
+ var LOG_LEVELS = {
58
+ TEST: { val: 0, label: "TEST", color: "color: cyan" },
59
+ EMERG: { val: 0, label: "EMERG", color: "color: magenta" },
60
+ ALERT: { val: 1, label: "ALERT", color: "color: magenta" },
61
+ CRIT: { val: 2, label: "CRIT", color: "color: red" },
62
+ ERROR: { val: 3, label: "ERROR", color: "color: red" },
63
+ WARN: { val: 4, label: "WARN", color: "color: orange" },
64
+ NOTICE: { val: 5, label: "NOTICE", color: "color: yellow" },
65
+ VERBOSE: { val: 6, label: "VERBOSE", color: "color: cyan" },
66
+ INFO: { val: 6, label: "INFO", color: "color: cyan" },
67
+ DEBUG: { val: 7, label: "DEBUG", color: "color: green" },
68
+ DEBUGV: { val: 8, label: "DEBUG", color: "color: green" },
69
+ DEBUGVV: { val: 9, label: "DEBUG", color: "color: green" }
70
+ };
71
+ var DEFAULT_LOG_LEVEL = typeof process !== "undefined" ? process.env["DEFAULT_LOG_LEVEL"] || "INFO" : "INFO";
72
+ function _extractContext(stack, depth) {
73
+ try {
74
+ var arr = stack.split(`
75
+ `);
76
+ var chunks = arr[depth].split("/");
77
+ var business = chunks[chunks.length - 1];
78
+ var matches = business.match(/^([^:]+):(\d+):(\d+)/i) || "";
79
+ var filename = matches[1];
80
+ var line = matches[2];
81
+ var pos = matches[3];
82
+ return { filename, line, pos };
83
+ } catch (ex) {
84
+ return { filename: "unknown" };
85
+ }
86
+ }
87
+ function _getContextString() {
88
+ var stack = new Error().stack || "";
89
+ var _a = _extractContext(stack, 3), filename = _a.filename, line = _a.line, pos = _a.pos;
90
+ return "[".concat(filename, ":").concat(line, ":").concat(pos, "]");
91
+ }
92
+ var Logger = function() {
93
+ function Logger2() {
94
+ var stack = new Error().stack || "";
95
+ var ctx = _extractContext(stack, 3);
96
+ this._tag = ctx.filename || "";
97
+ for (var lvl in LOG_LEVELS) {
98
+ this[lvl.toLowerCase()] = this._log.bind(this, lvl);
99
+ }
100
+ this._setLogLevel();
101
+ }
102
+ Logger2.prototype._setLogLevel = function() {
103
+ var tag = this._tag.split(".")[0];
104
+ tag = tag.toUpperCase().replace("-", "_");
105
+ var level = typeof process !== "undefined" ? process.env["LOG_LEVEL_" + tag] || null : null;
106
+ if (level && LOG_LEVELS[level] !== undefined) {
107
+ this._level = LOG_LEVELS[level].val;
108
+ } else {
109
+ this._level = LOG_LEVELS[DEFAULT_LOG_LEVEL].val;
110
+ }
111
+ };
112
+ Logger2.prototype._log = function(level) {
113
+ var args = [];
114
+ for (var _i = 1;_i < arguments.length; _i++) {
115
+ args[_i - 1] = arguments[_i];
116
+ }
117
+ if (this._level >= LOG_LEVELS[level].val) {
118
+ var dt = new Date().toISOString().replace("T", " ");
119
+ var ctx = _getContextString();
120
+ var label = LOG_LEVELS[level].label;
121
+ var color = LOG_LEVELS[level].color;
122
+ var message = undefined;
123
+ if (typeof process !== "undefined" && process.env["STRUCTURED_LOGGING"]) {
124
+ message = {};
125
+ var tag = args[0];
126
+ var param = args[1];
127
+ var value = args[2];
128
+ if (typeof args === "object") {
129
+ message.loggerdog = true;
130
+ message.label = label;
131
+ message.param = param;
132
+ message.value = value;
133
+ message.ctx = ctx;
134
+ message.dt = dt;
135
+ message.tag = tag.toString();
136
+ message.raw = args.toString();
137
+ } else {
138
+ message.raw = args;
139
+ }
140
+ console.log("%c " + dt, color, label, ctx, message);
141
+ } else {
142
+ console.log.apply(console, __spreadArray(["%c " + dt, color, label, ctx], args, false));
143
+ }
144
+ }
145
+ };
146
+ return Logger2;
147
+ }();
148
+ var getLogger = function() {
149
+ return new Logger;
150
+ };
151
+ exports2.default = getLogger;
152
+ module2.exports = getLogger;
153
+ });
154
+
44
155
  // ../../../node_modules/coinselect/utils.js
45
156
  var require_utils = __commonJS((exports2, module2) => {
46
157
  var TX_EMPTY_SIZE = 4 + 1 + 1 + 4;
@@ -798,7 +909,7 @@ var import_pioneer_caip8 = require("@pioneer-platform/pioneer-caip");
798
909
 
799
910
  // ../pioneer-client/lib/index.js
800
911
  var import_swagger_client = __toESM(require("swagger-client"));
801
- var import_loggerdog = __toESM(require("@pioneer-platform/loggerdog"));
912
+ var import_loggerdog = __toESM(require_lib());
802
913
  var log = typeof window === "undefined" ? import_loggerdog.default() : {
803
914
  debug: (...args) => console.debug(...args),
804
915
  info: (...args) => console.info(...args),
@@ -944,11 +1055,30 @@ class Pioneer {
944
1055
  }
945
1056
 
946
1057
  // src/index.ts
947
- var import_pioneer_coins4 = require("@pioneer-platform/pioneer-coins");
1058
+ var import_pioneer_coins6 = require("@pioneer-platform/pioneer-coins");
948
1059
  var import_pioneer_discovery2 = require("@pioneer-platform/pioneer-discovery");
949
1060
  var import_pioneer_events = require("@pioneer-platform/pioneer-events");
950
1061
  var import_events = __toESM(require("events"));
951
1062
 
1063
+ // src/utils/logger.ts
1064
+ var DEBUG = process.env.DEBUG === "true" || typeof window !== "undefined" && window.DEBUG;
1065
+ var logger = {
1066
+ info: (tag, ...args) => {
1067
+ console.log(`[INFO] ${tag}`, ...args);
1068
+ },
1069
+ debug: (tag, ...args) => {
1070
+ if (DEBUG) {
1071
+ console.log(`[DEBUG] ${tag}`, ...args);
1072
+ }
1073
+ },
1074
+ warn: (tag, ...args) => {
1075
+ console.warn(`[WARN] ${tag}`, ...args);
1076
+ },
1077
+ error: (tag, ...args) => {
1078
+ console.error(`[ERROR] ${tag}`, ...args);
1079
+ }
1080
+ };
1081
+
952
1082
  // src/getPubkey.ts
953
1083
  var import_pioneer_caip = require("@pioneer-platform/pioneer-caip");
954
1084
  var import_pioneer_coins = require("@pioneer-platform/pioneer-coins");
@@ -3983,25 +4113,400 @@ async function syncMarket(balances, pioneer) {
3983
4113
  }
3984
4114
  }
3985
4115
 
3986
- // src/index.ts
3987
- var TAG9 = " | Pioneer-sdk | ";
3988
- var ASSET_COLORS = {
3989
- "bip122:000000000019d6689c085ae165831e93/slip44:0": "#FF9800",
3990
- "eip155:1/slip44:60": "#627EEA",
3991
- "eip155:137/slip44:60": "#8247E5",
3992
- "eip155:8453/slip44:60": "#0052FF",
3993
- "eip155:56/slip44:60": "#F3BA2F",
3994
- "bip122:12a765e31ffd4059bada1e25190f6e98/slip44:2": "#BFBBBB",
3995
- "bip122:00000000001a91e3dace36e2be3bf030/slip44:3": "#C2A633",
3996
- "bip122:000000000000000000651ef99cb9fcbe/slip44:145": "#8DC351",
3997
- "bip122:000007d91d1254d60e2dd1ae58038307/slip44:5": "#008CE7",
3998
- "bip122:4da631f2ac1bed857bd968c67c913978/slip44:20": "#006AD2",
3999
- "cosmos:cosmoshub-4/slip44:118": "#2E3148",
4000
- "cosmos:osmosis-1/slip44:118": "#9B1FD7",
4001
- "ripple:4109c6f2045fc7eff4cde8f9905d19c2/slip44:144": "#23292F",
4002
- "cosmos:mayachain-mainnet-v1/slip44:931": "#00D4AA",
4003
- "cosmos:thorchain-mainnet-v1/slip44:931": "#00CCFF"
4116
+ // src/utils/pubkey-management.ts
4117
+ function getPubkeyKey(pubkey) {
4118
+ return `${pubkey.pubkey}_${pubkey.pathMaster}`;
4119
+ }
4120
+ function deduplicatePubkeys(pubkeys) {
4121
+ const seen = new Set;
4122
+ return pubkeys.filter((pubkey) => {
4123
+ const key = getPubkeyKey(pubkey);
4124
+ if (seen.has(key))
4125
+ return false;
4126
+ seen.add(key);
4127
+ return true;
4128
+ });
4129
+ }
4130
+ function validatePubkey(pubkey) {
4131
+ return !!(pubkey.pubkey && pubkey.pathMaster);
4132
+ }
4133
+ function findPubkeysForNetwork(pubkeys, networkId) {
4134
+ return pubkeys.filter((p) => {
4135
+ if (!p.networks || !Array.isArray(p.networks))
4136
+ return false;
4137
+ if (p.networks.includes(networkId))
4138
+ return true;
4139
+ if (networkId.startsWith("eip155:") && p.networks.includes("eip155:*")) {
4140
+ return true;
4141
+ }
4142
+ return false;
4143
+ });
4144
+ }
4145
+ function findPubkeyForNetwork(pubkeys, networkId) {
4146
+ return pubkeys.find((p) => {
4147
+ if (!p.networks || !Array.isArray(p.networks))
4148
+ return false;
4149
+ if (p.networks.includes(networkId))
4150
+ return true;
4151
+ if (networkId.startsWith("eip155:") && p.networks.includes("eip155:*"))
4152
+ return true;
4153
+ return false;
4154
+ });
4155
+ }
4156
+ function validatePubkeysForNetwork(pubkeys, networkId, caip) {
4157
+ if (!pubkeys || pubkeys.length === 0) {
4158
+ throw new Error(`Cannot set asset context for ${caip} - no pubkeys loaded. Please initialize wallet first.`);
4159
+ }
4160
+ const pubkeysForNetwork = findPubkeysForNetwork(pubkeys, networkId);
4161
+ if (pubkeysForNetwork.length === 0) {
4162
+ const availableNetworks = [...new Set(pubkeys.flatMap((p) => p.networks || []))];
4163
+ throw new Error(`Cannot set asset context for ${caip} - no address/xpub found for network ${networkId}. Available networks: ${availableNetworks.join(", ")}`);
4164
+ }
4165
+ const isUtxoChain = networkId.startsWith("bip122:");
4166
+ if (isUtxoChain) {
4167
+ const xpubFound = pubkeysForNetwork.some((p) => p.type === "xpub" && p.pubkey);
4168
+ if (!xpubFound) {
4169
+ throw new Error(`Cannot set asset context for UTXO chain ${caip} - xpub required but not found`);
4170
+ }
4171
+ }
4172
+ const hasValidAddress = pubkeysForNetwork.some((p) => p.address || p.master || p.pubkey);
4173
+ if (!hasValidAddress) {
4174
+ throw new Error(`Cannot set asset context for ${caip} - no valid address found in pubkeys`);
4175
+ }
4176
+ }
4177
+ function filterPubkeysForAsset(pubkeys, caip, caipToNetworkId7) {
4178
+ const networkId = caipToNetworkId7(caip);
4179
+ return pubkeys.filter((p) => {
4180
+ if (!p.networks || !Array.isArray(p.networks))
4181
+ return false;
4182
+ if (p.networks.includes(networkId))
4183
+ return true;
4184
+ if (networkId.includes("eip155") && p.networks.some((n) => n.startsWith("eip155"))) {
4185
+ return true;
4186
+ }
4187
+ return false;
4188
+ });
4189
+ }
4190
+
4191
+ // src/utils/portfolio-helpers.ts
4192
+ var TAG9 = " | portfolio-helpers | ";
4193
+ function isCacheDataValid(portfolioData) {
4194
+ if (!portfolioData.networks || !Array.isArray(portfolioData.networks)) {
4195
+ console.warn("[CACHE VALIDATION] Networks is not an array");
4196
+ return false;
4197
+ }
4198
+ if (portfolioData.networks.length > 50) {
4199
+ console.error(`[CACHE VALIDATION] CORRUPTED: ${portfolioData.networks.length} networks (should be < 50)`);
4200
+ return false;
4201
+ }
4202
+ const validNetworks = portfolioData.networks.filter((n) => n.networkId && n.totalValueUsd !== undefined && n.gasAssetSymbol);
4203
+ if (validNetworks.length === 0 && portfolioData.networks.length > 0) {
4204
+ console.error("[CACHE VALIDATION] CORRUPTED: No networks have required fields");
4205
+ return false;
4206
+ }
4207
+ console.log(`[CACHE VALIDATION] Found ${portfolioData.networks.length} networks, ${validNetworks.length} valid`);
4208
+ return true;
4209
+ }
4210
+ async function fetchMarketPrice(pioneer, caip) {
4211
+ const tag = TAG9 + " | fetchMarketPrice | ";
4212
+ try {
4213
+ if (!caip || typeof caip !== "string" || !caip.includes(":")) {
4214
+ logger.warn(tag, "Invalid or missing CAIP, skipping market price fetch:", caip);
4215
+ return 0;
4216
+ }
4217
+ logger.debug(tag, "Fetching fresh market price for:", caip);
4218
+ const marketData = await pioneer.GetMarketInfo([caip]);
4219
+ logger.debug(tag, "Market data response:", marketData);
4220
+ if (marketData && marketData.data && marketData.data.length > 0) {
4221
+ const price = marketData.data[0];
4222
+ logger.debug(tag, "✅ Fresh market price:", price);
4223
+ return price;
4224
+ } else {
4225
+ logger.warn(tag, "No market data returned for:", caip);
4226
+ return 0;
4227
+ }
4228
+ } catch (marketError) {
4229
+ logger.error(tag, "Error fetching market price:", marketError);
4230
+ return 0;
4231
+ }
4232
+ }
4233
+ function extractPriceFromBalances(balances) {
4234
+ const tag = TAG9 + " | extractPriceFromBalances | ";
4235
+ if (balances.length === 0)
4236
+ return 0;
4237
+ let priceValue = balances[0].priceUsd || balances[0].price;
4238
+ if ((!priceValue || priceValue === 0) && balances[0].valueUsd && balances[0].balance) {
4239
+ const balance = parseFloat(balances[0].balance);
4240
+ const valueUsd = parseFloat(balances[0].valueUsd);
4241
+ if (balance > 0 && valueUsd > 0) {
4242
+ priceValue = valueUsd / balance;
4243
+ logger.debug(tag, "Calculated priceUsd from valueUsd/balance:", priceValue);
4244
+ }
4245
+ }
4246
+ return priceValue || 0;
4247
+ }
4248
+ function aggregateBalances(balances, caip) {
4249
+ const tag = TAG9 + " | aggregateBalances | ";
4250
+ let totalBalance = 0;
4251
+ let totalValueUsd = 0;
4252
+ logger.debug(tag, `Aggregating ${balances.length} balance entries for ${caip}`);
4253
+ for (const balanceEntry of balances) {
4254
+ const balance = parseFloat(balanceEntry.balance) || 0;
4255
+ const valueUsd = parseFloat(balanceEntry.valueUsd) || 0;
4256
+ totalBalance += balance;
4257
+ totalValueUsd += valueUsd;
4258
+ logger.debug(tag, ` Balance entry: ${balance} (${valueUsd} USD)`);
4259
+ }
4260
+ logger.debug(tag, `Aggregated balance: ${totalBalance} (${totalValueUsd.toFixed(2)} USD)`);
4261
+ return { totalBalance, totalValueUsd };
4262
+ }
4263
+ function updateBalancesWithPrice(balances, freshPriceUsd) {
4264
+ const tag = TAG9 + " | updateBalancesWithPrice | ";
4265
+ for (const balance of balances) {
4266
+ balance.price = freshPriceUsd;
4267
+ balance.priceUsd = freshPriceUsd;
4268
+ const balanceAmount = parseFloat(balance.balance || 0);
4269
+ balance.valueUsd = (balanceAmount * freshPriceUsd).toString();
4270
+ }
4271
+ logger.debug(tag, "Updated all balances with fresh price data");
4272
+ }
4273
+ function buildDashboardFromPortfolioData(portfolioData) {
4274
+ const cacheAge = portfolioData.lastUpdated ? Math.floor((Date.now() - portfolioData.lastUpdated) / 1000) : 0;
4275
+ return {
4276
+ totalValueUsd: portfolioData.totalValueUsd,
4277
+ pairedDevices: portfolioData.pairedDevices,
4278
+ devices: portfolioData.devices || [],
4279
+ networks: portfolioData.networks || [],
4280
+ assets: portfolioData.assets || [],
4281
+ statistics: portfolioData.statistics || {},
4282
+ cached: portfolioData.cached,
4283
+ lastUpdated: portfolioData.lastUpdated,
4284
+ cacheAge,
4285
+ networkPercentages: portfolioData.networks?.map((network) => ({
4286
+ networkId: network.network_id || network.networkId,
4287
+ percentage: network.percentage || 0
4288
+ })) || []
4289
+ };
4290
+ }
4291
+ function buildAssetQuery(pubkeys, caip) {
4292
+ return pubkeys.map((pubkey) => ({ caip, pubkey: pubkey.pubkey }));
4293
+ }
4294
+ function logQueryDiagnostics(assetQuery, tag = "") {
4295
+ const caipCounts = new Map;
4296
+ for (const query of assetQuery) {
4297
+ caipCounts.set(query.caip, (caipCounts.get(query.caip) || 0) + 1);
4298
+ }
4299
+ if (tag) {
4300
+ console.log(tag, "Built assetQuery with", assetQuery.length, "entries");
4301
+ console.log(tag, "Sample queries:", assetQuery.slice(0, 5));
4302
+ console.log(tag, "Queries by chain:");
4303
+ caipCounts.forEach((count, caip) => {
4304
+ console.log(` - ${caip}: ${count} queries`);
4305
+ });
4306
+ }
4307
+ }
4308
+ function enrichBalancesWithAssetInfo(balances, assetsMap, caipToNetworkId7) {
4309
+ const tag = TAG9 + " | enrichBalancesWithAssetInfo | ";
4310
+ for (const balance of balances) {
4311
+ const assetInfo = assetsMap.get(balance.caip.toLowerCase()) || assetsMap.get(balance.caip);
4312
+ if (!assetInfo) {
4313
+ throw new Error(`Missing AssetInfo for ${balance.caip}`);
4314
+ }
4315
+ Object.assign(balance, assetInfo, {
4316
+ type: balance.type || assetInfo.type,
4317
+ isNative: balance.isNative ?? assetInfo.isNative,
4318
+ networkId: caipToNetworkId7(balance.caip),
4319
+ icon: assetInfo.icon || "https://pioneers.dev/coins/etherum.png",
4320
+ identifier: `${balance.caip}:${balance.pubkey}`,
4321
+ updated: Date.now(),
4322
+ color: assetInfo.color
4323
+ });
4324
+ }
4325
+ return balances;
4326
+ }
4327
+
4328
+ // src/utils/sync-state.ts
4329
+ var TAG10 = " | sync-state | ";
4330
+ function resolveAssetInfo(assetsMap, assetData, asset) {
4331
+ const tag = TAG10 + " | resolveAssetInfo | ";
4332
+ let assetInfo = assetsMap.get(asset.caip.toLowerCase());
4333
+ logger.debug(tag, "assetInfo from assetsMap:", assetInfo);
4334
+ const assetInfoDiscovery = assetData[asset.caip];
4335
+ logger.debug(tag, "assetInfoDiscovery:", assetInfoDiscovery);
4336
+ if (assetInfoDiscovery) {
4337
+ assetInfo = assetInfoDiscovery;
4338
+ }
4339
+ if (!assetInfo) {
4340
+ logger.debug(tag, "Building placeholder asset for", asset.caip);
4341
+ assetInfo = {
4342
+ caip: asset.caip.toLowerCase(),
4343
+ networkId: asset.networkId,
4344
+ symbol: asset.symbol || "UNKNOWN",
4345
+ name: asset.name || "Unknown Asset",
4346
+ icon: asset.icon || "https://pioneers.dev/coins/ethereum.png"
4347
+ };
4348
+ }
4349
+ return assetInfo;
4350
+ }
4351
+ function createInitialSyncState(totalChains) {
4352
+ return {
4353
+ isSynced: false,
4354
+ isInitialSync: true,
4355
+ cacheAge: 0,
4356
+ syncProgress: 0,
4357
+ syncedChains: 0,
4358
+ totalChains,
4359
+ lastSyncTime: null,
4360
+ syncSource: "none"
4361
+ };
4362
+ }
4363
+ function createCacheSyncState(lastUpdated, totalChains) {
4364
+ const cacheAge = lastUpdated ? Math.floor((Date.now() - lastUpdated) / 1000) : 0;
4365
+ return {
4366
+ isSynced: true,
4367
+ isInitialSync: false,
4368
+ cacheAge,
4369
+ syncProgress: 100,
4370
+ syncedChains: totalChains,
4371
+ totalChains,
4372
+ lastSyncTime: lastUpdated || Date.now(),
4373
+ syncSource: "cache"
4374
+ };
4375
+ }
4376
+ function createFreshSyncState(totalChains) {
4377
+ return {
4378
+ isSynced: true,
4379
+ isInitialSync: false,
4380
+ cacheAge: 0,
4381
+ syncProgress: 100,
4382
+ syncedChains: totalChains,
4383
+ totalChains,
4384
+ lastSyncTime: Date.now(),
4385
+ syncSource: "fresh"
4386
+ };
4387
+ }
4388
+
4389
+ // src/utils/fee-reserves.ts
4390
+ var TAG11 = " | Pioneer-sdk | fee-reserves | ";
4391
+ var FEE_RESERVE_MAP = {
4392
+ "bip122:000000000019d6689c085ae165831e93/slip44:0": 0.00005,
4393
+ "eip155:1/slip44:60": 0.001,
4394
+ "cosmos:thorchain-mainnet-v1/slip44:931": 0.02,
4395
+ "bip122:00000000001a91e3dace36e2be3bf030/slip44:3": 1,
4396
+ "bip122:000007d91d1254d60e2dd1ae58038307/slip44:5": 0.001,
4397
+ "bip122:000000000000000000651ef99cb9fcbe/slip44:145": 0.0005,
4398
+ "bip122:12a765e31ffd4059bada1e25190f6e98/slip44:2": 0.001,
4399
+ "bip122:4da631f2ac1bed857bd968c67c913978/slip44:20": 0.1,
4400
+ "cosmos:cosmoshub-4/slip44:118": 0.005,
4401
+ "cosmos:osmosis-1/slip44:118": 0.035,
4402
+ "cosmos:mayachain-mainnet-v1/slip44:931": 0.5,
4403
+ "eip155:56/slip44:60": 0.001,
4404
+ "eip155:137/slip44:60": 0.01,
4405
+ "eip155:43114/slip44:60": 0.01,
4406
+ "eip155:10/slip44:60": 0.0001,
4407
+ "eip155:8453/slip44:60": 0.0001,
4408
+ "eip155:42161/slip44:60": 0.0001,
4409
+ "ripple:4109c6f2045fc7eff4cde8f9905d19c2/slip44:144": 0.00001
4004
4410
  };
4411
+ var DEFAULT_FEE_RESERVE = 0.001;
4412
+ function getFeeReserve(caip) {
4413
+ if (FEE_RESERVE_MAP[caip]) {
4414
+ return FEE_RESERVE_MAP[caip];
4415
+ }
4416
+ if (caip.startsWith("eip155:") && caip.includes("/slip44:60")) {
4417
+ return FEE_RESERVE_MAP["eip155:1/slip44:60"] || 0.001;
4418
+ }
4419
+ if (caip.startsWith("cosmos:")) {
4420
+ return 0.01;
4421
+ }
4422
+ if (caip.startsWith("bip122:")) {
4423
+ return 0.0001;
4424
+ }
4425
+ console.warn(TAG11, `No fee reserve defined for ${caip}, using default: ${DEFAULT_FEE_RESERVE}`);
4426
+ return DEFAULT_FEE_RESERVE;
4427
+ }
4428
+ function getMaxSendableAmount(balance, caip) {
4429
+ const reserve = getFeeReserve(caip);
4430
+ const maxAmount = Math.max(0, balance - reserve);
4431
+ console.log(TAG11, `Max sendable for ${caip}: ${maxAmount} (balance: ${balance}, reserve: ${reserve})`);
4432
+ return maxAmount;
4433
+ }
4434
+
4435
+ // src/utils/network-helpers.ts
4436
+ function matchesNetwork(item, networkId) {
4437
+ if (!item.networks || !Array.isArray(item.networks))
4438
+ return false;
4439
+ if (item.networks.includes(networkId))
4440
+ return true;
4441
+ if (networkId.startsWith("eip155:") && item.networks.includes("eip155:*"))
4442
+ return true;
4443
+ return false;
4444
+ }
4445
+ function normalizeNetworkId(networkId) {
4446
+ return networkId.includes("eip155:") ? "eip155:*" : networkId;
4447
+ }
4448
+ function validatePubkeysNetworks(pubkeys, tag = "") {
4449
+ const valid = pubkeys.filter((p) => p.networks && Array.isArray(p.networks));
4450
+ const invalid = pubkeys.filter((p) => !p.networks || !Array.isArray(p.networks));
4451
+ if (tag && invalid.length > 0) {
4452
+ console.warn(tag, `⚠️ ${invalid.length} pubkeys missing networks field`);
4453
+ invalid.forEach((pk) => {
4454
+ console.warn(tag, ` - ${pk.note || pk.pubkey.slice(0, 10)}: networks=${pk.networks}`);
4455
+ });
4456
+ }
4457
+ return { valid, invalid };
4458
+ }
4459
+
4460
+ // src/utils/path-discovery.ts
4461
+ var import_pioneer_coins4 = require("@pioneer-platform/pioneer-coins");
4462
+ async function ensurePathsForBlockchains(blockchains, currentPaths, tag) {
4463
+ let allPaths = [...currentPaths];
4464
+ for (const blockchain of blockchains) {
4465
+ const networkId = normalizeNetworkId(blockchain);
4466
+ const existingPaths = allPaths.filter((path) => matchesNetwork(path, networkId));
4467
+ if (existingPaths.length === 0) {
4468
+ logger.info(tag, `Discovering paths for ${networkId}...`);
4469
+ const newPaths = import_pioneer_coins4.getPaths([networkId]);
4470
+ if (!newPaths || newPaths.length === 0) {
4471
+ throw new Error(`Path discovery failed for ${networkId}. ` + `Available blockchains: ${blockchains.join(", ")}`);
4472
+ }
4473
+ logger.debug(tag, `Added ${newPaths.length} paths for ${networkId}`);
4474
+ allPaths = allPaths.concat(newPaths);
4475
+ }
4476
+ }
4477
+ return allPaths;
4478
+ }
4479
+
4480
+ // src/utils/pubkey-sync.ts
4481
+ var import_pioneer_coins5 = require("@pioneer-platform/pioneer-coins");
4482
+ async function syncPubkeysForBlockchains(blockchains, paths, existingPubkeys, keepKeySdk, context, getPubkeyFn, addPubkeyCallback, tag) {
4483
+ for (const blockchain of blockchains) {
4484
+ const networkId = normalizeNetworkId(blockchain);
4485
+ const pathsForChain = paths.filter((path) => matchesNetwork(path, networkId));
4486
+ if (pathsForChain.length === 0) {
4487
+ const availablePaths = paths.map((p) => p.note || p.path || "unnamed").join(", ");
4488
+ throw new Error(`No paths found for ${networkId}. ` + `Available paths: ${availablePaths || "none"}`);
4489
+ }
4490
+ logger.info(tag, `Syncing ${pathsForChain.length} pubkeys for ${networkId}...`);
4491
+ for (const path of pathsForChain) {
4492
+ const pathBip32 = import_pioneer_coins5.addressNListToBIP32(path.addressNListMaster);
4493
+ const existingPubkey = existingPubkeys.find((p) => p.pathMaster === pathBip32);
4494
+ if (!existingPubkey) {
4495
+ logger.debug(tag, `Fetching pubkey for path ${pathBip32}...`);
4496
+ const newPubkey = await getPubkeyFn(blockchain, path, keepKeySdk, context);
4497
+ if (!newPubkey) {
4498
+ throw new Error(`Pubkey fetch failed for ${networkId} at path ${pathBip32}. ` + `Ensure hardware wallet is connected and unlocked.`);
4499
+ }
4500
+ addPubkeyCallback(newPubkey);
4501
+ logger.debug(tag, `✓ Added pubkey for ${pathBip32}`);
4502
+ }
4503
+ }
4504
+ }
4505
+ logger.info(tag, `✅ Pubkey sync complete. Total pubkeys: ${existingPubkeys.length}`);
4506
+ }
4507
+
4508
+ // src/index.ts
4509
+ var TAG12 = " | Pioneer-sdk | ";
4005
4510
 
4006
4511
  class SDK {
4007
4512
  status;
@@ -4059,7 +4564,6 @@ class SDK {
4059
4564
  init;
4060
4565
  getUnifiedPortfolio;
4061
4566
  offlineClient;
4062
- convertVaultPubkeysToPioneerFormat;
4063
4567
  app;
4064
4568
  addAsset;
4065
4569
  getAssets;
@@ -4132,23 +4636,14 @@ class SDK {
4132
4636
  this.utxoApiKey = config.utxoApiKey;
4133
4637
  this.walletConnectProjectId = config.walletConnectProjectId;
4134
4638
  this.contextType = "";
4135
- this.syncState = {
4136
- isSynced: false,
4137
- isInitialSync: true,
4138
- cacheAge: 0,
4139
- syncProgress: 0,
4140
- syncedChains: 0,
4141
- totalChains: this.blockchains.length,
4142
- lastSyncTime: null,
4143
- syncSource: "none"
4144
- };
4639
+ this.syncState = createInitialSyncState(this.blockchains.length);
4145
4640
  this.offlineClient = config.offlineFirst ? new OfflineClient({
4146
4641
  vaultUrl: config.vaultUrl || "kkapi://",
4147
4642
  timeout: 1000,
4148
4643
  fallbackToRemote: true
4149
4644
  }) : null;
4150
4645
  this.pairWallet = async (options) => {
4151
- const tag6 = TAG9 + " | pairWallet | ";
4646
+ const tag6 = TAG12 + " | pairWallet | ";
4152
4647
  if (this.viewOnlyMode || this.skipDevicePairing) {
4153
4648
  console.log(tag6, "\uD83D\uDC41️ [VIEW-ONLY] Skipping device pairing");
4154
4649
  return {
@@ -4163,35 +4658,20 @@ class SDK {
4163
4658
  message: "Device pairing not yet implemented"
4164
4659
  });
4165
4660
  };
4166
- this.getPubkeyKey = (pubkey) => {
4167
- return `${pubkey.pubkey}_${pubkey.pathMaster}`;
4168
- };
4169
- this.deduplicatePubkeys = (pubkeys) => {
4170
- const seen = new Set;
4171
- const deduped = pubkeys.filter((pubkey) => {
4172
- const key = this.getPubkeyKey(pubkey);
4173
- if (seen.has(key)) {
4174
- return false;
4175
- }
4176
- seen.add(key);
4177
- return true;
4178
- });
4179
- return deduped;
4180
- };
4661
+ this.getPubkeyKey = getPubkeyKey;
4662
+ this.deduplicatePubkeys = deduplicatePubkeys;
4181
4663
  this.addPubkey = (pubkey) => {
4182
- if (!pubkey.pubkey || !pubkey.pathMaster) {
4664
+ if (!validatePubkey(pubkey))
4183
4665
  return false;
4184
- }
4185
- const key = this.getPubkeyKey(pubkey);
4186
- if (this.pubkeySet.has(key)) {
4666
+ const key = getPubkeyKey(pubkey);
4667
+ if (this.pubkeySet.has(key))
4187
4668
  return false;
4188
- }
4189
4669
  this.pubkeys.push(pubkey);
4190
4670
  this.pubkeySet.add(key);
4191
4671
  return true;
4192
4672
  };
4193
4673
  this.setPubkeys = (newPubkeys) => {
4194
- const tag6 = `${TAG9} | setPubkeys | `;
4674
+ const tag6 = `${TAG12} | setPubkeys | `;
4195
4675
  this.pubkeys = [];
4196
4676
  this.pubkeySet.clear();
4197
4677
  let added = 0;
@@ -4207,17 +4687,8 @@ class SDK {
4207
4687
  this.pubkeys = [];
4208
4688
  this.pubkeySet.clear();
4209
4689
  }
4210
- this.isViewOnlyMode = () => {
4211
- return this.viewOnlyMode;
4212
- };
4213
- this.canSignTransactions = () => {
4214
- return !this.viewOnlyMode && !!this.keepKeySdk;
4215
- };
4216
- this.isVaultAvailable = () => {
4217
- return !!this.keepkeyEndpoint && this.keepkeyEndpoint.isAvailable;
4218
- };
4219
4690
  this.getUnifiedPortfolio = async function() {
4220
- const tag6 = `${TAG9} | getUnifiedPortfolio | `;
4691
+ const tag6 = `${TAG12} | getUnifiedPortfolio | `;
4221
4692
  try {
4222
4693
  const startTime = performance.now();
4223
4694
  try {
@@ -4249,8 +4720,7 @@ class SDK {
4249
4720
  this.events.emit("SET_BALANCES", this.balances);
4250
4721
  }
4251
4722
  if (portfolioData.pubkeys && portfolioData.pubkeys.length > 0) {
4252
- const convertedPubkeys = this.convertVaultPubkeysToPioneerFormat(portfolioData.pubkeys);
4253
- this.setPubkeys(convertedPubkeys);
4723
+ this.setPubkeys(portfolioData.pubkeys);
4254
4724
  this.events.emit("SET_PUBKEYS", this.pubkeys);
4255
4725
  }
4256
4726
  if (portfolioData.devices && portfolioData.devices.length > 0) {
@@ -4263,52 +4733,10 @@ class SDK {
4263
4733
  }));
4264
4734
  this.events.emit("SET_WALLETS", this.wallets);
4265
4735
  }
4266
- const isCacheDataValid = (portfolioData2) => {
4267
- if (!portfolioData2.networks || !Array.isArray(portfolioData2.networks)) {
4268
- console.warn("[CACHE VALIDATION] Networks is not an array");
4269
- return false;
4270
- }
4271
- if (portfolioData2.networks.length > 50) {
4272
- console.error(`[CACHE VALIDATION] CORRUPTED: ${portfolioData2.networks.length} networks (should be < 50)`);
4273
- return false;
4274
- }
4275
- const validNetworks = portfolioData2.networks.filter((n) => n.networkId && n.totalValueUsd !== undefined && n.gasAssetSymbol);
4276
- if (validNetworks.length === 0 && portfolioData2.networks.length > 0) {
4277
- console.error("[CACHE VALIDATION] CORRUPTED: No networks have required fields");
4278
- return false;
4279
- }
4280
- console.log(`[CACHE VALIDATION] Found ${portfolioData2.networks.length} networks, ${validNetworks.length} valid`);
4281
- return true;
4282
- };
4283
4736
  if (isCacheDataValid(portfolioData)) {
4284
- const dashboardData = {
4285
- totalValueUsd: portfolioData.totalValueUsd,
4286
- pairedDevices: portfolioData.pairedDevices,
4287
- devices: portfolioData.devices || [],
4288
- networks: portfolioData.networks || [],
4289
- assets: portfolioData.assets || [],
4290
- statistics: portfolioData.statistics || {},
4291
- cached: portfolioData.cached,
4292
- lastUpdated: portfolioData.lastUpdated,
4293
- cacheAge: portfolioData.lastUpdated ? Math.floor((Date.now() - portfolioData.lastUpdated) / 1000) : 0,
4294
- networkPercentages: portfolioData.networks?.map((network) => ({
4295
- networkId: network.network_id || network.networkId,
4296
- percentage: network.percentage || 0
4297
- })) || []
4298
- };
4299
- this.dashboard = dashboardData;
4737
+ this.dashboard = buildDashboardFromPortfolioData(portfolioData);
4300
4738
  this.events.emit("SET_DASHBOARD", this.dashboard);
4301
- const cacheAge = portfolioData.lastUpdated ? Math.floor((Date.now() - portfolioData.lastUpdated) / 1000) : 0;
4302
- this.syncState = {
4303
- isSynced: true,
4304
- isInitialSync: false,
4305
- cacheAge,
4306
- syncProgress: 100,
4307
- syncedChains: this.blockchains.length,
4308
- totalChains: this.blockchains.length,
4309
- lastSyncTime: portfolioData.lastUpdated || Date.now(),
4310
- syncSource: "cache"
4311
- };
4739
+ this.syncState = createCacheSyncState(portfolioData.lastUpdated, this.blockchains.length);
4312
4740
  this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4313
4741
  } else {
4314
4742
  console.warn("[CACHE VALIDATION] ❌ Cache data corrupted, building dashboard from cached balances");
@@ -4343,7 +4771,7 @@ class SDK {
4343
4771
  return this.syncState.isSynced;
4344
4772
  };
4345
4773
  this.init = async function(walletsVerbose, setup) {
4346
- const tag6 = `${TAG9} | init | `;
4774
+ const tag6 = `${TAG12} | init | `;
4347
4775
  try {
4348
4776
  if (!this.username)
4349
4777
  throw Error("username required!");
@@ -4364,7 +4792,7 @@ class SDK {
4364
4792
  this.pioneer = await PioneerClient.init();
4365
4793
  if (!this.pioneer)
4366
4794
  throw Error("Failed to init pioneer server!");
4367
- this.paths.concat(import_pioneer_coins4.getPaths(this.blockchains));
4795
+ this.paths.concat(import_pioneer_coins6.getPaths(this.blockchains));
4368
4796
  await this.getGasAssets();
4369
4797
  if (!this.skipKeeperEndpoint) {
4370
4798
  this.keepkeyEndpoint = await detectKkApiAvailability(this.forceLocalhost);
@@ -4408,7 +4836,7 @@ class SDK {
4408
4836
  this.events.emit("message", request);
4409
4837
  });
4410
4838
  clientEvents.events.on("balance:update", (data) => {
4411
- const tag7 = TAG9 + " | balance:update | ";
4839
+ const tag7 = TAG12 + " | balance:update | ";
4412
4840
  try {
4413
4841
  const payload = typeof data === "string" ? JSON.parse(data) : data;
4414
4842
  const balance = payload.balance;
@@ -4426,7 +4854,7 @@ class SDK {
4426
4854
  }
4427
4855
  });
4428
4856
  clientEvents.events.on("sync:progress", (data) => {
4429
- const tag7 = TAG9 + " | sync:progress | ";
4857
+ const tag7 = TAG12 + " | sync:progress | ";
4430
4858
  try {
4431
4859
  const payload = typeof data === "string" ? JSON.parse(data) : data;
4432
4860
  console.log(tag7, `Sync progress: ${payload.percentage}%`);
@@ -4439,7 +4867,7 @@ class SDK {
4439
4867
  }
4440
4868
  });
4441
4869
  clientEvents.events.on("sync:complete", (data) => {
4442
- const tag7 = TAG9 + " | sync:complete | ";
4870
+ const tag7 = TAG12 + " | sync:complete | ";
4443
4871
  try {
4444
4872
  const payload = typeof data === "string" ? JSON.parse(data) : data;
4445
4873
  console.log(tag7, `Sync complete: ${payload.balances} balances in ${payload.duration}ms`);
@@ -4490,155 +4918,60 @@ class SDK {
4490
4918
  this.buildDashboardFromBalances = function() {
4491
4919
  return buildDashboardFromBalances(this.balances, this.blockchains, this.assetsMap);
4492
4920
  };
4493
- this.inferTypeFromCaip = function(caip) {
4494
- if (caip.includes("/slip44:"))
4495
- return "native";
4496
- if (caip.includes("/erc20:") || caip.includes("/bep20:") || caip.includes("/spl:"))
4497
- return "token";
4498
- if (caip.includes("/denom:"))
4499
- return "native";
4500
- return "unknown";
4501
- };
4502
4921
  this.syncMarket = async function() {
4503
4922
  return syncMarket(this.balances, this.pioneer);
4504
4923
  };
4505
4924
  this.sync = async function() {
4506
- const tag6 = `${TAG9} | sync | `;
4925
+ const tag6 = `${TAG12} | sync | `;
4926
+ const log2 = logger;
4507
4927
  try {
4508
- const matchesNetwork = (item, networkId) => {
4509
- if (!item.networks || !Array.isArray(item.networks))
4510
- return false;
4511
- if (item.networks.includes(networkId))
4512
- return true;
4513
- if (networkId.startsWith("eip155:") && item.networks.includes("eip155:*"))
4514
- return true;
4515
- return false;
4928
+ this.syncState = {
4929
+ ...createInitialSyncState(this.blockchains.length),
4930
+ syncProgress: 10
4516
4931
  };
4932
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4933
+ log2.info(tag6, "Fetching initial pubkeys...");
4517
4934
  await this.getPubkeys();
4518
- for (let i = 0;i < this.blockchains.length; i++) {
4519
- let networkId = this.blockchains[i];
4520
- if (networkId.indexOf("eip155:") >= 0)
4521
- networkId = "eip155:*";
4522
- let paths = this.paths.filter((path) => matchesNetwork(path, networkId));
4523
- if (paths.length === 0) {
4524
- let paths2 = import_pioneer_coins4.getPaths([networkId]);
4525
- if (!paths2 || paths2.length === 0)
4526
- throw Error("Unable to find paths for: " + networkId);
4527
- this.paths = this.paths.concat(paths2);
4528
- }
4529
- }
4530
- for (let i = 0;i < this.blockchains.length; i++) {
4531
- let networkId = this.blockchains[i];
4532
- if (networkId.indexOf("eip155:") >= 0)
4533
- networkId = "eip155:*";
4534
- const pathsForChain = this.paths.filter((path) => matchesNetwork(path, networkId));
4535
- if (!pathsForChain || pathsForChain.length === 0)
4536
- throw Error("No paths found for blockchain: " + networkId);
4537
- for (let j = 0;j < pathsForChain.length; j++) {
4538
- const path = pathsForChain[j];
4539
- let pathBip32 = import_pioneer_coins4.addressNListToBIP32(path.addressNListMaster);
4540
- let pubkey = this.pubkeys.find((pubkey2) => pubkey2.pathMaster === pathBip32);
4541
- if (!pubkey) {
4542
- const pubkey2 = await getPubkey(this.blockchains[i], path, this.keepKeySdk, this.context);
4543
- if (!pubkey2)
4544
- throw Error("Unable to get pubkey for network+ " + networkId);
4545
- this.addPubkey(pubkey2);
4546
- }
4547
- }
4548
- }
4935
+ this.syncState.syncProgress = 20;
4936
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4937
+ log2.info(tag6, "Discovering paths for blockchains...");
4938
+ this.paths = await ensurePathsForBlockchains(this.blockchains, this.paths, tag6);
4939
+ this.syncState.syncProgress = 30;
4940
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4941
+ log2.info(tag6, "Synchronizing pubkeys...");
4942
+ await syncPubkeysForBlockchains(this.blockchains, this.paths, this.pubkeys, this.keepKeySdk, this.context, getPubkey, (pubkey) => this.addPubkey(pubkey), tag6);
4943
+ this.syncState.syncProgress = 50;
4944
+ this.syncState.syncedChains = this.blockchains.length;
4945
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4946
+ log2.info(tag6, "Fetching balances...");
4549
4947
  await this.getBalances();
4550
- console.log(tag6, "Loading charts (tokens + portfolio)...");
4948
+ this.syncState.syncProgress = 70;
4949
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4950
+ log2.info(tag6, "Loading charts (tokens + portfolio)...");
4551
4951
  await this.getCharts();
4552
- console.log(tag6, `Charts loaded. Total balances: ${this.balances.length}`);
4952
+ log2.info(tag6, `Charts loaded. Total balances: ${this.balances.length}`);
4953
+ this.syncState.syncProgress = 85;
4954
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4955
+ log2.info(tag6, "Syncing market prices...");
4553
4956
  await this.syncMarket();
4554
- const dashboardData = {
4555
- networks: [],
4556
- totalValueUsd: 0,
4557
- networkPercentages: []
4558
- };
4559
- let totalPortfolioValue = 0;
4560
- const networksTemp = [];
4561
- const uniqueBlockchains = [...new Set(this.blockchains)];
4562
- for (const blockchain of uniqueBlockchains) {
4563
- const filteredBalances = this.balances.filter((b) => {
4564
- const networkId = import_pioneer_caip8.caipToNetworkId(b.caip);
4565
- return networkId === blockchain || blockchain === "eip155:*" && networkId.startsWith("eip155:");
4566
- });
4567
- const balanceMap = new Map;
4568
- const isBitcoin = blockchain.includes("bip122:000000000019d6689c085ae165831e93");
4569
- if (isBitcoin) {
4570
- const bitcoinByValue = new Map;
4571
- filteredBalances.forEach((balance) => {
4572
- const valueKey = `${balance.balance}_${balance.valueUsd}`;
4573
- if (!bitcoinByValue.has(valueKey)) {
4574
- bitcoinByValue.set(valueKey, []);
4575
- }
4576
- bitcoinByValue.get(valueKey).push(balance);
4577
- });
4578
- for (const [valueKey, balances] of bitcoinByValue.entries()) {
4579
- if (balances.length === 3 && parseFloat(balances[0].valueUsd || "0") > 0) {
4580
- const xpubBalance = balances.find((b) => b.pubkey?.startsWith("xpub")) || balances[0];
4581
- const key = `${xpubBalance.caip}_${xpubBalance.pubkey || "default"}`;
4582
- balanceMap.set(key, xpubBalance);
4583
- } else {
4584
- balances.forEach((balance) => {
4585
- const key = `${balance.caip}_${balance.pubkey || "default"}`;
4586
- balanceMap.set(key, balance);
4587
- });
4588
- }
4589
- }
4590
- } else {
4591
- filteredBalances.forEach((balance) => {
4592
- const key = `${balance.caip}_${balance.pubkey || "default"}`;
4593
- if (!balanceMap.has(key) || parseFloat(balance.valueUsd || "0") > parseFloat(balanceMap.get(key).valueUsd || "0")) {
4594
- balanceMap.set(key, balance);
4595
- }
4596
- });
4597
- }
4598
- const networkBalances = Array.from(balanceMap.values());
4599
- const networkTotal = networkBalances.reduce((sum, balance, idx) => {
4600
- const valueUsd = typeof balance.valueUsd === "string" ? parseFloat(balance.valueUsd) : balance.valueUsd || 0;
4601
- return sum + valueUsd;
4602
- }, 0);
4603
- const nativeAssetCaip = import_pioneer_caip8.networkIdToCaip(blockchain);
4604
- const gasAsset = networkBalances.find((b) => b.caip === nativeAssetCaip);
4605
- const totalNativeBalance = networkBalances.filter((b) => b.caip === nativeAssetCaip).reduce((sum, balance) => {
4606
- const balanceNum = typeof balance.balance === "string" ? parseFloat(balance.balance) : balance.balance || 0;
4607
- return sum + balanceNum;
4608
- }, 0).toString();
4609
- networksTemp.push({
4610
- networkId: blockchain,
4611
- totalValueUsd: networkTotal,
4612
- gasAssetCaip: nativeAssetCaip || null,
4613
- gasAssetSymbol: gasAsset?.symbol || null,
4614
- icon: gasAsset?.icon || null,
4615
- color: gasAsset?.color || null,
4616
- totalNativeBalance
4617
- });
4618
- totalPortfolioValue += networkTotal;
4619
- }
4620
- dashboardData.networks = networksTemp.sort((a, b) => b.totalValueUsd - a.totalValueUsd);
4621
- dashboardData.totalValueUsd = totalPortfolioValue;
4622
- dashboardData.networkPercentages = dashboardData.networks.map((network) => ({
4623
- networkId: network.networkId,
4624
- percentage: totalPortfolioValue > 0 ? Number((network.totalValueUsd / totalPortfolioValue * 100).toFixed(2)) : 0
4625
- })).filter((entry) => entry.percentage > 0);
4626
- this.dashboard = dashboardData;
4627
- this.syncState = {
4628
- isSynced: true,
4629
- isInitialSync: false,
4630
- cacheAge: 0,
4631
- syncProgress: 100,
4632
- syncedChains: this.blockchains.length,
4633
- totalChains: this.blockchains.length,
4634
- lastSyncTime: Date.now(),
4635
- syncSource: "fresh"
4636
- };
4957
+ this.syncState.syncProgress = 95;
4958
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4959
+ log2.info(tag6, "Building dashboard...");
4960
+ this.dashboard = buildDashboardFromBalances(this.balances, [...new Set(this.blockchains)], this.assetsMap);
4961
+ this.syncState = createFreshSyncState(this.blockchains.length);
4637
4962
  this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4638
4963
  this.events.emit("SYNC_COMPLETE", this.syncState);
4964
+ log2.info(tag6, "✅ Sync complete!");
4639
4965
  return true;
4640
4966
  } catch (e) {
4641
- console.error(tag6, "Error in sync:", e);
4967
+ log2.error(tag6, "Sync failed:", e);
4968
+ this.syncState = {
4969
+ ...this.syncState,
4970
+ isSynced: false,
4971
+ syncProgress: 0
4972
+ };
4973
+ this.events.emit("SYNC_STATE_CHANGED", this.syncState);
4974
+ this.events.emit("SYNC_ERROR", e);
4642
4975
  throw e;
4643
4976
  }
4644
4977
  };
@@ -4652,7 +4985,7 @@ class SDK {
4652
4985
  }
4653
4986
  };
4654
4987
  this.buildTx = async function(sendPayload) {
4655
- let tag6 = TAG9 + " | buildTx | ";
4988
+ let tag6 = TAG12 + " | buildTx | ";
4656
4989
  try {
4657
4990
  const transactionDependencies = {
4658
4991
  context: this.context,
@@ -4674,7 +5007,7 @@ class SDK {
4674
5007
  }
4675
5008
  };
4676
5009
  this.buildDelegateTx = async function(caip, params) {
4677
- let tag6 = TAG9 + " | buildDelegateTx | ";
5010
+ let tag6 = TAG12 + " | buildDelegateTx | ";
4678
5011
  try {
4679
5012
  const delegateParams = {
4680
5013
  ...params,
@@ -4689,7 +5022,7 @@ class SDK {
4689
5022
  }
4690
5023
  };
4691
5024
  this.buildUndelegateTx = async function(caip, params) {
4692
- let tag6 = TAG9 + " | buildUndelegateTx | ";
5025
+ let tag6 = TAG12 + " | buildUndelegateTx | ";
4693
5026
  try {
4694
5027
  const undelegateParams = {
4695
5028
  ...params,
@@ -4704,7 +5037,7 @@ class SDK {
4704
5037
  }
4705
5038
  };
4706
5039
  this.buildClaimRewardsTx = async function(caip, params) {
4707
- let tag6 = TAG9 + " | buildClaimRewardsTx | ";
5040
+ let tag6 = TAG12 + " | buildClaimRewardsTx | ";
4708
5041
  try {
4709
5042
  const claimParams = {
4710
5043
  ...params,
@@ -4719,7 +5052,7 @@ class SDK {
4719
5052
  }
4720
5053
  };
4721
5054
  this.buildClaimAllRewardsTx = async function(caip, params) {
4722
- let tag6 = TAG9 + " | buildClaimAllRewardsTx | ";
5055
+ let tag6 = TAG12 + " | buildClaimAllRewardsTx | ";
4723
5056
  try {
4724
5057
  const claimAllParams = {
4725
5058
  ...params,
@@ -4733,7 +5066,7 @@ class SDK {
4733
5066
  }
4734
5067
  };
4735
5068
  this.signTx = async function(caip, unsignedTx) {
4736
- let tag6 = TAG9 + " | signTx | ";
5069
+ let tag6 = TAG12 + " | signTx | ";
4737
5070
  try {
4738
5071
  const transactionDependencies = {
4739
5072
  context: this.context,
@@ -4754,7 +5087,7 @@ class SDK {
4754
5087
  }
4755
5088
  };
4756
5089
  this.broadcastTx = async function(caip, signedTx) {
4757
- let tag6 = TAG9 + " | broadcastTx | ";
5090
+ let tag6 = TAG12 + " | broadcastTx | ";
4758
5091
  try {
4759
5092
  const transactionDependencies = {
4760
5093
  context: this.context,
@@ -4778,7 +5111,7 @@ class SDK {
4778
5111
  }
4779
5112
  };
4780
5113
  this.swap = async function(swapPayload) {
4781
- let tag6 = `${TAG9} | swap | `;
5114
+ let tag6 = `${TAG12} | swap | `;
4782
5115
  try {
4783
5116
  if (!swapPayload)
4784
5117
  throw Error("swapPayload required!");
@@ -4796,15 +5129,6 @@ class SDK {
4796
5129
  throw Error("Invalid networkId for outboundAssetContext");
4797
5130
  if (!this.outboundAssetContext || !this.outboundAssetContext.address)
4798
5131
  throw Error("Invalid outboundAssetContext missing address");
4799
- const matchesNetwork = (pubkey, networkId) => {
4800
- if (!pubkey.networks || !Array.isArray(pubkey.networks))
4801
- return false;
4802
- if (pubkey.networks.includes(networkId))
4803
- return true;
4804
- if (networkId.startsWith("eip155:") && pubkey.networks.includes("eip155:*"))
4805
- return true;
4806
- return false;
4807
- };
4808
5132
  const pubkeys = this.pubkeys.filter((e) => matchesNetwork(e, this.assetContext.networkId));
4809
5133
  let senderAddress = pubkeys[0]?.address || pubkeys[0]?.master || pubkeys[0]?.pubkey;
4810
5134
  if (!senderAddress)
@@ -4836,17 +5160,8 @@ class SDK {
4836
5160
  this.assetContext.balance = totalBalance.toString();
4837
5161
  this.assetContext.valueUsd = (totalBalance * parseFloat(this.assetContext.priceUsd || "0")).toFixed(2);
4838
5162
  console.log(tag6, `Updated assetContext balance to aggregated total: ${totalBalance}`);
4839
- const feeReserves = {
4840
- "bip122:000000000019d6689c085ae165831e93/slip44:0": 0.00005,
4841
- "eip155:1/slip44:60": 0.001,
4842
- "cosmos:thorchain-mainnet-v1/slip44:931": 0.02,
4843
- "bip122:00000000001a91e3dace36e2be3bf030/slip44:3": 1,
4844
- "bip122:000007d91d1254d60e2dd1ae58038307/slip44:5": 0.001,
4845
- "bip122:000000000000000000651ef99cb9fcbe/slip44:145": 0.0005
4846
- };
4847
- const reserve = feeReserves[swapPayload.caipIn] || 0.0001;
4848
- inputAmount = Math.max(0, totalBalance - reserve);
4849
- console.log(tag6, `Using max amount for swap: ${inputAmount} (total balance: ${totalBalance}, reserve: ${reserve})`);
5163
+ inputAmount = getMaxSendableAmount(totalBalance, swapPayload.caipIn);
5164
+ console.log(tag6, `Using max amount for swap: ${inputAmount} (total balance: ${totalBalance})`);
4850
5165
  } else {
4851
5166
  inputAmount = typeof swapPayload.amount === "string" ? parseFloat(swapPayload.amount) : swapPayload.amount;
4852
5167
  if (isNaN(inputAmount) || inputAmount <= 0) {
@@ -4967,7 +5282,7 @@ class SDK {
4967
5282
  }
4968
5283
  };
4969
5284
  this.transfer = async function(sendPayload) {
4970
- let tag6 = `${TAG9} | transfer | `;
5285
+ let tag6 = `${TAG12} | transfer | `;
4971
5286
  try {
4972
5287
  if (!sendPayload)
4973
5288
  throw Error("sendPayload required!");
@@ -5062,7 +5377,7 @@ class SDK {
5062
5377
  }
5063
5378
  };
5064
5379
  this.setBlockchains = async function(blockchains) {
5065
- const tag6 = `${TAG9} | setBlockchains | `;
5380
+ const tag6 = `${TAG12} | setBlockchains | `;
5066
5381
  try {
5067
5382
  if (!blockchains)
5068
5383
  throw Error("blockchains required!");
@@ -5078,7 +5393,7 @@ class SDK {
5078
5393
  }
5079
5394
  };
5080
5395
  this.addAsset = async function(caip, data) {
5081
- let tag6 = TAG9 + " | addAsset | ";
5396
+ let tag6 = TAG12 + " | addAsset | ";
5082
5397
  try {
5083
5398
  let success = false;
5084
5399
  if (!caip)
@@ -5116,7 +5431,7 @@ class SDK {
5116
5431
  }
5117
5432
  };
5118
5433
  this.clearWalletState = async function() {
5119
- const tag6 = `${TAG9} | clearWalletState | `;
5434
+ const tag6 = `${TAG12} | clearWalletState | `;
5120
5435
  try {
5121
5436
  this.context = null;
5122
5437
  this.paths = [];
@@ -5131,7 +5446,7 @@ class SDK {
5131
5446
  }
5132
5447
  };
5133
5448
  this.addPath = async function(path) {
5134
- const tag6 = `${TAG9} | addPath | `;
5449
+ const tag6 = `${TAG12} | addPath | `;
5135
5450
  try {
5136
5451
  this.paths.push(path);
5137
5452
  const pubkey = await getPubkey(path.networks[0], path, this.keepKeySdk, this.context);
@@ -5145,7 +5460,7 @@ class SDK {
5145
5460
  }
5146
5461
  };
5147
5462
  this.addPaths = async function(paths) {
5148
- const tag6 = `${TAG9} | addPaths | `;
5463
+ const tag6 = `${TAG12} | addPaths | `;
5149
5464
  try {
5150
5465
  console.log(tag6, `Adding ${paths.length} paths in batch mode...`);
5151
5466
  this.paths.push(...paths);
@@ -5181,7 +5496,7 @@ class SDK {
5181
5496
  return this.getGasAssets();
5182
5497
  };
5183
5498
  this.getGasAssets = async function() {
5184
- const tag6 = `${TAG9} | getGasAssets | `;
5499
+ const tag6 = `${TAG12} | getGasAssets | `;
5185
5500
  try {
5186
5501
  for (let i = 0;i < this.blockchains.length; i++) {
5187
5502
  let networkId = this.blockchains[i];
@@ -5195,28 +5510,6 @@ class SDK {
5195
5510
  throw Error("GAS Asset MISSING from assetData " + caip);
5196
5511
  }
5197
5512
  }
5198
- const mayaTokenCaip = "cosmos:mayachain-mainnet-v1/denom:maya";
5199
- if (!this.assetsMap.has(mayaTokenCaip)) {
5200
- const mayaToken = {
5201
- caip: mayaTokenCaip,
5202
- networkId: "cosmos:mayachain-mainnet-v1",
5203
- chainId: "mayachain-mainnet-v1",
5204
- symbol: "MAYA",
5205
- name: "Maya Token",
5206
- precision: 4,
5207
- decimals: 4,
5208
- color: "#00D4AA",
5209
- icon: "https://pioneers.dev/coins/maya.png",
5210
- explorer: "https://explorer.mayachain.info",
5211
- explorerAddressLink: "https://explorer.mayachain.info/address/{{address}}",
5212
- explorerTxLink: "https://explorer.mayachain.info/tx/{{txid}}",
5213
- type: "token",
5214
- isToken: true,
5215
- denom: "maya"
5216
- };
5217
- this.assetsMap.set(mayaTokenCaip, mayaToken);
5218
- console.log(tag6, "Added MAYA token to assetsMap");
5219
- }
5220
5513
  return this.assetsMap;
5221
5514
  } catch (e) {
5222
5515
  console.error(e);
@@ -5224,7 +5517,7 @@ class SDK {
5224
5517
  }
5225
5518
  };
5226
5519
  this.getPubkeys = async function() {
5227
- const tag6 = `${TAG9} | getPubkeys | `;
5520
+ const tag6 = `${TAG12} | getPubkeys | `;
5228
5521
  try {
5229
5522
  if (this.paths.length === 0)
5230
5523
  throw new Error("No paths found!");
@@ -5269,134 +5562,57 @@ class SDK {
5269
5562
  }
5270
5563
  };
5271
5564
  this.getBalancesForNetworks = async function(networkIds, forceRefresh) {
5272
- const tag6 = `${TAG9} | getBalancesForNetworks | `;
5565
+ const tag6 = `${TAG12} | getBalancesForNetworks | `;
5273
5566
  try {
5274
5567
  if (!this.pioneer) {
5275
- console.error(tag6, "ERROR: Pioneer client not initialized! this.pioneer is:", this.pioneer);
5276
5568
  throw new Error("Pioneer client not initialized. Call init() first.");
5277
5569
  }
5278
- if (forceRefresh) {
5279
- console.log(tag6, "\uD83D\uDD04 Force refresh requested - bypassing balance cache");
5280
- }
5281
- console.log("\uD83D\uDD0D [DIAGNOSTIC] Input networks:", networkIds);
5282
- console.log("\uD83D\uDD0D [DIAGNOSTIC] Total pubkeys:", this.pubkeys.length);
5283
- const pubkeysWithNetworks = this.pubkeys.filter((p) => p.networks && Array.isArray(p.networks));
5284
- const pubkeysWithoutNetworks = this.pubkeys.filter((p) => !p.networks || !Array.isArray(p.networks));
5285
- console.log("\uD83D\uDD0D [DIAGNOSTIC] Pubkeys WITH networks:", pubkeysWithNetworks.length);
5286
- console.log("\uD83D\uDD0D [DIAGNOSTIC] Pubkeys WITHOUT networks:", pubkeysWithoutNetworks.length);
5287
- if (pubkeysWithoutNetworks.length > 0) {
5288
- console.warn("⚠️ [WARNING] Some pubkeys missing networks field:");
5289
- pubkeysWithoutNetworks.forEach((pk) => {
5290
- console.warn(` - ${pk.note || pk.pubkey.slice(0, 10)}: networks=${pk.networks}`);
5291
- });
5292
- }
5570
+ if (forceRefresh)
5571
+ console.log(tag6, "\uD83D\uDD04 Force refresh requested");
5572
+ console.log("\uD83D\uDD0D [DIAGNOSTIC] Networks:", networkIds.length, "Pubkeys:", this.pubkeys.length);
5573
+ const { valid, invalid } = validatePubkeysNetworks(this.pubkeys, "\uD83D\uDD0D [DIAGNOSTIC]");
5574
+ console.log("\uD83D\uDD0D [DIAGNOSTIC] Pubkeys:", { valid: valid.length, invalid: invalid.length });
5293
5575
  const assetQuery = [];
5294
5576
  for (const networkId of networkIds) {
5295
- let adjustedNetworkId = networkId;
5296
- if (adjustedNetworkId.includes("eip155:")) {
5297
- adjustedNetworkId = "eip155:*";
5298
- }
5299
- const isEip155 = adjustedNetworkId.includes("eip155");
5300
- let pubkeys = this.pubkeys.filter((pubkey) => pubkey.networks && Array.isArray(pubkey.networks) && pubkey.networks.some((network) => {
5301
- if (isEip155)
5302
- return network.startsWith("eip155:");
5303
- return network === adjustedNetworkId;
5304
- }));
5305
- if (pubkeys.length === 0) {
5306
- console.warn(tag6, `⚠️ No pubkeys found for ${networkId} with networks field`);
5307
- console.warn(tag6, "Attempting fallback: finding pubkeys by path matching");
5308
- const pathsForNetwork = this.paths.filter((p) => p.networks?.includes(networkId) || networkId.startsWith("eip155:") && p.networks?.includes("eip155:*"));
5309
- for (const path of pathsForNetwork) {
5310
- const matchingPubkey = this.pubkeys.find((pk) => JSON.stringify(pk.addressNList) === JSON.stringify(path.addressNList));
5311
- if (matchingPubkey) {
5312
- console.warn(tag6, ` ✓ Found pubkey via path matching: ${matchingPubkey.note || matchingPubkey.pubkey.slice(0, 10)}`);
5313
- pubkeys.push(matchingPubkey);
5314
- }
5315
- }
5316
- if (pubkeys.length > 0) {
5317
- console.warn(tag6, ` ✅ Fallback successful: Found ${pubkeys.length} pubkeys for ${networkId}`);
5318
- } else {
5319
- console.error(tag6, ` ❌ Fallback failed: No pubkeys found for ${networkId}`);
5320
- }
5321
- }
5322
- const caipNative = await import_pioneer_caip8.networkIdToCaip(networkId);
5323
- for (const pubkey of pubkeys) {
5324
- assetQuery.push({ caip: caipNative, pubkey: pubkey.pubkey });
5325
- }
5326
- }
5327
- console.log("\uD83D\uDD0D [DIAGNOSTIC] Built assetQuery with", assetQuery.length, "entries");
5328
- console.log("\uD83D\uDD0D [DIAGNOSTIC] Sample queries:", assetQuery.slice(0, 5));
5329
- const caipCounts = new Map;
5330
- for (const query of assetQuery) {
5331
- caipCounts.set(query.caip, (caipCounts.get(query.caip) || 0) + 1);
5332
- }
5333
- console.log("\uD83D\uDD0D [DIAGNOSTIC] Queries by chain:");
5334
- caipCounts.forEach((count, caip) => {
5335
- console.log(` - ${caip}: ${count} queries`);
5336
- });
5337
- console.log(`⏱️ [PERF] Starting GetPortfolioBalances API call...`);
5338
- const apiCallStart = performance.now();
5339
- console.time("GetPortfolioBalances Response Time");
5340
- try {
5341
- let marketInfo = await this.pioneer.GetPortfolioBalances({ pubkeys: assetQuery }, forceRefresh ? { forceRefresh: true } : undefined);
5342
- const apiCallTime = performance.now() - apiCallStart;
5343
- console.timeEnd("GetPortfolioBalances Response Time");
5344
- console.log(`⏱️ [PERF] API call completed in ${apiCallTime.toFixed(0)}ms`);
5345
- const enrichStart = performance.now();
5346
- let balances = marketInfo.data;
5347
- console.log(`⏱️ [PERF] Received ${balances?.length || 0} balances from server`);
5348
- console.log(`⏱️ [PERF] Starting balance enrichment...`);
5349
- for (let balance of balances) {
5350
- const assetInfo = this.assetsMap.get(balance.caip.toLowerCase()) || this.assetsMap.get(balance.caip);
5351
- if (!assetInfo) {
5352
- console.warn(`⚠️ [ENRICHMENT] Asset metadata missing for ${balance.caip}, using fallback enrichment`);
5353
- const inferredType = this.inferTypeFromCaip(balance.caip);
5354
- Object.assign(balance, {
5355
- type: balance.type || inferredType,
5356
- isNative: balance.isNative ?? inferredType === "native",
5357
- networkId: import_pioneer_caip8.caipToNetworkId(balance.caip),
5358
- icon: "https://pioneers.dev/coins/unknown.png",
5359
- identifier: `${balance.caip}:${balance.pubkey}`,
5360
- updated: Date.now()
5361
- });
5362
- continue;
5363
- }
5364
- const color = ASSET_COLORS[balance.caip] || assetInfo.color;
5365
- Object.assign(balance, assetInfo, {
5366
- type: balance.type || assetInfo.type,
5367
- isNative: balance.isNative ?? assetInfo.isNative,
5368
- networkId: import_pioneer_caip8.caipToNetworkId(balance.caip),
5369
- icon: assetInfo.icon || "https://pioneers.dev/coins/etherum.png",
5370
- identifier: `${balance.caip}:${balance.pubkey}`,
5371
- updated: Date.now(),
5372
- color
5373
- });
5374
- }
5375
- const enrichTime = performance.now() - enrichStart;
5376
- console.log(`⏱️ [PERF] Enrichment completed in ${enrichTime.toFixed(0)}ms`);
5377
- this.balances = balances;
5378
- this.events.emit("SET_BALANCES", this.balances);
5379
- console.log(`⏱️ [PERF] Building dashboard from ${balances.length} balances...`);
5380
- const dashboardStart = performance.now();
5381
- const dashboardData = this.buildDashboardFromBalances();
5382
- this.dashboard = dashboardData;
5383
- this.events.emit("SET_DASHBOARD", this.dashboard);
5384
- console.log(`⏱️ [PERF] Dashboard built in ${(performance.now() - dashboardStart).toFixed(0)}ms`);
5385
- console.log(`\uD83D\uDCCA Dashboard created: ${this.dashboard?.networks?.length || 0} networks, $${this.dashboard?.totalValueUsd?.toFixed(2) || "0.00"} total`);
5386
- console.log(`⏱️ [PERF] Total getBalancesForNetworks: ${(performance.now() - apiCallStart).toFixed(0)}ms`);
5387
- return this.balances;
5388
- } catch (apiError) {
5389
- console.error(tag6, "GetPortfolioBalances API call failed:", apiError);
5390
- throw new Error(`GetPortfolioBalances API call failed: ${apiError?.message || "Unknown error"}`);
5577
+ const pubkeys = findPubkeysForNetwork(this.pubkeys, networkId, this.paths, tag6);
5578
+ const caip = await import_pioneer_caip8.networkIdToCaip(networkId);
5579
+ assetQuery.push(...buildAssetQuery(pubkeys, caip));
5391
5580
  }
5581
+ logQueryDiagnostics(assetQuery, "\uD83D\uDD0D [DIAGNOSTIC]");
5582
+ console.log(`⏱️ [PERF] Starting GetPortfolioBalances...`);
5583
+ const apiStart = performance.now();
5584
+ console.time("GetPortfolioBalances Response");
5585
+ const marketInfo = await this.pioneer.GetPortfolioBalances({ pubkeys: assetQuery }, forceRefresh ? { forceRefresh: true } : undefined);
5586
+ console.timeEnd("GetPortfolioBalances Response");
5587
+ console.log(`⏱️ [PERF] API completed in ${(performance.now() - apiStart).toFixed(0)}ms`);
5588
+ const enrichStart = performance.now();
5589
+ console.log(`⏱️ [PERF] Enriching ${marketInfo.data?.length || 0} balances...`);
5590
+ const balances = enrichBalancesWithAssetInfo(marketInfo.data, this.assetsMap, import_pioneer_caip8.caipToNetworkId);
5591
+ console.log(`⏱️ [PERF] Enrichment completed in ${(performance.now() - enrichStart).toFixed(0)}ms`);
5592
+ this.balances = balances;
5593
+ this.events.emit("SET_BALANCES", this.balances);
5594
+ const dashStart = performance.now();
5595
+ this.dashboard = this.buildDashboardFromBalances();
5596
+ this.events.emit("SET_DASHBOARD", this.dashboard);
5597
+ console.log(`⏱️ [PERF] Dashboard built in ${(performance.now() - dashStart).toFixed(0)}ms`);
5598
+ console.log(`\uD83D\uDCCA Dashboard: ${this.dashboard?.networks?.length || 0} networks, $${this.dashboard?.totalValueUsd?.toFixed(2) || "0.00"}`);
5599
+ console.log(`⏱️ [PERF] Total: ${(performance.now() - apiStart).toFixed(0)}ms`);
5600
+ return this.balances;
5392
5601
  } catch (e) {
5393
- console.error(tag6, "Error: ", e);
5602
+ console.error(tag6, "Error:", e?.message || e);
5394
5603
  throw e;
5395
5604
  }
5396
5605
  };
5397
- this.getBalances = async function(forceRefresh) {
5398
- const tag6 = `${TAG9} | getBalances | `;
5606
+ this.getBalances = async function(forceRefresh, caip) {
5607
+ const tag6 = `${TAG12} | getBalances | `;
5399
5608
  try {
5609
+ if (caip) {
5610
+ console.log(tag6, `\uD83C\uDFAF Refreshing single asset: ${caip}`);
5611
+ const networkId = caip.split("/")[0];
5612
+ console.log(tag6, `\uD83D\uDCCD Target network: ${networkId}`);
5613
+ const results = await this.getBalancesForNetworks([networkId], forceRefresh);
5614
+ return results.filter((b) => b.caip === caip || b.networkId === networkId);
5615
+ }
5400
5616
  return await this.getBalancesForNetworks(this.blockchains, forceRefresh);
5401
5617
  } catch (e) {
5402
5618
  console.error(tag6, "Error in getBalances: ", e);
@@ -5404,7 +5620,7 @@ class SDK {
5404
5620
  }
5405
5621
  };
5406
5622
  this.getBalance = async function(networkId) {
5407
- const tag6 = `${TAG9} | getBalance | `;
5623
+ const tag6 = `${TAG12} | getBalance | `;
5408
5624
  try {
5409
5625
  const results = await this.getBalancesForNetworks([networkId]);
5410
5626
  const filtered = results.filter(async (b) => b.networkId === await import_pioneer_caip8.networkIdToCaip(networkId));
@@ -5415,7 +5631,7 @@ class SDK {
5415
5631
  }
5416
5632
  };
5417
5633
  this.getFees = async function(networkId) {
5418
- const tag6 = `${TAG9} | getFees | `;
5634
+ const tag6 = `${TAG12} | getFees | `;
5419
5635
  try {
5420
5636
  if (!this.pioneer) {
5421
5637
  throw new Error("Pioneer client not initialized. Call init() first.");
@@ -5430,7 +5646,7 @@ class SDK {
5430
5646
  return estimateTransactionFee(feeRate, unit, networkType, txSize);
5431
5647
  };
5432
5648
  this.getCharts = async function() {
5433
- const tag6 = `${TAG9} | getCharts | `;
5649
+ const tag6 = `${TAG12} | getCharts | `;
5434
5650
  try {
5435
5651
  console.log(tag6, "Fetching charts (portfolio + tokens + staking)...");
5436
5652
  const { getCharts: getChartsModular } = await Promise.resolve().then(() => (init_charts(), exports_charts));
@@ -5455,7 +5671,7 @@ class SDK {
5455
5671
  }
5456
5672
  };
5457
5673
  this.setContext = async (context) => {
5458
- const tag6 = `${TAG9} | setContext | `;
5674
+ const tag6 = `${TAG12} | setContext | `;
5459
5675
  try {
5460
5676
  if (!context)
5461
5677
  throw Error("context required!");
@@ -5468,7 +5684,7 @@ class SDK {
5468
5684
  }
5469
5685
  };
5470
5686
  this.setContextType = async (contextType) => {
5471
- const tag6 = `${TAG9} | setContextType | `;
5687
+ const tag6 = `${TAG12} | setContextType | `;
5472
5688
  try {
5473
5689
  if (!contextType)
5474
5690
  throw Error("contextType required!");
@@ -5481,7 +5697,7 @@ class SDK {
5481
5697
  }
5482
5698
  };
5483
5699
  this.refresh = async (forceRefresh) => {
5484
- const tag6 = `${TAG9} | refresh | `;
5700
+ const tag6 = `${TAG12} | refresh | `;
5485
5701
  try {
5486
5702
  if (forceRefresh) {
5487
5703
  console.log(tag6, "\uD83D\uDD04 Force refresh - fetching fresh balances from blockchain");
@@ -5496,7 +5712,7 @@ class SDK {
5496
5712
  }
5497
5713
  };
5498
5714
  this.setAssetContext = async function(asset) {
5499
- const tag6 = `${TAG9} | setAssetContext | `;
5715
+ const tag6 = `${TAG12} | setAssetContext | `;
5500
5716
  try {
5501
5717
  if (!asset) {
5502
5718
  this.assetContext = null;
@@ -5506,114 +5722,28 @@ class SDK {
5506
5722
  throw Error("Invalid Asset! missing caip!");
5507
5723
  if (!asset.networkId)
5508
5724
  asset.networkId = import_pioneer_caip8.caipToNetworkId(asset.caip);
5509
- if (!this.pubkeys || this.pubkeys.length === 0) {
5510
- const errorMsg = `Cannot set asset context for ${asset.caip} - no pubkeys loaded. Please initialize wallet first.`;
5511
- console.error(tag6, errorMsg);
5512
- throw new Error(errorMsg);
5513
- }
5514
- const pubkeysForNetwork = this.pubkeys.filter((e) => {
5515
- if (!e.networks || !Array.isArray(e.networks))
5516
- return false;
5517
- if (e.networks.includes(asset.networkId))
5518
- return true;
5519
- if (asset.networkId.startsWith("eip155:") && e.networks.includes("eip155:*")) {
5520
- return true;
5521
- }
5522
- return false;
5523
- });
5524
- if (pubkeysForNetwork.length === 0) {
5525
- const errorMsg = `Cannot set asset context for ${asset.caip} - no address/xpub found for network ${asset.networkId}`;
5526
- console.error(tag6, errorMsg);
5527
- console.error(tag6, "Available networks in pubkeys:", [
5528
- ...new Set(this.pubkeys.flatMap((p) => p.networks || []))
5529
- ]);
5530
- throw new Error(errorMsg);
5531
- }
5532
- const isUtxoChain = asset.networkId.startsWith("bip122:");
5533
- if (isUtxoChain) {
5534
- const xpubFound = pubkeysForNetwork.some((p) => p.type === "xpub" && p.pubkey);
5535
- if (!xpubFound) {
5536
- const errorMsg = `Cannot set asset context for UTXO chain ${asset.caip} - xpub required but not found`;
5537
- console.error(tag6, errorMsg);
5538
- throw new Error(errorMsg);
5539
- }
5540
- }
5541
- const hasValidAddress = pubkeysForNetwork.some((p) => p.address || p.master || p.pubkey);
5542
- if (!hasValidAddress) {
5543
- const errorMsg = `Cannot set asset context for ${asset.caip} - no valid address found in pubkeys`;
5544
- console.error(tag6, errorMsg);
5545
- throw new Error(errorMsg);
5546
- }
5725
+ validatePubkeysForNetwork(this.pubkeys, asset.networkId, asset.caip);
5726
+ const pubkeysForNetwork = findPubkeysForNetwork(this.pubkeys, asset.networkId);
5547
5727
  console.log(tag6, `✅ Validated: Found ${pubkeysForNetwork.length} addresses for ${asset.networkId}`);
5548
- let freshPriceUsd = 0;
5549
- try {
5550
- if (!asset.caip || typeof asset.caip !== "string" || !asset.caip.includes(":")) {
5551
- console.warn(tag6, "Invalid or missing CAIP, skipping market price fetch:", asset.caip);
5552
- } else {
5553
- console.log(tag6, "Fetching fresh market price for:", asset.caip);
5554
- const marketData = await this.pioneer.GetMarketInfo([asset.caip]);
5555
- console.log(tag6, "Market data response:", marketData);
5556
- if (marketData && marketData.data && marketData.data.length > 0) {
5557
- freshPriceUsd = marketData.data[0];
5558
- console.log(tag6, "✅ Fresh market price:", freshPriceUsd);
5559
- } else {
5560
- console.warn(tag6, "No market data returned for:", asset.caip);
5561
- }
5562
- }
5563
- } catch (marketError) {
5564
- console.error(tag6, "Error fetching market price:", marketError);
5565
- }
5566
- let assetInfo = this.assetsMap.get(asset.caip.toLowerCase());
5567
- console.log(tag6, "assetInfo: ", assetInfo);
5568
- let assetInfoDiscovery = import_pioneer_discovery2.assetData[asset.caip];
5569
- console.log(tag6, "assetInfoDiscovery: ", assetInfoDiscovery);
5570
- if (assetInfoDiscovery)
5571
- assetInfo = assetInfoDiscovery;
5572
- if (!assetInfo) {
5573
- console.log(tag6, "Building placeholder asset!");
5574
- assetInfo = {
5575
- caip: asset.caip.toLowerCase(),
5576
- networkId: asset.networkId,
5577
- symbol: asset.symbol || "UNKNOWN",
5578
- name: asset.name || "Unknown Asset",
5579
- icon: asset.icon || "https://pioneers.dev/coins/ethereum.png"
5580
- };
5581
- }
5728
+ const freshPriceUsd = await fetchMarketPrice(this.pioneer, asset.caip);
5729
+ let assetInfo = resolveAssetInfo(this.assetsMap, import_pioneer_discovery2.assetData, asset);
5582
5730
  const matchingBalances = this.balances.filter((b) => b.caip === asset.caip);
5583
5731
  if (matchingBalances.length > 0) {
5584
- let priceValue = matchingBalances[0].priceUsd || matchingBalances[0].price;
5585
- if ((!priceValue || priceValue === 0) && matchingBalances[0].valueUsd && matchingBalances[0].balance) {
5586
- const balance = parseFloat(matchingBalances[0].balance);
5587
- const valueUsd = parseFloat(matchingBalances[0].valueUsd);
5588
- if (balance > 0 && valueUsd > 0) {
5589
- priceValue = valueUsd / balance;
5590
- console.log(tag6, "calculated priceUsd from valueUsd/balance:", priceValue);
5591
- }
5592
- }
5593
- if (priceValue && priceValue > 0) {
5732
+ const priceValue = extractPriceFromBalances(matchingBalances);
5733
+ if (priceValue > 0) {
5594
5734
  console.log(tag6, "detected priceUsd from balance:", priceValue);
5595
5735
  assetInfo.priceUsd = priceValue;
5596
5736
  }
5597
5737
  }
5598
- if (freshPriceUsd && freshPriceUsd > 0) {
5738
+ if (freshPriceUsd > 0) {
5599
5739
  assetInfo.priceUsd = freshPriceUsd;
5600
5740
  console.log(tag6, "✅ Using fresh market price:", freshPriceUsd);
5601
- let totalBalance = 0;
5602
- let totalValueUsd = 0;
5603
- console.log(tag6, `Found ${matchingBalances.length} balance entries for ${asset.caip}`);
5604
- for (const balanceEntry of matchingBalances) {
5605
- const balance = parseFloat(balanceEntry.balance) || 0;
5606
- const valueUsd = parseFloat(balanceEntry.valueUsd) || 0;
5607
- totalBalance += balance;
5608
- totalValueUsd += valueUsd;
5609
- console.log(tag6, ` Balance entry: ${balance} (${valueUsd} USD)`);
5610
- }
5741
+ const { totalBalance, totalValueUsd } = aggregateBalances(matchingBalances, asset.caip);
5611
5742
  assetInfo.balance = totalBalance.toString();
5612
5743
  assetInfo.valueUsd = totalValueUsd.toFixed(2);
5613
- console.log(tag6, `Aggregated balance: ${totalBalance} (${totalValueUsd.toFixed(2)} USD)`);
5614
5744
  }
5615
5745
  const assetBalances = this.balances.filter((b) => b.caip === asset.caip);
5616
- const assetPubkeys = this.pubkeys.filter((p) => p.networks && Array.isArray(p.networks) && p.networks.includes(import_pioneer_caip8.caipToNetworkId(asset.caip)) || import_pioneer_caip8.caipToNetworkId(asset.caip).includes("eip155") && p.networks && Array.isArray(p.networks) && p.networks.some((n) => n.startsWith("eip155")));
5746
+ const assetPubkeys = filterPubkeysForAsset(this.pubkeys, asset.caip, import_pioneer_caip8.caipToNetworkId);
5617
5747
  const finalAssetContext = {
5618
5748
  ...assetInfo,
5619
5749
  ...asset,
@@ -5623,45 +5753,12 @@ class SDK {
5623
5753
  if ((!asset.priceUsd || asset.priceUsd === 0) && assetInfo.priceUsd && assetInfo.priceUsd > 0) {
5624
5754
  finalAssetContext.priceUsd = assetInfo.priceUsd;
5625
5755
  }
5626
- if (freshPriceUsd && freshPriceUsd > 0) {
5627
- for (const balance of assetBalances) {
5628
- balance.price = freshPriceUsd;
5629
- balance.priceUsd = freshPriceUsd;
5630
- const balanceAmount = parseFloat(balance.balance || 0);
5631
- balance.valueUsd = (balanceAmount * freshPriceUsd).toString();
5632
- }
5633
- console.log(tag6, "Updated all balances with fresh price data");
5756
+ if (freshPriceUsd > 0) {
5757
+ updateBalancesWithPrice(assetBalances, freshPriceUsd);
5634
5758
  }
5635
5759
  this.assetContext = finalAssetContext;
5636
5760
  if (asset.isToken || asset.type === "token" || assetInfo.isToken || assetInfo.type === "token") {
5637
5761
  const networkId = asset.networkId || assetInfo.networkId;
5638
- let nativeSymbol = "GAS";
5639
- let nativeCaip = "";
5640
- if (networkId.includes("mayachain")) {
5641
- nativeSymbol = "CACAO";
5642
- nativeCaip = "cosmos:mayachain-mainnet-v1/slip44:931";
5643
- } else if (networkId.includes("thorchain")) {
5644
- nativeSymbol = "RUNE";
5645
- nativeCaip = "cosmos:thorchain-mainnet-v1/slip44:931";
5646
- } else if (networkId.includes("cosmoshub")) {
5647
- nativeSymbol = "ATOM";
5648
- nativeCaip = "cosmos:cosmoshub-4/slip44:118";
5649
- } else if (networkId.includes("osmosis")) {
5650
- nativeSymbol = "OSMO";
5651
- nativeCaip = "cosmos:osmosis-1/slip44:118";
5652
- } else if (networkId.includes("eip155:1")) {
5653
- nativeSymbol = "ETH";
5654
- nativeCaip = "eip155:1/slip44:60";
5655
- } else if (networkId.includes("eip155:137")) {
5656
- nativeSymbol = "MATIC";
5657
- nativeCaip = "eip155:137/slip44:60";
5658
- } else if (networkId.includes("eip155:56")) {
5659
- nativeSymbol = "BNB";
5660
- nativeCaip = "eip155:56/slip44:60";
5661
- } else if (networkId.includes("eip155:43114")) {
5662
- nativeSymbol = "AVAX";
5663
- nativeCaip = "eip155:43114/slip44:60";
5664
- }
5665
5762
  this.assetContext.nativeSymbol = nativeSymbol;
5666
5763
  if (nativeCaip) {
5667
5764
  const nativeBalance = this.balances.find((b) => b.caip === nativeCaip);
@@ -5695,7 +5792,7 @@ class SDK {
5695
5792
  }
5696
5793
  };
5697
5794
  this.setPubkeyContext = async function(pubkey) {
5698
- let tag6 = `${TAG9} | setPubkeyContext | `;
5795
+ let tag6 = `${TAG12} | setPubkeyContext | `;
5699
5796
  try {
5700
5797
  if (!pubkey)
5701
5798
  throw Error("pubkey is required");
@@ -5714,97 +5811,40 @@ class SDK {
5714
5811
  }
5715
5812
  };
5716
5813
  this.setOutboundAssetContext = async function(asset) {
5717
- const tag6 = `${TAG9} | setOutputAssetContext | `;
5814
+ const tag6 = `${TAG12} | setOutputAssetContext | `;
5718
5815
  try {
5719
- console.log(tag6, "0. asset: ", asset);
5816
+ console.log(tag6, "asset:", asset);
5720
5817
  if (!asset) {
5721
5818
  this.outboundAssetContext = null;
5722
5819
  return;
5723
5820
  }
5724
- console.log(tag6, "1 asset: ", asset);
5725
5821
  if (!asset.caip)
5726
5822
  throw Error("Invalid Asset! missing caip!");
5727
5823
  if (!asset.networkId)
5728
5824
  asset.networkId = import_pioneer_caip8.caipToNetworkId(asset.caip);
5729
- console.log(tag6, "networkId: ", asset.networkId);
5730
- console.log(tag6, "this.pubkeys: ", this.pubkeys);
5731
- const pubkey = this.pubkeys.find((p) => {
5732
- if (!p.networks || !Array.isArray(p.networks))
5733
- return false;
5734
- if (p.networks.includes(asset.networkId))
5735
- return true;
5736
- if (asset.networkId.startsWith("eip155:") && p.networks.includes("eip155:*"))
5737
- return true;
5738
- return false;
5739
- });
5825
+ console.log(tag6, "networkId:", asset.networkId);
5826
+ const pubkey = findPubkeyForNetwork(this.pubkeys, asset.networkId);
5740
5827
  if (!pubkey)
5741
5828
  throw Error("Invalid network! missing pubkey for network! " + asset.networkId);
5742
- let freshPriceUsd = 0;
5743
- try {
5744
- if (!asset.caip || typeof asset.caip !== "string" || !asset.caip.includes(":")) {
5745
- console.warn(tag6, "Invalid or missing CAIP, skipping market price fetch:", asset.caip);
5746
- } else {
5747
- console.log(tag6, "Fetching fresh market price for:", asset.caip);
5748
- const marketData = await this.pioneer.GetMarketInfo([asset.caip]);
5749
- console.log(tag6, "Market data response:", marketData);
5750
- if (marketData && marketData.data && marketData.data.length > 0) {
5751
- freshPriceUsd = marketData.data[0];
5752
- console.log(tag6, "✅ Fresh market price:", freshPriceUsd);
5753
- } else {
5754
- console.warn(tag6, "No market data returned for:", asset.caip);
5755
- }
5756
- }
5757
- } catch (marketError) {
5758
- console.error(tag6, "Error fetching market price:", marketError);
5759
- }
5760
- let assetInfo = this.assetsMap.get(asset.caip.toLowerCase());
5761
- console.log(tag6, "assetInfo: ", assetInfo);
5762
- if (!assetInfo) {
5763
- assetInfo = {
5764
- caip: asset.caip.toLowerCase(),
5765
- networkId: asset.networkId,
5766
- symbol: asset.symbol || "UNKNOWN",
5767
- name: asset.name || "Unknown Asset",
5768
- icon: asset.icon || "https://pioneers.dev/coins/ethereum.png"
5769
- };
5770
- }
5829
+ const freshPriceUsd = await fetchMarketPrice(this.pioneer, asset.caip);
5830
+ let assetInfo = resolveAssetInfo(this.assetsMap, import_pioneer_discovery2.assetData, asset);
5771
5831
  const matchingBalances = this.balances.filter((b) => b.caip === asset.caip);
5772
5832
  if (matchingBalances.length > 0) {
5773
- let priceValue = matchingBalances[0].priceUsd || matchingBalances[0].price;
5774
- if ((!priceValue || priceValue === 0) && matchingBalances[0].valueUsd && matchingBalances[0].balance) {
5775
- const balance = parseFloat(matchingBalances[0].balance);
5776
- const valueUsd = parseFloat(matchingBalances[0].valueUsd);
5777
- if (balance > 0 && valueUsd > 0) {
5778
- priceValue = valueUsd / balance;
5779
- console.log(tag6, "calculated priceUsd from valueUsd/balance:", priceValue);
5780
- }
5781
- }
5782
- if (priceValue && priceValue > 0) {
5833
+ const priceValue = extractPriceFromBalances(matchingBalances);
5834
+ if (priceValue > 0) {
5783
5835
  console.log(tag6, "detected priceUsd from balance:", priceValue);
5784
5836
  assetInfo.priceUsd = priceValue;
5785
5837
  }
5786
5838
  }
5787
- if (freshPriceUsd && freshPriceUsd > 0) {
5839
+ if (freshPriceUsd > 0) {
5788
5840
  assetInfo.priceUsd = freshPriceUsd;
5789
5841
  console.log(tag6, "✅ Using fresh market price:", freshPriceUsd);
5790
- let totalBalance = 0;
5791
- let totalValueUsd = 0;
5792
- console.log(tag6, `Found ${matchingBalances.length} balance entries for ${asset.caip}`);
5793
- for (const balanceEntry of matchingBalances) {
5794
- const balance = parseFloat(balanceEntry.balance) || 0;
5795
- const valueUsd = parseFloat(balanceEntry.valueUsd) || 0;
5796
- totalBalance += balance;
5797
- totalValueUsd += valueUsd;
5798
- console.log(tag6, ` Balance entry: ${balance} (${valueUsd} USD)`);
5799
- }
5842
+ const { totalBalance, totalValueUsd } = aggregateBalances(matchingBalances, asset.caip);
5800
5843
  assetInfo.balance = totalBalance.toString();
5801
5844
  assetInfo.valueUsd = totalValueUsd.toFixed(2);
5802
- console.log(tag6, `Aggregated balance: ${totalBalance} (${totalValueUsd.toFixed(2)} USD)`);
5803
5845
  }
5804
- console.log(tag6, "CHECKPOINT 1");
5805
5846
  this.outboundAssetContext = { ...assetInfo, ...asset, ...pubkey };
5806
- console.log(tag6, "CHECKPOINT 3");
5807
- console.log(tag6, "outboundAssetContext: assetInfo: ", assetInfo);
5847
+ console.log(tag6, "outboundAssetContext set:", this.outboundAssetContext.caip);
5808
5848
  if (asset.caip) {
5809
5849
  this.outboundBlockchainContext = import_pioneer_caip8.caipToNetworkId(asset.caip);
5810
5850
  } else if (asset.networkId) {
@@ -5820,28 +5860,12 @@ class SDK {
5820
5860
  };
5821
5861
  }
5822
5862
  CheckERC20Allowance = async (params) => {
5823
- const tag6 = TAG9 + " | CheckERC20Allowance | ";
5824
- try {
5825
- console.log(tag6, "Checking ERC20 allowance:", params);
5826
- const result = await this.pioneer.GetTokenAllowance(params);
5827
- console.log(tag6, "Allowance result:", result);
5828
- return result.data;
5829
- } catch (e) {
5830
- console.error(tag6, "Error checking ERC20 allowance:", e);
5831
- throw e;
5832
- }
5863
+ const result = await this.pioneer.GetTokenAllowance(params);
5864
+ return result.data;
5833
5865
  };
5834
5866
  BuildERC20ApprovalTx = async (params) => {
5835
- const tag6 = TAG9 + " | BuildERC20ApprovalTx | ";
5836
- try {
5837
- console.log(tag6, "Building ERC20 approval transaction:", params);
5838
- const result = await this.pioneer.BuildApprovalTransaction(params);
5839
- console.log(tag6, "Approval tx built:", result);
5840
- return result.data;
5841
- } catch (e) {
5842
- console.error(tag6, "Error building approval transaction:", e);
5843
- throw e;
5844
- }
5867
+ const result = await this.pioneer.BuildApprovalTransaction(params);
5868
+ return result.data;
5845
5869
  };
5846
5870
  }
5847
5871
  var src_default = SDK;