kokio-sdk 1.1.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 +7 -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 +3 -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/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
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { publicActions } from "viem";
|
|
2
2
|
import { _getChainSpecificConstants } from "../../constants.js";
|
|
3
3
|
import { Registry } from "../../../abis/index.js";
|
|
4
|
+
// Read-only admin logic for `Registry` (which inherits `RegistryHelper`, so its
|
|
5
|
+
// ABI carries the helper mappings too). Surfaces the public storage getters for
|
|
6
|
+
// the backend. Each read extends the `WalletClient` with `publicActions`; no EOA
|
|
7
|
+
// account is required.
|
|
4
8
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* account is required.
|
|
9
|
+
* The admin EOA (`eSIMWalletAdmin`) recorded in the registry. Reads zero while a
|
|
10
|
+
* nomination is pending or the admin is suspended, which means the role is
|
|
11
|
+
* dormant rather than unset.
|
|
9
12
|
*/
|
|
10
|
-
/** The admin EOA (`eSIMWalletAdmin`) recorded in the registry. */
|
|
11
13
|
export const _eSIMWalletAdmin = async (client) => {
|
|
12
14
|
const chainID = await client.getChainId();
|
|
13
15
|
const rpcURL = client.transport.url;
|
|
@@ -19,6 +21,68 @@ export const _eSIMWalletAdmin = async (client) => {
|
|
|
19
21
|
args: []
|
|
20
22
|
});
|
|
21
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* The admin address on the books, which keeps naming a suspended admin so the
|
|
26
|
+
* suspension can be lifted without supplying it again. Ask `_eSIMWalletAdmin`
|
|
27
|
+
* who may actually act.
|
|
28
|
+
*/
|
|
29
|
+
export const _adminOfRecord = async (client) => {
|
|
30
|
+
const chainID = await client.getChainId();
|
|
31
|
+
const rpcURL = client.transport.url;
|
|
32
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
33
|
+
return client.extend(publicActions).readContract({
|
|
34
|
+
address: values.factoryAddresses.REGISTRY,
|
|
35
|
+
abi: Registry,
|
|
36
|
+
functionName: "adminOfRecord",
|
|
37
|
+
args: []
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Whether the admin's powers are suspended protocol-wide. True and a pending
|
|
42
|
+
* nomination are separate reasons for `_eSIMWalletAdmin` to read zero, so read
|
|
43
|
+
* this alongside `_newRequestedAdmin` to tell them apart.
|
|
44
|
+
*/
|
|
45
|
+
export const _adminDisabled = async (client) => {
|
|
46
|
+
const chainID = await client.getChainId();
|
|
47
|
+
const rpcURL = client.transport.url;
|
|
48
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
49
|
+
return client.extend(publicActions).readContract({
|
|
50
|
+
address: values.factoryAddresses.REGISTRY,
|
|
51
|
+
abi: Registry,
|
|
52
|
+
functionName: "adminDisabled",
|
|
53
|
+
args: []
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Whether the protocol is paused. While true, every ETH-moving path on the
|
|
58
|
+
* device wallets and eSIM wallets reverts `ProtocolPaused`.
|
|
59
|
+
*/
|
|
60
|
+
export const _paused = async (client) => {
|
|
61
|
+
const chainID = await client.getChainId();
|
|
62
|
+
const rpcURL = client.transport.url;
|
|
63
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
64
|
+
return client.extend(publicActions).readContract({
|
|
65
|
+
address: values.factoryAddresses.REGISTRY,
|
|
66
|
+
abi: Registry,
|
|
67
|
+
functionName: "paused",
|
|
68
|
+
args: []
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* The fallback price ceiling in wei, applied to any eSIM wallet holding no cap of
|
|
73
|
+
* its own. Never zero.
|
|
74
|
+
*/
|
|
75
|
+
export const _defaultDataBundlePriceCap = async (client) => {
|
|
76
|
+
const chainID = await client.getChainId();
|
|
77
|
+
const rpcURL = client.transport.url;
|
|
78
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
79
|
+
return client.extend(publicActions).readContract({
|
|
80
|
+
address: values.factoryAddresses.REGISTRY,
|
|
81
|
+
abi: Registry,
|
|
82
|
+
functionName: "defaultDataBundlePriceCap",
|
|
83
|
+
args: []
|
|
84
|
+
});
|
|
85
|
+
};
|
|
22
86
|
/** The vault EOA recorded in the registry. */
|
|
23
87
|
export const _vault = async (client) => {
|
|
24
88
|
const chainID = await client.getChainId();
|
|
@@ -31,6 +95,34 @@ export const _vault = async (client) => {
|
|
|
31
95
|
args: []
|
|
32
96
|
});
|
|
33
97
|
};
|
|
98
|
+
/** The pending admin nominated via `requestAdminUpdate` (zero address if none). */
|
|
99
|
+
export const _newRequestedAdmin = async (client) => {
|
|
100
|
+
const chainID = await client.getChainId();
|
|
101
|
+
const rpcURL = client.transport.url;
|
|
102
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
103
|
+
return client.extend(publicActions).readContract({
|
|
104
|
+
address: values.factoryAddresses.REGISTRY,
|
|
105
|
+
abi: Registry,
|
|
106
|
+
functionName: "newRequestedAdmin",
|
|
107
|
+
args: []
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Who holds `onlyOwner` on the registry. On the live deployment this is the
|
|
112
|
+
* `ProtocolAdmin` timelock, so an owner call sent from an EOA reverts and has to
|
|
113
|
+
* be scheduled instead.
|
|
114
|
+
*/
|
|
115
|
+
export const _owner = async (client) => {
|
|
116
|
+
const chainID = await client.getChainId();
|
|
117
|
+
const rpcURL = client.transport.url;
|
|
118
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
119
|
+
return client.extend(publicActions).readContract({
|
|
120
|
+
address: values.factoryAddresses.REGISTRY,
|
|
121
|
+
abi: Registry,
|
|
122
|
+
functionName: "owner",
|
|
123
|
+
args: []
|
|
124
|
+
});
|
|
125
|
+
};
|
|
34
126
|
/** The upgrade-manager (owner) EOA recorded in the registry. */
|
|
35
127
|
export const _upgradeManager = async (client) => {
|
|
36
128
|
const chainID = await client.getChainId();
|
|
@@ -43,6 +135,74 @@ export const _upgradeManager = async (client) => {
|
|
|
43
135
|
args: []
|
|
44
136
|
});
|
|
45
137
|
};
|
|
138
|
+
/**
|
|
139
|
+
* The address a `transferOwnership` is waiting on. Worth reading before
|
|
140
|
+
* `protocolAdmin.acceptOwnershipBatch`, which reverts on any target that has not
|
|
141
|
+
* been offered to the timelock.
|
|
142
|
+
*/
|
|
143
|
+
export const _pendingOwner = async (client) => {
|
|
144
|
+
const chainID = await client.getChainId();
|
|
145
|
+
const rpcURL = client.transport.url;
|
|
146
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
147
|
+
return client.extend(publicActions).readContract({
|
|
148
|
+
address: values.factoryAddresses.REGISTRY,
|
|
149
|
+
abi: Registry,
|
|
150
|
+
functionName: "pendingOwner",
|
|
151
|
+
args: []
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
/** The `DeviceWalletFactory` address wired into the registry. */
|
|
155
|
+
export const _deviceWalletFactory = async (client) => {
|
|
156
|
+
const chainID = await client.getChainId();
|
|
157
|
+
const rpcURL = client.transport.url;
|
|
158
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
159
|
+
return client.extend(publicActions).readContract({
|
|
160
|
+
address: values.factoryAddresses.REGISTRY,
|
|
161
|
+
abi: Registry,
|
|
162
|
+
functionName: "deviceWalletFactory",
|
|
163
|
+
args: []
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
/** The `ESIMWalletFactory` address wired into the registry. */
|
|
167
|
+
export const _eSIMWalletFactory = async (client) => {
|
|
168
|
+
const chainID = await client.getChainId();
|
|
169
|
+
const rpcURL = client.transport.url;
|
|
170
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
171
|
+
return client.extend(publicActions).readContract({
|
|
172
|
+
address: values.factoryAddresses.REGISTRY,
|
|
173
|
+
abi: Registry,
|
|
174
|
+
functionName: "eSIMWalletFactory",
|
|
175
|
+
args: []
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
/** The EntryPoint the registry recognises. One per chain. */
|
|
179
|
+
export const _entryPoint = async (client) => {
|
|
180
|
+
const chainID = await client.getChainId();
|
|
181
|
+
const rpcURL = client.transport.url;
|
|
182
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
183
|
+
return client.extend(publicActions).readContract({
|
|
184
|
+
address: values.factoryAddresses.REGISTRY,
|
|
185
|
+
abi: Registry,
|
|
186
|
+
functionName: "entryPoint",
|
|
187
|
+
args: []
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* The same pause check the wallets themselves run, which throws rather than
|
|
192
|
+
* returning false. Use `_paused` to branch on it; use this when you want the
|
|
193
|
+
* failure to carry the protocol's own revert reason.
|
|
194
|
+
*/
|
|
195
|
+
export const _requireNotPaused = async (client) => {
|
|
196
|
+
const chainID = await client.getChainId();
|
|
197
|
+
const rpcURL = client.transport.url;
|
|
198
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
199
|
+
await client.extend(publicActions).readContract({
|
|
200
|
+
address: values.factoryAddresses.REGISTRY,
|
|
201
|
+
abi: Registry,
|
|
202
|
+
functionName: "requireNotPaused",
|
|
203
|
+
args: []
|
|
204
|
+
});
|
|
205
|
+
};
|
|
46
206
|
/** The `LazyWalletRegistry` address wired into the registry. */
|
|
47
207
|
export const _lazyWalletRegistry = async (client) => {
|
|
48
208
|
const chainID = await client.getChainId();
|
|
@@ -107,9 +267,13 @@ export const _isDeviceWalletValid = async (client, deviceWallet) => {
|
|
|
107
267
|
});
|
|
108
268
|
};
|
|
109
269
|
/**
|
|
110
|
-
* The device wallet
|
|
111
|
-
*
|
|
112
|
-
*
|
|
270
|
+
* The device wallet an eSIM wallet is registered against, zero if the protocol
|
|
271
|
+
* never deployed it. Despite the name this returns an address, not a boolean.
|
|
272
|
+
*
|
|
273
|
+
* This is a registration record, not a current holder. Once it goes non-zero it
|
|
274
|
+
* stays non-zero for the rest of the wallet's life, and mid-transfer it still
|
|
275
|
+
* names the device wallet that last held it. To ask who holds it now, read
|
|
276
|
+
* `DeviceWallet.isValidESIMWallet` on the device wallet.
|
|
113
277
|
*/
|
|
114
278
|
export const _isESIMWalletValid = async (client, eSIMWallet) => {
|
|
115
279
|
const chainID = await client.getChainId();
|
|
@@ -122,7 +286,15 @@ export const _isESIMWalletValid = async (client, eSIMWallet) => {
|
|
|
122
286
|
args: [eSIMWallet]
|
|
123
287
|
});
|
|
124
288
|
};
|
|
125
|
-
/**
|
|
289
|
+
/**
|
|
290
|
+
* Whether a transfer is outstanding on an eSIM wallet. `bindESIMWallet` clears
|
|
291
|
+
* it once the new device wallet takes the eSIM wallet on.
|
|
292
|
+
*
|
|
293
|
+
* Independent of `isESIMWalletValid`, and neither implies the other. A `true`
|
|
294
|
+
* here is not a claim the wallet left the protocol, and it is normal for the
|
|
295
|
+
* association to still name the device wallet that raised the flag. Do not use
|
|
296
|
+
* this to decide whether an eSIM wallet belongs to the protocol.
|
|
297
|
+
*/
|
|
126
298
|
export const _isESIMWalletOnStandby = async (client, eSIMWallet) => {
|
|
127
299
|
const chainID = await client.getChainId();
|
|
128
300
|
const rpcURL = client.transport.url;
|
|
@@ -134,3 +306,111 @@ export const _isESIMWalletOnStandby = async (client, eSIMWallet) => {
|
|
|
134
306
|
args: [eSIMWallet]
|
|
135
307
|
});
|
|
136
308
|
};
|
|
309
|
+
/**
|
|
310
|
+
* Whether a device identifier already has a wallet on chain. Not the same
|
|
311
|
+
* question as `lazyWalletRegistry.isDeviceIdentifierReserved`, which reads true
|
|
312
|
+
* as soon as history is recorded and well before anything is deployed.
|
|
313
|
+
*/
|
|
314
|
+
export const _isDeviceIdentifierAlreadyUsed = async (client, deviceUniqueIdentifier) => {
|
|
315
|
+
const chainID = await client.getChainId();
|
|
316
|
+
const rpcURL = client.transport.url;
|
|
317
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
318
|
+
return client.extend(publicActions).readContract({
|
|
319
|
+
address: values.factoryAddresses.REGISTRY,
|
|
320
|
+
abi: Registry,
|
|
321
|
+
functionName: "isDeviceIdentifierAlreadyUsed",
|
|
322
|
+
args: [deviceUniqueIdentifier]
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
/** Whether an eSIM identifier is already held by a wallet. */
|
|
326
|
+
export const _isESIMIdentifierClaimed = async (client, eSIMUniqueIdentifier) => {
|
|
327
|
+
const chainID = await client.getChainId();
|
|
328
|
+
const rpcURL = client.transport.url;
|
|
329
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
330
|
+
return client.extend(publicActions).readContract({
|
|
331
|
+
address: values.factoryAddresses.REGISTRY,
|
|
332
|
+
abi: Registry,
|
|
333
|
+
functionName: "isESIMIdentifierClaimed",
|
|
334
|
+
args: [eSIMUniqueIdentifier]
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
/**
|
|
338
|
+
* The one eSIM wallet holding an eSIM identifier, zero if nobody holds it. Set
|
|
339
|
+
* once and never cleared, an ownership transfer included, because the eSIM
|
|
340
|
+
* belongs to the wallet rather than to whichever device is holding it.
|
|
341
|
+
*/
|
|
342
|
+
export const _eSIMWalletForIdentifier = async (client, eSIMUniqueIdentifier) => {
|
|
343
|
+
const chainID = await client.getChainId();
|
|
344
|
+
const rpcURL = client.transport.url;
|
|
345
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
346
|
+
return client.extend(publicActions).readContract({
|
|
347
|
+
address: values.factoryAddresses.REGISTRY,
|
|
348
|
+
abi: Registry,
|
|
349
|
+
functionName: "eSIMWalletForIdentifier",
|
|
350
|
+
args: [eSIMUniqueIdentifier]
|
|
351
|
+
});
|
|
352
|
+
};
|
|
353
|
+
/**
|
|
354
|
+
* The same answer as `_eSIMWalletForIdentifier`, keyed by the keccak256 of the
|
|
355
|
+
* identifier. Use it when the hash is what you already have; otherwise take the
|
|
356
|
+
* string version and skip the hashing.
|
|
357
|
+
*/
|
|
358
|
+
export const _claimedESIMIdentifiers = async (client, hashOfESIMIdentifier) => {
|
|
359
|
+
const chainID = await client.getChainId();
|
|
360
|
+
const rpcURL = client.transport.url;
|
|
361
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
362
|
+
return client.extend(publicActions).readContract({
|
|
363
|
+
address: values.factoryAddresses.REGISTRY,
|
|
364
|
+
abi: Registry,
|
|
365
|
+
functionName: "claimedESIMIdentifiers",
|
|
366
|
+
args: [hashOfESIMIdentifier]
|
|
367
|
+
});
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* The check `DeviceWalletFactory` runs before taking a device identifier.
|
|
371
|
+
* Resolves if the identifier is free, reverts `DeviceIdentifierReservedForLazyWallet`
|
|
372
|
+
* if a fiat user's eSIMs are already waiting on it.
|
|
373
|
+
*
|
|
374
|
+
* Worth calling ahead of a deployment: taking a reserved identifier strands the
|
|
375
|
+
* lazy user, since the history copy, the wallet deployment and the device switch
|
|
376
|
+
* all then refuse it.
|
|
377
|
+
*/
|
|
378
|
+
export const _requireDeviceIdentifierNotReserved = async (client, deviceUniqueIdentifier) => {
|
|
379
|
+
const chainID = await client.getChainId();
|
|
380
|
+
const rpcURL = client.transport.url;
|
|
381
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
382
|
+
await client.extend(publicActions).readContract({
|
|
383
|
+
address: values.factoryAddresses.REGISTRY,
|
|
384
|
+
abi: Registry,
|
|
385
|
+
functionName: "requireDeviceIdentifierNotReserved",
|
|
386
|
+
args: [deviceUniqueIdentifier]
|
|
387
|
+
});
|
|
388
|
+
};
|
|
389
|
+
/**
|
|
390
|
+
* The ERC-1822 storage slot this proxy keeps its implementation in. An upgrade
|
|
391
|
+
* reverts unless the incoming implementation answers with the same value, which
|
|
392
|
+
* is what stops a non-UUPS address being installed.
|
|
393
|
+
*/
|
|
394
|
+
export const _proxiableUUID = async (client) => {
|
|
395
|
+
const chainID = await client.getChainId();
|
|
396
|
+
const rpcURL = client.transport.url;
|
|
397
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
398
|
+
return client.extend(publicActions).readContract({
|
|
399
|
+
address: values.factoryAddresses.REGISTRY,
|
|
400
|
+
abi: Registry,
|
|
401
|
+
functionName: "proxiableUUID",
|
|
402
|
+
args: []
|
|
403
|
+
});
|
|
404
|
+
};
|
|
405
|
+
/** The OpenZeppelin upgrade interface this proxy speaks, currently `"5.0.0"`. */
|
|
406
|
+
export const _upgradeInterfaceVersion = async (client) => {
|
|
407
|
+
const chainID = await client.getChainId();
|
|
408
|
+
const rpcURL = client.transport.url;
|
|
409
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
410
|
+
return client.extend(publicActions).readContract({
|
|
411
|
+
address: values.factoryAddresses.REGISTRY,
|
|
412
|
+
abi: Registry,
|
|
413
|
+
functionName: "UPGRADE_INTERFACE_VERSION",
|
|
414
|
+
args: []
|
|
415
|
+
});
|
|
416
|
+
};
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { _getChainSpecificConstants } from "../constants.js";
|
|
2
2
|
import { MissingEOAWalletError } from "../errors.js";
|
|
3
3
|
import { Registry } from "../../abis/index.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
// Admin-EOA logic for `Registry`. Most of this is `onlyOwner`, so the `client`
|
|
5
|
+
// must carry the owner EOA. `_acceptAdminUpdate` is the nominee's own call and
|
|
6
|
+
// `_assignESIMIdentifier` is `onlyESIMWalletAdmin`.
|
|
7
|
+
//
|
|
8
|
+
// On the live deployment the owner is the `ProtocolAdmin` timelock, not an EOA,
|
|
9
|
+
// so an `onlyOwner` call sent directly reverts. Route those through
|
|
10
|
+
// `protocolAdmin.proposer.schedule` instead. The direct path stays for
|
|
11
|
+
// deployments whose owner is a plain EOA or multisig.
|
|
8
12
|
/** Wire (or rewire) the LazyWalletRegistry into the Registry. `onlyOwner`. */
|
|
9
13
|
export const _addOrUpdateLazyWalletRegistryAddress = async (client, lazyWalletRegistry) => {
|
|
10
14
|
const chainID = await client.getChainId();
|
|
@@ -21,3 +25,269 @@ export const _addOrUpdateLazyWalletRegistryAddress = async (client, lazyWalletRe
|
|
|
21
25
|
args: [lazyWalletRegistry]
|
|
22
26
|
});
|
|
23
27
|
};
|
|
28
|
+
/** Update the vault that receives eSIM payments. `onlyOwner`. */
|
|
29
|
+
export const _updateVaultAddress = async (client, newVaultAddress) => {
|
|
30
|
+
const chainID = await client.getChainId();
|
|
31
|
+
const rpcURL = client.transport.url;
|
|
32
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
33
|
+
if (!client.account)
|
|
34
|
+
throw new MissingEOAWalletError();
|
|
35
|
+
return client.writeContract({
|
|
36
|
+
address: values.factoryAddresses.REGISTRY,
|
|
37
|
+
chain: values.chain,
|
|
38
|
+
account: client.account.address,
|
|
39
|
+
abi: Registry,
|
|
40
|
+
functionName: 'updateVaultAddress',
|
|
41
|
+
args: [newVaultAddress]
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Step 1 of the 2-step admin handover: nominate the next admin. `onlyOwner`, so
|
|
46
|
+
* the `client` is the owner EOA, not the outgoing admin.
|
|
47
|
+
*
|
|
48
|
+
* The nomination takes the role off the incumbent straight away: `eSIMWalletAdmin`
|
|
49
|
+
* reads zero until the nominee accepts, and every admin gated call across the
|
|
50
|
+
* protocol reverts in that window. Send the two steps close together. Naming the
|
|
51
|
+
* incumbent instead withdraws a pending nomination and hands the role back.
|
|
52
|
+
*/
|
|
53
|
+
export const _requestAdminUpdate = async (client, newAdmin) => {
|
|
54
|
+
const chainID = await client.getChainId();
|
|
55
|
+
const rpcURL = client.transport.url;
|
|
56
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
57
|
+
if (!client.account)
|
|
58
|
+
throw new MissingEOAWalletError();
|
|
59
|
+
return client.writeContract({
|
|
60
|
+
address: values.factoryAddresses.REGISTRY,
|
|
61
|
+
chain: values.chain,
|
|
62
|
+
account: client.account.address,
|
|
63
|
+
abi: Registry,
|
|
64
|
+
functionName: 'requestAdminUpdate',
|
|
65
|
+
args: [newAdmin]
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Suspend the admin's powers protocol-wide. `onlyOwner`.
|
|
70
|
+
*
|
|
71
|
+
* The address stays on the books as `adminOfRecord`, so lifting the suspension
|
|
72
|
+
* does not need it supplied again. Reverts if the admin is already suspended,
|
|
73
|
+
* rather than passing quietly and leaving the caller believing it acted.
|
|
74
|
+
*/
|
|
75
|
+
export const _disableAdmin = async (client) => {
|
|
76
|
+
const chainID = await client.getChainId();
|
|
77
|
+
const rpcURL = client.transport.url;
|
|
78
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
79
|
+
if (!client.account)
|
|
80
|
+
throw new MissingEOAWalletError();
|
|
81
|
+
return client.writeContract({
|
|
82
|
+
address: values.factoryAddresses.REGISTRY,
|
|
83
|
+
chain: values.chain,
|
|
84
|
+
account: client.account.address,
|
|
85
|
+
abi: Registry,
|
|
86
|
+
functionName: 'disableAdmin',
|
|
87
|
+
args: []
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Give the suspended admin its powers back. `onlyOwner`.
|
|
92
|
+
*
|
|
93
|
+
* Does nothing about an outstanding nomination, which keeps the incumbent
|
|
94
|
+
* powerless on its own. Withdraw that with `_requestAdminUpdate` naming the
|
|
95
|
+
* incumbent. Reverts if the admin was never suspended.
|
|
96
|
+
*/
|
|
97
|
+
export const _enableAdmin = async (client) => {
|
|
98
|
+
const chainID = await client.getChainId();
|
|
99
|
+
const rpcURL = client.transport.url;
|
|
100
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
101
|
+
if (!client.account)
|
|
102
|
+
throw new MissingEOAWalletError();
|
|
103
|
+
return client.writeContract({
|
|
104
|
+
address: values.factoryAddresses.REGISTRY,
|
|
105
|
+
chain: values.chain,
|
|
106
|
+
account: client.account.address,
|
|
107
|
+
abi: Registry,
|
|
108
|
+
functionName: 'enableAdmin',
|
|
109
|
+
args: []
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Stop the ETH-moving paths on every device wallet and eSIM wallet.
|
|
114
|
+
* `onlyESIMWalletAdmin`, so this is the one emergency lever the backend key can
|
|
115
|
+
* pull on its own.
|
|
116
|
+
*
|
|
117
|
+
* It cannot release it again: `_unpause` is `onlyOwner`. That split is what stops
|
|
118
|
+
* a compromised backend key holding user funds. Owners can still spend their own
|
|
119
|
+
* ETH through their device wallet's `execute`, which a pause never reaches.
|
|
120
|
+
*/
|
|
121
|
+
export const _pause = async (client) => {
|
|
122
|
+
const chainID = await client.getChainId();
|
|
123
|
+
const rpcURL = client.transport.url;
|
|
124
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
125
|
+
if (!client.account)
|
|
126
|
+
throw new MissingEOAWalletError();
|
|
127
|
+
return client.writeContract({
|
|
128
|
+
address: values.factoryAddresses.REGISTRY,
|
|
129
|
+
chain: values.chain,
|
|
130
|
+
account: client.account.address,
|
|
131
|
+
abi: Registry,
|
|
132
|
+
functionName: 'pause',
|
|
133
|
+
args: []
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Release the pause. `onlyOwner`, not the admin, see `_pause`.
|
|
138
|
+
*
|
|
139
|
+
* On the live deployment the owner is the timelock, so this reverts from an EOA.
|
|
140
|
+
* Schedule `protocolAdmin.unpauseCall` instead, or have a guardian call
|
|
141
|
+
* `unpauseInstantly` if the wait is not acceptable.
|
|
142
|
+
*/
|
|
143
|
+
export const _unpause = async (client) => {
|
|
144
|
+
const chainID = await client.getChainId();
|
|
145
|
+
const rpcURL = client.transport.url;
|
|
146
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
147
|
+
if (!client.account)
|
|
148
|
+
throw new MissingEOAWalletError();
|
|
149
|
+
return client.writeContract({
|
|
150
|
+
address: values.factoryAddresses.REGISTRY,
|
|
151
|
+
chain: values.chain,
|
|
152
|
+
account: client.account.address,
|
|
153
|
+
abi: Registry,
|
|
154
|
+
functionName: 'unpause',
|
|
155
|
+
args: []
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Set the price ceiling every eSIM wallet falls back to when it holds none of its
|
|
160
|
+
* own. `onlyOwner`, deliberately not the admin: the admin names the price on
|
|
161
|
+
* `buyDataBundle`, so it must not also be able to raise its own limit.
|
|
162
|
+
*
|
|
163
|
+
* Zero reverts `ZeroDataBundlePriceCap`, since a zero would read as "no ceiling"
|
|
164
|
+
* for every wallet without one of its own.
|
|
165
|
+
*/
|
|
166
|
+
export const _setDefaultDataBundlePriceCap = async (client, cap) => {
|
|
167
|
+
const chainID = await client.getChainId();
|
|
168
|
+
const rpcURL = client.transport.url;
|
|
169
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
170
|
+
if (!client.account)
|
|
171
|
+
throw new MissingEOAWalletError();
|
|
172
|
+
return client.writeContract({
|
|
173
|
+
address: values.factoryAddresses.REGISTRY,
|
|
174
|
+
chain: values.chain,
|
|
175
|
+
account: client.account.address,
|
|
176
|
+
abi: Registry,
|
|
177
|
+
functionName: 'setDefaultDataBundlePriceCap',
|
|
178
|
+
args: [cap]
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Bind an eSIM's unique identifier to its wallet. `onlyESIMWalletAdmin`.
|
|
183
|
+
*
|
|
184
|
+
* The identifier is claimed protocol-wide, so a string already bound to another
|
|
185
|
+
* wallet reverts rather than moving.
|
|
186
|
+
*/
|
|
187
|
+
export const _assignESIMIdentifier = async (client, eSIMWalletAddress, eSIMUniqueIdentifier) => {
|
|
188
|
+
const chainID = await client.getChainId();
|
|
189
|
+
const rpcURL = client.transport.url;
|
|
190
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
191
|
+
if (!client.account)
|
|
192
|
+
throw new MissingEOAWalletError();
|
|
193
|
+
return client.writeContract({
|
|
194
|
+
address: values.factoryAddresses.REGISTRY,
|
|
195
|
+
chain: values.chain,
|
|
196
|
+
account: client.account.address,
|
|
197
|
+
abi: Registry,
|
|
198
|
+
functionName: 'assignESIMIdentifier',
|
|
199
|
+
args: [eSIMWalletAddress, eSIMUniqueIdentifier]
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Step 2 of the 2-step admin handover: the nominee accepts. The chain requires
|
|
204
|
+
* `msg.sender` to equal the pending admin, so the `client` here must be the
|
|
205
|
+
* newly nominated admin EOA.
|
|
206
|
+
*/
|
|
207
|
+
export const _acceptAdminUpdate = async (client) => {
|
|
208
|
+
const chainID = await client.getChainId();
|
|
209
|
+
const rpcURL = client.transport.url;
|
|
210
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
211
|
+
if (!client.account)
|
|
212
|
+
throw new MissingEOAWalletError();
|
|
213
|
+
return client.writeContract({
|
|
214
|
+
address: values.factoryAddresses.REGISTRY,
|
|
215
|
+
chain: values.chain,
|
|
216
|
+
account: client.account.address,
|
|
217
|
+
abi: Registry,
|
|
218
|
+
functionName: 'acceptAdminUpdate',
|
|
219
|
+
args: []
|
|
220
|
+
});
|
|
221
|
+
};
|
|
222
|
+
/**
|
|
223
|
+
* Take ownership after a `transferOwnership` named this client. The chain
|
|
224
|
+
* requires `msg.sender` to equal `pendingOwner`, so the `client` is the incoming
|
|
225
|
+
* owner, not the outgoing one.
|
|
226
|
+
*
|
|
227
|
+
* Permissionless in the sense that it needs no role, so where the incoming owner
|
|
228
|
+
* is the timelock this is not the call to use: `protocolAdmin.acceptOwnershipBatch`
|
|
229
|
+
* accepts for every contract at once and needs no delay.
|
|
230
|
+
*/
|
|
231
|
+
export const _acceptOwnership = async (client) => {
|
|
232
|
+
const chainID = await client.getChainId();
|
|
233
|
+
const rpcURL = client.transport.url;
|
|
234
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
235
|
+
if (!client.account)
|
|
236
|
+
throw new MissingEOAWalletError();
|
|
237
|
+
return client.writeContract({
|
|
238
|
+
address: values.factoryAddresses.REGISTRY,
|
|
239
|
+
chain: values.chain,
|
|
240
|
+
account: client.account.address,
|
|
241
|
+
abi: Registry,
|
|
242
|
+
functionName: 'acceptOwnership',
|
|
243
|
+
args: []
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
// ---------------------------------------------------------------------------
|
|
247
|
+
// Owner payloads - only reachable through schedule
|
|
248
|
+
// ---------------------------------------------------------------------------
|
|
249
|
+
// Both are `onlyOwner`, and on the live deployment the owner is the timelock, so
|
|
250
|
+
// they exist as something to schedule rather than to send. Each returns the
|
|
251
|
+
// `OwnerCall` to hand to `protocolAdmin.schedule`.
|
|
252
|
+
/**
|
|
253
|
+
* Offer ownership to a new address. Pass the result to `schedule`.
|
|
254
|
+
*
|
|
255
|
+
* Ownable2Step, so the offer alone changes nothing: the named address has to
|
|
256
|
+
* call `acceptOwnership` before it holds anything. Until then the current owner
|
|
257
|
+
* keeps every power. Naming an address that cannot call back leaves the
|
|
258
|
+
* ownership where it is rather than stranding it.
|
|
259
|
+
*/
|
|
260
|
+
export const _transferOwnershipCall = async (client, newOwner) => {
|
|
261
|
+
const chainID = await client.getChainId();
|
|
262
|
+
const rpcURL = client.transport.url;
|
|
263
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
264
|
+
return {
|
|
265
|
+
address: values.factoryAddresses.REGISTRY,
|
|
266
|
+
abi: Registry,
|
|
267
|
+
functionName: 'transferOwnership',
|
|
268
|
+
args: [newOwner],
|
|
269
|
+
};
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* Point the proxy at a new implementation. Builds `upgradeToAndCall`. Pass the
|
|
273
|
+
* result to `schedule`.
|
|
274
|
+
*
|
|
275
|
+
* `data` runs on the proxy straight after the swap, in the same transaction, and
|
|
276
|
+
* is where a `reinitializer` goes. Leave it empty when the new implementation
|
|
277
|
+
* needs no setup.
|
|
278
|
+
*
|
|
279
|
+
* There is no undo. The implementation is checked for a matching `proxiableUUID`
|
|
280
|
+
* and nothing else, so an address that answers correctly but cannot upgrade
|
|
281
|
+
* again ends the proxy's life. Diff the storage layout before scheduling.
|
|
282
|
+
*/
|
|
283
|
+
export const _upgradeCall = async (client, newImplementation, data = '0x') => {
|
|
284
|
+
const chainID = await client.getChainId();
|
|
285
|
+
const rpcURL = client.transport.url;
|
|
286
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
287
|
+
return {
|
|
288
|
+
address: values.factoryAddresses.REGISTRY,
|
|
289
|
+
abi: Registry,
|
|
290
|
+
functionName: 'upgradeToAndCall',
|
|
291
|
+
args: [newImplementation, data],
|
|
292
|
+
};
|
|
293
|
+
};
|