kokio-sdk 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +68 -19
  2. package/dist/esm/abis/BeaconProxy.js +30 -46
  3. package/dist/esm/abis/DeviceWallet.js +546 -535
  4. package/dist/esm/abis/DeviceWalletFactory.js +537 -544
  5. package/dist/esm/abis/ESIMWallet.js +440 -299
  6. package/dist/esm/abis/ESIMWalletFactory.js +372 -289
  7. package/dist/esm/abis/LazyWalletRegistry.js +941 -421
  8. package/dist/esm/abis/P256Verifier.js +29 -29
  9. package/dist/esm/abis/ProtocolAdmin.js +1228 -0
  10. package/dist/esm/abis/Registry.js +1207 -466
  11. package/dist/esm/abis/RegistryHelper.js +414 -20
  12. package/dist/esm/abis/index.js +2 -1
  13. package/dist/esm/admin/config-admin.js +24 -0
  14. package/dist/esm/admin/interface/deviceWalletClass.js +27 -6
  15. package/dist/esm/admin/interface/deviceWalletFactoryClass.js +41 -19
  16. package/dist/esm/admin/interface/eSIMWalletClass.js +10 -1
  17. package/dist/esm/admin/interface/eSIMWalletFactoryClass.js +24 -2
  18. package/dist/esm/admin/interface/lazyWalletRegistryClass.js +83 -4
  19. package/dist/esm/admin/interface/protocolAdminClass.js +195 -0
  20. package/dist/esm/admin/interface/registryClass.js +93 -2
  21. package/dist/esm/config.js +42 -7
  22. package/dist/esm/interface/deviceWalletClass.js +45 -5
  23. package/dist/esm/interface/deviceWalletFactoryClass.js +20 -1
  24. package/dist/esm/interface/eSIMWalletClass.js +12 -3
  25. package/dist/esm/interface/registryClass.js +47 -0
  26. package/dist/esm/interface/smartAccountClass.js +2 -4
  27. package/dist/esm/logic/account-kit/createSmartAccount.js +156 -102
  28. package/dist/esm/logic/admin/deviceWallet.eoa.js +23 -12
  29. package/dist/esm/logic/admin/deviceWalletFactory.eoa.js +63 -42
  30. package/dist/esm/logic/admin/eSIMWallet.eoa.js +3 -5
  31. package/dist/esm/logic/admin/eSIMWalletFactory.eoa.js +76 -8
  32. package/dist/esm/logic/admin/lazyWalletRegistry.eoa.js +330 -19
  33. package/dist/esm/logic/admin/protocolAdmin.eoa.js +524 -0
  34. package/dist/esm/logic/admin/reads/deviceWallet.reads.js +82 -7
  35. package/dist/esm/logic/admin/reads/deviceWalletFactory.reads.js +82 -23
  36. package/dist/esm/logic/admin/reads/eSIMWallet.reads.js +50 -6
  37. package/dist/esm/logic/admin/reads/eSIMWalletFactory.reads.js +63 -5
  38. package/dist/esm/logic/admin/reads/lazyWalletRegistry.reads.js +171 -10
  39. package/dist/esm/logic/admin/reads/protocolAdmin.reads.js +154 -0
  40. package/dist/esm/logic/admin/reads/registry.reads.js +289 -9
  41. package/dist/esm/logic/admin/registry.eoa.js +274 -4
  42. package/dist/esm/logic/constants.js +53 -26
  43. package/dist/esm/logic/deviceWallet.js +224 -31
  44. package/dist/esm/logic/deviceWalletFactory.js +89 -0
  45. package/dist/esm/logic/eSIMWallet.js +113 -43
  46. package/dist/esm/logic/eSIMWalletFactory.js +8 -8
  47. package/dist/esm/logic/errors.js +64 -0
  48. package/dist/esm/logic/registry.js +236 -0
  49. package/dist/esm/logic/utils.js +2 -1
  50. package/dist/types/abis/BeaconProxy.d.ts +21 -33
  51. package/dist/types/abis/DeviceWallet.d.ts +372 -365
  52. package/dist/types/abis/DeviceWalletFactory.d.ts +438 -448
  53. package/dist/types/abis/ESIMWallet.d.ts +352 -245
  54. package/dist/types/abis/ESIMWalletFactory.d.ts +278 -216
  55. package/dist/types/abis/LazyWalletRegistry.d.ts +710 -317
  56. package/dist/types/abis/P256Verifier.d.ts +16 -16
  57. package/dist/types/abis/ProtocolAdmin.d.ts +947 -0
  58. package/dist/types/abis/Registry.d.ts +960 -393
  59. package/dist/types/abis/RegistryHelper.d.ts +317 -16
  60. package/dist/types/abis/index.d.ts +2 -1
  61. package/dist/types/admin/config-admin.d.ts +16 -0
  62. package/dist/types/admin/interface/deviceWalletClass.d.ts +10 -3
  63. package/dist/types/admin/interface/deviceWalletFactoryClass.d.ts +14 -7
  64. package/dist/types/admin/interface/eSIMWalletClass.d.ts +3 -0
  65. package/dist/types/admin/interface/eSIMWalletFactoryClass.d.ts +8 -1
  66. package/dist/types/admin/interface/lazyWalletRegistryClass.d.ts +38 -2
  67. package/dist/types/admin/interface/protocolAdminClass.d.ts +95 -0
  68. package/dist/types/admin/interface/registryClass.d.ts +30 -0
  69. package/dist/types/config.d.ts +26 -5
  70. package/dist/types/interface/P256VerifierClass.d.ts +3 -4
  71. package/dist/types/interface/constantsClass.d.ts +2 -2
  72. package/dist/types/interface/deviceWalletClass.d.ts +22 -2569
  73. package/dist/types/interface/deviceWalletFactoryClass.d.ts +10 -2564
  74. package/dist/types/interface/eSIMWalletClass.d.ts +11 -8
  75. package/dist/types/interface/eSIMWalletFactoryClass.d.ts +5 -2565
  76. package/dist/types/interface/registryClass.d.ts +19 -0
  77. package/dist/types/interface/smartAccountClass.d.ts +6 -2568
  78. package/dist/types/logic/P256Verifier.d.ts +2 -2
  79. package/dist/types/logic/account-kit/createSmartAccount.d.ts +43 -19
  80. package/dist/types/logic/admin/deviceWallet.eoa.d.ts +15 -9
  81. package/dist/types/logic/admin/deviceWalletFactory.eoa.d.ts +34 -23
  82. package/dist/types/logic/admin/eSIMWallet.eoa.d.ts +0 -5
  83. package/dist/types/logic/admin/eSIMWalletFactory.eoa.d.ts +27 -9
  84. package/dist/types/logic/admin/lazyWalletRegistry.eoa.d.ts +102 -10
  85. package/dist/types/logic/admin/protocolAdmin.eoa.d.ts +163 -0
  86. package/dist/types/logic/admin/reads/deviceWallet.reads.d.ts +28 -8
  87. package/dist/types/logic/admin/reads/deviceWalletFactory.reads.d.ts +45 -14
  88. package/dist/types/logic/admin/reads/eSIMWallet.reads.d.ts +25 -6
  89. package/dist/types/logic/admin/reads/eSIMWalletFactory.reads.d.ts +21 -6
  90. package/dist/types/logic/admin/reads/lazyWalletRegistry.reads.d.ts +44 -11
  91. package/dist/types/logic/admin/reads/protocolAdmin.reads.d.ts +53 -0
  92. package/dist/types/logic/admin/reads/registry.reads.d.ts +105 -9
  93. package/dist/types/logic/admin/registry.eoa.d.ts +102 -5
  94. package/dist/types/logic/constants.d.ts +2 -0
  95. package/dist/types/logic/deviceWallet.d.ts +78 -6
  96. package/dist/types/logic/deviceWalletFactory.d.ts +32 -3
  97. package/dist/types/logic/eSIMWallet.d.ts +48 -7
  98. package/dist/types/logic/eSIMWalletFactory.d.ts +3 -3
  99. package/dist/types/logic/errors.d.ts +45 -0
  100. package/dist/types/logic/registry.d.ts +78 -0
  101. package/dist/types/types-export.d.ts +1 -1
  102. package/dist/types/types.d.ts +111 -1
  103. package/package.json +11 -13
  104. package/dist/esm/interface/lazyWalletRegistryClass.js +0 -10
  105. package/dist/esm/logic/lazyWalletRegistry.js +0 -19
  106. package/dist/types/interface/lazyWalletRegistryClass.d.ts +0 -6
  107. package/dist/types/logic/lazyWalletRegistry.d.ts +0 -2
@@ -1,27 +1,39 @@
1
- import { encodeFunctionData } from "viem";
1
+ import { encodeFunctionData, maxUint256 } from "viem";
2
2
  import { MissingSmartWalletError } from "./errors.js";
3
3
  import { ESIMWallet } from "../abis/index.js";
4
+ import { _defaultDataBundlePriceCap } from "./registry.js";
4
5
  // Not exposed on this surface:
5
- // - populateHistory is `onlyRegistry` - callable only by the registry contract.
6
+ // - populateHistory and setESIMUniqueIdentifier are `onlyRegistry` - callable
7
+ // only by the registry contract. Naming an eSIM goes through
8
+ // `admin.registry.assignESIMIdentifier` instead.
6
9
  // - transferOwnership is a `pure` override that always reverts
7
10
  // ("Use acceptOwnershipTransfer instead."); use requestTransferOwnership /
8
11
  // acceptOwnershipTransfer instead.
9
12
  // The functions below are `onlyDeviceWallet` (the eSIM wallet's owner IS the device
10
13
  // wallet) or otherwise satisfiable by the device-wallet userOp sender, so they succeed.
11
- export const _setESIMUniqueIdentifier = async (client, address, eSIMUniqueIdentifier) => {
14
+ /**
15
+ * Cap what this eSIM wallet may be charged for one data bundle. Zero hands it
16
+ * back to the registry's ceiling.
17
+ *
18
+ * `onlyDeviceWallet`, so it needs the user's own signature. That is the point:
19
+ * the admin names the price on `buyDataBundle`, so it must not be able to raise
20
+ * the ceiling on that price too. A handover clears the cap, and the new owner has
21
+ * to set it again.
22
+ */
23
+ export const _setDataBundlePriceCap = async (client, address, cap) => {
12
24
  if (!client.account)
13
25
  throw new MissingSmartWalletError();
14
26
  // UserOp - `onlyDeviceWallet`.
15
27
  return client.sendUserOperation({
16
28
  account: client.account,
17
- uo: {
18
- target: address,
19
- data: encodeFunctionData({
20
- abi: ESIMWallet,
21
- functionName: "setESIMUniqueIdentifier",
22
- args: [eSIMUniqueIdentifier]
23
- })
24
- }
29
+ calls: [{
30
+ to: address,
31
+ data: encodeFunctionData({
32
+ abi: ESIMWallet,
33
+ functionName: "setDataBundlePriceCap",
34
+ args: [cap]
35
+ })
36
+ }]
25
37
  });
26
38
  };
27
39
  export const _buyDataBundle = async (client, address, dataBundleDetails) => {
@@ -30,14 +42,14 @@ export const _buyDataBundle = async (client, address, dataBundleDetails) => {
30
42
  // UserOp - `onlyDeviceWalletOrESIMWalletAdmin`; the owning device wallet may buy.
31
43
  return client.sendUserOperation({
32
44
  account: client.account,
33
- uo: {
34
- target: address,
35
- data: encodeFunctionData({
36
- abi: ESIMWallet,
37
- functionName: "buyDataBundle",
38
- args: [dataBundleDetails]
39
- })
40
- }
45
+ calls: [{
46
+ to: address,
47
+ data: encodeFunctionData({
48
+ abi: ESIMWallet,
49
+ functionName: "buyDataBundle",
50
+ args: [dataBundleDetails]
51
+ })
52
+ }]
41
53
  });
42
54
  };
43
55
  // `owner()` is a `view` - read it directly instead of spending a userOp.
@@ -49,20 +61,78 @@ export const _owner = async (client, address) => {
49
61
  args: []
50
62
  });
51
63
  };
64
+ /**
65
+ * The ceiling that actually applies to this wallet's next purchase, in wei.
66
+ * Read it before naming a price on `buyDataBundle`, since a price above the
67
+ * ceiling reverts.
68
+ *
69
+ * Resolved the way the contract resolves it. The wallet's own cap wins when it
70
+ * has one. Zero there means "follow the registry", which is where a fresh wallet
71
+ * and a newly handed-over wallet both start. A zero on both means no ceiling at
72
+ * all, so this returns `maxUint256` rather than a zero that reads as "you may
73
+ * not spend anything".
74
+ *
75
+ * That last case cannot happen on a live deployment: the registry refuses a zero
76
+ * cap in both `initialize` and `setDefaultDataBundlePriceCap`. It is handled
77
+ * because the contract's own check treats zero as unlimited, not because the
78
+ * state is reachable.
79
+ */
80
+ export const _dataBundlePriceCap = async (client, address) => {
81
+ const walletCap = await client.readContract({
82
+ address,
83
+ abi: ESIMWallet,
84
+ functionName: "dataBundlePriceCap",
85
+ args: []
86
+ });
87
+ if (walletCap !== 0n)
88
+ return walletCap;
89
+ const registryCap = await _defaultDataBundlePriceCap(client);
90
+ return registryCap === 0n ? maxUint256 : registryCap;
91
+ };
92
+ /**
93
+ * The device wallet this eSIM wallet belongs to. Tracks `owner`, but it is its
94
+ * own storage slot with its own getter, so read whichever one you mean.
95
+ */
96
+ export const _deviceWallet = async (client, address) => {
97
+ return client.readContract({
98
+ address,
99
+ abi: ESIMWallet,
100
+ functionName: "deviceWallet",
101
+ args: []
102
+ });
103
+ };
104
+ /**
105
+ * One data bundle purchase, by position. Holds every purchase this wallet has
106
+ * made, and for a wallet that came off the fiat path it also holds the
107
+ * pre-deployment purchases the lazy registry copies in.
108
+ *
109
+ * There is no length getter on the contract. Read upwards from zero until a call
110
+ * reverts, or track the count from the `DataBundleBought` and
111
+ * `TransactionHistoryPopulated` events.
112
+ */
113
+ export const _transactionHistory = async (client, address, index) => {
114
+ const [dataBundleID, dataBundlePrice] = await client.readContract({
115
+ address,
116
+ abi: ESIMWallet,
117
+ functionName: "transactionHistory",
118
+ args: [index]
119
+ });
120
+ return { dataBundleID, dataBundlePrice };
121
+ };
52
122
  export const _requestTransferOwnership = async (client, address, newOwner) => {
53
123
  if (!client.account)
54
124
  throw new MissingSmartWalletError();
55
125
  // UserOp - `onlyDeviceWallet`; the owning device wallet requests the transfer.
56
126
  return client.sendUserOperation({
57
127
  account: client.account,
58
- uo: {
59
- target: address,
60
- data: encodeFunctionData({
61
- abi: ESIMWallet,
62
- functionName: "requestTransferOwnership",
63
- args: [newOwner]
64
- })
65
- }
128
+ calls: [{
129
+ to: address,
130
+ data: encodeFunctionData({
131
+ abi: ESIMWallet,
132
+ functionName: "requestTransferOwnership",
133
+ args: [newOwner]
134
+ })
135
+ }]
66
136
  });
67
137
  };
68
138
  export const _acceptOwnershipTransfer = async (client, address) => {
@@ -71,14 +141,14 @@ export const _acceptOwnershipTransfer = async (client, address) => {
71
141
  // UserOp - the caller must be the pending `newRequestedOwner` (the new device wallet).
72
142
  return client.sendUserOperation({
73
143
  account: client.account,
74
- uo: {
75
- target: address,
76
- data: encodeFunctionData({
77
- abi: ESIMWallet,
78
- functionName: "acceptOwnershipTransfer",
79
- args: []
80
- })
81
- }
144
+ calls: [{
145
+ to: address,
146
+ data: encodeFunctionData({
147
+ abi: ESIMWallet,
148
+ functionName: "acceptOwnershipTransfer",
149
+ args: []
150
+ })
151
+ }]
82
152
  });
83
153
  };
84
154
  export const _sendETHToDeviceWallet = async (client, address, amount) => {
@@ -87,13 +157,13 @@ export const _sendETHToDeviceWallet = async (client, address, amount) => {
87
157
  // UserOp - `onlyDeviceWallet`.
88
158
  return client.sendUserOperation({
89
159
  account: client.account,
90
- uo: {
91
- target: address,
92
- data: encodeFunctionData({
93
- abi: ESIMWallet,
94
- functionName: "sendETHToDeviceWallet",
95
- args: [amount]
96
- })
97
- }
160
+ calls: [{
161
+ to: address,
162
+ data: encodeFunctionData({
163
+ abi: ESIMWallet,
164
+ functionName: "sendETHToDeviceWallet",
165
+ args: [amount]
166
+ })
167
+ }]
98
168
  });
99
169
  };
@@ -18,14 +18,14 @@ export const _deployESIMWalletWithUserOp = async (client, deviceWalletAddress, s
18
18
  // UserOp - the device-wallet sender is a valid device wallet per the registry.
19
19
  return client.sendUserOperation({
20
20
  account: client.account,
21
- uo: {
22
- target: values.factoryAddresses.ESIM_WALLET_FACTORY,
23
- data: encodeFunctionData({
24
- abi: ESIMWalletFactory,
25
- functionName: "deployESIMWallet",
26
- args: [deviceWalletAddress, salt]
27
- })
28
- }
21
+ calls: [{
22
+ to: values.factoryAddresses.ESIM_WALLET_FACTORY,
23
+ data: encodeFunctionData({
24
+ abi: ESIMWalletFactory,
25
+ functionName: "deployESIMWallet",
26
+ args: [deviceWalletAddress, salt]
27
+ })
28
+ }]
29
29
  });
30
30
  };
31
31
  export const _getCurrentESIMWalletImplementation = async (client) => {
@@ -68,6 +68,70 @@ export class CounterfactualMismatchError extends KokioError {
68
68
  this.onChain = onChain;
69
69
  }
70
70
  }
71
+ /**
72
+ * A batch size outside what the contract accepts. Both paginated calls refuse a
73
+ * request above their cap rather than clamping it, so this is caught locally to
74
+ * save the caller a reverted transaction.
75
+ */
76
+ export class BatchSizeOutOfRangeError extends KokioError {
77
+ requested;
78
+ max;
79
+ constructor(what, requested, max) {
80
+ super("BATCH_SIZE_OUT_OF_RANGE", `${what} must be between 1 and ${max}, got ${requested}.`);
81
+ this.requested = requested;
82
+ this.max = max;
83
+ }
84
+ }
85
+ /**
86
+ * A deposit was passed to a lazy deployment that turned out to be a resume. Only
87
+ * the first batch is payable and it already took the deposit, so carrying on
88
+ * would fund the device with less than the caller asked for.
89
+ */
90
+ export class DepositOnResumeError extends KokioError {
91
+ deviceUniqueIdentifier;
92
+ depositAmount;
93
+ constructor(deviceUniqueIdentifier, depositAmount) {
94
+ super("DEPOSIT_ON_RESUME", `Device ${deviceUniqueIdentifier} is already part-deployed, so its deposit was taken by ` +
95
+ `the first batch. Retry with a deposit of 0 rather than ${depositAmount}.`);
96
+ this.deviceUniqueIdentifier = deviceUniqueIdentifier;
97
+ this.depositAmount = depositAmount;
98
+ }
99
+ }
100
+ /**
101
+ * History was aimed at an eSIM this registry never deployed a wallet for. That
102
+ * lookup is the whole authorisation on chain, so it cannot be worked around.
103
+ */
104
+ export class ESIMWalletNotLazyDeployedError extends KokioError {
105
+ eSIMIdentifier;
106
+ constructor(eSIMIdentifier) {
107
+ super("ESIM_WALLET_NOT_LAZY_DEPLOYED", `No lazily deployed eSIM wallet for identifier ${eSIMIdentifier}.`);
108
+ this.eSIMIdentifier = eSIMIdentifier;
109
+ }
110
+ }
111
+ /**
112
+ * A batch landed but its receipt carried no event from the lazy registry. The
113
+ * loop reads its position from that event, so it cannot continue without one.
114
+ */
115
+ export class MissingBatchEventError extends KokioError {
116
+ hash;
117
+ constructor(eventName, hash) {
118
+ super("MISSING_BATCH_EVENT", `Transaction ${hash} emitted no ${eventName} event from the lazy registry.`);
119
+ this.hash = hash;
120
+ }
121
+ }
122
+ /**
123
+ * A batch reported work outstanding but did none of it. Nothing on chain should
124
+ * produce this; it stops the loop rather than letting it spin.
125
+ */
126
+ export class StalledBatchError extends KokioError {
127
+ hash;
128
+ remaining;
129
+ constructor(hash, remaining) {
130
+ super("STALLED_BATCH", `Transaction ${hash} made no progress with ${remaining} still outstanding.`);
131
+ this.hash = hash;
132
+ this.remaining = remaining;
133
+ }
134
+ }
71
135
  // Every ABI that can surface a custom error from an on-chain revert. viem's
72
136
  // `decodeErrorResult` walks each ABI's `error` fragments to match the 4-byte
73
137
  // selector in the revert data.
@@ -0,0 +1,236 @@
1
+ import { encodeFunctionData } from "viem";
2
+ import { _getChainSpecificConstants } from "./constants.js";
3
+ import { Registry } from "../abis/index.js";
4
+ import { MissingSmartWalletError } from "./errors.js";
5
+ // A userOp from a device wallet arrives at the registry with msg.sender set to the
6
+ // device wallet, which is what `onlyDeviceWallet` wants. Those three functions are
7
+ // the only writes this surface can reach; everything else is `onlyOwner`,
8
+ // `onlyESIMWalletAdmin`, `onlyDeviceWalletFactory` or `onlyLazyWalletRegistry` and
9
+ // lives on `KokioAdmin.registry` or behind the lazy registry wrappers.
10
+ //
11
+ // updateDeviceWalletOwnerKey is the exception among the three. It is
12
+ // `onlyDeviceWallet`, so a userOp reaches it, but calling it on its own writes a
13
+ // key into the registry that the wallet is not actually using.
14
+ // `deviceWallet.transferOwnership` rotates the key and updates the registry in one
15
+ // call, so that is the only way this surface offers to move it.
16
+ /**
17
+ * Take on an eSIM wallet and clear any standby flag left by a transfer.
18
+ *
19
+ * The registry only accepts the calling device wallet as the new holder, so the
20
+ * SDK fills that in and there is nothing to pass. The eSIM wallet's `owner()`
21
+ * has to already be this device wallet: accept the ownership transfer first,
22
+ * then bind.
23
+ *
24
+ * Reverts while a transfer is still pending on the eSIM wallet, and for any
25
+ * address the eSIM wallet factory did not deploy.
26
+ */
27
+ export const _bindESIMWallet = async (client, eSIMWalletAddress) => {
28
+ if (!client.account)
29
+ throw new MissingSmartWalletError();
30
+ const chainID = await client.getChainId();
31
+ const rpcURL = client.transport.url;
32
+ const values = _getChainSpecificConstants(chainID, rpcURL);
33
+ return client.sendUserOperation({
34
+ account: client.account,
35
+ calls: [{
36
+ to: values.factoryAddresses.REGISTRY,
37
+ data: encodeFunctionData({
38
+ abi: Registry,
39
+ functionName: "bindESIMWallet",
40
+ args: [eSIMWalletAddress, client.account.address]
41
+ })
42
+ }]
43
+ });
44
+ };
45
+ /**
46
+ * Flag an eSIM wallet as mid-transfer, or clear the flag when the move settles or
47
+ * is called off.
48
+ *
49
+ * Only the flag moves. The registry keeps naming this device wallet as the eSIM
50
+ * wallet's holder either way, so raising standby on a wallet still held here is
51
+ * the ordinary case rather than a contradiction.
52
+ */
53
+ export const _toggleESIMWalletStandbyStatus = async (client, eSIMWalletAddress, isOnStandby) => {
54
+ if (!client.account)
55
+ throw new MissingSmartWalletError();
56
+ const chainID = await client.getChainId();
57
+ const rpcURL = client.transport.url;
58
+ const values = _getChainSpecificConstants(chainID, rpcURL);
59
+ return client.sendUserOperation({
60
+ account: client.account,
61
+ calls: [{
62
+ to: values.factoryAddresses.REGISTRY,
63
+ data: encodeFunctionData({
64
+ abi: Registry,
65
+ functionName: "toggleESIMWalletStandbyStatus",
66
+ args: [eSIMWalletAddress, isOnStandby]
67
+ })
68
+ }]
69
+ });
70
+ };
71
+ /**
72
+ * True once the device has a wallet on chain. Note this is not the same question
73
+ * as `LazyWalletRegistry.isDeviceIdentifierReserved`, which only says whether
74
+ * history has been recorded for the device, and is true well before anything is
75
+ * deployed.
76
+ */
77
+ export const _isDeviceIdentifierAlreadyUsed = async (client, deviceUniqueIdentifier) => {
78
+ const chainID = await client.getChainId();
79
+ const rpcURL = client.transport.url;
80
+ const values = _getChainSpecificConstants(chainID, rpcURL);
81
+ // A `view` - read it directly instead of spending a userOp.
82
+ return client.readContract({
83
+ address: values.factoryAddresses.REGISTRY,
84
+ abi: Registry,
85
+ functionName: "isDeviceIdentifierAlreadyUsed",
86
+ args: [deviceUniqueIdentifier]
87
+ });
88
+ };
89
+ /**
90
+ * Whether the protocol is paused. While true, every ETH-moving path on the device
91
+ * wallets and eSIM wallets reverts, so check this before offering a purchase.
92
+ */
93
+ export const _paused = async (client) => {
94
+ const chainID = await client.getChainId();
95
+ const rpcURL = client.transport.url;
96
+ const values = _getChainSpecificConstants(chainID, rpcURL);
97
+ return client.readContract({
98
+ address: values.factoryAddresses.REGISTRY,
99
+ abi: Registry,
100
+ functionName: "paused",
101
+ args: []
102
+ });
103
+ };
104
+ /**
105
+ * The same pause check the wallets themselves run, which throws rather than
106
+ * returning false. Use `_paused` to branch on it; use this when you want the
107
+ * failure to carry the protocol's own revert reason.
108
+ */
109
+ export const _requireNotPaused = async (client) => {
110
+ const chainID = await client.getChainId();
111
+ const rpcURL = client.transport.url;
112
+ const values = _getChainSpecificConstants(chainID, rpcURL);
113
+ await client.readContract({
114
+ address: values.factoryAddresses.REGISTRY,
115
+ abi: Registry,
116
+ functionName: "requireNotPaused",
117
+ args: []
118
+ });
119
+ };
120
+ /**
121
+ * The device wallet holding an eSIM wallet, zero if it was never registered.
122
+ * Despite the name this returns an address, not a boolean, and it keeps naming
123
+ * the last holder after a release, so a non-zero answer is not proof anyone
124
+ * holds it now. Ask `deviceWallet.isValidESIMWallet` for that.
125
+ */
126
+ export const _isESIMWalletValid = async (client, eSIMWalletAddress) => {
127
+ const chainID = await client.getChainId();
128
+ const rpcURL = client.transport.url;
129
+ const values = _getChainSpecificConstants(chainID, rpcURL);
130
+ return client.readContract({
131
+ address: values.factoryAddresses.REGISTRY,
132
+ abi: Registry,
133
+ functionName: "isESIMWalletValid",
134
+ args: [eSIMWalletAddress]
135
+ });
136
+ };
137
+ /**
138
+ * Whether a transfer is outstanding on an eSIM wallet. `bindESIMWallet` clears
139
+ * it once the new device wallet takes the eSIM wallet on.
140
+ *
141
+ * Independent of `isESIMWalletValid`, and neither implies the other. A `true`
142
+ * here is not a claim the wallet left the protocol, and it is normal for the
143
+ * association to still name the device wallet that raised the flag.
144
+ */
145
+ export const _isESIMWalletOnStandby = async (client, eSIMWalletAddress) => {
146
+ const chainID = await client.getChainId();
147
+ const rpcURL = client.transport.url;
148
+ const values = _getChainSpecificConstants(chainID, rpcURL);
149
+ return client.readContract({
150
+ address: values.factoryAddresses.REGISTRY,
151
+ abi: Registry,
152
+ functionName: "isESIMWalletOnStandby",
153
+ args: [eSIMWalletAddress]
154
+ });
155
+ };
156
+ /** Whether a device wallet is registered with the protocol. */
157
+ export const _isDeviceWalletValid = async (client, deviceWalletAddress) => {
158
+ const chainID = await client.getChainId();
159
+ const rpcURL = client.transport.url;
160
+ const values = _getChainSpecificConstants(chainID, rpcURL);
161
+ return client.readContract({
162
+ address: values.factoryAddresses.REGISTRY,
163
+ abi: Registry,
164
+ functionName: "isDeviceWalletValid",
165
+ args: [deviceWalletAddress]
166
+ });
167
+ };
168
+ /** The device wallet registered for a device identifier, zero if none. */
169
+ export const _uniqueIdentifierToDeviceWallet = async (client, deviceUniqueIdentifier) => {
170
+ const chainID = await client.getChainId();
171
+ const rpcURL = client.transport.url;
172
+ const values = _getChainSpecificConstants(chainID, rpcURL);
173
+ return client.readContract({
174
+ address: values.factoryAddresses.REGISTRY,
175
+ abi: Registry,
176
+ functionName: "uniqueIdentifierToDeviceWallet",
177
+ args: [deviceUniqueIdentifier]
178
+ });
179
+ };
180
+ /** Whether an eSIM identifier is already held by a wallet. */
181
+ export const _isESIMIdentifierClaimed = async (client, eSIMUniqueIdentifier) => {
182
+ const chainID = await client.getChainId();
183
+ const rpcURL = client.transport.url;
184
+ const values = _getChainSpecificConstants(chainID, rpcURL);
185
+ return client.readContract({
186
+ address: values.factoryAddresses.REGISTRY,
187
+ abi: Registry,
188
+ functionName: "isESIMIdentifierClaimed",
189
+ args: [eSIMUniqueIdentifier]
190
+ });
191
+ };
192
+ /**
193
+ * The one eSIM wallet holding an eSIM identifier, zero if nobody holds it. Set
194
+ * once and never cleared, an ownership transfer included, because the eSIM
195
+ * belongs to the wallet rather than to whichever device is holding it.
196
+ */
197
+ export const _eSIMWalletForIdentifier = async (client, eSIMUniqueIdentifier) => {
198
+ const chainID = await client.getChainId();
199
+ const rpcURL = client.transport.url;
200
+ const values = _getChainSpecificConstants(chainID, rpcURL);
201
+ return client.readContract({
202
+ address: values.factoryAddresses.REGISTRY,
203
+ abi: Registry,
204
+ functionName: "eSIMWalletForIdentifier",
205
+ args: [eSIMUniqueIdentifier]
206
+ });
207
+ };
208
+ /** The fallback price ceiling in wei for a wallet holding no cap of its own. */
209
+ export const _defaultDataBundlePriceCap = async (client) => {
210
+ const chainID = await client.getChainId();
211
+ const rpcURL = client.transport.url;
212
+ const values = _getChainSpecificConstants(chainID, rpcURL);
213
+ return client.readContract({
214
+ address: values.factoryAddresses.REGISTRY,
215
+ abi: Registry,
216
+ functionName: "defaultDataBundlePriceCap",
217
+ args: []
218
+ });
219
+ };
220
+ /**
221
+ * Throws if a fiat user's eSIMs are already waiting on this device identifier.
222
+ * Worth calling before a deployment: taking a reserved identifier strands the
223
+ * lazy user, since the history copy, the wallet deployment and the device switch
224
+ * all then refuse it.
225
+ */
226
+ export const _requireDeviceIdentifierNotReserved = async (client, deviceUniqueIdentifier) => {
227
+ const chainID = await client.getChainId();
228
+ const rpcURL = client.transport.url;
229
+ const values = _getChainSpecificConstants(chainID, rpcURL);
230
+ await client.readContract({
231
+ address: values.factoryAddresses.REGISTRY,
232
+ abi: Registry,
233
+ functionName: "requireDeviceIdentifierNotReserved",
234
+ args: [deviceUniqueIdentifier]
235
+ });
236
+ };
@@ -54,7 +54,8 @@ export function parseDEREncodedSignature(signature) {
54
54
  let offset = 0;
55
55
  if (signature[offset++] !== 0x30)
56
56
  throw new Error("Invalid DER sequence");
57
- const length = signature[offset++];
57
+ // Sequence length byte. Skipped, because r and s each carry their own length.
58
+ offset++;
58
59
  if (signature[offset++] !== 0x02)
59
60
  throw new Error("Expected integer for r");
60
61
  const rLen = signature[offset++];
@@ -1,59 +1,47 @@
1
1
  declare const BeaconProxy: readonly [{
2
+ readonly type: "fallback";
3
+ readonly stateMutability: "payable";
4
+ }, {
5
+ readonly type: "event";
6
+ readonly name: "BeaconUpgraded";
2
7
  readonly inputs: readonly [{
3
- readonly internalType: "address";
4
8
  readonly name: "beacon";
5
9
  readonly type: "address";
6
- }, {
7
- readonly internalType: "bytes";
8
- readonly name: "data";
9
- readonly type: "bytes";
10
+ readonly indexed: true;
11
+ readonly internalType: "address";
10
12
  }];
11
- readonly stateMutability: "payable";
12
- readonly type: "constructor";
13
+ readonly anonymous: false;
13
14
  }, {
15
+ readonly type: "error";
16
+ readonly name: "AddressEmptyCode";
14
17
  readonly inputs: readonly [{
15
- readonly internalType: "address";
16
18
  readonly name: "target";
17
19
  readonly type: "address";
20
+ readonly internalType: "address";
18
21
  }];
19
- readonly name: "AddressEmptyCode";
20
- readonly type: "error";
21
22
  }, {
23
+ readonly type: "error";
24
+ readonly name: "ERC1967InvalidBeacon";
22
25
  readonly inputs: readonly [{
23
- readonly internalType: "address";
24
26
  readonly name: "beacon";
25
27
  readonly type: "address";
28
+ readonly internalType: "address";
26
29
  }];
27
- readonly name: "ERC1967InvalidBeacon";
28
- readonly type: "error";
29
30
  }, {
31
+ readonly type: "error";
32
+ readonly name: "ERC1967InvalidImplementation";
30
33
  readonly inputs: readonly [{
31
- readonly internalType: "address";
32
34
  readonly name: "implementation";
33
35
  readonly type: "address";
36
+ readonly internalType: "address";
34
37
  }];
35
- readonly name: "ERC1967InvalidImplementation";
36
- readonly type: "error";
37
38
  }, {
38
- readonly inputs: readonly [];
39
- readonly name: "ERC1967NonPayable";
40
39
  readonly type: "error";
41
- }, {
40
+ readonly name: "ERC1967NonPayable";
42
41
  readonly inputs: readonly [];
43
- readonly name: "FailedInnerCall";
44
- readonly type: "error";
45
42
  }, {
46
- readonly anonymous: false;
47
- readonly inputs: readonly [{
48
- readonly indexed: true;
49
- readonly internalType: "address";
50
- readonly name: "beacon";
51
- readonly type: "address";
52
- }];
53
- readonly name: "BeaconUpgraded";
54
- readonly type: "event";
55
- }, {
56
- readonly stateMutability: "payable";
57
- readonly type: "fallback";
43
+ readonly type: "error";
44
+ readonly name: "FailedCall";
45
+ readonly inputs: readonly [];
58
46
  }];
59
47
  export default BeaconProxy;