tempo.ts 0.9.0 → 0.10.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 (55) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/ox/AuthorizationTempo.d.ts +450 -0
  3. package/dist/ox/AuthorizationTempo.d.ts.map +1 -0
  4. package/dist/ox/AuthorizationTempo.js +433 -0
  5. package/dist/ox/AuthorizationTempo.js.map +1 -0
  6. package/dist/ox/KeyAuthorization.d.ts +1 -1
  7. package/dist/ox/KeyAuthorization.d.ts.map +1 -1
  8. package/dist/ox/KeyAuthorization.js +3 -4
  9. package/dist/ox/KeyAuthorization.js.map +1 -1
  10. package/dist/ox/Transaction.d.ts +4 -3
  11. package/dist/ox/Transaction.d.ts.map +1 -1
  12. package/dist/ox/Transaction.js +7 -0
  13. package/dist/ox/Transaction.js.map +1 -1
  14. package/dist/ox/TransactionEnvelopeTempo.d.ts +3 -3
  15. package/dist/ox/TransactionEnvelopeTempo.d.ts.map +1 -1
  16. package/dist/ox/TransactionEnvelopeTempo.js +8 -4
  17. package/dist/ox/TransactionEnvelopeTempo.js.map +1 -1
  18. package/dist/ox/TransactionRequest.d.ts +6 -4
  19. package/dist/ox/TransactionRequest.d.ts.map +1 -1
  20. package/dist/ox/TransactionRequest.js +7 -1
  21. package/dist/ox/TransactionRequest.js.map +1 -1
  22. package/dist/ox/index.d.ts +1 -0
  23. package/dist/ox/index.d.ts.map +1 -1
  24. package/dist/ox/index.js +1 -0
  25. package/dist/ox/index.js.map +1 -1
  26. package/dist/viem/Chain.d.ts +8 -3
  27. package/dist/viem/Chain.d.ts.map +1 -1
  28. package/dist/viem/Chain.js +1 -0
  29. package/dist/viem/Chain.js.map +1 -1
  30. package/dist/viem/Formatters.d.ts.map +1 -1
  31. package/dist/viem/Formatters.js +0 -13
  32. package/dist/viem/Formatters.js.map +1 -1
  33. package/dist/viem/Transaction.d.ts +5 -5
  34. package/dist/viem/Transaction.d.ts.map +1 -1
  35. package/dist/viem/Transaction.js +2 -15
  36. package/dist/viem/Transaction.js.map +1 -1
  37. package/dist/wagmi/Connector.d.ts +6 -12
  38. package/dist/wagmi/Connector.d.ts.map +1 -1
  39. package/dist/wagmi/Connector.js +73 -18
  40. package/dist/wagmi/Connector.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/ox/AuthorizationTempo.test.ts +1256 -0
  43. package/src/ox/AuthorizationTempo.ts +648 -0
  44. package/src/ox/KeyAuthorization.ts +5 -7
  45. package/src/ox/Transaction.ts +14 -3
  46. package/src/ox/TransactionEnvelopeTempo.test.ts +172 -2
  47. package/src/ox/TransactionEnvelopeTempo.ts +15 -5
  48. package/src/ox/TransactionRequest.ts +19 -5
  49. package/src/ox/e2e.test.ts +80 -8
  50. package/src/ox/index.ts +1 -0
  51. package/src/viem/Chain.ts +1 -0
  52. package/src/viem/Formatters.ts +0 -13
  53. package/src/viem/Transaction.ts +8 -29
  54. package/src/viem/e2e.test.ts +14 -28
  55. package/src/wagmi/Connector.ts +104 -31
@@ -7,10 +7,8 @@ import {
7
7
  type AccessList,
8
8
  type Account,
9
9
  type Address,
10
- type AuthorizationList,
11
10
  type FeeValuesEIP1559,
12
11
  type ParseTransactionReturnType,
13
- type SignedAuthorizationList,
14
12
  type TransactionBase,
15
13
  type TransactionRequestBase,
16
14
  type TransactionSerializableBase,
@@ -29,6 +27,7 @@ import {
29
27
  type TransactionType as viem_TransactionType,
30
28
  } from 'viem'
31
29
  import type { ExactPartial, OneOf, PartialBy } from '../internal/types.js'
30
+ import type * as AuthorizationTempo from '../ox/AuthorizationTempo.js'
32
31
  import type * as KeyAuthorization from '../ox/KeyAuthorization.js'
33
32
  import * as SignatureEnvelope from '../ox/SignatureEnvelope.js'
34
33
  import * as TxTempo from '../ox/TransactionEnvelopeTempo.js'
@@ -46,8 +45,9 @@ export type TransactionRpc<pending extends boolean = false> = OneOf<
46
45
  | viem_RpcTransaction<pending>
47
46
  | (Omit<
48
47
  TransactionTempo<Hex.Hex, Hex.Hex, pending, '0x76'>,
49
- 'keyAuthorization' | 'signature'
48
+ 'authorizationList' | 'keyAuthorization' | 'signature'
50
49
  > & {
50
+ authorizationList?: AuthorizationTempo.ListRpc | undefined
51
51
  keyAuthorization?: KeyAuthorization.Rpc | null | undefined
52
52
  signature: SignatureEnvelope.SignatureEnvelopeRpc
53
53
  })
@@ -66,7 +66,7 @@ export type TransactionTempo<
66
66
  'r' | 's' | 'v' | 'yParity'
67
67
  > & {
68
68
  accessList: AccessList
69
- authorizationList?: SignedAuthorizationList | undefined
69
+ authorizationList?: AuthorizationTempo.ListSigned<quantity, index> | undefined
70
70
  calls: readonly TxTempo.Call<quantity>[]
71
71
  chainId: index
72
72
  feeToken?: Address | undefined
@@ -114,7 +114,6 @@ export type TransactionRequestTempo<
114
114
  > = TransactionRequestBase<quantity, index, type> &
115
115
  ExactPartial<FeeValuesEIP1559<quantity>> & {
116
116
  accessList?: AccessList | undefined
117
- authorizationList?: AuthorizationList<index, boolean> | undefined
118
117
  keyAuthorization?: KeyAuthorization.Signed<quantity, index> | undefined
119
118
  calls?: readonly TxTempo.Call<quantity>[] | undefined
120
119
  feePayer?: Account | true | undefined
@@ -134,7 +133,6 @@ export type TransactionSerializableTempo<
134
133
  > = TransactionSerializableBase<quantity, index> &
135
134
  ExactPartial<FeeValuesEIP1559<quantity>> & {
136
135
  accessList?: AccessList | undefined
137
- authorizationList?: SignedAuthorizationList | undefined
138
136
  calls: readonly TxTempo.Call<quantity>[]
139
137
  chainId: number
140
138
  feeToken?: Address | bigint | undefined
@@ -252,16 +250,11 @@ export async function serialize(
252
250
  function deserializeTempo(
253
251
  serializedTransaction: TransactionSerializedTempo,
254
252
  ): TransactionSerializableTempo {
255
- const { authorizationList, feePayerSignature, nonce, ...tx } =
256
- TxTempo.deserialize(serializedTransaction)
253
+ const { feePayerSignature, nonce, ...tx } = TxTempo.deserialize(
254
+ serializedTransaction,
255
+ )
257
256
  return {
258
257
  ...tx,
259
- authorizationList: authorizationList?.map((auth) => ({
260
- ...auth,
261
- nonce: Number(auth.nonce ?? 0n),
262
- r: Hex.fromNumber(auth.r, { size: 32 }),
263
- s: Hex.fromNumber(auth.s, { size: 32 }),
264
- })),
265
258
  nonce: Number(nonce ?? 0n),
266
259
  feePayerSignature: feePayerSignature
267
260
  ? {
@@ -293,24 +286,10 @@ async function serializeTempo(
293
286
  return undefined
294
287
  })()
295
288
 
296
- const {
297
- authorizationList,
298
- chainId,
299
- feePayer,
300
- feePayerSignature,
301
- nonce,
302
- ...rest
303
- } = transaction
289
+ const { chainId, feePayer, feePayerSignature, nonce, ...rest } = transaction
304
290
 
305
291
  const transaction_ox = {
306
292
  ...rest,
307
- authorizationList: authorizationList?.map((auth) => ({
308
- ...auth,
309
- nonce: BigInt(auth.nonce),
310
- r: BigInt(auth.r!),
311
- s: BigInt(auth.s!),
312
- yParity: Number(auth.yParity),
313
- })),
314
293
  calls: rest.calls?.length
315
294
  ? rest.calls
316
295
  : [
@@ -68,9 +68,8 @@ describe('sendTransaction', () => {
68
68
  expect(transactionIndex).toBeDefined()
69
69
  expect(transaction).toMatchInlineSnapshot(`
70
70
  {
71
- "aaAuthorizationList": [],
72
71
  "accessList": [],
73
- "authorizationList": undefined,
72
+ "authorizationList": [],
74
73
  "calls": [
75
74
  {
76
75
  "data": "0xdeadbeef",
@@ -145,9 +144,8 @@ describe('sendTransaction', () => {
145
144
  expect(transactionIndex).toBeDefined()
146
145
  expect(transaction).toMatchInlineSnapshot(`
147
146
  {
148
- "aaAuthorizationList": [],
149
147
  "accessList": [],
150
- "authorizationList": undefined,
148
+ "authorizationList": [],
151
149
  "data": undefined,
152
150
  "feePayerSignature": undefined,
153
151
  "feeToken": "0x20c0000000000000000000000000000000000001",
@@ -210,9 +208,8 @@ describe('sendTransaction', () => {
210
208
  expect(transactionIndex).toBeDefined()
211
209
  expect(transaction).toMatchInlineSnapshot(`
212
210
  {
213
- "aaAuthorizationList": [],
214
211
  "accessList": [],
215
- "authorizationList": undefined,
212
+ "authorizationList": [],
216
213
  "calls": [
217
214
  {
218
215
  "data": "0x",
@@ -325,9 +322,8 @@ describe('sendTransaction', () => {
325
322
  expect(transactionIndex).toBeDefined()
326
323
  expect(transaction).toMatchInlineSnapshot(`
327
324
  {
328
- "aaAuthorizationList": [],
329
325
  "accessList": [],
330
- "authorizationList": undefined,
326
+ "authorizationList": [],
331
327
  "calls": [
332
328
  {
333
329
  "data": "0xdeadbeef",
@@ -410,9 +406,8 @@ describe('sendTransaction', () => {
410
406
  expect(transactionIndex).toBeDefined()
411
407
  expect(transaction).toMatchInlineSnapshot(`
412
408
  {
413
- "aaAuthorizationList": [],
414
409
  "accessList": [],
415
- "authorizationList": undefined,
410
+ "authorizationList": [],
416
411
  "data": undefined,
417
412
  "feePayerSignature": undefined,
418
413
  "feeToken": "0x20c0000000000000000000000000000000000001",
@@ -478,9 +473,8 @@ describe('sendTransaction', () => {
478
473
  expect(transactionIndex).toBeDefined()
479
474
  expect(transaction).toMatchInlineSnapshot(`
480
475
  {
481
- "aaAuthorizationList": [],
482
476
  "accessList": [],
483
- "authorizationList": undefined,
477
+ "authorizationList": [],
484
478
  "calls": [
485
479
  {
486
480
  "data": "0x",
@@ -608,9 +602,8 @@ describe('sendTransaction', () => {
608
602
  expect(transactionIndex).toBeDefined()
609
603
  expect(transaction).toMatchInlineSnapshot(`
610
604
  {
611
- "aaAuthorizationList": [],
612
605
  "accessList": [],
613
- "authorizationList": undefined,
606
+ "authorizationList": [],
614
607
  "calls": [
615
608
  {
616
609
  "data": "0xdeadbeef",
@@ -814,9 +807,8 @@ describe('sendTransaction', () => {
814
807
  expect(transactionIndex).toBeDefined()
815
808
  expect(transaction).toMatchInlineSnapshot(`
816
809
  {
817
- "aaAuthorizationList": [],
818
810
  "accessList": [],
819
- "authorizationList": undefined,
811
+ "authorizationList": [],
820
812
  "calls": [
821
813
  {
822
814
  "data": "0xdeadbeef",
@@ -903,9 +895,8 @@ describe('sendTransaction', () => {
903
895
  expect(transactionIndex).toBeDefined()
904
896
  expect(transaction).toMatchInlineSnapshot(`
905
897
  {
906
- "aaAuthorizationList": [],
907
898
  "accessList": [],
908
- "authorizationList": undefined,
899
+ "authorizationList": [],
909
900
  "data": undefined,
910
901
  "feePayerSignature": undefined,
911
902
  "feeToken": "0x20c0000000000000000000000000000000000001",
@@ -975,9 +966,8 @@ describe('sendTransaction', () => {
975
966
  expect(transactionIndex).toBeDefined()
976
967
  expect(transaction).toMatchInlineSnapshot(`
977
968
  {
978
- "aaAuthorizationList": [],
979
969
  "accessList": [],
980
- "authorizationList": undefined,
970
+ "authorizationList": [],
981
971
  "calls": [
982
972
  {
983
973
  "data": "0x",
@@ -1153,9 +1143,8 @@ describe('signTransaction', () => {
1153
1143
  expect(transactionIndex).toBeDefined()
1154
1144
  expect(transaction2).toMatchInlineSnapshot(`
1155
1145
  {
1156
- "aaAuthorizationList": [],
1157
1146
  "accessList": [],
1158
- "authorizationList": undefined,
1147
+ "authorizationList": [],
1159
1148
  "calls": [
1160
1149
  {
1161
1150
  "data": "0xdeadbeef",
@@ -1326,9 +1315,8 @@ describe('relay', () => {
1326
1315
  expect(transactionIndex).toBeDefined()
1327
1316
  expect(transaction).toMatchInlineSnapshot(`
1328
1317
  {
1329
- "aaAuthorizationList": [],
1330
1318
  "accessList": [],
1331
- "authorizationList": undefined,
1319
+ "authorizationList": [],
1332
1320
  "calls": [
1333
1321
  {
1334
1322
  "data": "0xe789744400000000000000000000000020c0000000000000000000000000000000000001",
@@ -1457,9 +1445,8 @@ describe('relay', () => {
1457
1445
  expect(transactionIndex).toBeDefined()
1458
1446
  expect(transaction).toMatchInlineSnapshot(`
1459
1447
  {
1460
- "aaAuthorizationList": [],
1461
1448
  "accessList": [],
1462
- "authorizationList": undefined,
1449
+ "authorizationList": [],
1463
1450
  "calls": [
1464
1451
  {
1465
1452
  "data": "0xe789744400000000000000000000000020c0000000000000000000000000000000000001",
@@ -1569,9 +1556,8 @@ describe('relay', () => {
1569
1556
  expect(transactionIndex).toBeDefined()
1570
1557
  expect(transaction).toMatchInlineSnapshot(`
1571
1558
  {
1572
- "aaAuthorizationList": [],
1573
1559
  "accessList": [],
1574
- "authorizationList": undefined,
1560
+ "authorizationList": [],
1575
1561
  "calls": [
1576
1562
  {
1577
1563
  "data": "0xe789744400000000000000000000000020c0000000000000000000000000000000000001",
@@ -209,8 +209,23 @@ export function webAuthn(options: webAuthn.Parameters) {
209
209
  let account: Account.RootAccount | undefined
210
210
  let accessKey: Account.AccessKeyAccount | undefined
211
211
 
212
+ const defaultAccessKeyOptions = {
213
+ expiry: Math.floor(
214
+ (Date.now() + 24 * 60 * 60 * 1000) / 1000, // one day
215
+ ),
216
+ strict: false,
217
+ }
218
+ const accessKeyOptions = (() => {
219
+ if (typeof options.grantAccessKey === 'object')
220
+ return { ...defaultAccessKeyOptions, ...options.grantAccessKey }
221
+ if (options.grantAccessKey === true) return defaultAccessKeyOptions
222
+ return undefined
223
+ })()
224
+
212
225
  const idbStorage = Storage.idb<{
213
- [key: `accessKey:${string}`]: WebCryptoP256.createKeyPair.ReturnType
226
+ [key: `accessKey:${string}`]: WebCryptoP256.createKeyPair.ReturnType & {
227
+ keyAuthorization: KeyAuthorization.KeyAuthorization
228
+ }
214
229
  }>()
215
230
 
216
231
  type Properties = {
@@ -251,10 +266,18 @@ export function webAuthn(options: webAuthn.Parameters) {
251
266
  account = Account.fromWebAuthnP256(credential)
252
267
  },
253
268
  async connect(parameters = {}) {
254
- const { grantAccessKey = false } = options
255
269
  const capabilities =
256
270
  'capabilities' in parameters ? (parameters.capabilities ?? {}) : {}
257
271
 
272
+ if (
273
+ accessKeyOptions?.strict &&
274
+ accessKeyOptions.expiry &&
275
+ accessKeyOptions.expiry < Date.now() / 1000
276
+ )
277
+ throw new Error(
278
+ `\`grantAccessKey.expiry = ${accessKeyOptions.expiry}\` is in the past (${new Date(accessKeyOptions.expiry * 1000).toLocaleString()}). Please provide a valid expiry.`,
279
+ )
280
+
258
281
  // We are going to need to find:
259
282
  // - a WebAuthn `credential` to instantiate an account
260
283
  // - optionally, a `keyPair` to use as the access key for the account
@@ -286,7 +309,7 @@ export function webAuthn(options: webAuthn.Parameters) {
286
309
 
287
310
  // Get key pair (access key) to use for the account.
288
311
  const keyPair = await (async () => {
289
- if (!grantAccessKey) return undefined
312
+ if (!accessKeyOptions) return undefined
290
313
  return await WebCryptoP256.createKeyPair()
291
314
  })()
292
315
 
@@ -303,15 +326,15 @@ export function webAuthn(options: webAuthn.Parameters) {
303
326
  if (credential) {
304
327
  // Get key pair (access key) to use for the account.
305
328
  const keyPair = await (async () => {
306
- if (!grantAccessKey) return undefined
329
+ if (!accessKeyOptions) return undefined
307
330
  const address = Address.fromPublicKey(
308
331
  PublicKey.fromHex(credential.publicKey),
309
332
  )
310
333
  return await idbStorage.getItem(`accessKey:${address}`)
311
334
  })()
312
335
 
313
- // If the access key policy is lax, return the credential and key pair (if exists).
314
- if (grantAccessKey === 'lax') return { credential, keyPair }
336
+ // If the access key provisioning is not in strict mode, return the credential and key pair (if exists).
337
+ if (!accessKeyOptions?.strict) return { credential, keyPair }
315
338
 
316
339
  // If a key pair is found, return the credential and key pair.
317
340
  if (keyPair) return { credential, keyPair }
@@ -328,21 +351,25 @@ export function webAuthn(options: webAuthn.Parameters) {
328
351
  {
329
352
  // Get key pair (access key) to use for the account.
330
353
  const keyPair = await (async () => {
331
- if (!grantAccessKey) return undefined
354
+ if (!accessKeyOptions) return undefined
332
355
  return await WebCryptoP256.createKeyPair()
333
356
  })()
334
357
 
335
358
  // If we are provisioning an access key, we will need to sign a key authorization.
336
359
  // We will need the hash (digest) to sign, and the address of the access key to construct the key authorization.
337
- const { accessKeyAddress, hash } = await (async () => {
360
+ const { hash, keyAuthorization_unsigned } = await (async () => {
338
361
  if (!keyPair)
339
362
  return { accessKeyAddress: undefined, hash: undefined }
340
363
  const accessKeyAddress = Address.fromPublicKey(keyPair.publicKey)
341
- const hash = KeyAuthorization.getSignPayload({
364
+ const keyAuthorization_unsigned = KeyAuthorization.from({
365
+ ...accessKeyOptions,
342
366
  address: accessKeyAddress,
343
367
  type: 'p256',
344
368
  })
345
- return { accessKeyAddress, hash, keyPair }
369
+ const hash = KeyAuthorization.getSignPayload(
370
+ keyAuthorization_unsigned,
371
+ )
372
+ return { keyAuthorization_unsigned, hash }
346
373
  })()
347
374
 
348
375
  // If no active credential, we will attempt to load the last active credential from storage.
@@ -363,16 +390,15 @@ export function webAuthn(options: webAuthn.Parameters) {
363
390
  rpId: options.getOptions?.rpId ?? options.rpId,
364
391
  })
365
392
 
366
- const keyAuthorization = accessKeyAddress
393
+ const keyAuthorization = keyAuthorization_unsigned
367
394
  ? KeyAuthorization.from({
368
- address: accessKeyAddress,
395
+ ...keyAuthorization_unsigned,
369
396
  signature: SignatureEnvelope.from({
370
397
  metadata: credential.metadata,
371
398
  signature: credential.signature,
372
399
  publicKey: PublicKey.fromHex(credential.publicKey),
373
400
  type: 'webAuthn',
374
401
  }),
375
- type: 'p256',
376
402
  })
377
403
  : undefined
378
404
 
@@ -399,19 +425,42 @@ export function webAuthn(options: webAuthn.Parameters) {
399
425
  storage: Storage.from(config.storage as never),
400
426
  })
401
427
 
428
+ // If we are reconnecting, check if the access key is expired.
429
+ if (parameters.isReconnecting) {
430
+ if (
431
+ 'keyAuthorization' in keyPair &&
432
+ keyPair.keyAuthorization.expiry &&
433
+ keyPair.keyAuthorization.expiry < Date.now() / 1000
434
+ ) {
435
+ // remove any pending key authorizations from storage.
436
+ await account?.storage.removeItem('pendingKeyAuthorization')
437
+
438
+ const message = `Access key expired (on ${new Date(keyPair.keyAuthorization.expiry * 1000).toLocaleString()}).`
439
+ accessKey = undefined
440
+
441
+ // if in strict mode, disconnect and throw an error.
442
+ if (accessKeyOptions?.strict) {
443
+ await this.disconnect()
444
+ throw new Error(message)
445
+ }
446
+ // otherwise, fall back to the root account.
447
+ console.warn(`${message} Falling back to passkey.`)
448
+ }
449
+ }
402
450
  // If we are not reconnecting, orchestrate the provisioning of the access key.
403
- if (!parameters.isReconnecting) {
451
+ else {
404
452
  const keyAuth =
405
- keyAuthorization ?? (await account.signKeyAuthorization(accessKey))
453
+ keyAuthorization ??
454
+ (await account.signKeyAuthorization(accessKey, accessKeyOptions))
406
455
 
407
456
  await account.storage.setItem('pendingKeyAuthorization', keyAuth)
408
457
  await idbStorage.setItem(
409
458
  `accessKey:${account.address.toLowerCase()}`,
410
- keyPair,
459
+ { ...keyPair, keyAuthorization: keyAuth },
411
460
  )
412
461
  }
413
- // If we are granting an access key, throw an error if the access key is not provisioned.
414
- } else if (grantAccessKey === true) {
462
+ // If we are granting an access key and it is in strict mode, throw an error if the access key is not provisioned.
463
+ } else if (accessKeyOptions?.strict) {
415
464
  await config.storage?.removeItem('webAuthn.activeCredential')
416
465
  throw new Error('access key not found')
417
466
  }
@@ -430,6 +479,7 @@ export function webAuthn(options: webAuthn.Parameters) {
430
479
  },
431
480
  async disconnect() {
432
481
  await config.storage?.removeItem('webAuthn.activeCredential')
482
+ config.emitter.emit('disconnect')
433
483
  account = undefined
434
484
  },
435
485
  async getAccounts() {
@@ -476,8 +526,36 @@ export function webAuthn(options: webAuthn.Parameters) {
476
526
  const transport = transports[chain.id]
477
527
  if (!transport) throw new ChainNotConfiguredError()
478
528
 
529
+ const targetAccount = await (async () => {
530
+ if (!accessKey) return account
531
+
532
+ const item = await idbStorage.getItem(
533
+ `accessKey:${accessKey.address.toLowerCase()}`,
534
+ )
535
+ if (
536
+ item?.keyAuthorization.expiry &&
537
+ item.keyAuthorization.expiry < Date.now() / 1000
538
+ ) {
539
+ // remove any pending key authorizations from storage.
540
+ await account?.storage.removeItem('pendingKeyAuthorization')
541
+
542
+ const message = `Access key expired (on ${new Date(item.keyAuthorization.expiry * 1000).toLocaleString()}).`
543
+
544
+ // if in strict mode, disconnect and throw an error.
545
+ if (accessKeyOptions?.strict) {
546
+ await this.disconnect()
547
+ throw new Error(message)
548
+ }
549
+
550
+ // otherwise, fall back to the root account.
551
+ console.warn(`${message} Falling back to passkey.`)
552
+ return account
553
+ }
554
+ return accessKey
555
+ })()
556
+
479
557
  return createClient({
480
- account: accessKey ?? account,
558
+ account: targetAccount,
481
559
  chain: chain as Chain,
482
560
  transport: walletNamespaceCompat(transport),
483
561
  })
@@ -503,19 +581,14 @@ export namespace webAuthn {
503
581
  | Pick<WebAuthnP256.getCredential.Parameters, 'getFn' | 'rpId'>
504
582
  | undefined
505
583
  /**
506
- * Whether or not to grant an access key upon connection.
507
- *
508
- * - `true`: The account MUST have an access key provisioned.
509
- * On failure, the connection will fail.
510
- * - `"lax"`: The account MAY have an access key provisioned.
511
- * On failure, the connection will succeed, but the access key will not be provisioned
512
- * and must be provisioned manually if the user wants to enforce access keys.
513
- * - `false`: The account WILL NOT have an access key provisioned. The access key must be
514
- * provisioned manually if the user wants to enforce access keys.
515
- *
516
- * @default false
584
+ * Whether or not to grant an access key upon connection, and optionally, expiry + limits to assign to the key.
517
585
  */
518
- grantAccessKey?: boolean | 'lax'
586
+ grantAccessKey?:
587
+ | boolean
588
+ | (Pick<KeyAuthorization.KeyAuthorization, 'expiry' | 'limits'> & {
589
+ /** Whether or not to throw an error and disconnect if the access key is not provisioned or is expired. */
590
+ strict?: boolean | undefined
591
+ })
519
592
  /** Public key manager. */
520
593
  keyManager: KeyManager.KeyManager
521
594
  /** The RP ID to use for WebAuthn. */