kokio-sdk 0.0.2 → 0.0.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/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -14,6 +14,7 @@ export class Kokio {
|
|
|
14
14
|
viemWalletClient: WalletClient;
|
|
15
15
|
turnkeyClient: TurnkeyClient;
|
|
16
16
|
organizationId: string;
|
|
17
|
+
gasPolicyId: string;
|
|
17
18
|
|
|
18
19
|
constants: ConstantsSubPackage;
|
|
19
20
|
|
|
@@ -29,6 +30,7 @@ export class Kokio {
|
|
|
29
30
|
viemWalletClient: WalletClient,
|
|
30
31
|
turnkeyClient: TurnkeyClient,
|
|
31
32
|
organizationId: string,
|
|
33
|
+
gasPolicyId: string,
|
|
32
34
|
smartAccountClient?: SmartAccountClient,
|
|
33
35
|
deviceWalletAddress?: Address,
|
|
34
36
|
eSIMWalletAddress?: Address
|
|
@@ -36,10 +38,11 @@ export class Kokio {
|
|
|
36
38
|
this.viemWalletClient = viemWalletClient;
|
|
37
39
|
this.turnkeyClient = turnkeyClient;
|
|
38
40
|
this.organizationId = organizationId;
|
|
41
|
+
this.gasPolicyId = gasPolicyId;
|
|
39
42
|
|
|
40
43
|
this.constants = new ConstantsSubPackage(this.viemWalletClient);
|
|
41
44
|
|
|
42
|
-
this.smartAccount = new SmartAccountSubPackage(this.viemWalletClient, this.turnkeyClient, this.organizationId);
|
|
45
|
+
this.smartAccount = new SmartAccountSubPackage(this.viemWalletClient, this.turnkeyClient, this.organizationId, this.gasPolicyId);
|
|
43
46
|
this.deviceWalletFactory = smartAccountClient? new DeviceWalletFactorySubPackage(viemWalletClient, smartAccountClient): undefined;
|
|
44
47
|
this.eSIMWalletFactory = smartAccountClient? new ESIMWalletFactorySubPackage(viemWalletClient, smartAccountClient): undefined;
|
|
45
48
|
this.lazyWalletRegistry = smartAccountClient? new LazyWalletRegistrySubPackage(smartAccountClient): undefined;
|
|
@@ -9,11 +9,13 @@ export class SmartAccountSubPackage {
|
|
|
9
9
|
client;
|
|
10
10
|
turnkeyClient;
|
|
11
11
|
organizationId;
|
|
12
|
+
gasPolicyId;
|
|
12
13
|
|
|
13
|
-
constructor(client: WalletClient, turnkeyClient: TurnkeyClient, organiationId: string) {
|
|
14
|
+
constructor(client: WalletClient, turnkeyClient: TurnkeyClient, organiationId: string, gasPolicyId: string) {
|
|
14
15
|
this.client = client;
|
|
15
16
|
this.turnkeyClient = turnkeyClient;
|
|
16
17
|
this.organizationId = organiationId;
|
|
18
|
+
this.gasPolicyId = gasPolicyId;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
getSmartWallet (deviceUniqueIdentifier: string, deviceWalletOwnerKey: P256Key, salt: bigint, sender?: Address) {
|
|
@@ -21,6 +23,6 @@ export class SmartAccountSubPackage {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
getSmartWalletClient (account: SmartContractAccount) {
|
|
24
|
-
return _getSmartWalletClient(this.client, account)
|
|
26
|
+
return _getSmartWalletClient(this.client, this.gasPolicyId, account)
|
|
25
27
|
}
|
|
26
28
|
}
|
|
@@ -25,7 +25,8 @@ import { _getChainSpecificConstants, ZERO } from "../constants.js";
|
|
|
25
25
|
import { _add0x, _concatUint8Arrays, _remove0x, _shouldRemoveLeadingZero } from "../utils.js";
|
|
26
26
|
import { P256Key, WebAuthnSignature } from "../../types.js";
|
|
27
27
|
import { DeviceWallet, DeviceWalletFactory } from "../../abis/index.js";
|
|
28
|
-
import { _signMessageWithTurnkey, _signTypedDataWithTurnkey } from "../services/turnkeyClient.js";
|
|
28
|
+
import { _signMessageWithTurnkey, _signTypedDataWithTurnkey, _stampAndSignMessageWithTurnkey, _stampAndSignTypedDataWithTurnkey } from "../services/turnkeyClient.js";
|
|
29
|
+
import { alchemyGasManagerMiddleware } from "@account-kit/infra";
|
|
29
30
|
|
|
30
31
|
const _encodeExecute = async (tx: AccountOp) => {
|
|
31
32
|
|
|
@@ -139,6 +140,7 @@ const getCounterFactualAddress = async (client: WalletClient, deviceUniqueIdenti
|
|
|
139
140
|
const values = _getChainSpecificConstants(chainID, rpcURL);
|
|
140
141
|
const deviceWalletFactoryAddress = values.factoryAddresses.DEVICE_WALLET_FACTORY;
|
|
141
142
|
|
|
143
|
+
|
|
142
144
|
sender = sender? sender : values.factoryAddresses.SENDER_CREATOR;
|
|
143
145
|
const uniqueSaltBytes32 = prepareSaltForCreate2(sender, salt);
|
|
144
146
|
const initCodeHash = await getInitCodeHash(client, deviceUniqueIdentifier, deviceWalletOwnerKey);
|
|
@@ -206,7 +208,7 @@ const _encodeSignature = async (webAuthnSignature: WebAuthnSignature): Promise<H
|
|
|
206
208
|
|
|
207
209
|
const _signMessage = async (message: SignableMessage, turnkeyClient: TurnkeyClient, organiationId: string, signWith: Address): Promise<Hex> => {
|
|
208
210
|
|
|
209
|
-
const webAuthnSignature = await
|
|
211
|
+
const webAuthnSignature = await _stampAndSignMessageWithTurnkey(turnkeyClient, organiationId, signWith, message);
|
|
210
212
|
|
|
211
213
|
return _encodeSignature(webAuthnSignature);
|
|
212
214
|
}
|
|
@@ -216,7 +218,7 @@ const _signTypedData = async <
|
|
|
216
218
|
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData
|
|
217
219
|
> (typedData: TypedDataDefinition<typedData, primaryType>, turnkeyClient: TurnkeyClient, organiationId: string, signWith: Address): Promise<Hex> => {
|
|
218
220
|
|
|
219
|
-
const webAuthnSignature = await
|
|
221
|
+
const webAuthnSignature = await _stampAndSignTypedDataWithTurnkey(turnkeyClient, organiationId, signWith, typedData);
|
|
220
222
|
|
|
221
223
|
return _encodeSignature(webAuthnSignature);
|
|
222
224
|
}
|
|
@@ -227,7 +229,15 @@ const _signUserOperationHash = async (hash: Hex, turnkeyClient: TurnkeyClient, o
|
|
|
227
229
|
return _signMessage(message, turnkeyClient, organiationId, signWith);
|
|
228
230
|
}
|
|
229
231
|
|
|
230
|
-
export const _getSmartWallet = async (
|
|
232
|
+
export const _getSmartWallet = async (
|
|
233
|
+
client: WalletClient,
|
|
234
|
+
turnkeyClient: TurnkeyClient,
|
|
235
|
+
organiationId: string,
|
|
236
|
+
deviceUniqueIdentifier: string,
|
|
237
|
+
deviceWalletOwnerKey: P256Key,
|
|
238
|
+
salt: bigint,
|
|
239
|
+
sender?: Address
|
|
240
|
+
): Promise<SmartContractAccount> => {
|
|
231
241
|
|
|
232
242
|
const chainID = await client.getChainId();
|
|
233
243
|
const rpcURL = client.transport.url;
|
|
@@ -244,14 +254,14 @@ export const _getSmartWallet = async (client: WalletClient, turnkeyClient: Turnk
|
|
|
244
254
|
chain: values.chain,
|
|
245
255
|
|
|
246
256
|
// The EntryPointDef that your account is compatible with
|
|
247
|
-
|
|
257
|
+
entryPoint: getEntryPoint(values.chain, {version: "0.7.0"}),
|
|
248
258
|
|
|
249
259
|
getAccountInitCode: async (): Promise<Hex> => await _getAccountInitCode(client, deviceUniqueIdentifier, deviceWalletOwnerKey, salt),
|
|
250
260
|
|
|
251
261
|
// getAccountInitCodeHash: async (): Promise<BytesLike> => await getInitCodeHash(client, deviceUniqueIdentifier, deviceWalletOwnerKey),
|
|
252
262
|
|
|
253
263
|
// an invalid signature that doesn't cause your account to revert during validation
|
|
254
|
-
getDummySignature: async (): Promise<Hash> => "
|
|
264
|
+
getDummySignature: async (): Promise<Hash> => "0x",
|
|
255
265
|
|
|
256
266
|
// given a UO in the form of {target, data, value} should output the calldata for calling your contract's execution method
|
|
257
267
|
encodeExecute: async (uo): Promise<Hash> => _encodeExecute(uo),
|
|
@@ -272,7 +282,7 @@ export const _getSmartWallet = async (client: WalletClient, turnkeyClient: Turnk
|
|
|
272
282
|
});
|
|
273
283
|
}
|
|
274
284
|
|
|
275
|
-
export const _getSmartWalletClient = async (client: WalletClient, account: SmartContractAccount) => {
|
|
285
|
+
export const _getSmartWalletClient = async (client: WalletClient, gasPolicyId: string, account: SmartContractAccount) => {
|
|
276
286
|
|
|
277
287
|
const chainID = await client.getChainId();
|
|
278
288
|
const rpcURL = client.transport.url;
|
|
@@ -283,5 +293,6 @@ export const _getSmartWalletClient = async (client: WalletClient, account: Smart
|
|
|
283
293
|
account: account,
|
|
284
294
|
chain: values.chain,
|
|
285
295
|
transport: http(values.rpcURL),
|
|
296
|
+
...alchemyGasManagerMiddleware(gasPolicyId)
|
|
286
297
|
});
|
|
287
298
|
}
|
package/src/logic/constants.ts
CHANGED
|
@@ -44,7 +44,7 @@ export const sepoliaFactoryAddresses: Record<string, Address> = {
|
|
|
44
44
|
LAZY_WALLET_REGISTRY: '0x8a1E53b903efcc6b252CE4bD3b255202318505Ef',
|
|
45
45
|
REGISTRY: '0xCa447f5C75C57f6C59027304A5Fb5A09F0E005c9',
|
|
46
46
|
ENTRY_POINT: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
|
47
|
-
SENDER_CREATOR: '
|
|
47
|
+
SENDER_CREATOR: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
|
|
48
48
|
P256VERIFIER: '0xF04f3b3935aD461D17d4a8a78E7ea21d4a61AEb1'
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -73,8 +73,8 @@ export const optimismSepoliaFactoryAddresses: Record<string, Address> = {
|
|
|
73
73
|
ESIM_WALLET_FACTORY: '0xaD2Ba6248D0e6990a844C94ACE78F8775A68b631',
|
|
74
74
|
LAZY_WALLET_REGISTRY: '0x29b98C32D83604664fd0742b9112b0825a74849F',
|
|
75
75
|
REGISTRY: '0xaeB98F0f092fCb4a476ea3a5EB6A4B9E3D63A686',
|
|
76
|
-
ENTRY_POINT: '
|
|
77
|
-
SENDER_CREATOR: '
|
|
76
|
+
ENTRY_POINT: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
|
77
|
+
SENDER_CREATOR: '0xefc2c1444ebcc4db75e7613d20c6a62ff67a167c',
|
|
78
78
|
P256VERIFIER: '0x5349aEA97Faa6D5d6D78A8847068300a4eC9D39E'
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { assertActivityCompleted, assertNonNull, TurnkeyClient } from "@turnkey/http"
|
|
1
|
+
import { assertActivityCompleted, assertNonNull, TurnkeyClient, TActivityResponse } from "@turnkey/http"
|
|
2
2
|
import { Address, hashMessage, hashTypedData, SignableMessage, toHex, TypedData, TypedDataDefinition } from "viem";
|
|
3
|
-
import { decodeAttestationObject, decodeClientDataJSON } from "@simplewebauthn/server/helpers";
|
|
3
|
+
import { decodeAttestationObject, decodeClientDataJSON, parseAuthenticatorData } from "@simplewebauthn/server/helpers";
|
|
4
4
|
import { base64UrlToBuffer } from "../utils.js";
|
|
5
5
|
import { WebAuthnSignature } from "../../types.js";
|
|
6
6
|
|
|
@@ -78,3 +78,91 @@ export const _signTypedDataWithTurnkey = async <
|
|
|
78
78
|
s: BigInt(signature.s)
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
|
|
82
|
+
export const _stampAndSignMessageWithTurnkey = async (client: TurnkeyClient, organizationId: string, signWith: Address, message: SignableMessage): Promise<WebAuthnSignature> => {
|
|
83
|
+
|
|
84
|
+
const payload = hashMessage(message);
|
|
85
|
+
|
|
86
|
+
const signedRequest = await client.stampSignRawPayload({
|
|
87
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
88
|
+
organizationId: organizationId,
|
|
89
|
+
parameters: {
|
|
90
|
+
signWith: signWith,
|
|
91
|
+
payload: payload,
|
|
92
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
93
|
+
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
94
|
+
},
|
|
95
|
+
timestampMs: String(Date.now()), // millisecond timestamp
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!signedRequest) throw new Error('Error: Failed to get signed request')
|
|
99
|
+
|
|
100
|
+
const stampedHeaderValue = JSON.parse(signedRequest.stamp.stampHeaderValue);
|
|
101
|
+
|
|
102
|
+
const response:TActivityResponse = await client.request('/public/v1/submit/sign_raw_payload', signedRequest)
|
|
103
|
+
|
|
104
|
+
if (!response || !response.activity) throw new Error('Error: Failed to sign payload');
|
|
105
|
+
|
|
106
|
+
const activity = response.activity;
|
|
107
|
+
|
|
108
|
+
assertActivityCompleted(activity);
|
|
109
|
+
|
|
110
|
+
const authenticatorData = base64UrlToBuffer(stampedHeaderValue.authenticatorData);
|
|
111
|
+
const decodedClientDataJson = decodeClientDataJSON(stampedHeaderValue.clientDataJson);
|
|
112
|
+
|
|
113
|
+
const signature = assertNonNull(activity.result.signRawPayloadResult);
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
authenticatorData: toHex(authenticatorData),
|
|
117
|
+
clientDataJSON: JSON.stringify(decodedClientDataJson),
|
|
118
|
+
challengeIndex: BigInt(23),
|
|
119
|
+
typeIndex: BigInt(1),
|
|
120
|
+
r: BigInt(signature.r),
|
|
121
|
+
s: BigInt(signature.s)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const _stampAndSignTypedDataWithTurnkey = async <
|
|
126
|
+
const typedData extends TypedData | Record<string, unknown>,
|
|
127
|
+
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData
|
|
128
|
+
> (client: TurnkeyClient, organizationId: string, signWith: Address, typedData: TypedDataDefinition<typedData, primaryType>): Promise<WebAuthnSignature> => {
|
|
129
|
+
|
|
130
|
+
const payload = hashTypedData(typedData);
|
|
131
|
+
|
|
132
|
+
const signedRequest = await client.stampSignRawPayload({
|
|
133
|
+
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
134
|
+
organizationId: organizationId,
|
|
135
|
+
parameters: {
|
|
136
|
+
signWith: signWith,
|
|
137
|
+
payload: payload,
|
|
138
|
+
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
139
|
+
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
140
|
+
},
|
|
141
|
+
timestampMs: String(Date.now()), // millisecond timestamp
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (!signedRequest) throw new Error('Error: Failed to get signed request')
|
|
145
|
+
|
|
146
|
+
const stampedHeaderValue = JSON.parse(signedRequest.stamp.stampHeaderValue);
|
|
147
|
+
|
|
148
|
+
const response:TActivityResponse = await client.request('/public/v1/submit/sign_raw_payload', signedRequest)
|
|
149
|
+
|
|
150
|
+
if (!response || !response.activity) throw new Error('Error: Failed to sign payload');
|
|
151
|
+
|
|
152
|
+
const activity = response.activity;
|
|
153
|
+
|
|
154
|
+
assertActivityCompleted(activity);
|
|
155
|
+
|
|
156
|
+
const authenticatorData = base64UrlToBuffer(stampedHeaderValue.authenticatorData);
|
|
157
|
+
const decodedClientDataJson = decodeClientDataJSON(stampedHeaderValue.clientDataJson);
|
|
158
|
+
const signature = assertNonNull(activity.result.signRawPayloadResult);
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
authenticatorData: toHex(authenticatorData),
|
|
162
|
+
clientDataJSON: JSON.stringify(decodedClientDataJson),
|
|
163
|
+
challengeIndex: BigInt(23),
|
|
164
|
+
typeIndex: BigInt(1),
|
|
165
|
+
r: BigInt(signature.r),
|
|
166
|
+
s: BigInt(signature.s)
|
|
167
|
+
}
|
|
168
|
+
}
|