@polkadot-apps/utils 0.2.1 → 0.3.0
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 +25 -0
- package/dist/hashing.d.ts +54 -0
- package/dist/hashing.js +149 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,23 @@ const text = utf8ToBytes("hello"); // Uint8Array [104, 101, 108, 108, 111]
|
|
|
23
23
|
const combined = concatBytes(header, payload);
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
### Hashing
|
|
27
|
+
|
|
28
|
+
Deterministic 32-byte hash functions used across the Polkadot ecosystem.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { blake2b256, sha256, keccak256, bytesToHex } from "@polkadot-apps/utils";
|
|
32
|
+
|
|
33
|
+
const hash = blake2b256(new TextEncoder().encode("hello"));
|
|
34
|
+
console.log(bytesToHex(hash)); // 64-char hex string
|
|
35
|
+
|
|
36
|
+
// SHA2-256 (bulletin-deploy default)
|
|
37
|
+
const sha = sha256(data);
|
|
38
|
+
|
|
39
|
+
// Keccak-256 (Ethereum compatibility)
|
|
40
|
+
const kek = keccak256(data);
|
|
41
|
+
```
|
|
42
|
+
|
|
26
43
|
### Token formatting
|
|
27
44
|
|
|
28
45
|
Convert between raw planck values (the smallest indivisible token unit on Substrate chains) and human-readable decimal strings.
|
|
@@ -56,6 +73,14 @@ parseToPlanck("1.0", 12); // 1_000_000_000_000n
|
|
|
56
73
|
| `utf8ToBytes` | `(str: string)` | `Uint8Array` |
|
|
57
74
|
| `concatBytes` | `(...arrays: Uint8Array[])` | `Uint8Array` |
|
|
58
75
|
|
|
76
|
+
### Hashing
|
|
77
|
+
|
|
78
|
+
| Function | Signature | Returns | Description |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| `blake2b256` | `(data: Uint8Array)` | `Uint8Array` (32 bytes) | BLAKE2b-256 — Polkadot default |
|
|
81
|
+
| `sha256` | `(data: Uint8Array)` | `Uint8Array` (32 bytes) | SHA2-256 — bulletin-deploy default |
|
|
82
|
+
| `keccak256` | `(data: Uint8Array)` | `Uint8Array` (32 bytes) | Keccak-256 — Ethereum compatibility |
|
|
83
|
+
|
|
59
84
|
### Token formatting
|
|
60
85
|
|
|
61
86
|
| Function | Signature | Returns |
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute a 32-byte BLAKE2b-256 hash.
|
|
3
|
+
*
|
|
4
|
+
* This is the default hash algorithm used by the Polkadot ecosystem and the
|
|
5
|
+
* Bulletin Chain. Deterministic: same input always produces the same output.
|
|
6
|
+
*
|
|
7
|
+
* @param data - Arbitrary bytes to hash.
|
|
8
|
+
* @returns 32-byte BLAKE2b-256 digest.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { blake2b256, bytesToHex } from "@polkadot-apps/utils";
|
|
13
|
+
*
|
|
14
|
+
* const hash = blake2b256(new TextEncoder().encode("hello"));
|
|
15
|
+
* console.log(bytesToHex(hash)); // 64-char hex string
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function blake2b256(data: Uint8Array): Uint8Array;
|
|
19
|
+
/**
|
|
20
|
+
* Compute a 32-byte SHA2-256 hash.
|
|
21
|
+
*
|
|
22
|
+
* Used by bulletin-deploy and supported by the Bulletin Chain as an
|
|
23
|
+
* alternative hashing algorithm.
|
|
24
|
+
*
|
|
25
|
+
* @param data - Arbitrary bytes to hash.
|
|
26
|
+
* @returns 32-byte SHA2-256 digest.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { sha256, bytesToHex } from "@polkadot-apps/utils";
|
|
31
|
+
*
|
|
32
|
+
* const hash = sha256(new TextEncoder().encode("hello"));
|
|
33
|
+
* console.log(bytesToHex(hash)); // 64-char hex string
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function sha256(data: Uint8Array): Uint8Array;
|
|
37
|
+
/**
|
|
38
|
+
* Compute a 32-byte Keccak-256 hash.
|
|
39
|
+
*
|
|
40
|
+
* Used for Ethereum-compatible operations (address derivation, EVM function
|
|
41
|
+
* selectors) and supported by the Bulletin Chain for cross-chain compatibility.
|
|
42
|
+
*
|
|
43
|
+
* @param data - Arbitrary bytes to hash.
|
|
44
|
+
* @returns 32-byte Keccak-256 digest.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { keccak256, bytesToHex } from "@polkadot-apps/utils";
|
|
49
|
+
*
|
|
50
|
+
* const hash = keccak256(new TextEncoder().encode("hello"));
|
|
51
|
+
* console.log(bytesToHex(hash)); // 64-char hex string
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function keccak256(data: Uint8Array): Uint8Array;
|
package/dist/hashing.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { blake2b } from "@noble/hashes/blake2.js";
|
|
2
|
+
import { sha256 as _sha256 } from "@noble/hashes/sha2.js";
|
|
3
|
+
import { bytesToHex as _bytesToHex } from "@noble/hashes/utils.js";
|
|
4
|
+
import { keccak_256 } from "@noble/hashes/sha3.js";
|
|
5
|
+
/**
|
|
6
|
+
* Compute a 32-byte BLAKE2b-256 hash.
|
|
7
|
+
*
|
|
8
|
+
* This is the default hash algorithm used by the Polkadot ecosystem and the
|
|
9
|
+
* Bulletin Chain. Deterministic: same input always produces the same output.
|
|
10
|
+
*
|
|
11
|
+
* @param data - Arbitrary bytes to hash.
|
|
12
|
+
* @returns 32-byte BLAKE2b-256 digest.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { blake2b256, bytesToHex } from "@polkadot-apps/utils";
|
|
17
|
+
*
|
|
18
|
+
* const hash = blake2b256(new TextEncoder().encode("hello"));
|
|
19
|
+
* console.log(bytesToHex(hash)); // 64-char hex string
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function blake2b256(data) {
|
|
23
|
+
return blake2b(data, { dkLen: 32 });
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Compute a 32-byte SHA2-256 hash.
|
|
27
|
+
*
|
|
28
|
+
* Used by bulletin-deploy and supported by the Bulletin Chain as an
|
|
29
|
+
* alternative hashing algorithm.
|
|
30
|
+
*
|
|
31
|
+
* @param data - Arbitrary bytes to hash.
|
|
32
|
+
* @returns 32-byte SHA2-256 digest.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { sha256, bytesToHex } from "@polkadot-apps/utils";
|
|
37
|
+
*
|
|
38
|
+
* const hash = sha256(new TextEncoder().encode("hello"));
|
|
39
|
+
* console.log(bytesToHex(hash)); // 64-char hex string
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function sha256(data) {
|
|
43
|
+
return _sha256(data);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compute a 32-byte Keccak-256 hash.
|
|
47
|
+
*
|
|
48
|
+
* Used for Ethereum-compatible operations (address derivation, EVM function
|
|
49
|
+
* selectors) and supported by the Bulletin Chain for cross-chain compatibility.
|
|
50
|
+
*
|
|
51
|
+
* @param data - Arbitrary bytes to hash.
|
|
52
|
+
* @returns 32-byte Keccak-256 digest.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { keccak256, bytesToHex } from "@polkadot-apps/utils";
|
|
57
|
+
*
|
|
58
|
+
* const hash = keccak256(new TextEncoder().encode("hello"));
|
|
59
|
+
* console.log(bytesToHex(hash)); // 64-char hex string
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function keccak256(data) {
|
|
63
|
+
return keccak_256(data);
|
|
64
|
+
}
|
|
65
|
+
if (import.meta.vitest) {
|
|
66
|
+
const { describe, test, expect } = import.meta.vitest;
|
|
67
|
+
describe("blake2b256", () => {
|
|
68
|
+
test("produces a 32-byte hash", () => {
|
|
69
|
+
const hash = blake2b256(new TextEncoder().encode("hello"));
|
|
70
|
+
expect(hash).toBeInstanceOf(Uint8Array);
|
|
71
|
+
expect(hash.length).toBe(32);
|
|
72
|
+
});
|
|
73
|
+
test("deterministic — same input, same output", () => {
|
|
74
|
+
const data = new TextEncoder().encode("test");
|
|
75
|
+
expect(blake2b256(data)).toEqual(blake2b256(data));
|
|
76
|
+
});
|
|
77
|
+
test("different inputs produce different hashes", () => {
|
|
78
|
+
const a = blake2b256(new Uint8Array([1]));
|
|
79
|
+
const b = blake2b256(new Uint8Array([2]));
|
|
80
|
+
expect(a).not.toEqual(b);
|
|
81
|
+
});
|
|
82
|
+
test("empty input produces valid 32-byte hash", () => {
|
|
83
|
+
const hash = blake2b256(new Uint8Array(0));
|
|
84
|
+
expect(hash.length).toBe(32);
|
|
85
|
+
});
|
|
86
|
+
test("matches direct @noble/hashes import", () => {
|
|
87
|
+
const data = new TextEncoder().encode("wrapper transparency check");
|
|
88
|
+
const direct = blake2b(data, { dkLen: 32 });
|
|
89
|
+
expect(blake2b256(data)).toEqual(direct);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe("sha256", () => {
|
|
93
|
+
test("produces a 32-byte hash", () => {
|
|
94
|
+
const hash = sha256(new TextEncoder().encode("hello"));
|
|
95
|
+
expect(hash).toBeInstanceOf(Uint8Array);
|
|
96
|
+
expect(hash.length).toBe(32);
|
|
97
|
+
});
|
|
98
|
+
test("deterministic — same input, same output", () => {
|
|
99
|
+
const data = new TextEncoder().encode("test");
|
|
100
|
+
expect(sha256(data)).toEqual(sha256(data));
|
|
101
|
+
});
|
|
102
|
+
test("different inputs produce different hashes", () => {
|
|
103
|
+
const a = sha256(new Uint8Array([1]));
|
|
104
|
+
const b = sha256(new Uint8Array([2]));
|
|
105
|
+
expect(a).not.toEqual(b);
|
|
106
|
+
});
|
|
107
|
+
test("empty input produces valid 32-byte hash", () => {
|
|
108
|
+
const hash = sha256(new Uint8Array(0));
|
|
109
|
+
expect(hash.length).toBe(32);
|
|
110
|
+
});
|
|
111
|
+
test("differs from blake2b256 for same input", () => {
|
|
112
|
+
const data = new TextEncoder().encode("cross-check");
|
|
113
|
+
expect(sha256(data)).not.toEqual(blake2b256(data));
|
|
114
|
+
});
|
|
115
|
+
test("matches known SHA-256 test vector", () => {
|
|
116
|
+
const hash = sha256(new TextEncoder().encode("hello"));
|
|
117
|
+
expect(_bytesToHex(hash)).toBe("2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("keccak256", () => {
|
|
121
|
+
test("produces a 32-byte hash", () => {
|
|
122
|
+
const hash = keccak256(new TextEncoder().encode("hello"));
|
|
123
|
+
expect(hash).toBeInstanceOf(Uint8Array);
|
|
124
|
+
expect(hash.length).toBe(32);
|
|
125
|
+
});
|
|
126
|
+
test("deterministic — same input, same output", () => {
|
|
127
|
+
const data = new TextEncoder().encode("test");
|
|
128
|
+
expect(keccak256(data)).toEqual(keccak256(data));
|
|
129
|
+
});
|
|
130
|
+
test("different inputs produce different hashes", () => {
|
|
131
|
+
const a = keccak256(new Uint8Array([1]));
|
|
132
|
+
const b = keccak256(new Uint8Array([2]));
|
|
133
|
+
expect(a).not.toEqual(b);
|
|
134
|
+
});
|
|
135
|
+
test("empty input produces valid 32-byte hash", () => {
|
|
136
|
+
const hash = keccak256(new Uint8Array(0));
|
|
137
|
+
expect(hash.length).toBe(32);
|
|
138
|
+
});
|
|
139
|
+
test("differs from sha256 and blake2b256 for same input", () => {
|
|
140
|
+
const data = new TextEncoder().encode("cross-check");
|
|
141
|
+
expect(keccak256(data)).not.toEqual(sha256(data));
|
|
142
|
+
expect(keccak256(data)).not.toEqual(blake2b256(data));
|
|
143
|
+
});
|
|
144
|
+
test("matches known Keccak-256 test vector", () => {
|
|
145
|
+
const hash = keccak256(new TextEncoder().encode("hello"));
|
|
146
|
+
expect(_bytesToHex(hash)).toBe("1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8");
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @polkadot-apps/utils — Encoding
|
|
2
|
+
* @polkadot-apps/utils — Encoding, hashing, and token formatting for the Polkadot app ecosystem.
|
|
3
3
|
*
|
|
4
4
|
* Provides general-purpose byte encoding/decoding (`bytesToHex`, `hexToBytes`, `utf8ToBytes`,
|
|
5
|
-
* `concatBytes`)
|
|
5
|
+
* `concatBytes`), 32-byte hash functions (`blake2b256`, `sha256`, `keccak256`),
|
|
6
|
+
* and Substrate token formatting (`formatPlanck`, `parseToPlanck`).
|
|
6
7
|
* All functions are synchronous and framework-agnostic.
|
|
7
8
|
*
|
|
8
9
|
* @packageDocumentation
|
|
9
10
|
*/
|
|
10
11
|
export * from "./encoding.js";
|
|
12
|
+
export * from "./hashing.js";
|
|
11
13
|
export * from "./planck.js";
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @polkadot-apps/utils — Encoding
|
|
2
|
+
* @polkadot-apps/utils — Encoding, hashing, and token formatting for the Polkadot app ecosystem.
|
|
3
3
|
*
|
|
4
4
|
* Provides general-purpose byte encoding/decoding (`bytesToHex`, `hexToBytes`, `utf8ToBytes`,
|
|
5
|
-
* `concatBytes`)
|
|
5
|
+
* `concatBytes`), 32-byte hash functions (`blake2b256`, `sha256`, `keccak256`),
|
|
6
|
+
* and Substrate token formatting (`formatPlanck`, `parseToPlanck`).
|
|
6
7
|
* All functions are synchronous and framework-agnostic.
|
|
7
8
|
*
|
|
8
9
|
* @packageDocumentation
|
|
9
10
|
*/
|
|
10
11
|
export * from "./encoding.js";
|
|
12
|
+
export * from "./hashing.js";
|
|
11
13
|
export * from "./planck.js";
|
package/package.json
CHANGED