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.
- package/README.md +68 -19
- package/dist/esm/abis/BeaconProxy.js +30 -46
- package/dist/esm/abis/DeviceWallet.js +546 -535
- package/dist/esm/abis/DeviceWalletFactory.js +537 -544
- package/dist/esm/abis/ESIMWallet.js +440 -299
- package/dist/esm/abis/ESIMWalletFactory.js +372 -289
- package/dist/esm/abis/LazyWalletRegistry.js +941 -421
- package/dist/esm/abis/P256Verifier.js +29 -29
- package/dist/esm/abis/ProtocolAdmin.js +1228 -0
- package/dist/esm/abis/Registry.js +1207 -466
- package/dist/esm/abis/RegistryHelper.js +414 -20
- package/dist/esm/abis/index.js +2 -1
- package/dist/esm/admin/config-admin.js +24 -0
- package/dist/esm/admin/interface/deviceWalletClass.js +27 -6
- package/dist/esm/admin/interface/deviceWalletFactoryClass.js +41 -19
- package/dist/esm/admin/interface/eSIMWalletClass.js +10 -1
- package/dist/esm/admin/interface/eSIMWalletFactoryClass.js +24 -2
- package/dist/esm/admin/interface/lazyWalletRegistryClass.js +83 -4
- package/dist/esm/admin/interface/protocolAdminClass.js +195 -0
- package/dist/esm/admin/interface/registryClass.js +93 -2
- package/dist/esm/config.js +42 -7
- package/dist/esm/interface/deviceWalletClass.js +45 -5
- package/dist/esm/interface/deviceWalletFactoryClass.js +20 -1
- package/dist/esm/interface/eSIMWalletClass.js +12 -3
- package/dist/esm/interface/registryClass.js +47 -0
- package/dist/esm/interface/smartAccountClass.js +2 -4
- package/dist/esm/logic/account-kit/createSmartAccount.js +156 -102
- package/dist/esm/logic/admin/deviceWallet.eoa.js +23 -12
- package/dist/esm/logic/admin/deviceWalletFactory.eoa.js +63 -42
- package/dist/esm/logic/admin/eSIMWallet.eoa.js +3 -5
- package/dist/esm/logic/admin/eSIMWalletFactory.eoa.js +76 -8
- package/dist/esm/logic/admin/lazyWalletRegistry.eoa.js +330 -19
- package/dist/esm/logic/admin/protocolAdmin.eoa.js +524 -0
- package/dist/esm/logic/admin/reads/deviceWallet.reads.js +82 -7
- package/dist/esm/logic/admin/reads/deviceWalletFactory.reads.js +82 -23
- package/dist/esm/logic/admin/reads/eSIMWallet.reads.js +50 -6
- package/dist/esm/logic/admin/reads/eSIMWalletFactory.reads.js +63 -5
- package/dist/esm/logic/admin/reads/lazyWalletRegistry.reads.js +171 -10
- package/dist/esm/logic/admin/reads/protocolAdmin.reads.js +154 -0
- package/dist/esm/logic/admin/reads/registry.reads.js +289 -9
- package/dist/esm/logic/admin/registry.eoa.js +274 -4
- package/dist/esm/logic/constants.js +53 -26
- package/dist/esm/logic/deviceWallet.js +224 -31
- package/dist/esm/logic/deviceWalletFactory.js +89 -0
- package/dist/esm/logic/eSIMWallet.js +113 -43
- package/dist/esm/logic/eSIMWalletFactory.js +8 -8
- package/dist/esm/logic/errors.js +64 -0
- package/dist/esm/logic/registry.js +236 -0
- package/dist/esm/logic/utils.js +2 -1
- package/dist/types/abis/BeaconProxy.d.ts +21 -33
- package/dist/types/abis/DeviceWallet.d.ts +372 -365
- package/dist/types/abis/DeviceWalletFactory.d.ts +438 -448
- package/dist/types/abis/ESIMWallet.d.ts +352 -245
- package/dist/types/abis/ESIMWalletFactory.d.ts +278 -216
- package/dist/types/abis/LazyWalletRegistry.d.ts +710 -317
- package/dist/types/abis/P256Verifier.d.ts +16 -16
- package/dist/types/abis/ProtocolAdmin.d.ts +947 -0
- package/dist/types/abis/Registry.d.ts +960 -393
- package/dist/types/abis/RegistryHelper.d.ts +317 -16
- package/dist/types/abis/index.d.ts +2 -1
- package/dist/types/admin/config-admin.d.ts +16 -0
- package/dist/types/admin/interface/deviceWalletClass.d.ts +10 -3
- package/dist/types/admin/interface/deviceWalletFactoryClass.d.ts +14 -7
- package/dist/types/admin/interface/eSIMWalletClass.d.ts +3 -0
- package/dist/types/admin/interface/eSIMWalletFactoryClass.d.ts +8 -1
- package/dist/types/admin/interface/lazyWalletRegistryClass.d.ts +38 -2
- package/dist/types/admin/interface/protocolAdminClass.d.ts +95 -0
- package/dist/types/admin/interface/registryClass.d.ts +30 -0
- package/dist/types/config.d.ts +26 -5
- package/dist/types/interface/P256VerifierClass.d.ts +3 -4
- package/dist/types/interface/constantsClass.d.ts +2 -2
- package/dist/types/interface/deviceWalletClass.d.ts +22 -2569
- package/dist/types/interface/deviceWalletFactoryClass.d.ts +10 -2564
- package/dist/types/interface/eSIMWalletClass.d.ts +11 -8
- package/dist/types/interface/eSIMWalletFactoryClass.d.ts +5 -2565
- package/dist/types/interface/registryClass.d.ts +19 -0
- package/dist/types/interface/smartAccountClass.d.ts +6 -2568
- package/dist/types/logic/P256Verifier.d.ts +2 -2
- package/dist/types/logic/account-kit/createSmartAccount.d.ts +43 -19
- package/dist/types/logic/admin/deviceWallet.eoa.d.ts +15 -9
- package/dist/types/logic/admin/deviceWalletFactory.eoa.d.ts +34 -23
- package/dist/types/logic/admin/eSIMWallet.eoa.d.ts +0 -5
- package/dist/types/logic/admin/eSIMWalletFactory.eoa.d.ts +27 -9
- package/dist/types/logic/admin/lazyWalletRegistry.eoa.d.ts +102 -10
- package/dist/types/logic/admin/protocolAdmin.eoa.d.ts +163 -0
- package/dist/types/logic/admin/reads/deviceWallet.reads.d.ts +28 -8
- package/dist/types/logic/admin/reads/deviceWalletFactory.reads.d.ts +45 -14
- package/dist/types/logic/admin/reads/eSIMWallet.reads.d.ts +25 -6
- package/dist/types/logic/admin/reads/eSIMWalletFactory.reads.d.ts +21 -6
- package/dist/types/logic/admin/reads/lazyWalletRegistry.reads.d.ts +44 -11
- package/dist/types/logic/admin/reads/protocolAdmin.reads.d.ts +53 -0
- package/dist/types/logic/admin/reads/registry.reads.d.ts +105 -9
- package/dist/types/logic/admin/registry.eoa.d.ts +102 -5
- package/dist/types/logic/constants.d.ts +2 -0
- package/dist/types/logic/deviceWallet.d.ts +78 -6
- package/dist/types/logic/deviceWalletFactory.d.ts +32 -3
- package/dist/types/logic/eSIMWallet.d.ts +48 -7
- package/dist/types/logic/eSIMWalletFactory.d.ts +3 -3
- package/dist/types/logic/errors.d.ts +45 -0
- package/dist/types/logic/registry.d.ts +78 -0
- package/dist/types/types-export.d.ts +1 -1
- package/dist/types/types.d.ts +111 -1
- package/package.json +11 -13
- package/dist/esm/interface/lazyWalletRegistryClass.js +0 -10
- package/dist/esm/logic/lazyWalletRegistry.js +0 -19
- package/dist/types/interface/lazyWalletRegistryClass.d.ts +0 -6
- package/dist/types/logic/lazyWalletRegistry.d.ts +0 -2
|
@@ -2,6 +2,22 @@ import { InvalidClientError, UnconfiguredChainError, UnsupportedChainError, } fr
|
|
|
2
2
|
import { mainnet, sepolia, optimism, optimismSepolia, arbitrum, arbitrumSepolia, base, baseSepolia } from "viem/chains";
|
|
3
3
|
export const ZERO = BigInt('0');
|
|
4
4
|
export const SIGNATURE_VALIDITY_SECONDS = 180; // 3 minutes validity
|
|
5
|
+
// Gas estimation runs before a passkey signature exists, so the account hands the
|
|
6
|
+
// bundler "0x" as a stub. Account4337 rejects any signature of 39 bytes or fewer
|
|
7
|
+
// before it reaches the P256 verifier, so the bundler measures an early return and
|
|
8
|
+
// prices calldata that is 519 bytes short of the real thing. Both estimates come
|
|
9
|
+
// back too low and an operation sized from them is refused, so both are padded.
|
|
10
|
+
//
|
|
11
|
+
// Measured on Base Sepolia: verification estimated at 33,703 gas against a floor of
|
|
12
|
+
// 76,628, and preVerificationGas 11,536 lower than the same operation carrying a
|
|
13
|
+
// real-length signature.
|
|
14
|
+
// Unused verification gas is refunded in full, unlike callGasLimit, so headroom
|
|
15
|
+
// here only raises the prefund the sponsor has to post and costs nothing when it
|
|
16
|
+
// goes unspent.
|
|
17
|
+
export const STUB_VERIFICATION_GAS_PAD = BigInt(60_000);
|
|
18
|
+
// preVerificationGas is charged whether or not it is used, so this stays close to
|
|
19
|
+
// the measured shortfall.
|
|
20
|
+
export const STUB_PRE_VERIFICATION_GAS_PAD = BigInt(15_000);
|
|
5
21
|
export var CHAIN_ID;
|
|
6
22
|
(function (CHAIN_ID) {
|
|
7
23
|
CHAIN_ID[CHAIN_ID["MAINNET"] = 1] = "MAINNET";
|
|
@@ -13,14 +29,17 @@ export var CHAIN_ID;
|
|
|
13
29
|
CHAIN_ID[CHAIN_ID["ARBITRUM_ONE"] = 42161] = "ARBITRUM_ONE";
|
|
14
30
|
CHAIN_ID[CHAIN_ID["ARBITRUM_SEPOLIA"] = 421614] = "ARBITRUM_SEPOLIA";
|
|
15
31
|
})(CHAIN_ID || (CHAIN_ID = {}));
|
|
32
|
+
// Cleared: the deployment here targets EntryPoint v0.7, which this SDK no longer
|
|
33
|
+
// speaks. Refill only after a redeploy on v0.8.
|
|
16
34
|
export const sepoliaFactoryAddresses = {
|
|
17
|
-
DEVICE_WALLET_FACTORY: '
|
|
18
|
-
ESIM_WALLET_FACTORY: '
|
|
19
|
-
LAZY_WALLET_REGISTRY: '
|
|
20
|
-
REGISTRY: '
|
|
21
|
-
ENTRY_POINT: '
|
|
22
|
-
SENDER_CREATOR: '
|
|
23
|
-
P256VERIFIER: '
|
|
35
|
+
DEVICE_WALLET_FACTORY: '0x',
|
|
36
|
+
ESIM_WALLET_FACTORY: '0x',
|
|
37
|
+
LAZY_WALLET_REGISTRY: '0x',
|
|
38
|
+
REGISTRY: '0x',
|
|
39
|
+
ENTRY_POINT: '0x',
|
|
40
|
+
SENDER_CREATOR: '0x',
|
|
41
|
+
P256VERIFIER: '0x',
|
|
42
|
+
PROTOCOL_ADMIN: '0x'
|
|
24
43
|
};
|
|
25
44
|
export const mainnetFactoryAddresses = {
|
|
26
45
|
DEVICE_WALLET_FACTORY: '0x',
|
|
@@ -29,7 +48,8 @@ export const mainnetFactoryAddresses = {
|
|
|
29
48
|
REGISTRY: '0x',
|
|
30
49
|
ENTRY_POINT: '0x',
|
|
31
50
|
SENDER_CREATOR: '0x',
|
|
32
|
-
P256VERIFIER: '0x'
|
|
51
|
+
P256VERIFIER: '0x',
|
|
52
|
+
PROTOCOL_ADMIN: '0x'
|
|
33
53
|
};
|
|
34
54
|
export const optimismMainnetFactoryAddresses = {
|
|
35
55
|
DEVICE_WALLET_FACTORY: '0x',
|
|
@@ -38,16 +58,19 @@ export const optimismMainnetFactoryAddresses = {
|
|
|
38
58
|
REGISTRY: '0x',
|
|
39
59
|
ENTRY_POINT: '0x',
|
|
40
60
|
SENDER_CREATOR: '0x',
|
|
41
|
-
P256VERIFIER: '0x'
|
|
61
|
+
P256VERIFIER: '0x',
|
|
62
|
+
PROTOCOL_ADMIN: '0x'
|
|
42
63
|
};
|
|
64
|
+
// Cleared for the same reason as Sepolia: a v0.7 deployment this SDK cannot use.
|
|
43
65
|
export const optimismSepoliaFactoryAddresses = {
|
|
44
|
-
DEVICE_WALLET_FACTORY: '
|
|
45
|
-
ESIM_WALLET_FACTORY: '
|
|
46
|
-
LAZY_WALLET_REGISTRY: '
|
|
47
|
-
REGISTRY: '
|
|
48
|
-
ENTRY_POINT: '
|
|
49
|
-
SENDER_CREATOR: '
|
|
50
|
-
P256VERIFIER: '
|
|
66
|
+
DEVICE_WALLET_FACTORY: '0x',
|
|
67
|
+
ESIM_WALLET_FACTORY: '0x',
|
|
68
|
+
LAZY_WALLET_REGISTRY: '0x',
|
|
69
|
+
REGISTRY: '0x',
|
|
70
|
+
ENTRY_POINT: '0x',
|
|
71
|
+
SENDER_CREATOR: '0x',
|
|
72
|
+
P256VERIFIER: '0x',
|
|
73
|
+
PROTOCOL_ADMIN: '0x'
|
|
51
74
|
};
|
|
52
75
|
export const baseMainnetFactoryAddresses = {
|
|
53
76
|
DEVICE_WALLET_FACTORY: '0x',
|
|
@@ -56,16 +79,18 @@ export const baseMainnetFactoryAddresses = {
|
|
|
56
79
|
REGISTRY: '0x',
|
|
57
80
|
ENTRY_POINT: '0x',
|
|
58
81
|
SENDER_CREATOR: '0x',
|
|
59
|
-
P256VERIFIER: '0x'
|
|
82
|
+
P256VERIFIER: '0x',
|
|
83
|
+
PROTOCOL_ADMIN: '0x'
|
|
60
84
|
};
|
|
61
85
|
export const baseSepoliaFactoryAddresses = {
|
|
62
|
-
DEVICE_WALLET_FACTORY: '
|
|
63
|
-
ESIM_WALLET_FACTORY: '
|
|
64
|
-
LAZY_WALLET_REGISTRY: '
|
|
65
|
-
REGISTRY: '
|
|
66
|
-
ENTRY_POINT: '
|
|
67
|
-
SENDER_CREATOR: '
|
|
68
|
-
P256VERIFIER: '
|
|
86
|
+
DEVICE_WALLET_FACTORY: '0xB006c7066C89a5d7Bfc229e9fb0bADf96c8F979f',
|
|
87
|
+
ESIM_WALLET_FACTORY: '0x13998C0bb7433c51cE5101922B12EE69F459699A',
|
|
88
|
+
LAZY_WALLET_REGISTRY: '0x394177c5cc4762b897c37de1820259B75993e033',
|
|
89
|
+
REGISTRY: '0x89e386E3251692F21a2E9048A46518AdC2A5Cb4A',
|
|
90
|
+
ENTRY_POINT: '0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108',
|
|
91
|
+
SENDER_CREATOR: '0x449ED7C3e6Fee6a97311d4b55475DF59C44AdD33',
|
|
92
|
+
P256VERIFIER: '0x625561429bD99d647956ccBCA4eBf762aaA142c5',
|
|
93
|
+
PROTOCOL_ADMIN: '0x77A1D6f27462c34BF038832d9Cff6b3E94a9Fe6F'
|
|
69
94
|
};
|
|
70
95
|
export const arbitrumOneFactoryAddresses = {
|
|
71
96
|
DEVICE_WALLET_FACTORY: '0x',
|
|
@@ -74,7 +99,8 @@ export const arbitrumOneFactoryAddresses = {
|
|
|
74
99
|
REGISTRY: '0x',
|
|
75
100
|
ENTRY_POINT: '0x',
|
|
76
101
|
SENDER_CREATOR: '0x',
|
|
77
|
-
P256VERIFIER: '0x'
|
|
102
|
+
P256VERIFIER: '0x',
|
|
103
|
+
PROTOCOL_ADMIN: '0x'
|
|
78
104
|
};
|
|
79
105
|
export const arbitrumSepoliaFactoryAddresses = {
|
|
80
106
|
DEVICE_WALLET_FACTORY: '0x',
|
|
@@ -83,7 +109,8 @@ export const arbitrumSepoliaFactoryAddresses = {
|
|
|
83
109
|
REGISTRY: '0x',
|
|
84
110
|
ENTRY_POINT: '0x',
|
|
85
111
|
SENDER_CREATOR: '0x',
|
|
86
|
-
P256VERIFIER: '0x'
|
|
112
|
+
P256VERIFIER: '0x',
|
|
113
|
+
PROTOCOL_ADMIN: '0x'
|
|
87
114
|
};
|
|
88
115
|
export const customErrors = {
|
|
89
116
|
NULL_OR_UNDEFINED_VALUE: "Error: Null or undefined value provided",
|
|
@@ -4,59 +4,159 @@ import { MissingSmartWalletError } from "./errors.js";
|
|
|
4
4
|
// A userOp from a device wallet runs through `execute`, so at the target contract
|
|
5
5
|
// msg.sender is the device-wallet account itself. That constrains which DeviceWallet
|
|
6
6
|
// functions this surface can expose:
|
|
7
|
-
// - deployESIMWallet
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
7
|
+
// - deployESIMWallet is `onlyESIMWalletAdmin` - only the admin EOA may call, so a
|
|
8
|
+
// device-wallet userOp always reverts. It is exposed on `KokioAdmin.deviceWallet`.
|
|
9
|
+
// - pullETH is `onlyAssociatedESIMWallets` - callable only by an associated eSIM
|
|
10
|
+
// wallet contract, never by the device wallet or an EOA. An eSIM wallet reaches it
|
|
11
|
+
// on its own during `buyDataBundle`.
|
|
12
|
+
// - execute and executeBatch are what a userOp runs through, so the smart account
|
|
13
|
+
// client already uses them; calling one directly would nest a userOp inside a userOp.
|
|
14
|
+
// `_sendUserOperation` below is the generic entry point instead: it hands the smart
|
|
15
|
+
// account client raw calls, and the account's own `encodeCalls` is what turns those
|
|
16
|
+
// into `execute` or `executeBatch`, never this file.
|
|
17
|
+
// - init runs at deploy, and validateUserOp is `onlyEntryPoint`.
|
|
12
18
|
// The functions below are self-callable (target = the device wallet's own address, so
|
|
13
19
|
// msg.sender == self), so they succeed via a userOp.
|
|
20
|
+
/**
|
|
21
|
+
* Send one or more calls from this device wallet as a single user operation.
|
|
22
|
+
* The only escape hatch on this surface for anything not named below: sending
|
|
23
|
+
* ETH to any address, calling another contract, moving tokens, interacting
|
|
24
|
+
* with a DeFi protocol. A lone call encodes to `execute`, several batch
|
|
25
|
+
* atomically through `executeBatch`.
|
|
26
|
+
*/
|
|
27
|
+
export const _sendUserOperation = async (client, calls) => {
|
|
28
|
+
if (!client.account)
|
|
29
|
+
throw new MissingSmartWalletError();
|
|
30
|
+
return client.sendUserOperation({
|
|
31
|
+
account: client.account,
|
|
32
|
+
calls
|
|
33
|
+
});
|
|
34
|
+
};
|
|
14
35
|
export const _toggleAccessToETH = async (client, address, eSIMWalletAddress, hasAccessToETH) => {
|
|
15
36
|
if (!client.account)
|
|
16
37
|
throw new MissingSmartWalletError();
|
|
17
38
|
// UserOp - `onlySelf`; the device wallet toggles ETH access for an eSIM wallet it owns.
|
|
18
39
|
return client.sendUserOperation({
|
|
19
40
|
account: client.account,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
calls: [{
|
|
42
|
+
to: address,
|
|
43
|
+
data: encodeFunctionData({
|
|
44
|
+
abi: DeviceWallet,
|
|
45
|
+
functionName: "toggleAccessToETH",
|
|
46
|
+
args: [eSIMWalletAddress, hasAccessToETH]
|
|
47
|
+
})
|
|
48
|
+
}]
|
|
28
49
|
});
|
|
29
50
|
};
|
|
30
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Bind an eSIM wallet this device wallet already owns.
|
|
53
|
+
*
|
|
54
|
+
* A bind never carries ETH access: the contract reverts on a `true` rather than
|
|
55
|
+
* downgrading it quietly, so the SDK passes `false` and there is nothing to
|
|
56
|
+
* choose. `toggleAccessToETH` is the only way to grant it, which is what stops a
|
|
57
|
+
* bind from undoing the owner's revocation.
|
|
58
|
+
*/
|
|
59
|
+
export const _addESIMWallet = async (client, address, eSIMWalletAddress) => {
|
|
31
60
|
if (!client.account)
|
|
32
61
|
throw new MissingSmartWalletError();
|
|
33
62
|
// UserOp - `onlyRegistryOrDeviceWalletFactoryOrOwner`; self is permitted.
|
|
34
63
|
return client.sendUserOperation({
|
|
35
64
|
account: client.account,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
65
|
+
calls: [{
|
|
66
|
+
to: address,
|
|
67
|
+
data: encodeFunctionData({
|
|
68
|
+
abi: DeviceWallet,
|
|
69
|
+
functionName: "addESIMWallet",
|
|
70
|
+
args: [eSIMWalletAddress, false]
|
|
71
|
+
})
|
|
72
|
+
}]
|
|
44
73
|
});
|
|
45
74
|
};
|
|
46
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Release an eSIM wallet and put it on standby for a transfer.
|
|
77
|
+
*
|
|
78
|
+
* `callBackETH` sweeps whatever ETH the eSIM wallet still holds back here. It
|
|
79
|
+
* runs after the release, so a wallet whose handler misbehaves has already lost
|
|
80
|
+
* its ETH access and its registry association. A failed sweep is swallowed by
|
|
81
|
+
* the contract, so a `true` is not a promise that anything arrived.
|
|
82
|
+
*/
|
|
83
|
+
export const _removeESIMWallet = async (client, address, eSIMWalletAddress, callBackETH) => {
|
|
47
84
|
if (!client.account)
|
|
48
85
|
throw new MissingSmartWalletError();
|
|
49
86
|
// UserOp - `onlySelfOrAssociatedESIMWallet`; self is permitted.
|
|
50
87
|
return client.sendUserOperation({
|
|
51
88
|
account: client.account,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
89
|
+
calls: [{
|
|
90
|
+
to: address,
|
|
91
|
+
data: encodeFunctionData({
|
|
92
|
+
abi: DeviceWallet,
|
|
93
|
+
functionName: "removeESIMWallet",
|
|
94
|
+
args: [eSIMWalletAddress, callBackETH]
|
|
95
|
+
})
|
|
96
|
+
}]
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Rotate the P256 key that owns this wallet. The registry is told in the same
|
|
101
|
+
* call, so its record of the owner cannot drift from the wallet's.
|
|
102
|
+
*
|
|
103
|
+
* A key that cannot produce a verifiable signature bricks the wallet: this is
|
|
104
|
+
* reachable only through a signed userOp, so there is no rotating back and no
|
|
105
|
+
* reaching the balance afterwards. The contract rejects a key it can tell is
|
|
106
|
+
* unusable, but check the new key can sign before calling.
|
|
107
|
+
*/
|
|
108
|
+
export const _transferOwnership = async (client, address, newOwner) => {
|
|
109
|
+
if (!client.account)
|
|
110
|
+
throw new MissingSmartWalletError();
|
|
111
|
+
// UserOp - `onlySelf`.
|
|
112
|
+
return client.sendUserOperation({
|
|
113
|
+
account: client.account,
|
|
114
|
+
calls: [{
|
|
115
|
+
to: address,
|
|
116
|
+
data: encodeFunctionData({
|
|
117
|
+
abi: DeviceWallet,
|
|
118
|
+
functionName: "transferOwnership",
|
|
119
|
+
args: [newOwner]
|
|
120
|
+
})
|
|
121
|
+
}]
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Top up the gas deposit the EntryPoint holds for this wallet, from the wallet's
|
|
126
|
+
* own balance. Anyone may pay into any account's deposit, so an EOA can do this
|
|
127
|
+
* with a plain transfer too and not spend a userOp on it.
|
|
128
|
+
*/
|
|
129
|
+
export const _addDeposit = async (client, address, amount) => {
|
|
130
|
+
if (!client.account)
|
|
131
|
+
throw new MissingSmartWalletError();
|
|
132
|
+
return client.sendUserOperation({
|
|
133
|
+
account: client.account,
|
|
134
|
+
calls: [{
|
|
135
|
+
to: address,
|
|
136
|
+
value: amount,
|
|
137
|
+
data: encodeFunctionData({
|
|
138
|
+
abi: DeviceWallet,
|
|
139
|
+
functionName: "addDeposit",
|
|
140
|
+
args: []
|
|
141
|
+
})
|
|
142
|
+
}]
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
/** Pull part of the EntryPoint gas deposit back out to any address. */
|
|
146
|
+
export const _withdrawDepositTo = async (client, address, withdrawAddress, amount) => {
|
|
147
|
+
if (!client.account)
|
|
148
|
+
throw new MissingSmartWalletError();
|
|
149
|
+
// UserOp - `onlySelf`.
|
|
150
|
+
return client.sendUserOperation({
|
|
151
|
+
account: client.account,
|
|
152
|
+
calls: [{
|
|
153
|
+
to: address,
|
|
154
|
+
data: encodeFunctionData({
|
|
155
|
+
abi: DeviceWallet,
|
|
156
|
+
functionName: "withdrawDepositTo",
|
|
157
|
+
args: [withdrawAddress, amount]
|
|
158
|
+
})
|
|
159
|
+
}]
|
|
60
160
|
});
|
|
61
161
|
};
|
|
62
162
|
// `getVaultAddress` is a `view` - read it directly instead of spending a userOp.
|
|
@@ -68,6 +168,99 @@ export const _getVaultAddress = async (client, address) => {
|
|
|
68
168
|
args: []
|
|
69
169
|
});
|
|
70
170
|
};
|
|
171
|
+
/** Gas this wallet has on deposit at the EntryPoint. */
|
|
172
|
+
export const _getDeposit = async (client, address) => {
|
|
173
|
+
return client.readContract({
|
|
174
|
+
address,
|
|
175
|
+
abi: DeviceWallet,
|
|
176
|
+
functionName: "getDeposit",
|
|
177
|
+
args: []
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
/** The device identifier this wallet was deployed for. Set once, at deploy. */
|
|
181
|
+
export const _deviceUniqueIdentifier = async (client, address) => {
|
|
182
|
+
return client.readContract({
|
|
183
|
+
address,
|
|
184
|
+
abi: DeviceWallet,
|
|
185
|
+
functionName: "deviceUniqueIdentifier",
|
|
186
|
+
args: []
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
/** Whether this wallet currently holds the given eSIM wallet. */
|
|
190
|
+
export const _isValidESIMWallet = async (client, address, eSIMWalletAddress) => {
|
|
191
|
+
return client.readContract({
|
|
192
|
+
address,
|
|
193
|
+
abi: DeviceWallet,
|
|
194
|
+
functionName: "isValidESIMWallet",
|
|
195
|
+
args: [eSIMWalletAddress]
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Whether an eSIM wallet may pull ETH from this one. Binding a wallet never
|
|
200
|
+
* grants it, so this stays false until `toggleAccessToETH` says otherwise.
|
|
201
|
+
*/
|
|
202
|
+
export const _canPullETH = async (client, address, eSIMWalletAddress) => {
|
|
203
|
+
return client.readContract({
|
|
204
|
+
address,
|
|
205
|
+
abi: DeviceWallet,
|
|
206
|
+
functionName: "canPullETH",
|
|
207
|
+
args: [eSIMWalletAddress]
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Check a signature over an arbitrary message, per ERC-1271. Returns
|
|
212
|
+
* `0x1626ba7e` when the signature is valid and unexpired, `0xffffffff` otherwise.
|
|
213
|
+
*
|
|
214
|
+
* The signature is a version byte, then six bytes of `validUntil`, then the
|
|
215
|
+
* ABI-encoded WebAuthn assertion. What was signed is not `messageHash` itself but
|
|
216
|
+
* an EIP-191 digest over version, validUntil, chain id, this wallet's address and
|
|
217
|
+
* `messageHash`, so a signature cannot be replayed on another chain or against
|
|
218
|
+
* the same owner key's wallet at a different salt.
|
|
219
|
+
*/
|
|
220
|
+
export const _isValidSignature = async (client, address, messageHash, signature) => {
|
|
221
|
+
return client.readContract({
|
|
222
|
+
address,
|
|
223
|
+
abi: DeviceWallet,
|
|
224
|
+
functionName: "isValidSignature",
|
|
225
|
+
args: [messageHash, signature]
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
/** The registry this wallet reports its ownership changes to. */
|
|
229
|
+
export const _registry = async (client, address) => {
|
|
230
|
+
return client.readContract({
|
|
231
|
+
address,
|
|
232
|
+
abi: DeviceWallet,
|
|
233
|
+
functionName: "registry",
|
|
234
|
+
args: []
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
/** The factory that deploys this wallet's eSIM wallets. */
|
|
238
|
+
export const _eSIMWalletFactory = async (client, address) => {
|
|
239
|
+
return client.readContract({
|
|
240
|
+
address,
|
|
241
|
+
abi: DeviceWallet,
|
|
242
|
+
functionName: "eSIMWalletFactory",
|
|
243
|
+
args: []
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
/** The ERC-4337 EntryPoint this wallet answers to. Immutable. */
|
|
247
|
+
export const _entryPoint = async (client, address) => {
|
|
248
|
+
return client.readContract({
|
|
249
|
+
address,
|
|
250
|
+
abi: DeviceWallet,
|
|
251
|
+
functionName: "entryPoint",
|
|
252
|
+
args: []
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
/** The P256 verifier used when the RIP-7212 precompile is unavailable. */
|
|
256
|
+
export const _verifier = async (client, address) => {
|
|
257
|
+
return client.readContract({
|
|
258
|
+
address,
|
|
259
|
+
abi: DeviceWallet,
|
|
260
|
+
functionName: "verifier",
|
|
261
|
+
args: []
|
|
262
|
+
});
|
|
263
|
+
};
|
|
71
264
|
export const _getOwner = async (client, address) => {
|
|
72
265
|
const contract = getContract({
|
|
73
266
|
abi: DeviceWallet,
|
|
@@ -45,3 +45,92 @@ export const _getCurrentDeviceWalletImplementation = async (client) => {
|
|
|
45
45
|
args: []
|
|
46
46
|
});
|
|
47
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Check an identifier and owner key before deploying. Answers the zero address
|
|
50
|
+
* when both are free, or the wallet already holding one of them.
|
|
51
|
+
*
|
|
52
|
+
* Call this first. `createAccount` runs inside EntryPoint validation, where the
|
|
53
|
+
* 4337 rules bar it from reading the registry, so it cannot see that an
|
|
54
|
+
* identifier or a key is taken: it deploys a second wallet at a fresh address
|
|
55
|
+
* and the `postCreateAccount` that would register it fails afterwards.
|
|
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) => {
|
|
60
|
+
const chainID = await client.getChainId();
|
|
61
|
+
const rpcURL = client.transport.url;
|
|
62
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
63
|
+
return client.readContract({
|
|
64
|
+
address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
|
|
65
|
+
abi: DeviceWalletFactory,
|
|
66
|
+
functionName: "preCreateAccountValidation",
|
|
67
|
+
args: [deviceUniqueIdentifier, deviceWalletOwnerKey]
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Whether the factory has recorded this wallet. Set by `postCreateAccount`, not
|
|
72
|
+
* by the deploy, so a wallet the app just created reads false until the backend
|
|
73
|
+
* registers it.
|
|
74
|
+
*/
|
|
75
|
+
export const _deviceWalletInfoAdded = async (client, deviceWallet) => {
|
|
76
|
+
const chainID = await client.getChainId();
|
|
77
|
+
const rpcURL = client.transport.url;
|
|
78
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
79
|
+
return client.readContract({
|
|
80
|
+
address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
|
|
81
|
+
abi: DeviceWalletFactory,
|
|
82
|
+
functionName: "deviceWalletInfoAdded",
|
|
83
|
+
args: [deviceWallet]
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* The beacon every device wallet reads its implementation from. One update moves
|
|
88
|
+
* all of them and no wallet can decline it.
|
|
89
|
+
*/
|
|
90
|
+
export const _beacon = async (client) => {
|
|
91
|
+
const chainID = await client.getChainId();
|
|
92
|
+
const rpcURL = client.transport.url;
|
|
93
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
94
|
+
return client.readContract({
|
|
95
|
+
address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
|
|
96
|
+
abi: DeviceWalletFactory,
|
|
97
|
+
functionName: "beacon",
|
|
98
|
+
args: []
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
/** The registry the factory writes new wallets into. */
|
|
102
|
+
export const _registry = async (client) => {
|
|
103
|
+
const chainID = await client.getChainId();
|
|
104
|
+
const rpcURL = client.transport.url;
|
|
105
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
106
|
+
return client.readContract({
|
|
107
|
+
address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
|
|
108
|
+
abi: DeviceWalletFactory,
|
|
109
|
+
functionName: "registry",
|
|
110
|
+
args: []
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
/** The EntryPoint baked into every device wallet this factory deploys. */
|
|
114
|
+
export const _entryPoint = async (client) => {
|
|
115
|
+
const chainID = await client.getChainId();
|
|
116
|
+
const rpcURL = client.transport.url;
|
|
117
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
118
|
+
return client.readContract({
|
|
119
|
+
address: values.factoryAddresses.DEVICE_WALLET_FACTORY,
|
|
120
|
+
abi: DeviceWalletFactory,
|
|
121
|
+
functionName: "entryPoint",
|
|
122
|
+
args: []
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
/** The contract new device wallets verify WebAuthn assertions through. */
|
|
126
|
+
export const _verifier = async (client) => {
|
|
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.DEVICE_WALLET_FACTORY,
|
|
132
|
+
abi: DeviceWalletFactory,
|
|
133
|
+
functionName: "verifier",
|
|
134
|
+
args: []
|
|
135
|
+
});
|
|
136
|
+
};
|