kokio-sdk 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +15 -15
  2. package/dist/esm/admin/config-admin.js +1 -1
  3. package/dist/esm/config.js +1 -1
  4. package/dist/esm/interface/deviceWalletClass.js +10 -1
  5. package/dist/esm/interface/eSIMWalletClass.js +9 -1
  6. package/dist/esm/interface/eSIMWalletFactoryClass.js +9 -1
  7. package/dist/esm/interface/registryClass.js +8 -0
  8. package/dist/esm/interface/smartAccountClass.js +9 -2
  9. package/dist/esm/logic/P256Verifier.js +2 -2
  10. package/dist/esm/logic/account-kit/createSmartAccount.js +47 -36
  11. package/dist/esm/logic/admin/deviceWallet.eoa.js +5 -5
  12. package/dist/esm/logic/admin/deviceWalletFactory.eoa.js +13 -13
  13. package/dist/esm/logic/admin/eSIMWallet.eoa.js +3 -3
  14. package/dist/esm/logic/admin/eSIMWalletFactory.eoa.js +9 -9
  15. package/dist/esm/logic/admin/lazyWalletRegistry.eoa.js +13 -13
  16. package/dist/esm/logic/admin/paymentAdapter.eoa.js +11 -11
  17. package/dist/esm/logic/admin/protocolAdmin.eoa.js +14 -14
  18. package/dist/esm/logic/admin/reads/deviceWalletFactory.reads.js +9 -9
  19. package/dist/esm/logic/admin/reads/eSIMWalletFactory.reads.js +7 -7
  20. package/dist/esm/logic/admin/reads/lazyWalletRegistry.reads.js +18 -18
  21. package/dist/esm/logic/admin/reads/paymentAdapter.reads.js +8 -8
  22. package/dist/esm/logic/admin/reads/protocolAdmin.reads.js +2 -2
  23. package/dist/esm/logic/admin/reads/registry.reads.js +31 -31
  24. package/dist/esm/logic/admin/registry.eoa.js +27 -27
  25. package/dist/esm/logic/constants.js +14 -1
  26. package/dist/esm/logic/deviceWallet.js +35 -1
  27. package/dist/esm/logic/deviceWalletFactory.js +11 -11
  28. package/dist/esm/logic/eSIMWallet.js +50 -2
  29. package/dist/esm/logic/eSIMWalletFactory.js +15 -3
  30. package/dist/esm/logic/errors.js +15 -9
  31. package/dist/esm/logic/paymentAdapter.js +8 -8
  32. package/dist/esm/logic/registry.js +17 -17
  33. package/dist/esm/logic/utils.js +1 -81
  34. package/dist/esm/types-export.js +1 -1
  35. package/dist/types/admin/config-admin.d.ts +1 -1
  36. package/dist/types/config.d.ts +1 -1
  37. package/dist/types/interface/deviceWalletClass.d.ts +12 -0
  38. package/dist/types/interface/eSIMWalletClass.d.ts +7 -1
  39. package/dist/types/interface/eSIMWalletFactoryClass.d.ts +6 -0
  40. package/dist/types/interface/registryClass.d.ts +8 -0
  41. package/dist/types/interface/smartAccountClass.d.ts +10 -1
  42. package/dist/types/logic/account-kit/createSmartAccount.d.ts +1 -1
  43. package/dist/types/logic/constants.d.ts +3 -0
  44. package/dist/types/logic/deviceWallet.d.ts +12 -0
  45. package/dist/types/logic/eSIMWallet.d.ts +8 -0
  46. package/dist/types/logic/eSIMWalletFactory.d.ts +2 -0
  47. package/dist/types/logic/errors.d.ts +6 -5
  48. package/dist/types/logic/utils.d.ts +0 -21
  49. package/dist/types/types-export.d.ts +3 -2
  50. package/dist/types/types.d.ts +1 -1
  51. package/package.json +21 -7
@@ -1,5 +1,5 @@
1
1
  import { publicActions } from "viem";
2
- import { _getChainSpecificConstants } from "../../constants.js";
2
+ import { _chainId, _getChainSpecificConstants } from "../../constants.js";
3
3
  import { PaymentAdapter } from "../../../abis/index.js";
4
4
  // Read-only admin logic for `PaymentAdapter`. Every write on it
5
5
  // (registerAsset/updateAsset) is `onlyOwner`, i.e. only reachable through the
@@ -7,7 +7,7 @@ import { PaymentAdapter } from "../../../abis/index.js";
7
7
  // rather than here.
8
8
  /** The registry this adapter reads `vault()` and `isESIMWalletValid()` from. */
9
9
  export const _registry = async (client) => {
10
- const chainID = await client.getChainId();
10
+ const chainID = await _chainId(client);
11
11
  const rpcURL = client.transport.url;
12
12
  const values = _getChainSpecificConstants(chainID, rpcURL);
13
13
  return client.extend(publicActions).readContract({
@@ -19,7 +19,7 @@ export const _registry = async (client) => {
19
19
  };
20
20
  /** The ERC-20 registered under the `USDC` symbol at configure time. */
21
21
  export const _settlementToken = async (client) => {
22
- const chainID = await client.getChainId();
22
+ const chainID = await _chainId(client);
23
23
  const rpcURL = client.transport.url;
24
24
  const values = _getChainSpecificConstants(chainID, rpcURL);
25
25
  return client.extend(publicActions).readContract({
@@ -35,7 +35,7 @@ export const _settlementToken = async (client) => {
35
35
  * from "registered but withdrawn" (`allowed: false`).
36
36
  */
37
37
  export const _assets = async (client, symbol) => {
38
- const chainID = await client.getChainId();
38
+ const chainID = await _chainId(client);
39
39
  const rpcURL = client.transport.url;
40
40
  const values = _getChainSpecificConstants(chainID, rpcURL);
41
41
  const [allowed, isDollarUnit, decimals, token] = await client.extend(publicActions).readContract({
@@ -48,7 +48,7 @@ export const _assets = async (client, symbol) => {
48
48
  };
49
49
  /** A currency's full entry, reverting if the symbol was never registered. */
50
50
  export const _resolveAsset = async (client, symbol) => {
51
- const chainID = await client.getChainId();
51
+ const chainID = await _chainId(client);
52
52
  const rpcURL = client.transport.url;
53
53
  const values = _getChainSpecificConstants(chainID, rpcURL);
54
54
  return client.extend(publicActions).readContract({
@@ -64,7 +64,7 @@ export const _resolveAsset = async (client, symbol) => {
64
64
  * `_tokenAmount` for the backend's own settlement record.
65
65
  */
66
66
  export const _quote = async (client, symbol, priceUSDCents) => {
67
- const chainID = await client.getChainId();
67
+ const chainID = await _chainId(client);
68
68
  const rpcURL = client.transport.url;
69
69
  const values = _getChainSpecificConstants(chainID, rpcURL);
70
70
  return client.extend(publicActions).readContract({
@@ -82,7 +82,7 @@ export const _quote = async (client, symbol, priceUSDCents) => {
82
82
  * still reads the adapter's own record from before that move.
83
83
  */
84
84
  export const _usedReferences = async (client, paymentReference) => {
85
- const chainID = await client.getChainId();
85
+ const chainID = await _chainId(client);
86
86
  const rpcURL = client.transport.url;
87
87
  const values = _getChainSpecificConstants(chainID, rpcURL);
88
88
  return client.extend(publicActions).readContract({
@@ -94,7 +94,7 @@ export const _usedReferences = async (client, paymentReference) => {
94
94
  };
95
95
  /** The address holding upgrade authority over this adapter (its owner). */
96
96
  export const _upgradeManager = async (client) => {
97
- const chainID = await client.getChainId();
97
+ const chainID = await _chainId(client);
98
98
  const rpcURL = client.transport.url;
99
99
  const values = _getChainSpecificConstants(chainID, rpcURL);
100
100
  return client.extend(publicActions).readContract({
@@ -1,5 +1,5 @@
1
1
  import { publicActions } from "viem";
2
- import { _getChainSpecificConstants } from "../../constants.js";
2
+ import { _chainId, _getChainSpecificConstants } from "../../constants.js";
3
3
  import { ProtocolAdmin } from "../../../abis/index.js";
4
4
  // Read-only logic for `ProtocolAdmin`, the timelock that owns the four
5
5
  // upgradeable contracts. Every read extends the `WalletClient` with
@@ -13,7 +13,7 @@ export var OperationState;
13
13
  OperationState[OperationState["Done"] = 3] = "Done";
14
14
  })(OperationState || (OperationState = {}));
15
15
  const _resolve = async (client) => {
16
- const chainID = await client.getChainId();
16
+ const chainID = await _chainId(client);
17
17
  const rpcURL = client.transport.url;
18
18
  return _getChainSpecificConstants(chainID, rpcURL);
19
19
  };
@@ -1,5 +1,5 @@
1
1
  import { publicActions } from "viem";
2
- import { _getChainSpecificConstants } from "../../constants.js";
2
+ import { _chainId, _getChainSpecificConstants } from "../../constants.js";
3
3
  import { Registry } from "../../../abis/index.js";
4
4
  // Read-only admin logic for `Registry` (which inherits `RegistryHelper`, so its
5
5
  // ABI carries the helper mappings too). Surfaces the public storage getters for
@@ -11,7 +11,7 @@ import { Registry } from "../../../abis/index.js";
11
11
  * dormant rather than unset.
12
12
  */
13
13
  export const _eSIMWalletAdmin = async (client) => {
14
- const chainID = await client.getChainId();
14
+ const chainID = await _chainId(client);
15
15
  const rpcURL = client.transport.url;
16
16
  const values = _getChainSpecificConstants(chainID, rpcURL);
17
17
  return client.extend(publicActions).readContract({
@@ -27,7 +27,7 @@ export const _eSIMWalletAdmin = async (client) => {
27
27
  * who may actually act.
28
28
  */
29
29
  export const _adminOfRecord = async (client) => {
30
- const chainID = await client.getChainId();
30
+ const chainID = await _chainId(client);
31
31
  const rpcURL = client.transport.url;
32
32
  const values = _getChainSpecificConstants(chainID, rpcURL);
33
33
  return client.extend(publicActions).readContract({
@@ -43,7 +43,7 @@ export const _adminOfRecord = async (client) => {
43
43
  * this alongside `_newRequestedAdmin` to tell them apart.
44
44
  */
45
45
  export const _adminDisabled = async (client) => {
46
- const chainID = await client.getChainId();
46
+ const chainID = await _chainId(client);
47
47
  const rpcURL = client.transport.url;
48
48
  const values = _getChainSpecificConstants(chainID, rpcURL);
49
49
  return client.extend(publicActions).readContract({
@@ -58,7 +58,7 @@ export const _adminDisabled = async (client) => {
58
58
  * paths on the device wallets and eSIM wallets revert `ProtocolPaused`.
59
59
  */
60
60
  export const _paused = async (client) => {
61
- const chainID = await client.getChainId();
61
+ const chainID = await _chainId(client);
62
62
  const rpcURL = client.transport.url;
63
63
  const values = _getChainSpecificConstants(chainID, rpcURL);
64
64
  return client.extend(publicActions).readContract({
@@ -73,7 +73,7 @@ export const _paused = async (client) => {
73
73
  * cap of its own. Never zero.
74
74
  */
75
75
  export const _defaultPriceCapUSDCents = async (client) => {
76
- const chainID = await client.getChainId();
76
+ const chainID = await _chainId(client);
77
77
  const rpcURL = client.transport.url;
78
78
  const values = _getChainSpecificConstants(chainID, rpcURL);
79
79
  return client.extend(publicActions).readContract({
@@ -85,7 +85,7 @@ export const _defaultPriceCapUSDCents = async (client) => {
85
85
  };
86
86
  /** The vault EOA recorded in the registry. */
87
87
  export const _vault = async (client) => {
88
- const chainID = await client.getChainId();
88
+ const chainID = await _chainId(client);
89
89
  const rpcURL = client.transport.url;
90
90
  const values = _getChainSpecificConstants(chainID, rpcURL);
91
91
  return client.extend(publicActions).readContract({
@@ -97,7 +97,7 @@ export const _vault = async (client) => {
97
97
  };
98
98
  /** The pending admin nominated via `requestAdminUpdate` (zero address if none). */
99
99
  export const _newRequestedAdmin = async (client) => {
100
- const chainID = await client.getChainId();
100
+ const chainID = await _chainId(client);
101
101
  const rpcURL = client.transport.url;
102
102
  const values = _getChainSpecificConstants(chainID, rpcURL);
103
103
  return client.extend(publicActions).readContract({
@@ -113,7 +113,7 @@ export const _newRequestedAdmin = async (client) => {
113
113
  * be scheduled instead.
114
114
  */
115
115
  export const _owner = async (client) => {
116
- const chainID = await client.getChainId();
116
+ const chainID = await _chainId(client);
117
117
  const rpcURL = client.transport.url;
118
118
  const values = _getChainSpecificConstants(chainID, rpcURL);
119
119
  return client.extend(publicActions).readContract({
@@ -125,7 +125,7 @@ export const _owner = async (client) => {
125
125
  };
126
126
  /** The upgrade-manager (owner) EOA recorded in the registry. */
127
127
  export const _upgradeManager = async (client) => {
128
- const chainID = await client.getChainId();
128
+ const chainID = await _chainId(client);
129
129
  const rpcURL = client.transport.url;
130
130
  const values = _getChainSpecificConstants(chainID, rpcURL);
131
131
  return client.extend(publicActions).readContract({
@@ -141,7 +141,7 @@ export const _upgradeManager = async (client) => {
141
141
  * been offered to the timelock.
142
142
  */
143
143
  export const _pendingOwner = async (client) => {
144
- const chainID = await client.getChainId();
144
+ const chainID = await _chainId(client);
145
145
  const rpcURL = client.transport.url;
146
146
  const values = _getChainSpecificConstants(chainID, rpcURL);
147
147
  return client.extend(publicActions).readContract({
@@ -153,7 +153,7 @@ export const _pendingOwner = async (client) => {
153
153
  };
154
154
  /** The `DeviceWalletFactory` address wired into the registry. */
155
155
  export const _deviceWalletFactory = async (client) => {
156
- const chainID = await client.getChainId();
156
+ const chainID = await _chainId(client);
157
157
  const rpcURL = client.transport.url;
158
158
  const values = _getChainSpecificConstants(chainID, rpcURL);
159
159
  return client.extend(publicActions).readContract({
@@ -165,7 +165,7 @@ export const _deviceWalletFactory = async (client) => {
165
165
  };
166
166
  /** The `ESIMWalletFactory` address wired into the registry. */
167
167
  export const _eSIMWalletFactory = async (client) => {
168
- const chainID = await client.getChainId();
168
+ const chainID = await _chainId(client);
169
169
  const rpcURL = client.transport.url;
170
170
  const values = _getChainSpecificConstants(chainID, rpcURL);
171
171
  return client.extend(publicActions).readContract({
@@ -177,7 +177,7 @@ export const _eSIMWalletFactory = async (client) => {
177
177
  };
178
178
  /** The EntryPoint the registry recognises. One per chain. */
179
179
  export const _entryPoint = async (client) => {
180
- const chainID = await client.getChainId();
180
+ const chainID = await _chainId(client);
181
181
  const rpcURL = client.transport.url;
182
182
  const values = _getChainSpecificConstants(chainID, rpcURL);
183
183
  return client.extend(publicActions).readContract({
@@ -193,7 +193,7 @@ export const _entryPoint = async (client) => {
193
193
  * failure to carry the protocol's own revert reason.
194
194
  */
195
195
  export const _requireNotPaused = async (client) => {
196
- const chainID = await client.getChainId();
196
+ const chainID = await _chainId(client);
197
197
  const rpcURL = client.transport.url;
198
198
  const values = _getChainSpecificConstants(chainID, rpcURL);
199
199
  await client.extend(publicActions).readContract({
@@ -205,7 +205,7 @@ export const _requireNotPaused = async (client) => {
205
205
  };
206
206
  /** The `LazyWalletRegistry` address wired into the registry. */
207
207
  export const _lazyWalletRegistry = async (client) => {
208
- const chainID = await client.getChainId();
208
+ const chainID = await _chainId(client);
209
209
  const rpcURL = client.transport.url;
210
210
  const values = _getChainSpecificConstants(chainID, rpcURL);
211
211
  return client.extend(publicActions).readContract({
@@ -217,7 +217,7 @@ export const _lazyWalletRegistry = async (client) => {
217
217
  };
218
218
  /** The device wallet registered for a device unique identifier (zero if none). */
219
219
  export const _uniqueIdentifierToDeviceWallet = async (client, deviceIdentifier) => {
220
- const chainID = await client.getChainId();
220
+ const chainID = await _chainId(client);
221
221
  const rpcURL = client.transport.url;
222
222
  const values = _getChainSpecificConstants(chainID, rpcURL);
223
223
  return client.extend(publicActions).readContract({
@@ -232,7 +232,7 @@ export const _uniqueIdentifierToDeviceWallet = async (client, deviceIdentifier)
232
232
  * `bytes32[2]` array takes the element index (`0` or `1`) and returns one key.
233
233
  */
234
234
  export const _deviceWalletToOwner = async (client, deviceWallet, index) => {
235
- const chainID = await client.getChainId();
235
+ const chainID = await _chainId(client);
236
236
  const rpcURL = client.transport.url;
237
237
  const values = _getChainSpecificConstants(chainID, rpcURL);
238
238
  return client.extend(publicActions).readContract({
@@ -244,7 +244,7 @@ export const _deviceWalletToOwner = async (client, deviceWallet, index) => {
244
244
  };
245
245
  /** The device wallet registered for a hash of owner P-256 keys (zero if none). */
246
246
  export const _registeredP256Keys = async (client, hashOfOwnerP256Keys) => {
247
- const chainID = await client.getChainId();
247
+ const chainID = await _chainId(client);
248
248
  const rpcURL = client.transport.url;
249
249
  const values = _getChainSpecificConstants(chainID, rpcURL);
250
250
  return client.extend(publicActions).readContract({
@@ -256,7 +256,7 @@ export const _registeredP256Keys = async (client, hashOfOwnerP256Keys) => {
256
256
  };
257
257
  /** Whether a device wallet is registered/valid. */
258
258
  export const _isDeviceWalletValid = async (client, deviceWallet) => {
259
- const chainID = await client.getChainId();
259
+ const chainID = await _chainId(client);
260
260
  const rpcURL = client.transport.url;
261
261
  const values = _getChainSpecificConstants(chainID, rpcURL);
262
262
  return client.extend(publicActions).readContract({
@@ -276,7 +276,7 @@ export const _isDeviceWalletValid = async (client, deviceWallet) => {
276
276
  * `DeviceWallet.isValidESIMWallet` on the device wallet.
277
277
  */
278
278
  export const _isESIMWalletValid = async (client, eSIMWallet) => {
279
- const chainID = await client.getChainId();
279
+ const chainID = await _chainId(client);
280
280
  const rpcURL = client.transport.url;
281
281
  const values = _getChainSpecificConstants(chainID, rpcURL);
282
282
  return client.extend(publicActions).readContract({
@@ -296,7 +296,7 @@ export const _isESIMWalletValid = async (client, eSIMWallet) => {
296
296
  * this to decide whether an eSIM wallet belongs to the protocol.
297
297
  */
298
298
  export const _isESIMWalletOnStandby = async (client, eSIMWallet) => {
299
- const chainID = await client.getChainId();
299
+ const chainID = await _chainId(client);
300
300
  const rpcURL = client.transport.url;
301
301
  const values = _getChainSpecificConstants(chainID, rpcURL);
302
302
  return client.extend(publicActions).readContract({
@@ -312,7 +312,7 @@ export const _isESIMWalletOnStandby = async (client, eSIMWallet) => {
312
312
  * as soon as history is recorded and well before anything is deployed.
313
313
  */
314
314
  export const _isDeviceIdentifierAlreadyUsed = async (client, deviceUniqueIdentifier) => {
315
- const chainID = await client.getChainId();
315
+ const chainID = await _chainId(client);
316
316
  const rpcURL = client.transport.url;
317
317
  const values = _getChainSpecificConstants(chainID, rpcURL);
318
318
  return client.extend(publicActions).readContract({
@@ -324,7 +324,7 @@ export const _isDeviceIdentifierAlreadyUsed = async (client, deviceUniqueIdentif
324
324
  };
325
325
  /** Whether an eSIM identifier is already held by a wallet. */
326
326
  export const _isESIMIdentifierClaimed = async (client, eSIMUniqueIdentifier) => {
327
- const chainID = await client.getChainId();
327
+ const chainID = await _chainId(client);
328
328
  const rpcURL = client.transport.url;
329
329
  const values = _getChainSpecificConstants(chainID, rpcURL);
330
330
  return client.extend(publicActions).readContract({
@@ -340,7 +340,7 @@ export const _isESIMIdentifierClaimed = async (client, eSIMUniqueIdentifier) =>
340
340
  * belongs to the wallet rather than to whichever device is holding it.
341
341
  */
342
342
  export const _eSIMWalletForIdentifier = async (client, eSIMUniqueIdentifier) => {
343
- const chainID = await client.getChainId();
343
+ const chainID = await _chainId(client);
344
344
  const rpcURL = client.transport.url;
345
345
  const values = _getChainSpecificConstants(chainID, rpcURL);
346
346
  return client.extend(publicActions).readContract({
@@ -356,7 +356,7 @@ export const _eSIMWalletForIdentifier = async (client, eSIMUniqueIdentifier) =>
356
356
  * string version and skip the hashing.
357
357
  */
358
358
  export const _claimedESIMIdentifiers = async (client, hashOfESIMIdentifier) => {
359
- const chainID = await client.getChainId();
359
+ const chainID = await _chainId(client);
360
360
  const rpcURL = client.transport.url;
361
361
  const values = _getChainSpecificConstants(chainID, rpcURL);
362
362
  return client.extend(publicActions).readContract({
@@ -376,7 +376,7 @@ export const _claimedESIMIdentifiers = async (client, hashOfESIMIdentifier) => {
376
376
  * all then refuse it.
377
377
  */
378
378
  export const _requireDeviceIdentifierNotReserved = async (client, deviceUniqueIdentifier) => {
379
- const chainID = await client.getChainId();
379
+ const chainID = await _chainId(client);
380
380
  const rpcURL = client.transport.url;
381
381
  const values = _getChainSpecificConstants(chainID, rpcURL);
382
382
  await client.extend(publicActions).readContract({
@@ -392,7 +392,7 @@ export const _requireDeviceIdentifierNotReserved = async (client, deviceUniqueId
392
392
  * is what stops a non-UUPS address being installed.
393
393
  */
394
394
  export const _proxiableUUID = async (client) => {
395
- const chainID = await client.getChainId();
395
+ const chainID = await _chainId(client);
396
396
  const rpcURL = client.transport.url;
397
397
  const values = _getChainSpecificConstants(chainID, rpcURL);
398
398
  return client.extend(publicActions).readContract({
@@ -404,7 +404,7 @@ export const _proxiableUUID = async (client) => {
404
404
  };
405
405
  /** The OpenZeppelin upgrade interface this proxy speaks, currently `"5.0.0"`. */
406
406
  export const _upgradeInterfaceVersion = async (client) => {
407
- const chainID = await client.getChainId();
407
+ const chainID = await _chainId(client);
408
408
  const rpcURL = client.transport.url;
409
409
  const values = _getChainSpecificConstants(chainID, rpcURL);
410
410
  return client.extend(publicActions).readContract({
@@ -416,7 +416,7 @@ export const _upgradeInterfaceVersion = async (client) => {
416
416
  };
417
417
  /** The payment adapter this registry currently points at. */
418
418
  export const _paymentAdapter = async (client) => {
419
- const chainID = await client.getChainId();
419
+ const chainID = await _chainId(client);
420
420
  const rpcURL = client.transport.url;
421
421
  const values = _getChainSpecificConstants(chainID, rpcURL);
422
422
  return client.extend(publicActions).readContract({
@@ -432,7 +432,7 @@ export const _paymentAdapter = async (client) => {
432
432
  * the contract keys `usedPaymentReferences` by, not the bare reference.
433
433
  */
434
434
  export const _usedPaymentReferences = async (client, scopedReference) => {
435
- const chainID = await client.getChainId();
435
+ const chainID = await _chainId(client);
436
436
  const rpcURL = client.transport.url;
437
437
  const values = _getChainSpecificConstants(chainID, rpcURL);
438
438
  return client.extend(publicActions).readContract({
@@ -1,4 +1,4 @@
1
- import { _getChainSpecificConstants } from "../constants.js";
1
+ import { _chainId, _getChainSpecificConstants } from "../constants.js";
2
2
  import { MissingEOAWalletError, writeContractOrThrow } from "../errors.js";
3
3
  import { Registry } from "../../abis/index.js";
4
4
  // Admin-EOA logic for `Registry`. Most of this is `onlyOwner`, so the `client`
@@ -11,7 +11,7 @@ import { Registry } from "../../abis/index.js";
11
11
  // deployments whose owner is a plain EOA or multisig.
12
12
  /** Wire (or rewire) the LazyWalletRegistry into the Registry. `onlyOwner`. */
13
13
  export const _addOrUpdateLazyWalletRegistryAddress = async (client, lazyWalletRegistry) => {
14
- const chainID = await client.getChainId();
14
+ const chainID = await _chainId(client);
15
15
  const rpcURL = client.transport.url;
16
16
  const values = _getChainSpecificConstants(chainID, rpcURL);
17
17
  if (!client.account)
@@ -19,7 +19,7 @@ export const _addOrUpdateLazyWalletRegistryAddress = async (client, lazyWalletRe
19
19
  return writeContractOrThrow(client, {
20
20
  address: values.factoryAddresses.REGISTRY,
21
21
  chain: values.chain,
22
- account: client.account.address,
22
+ account: client.account,
23
23
  abi: Registry,
24
24
  functionName: 'addOrUpdateLazyWalletRegistryAddress',
25
25
  args: [lazyWalletRegistry]
@@ -27,7 +27,7 @@ export const _addOrUpdateLazyWalletRegistryAddress = async (client, lazyWalletRe
27
27
  };
28
28
  /** Update the vault that receives eSIM payments. `onlyOwner`. */
29
29
  export const _updateVaultAddress = async (client, newVaultAddress) => {
30
- const chainID = await client.getChainId();
30
+ const chainID = await _chainId(client);
31
31
  const rpcURL = client.transport.url;
32
32
  const values = _getChainSpecificConstants(chainID, rpcURL);
33
33
  if (!client.account)
@@ -35,7 +35,7 @@ export const _updateVaultAddress = async (client, newVaultAddress) => {
35
35
  return writeContractOrThrow(client, {
36
36
  address: values.factoryAddresses.REGISTRY,
37
37
  chain: values.chain,
38
- account: client.account.address,
38
+ account: client.account,
39
39
  abi: Registry,
40
40
  functionName: 'updateVaultAddress',
41
41
  args: [newVaultAddress]
@@ -51,7 +51,7 @@ export const _updateVaultAddress = async (client, newVaultAddress) => {
51
51
  * incumbent instead withdraws a pending nomination and hands the role back.
52
52
  */
53
53
  export const _requestAdminUpdate = async (client, newAdmin) => {
54
- const chainID = await client.getChainId();
54
+ const chainID = await _chainId(client);
55
55
  const rpcURL = client.transport.url;
56
56
  const values = _getChainSpecificConstants(chainID, rpcURL);
57
57
  if (!client.account)
@@ -59,7 +59,7 @@ export const _requestAdminUpdate = async (client, newAdmin) => {
59
59
  return writeContractOrThrow(client, {
60
60
  address: values.factoryAddresses.REGISTRY,
61
61
  chain: values.chain,
62
- account: client.account.address,
62
+ account: client.account,
63
63
  abi: Registry,
64
64
  functionName: 'requestAdminUpdate',
65
65
  args: [newAdmin]
@@ -73,7 +73,7 @@ export const _requestAdminUpdate = async (client, newAdmin) => {
73
73
  * rather than passing quietly and leaving the caller believing it acted.
74
74
  */
75
75
  export const _disableAdmin = async (client) => {
76
- const chainID = await client.getChainId();
76
+ const chainID = await _chainId(client);
77
77
  const rpcURL = client.transport.url;
78
78
  const values = _getChainSpecificConstants(chainID, rpcURL);
79
79
  if (!client.account)
@@ -81,7 +81,7 @@ export const _disableAdmin = async (client) => {
81
81
  return writeContractOrThrow(client, {
82
82
  address: values.factoryAddresses.REGISTRY,
83
83
  chain: values.chain,
84
- account: client.account.address,
84
+ account: client.account,
85
85
  abi: Registry,
86
86
  functionName: 'disableAdmin',
87
87
  args: []
@@ -95,7 +95,7 @@ export const _disableAdmin = async (client) => {
95
95
  * incumbent. Reverts if the admin was never suspended.
96
96
  */
97
97
  export const _enableAdmin = async (client) => {
98
- const chainID = await client.getChainId();
98
+ const chainID = await _chainId(client);
99
99
  const rpcURL = client.transport.url;
100
100
  const values = _getChainSpecificConstants(chainID, rpcURL);
101
101
  if (!client.account)
@@ -103,7 +103,7 @@ export const _enableAdmin = async (client) => {
103
103
  return writeContractOrThrow(client, {
104
104
  address: values.factoryAddresses.REGISTRY,
105
105
  chain: values.chain,
106
- account: client.account.address,
106
+ account: client.account,
107
107
  abi: Registry,
108
108
  functionName: 'enableAdmin',
109
109
  args: []
@@ -119,7 +119,7 @@ export const _enableAdmin = async (client) => {
119
119
  * funds through their device wallet's `execute`, which a pause never reaches.
120
120
  */
121
121
  export const _pause = async (client) => {
122
- const chainID = await client.getChainId();
122
+ const chainID = await _chainId(client);
123
123
  const rpcURL = client.transport.url;
124
124
  const values = _getChainSpecificConstants(chainID, rpcURL);
125
125
  if (!client.account)
@@ -127,7 +127,7 @@ export const _pause = async (client) => {
127
127
  return writeContractOrThrow(client, {
128
128
  address: values.factoryAddresses.REGISTRY,
129
129
  chain: values.chain,
130
- account: client.account.address,
130
+ account: client.account,
131
131
  abi: Registry,
132
132
  functionName: 'pause',
133
133
  args: []
@@ -141,7 +141,7 @@ export const _pause = async (client) => {
141
141
  * `unpauseInstantly` if the wait is not acceptable.
142
142
  */
143
143
  export const _unpause = async (client) => {
144
- const chainID = await client.getChainId();
144
+ const chainID = await _chainId(client);
145
145
  const rpcURL = client.transport.url;
146
146
  const values = _getChainSpecificConstants(chainID, rpcURL);
147
147
  if (!client.account)
@@ -149,7 +149,7 @@ export const _unpause = async (client) => {
149
149
  return writeContractOrThrow(client, {
150
150
  address: values.factoryAddresses.REGISTRY,
151
151
  chain: values.chain,
152
- account: client.account.address,
152
+ account: client.account,
153
153
  abi: Registry,
154
154
  functionName: 'unpause',
155
155
  args: []
@@ -164,7 +164,7 @@ export const _unpause = async (client) => {
164
164
  * for every wallet without one of its own.
165
165
  */
166
166
  export const _setDefaultPriceCapUSDCents = async (client, cap) => {
167
- const chainID = await client.getChainId();
167
+ const chainID = await _chainId(client);
168
168
  const rpcURL = client.transport.url;
169
169
  const values = _getChainSpecificConstants(chainID, rpcURL);
170
170
  if (!client.account)
@@ -172,7 +172,7 @@ export const _setDefaultPriceCapUSDCents = async (client, cap) => {
172
172
  return writeContractOrThrow(client, {
173
173
  address: values.factoryAddresses.REGISTRY,
174
174
  chain: values.chain,
175
- account: client.account.address,
175
+ account: client.account,
176
176
  abi: Registry,
177
177
  functionName: 'setDefaultPriceCapUSDCents',
178
178
  args: [cap]
@@ -185,7 +185,7 @@ export const _setDefaultPriceCapUSDCents = async (client, cap) => {
185
185
  * wallet reverts rather than moving.
186
186
  */
187
187
  export const _assignESIMIdentifier = async (client, eSIMWalletAddress, eSIMUniqueIdentifier) => {
188
- const chainID = await client.getChainId();
188
+ const chainID = await _chainId(client);
189
189
  const rpcURL = client.transport.url;
190
190
  const values = _getChainSpecificConstants(chainID, rpcURL);
191
191
  if (!client.account)
@@ -193,7 +193,7 @@ export const _assignESIMIdentifier = async (client, eSIMWalletAddress, eSIMUniqu
193
193
  return writeContractOrThrow(client, {
194
194
  address: values.factoryAddresses.REGISTRY,
195
195
  chain: values.chain,
196
- account: client.account.address,
196
+ account: client.account,
197
197
  abi: Registry,
198
198
  functionName: 'assignESIMIdentifier',
199
199
  args: [eSIMWalletAddress, eSIMUniqueIdentifier]
@@ -209,7 +209,7 @@ export const _assignESIMIdentifier = async (client, eSIMWalletAddress, eSIMUniqu
209
209
  * `_paymentReference` is spendable once per eSIM wallet.
210
210
  */
211
211
  export const _recordSettledPurchase = async (client, eSIMWalletAddress, dataBundleDetail, asset, tokenAmount, paymentReference) => {
212
- const chainID = await client.getChainId();
212
+ const chainID = await _chainId(client);
213
213
  const rpcURL = client.transport.url;
214
214
  const values = _getChainSpecificConstants(chainID, rpcURL);
215
215
  if (!client.account)
@@ -217,7 +217,7 @@ export const _recordSettledPurchase = async (client, eSIMWalletAddress, dataBund
217
217
  return writeContractOrThrow(client, {
218
218
  address: values.factoryAddresses.REGISTRY,
219
219
  chain: values.chain,
220
- account: client.account.address,
220
+ account: client.account,
221
221
  abi: Registry,
222
222
  functionName: 'recordSettledPurchase',
223
223
  args: [eSIMWalletAddress, dataBundleDetail, asset, tokenAmount, paymentReference]
@@ -229,7 +229,7 @@ export const _recordSettledPurchase = async (client, eSIMWalletAddress, dataBund
229
229
  * newly nominated admin EOA.
230
230
  */
231
231
  export const _acceptAdminUpdate = async (client) => {
232
- const chainID = await client.getChainId();
232
+ const chainID = await _chainId(client);
233
233
  const rpcURL = client.transport.url;
234
234
  const values = _getChainSpecificConstants(chainID, rpcURL);
235
235
  if (!client.account)
@@ -237,7 +237,7 @@ export const _acceptAdminUpdate = async (client) => {
237
237
  return writeContractOrThrow(client, {
238
238
  address: values.factoryAddresses.REGISTRY,
239
239
  chain: values.chain,
240
- account: client.account.address,
240
+ account: client.account,
241
241
  abi: Registry,
242
242
  functionName: 'acceptAdminUpdate',
243
243
  args: []
@@ -253,7 +253,7 @@ export const _acceptAdminUpdate = async (client) => {
253
253
  * accepts for every contract at once and needs no delay.
254
254
  */
255
255
  export const _acceptOwnership = async (client) => {
256
- const chainID = await client.getChainId();
256
+ const chainID = await _chainId(client);
257
257
  const rpcURL = client.transport.url;
258
258
  const values = _getChainSpecificConstants(chainID, rpcURL);
259
259
  if (!client.account)
@@ -261,7 +261,7 @@ export const _acceptOwnership = async (client) => {
261
261
  return writeContractOrThrow(client, {
262
262
  address: values.factoryAddresses.REGISTRY,
263
263
  chain: values.chain,
264
- account: client.account.address,
264
+ account: client.account,
265
265
  abi: Registry,
266
266
  functionName: 'acceptOwnership',
267
267
  args: []
@@ -282,7 +282,7 @@ export const _acceptOwnership = async (client) => {
282
282
  * ownership where it is rather than stranding it.
283
283
  */
284
284
  export const _transferOwnershipCall = async (client, newOwner) => {
285
- const chainID = await client.getChainId();
285
+ const chainID = await _chainId(client);
286
286
  const rpcURL = client.transport.url;
287
287
  const values = _getChainSpecificConstants(chainID, rpcURL);
288
288
  return {
@@ -305,7 +305,7 @@ export const _transferOwnershipCall = async (client, newOwner) => {
305
305
  * again ends the proxy's life. Diff the storage layout before scheduling.
306
306
  */
307
307
  export const _upgradeCall = async (client, newImplementation, data = '0x') => {
308
- const chainID = await client.getChainId();
308
+ const chainID = await _chainId(client);
309
309
  const rpcURL = client.transport.url;
310
310
  const values = _getChainSpecificConstants(chainID, rpcURL);
311
311
  return {
@@ -54,11 +54,24 @@ export const customErrors = {
54
54
  MISSING_SMART_WALLET: "Error: Client does not have smart wallet account associated",
55
55
  MISSING_EOA_WALLET: "Error: Client does not have EOA wallet associated"
56
56
  };
57
+ // A client's RPC URL is fixed, so its chain id is too. Asking once per client
58
+ // saves every later SDK call a round trip to the node.
59
+ const chainIds = new WeakMap();
60
+ export const _chainId = (client) => {
61
+ let chainId = chainIds.get(client);
62
+ if (!chainId) {
63
+ chainId = client.getChainId();
64
+ chainIds.set(client, chainId);
65
+ // A failed lookup is not remembered, so the next call asks again.
66
+ chainId.catch(() => chainIds.delete(client));
67
+ }
68
+ return chainId;
69
+ };
57
70
  export const _extractChainID = async (client) => {
58
71
  if (!client) {
59
72
  throw new InvalidClientError();
60
73
  }
61
- return client.getChainId();
74
+ return _chainId(client);
62
75
  };
63
76
  // Maps each supported chain id to its factory-address book + viem chain. Base
64
77
  // Mainnet is listed with '0x' placeholders so the guard below rejects it with a
@@ -1,6 +1,8 @@
1
1
  import { encodeFunctionData, getContract } from "viem";
2
- import { DeviceWallet } from "../abis/index.js";
2
+ import { DeviceWallet, ESIMWalletFactory } from "../abis/index.js";
3
3
  import { MissingSmartWalletError } from "./errors.js";
4
+ import { _chainId, _getChainSpecificConstants } from "./constants.js";
5
+ import { _getESIMWalletCounterFactualAddress } from "./eSIMWalletFactory.js";
4
6
  // A userOp from a device wallet runs through `execute`, so at the target contract
5
7
  // msg.sender is the device-wallet account itself. That constrains which DeviceWallet
6
8
  // functions this surface can expose:
@@ -72,6 +74,38 @@ export const _addESIMWallet = async (client, address, eSIMWalletAddress) => {
72
74
  }]
73
75
  });
74
76
  };
77
+ /**
78
+ * Deploy an eSIM wallet for this device wallet and bind it, in one user operation.
79
+ *
80
+ * Fund access cannot be granted at bind time, so `grantAccessToFunds` adds a
81
+ * `toggleAccessToFunds` after the bind in the same operation. The device wallet
82
+ * must already be registered (`registry.isDeviceWalletValid`), or the factory
83
+ * refuses it.
84
+ */
85
+ export const _deployAndBindESIMWallet = async (client, address, salt, grantAccessToFunds) => {
86
+ const chainID = await _chainId(client);
87
+ const rpcURL = client.transport.url;
88
+ const values = _getChainSpecificConstants(chainID, rpcURL);
89
+ if (!client.account)
90
+ throw new MissingSmartWalletError();
91
+ const eSIMWalletAddress = await _getESIMWalletCounterFactualAddress(client, address, salt);
92
+ const self = (functionName, hasAccessToFunds) => ({
93
+ to: address,
94
+ data: encodeFunctionData({ abi: DeviceWallet, functionName, args: [eSIMWalletAddress, hasAccessToFunds] })
95
+ });
96
+ const userOpHash = await client.sendUserOperation({
97
+ account: client.account,
98
+ calls: [
99
+ {
100
+ to: values.factoryAddresses.ESIM_WALLET_FACTORY,
101
+ data: encodeFunctionData({ abi: ESIMWalletFactory, functionName: "deployESIMWallet", args: [address, salt] })
102
+ },
103
+ self("addESIMWallet", false),
104
+ ...(grantAccessToFunds ? [self("toggleAccessToFunds", true)] : [])
105
+ ]
106
+ });
107
+ return { userOpHash, eSIMWalletAddress };
108
+ };
75
109
  /**
76
110
  * Release an eSIM wallet and put it on standby for a transfer.
77
111
  *