shell-sdk 0.6.0 → 0.7.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/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.1] — 2026-05-06
4
+
5
+ ### Added
6
+ - Typed Shell RPC reward metadata for address-history and transaction-summary
7
+ responses, including block gas rewards, STARK rewards, reward layers,
8
+ source hashes, and compression accounting fields.
9
+
10
+ ### Changed
11
+ - Preserve pq1-only compatibility from `0.7.0` while aligning the SDK type
12
+ surface with `shell-chain v0.21.1`.
13
+
14
+ ## [0.7.0] — 2026-04-30 ⚠️ BREAKING
15
+
16
+ ### Breaking Changes — F-PQ1-ONLY (pq1 bech32m addresses everywhere)
17
+
18
+ This is a **breaking release**. All `0x` hex address support has been removed.
19
+
20
+ #### Removed
21
+ - `hexAddress()` / `hexAddressFromPubkey()` exports deleted — use `pq1Address()` instead.
22
+ - `normalizePqAddress()` no longer accepts `0x...` hex strings — only `pq1...` bech32m.
23
+ - Keystore `address` field: `encryptKeystore()` now always emits `pq1...` bech32m (was `0x...` hex).
24
+ - `decryptKeystore()` rejects keystores with `0x` address fields (use `shell-node key migrate` first).
25
+
26
+ #### Added
27
+ - `pq1Address(pubkey, sigType)` — canonical address derivation returning `pq1...` bech32m string.
28
+ - SK-only keystore format: `encryptKeystore` stores only the secret key in ciphertext (no pk concatenation), matching `shell-node key generate` output for full cross-language compatibility.
29
+ - Full cross-format compatibility: SDK keystores are now byte-for-byte compatible with Rust CLI keystores.
30
+
31
+ #### Updated
32
+ - All SDK test fixtures regenerated with `pq1` addresses.
33
+ - `SIGNATURE_TYPE_IDS.MlDsa65 = 1` (was incorrectly aliased to `0` in v0.6.x).
34
+ - ML-DSA-65 (FIPS 204) via `@noble/post-quantum` — real implementation, not a Dilithium3 alias.
35
+
36
+ ### Migration Guide
37
+ ```js
38
+ // Before (0.6.x)
39
+ import { hexAddress } from 'shell-sdk';
40
+ const addr = hexAddress(pubkey, sigType); // "0x..."
41
+
42
+ // After (0.7.0)
43
+ import { pq1Address } from 'shell-sdk';
44
+ const addr = pq1Address(pubkey, sigType); // "pq1..."
45
+ ```
46
+
47
+ For existing keystores with `0x` addresses: run `shell-node key migrate <keystore.json>` to upgrade to pq1 format.
48
+
49
+ ### Compatibility
50
+ - Requires `shell-chain v0.21.0+` (pq1-only RPC).
51
+ - Not backwards-compatible with SDK `0.6.x` address handling.
52
+
53
+ ## [0.6.0] — 2026-04-27
54
+
55
+ ### Added — ML-DSA-65 (FIPS 204) + Keystore SK-only format
56
+
57
+ #### Crypto (`keystore.ts`, `address.ts`)
58
+ - **`MlDsa65Adapter`**: real FIPS 204 ML-DSA-65 implementation via `@noble/post-quantum`.
59
+ - **`SIGNATURE_TYPE_IDS.MlDsa65 = 1`**: ML-DSA-65 is now a distinct algorithm (was aliased to Dilithium3=0).
60
+ - **SK-only keystore**: `encryptKeystore` stores only secret key bytes in ciphertext, matching `shell-node` CLI format. Cross-language compatible.
61
+ - **`decryptCliKeystore`** helper removed — standard `decryptKeystore` now handles CLI keystores.
62
+
63
+ #### Compatibility
64
+ - Fully cross-language compatible: Rust CLI keystores decryptable by SDK and vice versa.
65
+ - `shell-chain v0.20.0+` required for ML-DSA-65 transaction signing.
66
+
3
67
  ## [0.5.0] — 2026-04-26
4
68
 
5
69
  ### Added — AA Phase 2 (matches `shell-chain v0.19.0`)
package/README.md CHANGED
@@ -40,6 +40,7 @@
40
40
  - **Native account abstraction** — key rotation and custom validation code via system contracts
41
41
  - **viem integration** — standard Ethereum JSON-RPC methods via a typed `PublicClient`
42
42
  - **Shell-specific RPC** — `shell_getPqPubkey`, `shell_sendTransaction`, `shell_getTransactionsByAddress`, `shell_getNodeInfo`, `shell_getWitness`
43
+ - **Reward-aware history types** — block/address transaction summaries expose readable `shellType`, `rewardKind`, and STARK reward metadata (`rewardLayer`, `rewardSourceHash`, `originalSize`, `compressedSize`)
43
44
  - **Node introspection** — `getNodeInfo()` returns version, block height, peer count, and storage profile; `getWitness()` fetches raw PQ signatures for any block
44
45
  - **Encrypted keystore** — argon2id KDF + xchacha20-poly1305 cipher; compatible with the Shell CLI
45
46
 
@@ -78,7 +79,7 @@ const signer = new ShellSigner("MlDsa65", adapter);
78
79
  const from = signer.getAddress(); // pq1…
79
80
 
80
81
  const provider = createShellProvider();
81
- const nonce = await provider.client.getTransactionCount({ address: signer.getHexAddress() });
82
+ const nonce = await provider.client.getTransactionCount({ address: from });
82
83
 
83
84
  const tx = buildTransferTransaction({ chainId: 424242, nonce, to: "pq1recipient…", value: parseEther("1") });
84
85
  const txHash = hashTransaction(tx);
@@ -107,7 +108,7 @@ blake3( version(1) || algo_id(1) || public_key )[0..20]
107
108
 
108
109
  Algorithm IDs: `Dilithium3=0`, `MlDsa65=1`, `SphincsSha2256f=2`.
109
110
 
110
- Internally the chain also recognises the hex representation (`0x…`) of the same 20 bytes, so both forms are interchangeable in SDK APIs.
111
+ Shell Chain v0.21.0+ accepts `pq1…` addresses at user-facing RPC and SDK boundaries. Legacy `0x…` address inputs are rejected.
111
112
 
112
113
  ### Native account abstraction (AA)
113
114
 
@@ -147,7 +148,9 @@ Defined in `src/types.ts`. All types are re-exported from the package root.
147
148
  | `ShellSignature` | `{ sig_type, data: number[] }` |
148
149
  | `SignedShellTransaction` | Complete signed transaction ready to broadcast |
149
150
  | `ShellAccessListItem` | EIP-2930 access list entry |
150
- | `ShellTxByAddressPage` | Paginated address history response |
151
+ | `ShellKnownRpcTxType` | Literal union of known Shell RPC transaction kinds |
152
+ | `ShellRpcTransactionSummary` | Lightweight transaction summary with Shell reward metadata |
153
+ | `ShellTxByAddressPage` | Paginated address history response with effective `fromBlock`/`toBlock` range |
151
154
  | `ShellKdfParams` | argon2id parameters inside a keystore |
152
155
  | `ShellCipherParams` | xchacha20-poly1305 nonce inside a keystore |
153
156
  | `ShellEncryptedKey` | Full encrypted keystore file structure |
@@ -173,10 +176,7 @@ Defined in `src/types.ts`. All types are re-exported from the package root.
173
176
  | `bytesToPqAddress` | `(bytes: Uint8Array, version?) → string` | Encode 20 raw bytes as a `pq1…` bech32m address |
174
177
  | `pqAddressToBytes` | `(address: string) → Uint8Array` | Decode a `pq1…` address to its 20 raw bytes |
175
178
  | `pqAddressVersion` | `(address: string) → number` | Extract the version byte from a `pq1…` address |
176
- | `hexAddressToBytes` | `(address: string) → Uint8Array` | Parse a `0x…` address to 20 bytes |
177
- | `bytesToHexAddress` | `(bytes: Uint8Array) → HexString` | Encode 20 bytes as a `0x…` hex address |
178
- | `normalizePqAddress` | `(address: string) → string` | Accept either pq1 or 0x form, always return pq1 |
179
- | `normalizeHexAddress` | `(address: string) → HexString` | Accept either pq1 or 0x form, always return 0x |
179
+ | `normalizePqAddress` | `(address: string) → string` | Validate and return a `pq1…` address |
180
180
  | `derivePqAddressFromPublicKey` | `(pk, algoId, version?) → string` | Derive pq1 address from a raw public key |
181
181
  | `isPqAddress` | `(address: string) → boolean` | Return `true` if the string is a valid pq1 address |
182
182
 
@@ -194,9 +194,9 @@ const address = derivePqAddressFromPublicKey(publicKey, 1 /* MlDsa65 */);
194
194
 
195
195
  console.log(isPqAddress(address)); // true
196
196
 
197
- // Round-trip normalisation
198
- normalizePqAddress("0xabcdef…"); // → "pq1…"
197
+ // Validation / normalisation
199
198
  normalizePqAddress("pq1qx3f…"); // → "pq1qx3f…" (unchanged)
199
+ normalizePqAddress("0xabcdef…"); // throws: expected a pq1… bech32m address
200
200
  ```
201
201
 
202
202
  ---
@@ -236,8 +236,8 @@ import { shellDevnet } from "shell-sdk/provider";
236
236
  | `.rpcHttpUrl` | HTTP RPC URL in use |
237
237
  | `getPqPubkey(address)` | `shell_getPqPubkey` → hex public key or `null` |
238
238
  | `sendTransaction(signed)` | `shell_sendTransaction` → tx hash string |
239
- | `getTransactionsByAddress(address, opts)` | `shell_getTransactionsByAddress` with optional `fromBlock/toBlock/page/limit` |
240
- | `getBlockReceipts(block)` | `eth_getBlockReceipts` → array of receipts |
239
+ | `getTransactionsByAddress(address, opts)` | `shell_getTransactionsByAddress` with optional `fromBlock/toBlock/page/limit`; pin `toBlock` from page 0 for stable full-history pagination |
240
+ | `getBlockReceipts(block)` | `eth_getBlockReceipts` → `ShellRpcReceipt[]` |
241
241
  | `getNodeInfo()` | `shell_getNodeInfo` → `ShellNodeInfo` (version, block height, peer count, storage profile) |
242
242
  | `getWitness(blockNumberOrHash)` | `shell_getWitness` → `ShellWitnessBundle` or `null` if pruned |
243
243
  | `getStorageProfile()` | Convenience wrapper around `getNodeInfo()` → `ShellStorageProfile \| undefined` |
@@ -258,6 +258,11 @@ const pubkeyHex = await provider.getPqPubkey("pq1…");
258
258
  const txHash = await provider.sendTransaction(signedTx);
259
259
 
260
260
  const history = await provider.getTransactionsByAddress("pq1…", { page: 0, limit: 20 });
261
+ const older = await provider.getTransactionsByAddress("pq1…", {
262
+ page: 1,
263
+ limit: 20,
264
+ toBlock: history.toBlock ?? history.to_block,
265
+ });
261
266
  ```
262
267
 
263
268
  **Custom endpoint:**
@@ -334,7 +339,6 @@ const signer = new ShellSigner("MlDsa65", MlDsa65Adapter.generate());
334
339
  | `algorithmId` | Numeric algorithm ID (`0`, `1`, or `2`) |
335
340
  | `getPublicKey()` | Raw public key bytes |
336
341
  | `getAddress()` | `pq1…` bech32m address |
337
- | `getHexAddress()` | `0x…` hex address |
338
342
  | `sign(message)` | Sign an arbitrary byte message → signature bytes |
339
343
  | `buildSignedTransaction(options)` | Sign `txHash` and assemble a `SignedShellTransaction` |
340
344
 
@@ -568,7 +572,6 @@ import { buildTransferTransaction, hashTransaction } from "shell-sdk/transaction
568
572
  const adapter = MlDsa65Adapter.generate();
569
573
  const signer = new ShellSigner("MlDsa65", adapter);
570
574
  const from = signer.getAddress(); // pq1…
571
- const fromHex = signer.getHexAddress(); // 0x…
572
575
 
573
576
  console.log("Address:", from);
574
577
 
@@ -576,7 +579,7 @@ console.log("Address:", from);
576
579
  const provider = createShellProvider(); // defaults to http://127.0.0.1:8545
577
580
 
578
581
  // 3. Get current nonce
579
- const nonce = await provider.client.getTransactionCount({ address: fromHex });
582
+ const nonce = await provider.client.getTransactionCount({ address: from });
580
583
 
581
584
  // 4. Build the transaction
582
585
  const tx = buildTransferTransaction({
@@ -614,7 +617,7 @@ import { parseEther } from "viem";
614
617
 
615
618
  const signer = await decryptKeystore(readFileSync("./key.json", "utf8"), process.env.PASSPHRASE!);
616
619
  const provider = createShellProvider();
617
- const nonce = await provider.client.getTransactionCount({ address: signer.getHexAddress() });
620
+ const nonce = await provider.client.getTransactionCount({ address: signer.getAddress() });
618
621
 
619
622
  const tx = buildTransferTransaction({
620
623
  chainId: 424242,
@@ -639,13 +642,13 @@ This is the recommended shape for a Chrome extension background worker: keep the
639
642
  import { createShellProvider, buildTransferTransaction, hashTransaction } from "shell-sdk";
640
643
 
641
644
  async function submitTransfer({ signer, to, value, rpcHttpUrl }: {
642
- signer: { getHexAddress(): `0x${string}`; buildSignedTransaction(args: { tx: unknown; txHash: Uint8Array; includePublicKey?: boolean }): Promise<unknown> };
645
+ signer: { getAddress(): string; buildSignedTransaction(args: { tx: unknown; txHash: Uint8Array; includePublicKey?: boolean }): Promise<unknown> };
643
646
  to: string;
644
647
  value: bigint;
645
648
  rpcHttpUrl: string;
646
649
  }) {
647
650
  const provider = createShellProvider({ rpcHttpUrl });
648
- const nonce = await provider.client.getTransactionCount({ address: signer.getHexAddress() });
651
+ const nonce = await provider.client.getTransactionCount({ address: signer.getAddress() });
649
652
 
650
653
  const tx = buildTransferTransaction({
651
654
  chainId: 424242,
@@ -671,7 +674,7 @@ const provider = createShellProvider({
671
674
  rpcHttpUrl: "https://rpc.testnet.shell.network",
672
675
  });
673
676
 
674
- const account = normalizePqAddress("0x1234...abcd");
677
+ const account = normalizePqAddress("pq1qx3f...");
675
678
  const history = await provider.getTransactionsByAddress(account, { page: 1, limit: 10 });
676
679
 
677
680
  console.log("recent txs:", history.transactions);
@@ -699,7 +702,7 @@ const currentSigner = await decryptKeystore(readFileSync("old-key.json", "utf8")
699
702
  const newAdapter = MlDsa65Adapter.generate();
700
703
  const newSigner = new ShellSigner("MlDsa65", newAdapter);
701
704
 
702
- const nonce = await provider.client.getTransactionCount({ address: currentSigner.getHexAddress() });
705
+ const nonce = await provider.client.getTransactionCount({ address: currentSigner.getAddress() });
703
706
 
704
707
  // Build the rotateKey system transaction
705
708
  const tx = buildRotateKeyTransaction({
@@ -728,7 +731,6 @@ All SDK functions throw standard `Error` instances. Common error messages:
728
731
  |---|---|
729
732
  | `expected 20 address bytes, got N` | Wrong-length bytes passed to address helpers |
730
733
  | `expected pq address prefix, got X` | bech32m prefix is not `pq` |
731
- | `invalid hex address` | String does not start with `0x` |
732
734
  | `invalid bech32m address` | String is not a valid bech32m address |
733
735
  | `unsupported key type: X` | Keystore `key_type` not recognised |
734
736
  | `unsupported kdf: X` | Only `argon2id` is supported |
@@ -4,12 +4,10 @@
4
4
  * `@noble/post-quantum` provides ML-DSA-65 and SLH-DSA-SHA2-256f via
5
5
  * WebAssembly-accelerated pure-JS implementations.
6
6
  *
7
- * **Dilithium3 compatibility note**: `pqcrypto-dilithium` v0.5 (used by
8
- * shell-chain) implements ML-DSA-65 (FIPS 204) under the `dilithium3` name.
9
- * `@noble/post-quantum` `ml_dsa65` produces byte-identical keys and
10
- * signatures (pk=1952, sk=4032, sig=3309), so `MlDsa65Adapter` is fully
11
- * wire-compatible with the chain's Dilithium3 verifier. Both `"Dilithium3"`
12
- * and `"MlDsa65"` algorithm names route to the same adapter.
7
+ * **Algorithm distinction**: `"Dilithium3"` (type_id=0) and `"ML-DSA-65"` /
8
+ * `"MlDsa65"` (type_id=1) are now separate algorithms on chain with distinct
9
+ * address derivation. `MlDsa65Adapter` and `DilithiumAdapter` both use the
10
+ * same underlying `ml_dsa65` crypto (FIPS 204), but produce different addresses.
13
11
  *
14
12
  * @module adapters
15
13
  */
package/dist/adapters.js CHANGED
@@ -4,12 +4,10 @@
4
4
  * `@noble/post-quantum` provides ML-DSA-65 and SLH-DSA-SHA2-256f via
5
5
  * WebAssembly-accelerated pure-JS implementations.
6
6
  *
7
- * **Dilithium3 compatibility note**: `pqcrypto-dilithium` v0.5 (used by
8
- * shell-chain) implements ML-DSA-65 (FIPS 204) under the `dilithium3` name.
9
- * `@noble/post-quantum` `ml_dsa65` produces byte-identical keys and
10
- * signatures (pk=1952, sk=4032, sig=3309), so `MlDsa65Adapter` is fully
11
- * wire-compatible with the chain's Dilithium3 verifier. Both `"Dilithium3"`
12
- * and `"MlDsa65"` algorithm names route to the same adapter.
7
+ * **Algorithm distinction**: `"Dilithium3"` (type_id=0) and `"ML-DSA-65"` /
8
+ * `"MlDsa65"` (type_id=1) are now separate algorithms on chain with distinct
9
+ * address derivation. `MlDsa65Adapter` and `DilithiumAdapter` both use the
10
+ * same underlying `ml_dsa65` crypto (FIPS 204), but produce different addresses.
13
11
  *
14
12
  * @module adapters
15
13
  */
package/dist/address.d.ts CHANGED
@@ -4,7 +4,6 @@ export declare const PQ_ADDRESS_HRP = "pq";
4
4
  export declare const PQ_ADDRESS_LENGTH = 20;
5
5
  /** Version byte for V1 Shell addresses (`0x01`). */
6
6
  export declare const PQ_ADDRESS_VERSION_V1 = 1;
7
- type HexAddress = `0x${string}`;
8
7
  /**
9
8
  * Encode 20 raw address bytes as a `pq1…` bech32m address.
10
9
  *
@@ -45,40 +44,15 @@ export declare function pqAddressToBytes(address: string): Uint8Array;
45
44
  */
46
45
  export declare function pqAddressVersion(address: string): number;
47
46
  /**
48
- * Parse a `0x…` hex address string into its raw 20 bytes.
47
+ * Normalise an address: validates it is a `pq1…` bech32m address and returns it.
49
48
  *
50
- * @param address - A `0x`-prefixed 40-character hex address.
51
- * @returns The 20-byte address payload.
52
- * @throws {Error} If the string does not start with `"0x"` or is not exactly 20 bytes.
53
- */
54
- export declare function hexAddressToBytes(address: string): Uint8Array;
55
- /**
56
- * Encode 20 raw address bytes as a `0x…` hex address.
57
- *
58
- * @param bytes - Exactly 20 address bytes.
59
- * @returns A `0x`-prefixed 40-character hex string.
60
- * @throws {Error} If `bytes.length !== 20`.
61
- */
62
- export declare function bytesToHexAddress(bytes: Uint8Array): HexAddress;
63
- /**
64
- * Normalise an address to `pq1…` bech32m form.
49
+ * Hex (`0x…`) addresses are no longer accepted. Use `pq1…` format everywhere.
65
50
  *
66
- * Accepts either a `pq1…` or `0x…` address and always returns the canonical
67
- * bech32m form.
68
- *
69
- * @param address - A `pq1…` or `0x…` address.
70
- * @returns The `pq1…` bech32m address.
51
+ * @param address - A `pq1…` bech32m address.
52
+ * @returns The same `pq1…` address (validated).
53
+ * @throws {Error} If the address is not a valid `pq1…` bech32m address.
71
54
  */
72
55
  export declare function normalizePqAddress(address: string): string;
73
- /**
74
- * Normalise an address to `0x…` hex form.
75
- *
76
- * Accepts either a `pq1…` or `0x…` address and always returns the hex form.
77
- *
78
- * @param address - A `pq1…` or `0x…` address.
79
- * @returns The `0x`-prefixed hex address.
80
- */
81
- export declare function normalizeHexAddress(address: string): HexAddress;
82
56
  /**
83
57
  * Derive a `pq1…` address from a raw post-quantum public key.
84
58
  *
@@ -116,4 +90,3 @@ export declare function derivePqAddressFromPublicKey(publicKey: Uint8Array, algo
116
90
  * ```
117
91
  */
118
92
  export declare function isPqAddress(address: string): boolean;
119
- export {};
package/dist/address.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * PQ address utilities for Shell Chain.
3
3
  *
4
- * Shell Chain uses **bech32m**-encoded addresses (prefix `"pq"`) instead of
5
- * Ethereum's checksummed hex format. Each address encodes a version byte and
6
- * 20 address bytes derived from the account's post-quantum public key:
4
+ * Shell Chain uses **bech32m**-encoded addresses (prefix `"pq"`) exclusively.
5
+ * Each address encodes a version byte and 20 address bytes derived from the
6
+ * account's post-quantum public key:
7
7
  *
8
8
  * ```
9
9
  * address_bytes = blake3(version || algo_id || public_key)[0..20]
@@ -12,14 +12,10 @@
12
12
  *
13
13
  * Algorithm IDs: Dilithium3=0, MlDsa65=1, SphincsSha2256f=2.
14
14
  *
15
- * Both pq1… and 0x… representations refer to the same underlying 20 bytes;
16
- * the SDK accepts either form in most places via the `AddressLike` type.
17
- *
18
15
  * @module address
19
16
  */
20
17
  import { blake3 } from "@noble/hashes/blake3";
21
18
  import { bech32m } from "@scure/base";
22
- import { bytesToHex, hexToBytes } from "viem";
23
19
  /** Human-readable part (HRP) used in Shell bech32m addresses. */
24
20
  export const PQ_ADDRESS_HRP = "pq";
25
21
  /** Number of raw address bytes (excluding the version byte). */
@@ -31,11 +27,6 @@ function assertBech32Address(value) {
31
27
  throw new Error("invalid bech32m address");
32
28
  }
33
29
  }
34
- function assertHexAddress(value) {
35
- if (!value.startsWith("0x")) {
36
- throw new Error("invalid hex address");
37
- }
38
- }
39
30
  /**
40
31
  * Encode 20 raw address bytes as a `pq1…` bech32m address.
41
32
  *
@@ -106,61 +97,18 @@ export function pqAddressVersion(address) {
106
97
  return bytes[0];
107
98
  }
108
99
  /**
109
- * Parse a `0x…` hex address string into its raw 20 bytes.
100
+ * Normalise an address: validates it is a `pq1…` bech32m address and returns it.
110
101
  *
111
- * @param address - A `0x`-prefixed 40-character hex address.
112
- * @returns The 20-byte address payload.
113
- * @throws {Error} If the string does not start with `"0x"` or is not exactly 20 bytes.
114
- */
115
- export function hexAddressToBytes(address) {
116
- assertHexAddress(address);
117
- const bytes = hexToBytes(address);
118
- if (bytes.length !== PQ_ADDRESS_LENGTH) {
119
- throw new Error(`expected ${PQ_ADDRESS_LENGTH} address bytes, got ${bytes.length}`);
120
- }
121
- return bytes;
122
- }
123
- /**
124
- * Encode 20 raw address bytes as a `0x…` hex address.
102
+ * Hex (`0x…`) addresses are no longer accepted. Use `pq1…` format everywhere.
125
103
  *
126
- * @param bytes - Exactly 20 address bytes.
127
- * @returns A `0x`-prefixed 40-character hex string.
128
- * @throws {Error} If `bytes.length !== 20`.
129
- */
130
- export function bytesToHexAddress(bytes) {
131
- if (bytes.length !== PQ_ADDRESS_LENGTH) {
132
- throw new Error(`expected ${PQ_ADDRESS_LENGTH} address bytes, got ${bytes.length}`);
133
- }
134
- return bytesToHex(bytes);
135
- }
136
- /**
137
- * Normalise an address to `pq1…` bech32m form.
138
- *
139
- * Accepts either a `pq1…` or `0x…` address and always returns the canonical
140
- * bech32m form.
141
- *
142
- * @param address - A `pq1…` or `0x…` address.
143
- * @returns The `pq1…` bech32m address.
104
+ * @param address - A `pq1…` bech32m address.
105
+ * @returns The same `pq1…` address (validated).
106
+ * @throws {Error} If the address is not a valid `pq1…` bech32m address.
144
107
  */
145
108
  export function normalizePqAddress(address) {
146
- if (isPqAddress(address)) {
147
- return address;
148
- }
149
- return bytesToPqAddress(hexAddressToBytes(address));
150
- }
151
- /**
152
- * Normalise an address to `0x…` hex form.
153
- *
154
- * Accepts either a `pq1…` or `0x…` address and always returns the hex form.
155
- *
156
- * @param address - A `pq1…` or `0x…` address.
157
- * @returns The `0x`-prefixed hex address.
158
- */
159
- export function normalizeHexAddress(address) {
160
- if (isPqAddress(address)) {
161
- return bytesToHexAddress(pqAddressToBytes(address));
109
+ if (!isPqAddress(address)) {
110
+ throw new Error(`expected a pq1… bech32m address, got: "${address.slice(0, 10)}…"`);
162
111
  }
163
- assertHexAddress(address);
164
112
  return address;
165
113
  }
166
114
  /**
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- export { bytesToHexAddress, PQ_ADDRESS_HRP, PQ_ADDRESS_LENGTH, PQ_ADDRESS_VERSION_V1, bytesToPqAddress, derivePqAddressFromPublicKey, isPqAddress, normalizeHexAddress, normalizePqAddress, pqAddressVersion, pqAddressToBytes, } from "./address.js";
1
+ export { PQ_ADDRESS_HRP, PQ_ADDRESS_LENGTH, PQ_ADDRESS_VERSION_V1, bytesToPqAddress, derivePqAddressFromPublicKey, isPqAddress, normalizePqAddress, pqAddressVersion, pqAddressToBytes, } from "./address.js";
2
2
  export { createShellProvider, createShellPublicClient, createShellWsClient, ShellProvider, shellDevnet, type CreateShellPublicClientOptions, } from "./provider.js";
3
- export { accountManagerAddress, accountManagerHexAddress, cancelRecoverySelector, clearValidationCodeSelector, encodeCancelRecoveryCalldata, encodeClearValidationCodeCalldata, encodeExecuteRecoveryCalldata, encodeRotateKeyCalldata, encodeSetGuardiansCalldata, encodeSetValidationCodeCalldata, encodeSubmitRecoveryCalldata, executeRecoverySelector, isSystemContractAddress, rotateKeySelector, setGuardiansSelector, setValidationCodeSelector, submitRecoverySelector, validatorRegistryAddress, validatorRegistryHexAddress, } from "./system-contracts.js";
3
+ export { accountManagerAddress, cancelRecoverySelector, clearValidationCodeSelector, encodeCancelRecoveryCalldata, encodeClearValidationCodeCalldata, encodeExecuteRecoveryCalldata, encodeRotateKeyCalldata, encodeSetGuardiansCalldata, encodeSetValidationCodeCalldata, encodeSubmitRecoveryCalldata, executeRecoverySelector, isSystemContractAddress, rotateKeySelector, setGuardiansSelector, setValidationCodeSelector, submitRecoverySelector, validatorRegistryAddress, } from "./system-contracts.js";
4
4
  export { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS, buildBatchTransaction, buildClearValidationCodeTransaction, buildContractPaymasterTransaction, buildInnerCall, buildInnerTransfer, buildRotateKeyTransaction, buildSessionKeyTransaction, buildSetValidationCodeTransaction, buildSignature, buildSignedTransaction, buildSponsoredTransaction, buildSystemTransaction, buildTransaction, buildTransferTransaction, DEFAULT_AA_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_PRIORITY_FEE_PER_GAS, DEFAULT_SYSTEM_GAS_LIMIT, DEFAULT_TRANSFER_GAS_LIMIT, DEFAULT_TX_TYPE, hashBatchTransaction, hashTransaction, type BuildBatchTransactionOptions, type BuildContractPaymasterTransactionOptions, type BuildSessionKeyTransactionOptions, type BuildSponsoredTransactionOptions, } from "./transactions.js";
5
5
  export { assertSignerMatchesKeystore, decryptKeystore, exportEncryptedKeyJson, parseEncryptedKey, validateEncryptedKeyAddress, type ParsedShellKeystore, } from "./keystore.js";
6
6
  export { adapterFromKeyPair, generateAdapter, generateMlDsa65KeyPair, generateSlhDsaKeyPair, MlDsa65Adapter, SlhDsaAdapter, type MlDsa65KeyPair, type SlhDsaKeyPair, } from "./adapters.js";
7
7
  export { buildShellSignature, publicKeyFromHex, ShellSigner, signatureTypeFromKeyType, type SignerAdapter, } from "./signer.js";
8
8
  export { AA_MAX_PAYMASTER_CONTEXT, AA_SESSION_KEY_GAS_SURCHARGE } from "./types.js";
9
- export type { AaBundle, AaInnerCall, AddressLike, GuardianConfig, HexString, RecoveryProposal, SessionAuth, ShellAccessListItem, ShellBatchInnerCallRequest, ShellBatchInnerGas, ShellCipherParams, ShellEncryptedKey, ShellEstimateBatchRequest, ShellEstimateBatchResult, ShellIsSponsoredResult, ShellKdfParams, ShellNodeInfo, ShellPaymasterPolicy, ShellSendTransactionParams, ShellSignature, ShellStorageProfile, ShellTransactionRequest, ShellTxByAddressPage, ShellTxWitness, ShellWitnessBundle, ShellWitnessRootResult, SignedShellTransaction, SignatureTypeName, } from "./types.js";
9
+ export { formatShellRpcTxType } from "./types.js";
10
+ export type { AaBundle, AaInnerCall, AddressLike, GuardianConfig, HexString, RecoveryProposal, SessionAuth, ShellAccessListItem, ShellBatchInnerCallRequest, ShellBatchInnerGas, ShellCipherParams, ShellEncryptedKey, ShellEstimateBatchRequest, ShellEstimateBatchResult, ShellKnownRpcTxType, ShellIsSponsoredResult, ShellKdfParams, ShellNodeInfo, ShellPaymasterPolicy, ShellReadableTxType, ShellRewardKind, ShellRpcReceipt, ShellRpcTransaction, ShellRpcTransactionSummary, ShellRpcTxType, ShellSendTransactionParams, ShellSignature, ShellStorageProfile, ShellTransactionRequest, ShellTxByAddressPage, ShellTxWitness, ShellWitnessBundle, ShellWitnessRootResult, SignedShellTransaction, SignatureTypeName, } from "./types.js";
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
- export { bytesToHexAddress, PQ_ADDRESS_HRP, PQ_ADDRESS_LENGTH, PQ_ADDRESS_VERSION_V1, bytesToPqAddress, derivePqAddressFromPublicKey, isPqAddress, normalizeHexAddress, normalizePqAddress, pqAddressVersion, pqAddressToBytes, } from "./address.js";
1
+ export { PQ_ADDRESS_HRP, PQ_ADDRESS_LENGTH, PQ_ADDRESS_VERSION_V1, bytesToPqAddress, derivePqAddressFromPublicKey, isPqAddress, normalizePqAddress, pqAddressVersion, pqAddressToBytes, } from "./address.js";
2
2
  export { createShellProvider, createShellPublicClient, createShellWsClient, ShellProvider, shellDevnet, } from "./provider.js";
3
- export { accountManagerAddress, accountManagerHexAddress, cancelRecoverySelector, clearValidationCodeSelector, encodeCancelRecoveryCalldata, encodeClearValidationCodeCalldata, encodeExecuteRecoveryCalldata, encodeRotateKeyCalldata, encodeSetGuardiansCalldata, encodeSetValidationCodeCalldata, encodeSubmitRecoveryCalldata, executeRecoverySelector, isSystemContractAddress, rotateKeySelector, setGuardiansSelector, setValidationCodeSelector, submitRecoverySelector, validatorRegistryAddress, validatorRegistryHexAddress, } from "./system-contracts.js";
3
+ export { accountManagerAddress, cancelRecoverySelector, clearValidationCodeSelector, encodeCancelRecoveryCalldata, encodeClearValidationCodeCalldata, encodeExecuteRecoveryCalldata, encodeRotateKeyCalldata, encodeSetGuardiansCalldata, encodeSetValidationCodeCalldata, encodeSubmitRecoveryCalldata, executeRecoverySelector, isSystemContractAddress, rotateKeySelector, setGuardiansSelector, setValidationCodeSelector, submitRecoverySelector, validatorRegistryAddress, } from "./system-contracts.js";
4
4
  export { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS, buildBatchTransaction, buildClearValidationCodeTransaction, buildContractPaymasterTransaction, buildInnerCall, buildInnerTransfer, buildRotateKeyTransaction, buildSessionKeyTransaction, buildSetValidationCodeTransaction, buildSignature, buildSignedTransaction, buildSponsoredTransaction, buildSystemTransaction, buildTransaction, buildTransferTransaction, DEFAULT_AA_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_PRIORITY_FEE_PER_GAS, DEFAULT_SYSTEM_GAS_LIMIT, DEFAULT_TRANSFER_GAS_LIMIT, DEFAULT_TX_TYPE, hashBatchTransaction, hashTransaction, } from "./transactions.js";
5
5
  export { assertSignerMatchesKeystore, decryptKeystore, exportEncryptedKeyJson, parseEncryptedKey, validateEncryptedKeyAddress, } from "./keystore.js";
6
6
  export { adapterFromKeyPair, generateAdapter, generateMlDsa65KeyPair, generateSlhDsaKeyPair, MlDsa65Adapter, SlhDsaAdapter, } from "./adapters.js";
7
7
  export { buildShellSignature, publicKeyFromHex, ShellSigner, signatureTypeFromKeyType, } from "./signer.js";
8
8
  export { AA_MAX_PAYMASTER_CONTEXT, AA_SESSION_KEY_GAS_SURCHARGE } from "./types.js";
9
+ export { formatShellRpcTxType } from "./types.js";
@@ -16,8 +16,6 @@ export interface ParsedShellKeystore {
16
16
  publicKey: Uint8Array;
17
17
  /** Canonical `pq1…` address derived from `publicKey`. */
18
18
  canonicalAddress: string;
19
- /** `0x`-prefixed hex representation of the same address. */
20
- hexAddress: string;
21
19
  }
22
20
  /**
23
21
  * Parse a Shell keystore file (string or object) and extract public metadata.
@@ -33,7 +31,7 @@ export interface ParsedShellKeystore {
33
31
  * ```typescript
34
32
  * const parsed = parseEncryptedKey(readFileSync("key.json", "utf8"));
35
33
  * console.log(parsed.canonicalAddress); // pq1…
36
- * console.log(parsed.signatureType); // "MlDsa65"
34
+ * console.log(parsed.signatureType); // "ML-DSA-65"
37
35
  * ```
38
36
  */
39
37
  export declare function parseEncryptedKey(input: string | ShellEncryptedKey): ParsedShellKeystore;
@@ -77,17 +75,14 @@ export declare function assertSignerMatchesKeystore(signer: ShellSigner, keystor
77
75
  *
78
76
  * **KDF**: argon2id (parameters from `kdf_params`)
79
77
  * **Cipher**: xchacha20-poly1305 (24-byte nonce from `cipher_params`)
80
- * **Plaintext layout**: `[secret_key_bytes][public_key_bytes]`
81
- *
82
- * The decrypted public key is compared against `raw.public_key` to detect
83
- * wrong passwords or corrupt files before returning the signer.
78
+ * **Plaintext layout (v1)**: secret key bytes only (sk-only format).
79
+ * The public key is read from the `public_key` JSON field directly.
84
80
  *
85
81
  * @param input - Keystore JSON string or object.
86
82
  * @param password - The passphrase used to encrypt the key.
87
83
  * @returns A fully configured `ShellSigner` ready for signing transactions.
88
84
  * @throws {Error} If the KDF or cipher is unsupported.
89
85
  * @throws {Error} If decryption fails (wrong password or corrupt ciphertext).
90
- * @throws {Error} If the decrypted public key does not match the stored one.
91
86
  *
92
87
  * @example
93
88
  * ```typescript
package/dist/keystore.js CHANGED
@@ -6,19 +6,23 @@
6
6
  * - **KDF**: argon2id (memory-hard password derivation)
7
7
  * - **Cipher**: xchacha20-poly1305 (authenticated encryption)
8
8
  *
9
- * They are generated by the Shell CLI (`shell key generate`) and are
10
- * compatible with the SDK's `decryptKeystore` function.
9
+ * ## Keystore format (v1 canonical)
11
10
  *
12
- * Plaintext layout after decryption: `[secret_key_bytes][public_key_bytes]`.
11
+ * The **ciphertext** contains **only the secret key bytes** (sk-only format).
12
+ * The public key is stored separately in the `public_key` field as plain hex.
13
+ * This matches the format produced by `shell-node key generate`.
14
+ *
15
+ * Previous SDK versions expected `sk || pk` in the ciphertext. That format
16
+ * is no longer produced or accepted; all new keystores use sk-only.
13
17
  *
14
18
  * @module keystore
15
19
  */
16
20
  import { xchacha20poly1305 } from "@noble/ciphers/chacha.js";
17
21
  import { argon2id } from "hash-wasm";
18
- import { derivePqAddressFromPublicKey, normalizeHexAddress, normalizePqAddress } from "./address.js";
22
+ import { derivePqAddressFromPublicKey, normalizePqAddress } from "./address.js";
19
23
  import { adapterFromKeyPair } from "./adapters.js";
20
- import { ShellSigner, publicKeyFromHex, signatureTypeFromKeyType } from "./signer.js";
21
- const SIG_IDS = { "ML-DSA-65": 0, Dilithium3: 0, MlDsa65: 0, SphincsSha2256f: 2 };
24
+ import { ShellSigner, canonicalSignatureType, publicKeyFromHex, signatureTypeFromKeyType, } from "./signer.js";
25
+ const SIG_IDS = { "ML-DSA-65": 1, Dilithium3: 0, MlDsa65: 1, SphincsSha2256f: 2 };
22
26
  /**
23
27
  * Parse a Shell keystore file (string or object) and extract public metadata.
24
28
  *
@@ -33,7 +37,7 @@ const SIG_IDS = { "ML-DSA-65": 0, Dilithium3: 0, MlDsa65: 0, SphincsSha2256f: 2
33
37
  * ```typescript
34
38
  * const parsed = parseEncryptedKey(readFileSync("key.json", "utf8"));
35
39
  * console.log(parsed.canonicalAddress); // pq1…
36
- * console.log(parsed.signatureType); // "MlDsa65"
40
+ * console.log(parsed.signatureType); // "ML-DSA-65"
37
41
  * ```
38
42
  */
39
43
  export function parseEncryptedKey(input) {
@@ -42,8 +46,7 @@ export function parseEncryptedKey(input) {
42
46
  const algorithmId = SIG_IDS[signatureType];
43
47
  const publicKey = publicKeyFromHex(raw.public_key);
44
48
  const canonicalAddress = derivePqAddressFromPublicKey(publicKey, algorithmId);
45
- const hexAddress = normalizeHexAddress(canonicalAddress);
46
- return { raw, signatureType, algorithmId, publicKey, canonicalAddress, hexAddress };
49
+ return { raw, signatureType, algorithmId, publicKey, canonicalAddress };
47
50
  }
48
51
  /**
49
52
  * Parse a keystore and verify that the declared address matches the public key.
@@ -89,7 +92,7 @@ export function exportEncryptedKeyJson(input) {
89
92
  * ```
90
93
  */
91
94
  export function assertSignerMatchesKeystore(signer, keystore) {
92
- if (signer.signatureType !== keystore.signatureType) {
95
+ if (canonicalSignatureType(signer.signatureType) !== keystore.signatureType) {
93
96
  throw new Error("algorithm mismatch: signer=" + signer.signatureType + " keystore=" + keystore.signatureType);
94
97
  }
95
98
  const addr = signer.getAddress();
@@ -110,17 +113,14 @@ function hexToBytes(hex) {
110
113
  *
111
114
  * **KDF**: argon2id (parameters from `kdf_params`)
112
115
  * **Cipher**: xchacha20-poly1305 (24-byte nonce from `cipher_params`)
113
- * **Plaintext layout**: `[secret_key_bytes][public_key_bytes]`
114
- *
115
- * The decrypted public key is compared against `raw.public_key` to detect
116
- * wrong passwords or corrupt files before returning the signer.
116
+ * **Plaintext layout (v1)**: secret key bytes only (sk-only format).
117
+ * The public key is read from the `public_key` JSON field directly.
117
118
  *
118
119
  * @param input - Keystore JSON string or object.
119
120
  * @param password - The passphrase used to encrypt the key.
120
121
  * @returns A fully configured `ShellSigner` ready for signing transactions.
121
122
  * @throws {Error} If the KDF or cipher is unsupported.
122
123
  * @throws {Error} If decryption fails (wrong password or corrupt ciphertext).
123
- * @throws {Error} If the decrypted public key does not match the stored one.
124
124
  *
125
125
  * @example
126
126
  * ```typescript
@@ -150,17 +150,8 @@ export async function decryptKeystore(input, password) {
150
150
  });
151
151
  const derivedKey = hexToBytes(derivedKeyHex);
152
152
  const chacha = xchacha20poly1305(derivedKey, nonce);
153
- const plaintext = chacha.decrypt(ciphertext);
154
- const pubkeyLen = parsed.publicKey.length;
155
- const skLen = plaintext.length - pubkeyLen;
156
- if (skLen <= 0) {
157
- throw new Error("payload too short: " + plaintext.length + " bytes");
158
- }
159
- const secretKey = plaintext.slice(0, skLen);
160
- const derivedPubkey = plaintext.slice(skLen);
161
- if (!derivedPubkey.every((b, i) => b === parsed.publicKey[i])) {
162
- throw new Error("decrypted public key mismatch");
163
- }
153
+ // Plaintext is sk-only; public key comes from the JSON `public_key` field.
154
+ const secretKey = chacha.decrypt(ciphertext);
164
155
  const adapter = adapterFromKeyPair(parsed.signatureType, parsed.publicKey, secretKey);
165
156
  return new ShellSigner(parsed.signatureType, adapter);
166
157
  }
@@ -16,7 +16,7 @@
16
16
  * @module provider
17
17
  */
18
18
  import { type Chain, type PublicClient } from "viem";
19
- import type { ShellEstimateBatchRequest, ShellEstimateBatchResult, ShellIsSponsoredResult, ShellNodeInfo, ShellPaymasterPolicy, ShellStorageProfile, ShellWitnessBundle, ShellWitnessRootResult, SignedShellTransaction } from "./types.js";
19
+ import type { ShellEstimateBatchRequest, ShellEstimateBatchResult, ShellIsSponsoredResult, ShellNodeInfo, ShellPaymasterPolicy, ShellRpcReceipt, ShellStorageProfile, ShellTxByAddressPage, ShellWitnessBundle, ShellWitnessRootResult, SignedShellTransaction } from "./types.js";
20
20
  /**
21
21
  * Pre-configured viem chain definition for Shell Devnet.
22
22
  *
@@ -90,6 +90,7 @@ export interface CreateShellPublicClientOptions {
90
90
  }
91
91
  /** A typed alias for a viem `PublicClient`. */
92
92
  export type ShellPublicClient = PublicClient;
93
+ export type ShellBlockRangeBound = number | `0x${string}`;
93
94
  /**
94
95
  * RPC client for Shell Chain.
95
96
  *
@@ -113,7 +114,7 @@ export declare class ShellProvider {
113
114
  * Calls `shell_getPqPubkey`. Returns `null` if the address has not yet
114
115
  * submitted a transaction (public key is only recorded on first send).
115
116
  *
116
- * @param address - A `pq1…` or `0x…` address.
117
+ * @param address - A `pq1…` bech32m address.
117
118
  * @returns Hex-encoded public key string, or `null` if unknown.
118
119
  */
119
120
  getPqPubkey(address: string): Promise<string | null>;
@@ -138,14 +139,16 @@ export declare class ShellProvider {
138
139
  * @param options.toBlock - End of block range (inclusive).
139
140
  * @param options.page - Zero-based page index.
140
141
  * @param options.limit - Maximum number of results per page.
141
- * @returns Raw paginated response from the node.
142
+ * @returns Paginated response from the node. `fromBlock`/`toBlock` in the
143
+ * response is the effective inclusive range; clients that paginate under
144
+ * live load should pin `toBlock` from the first page.
142
145
  */
143
146
  getTransactionsByAddress(address: string, options?: {
144
- fromBlock?: number;
145
- toBlock?: number;
147
+ fromBlock?: ShellBlockRangeBound;
148
+ toBlock?: ShellBlockRangeBound;
146
149
  page?: number;
147
150
  limit?: number;
148
- }): Promise<unknown>;
151
+ }): Promise<ShellTxByAddressPage>;
149
152
  /**
150
153
  * Fetch all transaction receipts for a block.
151
154
  *
@@ -154,7 +157,7 @@ export declare class ShellProvider {
154
157
  * @param block - Block identifier: `"latest"`, `"earliest"`, or a hex block number.
155
158
  * @returns Array of transaction receipt objects.
156
159
  */
157
- getBlockReceipts(block: string): Promise<unknown[]>;
160
+ getBlockReceipts(block: string): Promise<ShellRpcReceipt[]>;
158
161
  /**
159
162
  * Fetch metadata about the connected Shell Chain node.
160
163
  *
@@ -279,7 +282,7 @@ export declare function createShellWsClient(options?: CreateShellPublicClientOpt
279
282
  * @example
280
283
  * ```typescript
281
284
  * const provider = createShellProvider();
282
- * const balance = await provider.client.getBalance({ address: signer.getHexAddress() });
285
+ * const balance = await provider.getBalance(signer.getAddress());
283
286
  * const hash = await provider.sendTransaction(signedTx);
284
287
  * ```
285
288
  */
package/dist/provider.js CHANGED
@@ -86,7 +86,7 @@ export class ShellProvider {
86
86
  * Calls `shell_getPqPubkey`. Returns `null` if the address has not yet
87
87
  * submitted a transaction (public key is only recorded on first send).
88
88
  *
89
- * @param address - A `pq1…` or `0x…` address.
89
+ * @param address - A `pq1…` bech32m address.
90
90
  * @returns Hex-encoded public key string, or `null` if unknown.
91
91
  */
92
92
  async getPqPubkey(address) {
@@ -115,7 +115,9 @@ export class ShellProvider {
115
115
  * @param options.toBlock - End of block range (inclusive).
116
116
  * @param options.page - Zero-based page index.
117
117
  * @param options.limit - Maximum number of results per page.
118
- * @returns Raw paginated response from the node.
118
+ * @returns Paginated response from the node. `fromBlock`/`toBlock` in the
119
+ * response is the effective inclusive range; clients that paginate under
120
+ * live load should pin `toBlock` from the first page.
119
121
  */
120
122
  async getTransactionsByAddress(address, options = {}) {
121
123
  return this.request("shell_getTransactionsByAddress", [
@@ -294,7 +296,7 @@ export function createShellWsClient(options = {}) {
294
296
  * @example
295
297
  * ```typescript
296
298
  * const provider = createShellProvider();
297
- * const balance = await provider.client.getBalance({ address: signer.getHexAddress() });
299
+ * const balance = await provider.getBalance(signer.getAddress());
298
300
  * const hash = await provider.sendTransaction(signedTx);
299
301
  * ```
300
302
  */
package/dist/signer.d.ts CHANGED
@@ -4,9 +4,8 @@ import type { SignedShellTransaction, SignatureTypeName } from "./types.js";
4
4
  * Maps each {@link SignatureTypeName} to its numeric algorithm ID used in
5
5
  * address derivation and on-chain records.
6
6
  *
7
- * - `"ML-DSA-65"` → `0` (canonical FIPS 204 name)
8
- * - `"Dilithium3"` → `0` (legacy alias, same algorithm)
9
- * - `"MlDsa65"` → `0` (camelCase alias, same algorithm)
7
+ * - `"Dilithium3"` → `0` (Round 3 Dilithium, legacy compat)
8
+ * - `"ML-DSA-65"` / `"MlDsa65"` → `1` (FIPS 204 ML-DSA-65, canonical)
10
9
  * - `"SphincsSha2256f"` → `2`
11
10
  */
12
11
  export declare const SIGNATURE_TYPE_IDS: Record<SignatureTypeName, number>;
@@ -15,9 +14,9 @@ export declare const SIGNATURE_TYPE_IDS: Record<SignatureTypeName, number>;
15
14
  * corresponding {@link SignatureTypeName}.
16
15
  *
17
16
  * Keys are lowercase; matching is done after calling `.toLowerCase()`.
18
- * Always returns the FIPS 204 canonical name `"ML-DSA-65"` for ML-DSA-65 variants.
19
17
  */
20
18
  export declare const KEY_TYPE_TO_SIGNATURE_TYPE: Record<string, SignatureTypeName>;
19
+ export declare function canonicalSignatureType(signatureType: SignatureTypeName): SignatureTypeName;
21
20
  /**
22
21
  * Minimal interface that any post-quantum signing implementation must satisfy
23
22
  * to be used with {@link ShellSigner}.
@@ -55,8 +54,7 @@ export interface SignerAdapter {
55
54
  * const adapter = MlDsa65Adapter.generate();
56
55
  * const signer = new ShellSigner("MlDsa65", adapter);
57
56
  *
58
- * console.log(signer.getAddress()); // pq1…
59
- * console.log(signer.getHexAddress()); // 0x…
57
+ * console.log(signer.getAddress()); // pq1…
60
58
  * ```
61
59
  */
62
60
  export declare class ShellSigner {
@@ -83,12 +81,6 @@ export declare class ShellSigner {
83
81
  * The address is computed deterministically from the public key and algorithm ID.
84
82
  */
85
83
  getAddress(): string;
86
- /**
87
- * Return the `0x…` hex representation of this signer's address.
88
- *
89
- * Equivalent to `normalizeHexAddress(signer.getAddress())`.
90
- */
91
- getHexAddress(): `0x${string}`;
92
84
  /**
93
85
  * Sign a raw byte message with the underlying adapter.
94
86
  *
@@ -132,7 +124,7 @@ export declare class ShellSigner {
132
124
  *
133
125
  * @example
134
126
  * ```typescript
135
- * signatureTypeFromKeyType("mldsa65"); // "MlDsa65"
127
+ * signatureTypeFromKeyType("mldsa65"); // "ML-DSA-65"
136
128
  * signatureTypeFromKeyType("sphincs-sha2-256f"); // "SphincsSha2256f"
137
129
  * ```
138
130
  */
package/dist/signer.js CHANGED
@@ -10,21 +10,20 @@
10
10
  * @module signer
11
11
  */
12
12
  import { hexToBytes } from "viem";
13
- import { derivePqAddressFromPublicKey, normalizeHexAddress, normalizePqAddress } from "./address.js";
13
+ import { derivePqAddressFromPublicKey, normalizePqAddress } from "./address.js";
14
14
  import { buildSignature, buildSignedTransaction, } from "./transactions.js";
15
15
  /**
16
16
  * Maps each {@link SignatureTypeName} to its numeric algorithm ID used in
17
17
  * address derivation and on-chain records.
18
18
  *
19
- * - `"ML-DSA-65"` → `0` (canonical FIPS 204 name)
20
- * - `"Dilithium3"` → `0` (legacy alias, same algorithm)
21
- * - `"MlDsa65"` → `0` (camelCase alias, same algorithm)
19
+ * - `"Dilithium3"` → `0` (Round 3 Dilithium, legacy compat)
20
+ * - `"ML-DSA-65"` / `"MlDsa65"` → `1` (FIPS 204 ML-DSA-65, canonical)
22
21
  * - `"SphincsSha2256f"` → `2`
23
22
  */
24
23
  export const SIGNATURE_TYPE_IDS = {
25
- "ML-DSA-65": 0,
24
+ "ML-DSA-65": 1,
26
25
  Dilithium3: 0,
27
- MlDsa65: 0,
26
+ MlDsa65: 1,
28
27
  SphincsSha2256f: 2,
29
28
  };
30
29
  /**
@@ -32,14 +31,16 @@ export const SIGNATURE_TYPE_IDS = {
32
31
  * corresponding {@link SignatureTypeName}.
33
32
  *
34
33
  * Keys are lowercase; matching is done after calling `.toLowerCase()`.
35
- * Always returns the FIPS 204 canonical name `"ML-DSA-65"` for ML-DSA-65 variants.
36
34
  */
37
35
  export const KEY_TYPE_TO_SIGNATURE_TYPE = {
38
36
  "ml-dsa-65": "ML-DSA-65",
39
37
  mldsa65: "ML-DSA-65",
40
- dilithium3: "ML-DSA-65",
38
+ dilithium3: "Dilithium3",
41
39
  "sphincs-sha2-256f": "SphincsSha2256f",
42
40
  };
41
+ export function canonicalSignatureType(signatureType) {
42
+ return signatureType === "MlDsa65" ? "ML-DSA-65" : signatureType;
43
+ }
43
44
  /**
44
45
  * High-level Shell Chain signer.
45
46
  *
@@ -54,8 +55,7 @@ export const KEY_TYPE_TO_SIGNATURE_TYPE = {
54
55
  * const adapter = MlDsa65Adapter.generate();
55
56
  * const signer = new ShellSigner("MlDsa65", adapter);
56
57
  *
57
- * console.log(signer.getAddress()); // pq1…
58
- * console.log(signer.getHexAddress()); // 0x…
58
+ * console.log(signer.getAddress()); // pq1…
59
59
  * ```
60
60
  */
61
61
  export class ShellSigner {
@@ -68,7 +68,7 @@ export class ShellSigner {
68
68
  * @param adapter - An adapter providing `sign` and `getPublicKey`.
69
69
  */
70
70
  constructor(signatureType, adapter) {
71
- this.signatureType = signatureType;
71
+ this.signatureType = canonicalSignatureType(signatureType);
72
72
  this.adapter = adapter;
73
73
  }
74
74
  /**
@@ -91,14 +91,6 @@ export class ShellSigner {
91
91
  getAddress() {
92
92
  return derivePqAddressFromPublicKey(this.getPublicKey(), this.algorithmId);
93
93
  }
94
- /**
95
- * Return the `0x…` hex representation of this signer's address.
96
- *
97
- * Equivalent to `normalizeHexAddress(signer.getAddress())`.
98
- */
99
- getHexAddress() {
100
- return normalizeHexAddress(this.getAddress());
101
- }
102
94
  /**
103
95
  * Sign a raw byte message with the underlying adapter.
104
96
  *
@@ -150,7 +142,7 @@ export class ShellSigner {
150
142
  *
151
143
  * @example
152
144
  * ```typescript
153
- * signatureTypeFromKeyType("mldsa65"); // "MlDsa65"
145
+ * signatureTypeFromKeyType("mldsa65"); // "ML-DSA-65"
154
146
  * signatureTypeFromKeyType("sphincs-sha2-256f"); // "SphincsSha2256f"
155
147
  * ```
156
148
  */
@@ -1,8 +1,4 @@
1
1
  import type { AddressLike, HexString } from "./types.js";
2
- /** Hex address of the ValidatorRegistry system contract (`0x…0001`). */
3
- export declare const validatorRegistryHexAddress = "0x0000000000000000000000000000000000000001";
4
- /** Hex address of the AccountManager system contract (`0x…0002`). */
5
- export declare const accountManagerHexAddress = "0x0000000000000000000000000000000000000002";
6
2
  /** `pq1…` bech32m address of the ValidatorRegistry system contract. */
7
3
  export declare const validatorRegistryAddress: string;
8
4
  /** `pq1…` bech32m address of the AccountManager system contract. */
@@ -57,17 +53,13 @@ export declare function encodeClearValidationCodeCalldata(): HexString;
57
53
  /**
58
54
  * Return `true` if `address` refers to one of the Shell system contracts.
59
55
  *
60
- * Accepts both `pq1…` and `0x…` forms for the AccountManager and
61
- * ValidatorRegistry addresses.
62
- *
63
- * @param address - Address to test (any format accepted by `AddressLike`).
56
+ * @param address - `pq1…` address to test.
64
57
  * @returns `true` if the address matches AccountManager or ValidatorRegistry.
65
58
  *
66
59
  * @example
67
60
  * ```typescript
68
- * isSystemContractAddress("0x0000000000000000000000000000000000000002"); // true
69
- * isSystemContractAddress(accountManagerAddress); // true
70
- * isSystemContractAddress("pq1someuser…"); // false
61
+ * isSystemContractAddress(accountManagerAddress); // true
62
+ * isSystemContractAddress("pq1someuser…"); // false
71
63
  * ```
72
64
  */
73
65
  export declare function isSystemContractAddress(address: AddressLike): boolean;
@@ -78,7 +70,7 @@ export declare function isSystemContractAddress(address: AddressLike): boolean;
78
70
  * account owner can call this (the call must be made as an inner call from
79
71
  * the owner's AA bundle, or as a direct transaction).
80
72
  *
81
- * @param guardians - Array of guardian addresses (1..5). May be hex or `pq1…` form.
73
+ * @param guardians - Array of guardian addresses (1..5). Must be `pq1…` bech32m form.
82
74
  * @param threshold - k-of-n required votes (1 ≤ threshold ≤ guardians.length).
83
75
  * @param timelock - Minimum blocks between threshold-reach and execution (≥ 100).
84
76
  * @returns `HexString` with the 4-byte selector prepended.
@@ -86,7 +78,7 @@ export declare function isSystemContractAddress(address: AddressLike): boolean;
86
78
  * @example
87
79
  * ```typescript
88
80
  * const data = encodeSetGuardiansCalldata(
89
- * ["0xGuardian1…", "0xGuardian2…", "0xGuardian3…"],
81
+ * ["pq1guardian1…", "pq1guardian2…", "pq1guardian3…"],
90
82
  * 2, // 2-of-3 threshold
91
83
  * 100, // 100-block timelock
92
84
  * );
@@ -100,7 +92,7 @@ export declare function encodeSetGuardiansCalldata(guardians: AddressLike[], thr
100
92
  * When k-of-n threshold is reached, the proposal becomes executable after
101
93
  * `timelock` blocks.
102
94
  *
103
- * @param account - Account being recovered (0x hex or `pq1…` form).
95
+ * @param account - Account being recovered (`pq1…` bech32m form).
104
96
  * @param newPubkey - Raw bytes of the new PQ public key.
105
97
  * @param newAlgo - Algorithm ID for the new key (ML-DSA-65 = 0, etc.).
106
98
  * @returns `HexString` with the 4-byte selector prepended.
@@ -108,7 +100,7 @@ export declare function encodeSetGuardiansCalldata(guardians: AddressLike[], thr
108
100
  * @example
109
101
  * ```typescript
110
102
  * const data = encodeSubmitRecoveryCalldata(
111
- * "0xAccountAddress…",
103
+ * "pq1accountaddress…",
112
104
  * newPubkeyBytes,
113
105
  * 0, // ML-DSA-65
114
106
  * );
@@ -18,7 +18,7 @@
18
18
  * @module system-contracts
19
19
  */
20
20
  import { bytesToHex, encodeAbiParameters, keccak256, toBytes } from "viem";
21
- import { bytesToPqAddress } from "./address.js";
21
+ import { bytesToPqAddress, pqAddressToBytes } from "./address.js";
22
22
  const SYSTEM_ADDRESS_LENGTH = 20;
23
23
  function systemAddress(lastByte) {
24
24
  const bytes = new Uint8Array(SYSTEM_ADDRESS_LENGTH);
@@ -28,10 +28,6 @@ function systemAddress(lastByte) {
28
28
  function selector(signature) {
29
29
  return keccak256(toBytes(signature)).slice(0, 10);
30
30
  }
31
- /** Hex address of the ValidatorRegistry system contract (`0x…0001`). */
32
- export const validatorRegistryHexAddress = "0x0000000000000000000000000000000000000001";
33
- /** Hex address of the AccountManager system contract (`0x…0002`). */
34
- export const accountManagerHexAddress = "0x0000000000000000000000000000000000000002";
35
31
  /** `pq1…` bech32m address of the ValidatorRegistry system contract. */
36
32
  export const validatorRegistryAddress = bytesToPqAddress(systemAddress(1));
37
33
  /** `pq1…` bech32m address of the AccountManager system contract. */
@@ -100,24 +96,17 @@ export function encodeClearValidationCodeCalldata() {
100
96
  /**
101
97
  * Return `true` if `address` refers to one of the Shell system contracts.
102
98
  *
103
- * Accepts both `pq1…` and `0x…` forms for the AccountManager and
104
- * ValidatorRegistry addresses.
105
- *
106
- * @param address - Address to test (any format accepted by `AddressLike`).
99
+ * @param address - `pq1…` address to test.
107
100
  * @returns `true` if the address matches AccountManager or ValidatorRegistry.
108
101
  *
109
102
  * @example
110
103
  * ```typescript
111
- * isSystemContractAddress("0x0000000000000000000000000000000000000002"); // true
112
- * isSystemContractAddress(accountManagerAddress); // true
113
- * isSystemContractAddress("pq1someuser…"); // false
104
+ * isSystemContractAddress(accountManagerAddress); // true
105
+ * isSystemContractAddress("pq1someuser…"); // false
114
106
  * ```
115
107
  */
116
108
  export function isSystemContractAddress(address) {
117
- return (address === accountManagerAddress ||
118
- address === validatorRegistryAddress ||
119
- address === accountManagerHexAddress ||
120
- address === validatorRegistryHexAddress);
109
+ return address === accountManagerAddress || address === validatorRegistryAddress;
121
110
  }
122
111
  // ---------------------------------------------------------------------------
123
112
  // AA Phase 2 — Guardian Recovery calldata encoders (v0.19.0-dev)
@@ -129,7 +118,7 @@ export function isSystemContractAddress(address) {
129
118
  * account owner can call this (the call must be made as an inner call from
130
119
  * the owner's AA bundle, or as a direct transaction).
131
120
  *
132
- * @param guardians - Array of guardian addresses (1..5). May be hex or `pq1…` form.
121
+ * @param guardians - Array of guardian addresses (1..5). Must be `pq1…` bech32m form.
133
122
  * @param threshold - k-of-n required votes (1 ≤ threshold ≤ guardians.length).
134
123
  * @param timelock - Minimum blocks between threshold-reach and execution (≥ 100).
135
124
  * @returns `HexString` with the 4-byte selector prepended.
@@ -137,18 +126,15 @@ export function isSystemContractAddress(address) {
137
126
  * @example
138
127
  * ```typescript
139
128
  * const data = encodeSetGuardiansCalldata(
140
- * ["0xGuardian1…", "0xGuardian2…", "0xGuardian3…"],
129
+ * ["pq1guardian1…", "pq1guardian2…", "pq1guardian3…"],
141
130
  * 2, // 2-of-3 threshold
142
131
  * 100, // 100-block timelock
143
132
  * );
144
133
  * ```
145
134
  */
146
135
  export function encodeSetGuardiansCalldata(guardians, threshold, timelock) {
147
- // Normalise to 0x… form; encodeAbiParameters expects `0x${string}` addresses.
148
- const hexGuardians = guardians.map((g) => {
149
- const s = typeof g === "string" ? g : bytesToHex(g);
150
- return (s.startsWith("0x") ? s : `0x${s}`);
151
- });
136
+ // Decode pq1… addresses to raw 20 bytes, then to 0x-hex for ABI encoding.
137
+ const hexGuardians = guardians.map((g) => bytesToHex(pqAddressToBytes(g)));
152
138
  const encoded = encodeAbiParameters([{ type: "address[]" }, { type: "uint8" }, { type: "uint64" }], [hexGuardians, threshold, BigInt(timelock)]);
153
139
  return `${setGuardiansSelector}${encoded.slice(2)}`;
154
140
  }
@@ -159,7 +145,7 @@ export function encodeSetGuardiansCalldata(guardians, threshold, timelock) {
159
145
  * When k-of-n threshold is reached, the proposal becomes executable after
160
146
  * `timelock` blocks.
161
147
  *
162
- * @param account - Account being recovered (0x hex or `pq1…` form).
148
+ * @param account - Account being recovered (`pq1…` bech32m form).
163
149
  * @param newPubkey - Raw bytes of the new PQ public key.
164
150
  * @param newAlgo - Algorithm ID for the new key (ML-DSA-65 = 0, etc.).
165
151
  * @returns `HexString` with the 4-byte selector prepended.
@@ -167,7 +153,7 @@ export function encodeSetGuardiansCalldata(guardians, threshold, timelock) {
167
153
  * @example
168
154
  * ```typescript
169
155
  * const data = encodeSubmitRecoveryCalldata(
170
- * "0xAccountAddress…",
156
+ * "pq1accountaddress…",
171
157
  * newPubkeyBytes,
172
158
  * 0, // ML-DSA-65
173
159
  * );
@@ -209,9 +195,7 @@ export function encodeCancelRecoveryCalldata(account) {
209
195
  // ---------------------------------------------------------------------------
210
196
  // Internal helpers
211
197
  // ---------------------------------------------------------------------------
198
+ /** Convert a pq1… address to a 0x-hex form for EVM ABI encoding. */
212
199
  function normaliseToHex(address) {
213
- if (typeof address !== "string") {
214
- return bytesToHex(address);
215
- }
216
- return (address.startsWith("0x") ? address : `0x${address}`);
200
+ return bytesToHex(pqAddressToBytes(address));
217
201
  }
@@ -11,7 +11,7 @@ import { bytesToHex, keccak256, toRlp, hexToBytes } from "viem";
11
11
  import { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS } from "./types.js";
12
12
  export { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS };
13
13
  import { accountManagerAddress, encodeClearValidationCodeCalldata, encodeRotateKeyCalldata, encodeSetValidationCodeCalldata, } from "./system-contracts.js";
14
- import { normalizeHexAddress } from "./address.js";
14
+ import { pqAddressToBytes } from "./address.js";
15
15
  /** Default transaction type: `2` (EIP-1559). */
16
16
  export const DEFAULT_TX_TYPE = 2;
17
17
  /** Default gas limit for simple SHELL token transfers (`21_000`). */
@@ -40,7 +40,7 @@ function toRlpAccessList(accessList) {
40
40
  return [];
41
41
  }
42
42
  return accessList.map((item) => [
43
- normalizeHexAddress(item.address),
43
+ bytesToHex(pqAddressToBytes(item.address)),
44
44
  item.storage_keys.map((key) => key),
45
45
  ]);
46
46
  }
@@ -249,7 +249,7 @@ export function hashTransaction(tx) {
249
249
  const fields = [
250
250
  toRlpUint(tx.chain_id),
251
251
  toRlpUint(tx.nonce),
252
- tx.to ? normalizeHexAddress(tx.to) : "0x",
252
+ tx.to ? bytesToHex(pqAddressToBytes(tx.to)) : "0x",
253
253
  toRlpUint(tx.value),
254
254
  tx.data,
255
255
  toRlpUint(tx.gas_limit),
@@ -368,14 +368,14 @@ export function hashBatchTransaction(tx, bundle) {
368
368
  }
369
369
  // Encode inner calls for signing (matches chain's encode_for_signing).
370
370
  const innerCallsRlp = bundle.inner_calls.map((call) => [
371
- call.to ? normalizeHexAddress(call.to) : "0x",
371
+ call.to ? bytesToHex(pqAddressToBytes(call.to)) : "0x",
372
372
  toRlpUint(call.value),
373
373
  call.data,
374
374
  toRlpUint(call.gas_limit),
375
375
  ]);
376
376
  // Paymaster: 20-byte address or empty bytes.
377
377
  const paymasterField = bundle.paymaster
378
- ? normalizeHexAddress(bundle.paymaster)
378
+ ? bytesToHex(pqAddressToBytes(bundle.paymaster))
379
379
  : "0x";
380
380
  // paymaster_context: raw bytes or empty.
381
381
  const paymasterContextField = bundle.paymaster_context && bundle.paymaster_context.length > 0
@@ -384,7 +384,7 @@ export function hashBatchTransaction(tx, bundle) {
384
384
  const txFields = [
385
385
  toRlpUint(tx.chain_id),
386
386
  toRlpUint(tx.nonce),
387
- tx.to ? normalizeHexAddress(tx.to) : "0x",
387
+ tx.to ? bytesToHex(pqAddressToBytes(tx.to)) : "0x",
388
388
  toRlpUint(tx.value),
389
389
  tx.data,
390
390
  toRlpUint(tx.gas_limit),
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /** A `0x`-prefixed hex string, e.g. `"0xdeadbeef"`. */
2
2
  export type HexString = `0x${string}`;
3
- /** Any string accepted as an address — either a `pq1…` bech32m address or a `0x…` hex address. */
3
+ /** A `pq1…` bech32m address string (Shell Chain canonical address format). */
4
4
  export type AddressLike = string;
5
5
  /** A single entry in an EIP-2930 access list. */
6
6
  export interface ShellAccessListItem {
@@ -18,7 +18,7 @@ export interface ShellTransactionRequest {
18
18
  chain_id: number;
19
19
  /** Sender account nonce. */
20
20
  nonce: number;
21
- /** Recipient address (pq1 or 0x…), or `null` for contract deployment. */
21
+ /** Recipient address (`pq1…` bech32m format), or `null` for contract deployment. */
22
22
  to: AddressLike | null;
23
23
  /** Transfer value as a hex-encoded bigint string, e.g. `"0xde0b6b3a7640000"`. */
24
24
  value: string;
@@ -237,6 +237,83 @@ export interface SignedShellTransaction {
237
237
  */
238
238
  aa_bundle?: AaBundle | null;
239
239
  }
240
+ /** Product-level transaction kind emitted by Shell Chain RPC. */
241
+ export type ShellKnownRpcTxType = "transfer" | "contractCreate" | "contractCall" | "aaBatch" | "blockGasReward" | "starkReward";
242
+ export type ShellRpcTxType = ShellKnownRpcTxType | (string & {});
243
+ /** Reward kind emitted for first-class system reward transactions. */
244
+ export type ShellRewardKind = "blockGasReward" | "starkReward";
245
+ /** Human-readable transaction label for wallets, explorers, and apps. */
246
+ export type ShellReadableTxType = "Transfer" | "Contract Create" | "Contract Call" | "AA Batch" | "Block Reward" | "STARK Reward" | "System" | "Transaction";
247
+ /** Shell Chain `eth_getTransactionByHash` transaction shape. */
248
+ export interface ShellRpcTransaction {
249
+ hash: HexString;
250
+ blockHash?: HexString | null;
251
+ blockNumber?: HexString | null;
252
+ transactionIndex?: HexString | null;
253
+ from: AddressLike;
254
+ to?: AddressLike | null;
255
+ value: HexString;
256
+ gas: HexString;
257
+ gasPrice: HexString;
258
+ maxFeePerGas?: HexString;
259
+ maxPriorityFeePerGas?: HexString;
260
+ nonce: HexString;
261
+ input: HexString;
262
+ chainId: HexString;
263
+ type: HexString;
264
+ shellType?: ShellRpcTxType | null;
265
+ rewardKind?: ShellRewardKind | null;
266
+ rewardLayer?: HexString | null;
267
+ rewardSourceHash?: HexString | null;
268
+ originalSize?: HexString | null;
269
+ compressedSize?: HexString | null;
270
+ }
271
+ /** Shell Chain transaction summary returned in block/address transaction lists. */
272
+ export interface ShellRpcTransactionSummary {
273
+ hash: HexString;
274
+ blockHash?: HexString | null;
275
+ blockNumber?: HexString | null;
276
+ transactionIndex?: HexString | null;
277
+ from?: AddressLike;
278
+ to?: AddressLike | null;
279
+ value?: HexString;
280
+ type?: HexString;
281
+ hasInput?: boolean;
282
+ shellType?: ShellRpcTxType | null;
283
+ rewardKind?: ShellRewardKind | null;
284
+ rewardLayer?: HexString | null;
285
+ rewardSourceHash?: HexString | null;
286
+ originalSize?: HexString | null;
287
+ compressedSize?: HexString | null;
288
+ }
289
+ /** Shell Chain transaction receipt shape, including system reward metadata. */
290
+ export interface ShellRpcReceipt {
291
+ transactionHash: HexString;
292
+ blockHash: HexString;
293
+ blockNumber: HexString;
294
+ transactionIndex: HexString;
295
+ from: AddressLike;
296
+ to?: AddressLike | null;
297
+ status: HexString;
298
+ gasUsed: HexString;
299
+ cumulativeGasUsed: HexString;
300
+ effectiveGasPrice: HexString;
301
+ contractAddress?: AddressLike | null;
302
+ logs: unknown[];
303
+ logsBloom: HexString;
304
+ type: HexString;
305
+ shellType?: ShellRpcTxType | null;
306
+ rewardKind?: ShellRewardKind | null;
307
+ }
308
+ /** Return a user-facing transaction type label without leaking EIP wire labels. */
309
+ export declare function formatShellRpcTxType(tx: {
310
+ type?: string | null;
311
+ to?: AddressLike | null;
312
+ hasInput?: boolean;
313
+ input?: string | null;
314
+ shellType?: ShellRpcTxType | null;
315
+ rewardKind?: ShellRewardKind | null;
316
+ }): ShellReadableTxType;
240
317
  /**
241
318
  * A single inner call entry in a `shell_estimateBatch` request.
242
319
  */
@@ -399,10 +476,18 @@ export interface ShellWitnessBundle {
399
476
  /** Paginated response from `shell_getTransactionsByAddress`. */
400
477
  export interface ShellTxByAddressPage {
401
478
  address: AddressLike;
479
+ /** Inclusive lower block bound used for the query, hex-encoded. */
480
+ from_block?: HexString;
481
+ /** Inclusive upper block snapshot used for the query, hex-encoded. */
482
+ to_block?: HexString;
483
+ /** Inclusive lower block bound used for the query, hex-encoded. */
484
+ fromBlock?: HexString;
485
+ /** Inclusive upper block snapshot used for the query, hex-encoded. */
486
+ toBlock?: HexString;
402
487
  page: number;
403
488
  limit: number;
404
489
  total: number;
405
- transactions: unknown[];
490
+ transactions: ShellRpcTransactionSummary[];
406
491
  }
407
492
  /** Parameters for `shell_sendTransaction`. */
408
493
  export interface ShellSendTransactionParams {
package/dist/types.js CHANGED
@@ -23,3 +23,36 @@ export const AA_MAX_PAYMASTER_CONTEXT = 256;
23
23
  * Added to intrinsic gas when a session key is used.
24
24
  */
25
25
  export const AA_SESSION_KEY_GAS_SURCHARGE = 20_000;
26
+ /** Return a user-facing transaction type label without leaking EIP wire labels. */
27
+ export function formatShellRpcTxType(tx) {
28
+ const shellType = tx.shellType ?? tx.rewardKind;
29
+ if (shellType === "blockGasReward")
30
+ return "Block Reward";
31
+ if (shellType === "starkReward")
32
+ return "STARK Reward";
33
+ if (shellType === "aaBatch")
34
+ return "AA Batch";
35
+ if (shellType === "contractCreate")
36
+ return "Contract Create";
37
+ if (shellType === "contractCall")
38
+ return "Contract Call";
39
+ if (shellType === "transfer")
40
+ return "Transfer";
41
+ if (shellType)
42
+ return "System";
43
+ if (tx.type === "0x7e")
44
+ return "AA Batch";
45
+ if (tx.to === null)
46
+ return "Contract Create";
47
+ if (tx.hasInput || (tx.input && tx.input !== "0x"))
48
+ return "Contract Call";
49
+ if (tx.type === "0x80")
50
+ return "System";
51
+ if (tx.type == null &&
52
+ tx.to === undefined &&
53
+ tx.hasInput === undefined &&
54
+ tx.input === undefined) {
55
+ return "Transaction";
56
+ }
57
+ return "Transfer";
58
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shell-sdk",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "TypeScript SDK for Shell Chain — build quantum-safe dApps before Q-Day.",
5
5
  "license": "MIT",
6
6
  "type": "module",