kokio-sdk 0.1.2 → 0.1.4
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/{src/abis/BeaconProxy.json → dist/esm/abis/BeaconProxy.js} +3 -2
- package/dist/esm/abis/DeviceWallet.js +913 -0
- package/{src/abis/DeviceWalletFactory.json → dist/esm/abis/DeviceWalletFactory.js} +3 -2
- package/{src/abis/ESIMWallet.json → dist/esm/abis/ESIMWallet.js} +3 -2
- package/{src/abis/ESIMWalletFactory.json → dist/esm/abis/ESIMWalletFactory.js} +3 -2
- package/{src/abis/LazyWalletRegistry.json → dist/esm/abis/LazyWalletRegistry.js} +3 -2
- package/{src/abis/P256Verifier.json → dist/esm/abis/P256Verifier.js} +3 -2
- package/{src/abis/Registry.json → dist/esm/abis/Registry.js} +3 -2
- package/{src/abis/RegistryHelper.json → dist/esm/abis/RegistryHelper.js} +3 -2
- package/dist/esm/abis/index.js +10 -0
- package/dist/esm/config.js +52 -0
- package/dist/esm/interface/P256VerifierClass.js +10 -0
- package/dist/esm/interface/constantsClass.js +38 -0
- package/{src/interface/deviceWalletClass.ts → dist/esm/interface/deviceWalletClass.js} +12 -36
- package/dist/esm/interface/deviceWalletFactoryClass.js +18 -0
- package/dist/esm/interface/eSIMWalletClass.js +33 -0
- package/dist/esm/interface/eSIMWalletFactoryClass.js +21 -0
- package/dist/esm/interface/lazyWalletRegistryClass.js +19 -0
- package/{src/interface/smartAccountClass.ts → dist/esm/interface/smartAccountClass.js} +3 -11
- package/dist/esm/interface/utilsClass.js +13 -0
- package/{src/logic/P256Verifier.ts → dist/esm/logic/P256Verifier.js} +6 -17
- package/dist/esm/logic/account-kit/createSmartAccount.js +298 -0
- package/{src/logic/constants.ts → dist/esm/logic/constants.js} +42 -103
- package/{src/logic/deviceWallet.ts → dist/esm/logic/deviceWallet.js} +46 -74
- package/{src/logic/deviceWalletFactory.ts → dist/esm/logic/deviceWalletFactory.js} +22 -43
- package/{src/logic/eSIMWallet.ts → dist/esm/logic/eSIMWallet.js} +41 -59
- package/{src/logic/eSIMWalletFactory.ts → dist/esm/logic/eSIMWalletFactory.js} +28 -41
- package/{src/logic/lazyWalletRegistry.ts → dist/esm/logic/lazyWalletRegistry.js} +29 -60
- package/dist/esm/logic/utils.js +100 -0
- package/dist/esm/types-export.js +1 -0
- package/dist/esm/types.js +1 -0
- package/dist/types/abis/BeaconProxy.d.ts +3 -0
- package/dist/types/abis/DeviceWallet.d.ts +3 -0
- package/dist/types/abis/DeviceWalletFactory.d.ts +3 -0
- package/dist/types/abis/ESIMWallet.d.ts +3 -0
- package/dist/types/abis/ESIMWalletFactory.d.ts +3 -0
- package/dist/types/abis/LazyWalletRegistry.d.ts +3 -0
- package/dist/types/abis/P256Verifier.d.ts +3 -0
- package/dist/types/abis/Registry.d.ts +3 -0
- package/dist/types/abis/RegistryHelper.d.ts +3 -0
- package/dist/types/abis/index.d.ts +10 -0
- package/dist/types/config.d.ts +37 -0
- package/dist/types/interface/P256VerifierClass.d.ts +7 -0
- package/dist/types/interface/constantsClass.d.ts +27 -0
- package/dist/types/interface/deviceWalletClass.d.ts +2577 -0
- package/dist/types/interface/deviceWalletFactoryClass.d.ts +2570 -0
- package/dist/types/interface/eSIMWalletClass.d.ts +16 -0
- package/dist/types/interface/eSIMWalletFactoryClass.d.ts +2571 -0
- package/dist/types/interface/lazyWalletRegistryClass.d.ts +11 -0
- package/dist/types/interface/smartAccountClass.d.ts +2574 -0
- package/dist/types/interface/utilsClass.d.ts +2567 -0
- package/dist/types/logic/P256Verifier.d.ts +3 -0
- package/dist/types/logic/account-kit/createSmartAccount.d.ts +6 -0
- package/dist/types/logic/constants.d.ts +32 -0
- package/dist/types/logic/deviceWallet.d.ts +12 -0
- package/dist/types/logic/deviceWalletFactory.d.ts +5 -0
- package/dist/types/logic/eSIMWallet.d.ts +11 -0
- package/dist/types/logic/eSIMWalletFactory.d.ts +6 -0
- package/dist/types/logic/lazyWalletRegistry.d.ts +7 -0
- package/dist/types/logic/utils.d.ts +18 -0
- package/dist/types/types-export.d.ts +1 -0
- package/{src/types.ts → dist/types/types.d.ts} +19 -21
- package/package.json +24 -14
- package/.github/workflows/npm_publish.yaml +0 -45
- package/src/abis/DeviceWallet.json +0 -912
- package/src/abis/index.ts +0 -21
- package/src/config.ts +0 -58
- package/src/interface/P256VerifierClass.ts +0 -19
- package/src/interface/constantsClass.ts +0 -36
- package/src/interface/deviceWalletFactoryClass.ts +0 -35
- package/src/interface/eSIMWalletClass.ts +0 -55
- package/src/interface/eSIMWalletFactoryClass.ts +0 -36
- package/src/interface/lazyWalletRegistryClass.ts +0 -34
- package/src/interface/utilsClass.ts +0 -21
- package/src/logic/account-kit/createSmartAccount.ts +0 -401
- package/src/logic/utils.ts +0 -123
- package/src/types-export.ts +0 -7
- package/tsconfig.json +0 -114
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { createSmartAccountClient, getEntryPoint, toSmartContractAccount, split, erc7677Middleware } from "@aa-sdk/core";
|
|
2
|
+
import { http, encodeFunctionData, encodePacked, encodeAbiParameters, parseAbiParameters, getContract, concat, keccak256, getContractAddress, getAddress, hashMessage, stringToBytes, toHex, hexToBytes, bytesToHex } from "viem";
|
|
3
|
+
import { _getChainSpecificConstants, ZERO, SIGNATURE_VALIDITY_SECONDS } from "../constants.js";
|
|
4
|
+
import { _remove0x } from "../utils.js";
|
|
5
|
+
import { DeviceWallet, DeviceWalletFactory } from "../../abis/index.js";
|
|
6
|
+
import { isoBase64URL } from "@simplewebauthn/server/helpers";
|
|
7
|
+
import { Passkey } from "react-native-passkey";
|
|
8
|
+
import { p256 } from "@noble/curves/nist.js";
|
|
9
|
+
var AuthenticatorTransport;
|
|
10
|
+
(function (AuthenticatorTransport) {
|
|
11
|
+
AuthenticatorTransport["usb"] = "usb";
|
|
12
|
+
AuthenticatorTransport["nfc"] = "nfc";
|
|
13
|
+
AuthenticatorTransport["ble"] = "ble";
|
|
14
|
+
AuthenticatorTransport["smartCard"] = "smart-card";
|
|
15
|
+
AuthenticatorTransport["hybrid"] = "hybrid";
|
|
16
|
+
AuthenticatorTransport["internal"] = "internal";
|
|
17
|
+
})(AuthenticatorTransport || (AuthenticatorTransport = {}));
|
|
18
|
+
/*
|
|
19
|
+
** Stamp is client-side authentication. Since the passkeys are one the user's mobile device
|
|
20
|
+
** react-native-passkey helps fetch passkey for the user (provided credentialId, rpId).
|
|
21
|
+
** This is exactly how the WebAuthn.sol contract needs it to be.
|
|
22
|
+
*/
|
|
23
|
+
export const _stamp = async (credentialId, rpId, payload) => {
|
|
24
|
+
const signingOptions = {
|
|
25
|
+
challenge: isoBase64URL.fromBuffer(hexToBytes(payload)),
|
|
26
|
+
allowCredentials: [{
|
|
27
|
+
id: credentialId,
|
|
28
|
+
type: "public-key",
|
|
29
|
+
transports: [AuthenticatorTransport.internal]
|
|
30
|
+
}],
|
|
31
|
+
rpId,
|
|
32
|
+
userVerification: "required"
|
|
33
|
+
};
|
|
34
|
+
let authenticationResult;
|
|
35
|
+
try {
|
|
36
|
+
authenticationResult = await Passkey.get(signingOptions);
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.log("Failed to get authenticationResult");
|
|
40
|
+
console.error(JSON.stringify(e, Object.getOwnPropertyNames(e)));
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
// See https://github.com/f-23/react-native-passkey/issues/54
|
|
44
|
+
// On Android the typedef lies. Authentication result is actually a string!
|
|
45
|
+
// TODO: remove me once the above is resolved.
|
|
46
|
+
const brokenAuthenticationResult = authenticationResult;
|
|
47
|
+
if (typeof brokenAuthenticationResult === "string") {
|
|
48
|
+
authenticationResult = JSON.parse(brokenAuthenticationResult);
|
|
49
|
+
}
|
|
50
|
+
const { clientDataJSON, authenticatorData, signature } = authenticationResult.response;
|
|
51
|
+
// 1. Decode clientDataJSON
|
|
52
|
+
const clientDataJSONBuffer = isoBase64URL.toBuffer(clientDataJSON);
|
|
53
|
+
const clientDataJSONString = new TextDecoder().decode(clientDataJSONBuffer);
|
|
54
|
+
// 2. Calculate indices for the contract (byte offsets)
|
|
55
|
+
const typeSearchString = '"type":"webauthn.get"';
|
|
56
|
+
const challengeSearchString = '"challenge":';
|
|
57
|
+
const rawTypeIndex = clientDataJSONString.indexOf(typeSearchString);
|
|
58
|
+
const challengeIndex = clientDataJSONString.indexOf(challengeSearchString);
|
|
59
|
+
let typeIndex = rawTypeIndex;
|
|
60
|
+
if (rawTypeIndex === -1) {
|
|
61
|
+
console.warn("typeIndex not found", {
|
|
62
|
+
expected: typeSearchString,
|
|
63
|
+
clientDataSnippet: clientDataJSONString.slice(0, 200),
|
|
64
|
+
});
|
|
65
|
+
typeIndex = 0;
|
|
66
|
+
}
|
|
67
|
+
if (challengeIndex === -1) {
|
|
68
|
+
throw new Error(`Could not find challenge substring '${challengeSearchString}' in clientDataJSON for index calculation.`);
|
|
69
|
+
}
|
|
70
|
+
// 3. Decode authenticatorData
|
|
71
|
+
const authenticatorDataBytes = isoBase64URL.toBuffer(authenticatorData);
|
|
72
|
+
const authenticatorDataHex = bytesToHex(authenticatorDataBytes);
|
|
73
|
+
// 4. Decode signature (ASN.1 DER encoded)
|
|
74
|
+
const signatureBytes = isoBase64URL.toBuffer(signature);
|
|
75
|
+
// let parsedSignature = p256.Signature.fromDER(signatureBytes);
|
|
76
|
+
let parsedSignature = p256.Signature.fromBytes(signatureBytes instanceof Uint8Array
|
|
77
|
+
? signatureBytes
|
|
78
|
+
: new Uint8Array(signatureBytes), "der");
|
|
79
|
+
// Normalize s
|
|
80
|
+
const n = p256.Point.CURVE().n;
|
|
81
|
+
const halfN = n >> 1n;
|
|
82
|
+
const r = parsedSignature.r;
|
|
83
|
+
const s = parsedSignature.s > halfN
|
|
84
|
+
? n - parsedSignature.s
|
|
85
|
+
: parsedSignature.s;
|
|
86
|
+
const webAuthnSig = {
|
|
87
|
+
authenticatorData: authenticatorDataHex,
|
|
88
|
+
clientDataJSON: clientDataJSONString,
|
|
89
|
+
challengeIndex: BigInt(challengeIndex),
|
|
90
|
+
typeIndex: BigInt(typeIndex),
|
|
91
|
+
r: r,
|
|
92
|
+
s: s
|
|
93
|
+
};
|
|
94
|
+
return webAuthnSig;
|
|
95
|
+
};
|
|
96
|
+
const _encodeExecute = async (tx) => {
|
|
97
|
+
return encodeFunctionData({
|
|
98
|
+
abi: DeviceWallet,
|
|
99
|
+
functionName: "execute",
|
|
100
|
+
args: [{
|
|
101
|
+
dest: tx.target,
|
|
102
|
+
value: tx.value ?? ZERO,
|
|
103
|
+
data: tx.data
|
|
104
|
+
}]
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
const _encodeBatchExecute = async (txs) => {
|
|
108
|
+
const new_txs = [];
|
|
109
|
+
for (let i = 0; i < txs.length; ++i) {
|
|
110
|
+
new_txs.push({
|
|
111
|
+
dest: txs[i].target,
|
|
112
|
+
value: txs[i].value ?? ZERO,
|
|
113
|
+
data: txs[i].data
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return encodeFunctionData({
|
|
117
|
+
abi: DeviceWallet,
|
|
118
|
+
functionName: "executeBatch",
|
|
119
|
+
args: [new_txs]
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
const _getAccountInitCode = async (client, deviceUniqueIdentifier, deviceWalletOwnerKey, salt) => {
|
|
123
|
+
// To send with user operations
|
|
124
|
+
const chainID = await client.getChainId();
|
|
125
|
+
const rpcURL = client.transport.url;
|
|
126
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
127
|
+
const callData = encodeFunctionData({
|
|
128
|
+
abi: DeviceWalletFactory,
|
|
129
|
+
functionName: "createAccount",
|
|
130
|
+
args: [deviceUniqueIdentifier, deviceWalletOwnerKey, salt],
|
|
131
|
+
});
|
|
132
|
+
return values.factoryAddresses.DEVICE_WALLET_FACTORY.concat(_remove0x(callData));
|
|
133
|
+
};
|
|
134
|
+
const getInitCodeHash = async (client, deviceUniqueIdentifier, deviceWalletOwnerKey) => {
|
|
135
|
+
const chainID = await client.getChainId();
|
|
136
|
+
const rpcURL = client.transport.url;
|
|
137
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
138
|
+
// off-chain computation of the DeviceWallet address
|
|
139
|
+
const registry = values.factoryAddresses.REGISTRY;
|
|
140
|
+
const deviceWalletFactoryAddress = values.factoryAddresses.DEVICE_WALLET_FACTORY;
|
|
141
|
+
const eSIMWalletFactoryAddress = values.factoryAddresses.ESIM_WALLET_FACTORY;
|
|
142
|
+
const deviceWalletFactory = getContract({
|
|
143
|
+
abi: DeviceWalletFactory,
|
|
144
|
+
address: deviceWalletFactoryAddress,
|
|
145
|
+
client
|
|
146
|
+
});
|
|
147
|
+
const beacon = await deviceWalletFactory.read.beacon([]);
|
|
148
|
+
// Encode the DeviceWallet.init with the init params
|
|
149
|
+
const deviceWalletInitData = encodeFunctionData({
|
|
150
|
+
abi: DeviceWallet,
|
|
151
|
+
functionName: "init",
|
|
152
|
+
args: [
|
|
153
|
+
registry,
|
|
154
|
+
deviceWalletOwnerKey,
|
|
155
|
+
deviceUniqueIdentifier,
|
|
156
|
+
eSIMWalletFactoryAddress
|
|
157
|
+
]
|
|
158
|
+
});
|
|
159
|
+
const beaconProxyBytecode = "0x60a06040908082526104a8803803809161001982856102ae565b8339810182828203126101e95761002f826102e7565b60208084015191939091906001600160401b0382116101e9570182601f820112156101e957805190610060826102fb565b9361006d875195866102ae565b8285528383830101116101e957829060005b83811061029a57505060009184010152823b1561027a577fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b038581169182179092558551635c60da1b60e01b8082529194928482600481895afa91821561026f57600092610238575b50813b1561021f5750508551847f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e600080a282511561020057508290600487518096819382525afa9283156101f5576000936101b3575b5091600080848461019096519101845af4903d156101aa573d610174816102fb565b90610181885192836102ae565b8152600081943d92013e610316565b505b6080525161012e908161037a82396080518160180152f35b60609250610316565b92508183813d83116101ee575b6101ca81836102ae565b810103126101e9576000806101e1610190956102e7565b945050610152565b600080fd5b503d6101c0565b85513d6000823e3d90fd5b9350505050346102105750610192565b63b398979f60e01b8152600490fd5b8751634c9c8ce360e01b81529116600482015260249150fd5b9091508481813d8311610268575b61025081836102ae565b810103126101e957610261906102e7565b90386100fb565b503d610246565b88513d6000823e3d90fd5b8351631933b43b60e21b81526001600160a01b0384166004820152602490fd5b81810183015186820184015284920161007f565b601f909101601f19168101906001600160401b038211908210176102d157604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036101e957565b6001600160401b0381116102d157601f01601f191660200190565b9061033d575080511561032b57805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580610370575b61034e575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b1561034656fe60806040819052635c60da1b60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811560a9576000916054575b5060da565b905060203d60201160a3575b601f8101601f191682019167ffffffffffffffff831181841017608d576088926040520160b5565b38604f565b634e487b7160e01b600052604160045260246000fd5b503d6060565b6040513d6000823e3d90fd5b602090607f19011260d5576080516001600160a01b038116810360d55790565b600080fd5b6000808092368280378136915af43d82803e1560f4573d90f35b3d90fdfea264697066735822122099ba460fd62b3e22c737d15959887e6cae3498f3495d31e43e2bcf1283aec7d264736f6c63430008190033";
|
|
160
|
+
// Encode BeaconProxy constructor args
|
|
161
|
+
const beaconProxyConstructorArgs = encodeAbiParameters(parseAbiParameters("address, bytes"), [beacon, deviceWalletInitData]);
|
|
162
|
+
// Compute initCode
|
|
163
|
+
const initCode = concat([beaconProxyBytecode, beaconProxyConstructorArgs]);
|
|
164
|
+
return keccak256(initCode);
|
|
165
|
+
};
|
|
166
|
+
const getCounterFactualAddress = async (client, deviceUniqueIdentifier, deviceWalletOwnerKey, salt) => {
|
|
167
|
+
const chainID = await client.getChainId();
|
|
168
|
+
const rpcURL = client.transport.url;
|
|
169
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
170
|
+
const deviceWalletFactoryAddress = values.factoryAddresses.DEVICE_WALLET_FACTORY;
|
|
171
|
+
const uniqueSaltBytes32 = toHex(salt, { size: 32 });
|
|
172
|
+
const initCodeHash = await getInitCodeHash(client, deviceUniqueIdentifier, deviceWalletOwnerKey);
|
|
173
|
+
// Calculate deterministic address from init code hash
|
|
174
|
+
const create2Address = getContractAddress({
|
|
175
|
+
from: deviceWalletFactoryAddress,
|
|
176
|
+
salt: uniqueSaltBytes32,
|
|
177
|
+
bytecodeHash: initCodeHash,
|
|
178
|
+
opcode: "CREATE2",
|
|
179
|
+
});
|
|
180
|
+
return getAddress(create2Address);
|
|
181
|
+
};
|
|
182
|
+
const _encodeSignature = async (webAuthnSignature, validUntil) => {
|
|
183
|
+
const encodedWebAuthnSignatureBytes = encodeAbiParameters([
|
|
184
|
+
{
|
|
185
|
+
type: "tuple",
|
|
186
|
+
name: "WebAuthnSignature",
|
|
187
|
+
components: [
|
|
188
|
+
{ name: "authenticatorData", type: "bytes", },
|
|
189
|
+
{ name: "clientDataJSON", type: "string", },
|
|
190
|
+
{ name: "challengeIndex", type: "uint256", },
|
|
191
|
+
{ name: "typeIndex", type: "uint256", },
|
|
192
|
+
{ name: "r", type: "uint256", },
|
|
193
|
+
{ name: "s", type: "uint256", },
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
], [
|
|
197
|
+
webAuthnSignature
|
|
198
|
+
]);
|
|
199
|
+
const signature = encodePacked(["uint8", "uint48", "bytes"], [1, validUntil, encodedWebAuthnSignatureBytes]);
|
|
200
|
+
return signature;
|
|
201
|
+
};
|
|
202
|
+
// message here is the original message data (string or Uint8Array) directly from the app
|
|
203
|
+
const _signMessage = async (message, credentialId, rpId) => {
|
|
204
|
+
const validUntil = Math.floor(Date.now() / 1000) + SIGNATURE_VALIDITY_SECONDS;
|
|
205
|
+
const payload = hashMessage({ raw: stringToBytes(message) });
|
|
206
|
+
// The original message is passed to the stamp and sign function.
|
|
207
|
+
// The stamp and sign function creates the EIP-191 digest hash using its hashMessage function
|
|
208
|
+
// The result of the hashMessage(message) will be the `payload` used as a challenge
|
|
209
|
+
const webAuthnSignature = await _stamp(credentialId, rpId, payload);
|
|
210
|
+
return _encodeSignature(webAuthnSignature, validUntil);
|
|
211
|
+
};
|
|
212
|
+
const _signTypedData = async (typedData, organiationId, signWith) => {
|
|
213
|
+
// signature valid until, UNIX timestamp in seconds
|
|
214
|
+
const validUntil = Math.floor(Date.now() / 1000) + SIGNATURE_VALIDITY_SECONDS;
|
|
215
|
+
// TODO: Implement stamping for Typed Data
|
|
216
|
+
let webAuthnSignature = {
|
|
217
|
+
authenticatorData: `0x`,
|
|
218
|
+
clientDataJSON: "",
|
|
219
|
+
challengeIndex: BigInt(0),
|
|
220
|
+
typeIndex: BigInt(0),
|
|
221
|
+
r: BigInt(0),
|
|
222
|
+
s: BigInt(0)
|
|
223
|
+
};
|
|
224
|
+
return _encodeSignature(webAuthnSignature, validUntil);
|
|
225
|
+
};
|
|
226
|
+
const _signUserOperationHash = async (credentialId, rpId, userOpHash) => {
|
|
227
|
+
const validUntil = Math.floor(Date.now() / 1000) + SIGNATURE_VALIDITY_SECONDS;
|
|
228
|
+
const messagePrecursor = encodePacked(["uint8", "uint48", "bytes32"], [
|
|
229
|
+
1,
|
|
230
|
+
validUntil,
|
|
231
|
+
userOpHash
|
|
232
|
+
]);
|
|
233
|
+
const payload = hashMessage({ raw: messagePrecursor });
|
|
234
|
+
const webAuthnSignature = await _stamp(credentialId, rpId, payload);
|
|
235
|
+
return _encodeSignature(webAuthnSignature, validUntil);
|
|
236
|
+
};
|
|
237
|
+
export const _getSmartWallet = async (client, credentialId, rpId, organiationId, deviceUniqueIdentifier, deviceWalletOwnerKey, salt) => {
|
|
238
|
+
const chainID = await client.getChainId();
|
|
239
|
+
const rpcURL = client.transport.url;
|
|
240
|
+
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
241
|
+
if (!client.account)
|
|
242
|
+
throw new Error('Error: No signer account found with WalletClient');
|
|
243
|
+
const signWith = client.account.address;
|
|
244
|
+
return toSmartContractAccount({
|
|
245
|
+
/// REQUIRED PARAMS ///
|
|
246
|
+
source: "MyAccount",
|
|
247
|
+
transport: http(values.rpcURL),
|
|
248
|
+
chain: values.chain,
|
|
249
|
+
// The EntryPointDef that your account is compatible with
|
|
250
|
+
entryPoint: getEntryPoint(values.chain, { version: "0.7.0" }),
|
|
251
|
+
getAccountInitCode: async () => await _getAccountInitCode(client, deviceUniqueIdentifier, deviceWalletOwnerKey, salt),
|
|
252
|
+
// getAccountInitCodeHash: async (): Promise<BytesLike> => await getInitCodeHash(client, deviceUniqueIdentifier, deviceWalletOwnerKey),
|
|
253
|
+
// an invalid signature that doesn't cause your account to revert during validation
|
|
254
|
+
getDummySignature: async () => "0x",
|
|
255
|
+
// given a UO in the form of {target, data, value} should output the calldata for calling your contract's execution method
|
|
256
|
+
encodeExecute: async (uo) => _encodeExecute(uo),
|
|
257
|
+
signMessage: async ({ message }) => _signMessage(message, credentialId, rpId),
|
|
258
|
+
signTypedData: async (typedData) => _signTypedData(typedData, organiationId, signWith),
|
|
259
|
+
/// OPTIONAL PARAMS ///
|
|
260
|
+
// if you already know your account's address, pass that in here to avoid generating a new counterfactual
|
|
261
|
+
accountAddress: await getCounterFactualAddress(client, deviceUniqueIdentifier, deviceWalletOwnerKey, salt),
|
|
262
|
+
// if your account supports batching, this should take an array of UOs and return the calldata for calling your contract's batchExecute method
|
|
263
|
+
encodeBatchExecute: async (uos) => _encodeBatchExecute(uos),
|
|
264
|
+
// if your contract expects a different signing scheme than the default signMessage scheme, you can override that here
|
|
265
|
+
signUserOperationHash: async (hash) => _signUserOperationHash(credentialId, rpId, hash),
|
|
266
|
+
// allows you to define the calldata for upgrading your account
|
|
267
|
+
// encodeUpgradeToAndCall: async (params): Promise<Hash> => "0x...",
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
export const _getSmartWalletClient = async (client, pimlicoAPIKey, gasPolicyId, account) => {
|
|
271
|
+
const chainID = await client.getChainId();
|
|
272
|
+
const rpcURL = client.transport.url;
|
|
273
|
+
const values = _getChainSpecificConstants(chainID, rpcURL, pimlicoAPIKey);
|
|
274
|
+
const bundlerMethods = [
|
|
275
|
+
"eth_sendUserOperation",
|
|
276
|
+
"eth_estimateUserOperationGas",
|
|
277
|
+
"eth_getUserOperationReceipt",
|
|
278
|
+
"eth_getUserOperationByHash",
|
|
279
|
+
"eth_supportedEntryPoints",
|
|
280
|
+
];
|
|
281
|
+
// Uses Pimlico paymaster by default for above defined bundler methods and Alchemy as fallback
|
|
282
|
+
return createSmartAccountClient({
|
|
283
|
+
// created above
|
|
284
|
+
account: account,
|
|
285
|
+
chain: values.chain,
|
|
286
|
+
transport: split({
|
|
287
|
+
overrides: [
|
|
288
|
+
{
|
|
289
|
+
methods: bundlerMethods,
|
|
290
|
+
transport: http(`${values.pimlicoRpcURL}`),
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
fallback: http(values.rpcURL),
|
|
294
|
+
}),
|
|
295
|
+
// transport: http(values.rpcURL),
|
|
296
|
+
...erc7677Middleware({ context: { policyId: gasPolicyId } })
|
|
297
|
+
});
|
|
298
|
+
};
|
|
@@ -1,55 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
mainnet,
|
|
4
|
-
sepolia,
|
|
5
|
-
optimism,
|
|
6
|
-
optimismSepolia,
|
|
7
|
-
arbitrum,
|
|
8
|
-
arbitrumSepolia,
|
|
9
|
-
base,
|
|
10
|
-
baseSepolia
|
|
11
|
-
} from "viem/chains";
|
|
12
|
-
|
|
1
|
+
import { mainnet, sepolia, optimism, optimismSepolia, arbitrum, arbitrumSepolia, base, baseSepolia } from "viem/chains";
|
|
13
2
|
export const ZERO = BigInt('0');
|
|
14
|
-
|
|
15
3
|
export const SIGNATURE_VALIDITY_SECONDS = 180; // 3 minutes validity
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
MAINNET = 1
|
|
19
|
-
SEPOLIA = 11155111
|
|
20
|
-
OPTIMISM_MAINNET = 10
|
|
21
|
-
OPTIMISM_SEPOLIA = 11155420
|
|
22
|
-
BASE_MAINNET = 8453
|
|
23
|
-
BASE_SEPOLIA = 84532
|
|
24
|
-
ARBITRUM_ONE = 42161
|
|
25
|
-
ARBITRUM_SEPOLIA = 421614
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface chainSpecifcConstants {
|
|
29
|
-
factoryAddresses:
|
|
30
|
-
typeof sepoliaFactoryAddresses |
|
|
31
|
-
typeof mainnetFactoryAddresses |
|
|
32
|
-
typeof optimismMainnetFactoryAddresses |
|
|
33
|
-
typeof optimismSepoliaFactoryAddresses |
|
|
34
|
-
typeof baseMainnetFactoryAddresses |
|
|
35
|
-
typeof baseSepoliaFactoryAddresses |
|
|
36
|
-
typeof arbitrumOneFactoryAddresses |
|
|
37
|
-
typeof arbitrumSepoliaFactoryAddresses;
|
|
38
|
-
chain:
|
|
39
|
-
typeof mainnet |
|
|
40
|
-
typeof sepolia |
|
|
41
|
-
typeof optimism |
|
|
42
|
-
typeof optimismSepolia |
|
|
43
|
-
typeof base |
|
|
44
|
-
typeof baseSepolia |
|
|
45
|
-
typeof arbitrum |
|
|
46
|
-
typeof arbitrumSepolia
|
|
47
|
-
rpcURL: string;
|
|
48
|
-
pimlicoRpcURL: string;
|
|
49
|
-
customErrors: typeof customErrors;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export const sepoliaFactoryAddresses: Record<string, Address> = {
|
|
4
|
+
export var CHAIN_ID;
|
|
5
|
+
(function (CHAIN_ID) {
|
|
6
|
+
CHAIN_ID[CHAIN_ID["MAINNET"] = 1] = "MAINNET";
|
|
7
|
+
CHAIN_ID[CHAIN_ID["SEPOLIA"] = 11155111] = "SEPOLIA";
|
|
8
|
+
CHAIN_ID[CHAIN_ID["OPTIMISM_MAINNET"] = 10] = "OPTIMISM_MAINNET";
|
|
9
|
+
CHAIN_ID[CHAIN_ID["OPTIMISM_SEPOLIA"] = 11155420] = "OPTIMISM_SEPOLIA";
|
|
10
|
+
CHAIN_ID[CHAIN_ID["BASE_MAINNET"] = 8453] = "BASE_MAINNET";
|
|
11
|
+
CHAIN_ID[CHAIN_ID["BASE_SEPOLIA"] = 84532] = "BASE_SEPOLIA";
|
|
12
|
+
CHAIN_ID[CHAIN_ID["ARBITRUM_ONE"] = 42161] = "ARBITRUM_ONE";
|
|
13
|
+
CHAIN_ID[CHAIN_ID["ARBITRUM_SEPOLIA"] = 421614] = "ARBITRUM_SEPOLIA";
|
|
14
|
+
})(CHAIN_ID || (CHAIN_ID = {}));
|
|
15
|
+
export const sepoliaFactoryAddresses = {
|
|
53
16
|
DEVICE_WALLET_FACTORY: '0x63005d8214533fC7209678Aa39F7b9b0b51a7bcB',
|
|
54
17
|
ESIM_WALLET_FACTORY: '0xB4473979ff8cE4e09161B08f74EEb66BD7718076',
|
|
55
18
|
LAZY_WALLET_REGISTRY: '0x8a1E53b903efcc6b252CE4bD3b255202318505Ef',
|
|
@@ -57,9 +20,8 @@ export const sepoliaFactoryAddresses: Record<string, Address> = {
|
|
|
57
20
|
ENTRY_POINT: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
|
58
21
|
SENDER_CREATOR: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
|
|
59
22
|
P256VERIFIER: '0xF04f3b3935aD461D17d4a8a78E7ea21d4a61AEb1'
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export const mainnetFactoryAddresses: Record<string, Address> = {
|
|
23
|
+
};
|
|
24
|
+
export const mainnetFactoryAddresses = {
|
|
63
25
|
DEVICE_WALLET_FACTORY: '0x',
|
|
64
26
|
ESIM_WALLET_FACTORY: '0x',
|
|
65
27
|
LAZY_WALLET_REGISTRY: '0x',
|
|
@@ -67,9 +29,8 @@ export const mainnetFactoryAddresses: Record<string, Address> = {
|
|
|
67
29
|
ENTRY_POINT: '0x',
|
|
68
30
|
SENDER_CREATOR: '0x',
|
|
69
31
|
P256VERIFIER: '0x'
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const optimismMainnetFactoryAddresses: Record<string, Address> = {
|
|
32
|
+
};
|
|
33
|
+
export const optimismMainnetFactoryAddresses = {
|
|
73
34
|
DEVICE_WALLET_FACTORY: '0x',
|
|
74
35
|
ESIM_WALLET_FACTORY: '0x',
|
|
75
36
|
LAZY_WALLET_REGISTRY: '0x',
|
|
@@ -77,9 +38,8 @@ export const optimismMainnetFactoryAddresses: Record<string, Address> = {
|
|
|
77
38
|
ENTRY_POINT: '0x',
|
|
78
39
|
SENDER_CREATOR: '0x',
|
|
79
40
|
P256VERIFIER: '0x'
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export const optimismSepoliaFactoryAddresses: Record<string, Address> = {
|
|
41
|
+
};
|
|
42
|
+
export const optimismSepoliaFactoryAddresses = {
|
|
83
43
|
DEVICE_WALLET_FACTORY: '0x243cCdE6a56b0Ba740E067f39896772748E20fFD',
|
|
84
44
|
ESIM_WALLET_FACTORY: '0x8444bF9C39F01e4B092e42DC11695C61f8B93957',
|
|
85
45
|
LAZY_WALLET_REGISTRY: '0x3F14D060074B174B0784056bDe5e0f8970D25ff1',
|
|
@@ -87,9 +47,8 @@ export const optimismSepoliaFactoryAddresses: Record<string, Address> = {
|
|
|
87
47
|
ENTRY_POINT: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
|
88
48
|
SENDER_CREATOR: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
|
|
89
49
|
P256VERIFIER: '0x3c15a78046838481788613A9F111F972B562623C'
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export const baseMainnetFactoryAddresses: Record<string, Address> = {
|
|
50
|
+
};
|
|
51
|
+
export const baseMainnetFactoryAddresses = {
|
|
93
52
|
DEVICE_WALLET_FACTORY: '0x',
|
|
94
53
|
ESIM_WALLET_FACTORY: '0x',
|
|
95
54
|
LAZY_WALLET_REGISTRY: '0x',
|
|
@@ -97,9 +56,8 @@ export const baseMainnetFactoryAddresses: Record<string, Address> = {
|
|
|
97
56
|
ENTRY_POINT: '0x',
|
|
98
57
|
SENDER_CREATOR: '0x',
|
|
99
58
|
P256VERIFIER: '0x'
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export const baseSepoliaFactoryAddresses: Record<string, Address> = {
|
|
59
|
+
};
|
|
60
|
+
export const baseSepoliaFactoryAddresses = {
|
|
103
61
|
DEVICE_WALLET_FACTORY: '0xB4473979ff8cE4e09161B08f74EEb66BD7718076',
|
|
104
62
|
ESIM_WALLET_FACTORY: '0x63005d8214533fC7209678Aa39F7b9b0b51a7bcB',
|
|
105
63
|
LAZY_WALLET_REGISTRY: '0x8a1E53b903efcc6b252CE4bD3b255202318505Ef',
|
|
@@ -107,9 +65,8 @@ export const baseSepoliaFactoryAddresses: Record<string, Address> = {
|
|
|
107
65
|
ENTRY_POINT: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
|
108
66
|
SENDER_CREATOR: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
|
|
109
67
|
P256VERIFIER: '0xF04f3b3935aD461D17d4a8a78E7ea21d4a61AEb1'
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export const arbitrumOneFactoryAddresses: Record<string, Address> = {
|
|
68
|
+
};
|
|
69
|
+
export const arbitrumOneFactoryAddresses = {
|
|
113
70
|
DEVICE_WALLET_FACTORY: '0x',
|
|
114
71
|
ESIM_WALLET_FACTORY: '0x',
|
|
115
72
|
LAZY_WALLET_REGISTRY: '0x',
|
|
@@ -117,9 +74,8 @@ export const arbitrumOneFactoryAddresses: Record<string, Address> = {
|
|
|
117
74
|
ENTRY_POINT: '0x',
|
|
118
75
|
SENDER_CREATOR: '0x',
|
|
119
76
|
P256VERIFIER: '0x'
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export const arbitrumSepoliaFactoryAddresses: Record<string, Address> = {
|
|
77
|
+
};
|
|
78
|
+
export const arbitrumSepoliaFactoryAddresses = {
|
|
123
79
|
DEVICE_WALLET_FACTORY: '0x',
|
|
124
80
|
ESIM_WALLET_FACTORY: '0x',
|
|
125
81
|
LAZY_WALLET_REGISTRY: '0x',
|
|
@@ -127,36 +83,19 @@ export const arbitrumSepoliaFactoryAddresses: Record<string, Address> = {
|
|
|
127
83
|
ENTRY_POINT: '0x',
|
|
128
84
|
SENDER_CREATOR: '0x',
|
|
129
85
|
P256VERIFIER: '0x'
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export const customErrors: Record<string, string> = {
|
|
86
|
+
};
|
|
87
|
+
export const customErrors = {
|
|
133
88
|
NULL_OR_UNDEFINED_VALUE: "Error: Null or undefined value provided",
|
|
134
89
|
MISSING_SMART_WALLET: "Error: Client does not have smart wallet account associated",
|
|
135
90
|
MISSING_EOA_WALLET: "Error: Client does not have EOA wallet associated"
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export const _extractChainID = async (client: WalletClient) => {
|
|
139
|
-
|
|
91
|
+
};
|
|
92
|
+
export const _extractChainID = async (client) => {
|
|
140
93
|
if (!client) {
|
|
141
94
|
throw "Invalid Signer or Provider instance";
|
|
142
95
|
}
|
|
143
96
|
return client.getChainId();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export const _getChainSpecificConstants = (
|
|
147
|
-
chainID:
|
|
148
|
-
CHAIN_ID.SEPOLIA |
|
|
149
|
-
CHAIN_ID.MAINNET |
|
|
150
|
-
CHAIN_ID.OPTIMISM_MAINNET |
|
|
151
|
-
CHAIN_ID.OPTIMISM_SEPOLIA |
|
|
152
|
-
CHAIN_ID.BASE_MAINNET |
|
|
153
|
-
CHAIN_ID.BASE_SEPOLIA |
|
|
154
|
-
CHAIN_ID.ARBITRUM_ONE |
|
|
155
|
-
CHAIN_ID.ARBITRUM_SEPOLIA,
|
|
156
|
-
rpcURL: string,
|
|
157
|
-
pimlicoAPIKey?: string
|
|
158
|
-
): chainSpecifcConstants => {
|
|
159
|
-
|
|
97
|
+
};
|
|
98
|
+
export const _getChainSpecificConstants = (chainID, rpcURL, pimlicoAPIKey) => {
|
|
160
99
|
if (chainID == CHAIN_ID.SEPOLIA) {
|
|
161
100
|
return {
|
|
162
101
|
factoryAddresses: sepoliaFactoryAddresses,
|
|
@@ -164,7 +103,7 @@ export const _getChainSpecificConstants = (
|
|
|
164
103
|
rpcURL: rpcURL,
|
|
165
104
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
166
105
|
customErrors: customErrors
|
|
167
|
-
}
|
|
106
|
+
};
|
|
168
107
|
}
|
|
169
108
|
else if (chainID == CHAIN_ID.MAINNET) {
|
|
170
109
|
return {
|
|
@@ -173,7 +112,7 @@ export const _getChainSpecificConstants = (
|
|
|
173
112
|
rpcURL: rpcURL,
|
|
174
113
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
175
114
|
customErrors: customErrors
|
|
176
|
-
}
|
|
115
|
+
};
|
|
177
116
|
}
|
|
178
117
|
else if (chainID == CHAIN_ID.OPTIMISM_MAINNET) {
|
|
179
118
|
return {
|
|
@@ -182,7 +121,7 @@ export const _getChainSpecificConstants = (
|
|
|
182
121
|
rpcURL: rpcURL,
|
|
183
122
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
184
123
|
customErrors: customErrors
|
|
185
|
-
}
|
|
124
|
+
};
|
|
186
125
|
}
|
|
187
126
|
else if (chainID == CHAIN_ID.OPTIMISM_SEPOLIA) {
|
|
188
127
|
return {
|
|
@@ -191,7 +130,7 @@ export const _getChainSpecificConstants = (
|
|
|
191
130
|
rpcURL: rpcURL,
|
|
192
131
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
193
132
|
customErrors: customErrors
|
|
194
|
-
}
|
|
133
|
+
};
|
|
195
134
|
}
|
|
196
135
|
else if (chainID == CHAIN_ID.BASE_MAINNET) {
|
|
197
136
|
return {
|
|
@@ -200,7 +139,7 @@ export const _getChainSpecificConstants = (
|
|
|
200
139
|
rpcURL: rpcURL,
|
|
201
140
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
202
141
|
customErrors: customErrors
|
|
203
|
-
}
|
|
142
|
+
};
|
|
204
143
|
}
|
|
205
144
|
else if (chainID == CHAIN_ID.BASE_SEPOLIA) {
|
|
206
145
|
return {
|
|
@@ -209,7 +148,7 @@ export const _getChainSpecificConstants = (
|
|
|
209
148
|
rpcURL: rpcURL,
|
|
210
149
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
211
150
|
customErrors: customErrors
|
|
212
|
-
}
|
|
151
|
+
};
|
|
213
152
|
}
|
|
214
153
|
else if (chainID == CHAIN_ID.ARBITRUM_ONE) {
|
|
215
154
|
return {
|
|
@@ -218,7 +157,7 @@ export const _getChainSpecificConstants = (
|
|
|
218
157
|
rpcURL: rpcURL,
|
|
219
158
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
220
159
|
customErrors: customErrors
|
|
221
|
-
}
|
|
160
|
+
};
|
|
222
161
|
}
|
|
223
162
|
else {
|
|
224
163
|
return {
|
|
@@ -227,6 +166,6 @@ export const _getChainSpecificConstants = (
|
|
|
227
166
|
rpcURL: rpcURL,
|
|
228
167
|
pimlicoRpcURL: pimlicoAPIKey ? `https://api.pimlico.io/v2/${chainID}/rpc?apikey=${pimlicoAPIKey}` : "",
|
|
229
168
|
customErrors: customErrors
|
|
230
|
-
}
|
|
169
|
+
};
|
|
231
170
|
}
|
|
232
|
-
}
|
|
171
|
+
};
|