@polkadot-apps/utils 0.2.1
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/README.md +88 -0
- package/dist/encoding.d.ts +28 -0
- package/dist/encoding.js +28 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/planck.d.ts +47 -0
- package/dist/planck.js +194 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# @polkadot-apps/utils
|
|
2
|
+
|
|
3
|
+
Encoding utilities and token formatting for the `@polkadot-apps` ecosystem.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @polkadot-apps/utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
### Encoding
|
|
14
|
+
|
|
15
|
+
General-purpose byte encoding/decoding functions for working with hex strings, UTF-8 text, and byte arrays.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { bytesToHex, hexToBytes, utf8ToBytes, concatBytes } from "@polkadot-apps/utils";
|
|
19
|
+
|
|
20
|
+
const hex = bytesToHex(new Uint8Array([0xab, 0xcd])); // "abcd"
|
|
21
|
+
const bytes = hexToBytes("abcd"); // Uint8Array [0xab, 0xcd]
|
|
22
|
+
const text = utf8ToBytes("hello"); // Uint8Array [104, 101, 108, 108, 111]
|
|
23
|
+
const combined = concatBytes(header, payload);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Token formatting
|
|
27
|
+
|
|
28
|
+
Convert between raw planck values (the smallest indivisible token unit on Substrate chains) and human-readable decimal strings.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { formatPlanck, parseToPlanck } from "@polkadot-apps/utils";
|
|
32
|
+
|
|
33
|
+
// Format planck to human-readable (default: 10 decimals for DOT)
|
|
34
|
+
formatPlanck(10_000_000_000n); // "1.0"
|
|
35
|
+
formatPlanck(15_000_000_000n); // "1.5"
|
|
36
|
+
formatPlanck(12_345_678_900n); // "1.23456789"
|
|
37
|
+
formatPlanck(0n); // "0.0"
|
|
38
|
+
|
|
39
|
+
// Parse human-readable to planck
|
|
40
|
+
parseToPlanck("1.5"); // 15_000_000_000n
|
|
41
|
+
parseToPlanck("100"); // 1_000_000_000_000n
|
|
42
|
+
|
|
43
|
+
// Custom decimals for other chains
|
|
44
|
+
formatPlanck(1_000_000_000_000n, 12); // "1.0"
|
|
45
|
+
parseToPlanck("1.0", 12); // 1_000_000_000_000n
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## API
|
|
49
|
+
|
|
50
|
+
### Encoding
|
|
51
|
+
|
|
52
|
+
| Function | Signature | Returns |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `bytesToHex` | `(bytes: Uint8Array)` | `string` (lowercase, no `0x` prefix) |
|
|
55
|
+
| `hexToBytes` | `(hex: string)` | `Uint8Array` (no `0x` prefix expected) |
|
|
56
|
+
| `utf8ToBytes` | `(str: string)` | `Uint8Array` |
|
|
57
|
+
| `concatBytes` | `(...arrays: Uint8Array[])` | `Uint8Array` |
|
|
58
|
+
|
|
59
|
+
### Token formatting
|
|
60
|
+
|
|
61
|
+
| Function | Signature | Returns |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `formatPlanck` | `(planck: bigint, decimals?: number)` | `string` |
|
|
64
|
+
| `parseToPlanck` | `(amount: string, decimals?: number)` | `bigint` |
|
|
65
|
+
|
|
66
|
+
**`formatPlanck(planck, decimals = 10)`**
|
|
67
|
+
|
|
68
|
+
Convert a planck bigint to a human-readable decimal string. Trailing zeros are trimmed but at least one fractional digit is always shown (e.g. `"1.0"`, not `"1"`).
|
|
69
|
+
|
|
70
|
+
- Throws `RangeError` if `planck < 0n`.
|
|
71
|
+
- Throws `RangeError` if `decimals` is not a non-negative integer.
|
|
72
|
+
|
|
73
|
+
**`parseToPlanck(amount, decimals = 10)`**
|
|
74
|
+
|
|
75
|
+
Parse a decimal string into its planck bigint representation. If the fractional part exceeds `decimals`, excess digits are truncated with a warning.
|
|
76
|
+
|
|
77
|
+
- Throws `Error` if `amount` is empty or contains invalid characters.
|
|
78
|
+
- Throws `RangeError` if `amount` is negative or `decimals` is invalid.
|
|
79
|
+
|
|
80
|
+
## Common mistakes
|
|
81
|
+
|
|
82
|
+
- **Passing a `0x`-prefixed string to `hexToBytes`.** The `@noble/hashes` implementation expects raw hex without a prefix. Strip it first: `hexToBytes(hex.slice(2))`.
|
|
83
|
+
- **Using `formatPlanck` with the wrong `decimals` for a chain.** DOT uses 10, KSM uses 12, many parachains use 18. Always check the chain's token metadata.
|
|
84
|
+
- **Assuming `parseToPlanck` rounds excess decimals.** It truncates, not rounds. `parseToPlanck("1.999999999999", 10)` gives the same result as `parseToPlanck("1.9999999999", 10)`.
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
Apache-2.0
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a `Uint8Array` to its lowercase hexadecimal string representation.
|
|
3
|
+
*
|
|
4
|
+
* @param bytes - The bytes to encode.
|
|
5
|
+
* @returns Hex string (no `0x` prefix).
|
|
6
|
+
*/
|
|
7
|
+
export { bytesToHex } from "@noble/hashes/utils.js";
|
|
8
|
+
/**
|
|
9
|
+
* Decode a hexadecimal string into a `Uint8Array`.
|
|
10
|
+
*
|
|
11
|
+
* @param hex - Hex string to decode (no `0x` prefix expected).
|
|
12
|
+
* @returns The decoded bytes.
|
|
13
|
+
*/
|
|
14
|
+
export { hexToBytes } from "@noble/hashes/utils.js";
|
|
15
|
+
/**
|
|
16
|
+
* Encode a UTF-8 string into a `Uint8Array`.
|
|
17
|
+
*
|
|
18
|
+
* @param str - The string to encode.
|
|
19
|
+
* @returns UTF-8 encoded bytes.
|
|
20
|
+
*/
|
|
21
|
+
export { utf8ToBytes } from "@noble/hashes/utils.js";
|
|
22
|
+
/**
|
|
23
|
+
* Concatenate multiple `Uint8Array` instances into a single `Uint8Array`.
|
|
24
|
+
*
|
|
25
|
+
* @param arrays - The byte arrays to concatenate.
|
|
26
|
+
* @returns A new `Uint8Array` containing all input bytes in order.
|
|
27
|
+
*/
|
|
28
|
+
export { concatBytes } from "@noble/hashes/utils.js";
|
package/dist/encoding.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a `Uint8Array` to its lowercase hexadecimal string representation.
|
|
3
|
+
*
|
|
4
|
+
* @param bytes - The bytes to encode.
|
|
5
|
+
* @returns Hex string (no `0x` prefix).
|
|
6
|
+
*/
|
|
7
|
+
export { bytesToHex } from "@noble/hashes/utils.js";
|
|
8
|
+
/**
|
|
9
|
+
* Decode a hexadecimal string into a `Uint8Array`.
|
|
10
|
+
*
|
|
11
|
+
* @param hex - Hex string to decode (no `0x` prefix expected).
|
|
12
|
+
* @returns The decoded bytes.
|
|
13
|
+
*/
|
|
14
|
+
export { hexToBytes } from "@noble/hashes/utils.js";
|
|
15
|
+
/**
|
|
16
|
+
* Encode a UTF-8 string into a `Uint8Array`.
|
|
17
|
+
*
|
|
18
|
+
* @param str - The string to encode.
|
|
19
|
+
* @returns UTF-8 encoded bytes.
|
|
20
|
+
*/
|
|
21
|
+
export { utf8ToBytes } from "@noble/hashes/utils.js";
|
|
22
|
+
/**
|
|
23
|
+
* Concatenate multiple `Uint8Array` instances into a single `Uint8Array`.
|
|
24
|
+
*
|
|
25
|
+
* @param arrays - The byte arrays to concatenate.
|
|
26
|
+
* @returns A new `Uint8Array` containing all input bytes in order.
|
|
27
|
+
*/
|
|
28
|
+
export { concatBytes } from "@noble/hashes/utils.js";
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @polkadot-apps/utils — Encoding utilities and token formatting for the Polkadot app ecosystem.
|
|
3
|
+
*
|
|
4
|
+
* Provides general-purpose byte encoding/decoding (`bytesToHex`, `hexToBytes`, `utf8ToBytes`,
|
|
5
|
+
* `concatBytes`) and Substrate token formatting (`formatPlanck`, `parseToPlanck`).
|
|
6
|
+
* All functions are synchronous and framework-agnostic.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
export * from "./encoding.js";
|
|
11
|
+
export * from "./planck.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @polkadot-apps/utils — Encoding utilities and token formatting for the Polkadot app ecosystem.
|
|
3
|
+
*
|
|
4
|
+
* Provides general-purpose byte encoding/decoding (`bytesToHex`, `hexToBytes`, `utf8ToBytes`,
|
|
5
|
+
* `concatBytes`) and Substrate token formatting (`formatPlanck`, `parseToPlanck`).
|
|
6
|
+
* All functions are synchronous and framework-agnostic.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
export * from "./encoding.js";
|
|
11
|
+
export * from "./planck.js";
|
package/dist/planck.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a planck (smallest indivisible token unit) value to a human-readable decimal string.
|
|
3
|
+
*
|
|
4
|
+
* Substrate chains store all token amounts as integer planck values. This function
|
|
5
|
+
* converts them to human-readable form (e.g. `10_000_000_000n` → `"1.0"` for DOT
|
|
6
|
+
* with 10 decimals). Trailing zeros are trimmed but at least one fractional digit
|
|
7
|
+
* is always shown.
|
|
8
|
+
*
|
|
9
|
+
* @param planck - The raw planck value as a bigint. Must be non-negative.
|
|
10
|
+
* @param decimals - Number of decimal places for the token (default: 10 for DOT).
|
|
11
|
+
* @returns A decimal string representation (e.g. `"1.5"`, `"0.0001"`).
|
|
12
|
+
* @throws {RangeError} If `planck` is negative or `decimals` is invalid.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { formatPlanck } from "@polkadot-apps/utils";
|
|
17
|
+
*
|
|
18
|
+
* formatPlanck(10_000_000_000n); // "1.0" (10 decimals, DOT default)
|
|
19
|
+
* formatPlanck(15_000_000_000n); // "1.5"
|
|
20
|
+
* formatPlanck(1_000_000_000_000n, 12); // "1.0" (12 decimals, e.g. Polkadot relay)
|
|
21
|
+
* formatPlanck(0n); // "0.0"
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatPlanck(planck: bigint, decimals?: number): string;
|
|
25
|
+
/**
|
|
26
|
+
* Parse a human-readable decimal token amount into its planck (smallest unit) representation.
|
|
27
|
+
*
|
|
28
|
+
* Converts a string like `"1.5"` into the corresponding bigint planck value
|
|
29
|
+
* (e.g. `15_000_000_000n` for 10 decimals). If the input has more fractional
|
|
30
|
+
* digits than `decimals`, excess digits are silently truncated with a warning log.
|
|
31
|
+
*
|
|
32
|
+
* @param amount - A non-negative decimal string (e.g. `"1.5"`, `"100"`, `"0.001"`).
|
|
33
|
+
* @param decimals - Number of decimal places for the token (default: 10 for DOT).
|
|
34
|
+
* @returns The planck value as a bigint.
|
|
35
|
+
* @throws {Error} If `amount` is empty, negative, or contains invalid characters.
|
|
36
|
+
* @throws {RangeError} If `decimals` is invalid.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { parseToPlanck } from "@polkadot-apps/utils";
|
|
41
|
+
*
|
|
42
|
+
* parseToPlanck("1.5"); // 15_000_000_000n (10 decimals, DOT default)
|
|
43
|
+
* parseToPlanck("100"); // 1_000_000_000_000n
|
|
44
|
+
* parseToPlanck("0.001", 12); // 1_000_000_000n (12 decimals)
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseToPlanck(amount: string, decimals?: number): bigint;
|
package/dist/planck.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { createLogger } from "@polkadot-apps/logger";
|
|
2
|
+
const log = createLogger("utils");
|
|
3
|
+
const MAX_REASONABLE_DECIMALS = 30;
|
|
4
|
+
/**
|
|
5
|
+
* Validate that `decimals` is a non-negative integer.
|
|
6
|
+
*
|
|
7
|
+
* @param decimals - The token decimal count to validate.
|
|
8
|
+
* @throws {RangeError} If `decimals` is negative, fractional, or not a safe integer.
|
|
9
|
+
*/
|
|
10
|
+
function validateDecimals(decimals) {
|
|
11
|
+
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
12
|
+
throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);
|
|
13
|
+
}
|
|
14
|
+
if (decimals > MAX_REASONABLE_DECIMALS) {
|
|
15
|
+
log.warn("Unusually large decimals value — possible bug", { decimals });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Convert a planck (smallest indivisible token unit) value to a human-readable decimal string.
|
|
20
|
+
*
|
|
21
|
+
* Substrate chains store all token amounts as integer planck values. This function
|
|
22
|
+
* converts them to human-readable form (e.g. `10_000_000_000n` → `"1.0"` for DOT
|
|
23
|
+
* with 10 decimals). Trailing zeros are trimmed but at least one fractional digit
|
|
24
|
+
* is always shown.
|
|
25
|
+
*
|
|
26
|
+
* @param planck - The raw planck value as a bigint. Must be non-negative.
|
|
27
|
+
* @param decimals - Number of decimal places for the token (default: 10 for DOT).
|
|
28
|
+
* @returns A decimal string representation (e.g. `"1.5"`, `"0.0001"`).
|
|
29
|
+
* @throws {RangeError} If `planck` is negative or `decimals` is invalid.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { formatPlanck } from "@polkadot-apps/utils";
|
|
34
|
+
*
|
|
35
|
+
* formatPlanck(10_000_000_000n); // "1.0" (10 decimals, DOT default)
|
|
36
|
+
* formatPlanck(15_000_000_000n); // "1.5"
|
|
37
|
+
* formatPlanck(1_000_000_000_000n, 12); // "1.0" (12 decimals, e.g. Polkadot relay)
|
|
38
|
+
* formatPlanck(0n); // "0.0"
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export function formatPlanck(planck, decimals = 10) {
|
|
42
|
+
validateDecimals(decimals);
|
|
43
|
+
if (planck < 0n) {
|
|
44
|
+
throw new RangeError(`planck must be non-negative, got ${planck}`);
|
|
45
|
+
}
|
|
46
|
+
if (decimals === 0) {
|
|
47
|
+
return `${planck}.0`;
|
|
48
|
+
}
|
|
49
|
+
const divisor = 10n ** BigInt(decimals);
|
|
50
|
+
const whole = planck / divisor;
|
|
51
|
+
const remainder = planck % divisor;
|
|
52
|
+
const fractionStr = remainder.toString().padStart(decimals, "0");
|
|
53
|
+
// Trim trailing zeros but keep at least 1 fractional digit
|
|
54
|
+
const trimmed = fractionStr.replace(/0+$/, "") || "0";
|
|
55
|
+
return `${whole}.${trimmed}`;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Parse a human-readable decimal token amount into its planck (smallest unit) representation.
|
|
59
|
+
*
|
|
60
|
+
* Converts a string like `"1.5"` into the corresponding bigint planck value
|
|
61
|
+
* (e.g. `15_000_000_000n` for 10 decimals). If the input has more fractional
|
|
62
|
+
* digits than `decimals`, excess digits are silently truncated with a warning log.
|
|
63
|
+
*
|
|
64
|
+
* @param amount - A non-negative decimal string (e.g. `"1.5"`, `"100"`, `"0.001"`).
|
|
65
|
+
* @param decimals - Number of decimal places for the token (default: 10 for DOT).
|
|
66
|
+
* @returns The planck value as a bigint.
|
|
67
|
+
* @throws {Error} If `amount` is empty, negative, or contains invalid characters.
|
|
68
|
+
* @throws {RangeError} If `decimals` is invalid.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { parseToPlanck } from "@polkadot-apps/utils";
|
|
73
|
+
*
|
|
74
|
+
* parseToPlanck("1.5"); // 15_000_000_000n (10 decimals, DOT default)
|
|
75
|
+
* parseToPlanck("100"); // 1_000_000_000_000n
|
|
76
|
+
* parseToPlanck("0.001", 12); // 1_000_000_000n (12 decimals)
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function parseToPlanck(amount, decimals = 10) {
|
|
80
|
+
validateDecimals(decimals);
|
|
81
|
+
if (amount === "") {
|
|
82
|
+
throw new Error("amount must not be empty");
|
|
83
|
+
}
|
|
84
|
+
if (amount.startsWith("-")) {
|
|
85
|
+
throw new RangeError(`amount must be non-negative, got "${amount}"`);
|
|
86
|
+
}
|
|
87
|
+
// Validate characters: only digits and at most one dot
|
|
88
|
+
if (!/^\d+\.?\d*$/.test(amount)) {
|
|
89
|
+
throw new Error(`amount contains invalid characters: "${amount}"`);
|
|
90
|
+
}
|
|
91
|
+
const parts = amount.split(".");
|
|
92
|
+
const wholePart = parts[0];
|
|
93
|
+
let fractionPart = parts[1] ?? "";
|
|
94
|
+
if (fractionPart.length > decimals) {
|
|
95
|
+
log.warn("Fractional digits exceed token decimals — truncating", {
|
|
96
|
+
amount,
|
|
97
|
+
decimals,
|
|
98
|
+
excessDigits: fractionPart.length - decimals,
|
|
99
|
+
});
|
|
100
|
+
fractionPart = fractionPart.slice(0, decimals);
|
|
101
|
+
}
|
|
102
|
+
const paddedFraction = fractionPart.padEnd(decimals, "0");
|
|
103
|
+
const whole = BigInt(wholePart) * 10n ** BigInt(decimals);
|
|
104
|
+
const fraction = decimals > 0 ? BigInt(paddedFraction) : 0n;
|
|
105
|
+
return whole + fraction;
|
|
106
|
+
}
|
|
107
|
+
if (import.meta.vitest) {
|
|
108
|
+
const { describe, test, expect } = import.meta.vitest;
|
|
109
|
+
describe("formatPlanck", () => {
|
|
110
|
+
test("formats 1 DOT with default 10 decimals", () => {
|
|
111
|
+
expect(formatPlanck(10000000000n)).toBe("1.0");
|
|
112
|
+
});
|
|
113
|
+
test("formats fractional amounts", () => {
|
|
114
|
+
expect(formatPlanck(15000000000n)).toBe("1.5");
|
|
115
|
+
expect(formatPlanck(12345678900n)).toBe("1.23456789");
|
|
116
|
+
});
|
|
117
|
+
test("formats zero", () => {
|
|
118
|
+
expect(formatPlanck(0n)).toBe("0.0");
|
|
119
|
+
});
|
|
120
|
+
test("formats sub-unit amounts", () => {
|
|
121
|
+
expect(formatPlanck(1n)).toBe("0.0000000001");
|
|
122
|
+
expect(formatPlanck(100n)).toBe("0.00000001");
|
|
123
|
+
});
|
|
124
|
+
test("formats large amounts", () => {
|
|
125
|
+
expect(formatPlanck(1000000000000000n)).toBe("100000.0");
|
|
126
|
+
});
|
|
127
|
+
test("trims trailing zeros but keeps at least one", () => {
|
|
128
|
+
expect(formatPlanck(20000000000n)).toBe("2.0");
|
|
129
|
+
expect(formatPlanck(10100000000n)).toBe("1.01");
|
|
130
|
+
});
|
|
131
|
+
test("handles custom decimals", () => {
|
|
132
|
+
expect(formatPlanck(1000000000000n, 12)).toBe("1.0");
|
|
133
|
+
expect(formatPlanck(1500000n, 6)).toBe("1.5");
|
|
134
|
+
});
|
|
135
|
+
test("handles zero decimals", () => {
|
|
136
|
+
expect(formatPlanck(42n, 0)).toBe("42.0");
|
|
137
|
+
});
|
|
138
|
+
test("throws on negative planck", () => {
|
|
139
|
+
expect(() => formatPlanck(-1n)).toThrow(RangeError);
|
|
140
|
+
});
|
|
141
|
+
test("throws on invalid decimals", () => {
|
|
142
|
+
expect(() => formatPlanck(0n, -1)).toThrow(RangeError);
|
|
143
|
+
expect(() => formatPlanck(0n, 1.5)).toThrow(RangeError);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe("parseToPlanck", () => {
|
|
147
|
+
test("parses whole number", () => {
|
|
148
|
+
expect(parseToPlanck("1")).toBe(10000000000n);
|
|
149
|
+
});
|
|
150
|
+
test("parses fractional amount", () => {
|
|
151
|
+
expect(parseToPlanck("1.5")).toBe(15000000000n);
|
|
152
|
+
});
|
|
153
|
+
test("parses zero", () => {
|
|
154
|
+
expect(parseToPlanck("0")).toBe(0n);
|
|
155
|
+
expect(parseToPlanck("0.0")).toBe(0n);
|
|
156
|
+
});
|
|
157
|
+
test("parses small fractions", () => {
|
|
158
|
+
expect(parseToPlanck("0.0000000001")).toBe(1n);
|
|
159
|
+
});
|
|
160
|
+
test("handles custom decimals", () => {
|
|
161
|
+
expect(parseToPlanck("1.0", 12)).toBe(1000000000000n);
|
|
162
|
+
expect(parseToPlanck("1.5", 6)).toBe(1500000n);
|
|
163
|
+
});
|
|
164
|
+
test("handles zero decimals", () => {
|
|
165
|
+
expect(parseToPlanck("42", 0)).toBe(42n);
|
|
166
|
+
});
|
|
167
|
+
test("truncates excess fractional digits", () => {
|
|
168
|
+
// 10 decimals, input has 12 fractional digits → truncate last 2
|
|
169
|
+
expect(parseToPlanck("1.123456789012")).toBe(11234567890n);
|
|
170
|
+
});
|
|
171
|
+
test("pads short fractional parts", () => {
|
|
172
|
+
expect(parseToPlanck("1.5")).toBe(15000000000n);
|
|
173
|
+
});
|
|
174
|
+
test("throws on empty string", () => {
|
|
175
|
+
expect(() => parseToPlanck("")).toThrow("must not be empty");
|
|
176
|
+
});
|
|
177
|
+
test("throws on negative amount", () => {
|
|
178
|
+
expect(() => parseToPlanck("-1")).toThrow(RangeError);
|
|
179
|
+
});
|
|
180
|
+
test("throws on invalid characters", () => {
|
|
181
|
+
expect(() => parseToPlanck("abc")).toThrow("invalid characters");
|
|
182
|
+
expect(() => parseToPlanck("1.2.3")).toThrow("invalid characters");
|
|
183
|
+
expect(() => parseToPlanck("1e10")).toThrow("invalid characters");
|
|
184
|
+
});
|
|
185
|
+
test("throws on invalid decimals", () => {
|
|
186
|
+
expect(() => parseToPlanck("1", -1)).toThrow(RangeError);
|
|
187
|
+
});
|
|
188
|
+
test("round-trips with formatPlanck", () => {
|
|
189
|
+
const original = 12345678901n;
|
|
190
|
+
const formatted = formatPlanck(original);
|
|
191
|
+
expect(parseToPlanck(formatted)).toBe(original);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@polkadot-apps/utils",
|
|
3
|
+
"description": "Encoding utilities and token formatting for the @polkadot-apps ecosystem",
|
|
4
|
+
"version": "0.2.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"source": "./src/index.ts",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@noble/hashes": "^2.0.1",
|
|
24
|
+
"@polkadot-apps/logger": "0.1.5"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"typescript": "^5.9.3"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc -p tsconfig.json",
|
|
31
|
+
"clean": "rm -rf dist"
|
|
32
|
+
}
|
|
33
|
+
}
|