shell-sdk 0.1.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/LICENSE +21 -0
- package/README.md +773 -0
- package/dist/adapters.d.ts +155 -0
- package/dist/adapters.js +191 -0
- package/dist/address.d.ts +119 -0
- package/dist/address.js +220 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -0
- package/dist/keystore.d.ts +99 -0
- package/dist/keystore.js +166 -0
- package/dist/provider.d.ts +204 -0
- package/dist/provider.js +208 -0
- package/dist/signer.d.ts +161 -0
- package/dist/signer.js +188 -0
- package/dist/system-contracts.d.ts +65 -0
- package/dist/system-contracts.js +105 -0
- package/dist/transactions.d.ts +208 -0
- package/dist/transactions.js +250 -0
- package/dist/types.d.ts +140 -0
- package/dist/types.js +1 -0
- package/package.json +82 -0
package/dist/signer.d.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type BuildSignedTransactionOptions } from "./transactions.js";
|
|
2
|
+
import type { SignedShellTransaction, SignatureTypeName } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Maps each {@link SignatureTypeName} to its numeric algorithm ID used in
|
|
5
|
+
* address derivation and on-chain records.
|
|
6
|
+
*
|
|
7
|
+
* - `Dilithium3` → `0`
|
|
8
|
+
* - `MlDsa65` → `1`
|
|
9
|
+
* - `SphincsSha2256f` → `2`
|
|
10
|
+
*/
|
|
11
|
+
export declare const SIGNATURE_TYPE_IDS: Record<SignatureTypeName, number>;
|
|
12
|
+
/**
|
|
13
|
+
* Maps the `key_type` strings found in Shell keystore files to their
|
|
14
|
+
* corresponding {@link SignatureTypeName}.
|
|
15
|
+
*
|
|
16
|
+
* Keys are lowercase; matching is done after calling `.toLowerCase()`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const KEY_TYPE_TO_SIGNATURE_TYPE: Record<string, SignatureTypeName>;
|
|
19
|
+
/**
|
|
20
|
+
* Minimal interface that any post-quantum signing implementation must satisfy
|
|
21
|
+
* to be used with {@link ShellSigner}.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* class MyAdapter implements SignerAdapter {
|
|
26
|
+
* getPublicKey(): Uint8Array { … }
|
|
27
|
+
* async sign(message: Uint8Array): Promise<Uint8Array> { … }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export interface SignerAdapter {
|
|
32
|
+
/**
|
|
33
|
+
* Sign a raw message (the transaction hash bytes) and return the signature.
|
|
34
|
+
*
|
|
35
|
+
* @param message - The bytes to sign (typically an RLP-encoded tx hash).
|
|
36
|
+
* @returns The raw signature bytes.
|
|
37
|
+
*/
|
|
38
|
+
sign(message: Uint8Array): Promise<Uint8Array>;
|
|
39
|
+
/** Return the raw public key bytes for this signer. */
|
|
40
|
+
getPublicKey(): Uint8Array;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* High-level Shell Chain signer.
|
|
44
|
+
*
|
|
45
|
+
* Wraps a {@link SignerAdapter} and provides address derivation, signing, and
|
|
46
|
+
* transaction assembly for Shell Chain.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { MlDsa65Adapter } from "shell-sdk/adapters";
|
|
51
|
+
* import { ShellSigner } from "shell-sdk/signer";
|
|
52
|
+
*
|
|
53
|
+
* const adapter = MlDsa65Adapter.generate();
|
|
54
|
+
* const signer = new ShellSigner("MlDsa65", adapter);
|
|
55
|
+
*
|
|
56
|
+
* console.log(signer.getAddress()); // pq1…
|
|
57
|
+
* console.log(signer.getHexAddress()); // 0x…
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare class ShellSigner {
|
|
61
|
+
/** The signature algorithm this signer uses. */
|
|
62
|
+
readonly signatureType: SignatureTypeName;
|
|
63
|
+
/** The underlying adapter that performs the actual cryptographic operations. */
|
|
64
|
+
readonly adapter: SignerAdapter;
|
|
65
|
+
/**
|
|
66
|
+
* @param signatureType - The PQ algorithm name.
|
|
67
|
+
* @param adapter - An adapter providing `sign` and `getPublicKey`.
|
|
68
|
+
*/
|
|
69
|
+
constructor(signatureType: SignatureTypeName, adapter: SignerAdapter);
|
|
70
|
+
/**
|
|
71
|
+
* Numeric algorithm ID for this signer's signature type.
|
|
72
|
+
*
|
|
73
|
+
* Used in address derivation and in `rotateKey` calldata.
|
|
74
|
+
*/
|
|
75
|
+
get algorithmId(): number;
|
|
76
|
+
/** Return the raw public key bytes from the underlying adapter. */
|
|
77
|
+
getPublicKey(): Uint8Array;
|
|
78
|
+
/**
|
|
79
|
+
* Derive and return the `pq1…` bech32m address for this signer.
|
|
80
|
+
*
|
|
81
|
+
* The address is computed deterministically from the public key and algorithm ID.
|
|
82
|
+
*/
|
|
83
|
+
getAddress(): string;
|
|
84
|
+
/**
|
|
85
|
+
* Return the `0x…` hex representation of this signer's address.
|
|
86
|
+
*
|
|
87
|
+
* Equivalent to `normalizeHexAddress(signer.getAddress())`.
|
|
88
|
+
*/
|
|
89
|
+
getHexAddress(): `0x${string}`;
|
|
90
|
+
/**
|
|
91
|
+
* Sign a raw byte message with the underlying adapter.
|
|
92
|
+
*
|
|
93
|
+
* @param message - Bytes to sign (e.g. RLP-encoded transaction hash).
|
|
94
|
+
* @returns Raw signature bytes.
|
|
95
|
+
*/
|
|
96
|
+
sign(message: Uint8Array): Promise<Uint8Array>;
|
|
97
|
+
/**
|
|
98
|
+
* Sign a transaction hash and assemble a complete {@link SignedShellTransaction}.
|
|
99
|
+
*
|
|
100
|
+
* @param options.tx - The unsigned `ShellTransactionRequest` to embed.
|
|
101
|
+
* @param options.txHash - The bytes to sign (RLP-encoded EIP-1559 signing hash).
|
|
102
|
+
* @param options.includePublicKey - When `true`, embeds `sender_pubkey` in the
|
|
103
|
+
* result. Required for accounts that have not yet appeared on-chain.
|
|
104
|
+
* @returns A fully-signed transaction ready for {@link ShellProvider.sendTransaction}.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const signed = await signer.buildSignedTransaction({
|
|
109
|
+
* tx,
|
|
110
|
+
* txHash: rlpHashBytes,
|
|
111
|
+
* includePublicKey: true,
|
|
112
|
+
* });
|
|
113
|
+
* const hash = await provider.sendTransaction(signed);
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
buildSignedTransaction(options: Omit<BuildSignedTransactionOptions, "from" | "signature" | "signatureType"> & {
|
|
117
|
+
txHash: Uint8Array;
|
|
118
|
+
includePublicKey?: boolean;
|
|
119
|
+
}): Promise<SignedShellTransaction>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Convert a keystore `key_type` string to a {@link SignatureTypeName}.
|
|
123
|
+
*
|
|
124
|
+
* Matching is case-insensitive and ignores leading/trailing whitespace.
|
|
125
|
+
*
|
|
126
|
+
* @param keyType - The `key_type` field from a Shell keystore file (e.g. `"mldsa65"`).
|
|
127
|
+
* @returns The corresponding `SignatureTypeName`.
|
|
128
|
+
* @throws {Error} If the key type is not recognised.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* signatureTypeFromKeyType("mldsa65"); // "MlDsa65"
|
|
133
|
+
* signatureTypeFromKeyType("sphincs-sha2-256f"); // "SphincsSha2256f"
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export declare function signatureTypeFromKeyType(keyType: string): SignatureTypeName;
|
|
137
|
+
/**
|
|
138
|
+
* Convert a hex-encoded public key string to a `Uint8Array`.
|
|
139
|
+
*
|
|
140
|
+
* Accepts both `0x`-prefixed and bare hex strings.
|
|
141
|
+
*
|
|
142
|
+
* @param publicKeyHex - Hex-encoded public key (with or without `0x` prefix).
|
|
143
|
+
* @returns The decoded public key bytes.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* const pk = publicKeyFromHex("0xabcdef…");
|
|
148
|
+
* const pk = publicKeyFromHex("abcdef…");
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export declare function publicKeyFromHex(publicKeyHex: string): Uint8Array;
|
|
152
|
+
/**
|
|
153
|
+
* Build a {@link ShellSignature} object from raw signature bytes.
|
|
154
|
+
*
|
|
155
|
+
* A thin wrapper around {@link buildSignature} from `transactions.ts`.
|
|
156
|
+
*
|
|
157
|
+
* @param signatureType - The algorithm that produced the signature.
|
|
158
|
+
* @param signature - Raw signature bytes.
|
|
159
|
+
* @returns A `ShellSignature` with `sig_type` and `data` fields.
|
|
160
|
+
*/
|
|
161
|
+
export declare function buildShellSignature(signatureType: SignatureTypeName, signature: Uint8Array): import("./types.js").ShellSignature;
|
package/dist/signer.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShellSigner and SignerAdapter — the signing layer for Shell Chain transactions.
|
|
3
|
+
*
|
|
4
|
+
* `SignerAdapter` is a minimal interface for plugging in any PQ signing
|
|
5
|
+
* implementation. Concrete adapters live in `adapters.ts`.
|
|
6
|
+
*
|
|
7
|
+
* `ShellSigner` wraps an adapter and adds address derivation, transaction
|
|
8
|
+
* building, and Shell-specific helpers.
|
|
9
|
+
*
|
|
10
|
+
* @module signer
|
|
11
|
+
*/
|
|
12
|
+
import { hexToBytes } from "viem";
|
|
13
|
+
import { derivePqAddressFromPublicKey, normalizeHexAddress, normalizePqAddress } from "./address.js";
|
|
14
|
+
import { buildSignature, buildSignedTransaction, } from "./transactions.js";
|
|
15
|
+
/**
|
|
16
|
+
* Maps each {@link SignatureTypeName} to its numeric algorithm ID used in
|
|
17
|
+
* address derivation and on-chain records.
|
|
18
|
+
*
|
|
19
|
+
* - `Dilithium3` → `0`
|
|
20
|
+
* - `MlDsa65` → `1`
|
|
21
|
+
* - `SphincsSha2256f` → `2`
|
|
22
|
+
*/
|
|
23
|
+
export const SIGNATURE_TYPE_IDS = {
|
|
24
|
+
Dilithium3: 0,
|
|
25
|
+
MlDsa65: 1,
|
|
26
|
+
SphincsSha2256f: 2,
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Maps the `key_type` strings found in Shell keystore files to their
|
|
30
|
+
* corresponding {@link SignatureTypeName}.
|
|
31
|
+
*
|
|
32
|
+
* Keys are lowercase; matching is done after calling `.toLowerCase()`.
|
|
33
|
+
*/
|
|
34
|
+
export const KEY_TYPE_TO_SIGNATURE_TYPE = {
|
|
35
|
+
dilithium3: "Dilithium3",
|
|
36
|
+
"sphincs-sha2-256f": "SphincsSha2256f",
|
|
37
|
+
mldsa65: "MlDsa65",
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* High-level Shell Chain signer.
|
|
41
|
+
*
|
|
42
|
+
* Wraps a {@link SignerAdapter} and provides address derivation, signing, and
|
|
43
|
+
* transaction assembly for Shell Chain.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import { MlDsa65Adapter } from "shell-sdk/adapters";
|
|
48
|
+
* import { ShellSigner } from "shell-sdk/signer";
|
|
49
|
+
*
|
|
50
|
+
* const adapter = MlDsa65Adapter.generate();
|
|
51
|
+
* const signer = new ShellSigner("MlDsa65", adapter);
|
|
52
|
+
*
|
|
53
|
+
* console.log(signer.getAddress()); // pq1…
|
|
54
|
+
* console.log(signer.getHexAddress()); // 0x…
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export class ShellSigner {
|
|
58
|
+
/** The signature algorithm this signer uses. */
|
|
59
|
+
signatureType;
|
|
60
|
+
/** The underlying adapter that performs the actual cryptographic operations. */
|
|
61
|
+
adapter;
|
|
62
|
+
/**
|
|
63
|
+
* @param signatureType - The PQ algorithm name.
|
|
64
|
+
* @param adapter - An adapter providing `sign` and `getPublicKey`.
|
|
65
|
+
*/
|
|
66
|
+
constructor(signatureType, adapter) {
|
|
67
|
+
this.signatureType = signatureType;
|
|
68
|
+
this.adapter = adapter;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Numeric algorithm ID for this signer's signature type.
|
|
72
|
+
*
|
|
73
|
+
* Used in address derivation and in `rotateKey` calldata.
|
|
74
|
+
*/
|
|
75
|
+
get algorithmId() {
|
|
76
|
+
return SIGNATURE_TYPE_IDS[this.signatureType];
|
|
77
|
+
}
|
|
78
|
+
/** Return the raw public key bytes from the underlying adapter. */
|
|
79
|
+
getPublicKey() {
|
|
80
|
+
return this.adapter.getPublicKey();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Derive and return the `pq1…` bech32m address for this signer.
|
|
84
|
+
*
|
|
85
|
+
* The address is computed deterministically from the public key and algorithm ID.
|
|
86
|
+
*/
|
|
87
|
+
getAddress() {
|
|
88
|
+
return derivePqAddressFromPublicKey(this.getPublicKey(), this.algorithmId);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Return the `0x…` hex representation of this signer's address.
|
|
92
|
+
*
|
|
93
|
+
* Equivalent to `normalizeHexAddress(signer.getAddress())`.
|
|
94
|
+
*/
|
|
95
|
+
getHexAddress() {
|
|
96
|
+
return normalizeHexAddress(this.getAddress());
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Sign a raw byte message with the underlying adapter.
|
|
100
|
+
*
|
|
101
|
+
* @param message - Bytes to sign (e.g. RLP-encoded transaction hash).
|
|
102
|
+
* @returns Raw signature bytes.
|
|
103
|
+
*/
|
|
104
|
+
async sign(message) {
|
|
105
|
+
return this.adapter.sign(message);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Sign a transaction hash and assemble a complete {@link SignedShellTransaction}.
|
|
109
|
+
*
|
|
110
|
+
* @param options.tx - The unsigned `ShellTransactionRequest` to embed.
|
|
111
|
+
* @param options.txHash - The bytes to sign (RLP-encoded EIP-1559 signing hash).
|
|
112
|
+
* @param options.includePublicKey - When `true`, embeds `sender_pubkey` in the
|
|
113
|
+
* result. Required for accounts that have not yet appeared on-chain.
|
|
114
|
+
* @returns A fully-signed transaction ready for {@link ShellProvider.sendTransaction}.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const signed = await signer.buildSignedTransaction({
|
|
119
|
+
* tx,
|
|
120
|
+
* txHash: rlpHashBytes,
|
|
121
|
+
* includePublicKey: true,
|
|
122
|
+
* });
|
|
123
|
+
* const hash = await provider.sendTransaction(signed);
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
async buildSignedTransaction(options) {
|
|
127
|
+
const signature = await this.sign(options.txHash);
|
|
128
|
+
return buildSignedTransaction({
|
|
129
|
+
from: normalizePqAddress(this.getAddress()),
|
|
130
|
+
tx: options.tx,
|
|
131
|
+
signature,
|
|
132
|
+
signatureType: this.signatureType,
|
|
133
|
+
senderPubkey: options.includePublicKey ? this.getPublicKey() : undefined,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Convert a keystore `key_type` string to a {@link SignatureTypeName}.
|
|
139
|
+
*
|
|
140
|
+
* Matching is case-insensitive and ignores leading/trailing whitespace.
|
|
141
|
+
*
|
|
142
|
+
* @param keyType - The `key_type` field from a Shell keystore file (e.g. `"mldsa65"`).
|
|
143
|
+
* @returns The corresponding `SignatureTypeName`.
|
|
144
|
+
* @throws {Error} If the key type is not recognised.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* signatureTypeFromKeyType("mldsa65"); // "MlDsa65"
|
|
149
|
+
* signatureTypeFromKeyType("sphincs-sha2-256f"); // "SphincsSha2256f"
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export function signatureTypeFromKeyType(keyType) {
|
|
153
|
+
const normalized = keyType.trim().toLowerCase();
|
|
154
|
+
const value = KEY_TYPE_TO_SIGNATURE_TYPE[normalized];
|
|
155
|
+
if (!value) {
|
|
156
|
+
throw new Error(`unsupported key type: ${keyType}`);
|
|
157
|
+
}
|
|
158
|
+
return value;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Convert a hex-encoded public key string to a `Uint8Array`.
|
|
162
|
+
*
|
|
163
|
+
* Accepts both `0x`-prefixed and bare hex strings.
|
|
164
|
+
*
|
|
165
|
+
* @param publicKeyHex - Hex-encoded public key (with or without `0x` prefix).
|
|
166
|
+
* @returns The decoded public key bytes.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```typescript
|
|
170
|
+
* const pk = publicKeyFromHex("0xabcdef…");
|
|
171
|
+
* const pk = publicKeyFromHex("abcdef…");
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export function publicKeyFromHex(publicKeyHex) {
|
|
175
|
+
return hexToBytes(`0x${publicKeyHex.replace(/^0x/i, "")}`);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Build a {@link ShellSignature} object from raw signature bytes.
|
|
179
|
+
*
|
|
180
|
+
* A thin wrapper around {@link buildSignature} from `transactions.ts`.
|
|
181
|
+
*
|
|
182
|
+
* @param signatureType - The algorithm that produced the signature.
|
|
183
|
+
* @param signature - Raw signature bytes.
|
|
184
|
+
* @returns A `ShellSignature` with `sig_type` and `data` fields.
|
|
185
|
+
*/
|
|
186
|
+
export function buildShellSignature(signatureType, signature) {
|
|
187
|
+
return buildSignature(signatureType, signature);
|
|
188
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
/** `pq1…` bech32m address of the ValidatorRegistry system contract. */
|
|
7
|
+
export declare const validatorRegistryAddress: string;
|
|
8
|
+
/** `pq1…` bech32m address of the AccountManager system contract. */
|
|
9
|
+
export declare const accountManagerAddress: string;
|
|
10
|
+
/** 4-byte ABI function selector for `rotateKey(bytes,uint8)`. */
|
|
11
|
+
export declare const rotateKeySelector: `0x${string}`;
|
|
12
|
+
/** 4-byte ABI function selector for `setValidationCode(bytes32)`. */
|
|
13
|
+
export declare const setValidationCodeSelector: `0x${string}`;
|
|
14
|
+
/** 4-byte ABI function selector for `clearValidationCode()`. */
|
|
15
|
+
export declare const clearValidationCodeSelector: `0x${string}`;
|
|
16
|
+
/**
|
|
17
|
+
* ABI-encode calldata for `rotateKey(bytes publicKey, uint8 algorithmId)`.
|
|
18
|
+
*
|
|
19
|
+
* @param publicKey - Raw bytes of the new public key.
|
|
20
|
+
* @param algorithmId - Numeric algorithm ID (Dilithium3=0, MlDsa65=1, SphincsSha2256f=2).
|
|
21
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const data = encodeRotateKeyCalldata(newPublicKey, 1 /* MlDsa65 *\/);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function encodeRotateKeyCalldata(publicKey: Uint8Array, algorithmId: number): HexString;
|
|
29
|
+
/**
|
|
30
|
+
* ABI-encode calldata for `setValidationCode(bytes32 codeHash)`.
|
|
31
|
+
*
|
|
32
|
+
* @param codeHash - `bytes32` hash of the custom validation contract.
|
|
33
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const data = encodeSetValidationCodeCalldata("0xabc123…");
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function encodeSetValidationCodeCalldata(codeHash: HexString): HexString;
|
|
41
|
+
/**
|
|
42
|
+
* Return the 4-byte selector for `clearValidationCode()`.
|
|
43
|
+
*
|
|
44
|
+
* No parameters are encoded since the function takes no arguments.
|
|
45
|
+
*
|
|
46
|
+
* @returns The 4-byte function selector as a `HexString`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function encodeClearValidationCodeCalldata(): HexString;
|
|
49
|
+
/**
|
|
50
|
+
* Return `true` if `address` refers to one of the Shell system contracts.
|
|
51
|
+
*
|
|
52
|
+
* Accepts both `pq1…` and `0x…` forms for the AccountManager and
|
|
53
|
+
* ValidatorRegistry addresses.
|
|
54
|
+
*
|
|
55
|
+
* @param address - Address to test (any format accepted by `AddressLike`).
|
|
56
|
+
* @returns `true` if the address matches AccountManager or ValidatorRegistry.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* isSystemContractAddress("0x0000000000000000000000000000000000000002"); // true
|
|
61
|
+
* isSystemContractAddress(accountManagerAddress); // true
|
|
62
|
+
* isSystemContractAddress("pq1someuser…"); // false
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function isSystemContractAddress(address: AddressLike): boolean;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System contract addresses and calldata encoders for Shell Chain.
|
|
3
|
+
*
|
|
4
|
+
* Shell Chain ships two built-in system contracts at well-known addresses:
|
|
5
|
+
*
|
|
6
|
+
* - **ValidatorRegistry** (`0x…0001`) — manages the set of active validators.
|
|
7
|
+
* - **AccountManager** (`0x…0002`) — handles per-account key rotation and
|
|
8
|
+
* custom AA validation code.
|
|
9
|
+
*
|
|
10
|
+
* Transactions targeting these contracts should be built with the helpers in
|
|
11
|
+
* `transactions.ts` (e.g. {@link buildRotateKeyTransaction}).
|
|
12
|
+
*
|
|
13
|
+
* @module system-contracts
|
|
14
|
+
*/
|
|
15
|
+
import { bytesToHex, encodeAbiParameters, keccak256, toBytes } from "viem";
|
|
16
|
+
import { bytesToPqAddress } from "./address.js";
|
|
17
|
+
const SYSTEM_ADDRESS_LENGTH = 20;
|
|
18
|
+
function systemAddress(lastByte) {
|
|
19
|
+
const bytes = new Uint8Array(SYSTEM_ADDRESS_LENGTH);
|
|
20
|
+
bytes[SYSTEM_ADDRESS_LENGTH - 1] = lastByte;
|
|
21
|
+
return bytes;
|
|
22
|
+
}
|
|
23
|
+
function selector(signature) {
|
|
24
|
+
return keccak256(toBytes(signature)).slice(0, 10);
|
|
25
|
+
}
|
|
26
|
+
/** Hex address of the ValidatorRegistry system contract (`0x…0001`). */
|
|
27
|
+
export const validatorRegistryHexAddress = "0x0000000000000000000000000000000000000001";
|
|
28
|
+
/** Hex address of the AccountManager system contract (`0x…0002`). */
|
|
29
|
+
export const accountManagerHexAddress = "0x0000000000000000000000000000000000000002";
|
|
30
|
+
/** `pq1…` bech32m address of the ValidatorRegistry system contract. */
|
|
31
|
+
export const validatorRegistryAddress = bytesToPqAddress(systemAddress(1));
|
|
32
|
+
/** `pq1…` bech32m address of the AccountManager system contract. */
|
|
33
|
+
export const accountManagerAddress = bytesToPqAddress(systemAddress(2));
|
|
34
|
+
/** 4-byte ABI function selector for `rotateKey(bytes,uint8)`. */
|
|
35
|
+
export const rotateKeySelector = selector("rotateKey(bytes,uint8)");
|
|
36
|
+
/** 4-byte ABI function selector for `setValidationCode(bytes32)`. */
|
|
37
|
+
export const setValidationCodeSelector = selector("setValidationCode(bytes32)");
|
|
38
|
+
/** 4-byte ABI function selector for `clearValidationCode()`. */
|
|
39
|
+
export const clearValidationCodeSelector = selector("clearValidationCode()");
|
|
40
|
+
/**
|
|
41
|
+
* ABI-encode calldata for `rotateKey(bytes publicKey, uint8 algorithmId)`.
|
|
42
|
+
*
|
|
43
|
+
* @param publicKey - Raw bytes of the new public key.
|
|
44
|
+
* @param algorithmId - Numeric algorithm ID (Dilithium3=0, MlDsa65=1, SphincsSha2256f=2).
|
|
45
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const data = encodeRotateKeyCalldata(newPublicKey, 1 /* MlDsa65 *\/);
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function encodeRotateKeyCalldata(publicKey, algorithmId) {
|
|
53
|
+
const encoded = encodeAbiParameters([
|
|
54
|
+
{ type: "bytes" },
|
|
55
|
+
{ type: "uint8" },
|
|
56
|
+
], [bytesToHex(publicKey), algorithmId]);
|
|
57
|
+
return `${rotateKeySelector}${encoded.slice(2)}`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* ABI-encode calldata for `setValidationCode(bytes32 codeHash)`.
|
|
61
|
+
*
|
|
62
|
+
* @param codeHash - `bytes32` hash of the custom validation contract.
|
|
63
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const data = encodeSetValidationCodeCalldata("0xabc123…");
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function encodeSetValidationCodeCalldata(codeHash) {
|
|
71
|
+
const encoded = encodeAbiParameters([{ type: "bytes32" }], [codeHash]);
|
|
72
|
+
return `${setValidationCodeSelector}${encoded.slice(2)}`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Return the 4-byte selector for `clearValidationCode()`.
|
|
76
|
+
*
|
|
77
|
+
* No parameters are encoded since the function takes no arguments.
|
|
78
|
+
*
|
|
79
|
+
* @returns The 4-byte function selector as a `HexString`.
|
|
80
|
+
*/
|
|
81
|
+
export function encodeClearValidationCodeCalldata() {
|
|
82
|
+
return clearValidationCodeSelector;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Return `true` if `address` refers to one of the Shell system contracts.
|
|
86
|
+
*
|
|
87
|
+
* Accepts both `pq1…` and `0x…` forms for the AccountManager and
|
|
88
|
+
* ValidatorRegistry addresses.
|
|
89
|
+
*
|
|
90
|
+
* @param address - Address to test (any format accepted by `AddressLike`).
|
|
91
|
+
* @returns `true` if the address matches AccountManager or ValidatorRegistry.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* isSystemContractAddress("0x0000000000000000000000000000000000000002"); // true
|
|
96
|
+
* isSystemContractAddress(accountManagerAddress); // true
|
|
97
|
+
* isSystemContractAddress("pq1someuser…"); // false
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export function isSystemContractAddress(address) {
|
|
101
|
+
return (address === accountManagerAddress ||
|
|
102
|
+
address === validatorRegistryAddress ||
|
|
103
|
+
address === accountManagerHexAddress ||
|
|
104
|
+
address === validatorRegistryHexAddress);
|
|
105
|
+
}
|