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.
Files changed (107) hide show
  1. package/README.md +68 -19
  2. package/dist/esm/abis/BeaconProxy.js +30 -46
  3. package/dist/esm/abis/DeviceWallet.js +546 -535
  4. package/dist/esm/abis/DeviceWalletFactory.js +537 -544
  5. package/dist/esm/abis/ESIMWallet.js +440 -299
  6. package/dist/esm/abis/ESIMWalletFactory.js +372 -289
  7. package/dist/esm/abis/LazyWalletRegistry.js +941 -421
  8. package/dist/esm/abis/P256Verifier.js +29 -29
  9. package/dist/esm/abis/ProtocolAdmin.js +1228 -0
  10. package/dist/esm/abis/Registry.js +1207 -466
  11. package/dist/esm/abis/RegistryHelper.js +414 -20
  12. package/dist/esm/abis/index.js +2 -1
  13. package/dist/esm/admin/config-admin.js +24 -0
  14. package/dist/esm/admin/interface/deviceWalletClass.js +27 -6
  15. package/dist/esm/admin/interface/deviceWalletFactoryClass.js +41 -19
  16. package/dist/esm/admin/interface/eSIMWalletClass.js +10 -1
  17. package/dist/esm/admin/interface/eSIMWalletFactoryClass.js +24 -2
  18. package/dist/esm/admin/interface/lazyWalletRegistryClass.js +83 -4
  19. package/dist/esm/admin/interface/protocolAdminClass.js +195 -0
  20. package/dist/esm/admin/interface/registryClass.js +93 -2
  21. package/dist/esm/config.js +42 -7
  22. package/dist/esm/interface/deviceWalletClass.js +45 -5
  23. package/dist/esm/interface/deviceWalletFactoryClass.js +20 -1
  24. package/dist/esm/interface/eSIMWalletClass.js +12 -3
  25. package/dist/esm/interface/registryClass.js +47 -0
  26. package/dist/esm/interface/smartAccountClass.js +2 -4
  27. package/dist/esm/logic/account-kit/createSmartAccount.js +156 -102
  28. package/dist/esm/logic/admin/deviceWallet.eoa.js +23 -12
  29. package/dist/esm/logic/admin/deviceWalletFactory.eoa.js +63 -42
  30. package/dist/esm/logic/admin/eSIMWallet.eoa.js +3 -5
  31. package/dist/esm/logic/admin/eSIMWalletFactory.eoa.js +76 -8
  32. package/dist/esm/logic/admin/lazyWalletRegistry.eoa.js +330 -19
  33. package/dist/esm/logic/admin/protocolAdmin.eoa.js +524 -0
  34. package/dist/esm/logic/admin/reads/deviceWallet.reads.js +82 -7
  35. package/dist/esm/logic/admin/reads/deviceWalletFactory.reads.js +82 -23
  36. package/dist/esm/logic/admin/reads/eSIMWallet.reads.js +50 -6
  37. package/dist/esm/logic/admin/reads/eSIMWalletFactory.reads.js +63 -5
  38. package/dist/esm/logic/admin/reads/lazyWalletRegistry.reads.js +171 -10
  39. package/dist/esm/logic/admin/reads/protocolAdmin.reads.js +154 -0
  40. package/dist/esm/logic/admin/reads/registry.reads.js +289 -9
  41. package/dist/esm/logic/admin/registry.eoa.js +274 -4
  42. package/dist/esm/logic/constants.js +53 -26
  43. package/dist/esm/logic/deviceWallet.js +224 -31
  44. package/dist/esm/logic/deviceWalletFactory.js +89 -0
  45. package/dist/esm/logic/eSIMWallet.js +113 -43
  46. package/dist/esm/logic/eSIMWalletFactory.js +8 -8
  47. package/dist/esm/logic/errors.js +64 -0
  48. package/dist/esm/logic/registry.js +236 -0
  49. package/dist/esm/logic/utils.js +2 -1
  50. package/dist/types/abis/BeaconProxy.d.ts +21 -33
  51. package/dist/types/abis/DeviceWallet.d.ts +372 -365
  52. package/dist/types/abis/DeviceWalletFactory.d.ts +438 -448
  53. package/dist/types/abis/ESIMWallet.d.ts +352 -245
  54. package/dist/types/abis/ESIMWalletFactory.d.ts +278 -216
  55. package/dist/types/abis/LazyWalletRegistry.d.ts +710 -317
  56. package/dist/types/abis/P256Verifier.d.ts +16 -16
  57. package/dist/types/abis/ProtocolAdmin.d.ts +947 -0
  58. package/dist/types/abis/Registry.d.ts +960 -393
  59. package/dist/types/abis/RegistryHelper.d.ts +317 -16
  60. package/dist/types/abis/index.d.ts +2 -1
  61. package/dist/types/admin/config-admin.d.ts +16 -0
  62. package/dist/types/admin/interface/deviceWalletClass.d.ts +10 -3
  63. package/dist/types/admin/interface/deviceWalletFactoryClass.d.ts +14 -7
  64. package/dist/types/admin/interface/eSIMWalletClass.d.ts +3 -0
  65. package/dist/types/admin/interface/eSIMWalletFactoryClass.d.ts +8 -1
  66. package/dist/types/admin/interface/lazyWalletRegistryClass.d.ts +38 -2
  67. package/dist/types/admin/interface/protocolAdminClass.d.ts +95 -0
  68. package/dist/types/admin/interface/registryClass.d.ts +30 -0
  69. package/dist/types/config.d.ts +26 -5
  70. package/dist/types/interface/P256VerifierClass.d.ts +3 -4
  71. package/dist/types/interface/constantsClass.d.ts +2 -2
  72. package/dist/types/interface/deviceWalletClass.d.ts +22 -2569
  73. package/dist/types/interface/deviceWalletFactoryClass.d.ts +10 -2564
  74. package/dist/types/interface/eSIMWalletClass.d.ts +11 -8
  75. package/dist/types/interface/eSIMWalletFactoryClass.d.ts +5 -2565
  76. package/dist/types/interface/registryClass.d.ts +19 -0
  77. package/dist/types/interface/smartAccountClass.d.ts +6 -2568
  78. package/dist/types/logic/P256Verifier.d.ts +2 -2
  79. package/dist/types/logic/account-kit/createSmartAccount.d.ts +43 -19
  80. package/dist/types/logic/admin/deviceWallet.eoa.d.ts +15 -9
  81. package/dist/types/logic/admin/deviceWalletFactory.eoa.d.ts +34 -23
  82. package/dist/types/logic/admin/eSIMWallet.eoa.d.ts +0 -5
  83. package/dist/types/logic/admin/eSIMWalletFactory.eoa.d.ts +27 -9
  84. package/dist/types/logic/admin/lazyWalletRegistry.eoa.d.ts +102 -10
  85. package/dist/types/logic/admin/protocolAdmin.eoa.d.ts +163 -0
  86. package/dist/types/logic/admin/reads/deviceWallet.reads.d.ts +28 -8
  87. package/dist/types/logic/admin/reads/deviceWalletFactory.reads.d.ts +45 -14
  88. package/dist/types/logic/admin/reads/eSIMWallet.reads.d.ts +25 -6
  89. package/dist/types/logic/admin/reads/eSIMWalletFactory.reads.d.ts +21 -6
  90. package/dist/types/logic/admin/reads/lazyWalletRegistry.reads.d.ts +44 -11
  91. package/dist/types/logic/admin/reads/protocolAdmin.reads.d.ts +53 -0
  92. package/dist/types/logic/admin/reads/registry.reads.d.ts +105 -9
  93. package/dist/types/logic/admin/registry.eoa.d.ts +102 -5
  94. package/dist/types/logic/constants.d.ts +2 -0
  95. package/dist/types/logic/deviceWallet.d.ts +78 -6
  96. package/dist/types/logic/deviceWalletFactory.d.ts +32 -3
  97. package/dist/types/logic/eSIMWallet.d.ts +48 -7
  98. package/dist/types/logic/eSIMWalletFactory.d.ts +3 -3
  99. package/dist/types/logic/errors.d.ts +45 -0
  100. package/dist/types/logic/registry.d.ts +78 -0
  101. package/dist/types/types-export.d.ts +1 -1
  102. package/dist/types/types.d.ts +111 -1
  103. package/package.json +11 -13
  104. package/dist/esm/interface/lazyWalletRegistryClass.js +0 -10
  105. package/dist/esm/logic/lazyWalletRegistry.js +0 -19
  106. package/dist/types/interface/lazyWalletRegistryClass.d.ts +0 -6
  107. 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
- * Read-only admin logic targeting a specific `DeviceWallet` instance (its address
5
- * is passed in). Surfaces the instance's public storage getters + `getVaultAddress`
6
- * view for the backend. Each read extends the `WalletClient` with `publicActions`;
7
- * no EOA account is required, and the target is the instance address (not a
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
+ };