shell-sdk 0.4.1 → 0.6.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/CHANGELOG.md +26 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/system-contracts.d.ts +72 -0
- package/dist/system-contracts.js +114 -2
- package/dist/transactions.d.ts +84 -1
- package/dist/transactions.js +68 -1
- package/dist/types.d.ts +107 -2
- package/dist/types.js +12 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0] — 2026-04-26
|
|
4
|
+
|
|
5
|
+
### Added — AA Phase 2 (matches `shell-chain v0.19.0`)
|
|
6
|
+
|
|
7
|
+
#### Types (`types.ts`)
|
|
8
|
+
- **`SessionAuth`** interface: session PQ key authorization struct with `session_pubkey`, `session_algo`, `target?`, `value_cap`, `expiry_block`, `root_signature`, `session_signature`.
|
|
9
|
+
- **`GuardianConfig`** interface: on-chain guardian set descriptor.
|
|
10
|
+
- **`RecoveryProposal`** interface: active recovery proposal with votes and maturity block.
|
|
11
|
+
- **`AaBundle`** extended: added `paymaster_context?: number[] | null` (contract paymaster opaque bytes) and `session_auth?: SessionAuth | null` (session key authorization).
|
|
12
|
+
- Constants: `AA_MAX_PAYMASTER_CONTEXT = 256`, `AA_SESSION_KEY_GAS_SURCHARGE = 20_000`.
|
|
13
|
+
|
|
14
|
+
#### Transaction builders (`transactions.ts`)
|
|
15
|
+
- **`buildContractPaymasterTransaction`**: builds an AA batch tx with a contract paymaster (sets `paymaster_context`). Mutually exclusive with `paymaster_signature`.
|
|
16
|
+
- **`buildSessionKeyTransaction`**: builds an AA batch tx authorized by a session key (sets `session_auth`).
|
|
17
|
+
- **`hashBatchTransaction`**: updated signing hash to include `paymaster_context` as the 3rd RLP field in `bundleSigningFields`, matching `shell-chain` `AaBundle::encode_for_signing`.
|
|
18
|
+
|
|
19
|
+
#### System contract calldata (`system-contracts.ts`)
|
|
20
|
+
- **`setGuardiansSelector`** + **`encodeSetGuardiansCalldata`**: `setGuardians(address[],uint8,uint64)`.
|
|
21
|
+
- **`submitRecoverySelector`** + **`encodeSubmitRecoveryCalldata`**: `submitRecovery(address,bytes,uint8)`.
|
|
22
|
+
- **`executeRecoverySelector`** + **`encodeExecuteRecoveryCalldata`**: `executeRecovery(address)`.
|
|
23
|
+
- **`cancelRecoverySelector`** + **`encodeCancelRecoveryCalldata`**: `cancelRecovery(address)`.
|
|
24
|
+
|
|
25
|
+
### Compatibility
|
|
26
|
+
- Fully backwards-compatible with SDK `0.4.x` usage. All new fields are optional.
|
|
27
|
+
- New AA Phase 2 features require `shell-chain v0.19.0+`.
|
|
28
|
+
|
|
3
29
|
## [0.4.1] — 2026-04-25
|
|
4
30
|
|
|
5
31
|
### Changed
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { bytesToHexAddress, PQ_ADDRESS_HRP, PQ_ADDRESS_LENGTH, PQ_ADDRESS_VERSION_V1, bytesToPqAddress, derivePqAddressFromPublicKey, isPqAddress, normalizeHexAddress, normalizePqAddress, pqAddressVersion, pqAddressToBytes, } from "./address.js";
|
|
2
2
|
export { createShellProvider, createShellPublicClient, createShellWsClient, ShellProvider, shellDevnet, type CreateShellPublicClientOptions, } from "./provider.js";
|
|
3
|
-
export { accountManagerAddress, accountManagerHexAddress, clearValidationCodeSelector, encodeClearValidationCodeCalldata, encodeRotateKeyCalldata, encodeSetValidationCodeCalldata, isSystemContractAddress, rotateKeySelector, setValidationCodeSelector, validatorRegistryAddress, validatorRegistryHexAddress, } from "./system-contracts.js";
|
|
4
|
-
export { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS, buildBatchTransaction, buildClearValidationCodeTransaction, buildInnerCall, buildInnerTransfer, buildRotateKeyTransaction, 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 BuildSponsoredTransactionOptions, } from "./transactions.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";
|
|
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
|
-
export
|
|
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";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { bytesToHexAddress, PQ_ADDRESS_HRP, PQ_ADDRESS_LENGTH, PQ_ADDRESS_VERSION_V1, bytesToPqAddress, derivePqAddressFromPublicKey, isPqAddress, normalizeHexAddress, normalizePqAddress, pqAddressVersion, pqAddressToBytes, } from "./address.js";
|
|
2
2
|
export { createShellProvider, createShellPublicClient, createShellWsClient, ShellProvider, shellDevnet, } from "./provider.js";
|
|
3
|
-
export { accountManagerAddress, accountManagerHexAddress, clearValidationCodeSelector, encodeClearValidationCodeCalldata, encodeRotateKeyCalldata, encodeSetValidationCodeCalldata, isSystemContractAddress, rotateKeySelector, setValidationCodeSelector, validatorRegistryAddress, validatorRegistryHexAddress, } from "./system-contracts.js";
|
|
4
|
-
export { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS, buildBatchTransaction, buildClearValidationCodeTransaction, buildInnerCall, buildInnerTransfer, buildRotateKeyTransaction, 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";
|
|
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";
|
|
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
|
+
export { AA_MAX_PAYMASTER_CONTEXT, AA_SESSION_KEY_GAS_SURCHARGE } from "./types.js";
|
|
@@ -13,6 +13,14 @@ export declare const rotateKeySelector: `0x${string}`;
|
|
|
13
13
|
export declare const setValidationCodeSelector: `0x${string}`;
|
|
14
14
|
/** 4-byte ABI function selector for `clearValidationCode()`. */
|
|
15
15
|
export declare const clearValidationCodeSelector: `0x${string}`;
|
|
16
|
+
/** 4-byte ABI function selector for `setGuardians(address[],uint8,uint64)`. */
|
|
17
|
+
export declare const setGuardiansSelector: `0x${string}`;
|
|
18
|
+
/** 4-byte ABI function selector for `submitRecovery(address,bytes,uint8)`. */
|
|
19
|
+
export declare const submitRecoverySelector: `0x${string}`;
|
|
20
|
+
/** 4-byte ABI function selector for `executeRecovery(address)`. */
|
|
21
|
+
export declare const executeRecoverySelector: `0x${string}`;
|
|
22
|
+
/** 4-byte ABI function selector for `cancelRecovery(address)`. */
|
|
23
|
+
export declare const cancelRecoverySelector: `0x${string}`;
|
|
16
24
|
/**
|
|
17
25
|
* ABI-encode calldata for `rotateKey(bytes publicKey, uint8 algorithmId)`.
|
|
18
26
|
*
|
|
@@ -63,3 +71,67 @@ export declare function encodeClearValidationCodeCalldata(): HexString;
|
|
|
63
71
|
* ```
|
|
64
72
|
*/
|
|
65
73
|
export declare function isSystemContractAddress(address: AddressLike): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* ABI-encode calldata for `setGuardians(address[] guardians, uint8 threshold, uint64 timelock)`.
|
|
76
|
+
*
|
|
77
|
+
* Configures the guardian recovery set for the caller's account. Only the
|
|
78
|
+
* account owner can call this (the call must be made as an inner call from
|
|
79
|
+
* the owner's AA bundle, or as a direct transaction).
|
|
80
|
+
*
|
|
81
|
+
* @param guardians - Array of guardian addresses (1..5). May be hex or `pq1…` form.
|
|
82
|
+
* @param threshold - k-of-n required votes (1 ≤ threshold ≤ guardians.length).
|
|
83
|
+
* @param timelock - Minimum blocks between threshold-reach and execution (≥ 100).
|
|
84
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const data = encodeSetGuardiansCalldata(
|
|
89
|
+
* ["0xGuardian1…", "0xGuardian2…", "0xGuardian3…"],
|
|
90
|
+
* 2, // 2-of-3 threshold
|
|
91
|
+
* 100, // 100-block timelock
|
|
92
|
+
* );
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function encodeSetGuardiansCalldata(guardians: AddressLike[], threshold: number, timelock: number): HexString;
|
|
96
|
+
/**
|
|
97
|
+
* ABI-encode calldata for `submitRecovery(address account, bytes newPubkey, uint8 newAlgo)`.
|
|
98
|
+
*
|
|
99
|
+
* Called by a guardian to vote for a new PQ public key on behalf of `account`.
|
|
100
|
+
* When k-of-n threshold is reached, the proposal becomes executable after
|
|
101
|
+
* `timelock` blocks.
|
|
102
|
+
*
|
|
103
|
+
* @param account - Account being recovered (0x hex or `pq1…` form).
|
|
104
|
+
* @param newPubkey - Raw bytes of the new PQ public key.
|
|
105
|
+
* @param newAlgo - Algorithm ID for the new key (ML-DSA-65 = 0, etc.).
|
|
106
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const data = encodeSubmitRecoveryCalldata(
|
|
111
|
+
* "0xAccountAddress…",
|
|
112
|
+
* newPubkeyBytes,
|
|
113
|
+
* 0, // ML-DSA-65
|
|
114
|
+
* );
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare function encodeSubmitRecoveryCalldata(account: AddressLike, newPubkey: Uint8Array, newAlgo: number): HexString;
|
|
118
|
+
/**
|
|
119
|
+
* ABI-encode calldata for `executeRecovery(address account)`.
|
|
120
|
+
*
|
|
121
|
+
* Can be called by anyone once the recovery proposal has reached maturity
|
|
122
|
+
* (`current_block >= maturity_block && maturity_block != 0`).
|
|
123
|
+
*
|
|
124
|
+
* @param account - Account whose recovery proposal to execute.
|
|
125
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
126
|
+
*/
|
|
127
|
+
export declare function encodeExecuteRecoveryCalldata(account: AddressLike): HexString;
|
|
128
|
+
/**
|
|
129
|
+
* ABI-encode calldata for `cancelRecovery(address account)`.
|
|
130
|
+
*
|
|
131
|
+
* Owner-only: removes the active recovery proposal. Useful if the account
|
|
132
|
+
* owner regains access before the timelock expires.
|
|
133
|
+
*
|
|
134
|
+
* @param account - Account whose recovery proposal to cancel (must be caller).
|
|
135
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
136
|
+
*/
|
|
137
|
+
export declare function encodeCancelRecoveryCalldata(account: AddressLike): HexString;
|
package/dist/system-contracts.js
CHANGED
|
@@ -4,12 +4,17 @@
|
|
|
4
4
|
* Shell Chain ships two built-in system contracts at well-known addresses:
|
|
5
5
|
*
|
|
6
6
|
* - **ValidatorRegistry** (`0x…0001`) — manages the set of active validators.
|
|
7
|
-
* - **AccountManager** (`0x…0002`) — handles per-account key rotation
|
|
8
|
-
* custom AA validation code.
|
|
7
|
+
* - **AccountManager** (`0x…0002`) — handles per-account key rotation,
|
|
8
|
+
* custom AA validation code, and (v0.19.0+) guardian recovery.
|
|
9
9
|
*
|
|
10
10
|
* Transactions targeting these contracts should be built with the helpers in
|
|
11
11
|
* `transactions.ts` (e.g. {@link buildRotateKeyTransaction}).
|
|
12
12
|
*
|
|
13
|
+
* ## AA Phase 2 — Guardian Recovery (v0.19.0-dev)
|
|
14
|
+
*
|
|
15
|
+
* Use {@link encodeSetGuardiansCalldata}, {@link encodeSubmitRecoveryCalldata},
|
|
16
|
+
* {@link encodeExecuteRecoveryCalldata}, and {@link encodeCancelRecoveryCalldata}.
|
|
17
|
+
*
|
|
13
18
|
* @module system-contracts
|
|
14
19
|
*/
|
|
15
20
|
import { bytesToHex, encodeAbiParameters, keccak256, toBytes } from "viem";
|
|
@@ -37,6 +42,17 @@ export const rotateKeySelector = selector("rotateKey(bytes,uint8)");
|
|
|
37
42
|
export const setValidationCodeSelector = selector("setValidationCode(bytes32)");
|
|
38
43
|
/** 4-byte ABI function selector for `clearValidationCode()`. */
|
|
39
44
|
export const clearValidationCodeSelector = selector("clearValidationCode()");
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// AA Phase 2 — Guardian Recovery selectors (v0.19.0-dev)
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
/** 4-byte ABI function selector for `setGuardians(address[],uint8,uint64)`. */
|
|
49
|
+
export const setGuardiansSelector = selector("setGuardians(address[],uint8,uint64)");
|
|
50
|
+
/** 4-byte ABI function selector for `submitRecovery(address,bytes,uint8)`. */
|
|
51
|
+
export const submitRecoverySelector = selector("submitRecovery(address,bytes,uint8)");
|
|
52
|
+
/** 4-byte ABI function selector for `executeRecovery(address)`. */
|
|
53
|
+
export const executeRecoverySelector = selector("executeRecovery(address)");
|
|
54
|
+
/** 4-byte ABI function selector for `cancelRecovery(address)`. */
|
|
55
|
+
export const cancelRecoverySelector = selector("cancelRecovery(address)");
|
|
40
56
|
/**
|
|
41
57
|
* ABI-encode calldata for `rotateKey(bytes publicKey, uint8 algorithmId)`.
|
|
42
58
|
*
|
|
@@ -103,3 +119,99 @@ export function isSystemContractAddress(address) {
|
|
|
103
119
|
address === accountManagerHexAddress ||
|
|
104
120
|
address === validatorRegistryHexAddress);
|
|
105
121
|
}
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// AA Phase 2 — Guardian Recovery calldata encoders (v0.19.0-dev)
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
/**
|
|
126
|
+
* ABI-encode calldata for `setGuardians(address[] guardians, uint8 threshold, uint64 timelock)`.
|
|
127
|
+
*
|
|
128
|
+
* Configures the guardian recovery set for the caller's account. Only the
|
|
129
|
+
* account owner can call this (the call must be made as an inner call from
|
|
130
|
+
* the owner's AA bundle, or as a direct transaction).
|
|
131
|
+
*
|
|
132
|
+
* @param guardians - Array of guardian addresses (1..5). May be hex or `pq1…` form.
|
|
133
|
+
* @param threshold - k-of-n required votes (1 ≤ threshold ≤ guardians.length).
|
|
134
|
+
* @param timelock - Minimum blocks between threshold-reach and execution (≥ 100).
|
|
135
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const data = encodeSetGuardiansCalldata(
|
|
140
|
+
* ["0xGuardian1…", "0xGuardian2…", "0xGuardian3…"],
|
|
141
|
+
* 2, // 2-of-3 threshold
|
|
142
|
+
* 100, // 100-block timelock
|
|
143
|
+
* );
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
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
|
+
});
|
|
152
|
+
const encoded = encodeAbiParameters([{ type: "address[]" }, { type: "uint8" }, { type: "uint64" }], [hexGuardians, threshold, BigInt(timelock)]);
|
|
153
|
+
return `${setGuardiansSelector}${encoded.slice(2)}`;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* ABI-encode calldata for `submitRecovery(address account, bytes newPubkey, uint8 newAlgo)`.
|
|
157
|
+
*
|
|
158
|
+
* Called by a guardian to vote for a new PQ public key on behalf of `account`.
|
|
159
|
+
* When k-of-n threshold is reached, the proposal becomes executable after
|
|
160
|
+
* `timelock` blocks.
|
|
161
|
+
*
|
|
162
|
+
* @param account - Account being recovered (0x hex or `pq1…` form).
|
|
163
|
+
* @param newPubkey - Raw bytes of the new PQ public key.
|
|
164
|
+
* @param newAlgo - Algorithm ID for the new key (ML-DSA-65 = 0, etc.).
|
|
165
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const data = encodeSubmitRecoveryCalldata(
|
|
170
|
+
* "0xAccountAddress…",
|
|
171
|
+
* newPubkeyBytes,
|
|
172
|
+
* 0, // ML-DSA-65
|
|
173
|
+
* );
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export function encodeSubmitRecoveryCalldata(account, newPubkey, newAlgo) {
|
|
177
|
+
const hexAccount = normaliseToHex(account);
|
|
178
|
+
const encoded = encodeAbiParameters([{ type: "address" }, { type: "bytes" }, { type: "uint8" }], [hexAccount, bytesToHex(newPubkey), newAlgo]);
|
|
179
|
+
return `${submitRecoverySelector}${encoded.slice(2)}`;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* ABI-encode calldata for `executeRecovery(address account)`.
|
|
183
|
+
*
|
|
184
|
+
* Can be called by anyone once the recovery proposal has reached maturity
|
|
185
|
+
* (`current_block >= maturity_block && maturity_block != 0`).
|
|
186
|
+
*
|
|
187
|
+
* @param account - Account whose recovery proposal to execute.
|
|
188
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
189
|
+
*/
|
|
190
|
+
export function encodeExecuteRecoveryCalldata(account) {
|
|
191
|
+
const hexAccount = normaliseToHex(account);
|
|
192
|
+
const encoded = encodeAbiParameters([{ type: "address" }], [hexAccount]);
|
|
193
|
+
return `${executeRecoverySelector}${encoded.slice(2)}`;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* ABI-encode calldata for `cancelRecovery(address account)`.
|
|
197
|
+
*
|
|
198
|
+
* Owner-only: removes the active recovery proposal. Useful if the account
|
|
199
|
+
* owner regains access before the timelock expires.
|
|
200
|
+
*
|
|
201
|
+
* @param account - Account whose recovery proposal to cancel (must be caller).
|
|
202
|
+
* @returns `HexString` with the 4-byte selector prepended.
|
|
203
|
+
*/
|
|
204
|
+
export function encodeCancelRecoveryCalldata(account) {
|
|
205
|
+
const hexAccount = normaliseToHex(account);
|
|
206
|
+
const encoded = encodeAbiParameters([{ type: "address" }], [hexAccount]);
|
|
207
|
+
return `${cancelRecoverySelector}${encoded.slice(2)}`;
|
|
208
|
+
}
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Internal helpers
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
function normaliseToHex(address) {
|
|
213
|
+
if (typeof address !== "string") {
|
|
214
|
+
return bytesToHex(address);
|
|
215
|
+
}
|
|
216
|
+
return (address.startsWith("0x") ? address : `0x${address}`);
|
|
217
|
+
}
|
package/dist/transactions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AaBundle, AaInnerCall, AddressLike, HexString, ShellSignature, ShellTransactionRequest, SignedShellTransaction, SignatureTypeName } from "./types.js";
|
|
1
|
+
import type { AaBundle, AaInnerCall, AddressLike, HexString, SessionAuth, ShellSignature, ShellTransactionRequest, SignedShellTransaction, SignatureTypeName } from "./types.js";
|
|
2
2
|
import { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS } from "./types.js";
|
|
3
3
|
export { AA_BUNDLE_TX_TYPE, AA_MAX_INNER_CALLS };
|
|
4
4
|
/** Default transaction type: `2` (EIP-1559). */
|
|
@@ -334,3 +334,86 @@ export declare function buildInnerTransfer(to: AddressLike, value: bigint, gasLi
|
|
|
334
334
|
* @returns An `AaInnerCall` ready for use in {@link buildBatchTransaction}.
|
|
335
335
|
*/
|
|
336
336
|
export declare function buildInnerCall(to: AddressLike, data: HexString, gasLimit: number, value?: bigint): AaInnerCall;
|
|
337
|
+
/**
|
|
338
|
+
* Options for {@link buildContractPaymasterTransaction}.
|
|
339
|
+
*
|
|
340
|
+
* Extends {@link BuildBatchTransactionOptions} with contract paymaster fields.
|
|
341
|
+
*/
|
|
342
|
+
export interface BuildContractPaymasterTransactionOptions extends BuildBatchTransactionOptions {
|
|
343
|
+
/** Contract paymaster address. */
|
|
344
|
+
paymaster: AddressLike;
|
|
345
|
+
/**
|
|
346
|
+
* Opaque context bytes forwarded to `IPaymaster.validatePaymasterOp`.
|
|
347
|
+
* Max 256 bytes.
|
|
348
|
+
*/
|
|
349
|
+
paymasterContext: Uint8Array | number[];
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Build an AA batch transaction using a **contract paymaster** (Phase 2).
|
|
353
|
+
*
|
|
354
|
+
* Unlike {@link buildSponsoredTransaction} (off-chain paymaster), a contract
|
|
355
|
+
* paymaster implements `IPaymaster.validatePaymasterOp` on-chain and receives
|
|
356
|
+
* `paymasterContext` as input. The bundle must NOT include `paymaster_signature`.
|
|
357
|
+
*
|
|
358
|
+
* @param options - Options including contract paymaster address and context bytes.
|
|
359
|
+
* @returns `{ tx, aa_bundle }` — an unsigned transaction skeleton plus bundle.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* const { tx, aa_bundle } = buildContractPaymasterTransaction({
|
|
364
|
+
* chainId: 424242,
|
|
365
|
+
* nonce: 0,
|
|
366
|
+
* innerCalls: [...],
|
|
367
|
+
* paymaster: contractPaymasterAddress,
|
|
368
|
+
* paymasterContext: contextBytes,
|
|
369
|
+
* });
|
|
370
|
+
* const signingHash = hashBatchTransaction(tx, aa_bundle);
|
|
371
|
+
* const signed = await signer.buildSignedTransaction({ tx, txHash: signingHash, aaBundle: aa_bundle });
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
export declare function buildContractPaymasterTransaction(options: BuildContractPaymasterTransactionOptions): {
|
|
375
|
+
tx: ShellTransactionRequest;
|
|
376
|
+
aa_bundle: AaBundle;
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* Options for {@link buildSessionKeyTransaction}.
|
|
380
|
+
*
|
|
381
|
+
* Extends {@link BuildBatchTransactionOptions} with session key authorization.
|
|
382
|
+
*/
|
|
383
|
+
export interface BuildSessionKeyTransactionOptions extends BuildBatchTransactionOptions {
|
|
384
|
+
/** Pre-built session key authorization. */
|
|
385
|
+
sessionAuth: SessionAuth;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Build an AA batch transaction authorized by a **session key** (Phase 2).
|
|
389
|
+
*
|
|
390
|
+
* The session key must have been authorized by the root account via a
|
|
391
|
+
* `root_signature` over its `auth_hash`. The transaction is then signed
|
|
392
|
+
* by the session key via `session_signature`.
|
|
393
|
+
*
|
|
394
|
+
* @param options - Options including the session key authorization struct.
|
|
395
|
+
* @returns `{ tx, aa_bundle }` — an unsigned transaction skeleton plus bundle.
|
|
396
|
+
*
|
|
397
|
+
* @example
|
|
398
|
+
* ```typescript
|
|
399
|
+
* const { tx, aa_bundle } = buildSessionKeyTransaction({
|
|
400
|
+
* chainId: 424242,
|
|
401
|
+
* nonce: 0,
|
|
402
|
+
* innerCalls: [...],
|
|
403
|
+
* sessionAuth: {
|
|
404
|
+
* session_pubkey: Array.from(sessionPubkeyBytes),
|
|
405
|
+
* session_algo: 0,
|
|
406
|
+
* target: null,
|
|
407
|
+
* value_cap: "0xde0b6b3a7640000",
|
|
408
|
+
* expiry_block: 500,
|
|
409
|
+
* root_signature: Array.from(rootSigBytes),
|
|
410
|
+
* session_signature: Array.from(sessionSigBytes),
|
|
411
|
+
* },
|
|
412
|
+
* });
|
|
413
|
+
* const signingHash = hashBatchTransaction(tx, aa_bundle);
|
|
414
|
+
* ```
|
|
415
|
+
*/
|
|
416
|
+
export declare function buildSessionKeyTransaction(options: BuildSessionKeyTransactionOptions): {
|
|
417
|
+
tx: ShellTransactionRequest;
|
|
418
|
+
aa_bundle: AaBundle;
|
|
419
|
+
};
|
package/dist/transactions.js
CHANGED
|
@@ -377,6 +377,10 @@ export function hashBatchTransaction(tx, bundle) {
|
|
|
377
377
|
const paymasterField = bundle.paymaster
|
|
378
378
|
? normalizeHexAddress(bundle.paymaster)
|
|
379
379
|
: "0x";
|
|
380
|
+
// paymaster_context: raw bytes or empty.
|
|
381
|
+
const paymasterContextField = bundle.paymaster_context && bundle.paymaster_context.length > 0
|
|
382
|
+
? bytesToHex(new Uint8Array(bundle.paymaster_context))
|
|
383
|
+
: "0x";
|
|
380
384
|
const txFields = [
|
|
381
385
|
toRlpUint(tx.chain_id),
|
|
382
386
|
toRlpUint(tx.nonce),
|
|
@@ -392,7 +396,7 @@ export function hashBatchTransaction(tx, bundle) {
|
|
|
392
396
|
toRlpUint(tx.max_fee_per_blob_gas ?? 0),
|
|
393
397
|
(tx.blob_versioned_hashes ?? []).map((hash) => hash),
|
|
394
398
|
];
|
|
395
|
-
const bundleSigningFields = [innerCallsRlp, paymasterField];
|
|
399
|
+
const bundleSigningFields = [innerCallsRlp, paymasterField, paymasterContextField];
|
|
396
400
|
const domainBuf = new Uint8Array([BATCH_SIGNING_HASH_DOMAIN]);
|
|
397
401
|
const txRlp = hexToBytes(toRlp(txFields));
|
|
398
402
|
const bundleRlp = hexToBytes(toRlp(bundleSigningFields));
|
|
@@ -425,3 +429,66 @@ export function buildInnerTransfer(to, value, gasLimit = 21_000) {
|
|
|
425
429
|
export function buildInnerCall(to, data, gasLimit, value = 0n) {
|
|
426
430
|
return { to, value: ("0x" + value.toString(16)), data, gas_limit: gasLimit };
|
|
427
431
|
}
|
|
432
|
+
/**
|
|
433
|
+
* Build an AA batch transaction using a **contract paymaster** (Phase 2).
|
|
434
|
+
*
|
|
435
|
+
* Unlike {@link buildSponsoredTransaction} (off-chain paymaster), a contract
|
|
436
|
+
* paymaster implements `IPaymaster.validatePaymasterOp` on-chain and receives
|
|
437
|
+
* `paymasterContext` as input. The bundle must NOT include `paymaster_signature`.
|
|
438
|
+
*
|
|
439
|
+
* @param options - Options including contract paymaster address and context bytes.
|
|
440
|
+
* @returns `{ tx, aa_bundle }` — an unsigned transaction skeleton plus bundle.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```typescript
|
|
444
|
+
* const { tx, aa_bundle } = buildContractPaymasterTransaction({
|
|
445
|
+
* chainId: 424242,
|
|
446
|
+
* nonce: 0,
|
|
447
|
+
* innerCalls: [...],
|
|
448
|
+
* paymaster: contractPaymasterAddress,
|
|
449
|
+
* paymasterContext: contextBytes,
|
|
450
|
+
* });
|
|
451
|
+
* const signingHash = hashBatchTransaction(tx, aa_bundle);
|
|
452
|
+
* const signed = await signer.buildSignedTransaction({ tx, txHash: signingHash, aaBundle: aa_bundle });
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
export function buildContractPaymasterTransaction(options) {
|
|
456
|
+
const { tx, aa_bundle } = buildBatchTransaction(options);
|
|
457
|
+
aa_bundle.paymaster = options.paymaster;
|
|
458
|
+
aa_bundle.paymaster_context = Array.from(options.paymasterContext);
|
|
459
|
+
return { tx, aa_bundle };
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Build an AA batch transaction authorized by a **session key** (Phase 2).
|
|
463
|
+
*
|
|
464
|
+
* The session key must have been authorized by the root account via a
|
|
465
|
+
* `root_signature` over its `auth_hash`. The transaction is then signed
|
|
466
|
+
* by the session key via `session_signature`.
|
|
467
|
+
*
|
|
468
|
+
* @param options - Options including the session key authorization struct.
|
|
469
|
+
* @returns `{ tx, aa_bundle }` — an unsigned transaction skeleton plus bundle.
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```typescript
|
|
473
|
+
* const { tx, aa_bundle } = buildSessionKeyTransaction({
|
|
474
|
+
* chainId: 424242,
|
|
475
|
+
* nonce: 0,
|
|
476
|
+
* innerCalls: [...],
|
|
477
|
+
* sessionAuth: {
|
|
478
|
+
* session_pubkey: Array.from(sessionPubkeyBytes),
|
|
479
|
+
* session_algo: 0,
|
|
480
|
+
* target: null,
|
|
481
|
+
* value_cap: "0xde0b6b3a7640000",
|
|
482
|
+
* expiry_block: 500,
|
|
483
|
+
* root_signature: Array.from(rootSigBytes),
|
|
484
|
+
* session_signature: Array.from(sessionSigBytes),
|
|
485
|
+
* },
|
|
486
|
+
* });
|
|
487
|
+
* const signingHash = hashBatchTransaction(tx, aa_bundle);
|
|
488
|
+
* ```
|
|
489
|
+
*/
|
|
490
|
+
export function buildSessionKeyTransaction(options) {
|
|
491
|
+
const { tx, aa_bundle } = buildBatchTransaction(options);
|
|
492
|
+
aa_bundle.session_auth = options.sessionAuth;
|
|
493
|
+
return { tx, aa_bundle };
|
|
494
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -90,20 +90,125 @@ export interface AaInnerCall {
|
|
|
90
90
|
*
|
|
91
91
|
* All inner calls execute atomically under a single PQ signature covering
|
|
92
92
|
* the outer envelope + bundle (via `batch_signing_hash`).
|
|
93
|
+
*
|
|
94
|
+
* ## AA Phase 2 extensions (v0.19.0-dev)
|
|
95
|
+
*
|
|
96
|
+
* - **Contract paymaster** (`paymaster_context`): pass opaque bytes to a
|
|
97
|
+
* contract paymaster's `validatePaymasterOp` on-chain. Mutually exclusive
|
|
98
|
+
* with `paymaster_signature` (off-chain/EOA paymaster).
|
|
99
|
+
* - **Session keys** (`session_auth`): attach a short-lived sub-key
|
|
100
|
+
* authorization instead of the root PQ key.
|
|
93
101
|
*/
|
|
94
102
|
export interface AaBundle {
|
|
95
103
|
/** Ordered list of inner calls to execute. Max {@link AA_MAX_INNER_CALLS}. */
|
|
96
104
|
inner_calls: AaInnerCall[];
|
|
97
105
|
/**
|
|
98
106
|
* Optional paymaster address paying the gas cost.
|
|
99
|
-
*
|
|
107
|
+
*
|
|
108
|
+
* - EOA/off-chain paymaster: set `paymaster_signature` (not `paymaster_context`).
|
|
109
|
+
* - Contract paymaster: set `paymaster_context` (not `paymaster_signature`).
|
|
100
110
|
*/
|
|
101
111
|
paymaster?: AddressLike | null;
|
|
102
112
|
/**
|
|
103
113
|
* Paymaster's PQ signature over the `paymaster_signing_hash`.
|
|
104
|
-
* Required
|
|
114
|
+
* Required for EOA/off-chain paymaster. Mutually exclusive with `paymaster_context`.
|
|
105
115
|
*/
|
|
106
116
|
paymaster_signature?: number[] | null;
|
|
117
|
+
/**
|
|
118
|
+
* Opaque context bytes forwarded to `IPaymaster.validatePaymasterOp`.
|
|
119
|
+
* Required for contract paymaster. Mutually exclusive with `paymaster_signature`.
|
|
120
|
+
* Max 256 bytes.
|
|
121
|
+
*/
|
|
122
|
+
paymaster_context?: number[] | null;
|
|
123
|
+
/**
|
|
124
|
+
* Session key authorization. When set the root signature field belongs to
|
|
125
|
+
* the session `root_signature` and `session_signature` pair, not the root
|
|
126
|
+
* key signing the tx directly.
|
|
127
|
+
*/
|
|
128
|
+
session_auth?: SessionAuth | null;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Maximum length of `paymaster_context` bytes (256 bytes).
|
|
132
|
+
*/
|
|
133
|
+
export declare const AA_MAX_PAYMASTER_CONTEXT = 256;
|
|
134
|
+
/**
|
|
135
|
+
* Extra PQ verify gas cost per session key authorization (2 × PQ_VERIFY_GAS = 20 000).
|
|
136
|
+
* Added to intrinsic gas when a session key is used.
|
|
137
|
+
*/
|
|
138
|
+
export declare const AA_SESSION_KEY_GAS_SURCHARGE = 20000;
|
|
139
|
+
/**
|
|
140
|
+
* Session key authorization attached to an AA bundle.
|
|
141
|
+
*
|
|
142
|
+
* Allows a short-lived sub-key to authorize a transaction on behalf of the
|
|
143
|
+
* root account, with optional restrictions on target address and value cap.
|
|
144
|
+
*
|
|
145
|
+
* ## Spec (AA_PHASE2_SPEC.md §4)
|
|
146
|
+
*
|
|
147
|
+
* 1. `session_pubkey` is authorized by the root key's `root_signature` over
|
|
148
|
+
* `auth_hash = blake3(0x81 || session_pubkey || target(20B) || value_cap(32B BE) || expiry_block(8B BE) || chain_id(8B BE))`.
|
|
149
|
+
* 2. The transaction is signed by `session_pubkey` via `session_signature`.
|
|
150
|
+
* 3. `expiry_block` must be > current block at validation time.
|
|
151
|
+
* 4. Σ(inner_call.value) ≤ `value_cap`.
|
|
152
|
+
* 5. If `target` is set, all inner calls must target that address.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* const sessionAuth: SessionAuth = {
|
|
157
|
+
* session_pubkey: Array.from(sessionPubkeyBytes),
|
|
158
|
+
* session_algo: 0, // ML-DSA-65
|
|
159
|
+
* target: null,
|
|
160
|
+
* value_cap: "0xde0b6b3a7640000",
|
|
161
|
+
* expiry_block: 500,
|
|
162
|
+
* root_signature: Array.from(rootSigBytes),
|
|
163
|
+
* session_signature: Array.from(sessionSigBytes),
|
|
164
|
+
* };
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
export interface SessionAuth {
|
|
168
|
+
/** Raw bytes of the session public key. */
|
|
169
|
+
session_pubkey: number[];
|
|
170
|
+
/** Algorithm ID of the session key (Dilithium3/ML-DSA-65 = 0, SphincsSha2256f = 2). */
|
|
171
|
+
session_algo: number;
|
|
172
|
+
/** If set, every inner call in the bundle must target this address. */
|
|
173
|
+
target?: AddressLike | null;
|
|
174
|
+
/** Maximum total value (Σ inner_call.value) permitted in wei as a hex string. */
|
|
175
|
+
value_cap: HexString;
|
|
176
|
+
/** Block number after which the session key is no longer valid (exclusive). */
|
|
177
|
+
expiry_block: number;
|
|
178
|
+
/**
|
|
179
|
+
* Root account's PQ signature over the session key authorization hash.
|
|
180
|
+
* `auth_hash = blake3(0x81 || session_pubkey || target || value_cap || expiry_block || chain_id)`.
|
|
181
|
+
*/
|
|
182
|
+
root_signature: number[];
|
|
183
|
+
/** Session key's PQ signature over the tx `sender_signing_hash()`. */
|
|
184
|
+
session_signature: number[];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Guardian recovery configuration stored on-chain for an account.
|
|
188
|
+
*
|
|
189
|
+
* Set via `setGuardians` calldata (use {@link encodeSetGuardiansCalldata}).
|
|
190
|
+
*/
|
|
191
|
+
export interface GuardianConfig {
|
|
192
|
+
/** Guardian addresses (1..=5). */
|
|
193
|
+
guardians: AddressLike[];
|
|
194
|
+
/** Required votes (k-of-n). */
|
|
195
|
+
threshold: number;
|
|
196
|
+
/** Minimum blocks between threshold-reach and execution (≥ 100). */
|
|
197
|
+
timelock: number;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Active recovery proposal returned by the `shell_getRecoveryProposal` RPC method
|
|
201
|
+
* (if implemented by the node).
|
|
202
|
+
*/
|
|
203
|
+
export interface RecoveryProposal {
|
|
204
|
+
/** Proposed new PQ public key as a hex string. */
|
|
205
|
+
new_pubkey: HexString;
|
|
206
|
+
/** Algorithm ID of the new public key. */
|
|
207
|
+
new_algo: number;
|
|
208
|
+
/** Guardian addresses that have voted for this proposal. */
|
|
209
|
+
votes: AddressLike[];
|
|
210
|
+
/** Block after which `executeRecovery` may be called (0 = threshold not yet met). */
|
|
211
|
+
maturity_block: number;
|
|
107
212
|
}
|
|
108
213
|
/**
|
|
109
214
|
* A fully-signed Shell Chain transaction ready to broadcast via `shell_sendTransaction`.
|
package/dist/types.js
CHANGED
|
@@ -11,3 +11,15 @@ export const AA_BUNDLE_TX_TYPE = 0x7e;
|
|
|
11
11
|
* Maximum number of inner calls per AA bundle.
|
|
12
12
|
*/
|
|
13
13
|
export const AA_MAX_INNER_CALLS = 16;
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// AA Phase 2 types (v0.19.0-dev)
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* Maximum length of `paymaster_context` bytes (256 bytes).
|
|
19
|
+
*/
|
|
20
|
+
export const AA_MAX_PAYMASTER_CONTEXT = 256;
|
|
21
|
+
/**
|
|
22
|
+
* Extra PQ verify gas cost per session key authorization (2 × PQ_VERIFY_GAS = 20 000).
|
|
23
|
+
* Added to intrinsic gas when a session key is used.
|
|
24
|
+
*/
|
|
25
|
+
export const AA_SESSION_KEY_GAS_SURCHARGE = 20_000;
|