@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 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;
@@ -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 utilities and token formatting for the Polkadot app ecosystem.
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`) and Substrate token formatting (`formatPlanck`, `parseToPlanck`).
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 utilities and token formatting for the Polkadot app ecosystem.
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`) and Substrate token formatting (`formatPlanck`, `parseToPlanck`).
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@polkadot-apps/utils",
3
3
  "description": "Encoding utilities and token formatting for the @polkadot-apps ecosystem",
4
- "version": "0.2.1",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",