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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kokio-sdk",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/esm/config.js",
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 _signMessageWithTurnkey(turnkeyClient, organiationId, signWith, message);
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 _signTypedDataWithTurnkey(turnkeyClient, organiationId, signWith, typedData);
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 (client: WalletClient, turnkeyClient: TurnkeyClient, organiationId: string, deviceUniqueIdentifier: string, deviceWalletOwnerKey: P256Key, salt: bigint, sender?: Address): Promise<SmartContractAccount> => {
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
- entryPoint: getEntryPoint(values.chain, {addressOverride: values.factoryAddresses.ENTRY_POINT}),
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> => "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c", //from Alchemy docs
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
  }
@@ -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: '0x9406Cc6185a346906296840746125a0E44976454',
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: '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789',
77
- SENDER_CREATOR: '0x7fc98430eaedbb6070b35b39d798725049088348',
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
+ }