@talismn/util 0.0.0-pr2080-20250710073919 → 0.0.0-pr2091-20250715125148

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.
@@ -1 +1,2 @@
1
1
  export declare const classNames: (...classLists: import("tailwind-merge").ClassNameValue[]) => string;
2
+ export declare const cn: (...classLists: import("tailwind-merge").ClassNameValue[]) => string;
@@ -1,12 +1,7 @@
1
1
  export * from "./addTrailingSlash";
2
2
  export * from "./BigMath";
3
- export * from "./blake2Concat";
4
3
  export * from "./classNames";
5
- export * from "./convertAddress";
6
- export * from "./decodeAnyAddress";
7
- export * from "./decodeSs58Format";
8
4
  export * from "./deferred";
9
- export * from "./encodeAnyAddress";
10
5
  export * from "./firstThenDebounce";
11
6
  export * from "./formatDecimals";
12
7
  export * from "./formatPrice";
@@ -15,18 +10,14 @@ export * from "./hasOwnProperty";
15
10
  export * from "./isArrayOf";
16
11
  export * from "./isBigInt";
17
12
  export * from "./isBooleanTrue";
18
- export * from "./isEthereumAddress";
19
- export * from "./isValidSubstrateAddress";
20
13
  export * from "./planckToTokens";
21
14
  export * from "./sleep";
22
15
  export * from "./throwAfter";
23
16
  export * from "./tokensToPlanck";
24
- export * from "./twox64Concat";
25
17
  export * from "./validateHexString";
26
- export * from "./normalizeAddress";
27
- export * from "./isAddressEqual";
28
18
  export * from "./isAscii";
29
19
  export * from "./isNotNil";
30
20
  export * from "./isTruthy";
31
21
  export * from "./isAbortError";
32
22
  export * from "./getSharedObservable";
23
+ export * from "./keepAlive";
@@ -0,0 +1,17 @@
1
+ import type { OperatorFunction } from "rxjs";
2
+ /**
3
+ * An RxJS operator that keeps the source observable alive for a specified duration
4
+ * after all subscribers have unsubscribed. This prevents expensive re-subscriptions
5
+ * when subscribers come and go frequently.
6
+ *
7
+ * @param keepAliveMs - Duration in milliseconds to keep the source alive after last unsubscription
8
+ * @returns MonoTypeOperatorFunction that can be used in pipe()
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const data$ = expensive_api_call$.pipe(
13
+ * keepAlive(3000) // Keep alive for 3 seconds
14
+ * );
15
+ * ```
16
+ */
17
+ export declare const keepAlive: <T>(timeout: number) => OperatorFunction<T, T>;
@@ -1,12 +1,11 @@
1
- import { HexString } from "@polkadot/util/types";
2
1
  /**
3
2
  * @name validateHexString
4
3
  * @description Checks if a string is a hex string. Required to account for type differences between different polkadot libraries
5
4
  * @param {string} str - string to check
6
- * @returns {HexString} - boolean
5
+ * @returns {`0x${string}`} - boolean
7
6
  * @example
8
7
  * validateHexString("0x1234") // "0x1234"
9
8
  * validateHexString("1234") // Error: Expected a hex string
10
9
  * validateHexString(1234) // Error: Expected a string
11
10
  **/
12
- export declare const validateHexString: (str: string) => HexString;
11
+ export declare const validateHexString: (str: string) => `0x${string}`;
@@ -1,9 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var util = require('@polkadot/util');
4
- var utilCrypto = require('@polkadot/util-crypto');
5
3
  var tailwindMerge = require('tailwind-merge');
6
- var keyring = require('@polkadot/keyring');
7
4
  var rxjs = require('rxjs');
8
5
  var BigNumber = require('bignumber.js');
9
6
 
@@ -45,54 +42,8 @@ const BigMath = {
45
42
  }
46
43
  };
47
44
 
48
- const bitLength$1 = 128;
49
- function blake2Concat(input) {
50
- return util.u8aToHex(util.u8aConcat(utilCrypto.blake2AsU8a(input, bitLength$1), util.u8aToU8a(input)));
51
- }
52
-
53
45
  const classNames = tailwindMerge.twMerge;
54
-
55
- function encodeAnyAddress(key, ss58Format) {
56
- try {
57
- return keyring.encodeAddress(key, ss58Format);
58
- } catch (error) {
59
- if (typeof key !== "string") throw error;
60
- if (!utilCrypto.isEthereumAddress(key)) throw error;
61
- return utilCrypto.ethereumEncode(key);
62
- }
63
- }
64
-
65
- /**
66
- *
67
- * @param address substrate SS58 address
68
- * @param prefix prefix used to format the address
69
- * @returns address encoded with supplied prefix
70
- */
71
- const convertAddress = (address, prefix) => {
72
- return encodeAnyAddress(address, prefix ?? undefined);
73
- };
74
-
75
- function decodeAnyAddress(encoded, ignoreChecksum, ss58Format) {
76
- try {
77
- return keyring.decodeAddress(encoded, ignoreChecksum, ss58Format);
78
- } catch (error) {
79
- if (typeof encoded !== "string") throw error;
80
- if (!utilCrypto.isEthereumAddress(encoded)) throw error;
81
- return util.hexToU8a(encoded.slice("0x".length));
82
- }
83
- }
84
-
85
- const decodeSs58Format = address => {
86
- if (!address) return;
87
- try {
88
- utilCrypto.decodeAddress(address);
89
- const decoded = utilCrypto.base58Decode(address);
90
- const [,,, ss58Format] = utilCrypto.checkAddressChecksum(decoded);
91
- return ss58Format;
92
- } catch {
93
- return; // invalid address
94
- }
95
- };
46
+ const cn = tailwindMerge.twMerge;
96
47
 
97
48
  /**
98
49
  * In TypeScript, a deferred promise refers to a pattern that involves creating a promise that can be
@@ -210,30 +161,6 @@ const isBigInt = value => typeof value === "bigint";
210
161
 
211
162
  const isBooleanTrue = x => !!x;
212
163
 
213
- const isEthereumAddress = address => !!address && address.startsWith("0x") && address.length === 42;
214
-
215
- /**
216
- * Similar to isValidAddress but will not call isEthereumAddress under the hood
217
- * @param address
218
- * @param prefix if supplied, the method will also check the prefix
219
- * @returns true if valid substrate (SS58) address, false otherwise
220
- */
221
- const isValidSubstrateAddress = (address, prefix) => {
222
- try {
223
- // attempt to encode, it will throw an error if address is invalid
224
- const encoded = keyring.encodeAddress(address, prefix ?? undefined);
225
-
226
- //if a prefix is supplied, check that reencoding using this prefix matches the input address
227
- if (prefix !== undefined) return address === encoded;
228
-
229
- //if no prefix supplied, the fact that decoding + encoding succeded indicates that the address is valid
230
- return true;
231
- } catch (error) {
232
- // input is not a substrate (SS58) address
233
- return false;
234
- }
235
- };
236
-
237
164
  function planckToTokens(planck, tokenDecimals) {
238
165
  if (typeof planck !== "string" || typeof tokenDecimals !== "number") return;
239
166
  const base = 10;
@@ -256,17 +183,11 @@ function tokensToPlanck(tokens, tokenDecimals) {
256
183
  return new BigNumber__default.default(tokens).multipliedBy(multiplier).toString(10);
257
184
  }
258
185
 
259
- const bitLength = 64;
260
- function twox64Concat(input) {
261
- const inputAsU8a = typeof input === "string" ? input : new Uint8Array(input);
262
- return util.u8aToHex(util.u8aConcat(utilCrypto.xxhashAsU8a(inputAsU8a, bitLength), util.u8aToU8a(inputAsU8a)));
263
- }
264
-
265
186
  /**
266
187
  * @name validateHexString
267
188
  * @description Checks if a string is a hex string. Required to account for type differences between different polkadot libraries
268
189
  * @param {string} str - string to check
269
- * @returns {HexString} - boolean
190
+ * @returns {`0x${string}`} - boolean
270
191
  * @example
271
192
  * validateHexString("0x1234") // "0x1234"
272
193
  * validateHexString("1234") // Error: Expected a hex string
@@ -282,24 +203,6 @@ const validateHexString = str => {
282
203
  throw new Error("Expected a hex string");
283
204
  };
284
205
 
285
- const CACHE$1 = new Map();
286
-
287
- // Normalize an address in a way that it can be compared to other addresses that have also been normalized
288
- const normalizeAddress = address => {
289
- try {
290
- if (!CACHE$1.has(address)) CACHE$1.set(address, encodeAnyAddress(address));
291
- return CACHE$1.get(address);
292
- } catch (cause) {
293
- throw new Error(`Unable to normalize address: ${address}`, {
294
- cause
295
- });
296
- }
297
- };
298
-
299
- const isAddressEqual = (address1, address2) => {
300
- return normalizeAddress(address1) === normalizeAddress(address2);
301
- };
302
-
303
206
  const isAscii = str => {
304
207
  return [...str].every(char => char.charCodeAt(0) <= 127);
305
208
  };
@@ -345,35 +248,61 @@ const getSharedObservable = (namespace, args, createObservable, serializer = arg
345
248
  return sharedObs;
346
249
  };
347
250
 
251
+ /**
252
+ * An RxJS operator that keeps the source observable alive for a specified duration
253
+ * after all subscribers have unsubscribed. This prevents expensive re-subscriptions
254
+ * when subscribers come and go frequently.
255
+ *
256
+ * @param keepAliveMs - Duration in milliseconds to keep the source alive after last unsubscription
257
+ * @returns MonoTypeOperatorFunction that can be used in pipe()
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * const data$ = expensive_api_call$.pipe(
262
+ * keepAlive(3000) // Keep alive for 3 seconds
263
+ * );
264
+ * ```
265
+ */
266
+ const keepAlive = timeout => {
267
+ let release;
268
+ return source => source.pipe(rxjs.tap({
269
+ subscribe: () => {
270
+ release = keepSourceSubscribed(source, timeout);
271
+ },
272
+ unsubscribe: () => {
273
+ release?.();
274
+ }
275
+ }), rxjs.shareReplay({
276
+ refCount: true,
277
+ bufferSize: 1
278
+ }));
279
+ };
280
+ const keepSourceSubscribed = (observable, ms) => {
281
+ const sub = observable.subscribe();
282
+ return () => setTimeout(() => sub.unsubscribe(), ms);
283
+ };
284
+
348
285
  exports.BigMath = BigMath;
349
286
  exports.Deferred = Deferred;
350
287
  exports.MAX_DECIMALS_FORMAT = MAX_DECIMALS_FORMAT;
351
288
  exports.addTrailingSlash = addTrailingSlash;
352
- exports.blake2Concat = blake2Concat;
353
289
  exports.classNames = classNames;
354
- exports.convertAddress = convertAddress;
355
- exports.decodeAnyAddress = decodeAnyAddress;
356
- exports.decodeSs58Format = decodeSs58Format;
357
- exports.encodeAnyAddress = encodeAnyAddress;
290
+ exports.cn = cn;
358
291
  exports.firstThenDebounce = firstThenDebounce;
359
292
  exports.formatDecimals = formatDecimals;
360
293
  exports.formatPrice = formatPrice;
361
294
  exports.getSharedObservable = getSharedObservable;
362
295
  exports.hasOwnProperty = hasOwnProperty;
363
296
  exports.isAbortError = isAbortError;
364
- exports.isAddressEqual = isAddressEqual;
365
297
  exports.isArrayOf = isArrayOf;
366
298
  exports.isAscii = isAscii;
367
299
  exports.isBigInt = isBigInt;
368
300
  exports.isBooleanTrue = isBooleanTrue;
369
- exports.isEthereumAddress = isEthereumAddress;
370
301
  exports.isNotNil = isNotNil;
371
302
  exports.isTruthy = isTruthy;
372
- exports.isValidSubstrateAddress = isValidSubstrateAddress;
373
- exports.normalizeAddress = normalizeAddress;
303
+ exports.keepAlive = keepAlive;
374
304
  exports.planckToTokens = planckToTokens;
375
305
  exports.sleep = sleep;
376
306
  exports.throwAfter = throwAfter;
377
307
  exports.tokensToPlanck = tokensToPlanck;
378
- exports.twox64Concat = twox64Concat;
379
308
  exports.validateHexString = validateHexString;
@@ -1,9 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var util = require('@polkadot/util');
4
- var utilCrypto = require('@polkadot/util-crypto');
5
3
  var tailwindMerge = require('tailwind-merge');
6
- var keyring = require('@polkadot/keyring');
7
4
  var rxjs = require('rxjs');
8
5
  var BigNumber = require('bignumber.js');
9
6
 
@@ -45,54 +42,8 @@ const BigMath = {
45
42
  }
46
43
  };
47
44
 
48
- const bitLength$1 = 128;
49
- function blake2Concat(input) {
50
- return util.u8aToHex(util.u8aConcat(utilCrypto.blake2AsU8a(input, bitLength$1), util.u8aToU8a(input)));
51
- }
52
-
53
45
  const classNames = tailwindMerge.twMerge;
54
-
55
- function encodeAnyAddress(key, ss58Format) {
56
- try {
57
- return keyring.encodeAddress(key, ss58Format);
58
- } catch (error) {
59
- if (typeof key !== "string") throw error;
60
- if (!utilCrypto.isEthereumAddress(key)) throw error;
61
- return utilCrypto.ethereumEncode(key);
62
- }
63
- }
64
-
65
- /**
66
- *
67
- * @param address substrate SS58 address
68
- * @param prefix prefix used to format the address
69
- * @returns address encoded with supplied prefix
70
- */
71
- const convertAddress = (address, prefix) => {
72
- return encodeAnyAddress(address, prefix ?? undefined);
73
- };
74
-
75
- function decodeAnyAddress(encoded, ignoreChecksum, ss58Format) {
76
- try {
77
- return keyring.decodeAddress(encoded, ignoreChecksum, ss58Format);
78
- } catch (error) {
79
- if (typeof encoded !== "string") throw error;
80
- if (!utilCrypto.isEthereumAddress(encoded)) throw error;
81
- return util.hexToU8a(encoded.slice("0x".length));
82
- }
83
- }
84
-
85
- const decodeSs58Format = address => {
86
- if (!address) return;
87
- try {
88
- utilCrypto.decodeAddress(address);
89
- const decoded = utilCrypto.base58Decode(address);
90
- const [,,, ss58Format] = utilCrypto.checkAddressChecksum(decoded);
91
- return ss58Format;
92
- } catch {
93
- return; // invalid address
94
- }
95
- };
46
+ const cn = tailwindMerge.twMerge;
96
47
 
97
48
  /**
98
49
  * In TypeScript, a deferred promise refers to a pattern that involves creating a promise that can be
@@ -210,30 +161,6 @@ const isBigInt = value => typeof value === "bigint";
210
161
 
211
162
  const isBooleanTrue = x => !!x;
212
163
 
213
- const isEthereumAddress = address => !!address && address.startsWith("0x") && address.length === 42;
214
-
215
- /**
216
- * Similar to isValidAddress but will not call isEthereumAddress under the hood
217
- * @param address
218
- * @param prefix if supplied, the method will also check the prefix
219
- * @returns true if valid substrate (SS58) address, false otherwise
220
- */
221
- const isValidSubstrateAddress = (address, prefix) => {
222
- try {
223
- // attempt to encode, it will throw an error if address is invalid
224
- const encoded = keyring.encodeAddress(address, prefix ?? undefined);
225
-
226
- //if a prefix is supplied, check that reencoding using this prefix matches the input address
227
- if (prefix !== undefined) return address === encoded;
228
-
229
- //if no prefix supplied, the fact that decoding + encoding succeded indicates that the address is valid
230
- return true;
231
- } catch (error) {
232
- // input is not a substrate (SS58) address
233
- return false;
234
- }
235
- };
236
-
237
164
  function planckToTokens(planck, tokenDecimals) {
238
165
  if (typeof planck !== "string" || typeof tokenDecimals !== "number") return;
239
166
  const base = 10;
@@ -256,17 +183,11 @@ function tokensToPlanck(tokens, tokenDecimals) {
256
183
  return new BigNumber__default.default(tokens).multipliedBy(multiplier).toString(10);
257
184
  }
258
185
 
259
- const bitLength = 64;
260
- function twox64Concat(input) {
261
- const inputAsU8a = typeof input === "string" ? input : new Uint8Array(input);
262
- return util.u8aToHex(util.u8aConcat(utilCrypto.xxhashAsU8a(inputAsU8a, bitLength), util.u8aToU8a(inputAsU8a)));
263
- }
264
-
265
186
  /**
266
187
  * @name validateHexString
267
188
  * @description Checks if a string is a hex string. Required to account for type differences between different polkadot libraries
268
189
  * @param {string} str - string to check
269
- * @returns {HexString} - boolean
190
+ * @returns {`0x${string}`} - boolean
270
191
  * @example
271
192
  * validateHexString("0x1234") // "0x1234"
272
193
  * validateHexString("1234") // Error: Expected a hex string
@@ -282,24 +203,6 @@ const validateHexString = str => {
282
203
  throw new Error("Expected a hex string");
283
204
  };
284
205
 
285
- const CACHE$1 = new Map();
286
-
287
- // Normalize an address in a way that it can be compared to other addresses that have also been normalized
288
- const normalizeAddress = address => {
289
- try {
290
- if (!CACHE$1.has(address)) CACHE$1.set(address, encodeAnyAddress(address));
291
- return CACHE$1.get(address);
292
- } catch (cause) {
293
- throw new Error(`Unable to normalize address: ${address}`, {
294
- cause
295
- });
296
- }
297
- };
298
-
299
- const isAddressEqual = (address1, address2) => {
300
- return normalizeAddress(address1) === normalizeAddress(address2);
301
- };
302
-
303
206
  const isAscii = str => {
304
207
  return [...str].every(char => char.charCodeAt(0) <= 127);
305
208
  };
@@ -345,35 +248,61 @@ const getSharedObservable = (namespace, args, createObservable, serializer = arg
345
248
  return sharedObs;
346
249
  };
347
250
 
251
+ /**
252
+ * An RxJS operator that keeps the source observable alive for a specified duration
253
+ * after all subscribers have unsubscribed. This prevents expensive re-subscriptions
254
+ * when subscribers come and go frequently.
255
+ *
256
+ * @param keepAliveMs - Duration in milliseconds to keep the source alive after last unsubscription
257
+ * @returns MonoTypeOperatorFunction that can be used in pipe()
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * const data$ = expensive_api_call$.pipe(
262
+ * keepAlive(3000) // Keep alive for 3 seconds
263
+ * );
264
+ * ```
265
+ */
266
+ const keepAlive = timeout => {
267
+ let release;
268
+ return source => source.pipe(rxjs.tap({
269
+ subscribe: () => {
270
+ release = keepSourceSubscribed(source, timeout);
271
+ },
272
+ unsubscribe: () => {
273
+ release?.();
274
+ }
275
+ }), rxjs.shareReplay({
276
+ refCount: true,
277
+ bufferSize: 1
278
+ }));
279
+ };
280
+ const keepSourceSubscribed = (observable, ms) => {
281
+ const sub = observable.subscribe();
282
+ return () => setTimeout(() => sub.unsubscribe(), ms);
283
+ };
284
+
348
285
  exports.BigMath = BigMath;
349
286
  exports.Deferred = Deferred;
350
287
  exports.MAX_DECIMALS_FORMAT = MAX_DECIMALS_FORMAT;
351
288
  exports.addTrailingSlash = addTrailingSlash;
352
- exports.blake2Concat = blake2Concat;
353
289
  exports.classNames = classNames;
354
- exports.convertAddress = convertAddress;
355
- exports.decodeAnyAddress = decodeAnyAddress;
356
- exports.decodeSs58Format = decodeSs58Format;
357
- exports.encodeAnyAddress = encodeAnyAddress;
290
+ exports.cn = cn;
358
291
  exports.firstThenDebounce = firstThenDebounce;
359
292
  exports.formatDecimals = formatDecimals;
360
293
  exports.formatPrice = formatPrice;
361
294
  exports.getSharedObservable = getSharedObservable;
362
295
  exports.hasOwnProperty = hasOwnProperty;
363
296
  exports.isAbortError = isAbortError;
364
- exports.isAddressEqual = isAddressEqual;
365
297
  exports.isArrayOf = isArrayOf;
366
298
  exports.isAscii = isAscii;
367
299
  exports.isBigInt = isBigInt;
368
300
  exports.isBooleanTrue = isBooleanTrue;
369
- exports.isEthereumAddress = isEthereumAddress;
370
301
  exports.isNotNil = isNotNil;
371
302
  exports.isTruthy = isTruthy;
372
- exports.isValidSubstrateAddress = isValidSubstrateAddress;
373
- exports.normalizeAddress = normalizeAddress;
303
+ exports.keepAlive = keepAlive;
374
304
  exports.planckToTokens = planckToTokens;
375
305
  exports.sleep = sleep;
376
306
  exports.throwAfter = throwAfter;
377
307
  exports.tokensToPlanck = tokensToPlanck;
378
- exports.twox64Concat = twox64Concat;
379
308
  exports.validateHexString = validateHexString;
@@ -1,8 +1,5 @@
1
- import { u8aToHex, u8aConcat, u8aToU8a, hexToU8a } from '@polkadot/util';
2
- import { blake2AsU8a, isEthereumAddress as isEthereumAddress$1, ethereumEncode, decodeAddress as decodeAddress$1, base58Decode, checkAddressChecksum, xxhashAsU8a } from '@polkadot/util-crypto';
3
1
  import { twMerge } from 'tailwind-merge';
4
- import { encodeAddress, decodeAddress } from '@polkadot/keyring';
5
- import { concat, take, skip, debounceTime, shareReplay } from 'rxjs';
2
+ import { concat, take, skip, debounceTime, shareReplay, tap } from 'rxjs';
6
3
  import BigNumber from 'bignumber.js';
7
4
 
8
5
  const addTrailingSlash = url => {
@@ -39,54 +36,8 @@ const BigMath = {
39
36
  }
40
37
  };
41
38
 
42
- const bitLength$1 = 128;
43
- function blake2Concat(input) {
44
- return u8aToHex(u8aConcat(blake2AsU8a(input, bitLength$1), u8aToU8a(input)));
45
- }
46
-
47
39
  const classNames = twMerge;
48
-
49
- function encodeAnyAddress(key, ss58Format) {
50
- try {
51
- return encodeAddress(key, ss58Format);
52
- } catch (error) {
53
- if (typeof key !== "string") throw error;
54
- if (!isEthereumAddress$1(key)) throw error;
55
- return ethereumEncode(key);
56
- }
57
- }
58
-
59
- /**
60
- *
61
- * @param address substrate SS58 address
62
- * @param prefix prefix used to format the address
63
- * @returns address encoded with supplied prefix
64
- */
65
- const convertAddress = (address, prefix) => {
66
- return encodeAnyAddress(address, prefix ?? undefined);
67
- };
68
-
69
- function decodeAnyAddress(encoded, ignoreChecksum, ss58Format) {
70
- try {
71
- return decodeAddress(encoded, ignoreChecksum, ss58Format);
72
- } catch (error) {
73
- if (typeof encoded !== "string") throw error;
74
- if (!isEthereumAddress$1(encoded)) throw error;
75
- return hexToU8a(encoded.slice("0x".length));
76
- }
77
- }
78
-
79
- const decodeSs58Format = address => {
80
- if (!address) return;
81
- try {
82
- decodeAddress$1(address);
83
- const decoded = base58Decode(address);
84
- const [,,, ss58Format] = checkAddressChecksum(decoded);
85
- return ss58Format;
86
- } catch {
87
- return; // invalid address
88
- }
89
- };
40
+ const cn = twMerge;
90
41
 
91
42
  /**
92
43
  * In TypeScript, a deferred promise refers to a pattern that involves creating a promise that can be
@@ -204,30 +155,6 @@ const isBigInt = value => typeof value === "bigint";
204
155
 
205
156
  const isBooleanTrue = x => !!x;
206
157
 
207
- const isEthereumAddress = address => !!address && address.startsWith("0x") && address.length === 42;
208
-
209
- /**
210
- * Similar to isValidAddress but will not call isEthereumAddress under the hood
211
- * @param address
212
- * @param prefix if supplied, the method will also check the prefix
213
- * @returns true if valid substrate (SS58) address, false otherwise
214
- */
215
- const isValidSubstrateAddress = (address, prefix) => {
216
- try {
217
- // attempt to encode, it will throw an error if address is invalid
218
- const encoded = encodeAddress(address, prefix ?? undefined);
219
-
220
- //if a prefix is supplied, check that reencoding using this prefix matches the input address
221
- if (prefix !== undefined) return address === encoded;
222
-
223
- //if no prefix supplied, the fact that decoding + encoding succeded indicates that the address is valid
224
- return true;
225
- } catch (error) {
226
- // input is not a substrate (SS58) address
227
- return false;
228
- }
229
- };
230
-
231
158
  function planckToTokens(planck, tokenDecimals) {
232
159
  if (typeof planck !== "string" || typeof tokenDecimals !== "number") return;
233
160
  const base = 10;
@@ -250,17 +177,11 @@ function tokensToPlanck(tokens, tokenDecimals) {
250
177
  return new BigNumber(tokens).multipliedBy(multiplier).toString(10);
251
178
  }
252
179
 
253
- const bitLength = 64;
254
- function twox64Concat(input) {
255
- const inputAsU8a = typeof input === "string" ? input : new Uint8Array(input);
256
- return u8aToHex(u8aConcat(xxhashAsU8a(inputAsU8a, bitLength), u8aToU8a(inputAsU8a)));
257
- }
258
-
259
180
  /**
260
181
  * @name validateHexString
261
182
  * @description Checks if a string is a hex string. Required to account for type differences between different polkadot libraries
262
183
  * @param {string} str - string to check
263
- * @returns {HexString} - boolean
184
+ * @returns {`0x${string}`} - boolean
264
185
  * @example
265
186
  * validateHexString("0x1234") // "0x1234"
266
187
  * validateHexString("1234") // Error: Expected a hex string
@@ -276,24 +197,6 @@ const validateHexString = str => {
276
197
  throw new Error("Expected a hex string");
277
198
  };
278
199
 
279
- const CACHE$1 = new Map();
280
-
281
- // Normalize an address in a way that it can be compared to other addresses that have also been normalized
282
- const normalizeAddress = address => {
283
- try {
284
- if (!CACHE$1.has(address)) CACHE$1.set(address, encodeAnyAddress(address));
285
- return CACHE$1.get(address);
286
- } catch (cause) {
287
- throw new Error(`Unable to normalize address: ${address}`, {
288
- cause
289
- });
290
- }
291
- };
292
-
293
- const isAddressEqual = (address1, address2) => {
294
- return normalizeAddress(address1) === normalizeAddress(address2);
295
- };
296
-
297
200
  const isAscii = str => {
298
201
  return [...str].every(char => char.charCodeAt(0) <= 127);
299
202
  };
@@ -339,4 +242,38 @@ const getSharedObservable = (namespace, args, createObservable, serializer = arg
339
242
  return sharedObs;
340
243
  };
341
244
 
342
- export { BigMath, Deferred, MAX_DECIMALS_FORMAT, addTrailingSlash, blake2Concat, classNames, convertAddress, decodeAnyAddress, decodeSs58Format, encodeAnyAddress, firstThenDebounce, formatDecimals, formatPrice, getSharedObservable, hasOwnProperty, isAbortError, isAddressEqual, isArrayOf, isAscii, isBigInt, isBooleanTrue, isEthereumAddress, isNotNil, isTruthy, isValidSubstrateAddress, normalizeAddress, planckToTokens, sleep, throwAfter, tokensToPlanck, twox64Concat, validateHexString };
245
+ /**
246
+ * An RxJS operator that keeps the source observable alive for a specified duration
247
+ * after all subscribers have unsubscribed. This prevents expensive re-subscriptions
248
+ * when subscribers come and go frequently.
249
+ *
250
+ * @param keepAliveMs - Duration in milliseconds to keep the source alive after last unsubscription
251
+ * @returns MonoTypeOperatorFunction that can be used in pipe()
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * const data$ = expensive_api_call$.pipe(
256
+ * keepAlive(3000) // Keep alive for 3 seconds
257
+ * );
258
+ * ```
259
+ */
260
+ const keepAlive = timeout => {
261
+ let release;
262
+ return source => source.pipe(tap({
263
+ subscribe: () => {
264
+ release = keepSourceSubscribed(source, timeout);
265
+ },
266
+ unsubscribe: () => {
267
+ release?.();
268
+ }
269
+ }), shareReplay({
270
+ refCount: true,
271
+ bufferSize: 1
272
+ }));
273
+ };
274
+ const keepSourceSubscribed = (observable, ms) => {
275
+ const sub = observable.subscribe();
276
+ return () => setTimeout(() => sub.unsubscribe(), ms);
277
+ };
278
+
279
+ export { BigMath, Deferred, MAX_DECIMALS_FORMAT, addTrailingSlash, classNames, cn, firstThenDebounce, formatDecimals, formatPrice, getSharedObservable, hasOwnProperty, isAbortError, isArrayOf, isAscii, isBigInt, isBooleanTrue, isNotNil, isTruthy, keepAlive, planckToTokens, sleep, throwAfter, tokensToPlanck, validateHexString };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talismn/util",
3
- "version": "0.0.0-pr2080-20250710073919",
3
+ "version": "0.0.0-pr2091-20250715125148",
4
4
  "author": "Talisman",
5
5
  "homepage": "https://talisman.xyz",
6
6
  "license": "GPL-3.0-or-later",
@@ -26,9 +26,6 @@
26
26
  "tailwind-merge": "^2.5.4"
27
27
  },
28
28
  "devDependencies": {
29
- "@polkadot/keyring": "13.5.1",
30
- "@polkadot/util": "13.5.1",
31
- "@polkadot/util-crypto": "13.5.1",
32
29
  "@types/jest": "^29.5.14",
33
30
  "eslint": "^8.57.1",
34
31
  "jest": "^29.7.0",
@@ -38,9 +35,6 @@
38
35
  "@talismn/tsconfig": "0.0.2"
39
36
  },
40
37
  "peerDependencies": {
41
- "@polkadot/keyring": "*",
42
- "@polkadot/util": "*",
43
- "@polkadot/util-crypto": "*",
44
38
  "rxjs": ">= 7.8.1"
45
39
  },
46
40
  "eslintConfig": {
@@ -1 +0,0 @@
1
- export declare function blake2Concat(input: Uint8Array): `0x${string}`;
@@ -1,7 +0,0 @@
1
- /**
2
- *
3
- * @param address substrate SS58 address
4
- * @param prefix prefix used to format the address
5
- * @returns address encoded with supplied prefix
6
- */
7
- export declare const convertAddress: (address: string, prefix: number | null) => string;
@@ -1 +0,0 @@
1
- export declare function decodeAnyAddress(encoded?: string | Uint8Array | null | undefined, ignoreChecksum?: boolean | undefined, ss58Format?: number | undefined): Uint8Array;
@@ -1 +0,0 @@
1
- export declare const decodeSs58Format: (address?: string) => number | undefined;
@@ -1 +0,0 @@
1
- export declare function encodeAnyAddress(key: string | Uint8Array, ss58Format?: number | undefined): string;
@@ -1 +0,0 @@
1
- export declare const isAddressEqual: (address1: string, address2: string) => boolean;
@@ -1 +0,0 @@
1
- export declare const isEthereumAddress: (address: string | undefined | null) => address is `0x${string}`;
@@ -1,7 +0,0 @@
1
- /**
2
- * Similar to isValidAddress but will not call isEthereumAddress under the hood
3
- * @param address
4
- * @param prefix if supplied, the method will also check the prefix
5
- * @returns true if valid substrate (SS58) address, false otherwise
6
- */
7
- export declare const isValidSubstrateAddress: (address: string, prefix?: number | null) => boolean;
@@ -1 +0,0 @@
1
- export declare const normalizeAddress: (address: string) => string;
@@ -1 +0,0 @@
1
- export declare function twox64Concat(input: string | Buffer | Uint8Array): `0x${string}`;