passkey-kit 0.7.2 → 0.7.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/cheatsheet CHANGED
@@ -13,7 +13,7 @@ stellar contract deploy --wasm target/wasm32-unknown-unknown/release/sample_poli
13
13
 
14
14
  export JWT=???
15
15
  mercury-cli --jwt $JWT --local false --mainnet false deploy
16
- mercury-cli --jwt $JWT --local false --mainnet false catchup --project-name "smart-wallets-data-multi-signer-multi-sig" --contracts "CDONKSPO6DUH46JRRIAK4O5ZINA5C2RXHP57BMFHKVBGOQXAT3IW6QCO"
16
+ mercury-cli --jwt $JWT --local false --mainnet false catchup --project-name "smart-wallets-data-multi-signer-multi-sig" --contracts "CBMMJ55OQSFSYASVENVHW55QNA4Q52GE42P23E4V7O37GKMETKOFFENA"
17
17
  curl -X GET https://api.mercurydata.app/catchups/4
18
18
  curl -X POST https://api.mercurydata.app/zephyr/execute -H "Authorization: Bearer $MERCURY_JWT" -H 'Content-Type: application/json' -d '{"mode":{"Function": {"fname": "get_signers_by_address", "arguments": "{\"address\": \"CA4G3X75IGGNXNLXFIVFNYIGC6YAVLA7KSIFFDBSR7RQ7KEZMZWLXQBH\"}"}}}'
19
19
  curl -X POST https://api.mercurydata.app/zephyr/execute -H "Authorization: Bearer $MERCURY_JWT" -H 'Content-Type: application/json' -d '{"mode":{"Function": {"fname": "get_address_by_signer", "arguments": "{\"id\": [78,127,30,69,248,174,95,168,47,59,161,168,51,120,117,135,112,133,232,92]}"}}}'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "passkey-kit",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "A helper library for creating and using passkey accounts on the Stellar blockchain.",
5
5
  "author": "Tyler van der Hoeven",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PasskeyServer } from "./server"
2
- import { PasskeyKit, DEFAULT_LTL } from "./kit"
2
+ import { PasskeyKit } from "./kit"
3
3
  import { SACClient } from "./sac"
4
4
 
5
- export { PasskeyServer, PasskeyKit, SACClient, DEFAULT_LTL }
5
+ export { PasskeyServer, PasskeyKit, SACClient }
package/src/kit.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  import { Client as PasskeyClient, type Signature, type SignerKey } from 'passkey-kit-sdk'
2
2
  import { Client as FactoryClient } from 'passkey-factory-sdk'
3
- import { Address, StrKey, hash, xdr, Transaction, SorobanRpc, Operation, TransactionBuilder, Keypair } from '@stellar/stellar-sdk'
3
+ import { Address, StrKey, hash, xdr, SorobanRpc, Keypair, Transaction } from '@stellar/stellar-sdk'
4
4
  import base64url from 'base64url'
5
5
  import { startRegistration, startAuthentication } from "@simplewebauthn/browser"
6
6
  import type { AuthenticatorAttestationResponseJSON, AuthenticatorSelectionCriteria } from "@simplewebauthn/types"
7
7
  import { Buffer } from 'buffer'
8
8
  import { PasskeyBase } from './base'
9
- import { DEFAULT_TIMEOUT } from '@stellar/stellar-sdk/contract'
10
-
11
- export const DEFAULT_LTL = 12
9
+ import { DEFAULT_TIMEOUT, type Tx } from '@stellar/stellar-sdk/contract'
12
10
 
13
11
  export class PasskeyKit extends PasskeyBase {
14
12
  declare public rpc: SorobanRpc.Server
@@ -77,7 +75,7 @@ export class PasskeyKit extends PasskeyBase {
77
75
  return {
78
76
  keyId,
79
77
  contractId,
80
- xdr: built.toXDR()
78
+ built
81
79
  }
82
80
  }
83
81
 
@@ -195,20 +193,28 @@ export class PasskeyKit extends PasskeyBase {
195
193
  if (keyId && keypair)
196
194
  throw new Error('Provide either `options.keyId` or `options.keypair` but not both')
197
195
 
196
+ const credentials = entry.credentials().address();
197
+
198
198
  if (!validUntilLedgerSeq) {
199
- const lastLedger = await this.rpc.getLatestLedger().then(({ sequence }) => sequence)
200
- validUntilLedgerSeq = lastLedger + DEFAULT_TIMEOUT / 5;
199
+ validUntilLedgerSeq = credentials.signatureExpirationLedger()
200
+
201
+ if (!validUntilLedgerSeq) {
202
+ const lastLedger = await this.rpc.getLatestLedger().then(({ sequence }) => sequence)
203
+ validUntilLedgerSeq = lastLedger + DEFAULT_TIMEOUT / 5;
204
+ }
201
205
  }
202
206
 
203
- const credentials = entry.credentials().address();
207
+ credentials.signatureExpirationLedger(validUntilLedgerSeq)
208
+
204
209
  const preimage = xdr.HashIdPreimage.envelopeTypeSorobanAuthorization(
205
210
  new xdr.HashIdPreimageSorobanAuthorization({
206
211
  networkId: hash(Buffer.from(this.networkPassphrase)),
207
212
  nonce: credentials.nonce(),
208
- signatureExpirationLedger: validUntilLedgerSeq,
213
+ signatureExpirationLedger: credentials.signatureExpirationLedger(),
209
214
  invocation: entry.rootInvocation()
210
215
  })
211
216
  )
217
+
212
218
  const payload = hash(preimage.toXDR())
213
219
 
214
220
  let key: SignerKey
@@ -295,15 +301,16 @@ export class PasskeyKit extends PasskeyBase {
295
301
  credentials.signature(xdr.ScVal.scvMap([scEntry]))
296
302
  break;
297
303
  case 'scvMap':
304
+ // Add the new signature to the existing map
298
305
  credentials.signature().map()?.push(scEntry)
306
+ // Order the map by key
307
+ credentials.signature().map()?.sort((a, b) =>
308
+ a.key().toXDR().compare(b.key().toXDR())
309
+ )
299
310
  break;
300
311
  default:
301
312
  throw new Error('Unsupported signature')
302
313
  }
303
-
304
- credentials.signatureExpirationLedger(validUntilLedgerSeq)
305
-
306
- return entry
307
314
  }
308
315
 
309
316
  public async signAuthEntries(
@@ -315,6 +322,8 @@ export class PasskeyKit extends PasskeyBase {
315
322
  validUntilLedgerSeq?: number
316
323
  }
317
324
  ) {
325
+ // TODO should there be more control over which auth entries are signed? Especially given we support multiple signers now?
326
+ // As-is .sign() will always sign every smart wallet auth entry. This may be okay but likely we should have more control over which auth entry the signer is signing
318
327
  for (const auth of entries) {
319
328
  if (
320
329
  auth.credentials().switch().name === 'sorobanCredentialsAddress'
@@ -325,12 +334,10 @@ export class PasskeyKit extends PasskeyBase {
325
334
  await this.signAuthEntry(auth, options)
326
335
  }
327
336
  }
328
-
329
- return entries
330
337
  }
331
338
 
332
339
  public async sign(
333
- txn: Transaction | string,
340
+ txn: Transaction,
334
341
  options?: {
335
342
  rpId?: string,
336
343
  keyId?: 'any' | string | Uint8Array
@@ -338,41 +345,29 @@ export class PasskeyKit extends PasskeyBase {
338
345
  validUntilLedgerSeq?: number
339
346
  }
340
347
  ) {
341
- txn = this.getTxn(txn)
342
-
343
- // Only need to sign auth for `invokeHostFunction` operations
344
- if (txn.operations[0].type === 'invokeHostFunction') {
345
- const entries = txn.operations[0].auth
348
+ const entries = this.getAuthEntries(txn)
346
349
 
347
- if (entries)
348
- await this.signAuthEntries(entries, options)
349
- }
350
-
351
- return txn.toXDR()
350
+ if (entries)
351
+ await this.signAuthEntries(entries, options)
352
352
  }
353
353
 
354
354
  public async attachPolicy(
355
- txn: Transaction | string,
355
+ txn: Transaction,
356
356
  index: number,
357
357
  policy: string
358
358
  ) {
359
- txn = this.getTxn(txn)
360
-
361
- // Only need to sign auth for `invokeHostFunction` operations
362
- if (txn.operations[0].type !== 'invokeHostFunction')
363
- return txn.toXDR()
364
-
365
359
  if (!this.wallet)
366
360
  throw new Error('Wallet not connected')
367
361
 
368
- let context_arg: xdr.ScVal
369
-
370
- const auth = txn.operations[0].auth?.[index]
362
+ const entries = this.getAuthEntries(txn)
363
+ const auth = entries?.[index]
371
364
  const context = auth?.rootInvocation().function()
372
365
 
373
- if (!auth || !context)
366
+ if (!entries || !auth || !context)
374
367
  throw new Error('No context found')
375
368
 
369
+ let context_arg: xdr.ScVal
370
+
376
371
  switch (context.switch().name) {
377
372
  case 'sorobanAuthorizedFunctionTypeContractFn':
378
373
  switch (context.contractFn().contractAddress().switch().name) {
@@ -453,19 +448,14 @@ export class PasskeyKit extends PasskeyBase {
453
448
  rootInvocation: __check_auth_invocation,
454
449
  });
455
450
 
456
- txn.operations[0].auth?.push(__check_auth)
457
-
458
- return txn.toXDR()
451
+ entries.push(__check_auth)
459
452
  }
460
453
 
461
- private getTxn(txn: Transaction | string): Transaction {
462
- txn = TransactionBuilder.cloneFrom(new Transaction(
463
- typeof txn === 'string'
464
- ? txn
465
- : txn.toXDR(),
466
- this.networkPassphrase
467
- ), { fee: '0' }).build()
454
+ public prepareTransaction(txn: Tx) {
455
+ return new Transaction(txn.toXDR(), this.networkPassphrase);
456
+ }
468
457
 
458
+ private getAuthEntries(txn: Transaction) {
469
459
  if (txn.operations.length !== 1)
470
460
  throw new Error('Must include only one Soroban operation')
471
461
 
@@ -477,7 +467,13 @@ export class PasskeyKit extends PasskeyBase {
477
467
  ) throw new Error('Must include only one operation of type `invokeHostFunction` or `extendFootprintTtl` or `restoreFootprint`')
478
468
  }
479
469
 
480
- return txn
470
+ // Only need to sign auth for `invokeHostFunction` operations
471
+ if (txn.operations[0].type === 'invokeHostFunction') {
472
+ const entries = txn.operations[0].auth
473
+
474
+ if (entries && entries.length)
475
+ return entries
476
+ }
481
477
  }
482
478
 
483
479
  /* LATER
package/src/server.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SorobanRpc, xdr } from "@stellar/stellar-sdk"
1
+ import { SorobanRpc, Transaction, xdr } from "@stellar/stellar-sdk"
2
2
  import { PasskeyBase } from "./base"
3
3
  import base64url from "base64url"
4
4
 
@@ -123,13 +123,13 @@ export class PasskeyServer extends PasskeyBase {
123
123
  - Add a method for getting a paginated or filtered list of all a wallet's events
124
124
  */
125
125
 
126
- public async send(xdr: string, fee?: number) {
126
+ public async send(txn: Transaction, fee?: number) {
127
127
  if (!this.launchtubeUrl || !this.launchtubeJwt)
128
128
  throw new Error('Launchtube service not configured')
129
129
 
130
130
  const data = new FormData();
131
131
 
132
- data.set('xdr', xdr);
132
+ data.set('xdr', txn.toXDR());
133
133
 
134
134
  if (fee)
135
135
  data.set('fee', fee.toString());
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { PasskeyServer } from "./server";
2
- import { PasskeyKit, DEFAULT_LTL } from "./kit";
2
+ import { PasskeyKit } from "./kit";
3
3
  import { SACClient } from "./sac";
4
- export { PasskeyServer, PasskeyKit, SACClient, DEFAULT_LTL };
4
+ export { PasskeyServer, PasskeyKit, SACClient };
package/types/kit.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { Client as PasskeyClient } from 'passkey-kit-sdk';
2
2
  import { Client as FactoryClient } from 'passkey-factory-sdk';
3
- import { xdr, Transaction, SorobanRpc, Keypair } from '@stellar/stellar-sdk';
3
+ import { xdr, SorobanRpc, Keypair, Transaction } from '@stellar/stellar-sdk';
4
4
  import { startRegistration, startAuthentication } from "@simplewebauthn/browser";
5
5
  import type { AuthenticatorSelectionCriteria } from "@simplewebauthn/types";
6
6
  import { Buffer } from 'buffer';
7
7
  import { PasskeyBase } from './base';
8
- export declare const DEFAULT_LTL = 12;
8
+ import { type Tx } from '@stellar/stellar-sdk/contract';
9
9
  export declare class PasskeyKit extends PasskeyBase {
10
10
  rpc: SorobanRpc.Server;
11
11
  rpcUrl: string;
@@ -29,7 +29,7 @@ export declare class PasskeyKit extends PasskeyBase {
29
29
  createWallet(app: string, user: string): Promise<{
30
30
  keyId: Buffer;
31
31
  contractId: string;
32
- xdr: string;
32
+ built: Tx;
33
33
  }>;
34
34
  createKey(app: string, user: string, settings?: {
35
35
  rpId?: string;
@@ -51,21 +51,22 @@ export declare class PasskeyKit extends PasskeyBase {
51
51
  keyId?: 'any' | string | Uint8Array;
52
52
  keypair?: Keypair;
53
53
  validUntilLedgerSeq?: number;
54
- }): Promise<xdr.SorobanAuthorizationEntry>;
54
+ }): Promise<void>;
55
55
  signAuthEntries(entries: xdr.SorobanAuthorizationEntry[], options?: {
56
56
  rpId?: string;
57
57
  keyId?: 'any' | string | Uint8Array;
58
58
  keypair?: Keypair;
59
59
  validUntilLedgerSeq?: number;
60
- }): Promise<xdr.SorobanAuthorizationEntry[]>;
61
- sign(txn: Transaction | string, options?: {
60
+ }): Promise<void>;
61
+ sign(txn: Transaction, options?: {
62
62
  rpId?: string;
63
63
  keyId?: 'any' | string | Uint8Array;
64
64
  keypair?: Keypair;
65
65
  validUntilLedgerSeq?: number;
66
- }): Promise<string>;
67
- attachPolicy(txn: Transaction | string, index: number, policy: string): Promise<string>;
68
- private getTxn;
66
+ }): Promise<void>;
67
+ attachPolicy(txn: Transaction, index: number, policy: string): Promise<void>;
68
+ prepareTransaction(txn: Tx): Transaction<import("@stellar/stellar-sdk").Memo<import("@stellar/stellar-sdk").MemoType>, import("@stellar/stellar-sdk").Operation[]>;
69
+ private getAuthEntries;
69
70
  private getPublicKey;
70
71
  private compactSignature;
71
72
  }
package/types/server.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Transaction } from "@stellar/stellar-sdk";
1
2
  import { PasskeyBase } from "./base";
2
3
  export declare class PasskeyServer extends PasskeyBase {
3
4
  launchtubeUrl: string | undefined;
@@ -19,5 +20,5 @@ export declare class PasskeyServer extends PasskeyBase {
19
20
  expired?: boolean;
20
21
  }[]>;
21
22
  getContractId(keyId: string): Promise<any>;
22
- send(xdr: string, fee?: number): Promise<any>;
23
+ send(txn: Transaction, fee?: number): Promise<any>;
23
24
  }