kokio-sdk 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -19
- package/dist/esm/abis/BeaconProxy.js +30 -46
- package/dist/esm/abis/DeviceWallet.js +546 -535
- package/dist/esm/abis/DeviceWalletFactory.js +537 -544
- package/dist/esm/abis/ESIMWallet.js +440 -299
- package/dist/esm/abis/ESIMWalletFactory.js +372 -289
- package/dist/esm/abis/LazyWalletRegistry.js +941 -421
- package/dist/esm/abis/P256Verifier.js +29 -29
- package/dist/esm/abis/ProtocolAdmin.js +1228 -0
- package/dist/esm/abis/Registry.js +1207 -466
- package/dist/esm/abis/RegistryHelper.js +414 -20
- package/dist/esm/abis/index.js +2 -1
- package/dist/esm/admin/config-admin.js +24 -0
- package/dist/esm/admin/interface/deviceWalletClass.js +27 -6
- package/dist/esm/admin/interface/deviceWalletFactoryClass.js +41 -19
- package/dist/esm/admin/interface/eSIMWalletClass.js +10 -1
- package/dist/esm/admin/interface/eSIMWalletFactoryClass.js +24 -2
- package/dist/esm/admin/interface/lazyWalletRegistryClass.js +83 -4
- package/dist/esm/admin/interface/protocolAdminClass.js +195 -0
- package/dist/esm/admin/interface/registryClass.js +93 -2
- package/dist/esm/config.js +42 -7
- package/dist/esm/interface/deviceWalletClass.js +45 -5
- package/dist/esm/interface/deviceWalletFactoryClass.js +20 -1
- package/dist/esm/interface/eSIMWalletClass.js +12 -3
- package/dist/esm/interface/registryClass.js +47 -0
- package/dist/esm/interface/smartAccountClass.js +2 -4
- package/dist/esm/logic/account-kit/createSmartAccount.js +156 -102
- package/dist/esm/logic/admin/deviceWallet.eoa.js +23 -12
- package/dist/esm/logic/admin/deviceWalletFactory.eoa.js +63 -42
- package/dist/esm/logic/admin/eSIMWallet.eoa.js +3 -5
- package/dist/esm/logic/admin/eSIMWalletFactory.eoa.js +76 -8
- package/dist/esm/logic/admin/lazyWalletRegistry.eoa.js +330 -19
- package/dist/esm/logic/admin/protocolAdmin.eoa.js +524 -0
- package/dist/esm/logic/admin/reads/deviceWallet.reads.js +82 -7
- package/dist/esm/logic/admin/reads/deviceWalletFactory.reads.js +82 -23
- package/dist/esm/logic/admin/reads/eSIMWallet.reads.js +50 -6
- package/dist/esm/logic/admin/reads/eSIMWalletFactory.reads.js +63 -5
- package/dist/esm/logic/admin/reads/lazyWalletRegistry.reads.js +171 -10
- package/dist/esm/logic/admin/reads/protocolAdmin.reads.js +154 -0
- package/dist/esm/logic/admin/reads/registry.reads.js +289 -9
- package/dist/esm/logic/admin/registry.eoa.js +274 -4
- package/dist/esm/logic/constants.js +53 -26
- package/dist/esm/logic/deviceWallet.js +224 -31
- package/dist/esm/logic/deviceWalletFactory.js +89 -0
- package/dist/esm/logic/eSIMWallet.js +113 -43
- package/dist/esm/logic/eSIMWalletFactory.js +8 -8
- package/dist/esm/logic/errors.js +64 -0
- package/dist/esm/logic/registry.js +236 -0
- package/dist/esm/logic/utils.js +2 -1
- package/dist/types/abis/BeaconProxy.d.ts +21 -33
- package/dist/types/abis/DeviceWallet.d.ts +372 -365
- package/dist/types/abis/DeviceWalletFactory.d.ts +438 -448
- package/dist/types/abis/ESIMWallet.d.ts +352 -245
- package/dist/types/abis/ESIMWalletFactory.d.ts +278 -216
- package/dist/types/abis/LazyWalletRegistry.d.ts +710 -317
- package/dist/types/abis/P256Verifier.d.ts +16 -16
- package/dist/types/abis/ProtocolAdmin.d.ts +947 -0
- package/dist/types/abis/Registry.d.ts +960 -393
- package/dist/types/abis/RegistryHelper.d.ts +317 -16
- package/dist/types/abis/index.d.ts +2 -1
- package/dist/types/admin/config-admin.d.ts +16 -0
- package/dist/types/admin/interface/deviceWalletClass.d.ts +10 -3
- package/dist/types/admin/interface/deviceWalletFactoryClass.d.ts +14 -7
- package/dist/types/admin/interface/eSIMWalletClass.d.ts +3 -0
- package/dist/types/admin/interface/eSIMWalletFactoryClass.d.ts +8 -1
- package/dist/types/admin/interface/lazyWalletRegistryClass.d.ts +38 -2
- package/dist/types/admin/interface/protocolAdminClass.d.ts +95 -0
- package/dist/types/admin/interface/registryClass.d.ts +30 -0
- package/dist/types/config.d.ts +26 -5
- package/dist/types/interface/P256VerifierClass.d.ts +3 -4
- package/dist/types/interface/constantsClass.d.ts +2 -2
- package/dist/types/interface/deviceWalletClass.d.ts +22 -2569
- package/dist/types/interface/deviceWalletFactoryClass.d.ts +10 -2564
- package/dist/types/interface/eSIMWalletClass.d.ts +11 -8
- package/dist/types/interface/eSIMWalletFactoryClass.d.ts +5 -2565
- package/dist/types/interface/registryClass.d.ts +19 -0
- package/dist/types/interface/smartAccountClass.d.ts +6 -2568
- package/dist/types/logic/P256Verifier.d.ts +2 -2
- package/dist/types/logic/account-kit/createSmartAccount.d.ts +43 -19
- package/dist/types/logic/admin/deviceWallet.eoa.d.ts +15 -9
- package/dist/types/logic/admin/deviceWalletFactory.eoa.d.ts +34 -23
- package/dist/types/logic/admin/eSIMWallet.eoa.d.ts +0 -5
- package/dist/types/logic/admin/eSIMWalletFactory.eoa.d.ts +27 -9
- package/dist/types/logic/admin/lazyWalletRegistry.eoa.d.ts +102 -10
- package/dist/types/logic/admin/protocolAdmin.eoa.d.ts +163 -0
- package/dist/types/logic/admin/reads/deviceWallet.reads.d.ts +28 -8
- package/dist/types/logic/admin/reads/deviceWalletFactory.reads.d.ts +45 -14
- package/dist/types/logic/admin/reads/eSIMWallet.reads.d.ts +25 -6
- package/dist/types/logic/admin/reads/eSIMWalletFactory.reads.d.ts +21 -6
- package/dist/types/logic/admin/reads/lazyWalletRegistry.reads.d.ts +44 -11
- package/dist/types/logic/admin/reads/protocolAdmin.reads.d.ts +53 -0
- package/dist/types/logic/admin/reads/registry.reads.d.ts +105 -9
- package/dist/types/logic/admin/registry.eoa.d.ts +102 -5
- package/dist/types/logic/constants.d.ts +2 -0
- package/dist/types/logic/deviceWallet.d.ts +78 -6
- package/dist/types/logic/deviceWalletFactory.d.ts +32 -3
- package/dist/types/logic/eSIMWallet.d.ts +48 -7
- package/dist/types/logic/eSIMWalletFactory.d.ts +3 -3
- package/dist/types/logic/errors.d.ts +45 -0
- package/dist/types/logic/registry.d.ts +78 -0
- package/dist/types/types-export.d.ts +1 -1
- package/dist/types/types.d.ts +111 -1
- package/package.json +11 -13
- package/dist/esm/interface/lazyWalletRegistryClass.js +0 -10
- package/dist/esm/logic/lazyWalletRegistry.js +0 -19
- package/dist/types/interface/lazyWalletRegistryClass.d.ts +0 -6
- package/dist/types/logic/lazyWalletRegistry.d.ts +0 -2
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import { encodeFunctionData, publicActions } from "viem";
|
|
2
|
+
import { _getChainSpecificConstants } from "../constants.js";
|
|
3
|
+
import { MissingEOAWalletError } from "../errors.js";
|
|
4
|
+
import { ProtocolAdmin, Registry } from "../../abis/index.js";
|
|
5
|
+
// Admin-EOA logic for `ProtocolAdmin`, the timelock that owns `Registry`,
|
|
6
|
+
// `LazyWalletRegistry`, `DeviceWalletFactory` and `ESIMWalletFactory`.
|
|
7
|
+
//
|
|
8
|
+
// Anything `onlyOwner` on those four contracts goes one way: a proposer schedules
|
|
9
|
+
// it, the delay elapses, and anyone executes it. Only `schedule` and `cancel` need
|
|
10
|
+
// a privileged EOA. Execution is open, so the `client` for `_execute` can be any
|
|
11
|
+
// funded account.
|
|
12
|
+
//
|
|
13
|
+
// The guardian calls and `_acceptOwnershipBatch` are the exceptions: they land
|
|
14
|
+
// straight away with no delay.
|
|
15
|
+
const ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
16
|
+
const _resolve = async (client) => {
|
|
17
|
+
const chainID = await client.getChainId();
|
|
18
|
+
const rpcURL = client.transport.url;
|
|
19
|
+
return _getChainSpecificConstants(chainID, rpcURL);
|
|
20
|
+
};
|
|
21
|
+
// Turns an `OwnerCall` into the (target, value, payload) triple the timelock stores.
|
|
22
|
+
const _encode = (call) => ({
|
|
23
|
+
target: call.address,
|
|
24
|
+
value: call.value ?? 0n,
|
|
25
|
+
payload: encodeFunctionData({
|
|
26
|
+
abi: call.abi,
|
|
27
|
+
functionName: call.functionName,
|
|
28
|
+
args: call.args,
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Operation ids
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
/**
|
|
35
|
+
* The id the timelock will file this call under. Computed on chain so the SDK
|
|
36
|
+
* and the contract cannot disagree about it.
|
|
37
|
+
*/
|
|
38
|
+
export const _operationId = async (client, call, opts = {}) => {
|
|
39
|
+
const values = await _resolve(client);
|
|
40
|
+
const { target, value, payload } = _encode(call);
|
|
41
|
+
return client.extend(publicActions).readContract({
|
|
42
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
43
|
+
abi: ProtocolAdmin,
|
|
44
|
+
functionName: "hashOperation",
|
|
45
|
+
args: [target, value, payload, opts.predecessor ?? ZERO_BYTES32, opts.salt ?? ZERO_BYTES32]
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
/** The id for a batch. Hashes differently from the same calls scheduled one by one. */
|
|
49
|
+
export const _operationIdBatch = async (client, calls, opts = {}) => {
|
|
50
|
+
const values = await _resolve(client);
|
|
51
|
+
const encoded = calls.map(_encode);
|
|
52
|
+
return client.extend(publicActions).readContract({
|
|
53
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
54
|
+
abi: ProtocolAdmin,
|
|
55
|
+
functionName: "hashOperationBatch",
|
|
56
|
+
args: [
|
|
57
|
+
encoded.map((e) => e.target),
|
|
58
|
+
encoded.map((e) => e.value),
|
|
59
|
+
encoded.map((e) => e.payload),
|
|
60
|
+
opts.predecessor ?? ZERO_BYTES32,
|
|
61
|
+
opts.salt ?? ZERO_BYTES32
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* The id for a payload built outside this SDK. `_scheduleRaw` hands back only a
|
|
67
|
+
* transaction hash, so this is the only way to get the id that `cancel`,
|
|
68
|
+
* `getTimestamp` and the `isOperation*` reads need.
|
|
69
|
+
*/
|
|
70
|
+
export const _operationIdRaw = async (client, target, value, payload, predecessor, salt) => {
|
|
71
|
+
const values = await _resolve(client);
|
|
72
|
+
return client.extend(publicActions).readContract({
|
|
73
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
74
|
+
abi: ProtocolAdmin,
|
|
75
|
+
functionName: "hashOperation",
|
|
76
|
+
args: [target, value, payload, predecessor, salt]
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
/** The id for a raw batch. Same reason as `_operationIdRaw`. */
|
|
80
|
+
export const _operationIdBatchRaw = async (client, targets, callValues, payloads, predecessor, salt) => {
|
|
81
|
+
const values = await _resolve(client);
|
|
82
|
+
return client.extend(publicActions).readContract({
|
|
83
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
84
|
+
abi: ProtocolAdmin,
|
|
85
|
+
functionName: "hashOperationBatch",
|
|
86
|
+
args: [targets, callValues, payloads, predecessor, salt]
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Scheduling - PROPOSER_ROLE
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
/**
|
|
93
|
+
* Announce an owner call. `PROPOSER_ROLE`.
|
|
94
|
+
*
|
|
95
|
+
* `delay` defaults to `getMinDelay()`. Keep the returned object: `execute` rebuilds
|
|
96
|
+
* the id from it, and without it the arguments have to be recovered from the
|
|
97
|
+
* `CallScheduled` event.
|
|
98
|
+
*/
|
|
99
|
+
export const _schedule = async (client, call, opts = {}, delay) => {
|
|
100
|
+
const values = await _resolve(client);
|
|
101
|
+
if (!client.account)
|
|
102
|
+
throw new MissingEOAWalletError();
|
|
103
|
+
const { target, value, payload } = _encode(call);
|
|
104
|
+
const predecessor = opts.predecessor ?? ZERO_BYTES32;
|
|
105
|
+
const salt = opts.salt ?? ZERO_BYTES32;
|
|
106
|
+
const publicClient = client.extend(publicActions);
|
|
107
|
+
const resolvedDelay = delay ?? await publicClient.readContract({
|
|
108
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
109
|
+
abi: ProtocolAdmin,
|
|
110
|
+
functionName: "getMinDelay",
|
|
111
|
+
args: []
|
|
112
|
+
});
|
|
113
|
+
const id = await publicClient.readContract({
|
|
114
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
115
|
+
abi: ProtocolAdmin,
|
|
116
|
+
functionName: "hashOperation",
|
|
117
|
+
args: [target, value, payload, predecessor, salt]
|
|
118
|
+
});
|
|
119
|
+
const hash = await client.writeContract({
|
|
120
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
121
|
+
chain: values.chain,
|
|
122
|
+
account: client.account.address,
|
|
123
|
+
abi: ProtocolAdmin,
|
|
124
|
+
functionName: 'schedule',
|
|
125
|
+
args: [target, value, payload, predecessor, salt, resolvedDelay]
|
|
126
|
+
});
|
|
127
|
+
return { hash, id, target, value, payload, predecessor, salt, delay: resolvedDelay };
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Announce several owner calls as one operation. `PROPOSER_ROLE`.
|
|
131
|
+
*
|
|
132
|
+
* Use this where the calls only make sense together, such as evicting a guardian,
|
|
133
|
+
* which needs both its guardian and its executor role revoked before it can act
|
|
134
|
+
* again.
|
|
135
|
+
*/
|
|
136
|
+
export const _scheduleBatch = async (client, calls, opts = {}, delay) => {
|
|
137
|
+
const values = await _resolve(client);
|
|
138
|
+
if (!client.account)
|
|
139
|
+
throw new MissingEOAWalletError();
|
|
140
|
+
const encoded = calls.map(_encode);
|
|
141
|
+
const targets = encoded.map((e) => e.target);
|
|
142
|
+
const callValues = encoded.map((e) => e.value);
|
|
143
|
+
const payloads = encoded.map((e) => e.payload);
|
|
144
|
+
const predecessor = opts.predecessor ?? ZERO_BYTES32;
|
|
145
|
+
const salt = opts.salt ?? ZERO_BYTES32;
|
|
146
|
+
const publicClient = client.extend(publicActions);
|
|
147
|
+
const resolvedDelay = delay ?? await publicClient.readContract({
|
|
148
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
149
|
+
abi: ProtocolAdmin,
|
|
150
|
+
functionName: "getMinDelay",
|
|
151
|
+
args: []
|
|
152
|
+
});
|
|
153
|
+
const id = await publicClient.readContract({
|
|
154
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
155
|
+
abi: ProtocolAdmin,
|
|
156
|
+
functionName: "hashOperationBatch",
|
|
157
|
+
args: [targets, callValues, payloads, predecessor, salt]
|
|
158
|
+
});
|
|
159
|
+
const hash = await client.writeContract({
|
|
160
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
161
|
+
chain: values.chain,
|
|
162
|
+
account: client.account.address,
|
|
163
|
+
abi: ProtocolAdmin,
|
|
164
|
+
functionName: 'scheduleBatch',
|
|
165
|
+
args: [targets, callValues, payloads, predecessor, salt, resolvedDelay]
|
|
166
|
+
});
|
|
167
|
+
return { hash, id, targets, values: callValues, payloads, predecessor, salt, delay: resolvedDelay };
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Schedule a payload built elsewhere. `PROPOSER_ROLE`. For calldata that did not
|
|
171
|
+
* come from an ABI in this SDK.
|
|
172
|
+
*
|
|
173
|
+
* Returns what `_schedule` returns, so the id needed to cancel or inspect the
|
|
174
|
+
* operation comes back with it.
|
|
175
|
+
*/
|
|
176
|
+
export const _scheduleRaw = async (client, target, value, payload, predecessor, salt, delay) => {
|
|
177
|
+
const values = await _resolve(client);
|
|
178
|
+
if (!client.account)
|
|
179
|
+
throw new MissingEOAWalletError();
|
|
180
|
+
const id = await client.extend(publicActions).readContract({
|
|
181
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
182
|
+
abi: ProtocolAdmin,
|
|
183
|
+
functionName: "hashOperation",
|
|
184
|
+
args: [target, value, payload, predecessor, salt]
|
|
185
|
+
});
|
|
186
|
+
const hash = await client.writeContract({
|
|
187
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
188
|
+
chain: values.chain,
|
|
189
|
+
account: client.account.address,
|
|
190
|
+
abi: ProtocolAdmin,
|
|
191
|
+
functionName: 'schedule',
|
|
192
|
+
args: [target, value, payload, predecessor, salt, delay]
|
|
193
|
+
});
|
|
194
|
+
return { hash, id, target, value, payload, predecessor, salt, delay };
|
|
195
|
+
};
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
// Execution - open to anyone
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
/**
|
|
200
|
+
* Run a scheduled operation once its delay has elapsed. Permissionless, so any
|
|
201
|
+
* funded EOA works.
|
|
202
|
+
*
|
|
203
|
+
* Pass back the object `schedule` returned. The timelock recomputes the id from
|
|
204
|
+
* these fields, so an altered value looks up an operation that was never
|
|
205
|
+
* scheduled and reverts.
|
|
206
|
+
*/
|
|
207
|
+
export const _execute = async (client, operation) => {
|
|
208
|
+
const values = await _resolve(client);
|
|
209
|
+
if (!client.account)
|
|
210
|
+
throw new MissingEOAWalletError();
|
|
211
|
+
return client.writeContract({
|
|
212
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
213
|
+
chain: values.chain,
|
|
214
|
+
account: client.account.address,
|
|
215
|
+
abi: ProtocolAdmin,
|
|
216
|
+
functionName: 'execute',
|
|
217
|
+
args: [operation.target, operation.value, operation.payload, operation.predecessor, operation.salt],
|
|
218
|
+
value: operation.value
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
/** Run a scheduled batch. Permissionless, same rules as `_execute`. */
|
|
222
|
+
export const _executeBatch = async (client, operation) => {
|
|
223
|
+
const values = await _resolve(client);
|
|
224
|
+
if (!client.account)
|
|
225
|
+
throw new MissingEOAWalletError();
|
|
226
|
+
return client.writeContract({
|
|
227
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
228
|
+
chain: values.chain,
|
|
229
|
+
account: client.account.address,
|
|
230
|
+
abi: ProtocolAdmin,
|
|
231
|
+
functionName: 'executeBatch',
|
|
232
|
+
args: [operation.targets, operation.values, operation.payloads, operation.predecessor, operation.salt],
|
|
233
|
+
value: operation.values.reduce((sum, v) => sum + v, 0n)
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
/** Execute a payload scheduled through `_scheduleRaw`. Permissionless. */
|
|
237
|
+
export const _executeRaw = async (client, target, value, payload, predecessor, salt) => {
|
|
238
|
+
const values = await _resolve(client);
|
|
239
|
+
if (!client.account)
|
|
240
|
+
throw new MissingEOAWalletError();
|
|
241
|
+
return client.writeContract({
|
|
242
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
243
|
+
chain: values.chain,
|
|
244
|
+
account: client.account.address,
|
|
245
|
+
abi: ProtocolAdmin,
|
|
246
|
+
functionName: 'execute',
|
|
247
|
+
args: [target, value, payload, predecessor, salt],
|
|
248
|
+
value
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Cancelling - CANCELLER_ROLE
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
/**
|
|
255
|
+
* Drop a scheduled operation before it runs. `CANCELLER_ROLE`, which every
|
|
256
|
+
* proposer also holds.
|
|
257
|
+
*/
|
|
258
|
+
export const _cancel = async (client, id) => {
|
|
259
|
+
const values = await _resolve(client);
|
|
260
|
+
if (!client.account)
|
|
261
|
+
throw new MissingEOAWalletError();
|
|
262
|
+
return client.writeContract({
|
|
263
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
264
|
+
chain: values.chain,
|
|
265
|
+
account: client.account.address,
|
|
266
|
+
abi: ProtocolAdmin,
|
|
267
|
+
functionName: 'cancel',
|
|
268
|
+
args: [id]
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
// Guardian powers - GUARDIAN_ROLE, no delay
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
/**
|
|
275
|
+
* Release a pause on a protocol contract straight away. `GUARDIAN_ROLE`.
|
|
276
|
+
*
|
|
277
|
+
* The selector is fixed in the contract, so this cannot be pointed at anything
|
|
278
|
+
* else on the target.
|
|
279
|
+
*/
|
|
280
|
+
export const _unpauseInstantly = async (client, target) => {
|
|
281
|
+
const values = await _resolve(client);
|
|
282
|
+
if (!client.account)
|
|
283
|
+
throw new MissingEOAWalletError();
|
|
284
|
+
return client.writeContract({
|
|
285
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
286
|
+
chain: values.chain,
|
|
287
|
+
account: client.account.address,
|
|
288
|
+
abi: ProtocolAdmin,
|
|
289
|
+
functionName: 'unpauseInstantly',
|
|
290
|
+
args: [target]
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* Strip the cancel power from accounts straight away. `GUARDIAN_ROLE`.
|
|
295
|
+
*
|
|
296
|
+
* All or nothing: an account that does not hold the role reverts the whole batch
|
|
297
|
+
* rather than being skipped, so a guardian acting on a list is never left
|
|
298
|
+
* believing a veto is gone while it is still there.
|
|
299
|
+
*/
|
|
300
|
+
export const _revokeCancellersInstantly = async (client, accounts) => {
|
|
301
|
+
const values = await _resolve(client);
|
|
302
|
+
if (!client.account)
|
|
303
|
+
throw new MissingEOAWalletError();
|
|
304
|
+
return client.writeContract({
|
|
305
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
306
|
+
chain: values.chain,
|
|
307
|
+
account: client.account.address,
|
|
308
|
+
abi: ProtocolAdmin,
|
|
309
|
+
functionName: 'revokeCancellersInstantly',
|
|
310
|
+
args: [accounts]
|
|
311
|
+
});
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* Suspend a protocol contract's admin key straight away. `GUARDIAN_ROLE`.
|
|
315
|
+
*
|
|
316
|
+
* Takes the power away and hands none out. Reinstating the key or naming a
|
|
317
|
+
* replacement is an owner action and waits out the delay.
|
|
318
|
+
*
|
|
319
|
+
* `target` defaults to the registry, the one contract that keeps the admin
|
|
320
|
+
* address. Everything else reads it from there, so suspending it there closes
|
|
321
|
+
* every gate in the protocol.
|
|
322
|
+
*/
|
|
323
|
+
export const _disableAdminInstantly = async (client, target) => {
|
|
324
|
+
const values = await _resolve(client);
|
|
325
|
+
if (!client.account)
|
|
326
|
+
throw new MissingEOAWalletError();
|
|
327
|
+
return client.writeContract({
|
|
328
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
329
|
+
chain: values.chain,
|
|
330
|
+
account: client.account.address,
|
|
331
|
+
abi: ProtocolAdmin,
|
|
332
|
+
functionName: 'disableAdminInstantly',
|
|
333
|
+
args: [target ?? values.factoryAddresses.REGISTRY]
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
// Ownership handover and role exit - permissionless / self
|
|
338
|
+
// ---------------------------------------------------------------------------
|
|
339
|
+
/**
|
|
340
|
+
* Finish taking ownership of contracts that have already offered it.
|
|
341
|
+
* Permissionless, and reverts `OwnershipNotOffered` for any target whose
|
|
342
|
+
* `pendingOwner` is not the timelock.
|
|
343
|
+
*/
|
|
344
|
+
export const _acceptOwnershipBatch = async (client, targets) => {
|
|
345
|
+
const values = await _resolve(client);
|
|
346
|
+
if (!client.account)
|
|
347
|
+
throw new MissingEOAWalletError();
|
|
348
|
+
return client.writeContract({
|
|
349
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
350
|
+
chain: values.chain,
|
|
351
|
+
account: client.account.address,
|
|
352
|
+
abi: ProtocolAdmin,
|
|
353
|
+
functionName: 'acceptOwnershipBatch',
|
|
354
|
+
args: [targets]
|
|
355
|
+
});
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* Give up one of your own roles. The chain requires `account` to be the caller,
|
|
359
|
+
* so this is the one role change that does not wait.
|
|
360
|
+
*/
|
|
361
|
+
export const _renounceRole = async (client, role, account) => {
|
|
362
|
+
const values = await _resolve(client);
|
|
363
|
+
if (!client.account)
|
|
364
|
+
throw new MissingEOAWalletError();
|
|
365
|
+
return client.writeContract({
|
|
366
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
367
|
+
chain: values.chain,
|
|
368
|
+
account: client.account.address,
|
|
369
|
+
abi: ProtocolAdmin,
|
|
370
|
+
functionName: 'renounceRole',
|
|
371
|
+
args: [role, account]
|
|
372
|
+
});
|
|
373
|
+
};
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
// Self-call payloads - only reachable through schedule
|
|
376
|
+
// ---------------------------------------------------------------------------
|
|
377
|
+
// These four are `msg.sender == address(this)` on chain, so they exist only as
|
|
378
|
+
// something to schedule. Each builds the `OwnerCall` to hand to `schedule`, which
|
|
379
|
+
// is why they return a call rather than sending one.
|
|
380
|
+
/** Grant a role. Pass the result to `schedule`. */
|
|
381
|
+
export const _grantRoleCall = async (client, role, account) => {
|
|
382
|
+
const values = await _resolve(client);
|
|
383
|
+
return {
|
|
384
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
385
|
+
abi: ProtocolAdmin,
|
|
386
|
+
functionName: 'grantRole',
|
|
387
|
+
args: [role, account],
|
|
388
|
+
};
|
|
389
|
+
};
|
|
390
|
+
/**
|
|
391
|
+
* Revoke a role. Pass the result to `schedule`.
|
|
392
|
+
*
|
|
393
|
+
* Evicting a guardian takes two of these in one `scheduleBatch`, its guardian
|
|
394
|
+
* role and its executor role, because the grant paired them but the revoke
|
|
395
|
+
* cannot tell that pairing from an independent grant.
|
|
396
|
+
*/
|
|
397
|
+
export const _revokeRoleCall = async (client, role, account) => {
|
|
398
|
+
const values = await _resolve(client);
|
|
399
|
+
return {
|
|
400
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
401
|
+
abi: ProtocolAdmin,
|
|
402
|
+
functionName: 'revokeRole',
|
|
403
|
+
args: [role, account],
|
|
404
|
+
};
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
* Change the delay. Pass the result to `schedule`. `minDelayFloor` still clamps
|
|
408
|
+
* whatever this writes, so it cannot take the timelock below the floor.
|
|
409
|
+
*/
|
|
410
|
+
export const _updateDelayCall = async (client, newDelay) => {
|
|
411
|
+
const values = await _resolve(client);
|
|
412
|
+
return {
|
|
413
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
414
|
+
abi: ProtocolAdmin,
|
|
415
|
+
functionName: 'updateDelay',
|
|
416
|
+
args: [newDelay],
|
|
417
|
+
};
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* Suspend a protocol contract's admin and nominate its replacement in one step.
|
|
421
|
+
* Pass the result to `schedule`.
|
|
422
|
+
*
|
|
423
|
+
* The nominee still has to accept, and the role stays dormant until it does.
|
|
424
|
+
*/
|
|
425
|
+
export const _disableAndNominateCall = async (client, target, newAdmin) => {
|
|
426
|
+
const values = await _resolve(client);
|
|
427
|
+
return {
|
|
428
|
+
address: values.factoryAddresses.PROTOCOL_ADMIN,
|
|
429
|
+
abi: ProtocolAdmin,
|
|
430
|
+
functionName: 'disableAndNominate',
|
|
431
|
+
args: [target, newAdmin],
|
|
432
|
+
};
|
|
433
|
+
};
|
|
434
|
+
// ---------------------------------------------------------------------------
|
|
435
|
+
// Pause and price ceiling payloads - aimed at the registry
|
|
436
|
+
// ---------------------------------------------------------------------------
|
|
437
|
+
/**
|
|
438
|
+
* Release the protocol pause on the owner's route. Pass the result to `schedule`.
|
|
439
|
+
*
|
|
440
|
+
* There is no matching `pauseCall`. Tripping the pause is `onlyESIMWalletAdmin`,
|
|
441
|
+
* so the timelock cannot do it at all; the admin key calls `registry.pause`
|
|
442
|
+
* directly.
|
|
443
|
+
*
|
|
444
|
+
* A guardian can skip the delay with `_unpauseInstantly`. Use this form when no
|
|
445
|
+
* guardian key is to hand, or when the release is planned rather than urgent.
|
|
446
|
+
*
|
|
447
|
+
* `target` defaults to the registry.
|
|
448
|
+
*/
|
|
449
|
+
export const _unpauseCall = async (client, target) => {
|
|
450
|
+
const values = await _resolve(client);
|
|
451
|
+
return {
|
|
452
|
+
address: target ?? values.factoryAddresses.REGISTRY,
|
|
453
|
+
abi: Registry,
|
|
454
|
+
functionName: 'unpause',
|
|
455
|
+
args: [],
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
/**
|
|
459
|
+
* Set the fallback data bundle price ceiling. Pass the result to `schedule`.
|
|
460
|
+
*
|
|
461
|
+
* Zero reverts on execution, not on scheduling, so a zero here costs the whole
|
|
462
|
+
* delay before it fails.
|
|
463
|
+
*
|
|
464
|
+
* `target` defaults to the registry.
|
|
465
|
+
*/
|
|
466
|
+
export const _setDefaultDataBundlePriceCapCall = async (client, cap, target) => {
|
|
467
|
+
const values = await _resolve(client);
|
|
468
|
+
return {
|
|
469
|
+
address: target ?? values.factoryAddresses.REGISTRY,
|
|
470
|
+
abi: Registry,
|
|
471
|
+
functionName: 'setDefaultDataBundlePriceCap',
|
|
472
|
+
args: [cap],
|
|
473
|
+
};
|
|
474
|
+
};
|
|
475
|
+
// ---------------------------------------------------------------------------
|
|
476
|
+
// Admin suspension payloads - the owner's route, aimed at the target contract
|
|
477
|
+
// ---------------------------------------------------------------------------
|
|
478
|
+
// Unlike the four above, these are aimed at the registry rather than the
|
|
479
|
+
// timelock. The timelock owns it, so both are `onlyOwner` calls it can only make
|
|
480
|
+
// through `schedule`.
|
|
481
|
+
//
|
|
482
|
+
// There is no instant form of either. A guardian can suspend an admin without
|
|
483
|
+
// waiting through `_disableAdminInstantly`, and nothing lifts a suspension
|
|
484
|
+
// without the delay. That asymmetry is what stops a compromised key from undoing
|
|
485
|
+
// its own suspension.
|
|
486
|
+
/**
|
|
487
|
+
* Suspend a contract's admin key on the owner's route. Pass the result to
|
|
488
|
+
* `schedule`.
|
|
489
|
+
*
|
|
490
|
+
* Prefer `_disableAdminInstantly` during an incident: it does the same thing
|
|
491
|
+
* with no wait. This form is for a planned suspension, and for an owner holding
|
|
492
|
+
* no guardian key.
|
|
493
|
+
*
|
|
494
|
+
* `target` defaults to the registry, the one contract that keeps the admin
|
|
495
|
+
* address.
|
|
496
|
+
*/
|
|
497
|
+
export const _disableAdminCall = async (client, target) => {
|
|
498
|
+
const values = await _resolve(client);
|
|
499
|
+
return {
|
|
500
|
+
address: target ?? values.factoryAddresses.REGISTRY,
|
|
501
|
+
abi: Registry,
|
|
502
|
+
functionName: 'disableAdmin',
|
|
503
|
+
args: [],
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
/**
|
|
507
|
+
* Give a suspended admin its powers back. Pass the result to `schedule`.
|
|
508
|
+
*
|
|
509
|
+
* The only route there is, and it waits out the delay however the key is held.
|
|
510
|
+
* Leaves an outstanding nomination alone, so an incumbent stripped by one is
|
|
511
|
+
* still powerless afterwards; withdraw that by naming the incumbent in
|
|
512
|
+
* `requestAdminUpdate`.
|
|
513
|
+
*
|
|
514
|
+
* `target` defaults to the registry.
|
|
515
|
+
*/
|
|
516
|
+
export const _enableAdminCall = async (client, target) => {
|
|
517
|
+
const values = await _resolve(client);
|
|
518
|
+
return {
|
|
519
|
+
address: target ?? values.factoryAddresses.REGISTRY,
|
|
520
|
+
abi: Registry,
|
|
521
|
+
functionName: 'enableAdmin',
|
|
522
|
+
args: [],
|
|
523
|
+
};
|
|
524
|
+
};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { publicActions } from "viem";
|
|
2
2
|
import { DeviceWallet } from "../../../abis/index.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* factory address, so no chain-constants lookup is needed).
|
|
9
|
-
*/
|
|
3
|
+
// Read-only admin logic targeting a specific `DeviceWallet` instance (its address
|
|
4
|
+
// is passed in). Surfaces the instance's public storage getters + `getVaultAddress`
|
|
5
|
+
// view for the backend. Each read extends the `WalletClient` with `publicActions`;
|
|
6
|
+
// no EOA account is required, and the target is the instance address (not a
|
|
7
|
+
// factory address, so no chain-constants lookup is needed).
|
|
10
8
|
/** The device's unique identifier string. */
|
|
11
9
|
export const _deviceUniqueIdentifier = async (client, deviceWalletAddress) => {
|
|
12
10
|
return client.extend(publicActions).readContract({
|
|
@@ -43,3 +41,80 @@ export const _getVaultAddress = async (client, deviceWalletAddress) => {
|
|
|
43
41
|
args: []
|
|
44
42
|
});
|
|
45
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* The P256 key that owns this wallet, as its X and Y co-ordinates. Two reads,
|
|
46
|
+
* because the contract stores the pair as an array and Solidity gives an indexed
|
|
47
|
+
* getter rather than one returning both.
|
|
48
|
+
*/
|
|
49
|
+
export const _getOwner = async (client, deviceWalletAddress) => {
|
|
50
|
+
const publicClient = client.extend(publicActions);
|
|
51
|
+
const read = (index) => publicClient.readContract({
|
|
52
|
+
address: deviceWalletAddress,
|
|
53
|
+
abi: DeviceWallet,
|
|
54
|
+
functionName: "owner",
|
|
55
|
+
args: [index]
|
|
56
|
+
});
|
|
57
|
+
return Promise.all([read(0n), read(1n)]);
|
|
58
|
+
};
|
|
59
|
+
/** Gas this wallet has on deposit at the EntryPoint. */
|
|
60
|
+
export const _getDeposit = async (client, deviceWalletAddress) => {
|
|
61
|
+
return client.extend(publicActions).readContract({
|
|
62
|
+
address: deviceWalletAddress,
|
|
63
|
+
abi: DeviceWallet,
|
|
64
|
+
functionName: "getDeposit",
|
|
65
|
+
args: []
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Check a signature over an arbitrary message, per ERC-1271. Returns `0x1626ba7e`
|
|
70
|
+
* when the signature is valid and unexpired, `0xffffffff` otherwise.
|
|
71
|
+
*
|
|
72
|
+
* The signature is a version byte, then six bytes of `validUntil`, then the
|
|
73
|
+
* ABI-encoded WebAuthn assertion. What was signed is an EIP-191 digest over
|
|
74
|
+
* version, validUntil, chain id, the wallet address and `messageHash`, not
|
|
75
|
+
* `messageHash` on its own.
|
|
76
|
+
*/
|
|
77
|
+
export const _isValidSignature = async (client, deviceWalletAddress, messageHash, signature) => {
|
|
78
|
+
return client.extend(publicActions).readContract({
|
|
79
|
+
address: deviceWalletAddress,
|
|
80
|
+
abi: DeviceWallet,
|
|
81
|
+
functionName: "isValidSignature",
|
|
82
|
+
args: [messageHash, signature]
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
/** The registry this wallet reports its ownership changes to. */
|
|
86
|
+
export const _registry = async (client, deviceWalletAddress) => {
|
|
87
|
+
return client.extend(publicActions).readContract({
|
|
88
|
+
address: deviceWalletAddress,
|
|
89
|
+
abi: DeviceWallet,
|
|
90
|
+
functionName: "registry",
|
|
91
|
+
args: []
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
/** The factory that deploys this wallet's eSIM wallets. */
|
|
95
|
+
export const _eSIMWalletFactory = async (client, deviceWalletAddress) => {
|
|
96
|
+
return client.extend(publicActions).readContract({
|
|
97
|
+
address: deviceWalletAddress,
|
|
98
|
+
abi: DeviceWallet,
|
|
99
|
+
functionName: "eSIMWalletFactory",
|
|
100
|
+
args: []
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
/** The ERC-4337 EntryPoint this wallet answers to. Immutable. */
|
|
104
|
+
export const _entryPoint = async (client, deviceWalletAddress) => {
|
|
105
|
+
return client.extend(publicActions).readContract({
|
|
106
|
+
address: deviceWalletAddress,
|
|
107
|
+
abi: DeviceWallet,
|
|
108
|
+
functionName: "entryPoint",
|
|
109
|
+
args: []
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
/** The P256 verifier used when the RIP-7212 precompile is unavailable. */
|
|
113
|
+
export const _verifier = async (client, deviceWalletAddress) => {
|
|
114
|
+
return client.extend(publicActions).readContract({
|
|
115
|
+
address: deviceWalletAddress,
|
|
116
|
+
abi: DeviceWallet,
|
|
117
|
+
functionName: "verifier",
|
|
118
|
+
args: []
|
|
119
|
+
});
|
|
120
|
+
};
|