@bitpay-labs/bitcore-wallet-service 11.6.0 → 11.6.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/package.json +2 -2
- package/src/externalservices/coingecko.ts +448 -368
- package/src/lib/common/utils.ts +37 -32
- package/src/lib/pushnotificationsservice.ts +12 -12
- package/src/lib/tss.ts +18 -10
- package/test/integration/externalservices/coinGecko.test.ts +811 -156
- package/test/integration/pushNotifications.test.ts +6 -6
- package/test/utils.test.ts +5 -0
- package/ts_build/package.json +3 -3
- package/ts_build/src/externalservices/coingecko.d.ts +24 -20
- package/ts_build/src/externalservices/coingecko.d.ts.map +1 -1
- package/ts_build/src/externalservices/coingecko.js +356 -306
- package/ts_build/src/externalservices/coingecko.js.map +1 -1
- package/ts_build/src/lib/common/index.d.ts +2 -2
- package/ts_build/src/lib/common/utils.d.ts +2 -2
- package/ts_build/src/lib/common/utils.d.ts.map +1 -1
- package/ts_build/src/lib/common/utils.js +28 -29
- package/ts_build/src/lib/common/utils.js.map +1 -1
- package/ts_build/src/lib/tss.d.ts.map +1 -1
- package/ts_build/src/lib/tss.js +2 -10
- package/ts_build/src/lib/tss.js.map +1 -1
- package/ts_build/test/integration/externalservices/coinGecko.test.d.ts +1 -1
- package/ts_build/test/integration/externalservices/coinGecko.test.d.ts.map +1 -1
- package/ts_build/test/integration/externalservices/coinGecko.test.js +710 -149
- package/ts_build/test/integration/externalservices/coinGecko.test.js.map +1 -1
- package/ts_build/test/utils.test.js +4 -0
- package/ts_build/test/utils.test.js.map +1 -1
package/src/lib/common/utils.ts
CHANGED
|
@@ -375,61 +375,66 @@ export const Utils = {
|
|
|
375
375
|
|
|
376
376
|
/**
|
|
377
377
|
* Sort array by keys in ascending order
|
|
378
|
-
* @param {Array<
|
|
379
|
-
* @param {...string|
|
|
378
|
+
* @param {Array<T>} arr Array to be sorted
|
|
379
|
+
* @param {...(string|string[])} keys Keys to sort by in order. If a key is an array, it will be treated as a nested key.
|
|
380
380
|
* e.g.: sortAsc(arr, 'a', 'b', ['c', 'd']) will sort by a, then b, then c.d
|
|
381
381
|
* @returns
|
|
382
382
|
*/
|
|
383
|
-
sortAsc(arr
|
|
384
|
-
function
|
|
385
|
-
if (
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
383
|
+
sortAsc<T = any>(arr: Array<T>, ...keys: (string | string[])[]): Array<T> {
|
|
384
|
+
function normalizeVal(v) {
|
|
385
|
+
if (v === undefined) return '\uFFFF'; // highest possible value, sorts last
|
|
386
|
+
if (v === null || v === false || v?.toString() === 'NaN') return 0;
|
|
387
|
+
if (v === true) return 1;
|
|
388
|
+
return v;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function compareVals(a, b): number {
|
|
392
|
+
a = normalizeVal(a);
|
|
393
|
+
b = normalizeVal(b);
|
|
394
|
+
|
|
395
|
+
// Compare bigints directly to avoid loss of precision via Number()
|
|
396
|
+
if (typeof a === 'bigint' && typeof b === 'bigint') {
|
|
397
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
391
398
|
}
|
|
392
399
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
400
|
+
// Numeric comparison for numbers, bigints, and non-empty numeric strings
|
|
401
|
+
const aIsNumeric = typeof a !== 'string' ? !isNaN(Number(a)) : a.trim() !== '' && !isNaN(Number(a));
|
|
402
|
+
const bIsNumeric = typeof b !== 'string' ? !isNaN(Number(b)) : b.trim() !== '' && !isNaN(Number(b));
|
|
403
|
+
if (aIsNumeric && bIsNumeric) {
|
|
404
|
+
const na = Number(a);
|
|
405
|
+
const nb = Number(b);
|
|
406
|
+
return na < nb ? -1 : na > nb ? 1 : 0;
|
|
399
407
|
}
|
|
400
408
|
|
|
401
|
-
|
|
402
|
-
|
|
409
|
+
// String comparison fallback
|
|
410
|
+
const sa = String(a);
|
|
411
|
+
const sb = String(b);
|
|
412
|
+
return sa < sb ? -1 : sa > sb ? 1 : 0;
|
|
413
|
+
}
|
|
403
414
|
|
|
404
415
|
if (!keys.length) {
|
|
405
|
-
return arr.sort((a, b) =>
|
|
406
|
-
} else if (keys.length === 1 && !Array.isArray(keys[0])) {
|
|
407
|
-
return arr.sort((a, b) => { const [_a, _b] = transformVals(a[keys[0]], b[keys[0]]); return _a.compare(_b); });
|
|
416
|
+
return arr.sort((a, b) => compareVals(a, b));
|
|
408
417
|
}
|
|
418
|
+
|
|
409
419
|
return arr.sort((a, b) => {
|
|
410
|
-
// compare concatenated strings for multiple key sorting
|
|
411
|
-
let aVal = '';
|
|
412
|
-
let bVal = '';
|
|
413
420
|
for (const k of keys) {
|
|
414
|
-
const
|
|
421
|
+
const cmp = compareVals(
|
|
415
422
|
Array.isArray(k) ? k.reduce((val, key) => val[key], a) : a[k],
|
|
416
423
|
Array.isArray(k) ? k.reduce((val, key) => val[key], b) : b[k]
|
|
417
424
|
);
|
|
418
|
-
|
|
419
|
-
aVal += aTemp.toString();
|
|
420
|
-
bVal += bTemp.toString();
|
|
425
|
+
if (cmp !== 0) return cmp;
|
|
421
426
|
}
|
|
422
|
-
return
|
|
427
|
+
return 0;
|
|
423
428
|
});
|
|
424
429
|
},
|
|
425
430
|
|
|
426
431
|
/**
|
|
427
432
|
* Sort array by keys in descending order
|
|
428
|
-
* @param {Array<
|
|
429
|
-
* @param {...string|
|
|
433
|
+
* @param {Array<T>} arr Array to be sorted
|
|
434
|
+
* @param {...(string|string[])} keys Keys to sort by in order. If a key is an array, it will be treated as a nested key.
|
|
430
435
|
* e.g.: sortDesc(arr, 'a', 'b', ['c', 'd']) will sort by a, then b, then c.d
|
|
431
436
|
*/
|
|
432
|
-
sortDesc(arr: Array<
|
|
437
|
+
sortDesc<T = any>(arr: Array<T>, ...keys: (string | string[])[]): Array<T> {
|
|
433
438
|
return Utils.sortAsc(arr, ...keys).reverse();
|
|
434
439
|
},
|
|
435
440
|
|
|
@@ -47,10 +47,10 @@ const PUSHNOTIFICATIONS_TYPES = {
|
|
|
47
47
|
dataOnly: true,
|
|
48
48
|
broadcastToActiveUsers: true
|
|
49
49
|
},
|
|
50
|
-
NewBlock: {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
},
|
|
50
|
+
// NewBlock: {
|
|
51
|
+
// dataOnly: true,
|
|
52
|
+
// broadcastToActiveUsers: true
|
|
53
|
+
// },
|
|
54
54
|
TxProposalAcceptedBy: {
|
|
55
55
|
dataOnly: true
|
|
56
56
|
},
|
|
@@ -713,15 +713,15 @@ export class PushNotificationsService {
|
|
|
713
713
|
|
|
714
714
|
private coinGeckoGetCredentials() {
|
|
715
715
|
if (!config.coinGecko) throw new Error('coinGecko missing credentials');
|
|
716
|
-
|
|
716
|
+
|
|
717
717
|
const credentials = {
|
|
718
718
|
API: config.coinGecko.api,
|
|
719
719
|
API_KEY: config.coinGecko.apiKey,
|
|
720
720
|
};
|
|
721
|
-
|
|
721
|
+
|
|
722
722
|
return credentials;
|
|
723
723
|
}
|
|
724
|
-
|
|
724
|
+
|
|
725
725
|
getTokenData(chain: string): Promise<Array<{
|
|
726
726
|
chainId: number;
|
|
727
727
|
address: string;
|
|
@@ -733,11 +733,11 @@ export class PushNotificationsService {
|
|
|
733
733
|
return new Promise((resolve, reject) => {
|
|
734
734
|
const cacheKey = `cgTokenList:${chain}`;
|
|
735
735
|
const credentials = this.coinGeckoGetCredentials();
|
|
736
|
-
|
|
736
|
+
|
|
737
737
|
this.storage.checkAndUseGlobalCache(cacheKey, Defaults.COIN_GECKO_CACHE_DURATION, (err, values, oldvalues) => {
|
|
738
738
|
if (err) logger.warn('Cache check failed', err);
|
|
739
739
|
if (values) return resolve(values);
|
|
740
|
-
|
|
740
|
+
|
|
741
741
|
const assetPlatformMap = {
|
|
742
742
|
eth: 'ethereum',
|
|
743
743
|
matic: 'polygon-pos',
|
|
@@ -747,17 +747,17 @@ export class PushNotificationsService {
|
|
|
747
747
|
op: 'optimistic-ethereum',
|
|
748
748
|
sol: 'solana',
|
|
749
749
|
};
|
|
750
|
-
|
|
750
|
+
|
|
751
751
|
const assetId = assetPlatformMap[chain];
|
|
752
752
|
if (!assetId) return reject(new Error(`Unsupported chain '${chain}'`));
|
|
753
|
-
|
|
753
|
+
|
|
754
754
|
const URL: string = `${credentials.API}/v3/token_lists/${assetId}/all.json`;
|
|
755
755
|
const headers = {
|
|
756
756
|
'Content-Type': 'application/json',
|
|
757
757
|
'Accept': 'application/json',
|
|
758
758
|
'x-cg-pro-api-key': credentials.API_KEY
|
|
759
759
|
};
|
|
760
|
-
|
|
760
|
+
|
|
761
761
|
this.request.get(
|
|
762
762
|
URL,
|
|
763
763
|
{
|
package/src/lib/tss.ts
CHANGED
|
@@ -185,12 +185,14 @@ class TssKeyGenClass {
|
|
|
185
185
|
id: string;
|
|
186
186
|
message: {
|
|
187
187
|
publicKey: ITssKeyMessageObject['publicKey'];
|
|
188
|
+
/** unused */
|
|
188
189
|
encryptedKeyChain: string;
|
|
189
190
|
};
|
|
191
|
+
/** unused - only needed for storing the encryptedKeyChain */
|
|
190
192
|
copayerId: string;
|
|
191
193
|
}) {
|
|
192
|
-
const { id, message
|
|
193
|
-
const { publicKey
|
|
194
|
+
const { id, message } = params;
|
|
195
|
+
const { publicKey } = message;
|
|
194
196
|
if (!publicKey) {
|
|
195
197
|
throw Errors.TSS_GENERIC_ERROR.withMessage('No public key provided');
|
|
196
198
|
}
|
|
@@ -210,15 +212,21 @@ class TssKeyGenClass {
|
|
|
210
212
|
}
|
|
211
213
|
}
|
|
212
214
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
/**
|
|
216
|
+
* 2026-03-10:
|
|
217
|
+
* Removing this feature until we decide to support keychain backup to our DB (probably never).
|
|
218
|
+
* If we ever decide to do this, we may need to add support in BWC for restoring it.
|
|
219
|
+
*/
|
|
216
220
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
221
|
+
// if (encryptedKeyChain) {
|
|
222
|
+
// const partyId = session.participants.indexOf(copayerId);
|
|
223
|
+
// const result = await storage.storeTssKeyShare({ id, partyId, encryptedKeyChain });
|
|
224
|
+
|
|
225
|
+
// if (!result.result.ok) {
|
|
226
|
+
// logger.error('Failed to store TSS key generation public key %o %o', id, result);
|
|
227
|
+
// throw Errors.TSS_GENERIC_ERROR.withMessage('Failed to store TSS key generation public key');
|
|
228
|
+
// }
|
|
229
|
+
// }
|
|
222
230
|
}
|
|
223
231
|
|
|
224
232
|
async storeBwsJoinSecret(params: {
|