kokio-sdk 1.1.0 → 2.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 (106) 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 +7 -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 +26 -15
  29. package/dist/esm/logic/admin/deviceWalletFactory.eoa.js +69 -48
  30. package/dist/esm/logic/admin/eSIMWallet.eoa.js +5 -7
  31. package/dist/esm/logic/admin/eSIMWalletFactory.eoa.js +79 -11
  32. package/dist/esm/logic/admin/lazyWalletRegistry.eoa.js +333 -22
  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 +276 -6
  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 +94 -1
  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 +3 -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/deviceWalletClass.d.ts +22 -2569
  72. package/dist/types/interface/deviceWalletFactoryClass.d.ts +10 -2564
  73. package/dist/types/interface/eSIMWalletClass.d.ts +11 -8
  74. package/dist/types/interface/eSIMWalletFactoryClass.d.ts +5 -2565
  75. package/dist/types/interface/registryClass.d.ts +19 -0
  76. package/dist/types/interface/smartAccountClass.d.ts +6 -2568
  77. package/dist/types/logic/P256Verifier.d.ts +2 -2
  78. package/dist/types/logic/account-kit/createSmartAccount.d.ts +43 -19
  79. package/dist/types/logic/admin/deviceWallet.eoa.d.ts +15 -9
  80. package/dist/types/logic/admin/deviceWalletFactory.eoa.d.ts +34 -23
  81. package/dist/types/logic/admin/eSIMWallet.eoa.d.ts +0 -5
  82. package/dist/types/logic/admin/eSIMWalletFactory.eoa.d.ts +27 -9
  83. package/dist/types/logic/admin/lazyWalletRegistry.eoa.d.ts +102 -10
  84. package/dist/types/logic/admin/protocolAdmin.eoa.d.ts +163 -0
  85. package/dist/types/logic/admin/reads/deviceWallet.reads.d.ts +28 -8
  86. package/dist/types/logic/admin/reads/deviceWalletFactory.reads.d.ts +45 -14
  87. package/dist/types/logic/admin/reads/eSIMWallet.reads.d.ts +25 -6
  88. package/dist/types/logic/admin/reads/eSIMWalletFactory.reads.d.ts +21 -6
  89. package/dist/types/logic/admin/reads/lazyWalletRegistry.reads.d.ts +44 -11
  90. package/dist/types/logic/admin/reads/protocolAdmin.reads.d.ts +53 -0
  91. package/dist/types/logic/admin/reads/registry.reads.d.ts +105 -9
  92. package/dist/types/logic/admin/registry.eoa.d.ts +102 -5
  93. package/dist/types/logic/constants.d.ts +2 -0
  94. package/dist/types/logic/deviceWallet.d.ts +78 -6
  95. package/dist/types/logic/deviceWalletFactory.d.ts +32 -3
  96. package/dist/types/logic/eSIMWallet.d.ts +48 -7
  97. package/dist/types/logic/eSIMWalletFactory.d.ts +3 -3
  98. package/dist/types/logic/errors.d.ts +61 -1
  99. package/dist/types/logic/registry.d.ts +78 -0
  100. package/dist/types/types-export.d.ts +1 -1
  101. package/dist/types/types.d.ts +111 -1
  102. package/package.json +11 -13
  103. package/dist/esm/interface/lazyWalletRegistryClass.js +0 -10
  104. package/dist/esm/logic/lazyWalletRegistry.js +0 -19
  105. package/dist/types/interface/lazyWalletRegistryClass.d.ts +0 -6
  106. package/dist/types/logic/lazyWalletRegistry.d.ts +0 -2
@@ -1,15 +1,13 @@
1
1
  import { publicActions } from "viem";
2
2
  import { _getChainSpecificConstants } from "../../constants.js";
3
3
  import { DeviceWalletFactory } from "../../../abis/index.js";
4
- /**
5
- * Read-only admin logic for `DeviceWalletFactory` - the contract's public
6
- * storage getters and `view` functions, surfaced for the backend.
7
- *
8
- * A viem `WalletClient` carries no public actions, so each read extends it with
9
- * `publicActions` (reusing the same transport, so it also works under an anvil
10
- * fork) before calling `readContract`. Reads need no EOA account, so there is no
11
- * `MissingEOAWalletError` guard.
12
- */
4
+ // Read-only admin logic for `DeviceWalletFactory` - the contract's public
5
+ // storage getters and `view` functions, surfaced for the backend.
6
+ //
7
+ // A viem `WalletClient` carries no public actions, so each read extends it with
8
+ // `publicActions` (reusing the same transport, so it also works under an anvil
9
+ // fork) before calling `readContract`. Reads need no EOA account, so there is no
10
+ // `MissingEOAWalletError` guard.
13
11
  /** The admin EOA (`eSIMWalletAdmin`) currently set on the factory. */
14
12
  export const _eSIMWalletAdmin = async (client) => {
15
13
  const chainID = await client.getChainId();
@@ -22,54 +20,87 @@ export const _eSIMWalletAdmin = async (client) => {
22
20
  args: []
23
21
  });
24
22
  };
25
- /** The vault EOA that receives eSIM payments. */
26
- export const _vault = async (client) => {
23
+ /** Whether a device wallet has been registered with the factory. */
24
+ export const _deviceWalletInfoAdded = async (client, deviceWallet) => {
27
25
  const chainID = await client.getChainId();
28
26
  const rpcURL = client.transport.url;
29
27
  const values = _getChainSpecificConstants(chainID, rpcURL);
30
28
  return client.extend(publicActions).readContract({
31
29
  address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
32
30
  abi: DeviceWalletFactory,
33
- functionName: "vault",
34
- args: []
31
+ functionName: "deviceWalletInfoAdded",
32
+ args: [deviceWallet]
35
33
  });
36
34
  };
37
- /** The pending admin proposed via `requestAdminUpdate` (zero address if none). */
38
- export const _newRequestedAdmin = async (client) => {
35
+ /** The current device-wallet beacon implementation. */
36
+ export const _getCurrentDeviceWalletImplementation = async (client) => {
39
37
  const chainID = await client.getChainId();
40
38
  const rpcURL = client.transport.url;
41
39
  const values = _getChainSpecificConstants(chainID, rpcURL);
42
40
  return client.extend(publicActions).readContract({
43
41
  address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
44
42
  abi: DeviceWalletFactory,
45
- functionName: "newRequestedAdmin",
43
+ functionName: "getCurrentDeviceWalletImplementation",
46
44
  args: []
47
45
  });
48
46
  };
49
- /** Whether a device wallet has been registered with the factory. */
50
- export const _deviceWalletInfoAdded = async (client, deviceWallet) => {
47
+ /**
48
+ * Check an identifier and owner key before deploying. Answers the zero address
49
+ * when both are free, or the wallet already holding one of them.
50
+ *
51
+ * `createAccount` runs inside EntryPoint validation, where the 4337 rules bar it
52
+ * from reading the registry, so it cannot see that an identifier or a key is
53
+ * taken: it deploys a second wallet at a fresh address and the
54
+ * `postCreateAccount` that would register it fails afterwards. Checking here
55
+ * first is what stops that.
56
+ *
57
+ * Reverts on an empty identifier or a key that is not a point on the P256 curve.
58
+ */
59
+ export const _preCreateAccountValidation = async (client, deviceUniqueIdentifier, deviceWalletOwnerKey) => {
51
60
  const chainID = await client.getChainId();
52
61
  const rpcURL = client.transport.url;
53
62
  const values = _getChainSpecificConstants(chainID, rpcURL);
54
63
  return client.extend(publicActions).readContract({
55
64
  address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
56
65
  abi: DeviceWalletFactory,
57
- functionName: "deviceWalletInfoAdded",
58
- args: [deviceWallet]
66
+ functionName: "preCreateAccountValidation",
67
+ args: [deviceUniqueIdentifier, deviceWalletOwnerKey]
59
68
  });
60
69
  };
61
- /** The current device-wallet beacon implementation. */
62
- export const _getCurrentDeviceWalletImplementation = async (client) => {
70
+ const _addressGetter = async (client, functionName) => {
63
71
  const chainID = await client.getChainId();
64
72
  const rpcURL = client.transport.url;
65
73
  const values = _getChainSpecificConstants(chainID, rpcURL);
66
74
  return client.extend(publicActions).readContract({
67
75
  address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
68
76
  abi: DeviceWalletFactory,
69
- functionName: "getCurrentDeviceWalletImplementation",
77
+ functionName,
70
78
  args: []
71
79
  });
72
80
  };
81
+ /**
82
+ * The beacon every device wallet reads its implementation from. One update moves
83
+ * all of them and no wallet can decline it.
84
+ */
85
+ export const _beacon = (client) => _addressGetter(client, "beacon");
86
+ /** The registry the factory writes new wallets into. */
87
+ export const _registry = (client) => _addressGetter(client, "registry");
88
+ /** The EntryPoint baked into every device wallet this factory deploys. */
89
+ export const _entryPoint = (client) => _addressGetter(client, "entryPoint");
90
+ /** The contract new device wallets verify WebAuthn assertions through. */
91
+ export const _verifier = (client) => _addressGetter(client, "verifier");
92
+ /**
93
+ * Who holds `onlyOwner` on the factory. On the live deployment this is the
94
+ * `ProtocolAdmin` timelock, so an owner call sent from an EOA reverts and has to
95
+ * be scheduled instead.
96
+ */
97
+ export const _owner = (client) => _addressGetter(client, "owner");
98
+ /**
99
+ * The address a `transferOwnership` is waiting on. Worth reading before
100
+ * `protocolAdmin.acceptOwnershipBatch`, which reverts on any target that has not
101
+ * been offered to the timelock.
102
+ */
103
+ export const _pendingOwner = (client) => _addressGetter(client, "pendingOwner");
73
104
  /**
74
105
  * The counterfactual (CREATE2) device-wallet address for an owner key. On-chain
75
106
  * arg order is `(ownerKey, uid, salt)` - note this differs from `createAccount`.
@@ -85,3 +116,31 @@ export const _getCounterFactualAddress = async (client, deviceWalletOwnerKey, de
85
116
  args: [deviceWalletOwnerKey, deviceUniqueIdentifier, salt]
86
117
  });
87
118
  };
119
+ /**
120
+ * The ERC-1822 storage slot this proxy keeps its implementation in. An upgrade
121
+ * reverts unless the incoming implementation answers with the same value, which
122
+ * is what stops a non-UUPS address being installed.
123
+ */
124
+ export const _proxiableUUID = async (client) => {
125
+ const chainID = await client.getChainId();
126
+ const rpcURL = client.transport.url;
127
+ const values = _getChainSpecificConstants(chainID, rpcURL);
128
+ return client.extend(publicActions).readContract({
129
+ address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
130
+ abi: DeviceWalletFactory,
131
+ functionName: "proxiableUUID",
132
+ args: []
133
+ });
134
+ };
135
+ /** The OpenZeppelin upgrade interface this proxy speaks, currently `"5.0.0"`. */
136
+ export const _upgradeInterfaceVersion = async (client) => {
137
+ const chainID = await client.getChainId();
138
+ const rpcURL = client.transport.url;
139
+ const values = _getChainSpecificConstants(chainID, rpcURL);
140
+ return client.extend(publicActions).readContract({
141
+ address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
142
+ abi: DeviceWalletFactory,
143
+ functionName: "UPGRADE_INTERFACE_VERSION",
144
+ args: []
145
+ });
146
+ };
@@ -1,11 +1,9 @@
1
1
  import { publicActions } from "viem";
2
2
  import { ESIMWallet } from "../../../abis/index.js";
3
- /**
4
- * Read-only admin logic targeting a specific `ESIMWallet` instance (its address
5
- * is passed in). Surfaces the instance's public storage getters + `owner` view
6
- * for the backend. Each read extends the `WalletClient` with `publicActions`; no
7
- * EOA account is required.
8
- */
3
+ // Read-only admin logic targeting a specific `ESIMWallet` instance (its address
4
+ // is passed in). Surfaces the instance's public storage getters + `owner` view
5
+ // for the backend. Each read extends the `WalletClient` with `publicActions`; no
6
+ // EOA account is required.
9
7
  /** The `ESIMWalletFactory` that deployed this eSIM wallet. */
10
8
  export const _eSIMWalletFactory = async (client, eSIMWalletAddress) => {
11
9
  return client.extend(publicActions).readContract({
@@ -24,6 +22,20 @@ export const _eSIMUniqueIdentifier = async (client, eSIMWalletAddress) => {
24
22
  args: []
25
23
  });
26
24
  };
25
+ /**
26
+ * This wallet's own price ceiling in wei. Zero means it follows the registry's
27
+ * `defaultDataBundlePriceCap` instead, which is the state a fresh wallet and a
28
+ * newly handed-over wallet both start in. Worth reading before naming a price on
29
+ * `buyDataBundle`, since a price over the ceiling reverts.
30
+ */
31
+ export const _dataBundlePriceCap = async (client, eSIMWalletAddress) => {
32
+ return client.extend(publicActions).readContract({
33
+ address: eSIMWalletAddress,
34
+ abi: ESIMWallet,
35
+ functionName: "dataBundlePriceCap",
36
+ args: []
37
+ });
38
+ };
27
39
  /** The pending owner proposed via `requestTransferOwnership` (zero if none). */
28
40
  export const _newRequestedOwner = async (client, eSIMWalletAddress) => {
29
41
  return client.extend(publicActions).readContract({
@@ -42,3 +54,35 @@ export const _owner = async (client, eSIMWalletAddress) => {
42
54
  args: []
43
55
  });
44
56
  };
57
+ /**
58
+ * The device wallet this eSIM wallet belongs to. Tracks `owner` today, but it is
59
+ * a separate storage slot with its own typed getter, so read whichever one the
60
+ * calling code actually means.
61
+ */
62
+ export const _deviceWallet = async (client, eSIMWalletAddress) => {
63
+ return client.extend(publicActions).readContract({
64
+ address: eSIMWalletAddress,
65
+ abi: ESIMWallet,
66
+ functionName: "deviceWallet",
67
+ args: []
68
+ });
69
+ };
70
+ /**
71
+ * One data bundle purchase, by position. The array holds every purchase this
72
+ * wallet has made, and for a wallet that started life on the fiat path it also
73
+ * holds the pre-deployment purchases the lazy registry copies in.
74
+ *
75
+ * The contract publishes no length getter, so there is no way to ask how many
76
+ * entries exist. Read upwards from zero until a call reverts, or track the count
77
+ * from the `DataBundleBought` and `TransactionHistoryPopulated` events, whose
78
+ * `_totalEntries` is the length after the batch landed.
79
+ */
80
+ export const _transactionHistory = async (client, eSIMWalletAddress, index) => {
81
+ const [dataBundleID, dataBundlePrice] = await client.extend(publicActions).readContract({
82
+ address: eSIMWalletAddress,
83
+ abi: ESIMWallet,
84
+ functionName: "transactionHistory",
85
+ args: [index]
86
+ });
87
+ return { dataBundleID, dataBundlePrice };
88
+ };
@@ -1,11 +1,9 @@
1
1
  import { publicActions } from "viem";
2
2
  import { _getChainSpecificConstants } from "../../constants.js";
3
3
  import { ESIMWalletFactory } from "../../../abis/index.js";
4
- /**
5
- * Read-only admin logic for `ESIMWalletFactory` - its public storage getter and
6
- * `view` function, surfaced for the backend. Each read extends the `WalletClient`
7
- * with `publicActions` (no EOA account required).
8
- */
4
+ // Read-only admin logic for `ESIMWalletFactory` - its public storage getter and
5
+ // `view` function, surfaced for the backend. Each read extends the `WalletClient`
6
+ // with `publicActions` (no EOA account required).
9
7
  /** Whether an eSIM wallet was deployed by this factory. */
10
8
  export const _isESIMWalletDeployed = async (client, eSIMWallet) => {
11
9
  const chainID = await client.getChainId();
@@ -30,3 +28,63 @@ export const _getCurrentESIMWalletImplementation = async (client) => {
30
28
  args: []
31
29
  });
32
30
  };
31
+ /**
32
+ * The ERC-1822 storage slot this proxy keeps its implementation in. An upgrade
33
+ * reverts unless the incoming implementation answers with the same value, which
34
+ * is what stops a non-UUPS address being installed.
35
+ */
36
+ export const _proxiableUUID = async (client) => {
37
+ const chainID = await client.getChainId();
38
+ const rpcURL = client.transport.url;
39
+ const values = _getChainSpecificConstants(chainID, rpcURL);
40
+ return client.extend(publicActions).readContract({
41
+ address: values.factoryAddresses.ESIM_WALLET_FACTORY,
42
+ abi: ESIMWalletFactory,
43
+ functionName: "proxiableUUID",
44
+ args: []
45
+ });
46
+ };
47
+ /** The OpenZeppelin upgrade interface this proxy speaks, currently `"5.0.0"`. */
48
+ export const _upgradeInterfaceVersion = async (client) => {
49
+ const chainID = await client.getChainId();
50
+ const rpcURL = client.transport.url;
51
+ const values = _getChainSpecificConstants(chainID, rpcURL);
52
+ return client.extend(publicActions).readContract({
53
+ address: values.factoryAddresses.ESIM_WALLET_FACTORY,
54
+ abi: ESIMWalletFactory,
55
+ functionName: "UPGRADE_INTERFACE_VERSION",
56
+ args: []
57
+ });
58
+ };
59
+ /**
60
+ * Who holds `onlyOwner` here. On the live deployment this is the
61
+ * `ProtocolAdmin` timelock, so an owner call sent from an EOA reverts and has to
62
+ * be scheduled instead.
63
+ */
64
+ export const _owner = async (client) => {
65
+ const chainID = await client.getChainId();
66
+ const rpcURL = client.transport.url;
67
+ const values = _getChainSpecificConstants(chainID, rpcURL);
68
+ return client.extend(publicActions).readContract({
69
+ address: values.factoryAddresses.ESIM_WALLET_FACTORY,
70
+ abi: ESIMWalletFactory,
71
+ functionName: "owner",
72
+ args: []
73
+ });
74
+ };
75
+ /**
76
+ * The address a `transferOwnership` is waiting on. Worth reading before
77
+ * `protocolAdmin.acceptOwnershipBatch`, which reverts on any target that has not
78
+ * been offered to the timelock.
79
+ */
80
+ export const _pendingOwner = async (client) => {
81
+ const chainID = await client.getChainId();
82
+ const rpcURL = client.transport.url;
83
+ const values = _getChainSpecificConstants(chainID, rpcURL);
84
+ return client.extend(publicActions).readContract({
85
+ address: values.factoryAddresses.ESIM_WALLET_FACTORY,
86
+ abi: ESIMWalletFactory,
87
+ functionName: "pendingOwner",
88
+ args: []
89
+ });
90
+ };
@@ -1,16 +1,14 @@
1
1
  import { publicActions } from "viem";
2
2
  import { _getChainSpecificConstants } from "../../constants.js";
3
3
  import { LazyWalletRegistry } from "../../../abis/index.js";
4
- /**
5
- * Read-only admin logic for `LazyWalletRegistry` - its public storage getters,
6
- * surfaced for the backend's fiat/lazy provisioning flows. Each read extends the
7
- * `WalletClient` with `publicActions`; no EOA account is required.
8
- *
9
- * Note: `deviceIdentifierToESIMDetails` and
10
- * `eSIMIdentifiersAssociatedWithDeviceIdentifier` back dynamic arrays on chain,
11
- * so their auto-generated getters take an element `index` and return one entry -
12
- * callers iterate indices to read the whole list (there is no full-array getter).
13
- */
4
+ // Read-only admin logic for `LazyWalletRegistry` - its public storage getters,
5
+ // surfaced for the backend's fiat/lazy provisioning flows. Each read extends the
6
+ // `WalletClient` with `publicActions`; no EOA account is required.
7
+ //
8
+ // Note: `deviceIdentifierToESIMDetails` and
9
+ // `eSIMIdentifiersAssociatedWithDeviceIdentifier` back dynamic arrays on chain,
10
+ // so their auto-generated getters take an element `index` and return one entry -
11
+ // callers iterate indices to read the whole list (there is no full-array getter).
14
12
  /** The upgrade-manager (owner) EOA of the lazy registry. */
15
13
  export const _upgradeManager = async (client) => {
16
14
  const chainID = await client.getChainId();
@@ -48,6 +46,109 @@ export const _deviceIdentifierToESIMDetails = async (client, deviceIdentifier, e
48
46
  });
49
47
  return { dataBundleID, dataBundlePrice };
50
48
  };
49
+ /** Most eSIM wallets one `deployLazyWalletAndSetESIMIdentifier` call will deploy. */
50
+ export const _maxESIMWalletsPerCall = async (client) => {
51
+ const chainID = await client.getChainId();
52
+ const rpcURL = client.transport.url;
53
+ const values = _getChainSpecificConstants(chainID, rpcURL);
54
+ return client.extend(publicActions).readContract({
55
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
56
+ abi: LazyWalletRegistry,
57
+ functionName: "MAX_ESIM_WALLETS_PER_CALL",
58
+ args: []
59
+ });
60
+ };
61
+ /** Most history entries one `setHistoryForLazyWallet` call will copy. */
62
+ export const _maxHistoryEntriesPerCall = async (client) => {
63
+ const chainID = await client.getChainId();
64
+ const rpcURL = client.transport.url;
65
+ const values = _getChainSpecificConstants(chainID, rpcURL);
66
+ return client.extend(publicActions).readContract({
67
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
68
+ abi: LazyWalletRegistry,
69
+ functionName: "MAX_HISTORY_ENTRIES_PER_CALL",
70
+ args: []
71
+ });
72
+ };
73
+ /**
74
+ * How many of a device's eSIM wallets are already deployed. Non-zero exactly when
75
+ * the lazy route ran the device's first batch, so it doubles as the marker for
76
+ * the route itself.
77
+ */
78
+ export const _eSIMWalletsDeployed = async (client, deviceIdentifier) => {
79
+ const chainID = await client.getChainId();
80
+ const rpcURL = client.transport.url;
81
+ const values = _getChainSpecificConstants(chainID, rpcURL);
82
+ return client.extend(publicActions).readContract({
83
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
84
+ abi: LazyWalletRegistry,
85
+ functionName: "eSIMWalletsDeployed",
86
+ args: [deviceIdentifier]
87
+ });
88
+ };
89
+ /** Salt the device's first deployment batch started from. Every later batch derives from it. */
90
+ export const _lazyDeploymentSalt = async (client, deviceIdentifier) => {
91
+ const chainID = await client.getChainId();
92
+ const rpcURL = client.transport.url;
93
+ const values = _getChainSpecificConstants(chainID, rpcURL);
94
+ return client.extend(publicActions).readContract({
95
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
96
+ abi: LazyWalletRegistry,
97
+ functionName: "lazyDeploymentSalt",
98
+ args: [deviceIdentifier]
99
+ });
100
+ };
101
+ /**
102
+ * The eSIM wallet this registry deployed for an identifier. Zero for anything it
103
+ * did not deploy, which is what authorises the history copy.
104
+ */
105
+ export const _lazyDeployedESIMWallet = async (client, eSIMIdentifier) => {
106
+ const chainID = await client.getChainId();
107
+ const rpcURL = client.transport.url;
108
+ const values = _getChainSpecificConstants(chainID, rpcURL);
109
+ return client.extend(publicActions).readContract({
110
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
111
+ abi: LazyWalletRegistry,
112
+ functionName: "lazyDeployedESIMWallet",
113
+ args: [eSIMIdentifier]
114
+ });
115
+ };
116
+ /** How many of an eSIM's stored purchase entries have already reached its wallet. */
117
+ export const _historyEntriesCopied = async (client, eSIMIdentifier) => {
118
+ const chainID = await client.getChainId();
119
+ const rpcURL = client.transport.url;
120
+ const values = _getChainSpecificConstants(chainID, rpcURL);
121
+ return client.extend(publicActions).readContract({
122
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
123
+ abi: LazyWalletRegistry,
124
+ functionName: "historyEntriesCopied",
125
+ args: [eSIMIdentifier]
126
+ });
127
+ };
128
+ /** Whether a device identifier has purchases recorded against it here. */
129
+ export const _isDeviceIdentifierReserved = async (client, deviceIdentifier) => {
130
+ const chainID = await client.getChainId();
131
+ const rpcURL = client.transport.url;
132
+ const values = _getChainSpecificConstants(chainID, rpcURL);
133
+ return client.extend(publicActions).readContract({
134
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
135
+ abi: LazyWalletRegistry,
136
+ functionName: "isDeviceIdentifierReserved",
137
+ args: [deviceIdentifier]
138
+ });
139
+ };
140
+ /** Whether an eSIM identifier is bound to a device here. */
141
+ export const _isESIMIdentifierReserved = async (client, eSIMIdentifier) => {
142
+ const chainID = await client.getChainId();
143
+ const rpcURL = client.transport.url;
144
+ const values = _getChainSpecificConstants(chainID, rpcURL);
145
+ return client.extend(publicActions).readContract({
146
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
147
+ abi: LazyWalletRegistry,
148
+ functionName: "isESIMIdentifierReserved",
149
+ args: [eSIMIdentifier]
150
+ });
151
+ };
51
152
  /** One eSIM identifier associated with a device identifier, by array index. */
52
153
  export const _eSIMIdentifiersAssociatedWithDeviceIdentifier = async (client, deviceIdentifier, index) => {
53
154
  const chainID = await client.getChainId();
@@ -60,3 +161,63 @@ export const _eSIMIdentifiersAssociatedWithDeviceIdentifier = async (client, dev
60
161
  args: [deviceIdentifier, index]
61
162
  });
62
163
  };
164
+ /**
165
+ * The ERC-1822 storage slot this proxy keeps its implementation in. An upgrade
166
+ * reverts unless the incoming implementation answers with the same value, which
167
+ * is what stops a non-UUPS address being installed.
168
+ */
169
+ export const _proxiableUUID = async (client) => {
170
+ const chainID = await client.getChainId();
171
+ const rpcURL = client.transport.url;
172
+ const values = _getChainSpecificConstants(chainID, rpcURL);
173
+ return client.extend(publicActions).readContract({
174
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
175
+ abi: LazyWalletRegistry,
176
+ functionName: "proxiableUUID",
177
+ args: []
178
+ });
179
+ };
180
+ /** The OpenZeppelin upgrade interface this proxy speaks, currently `"5.0.0"`. */
181
+ export const _upgradeInterfaceVersion = async (client) => {
182
+ const chainID = await client.getChainId();
183
+ const rpcURL = client.transport.url;
184
+ const values = _getChainSpecificConstants(chainID, rpcURL);
185
+ return client.extend(publicActions).readContract({
186
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
187
+ abi: LazyWalletRegistry,
188
+ functionName: "UPGRADE_INTERFACE_VERSION",
189
+ args: []
190
+ });
191
+ };
192
+ /**
193
+ * Who holds `onlyOwner` here. On the live deployment this is the
194
+ * `ProtocolAdmin` timelock, so an owner call sent from an EOA reverts and has to
195
+ * be scheduled instead.
196
+ */
197
+ export const _owner = async (client) => {
198
+ const chainID = await client.getChainId();
199
+ const rpcURL = client.transport.url;
200
+ const values = _getChainSpecificConstants(chainID, rpcURL);
201
+ return client.extend(publicActions).readContract({
202
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
203
+ abi: LazyWalletRegistry,
204
+ functionName: "owner",
205
+ args: []
206
+ });
207
+ };
208
+ /**
209
+ * The address a `transferOwnership` is waiting on. Worth reading before
210
+ * `protocolAdmin.acceptOwnershipBatch`, which reverts on any target that has not
211
+ * been offered to the timelock.
212
+ */
213
+ export const _pendingOwner = async (client) => {
214
+ const chainID = await client.getChainId();
215
+ const rpcURL = client.transport.url;
216
+ const values = _getChainSpecificConstants(chainID, rpcURL);
217
+ return client.extend(publicActions).readContract({
218
+ address: values.factoryAddresses.LAZY_WALLET_REGISTRY,
219
+ abi: LazyWalletRegistry,
220
+ functionName: "pendingOwner",
221
+ args: []
222
+ });
223
+ };
@@ -0,0 +1,154 @@
1
+ import { publicActions } from "viem";
2
+ import { _getChainSpecificConstants } from "../../constants.js";
3
+ import { ProtocolAdmin } from "../../../abis/index.js";
4
+ // Read-only logic for `ProtocolAdmin`, the timelock that owns the four
5
+ // upgradeable contracts. Every read extends the `WalletClient` with
6
+ // `publicActions`; no EOA account is required.
7
+ /** Operation lifecycle, matching the on-chain `OperationState` enum. */
8
+ export var OperationState;
9
+ (function (OperationState) {
10
+ OperationState[OperationState["Unset"] = 0] = "Unset";
11
+ OperationState[OperationState["Waiting"] = 1] = "Waiting";
12
+ OperationState[OperationState["Ready"] = 2] = "Ready";
13
+ OperationState[OperationState["Done"] = 3] = "Done";
14
+ })(OperationState || (OperationState = {}));
15
+ const _resolve = async (client) => {
16
+ const chainID = await client.getChainId();
17
+ const rpcURL = client.transport.url;
18
+ return _getChainSpecificConstants(chainID, rpcURL);
19
+ };
20
+ /**
21
+ * Shortest delay a new operation will be given. Read this rather than following
22
+ * `MinDelayChange`, which carries the value `updateDelay` stored and not the
23
+ * floor that overrides it.
24
+ */
25
+ export const _getMinDelay = async (client) => {
26
+ const values = await _resolve(client);
27
+ return client.extend(publicActions).readContract({
28
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
29
+ abi: ProtocolAdmin,
30
+ functionName: "getMinDelay",
31
+ args: []
32
+ });
33
+ };
34
+ /**
35
+ * The floor `getMinDelay` clamps to. Immutable, so `updateDelay` can never bring
36
+ * the timelock below it.
37
+ */
38
+ export const _minDelayFloor = async (client) => {
39
+ const values = await _resolve(client);
40
+ return client.extend(publicActions).readContract({
41
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
42
+ abi: ProtocolAdmin,
43
+ functionName: "minDelayFloor",
44
+ args: []
45
+ });
46
+ };
47
+ /** Where an operation is in its lifecycle. */
48
+ export const _getOperationState = async (client, id) => {
49
+ const values = await _resolve(client);
50
+ return client.extend(publicActions).readContract({
51
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
52
+ abi: ProtocolAdmin,
53
+ functionName: "getOperationState",
54
+ args: [id]
55
+ });
56
+ };
57
+ /**
58
+ * When an operation becomes executable, as a unix timestamp. Reads `0` for an
59
+ * unknown operation and the literal `1` for one already done, so compare against
60
+ * the state rather than treating this as a time in both cases.
61
+ */
62
+ export const _getTimestamp = async (client, id) => {
63
+ const values = await _resolve(client);
64
+ return client.extend(publicActions).readContract({
65
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
66
+ abi: ProtocolAdmin,
67
+ functionName: "getTimestamp",
68
+ args: [id]
69
+ });
70
+ };
71
+ /** Whether the timelock has ever seen this operation. */
72
+ export const _isOperation = async (client, id) => {
73
+ const values = await _resolve(client);
74
+ return client.extend(publicActions).readContract({
75
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
76
+ abi: ProtocolAdmin,
77
+ functionName: "isOperation",
78
+ args: [id]
79
+ });
80
+ };
81
+ /** Scheduled and not yet executed, whether or not the delay has elapsed. */
82
+ export const _isOperationPending = async (client, id) => {
83
+ const values = await _resolve(client);
84
+ return client.extend(publicActions).readContract({
85
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
86
+ abi: ProtocolAdmin,
87
+ functionName: "isOperationPending",
88
+ args: [id]
89
+ });
90
+ };
91
+ /** The delay has elapsed and the operation can be executed now. */
92
+ export const _isOperationReady = async (client, id) => {
93
+ const values = await _resolve(client);
94
+ return client.extend(publicActions).readContract({
95
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
96
+ abi: ProtocolAdmin,
97
+ functionName: "isOperationReady",
98
+ args: [id]
99
+ });
100
+ };
101
+ /** The operation has already run. */
102
+ export const _isOperationDone = async (client, id) => {
103
+ const values = await _resolve(client);
104
+ return client.extend(publicActions).readContract({
105
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
106
+ abi: ProtocolAdmin,
107
+ functionName: "isOperationDone",
108
+ args: [id]
109
+ });
110
+ };
111
+ /** Whether an account holds a role. Role ids come from the constants below. */
112
+ export const _hasRole = async (client, role, account) => {
113
+ const values = await _resolve(client);
114
+ return client.extend(publicActions).readContract({
115
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
116
+ abi: ProtocolAdmin,
117
+ functionName: "hasRole",
118
+ args: [role, account]
119
+ });
120
+ };
121
+ /**
122
+ * The role that can grant and revoke the given one. Always `DEFAULT_ADMIN_ROLE`,
123
+ * which only the timelock itself holds, so every role change is a scheduled
124
+ * operation.
125
+ */
126
+ export const _getRoleAdmin = async (client, role) => {
127
+ const values = await _resolve(client);
128
+ return client.extend(publicActions).readContract({
129
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
130
+ abi: ProtocolAdmin,
131
+ functionName: "getRoleAdmin",
132
+ args: [role]
133
+ });
134
+ };
135
+ // Reads one of the five role id constants off the contract.
136
+ const _roleConstant = async (client, functionName) => {
137
+ const values = await _resolve(client);
138
+ return client.extend(publicActions).readContract({
139
+ address: values.factoryAddresses.PROTOCOL_ADMIN,
140
+ abi: ProtocolAdmin,
141
+ functionName,
142
+ args: []
143
+ });
144
+ };
145
+ /** Held only by the timelock itself, which is what makes role changes wait. */
146
+ export const _defaultAdminRole = (client) => _roleConstant(client, "DEFAULT_ADMIN_ROLE");
147
+ /** Can schedule operations, and can cancel them. */
148
+ export const _proposerRole = (client) => _roleConstant(client, "PROPOSER_ROLE");
149
+ /** Can cancel a scheduled operation and nothing else. */
150
+ export const _cancellerRole = (client) => _roleConstant(client, "CANCELLER_ROLE");
151
+ /** Granted to the zero address, so execution is open to anyone. */
152
+ export const _executorRole = (client) => _roleConstant(client, "EXECUTOR_ROLE");
153
+ /** The three instant powers. Cannot be held alongside proposer or canceller. */
154
+ export const _guardianRole = (client) => _roleConstant(client, "GUARDIAN_ROLE");