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 +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -2
- package/src/kit.ts +44 -48
- package/src/server.ts +3 -3
- package/types/index.d.ts +2 -2
- package/types/kit.d.ts +10 -9
- package/types/server.d.ts +2 -1
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 "
|
|
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
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PasskeyServer } from "./server"
|
|
2
|
-
import { PasskeyKit
|
|
2
|
+
import { PasskeyKit } from "./kit"
|
|
3
3
|
import { SACClient } from "./sac"
|
|
4
4
|
|
|
5
|
-
export { PasskeyServer, PasskeyKit, SACClient
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
200
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
348
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
return txn.toXDR()
|
|
451
|
+
entries.push(__check_auth)
|
|
459
452
|
}
|
|
460
453
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
-
|
|
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(
|
|
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',
|
|
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
|
|
2
|
+
import { PasskeyKit } from "./kit";
|
|
3
3
|
import { SACClient } from "./sac";
|
|
4
|
-
export { PasskeyServer, PasskeyKit, SACClient
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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<
|
|
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<
|
|
61
|
-
sign(txn: Transaction
|
|
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<
|
|
67
|
-
attachPolicy(txn: Transaction
|
|
68
|
-
|
|
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(
|
|
23
|
+
send(txn: Transaction, fee?: number): Promise<any>;
|
|
23
24
|
}
|