@cavos/kit 0.0.3 → 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/dist/{Cavos-BH2_tOQ2.d.mts → Cavos-x9qFpOvJ.d.mts} +30 -1
- package/dist/{Cavos-BH2_tOQ2.d.ts → Cavos-x9qFpOvJ.d.ts} +30 -1
- package/dist/{chunk-BNGLH3Q3.mjs → chunk-F2J25XSL.mjs} +193 -24
- package/dist/chunk-F2J25XSL.mjs.map +1 -0
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +104 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -88
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +36 -28
- package/dist/react/index.d.ts +36 -28
- package/dist/react/index.js +549 -100
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +330 -91
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-BNGLH3Q3.mjs.map +0 -1
|
@@ -209,6 +209,8 @@ declare class SolanaAdapter {
|
|
|
209
209
|
*/
|
|
210
210
|
buildAddSignerViaPasskey(account: string, newSigner: DevicePublicKey, passkey: DevicePublicKey, leaves: Uint8Array[], leafIndex: number, assertion: PasskeyAssertion): TransactionInstruction[];
|
|
211
211
|
/** Read whether `passkey` is a registered approver. */
|
|
212
|
+
/** True if the account has at least one passkey registered as an approver. */
|
|
213
|
+
hasPasskeyApprover(account: string): Promise<boolean>;
|
|
212
214
|
isApprover(account: string, passkey: DevicePublicKey): Promise<boolean>;
|
|
213
215
|
/** Read the current passkey-approval nonce. */
|
|
214
216
|
passkeyNonce(account: string): Promise<bigint>;
|
|
@@ -413,6 +415,8 @@ declare class CavosSolana {
|
|
|
413
415
|
private readonly feePayer?;
|
|
414
416
|
/** Discriminant for the `CavosWallet` union — narrows `execute()` per chain. */
|
|
415
417
|
readonly chain: "solana";
|
|
418
|
+
/** True when this connect just created a brand-new account (first sign-up). */
|
|
419
|
+
isNewAccount: boolean;
|
|
416
420
|
private constructor();
|
|
417
421
|
get publicKey(): DevicePublicKey;
|
|
418
422
|
static connect(opts: ConnectSolanaOptions): Promise<CavosSolana>;
|
|
@@ -431,6 +435,12 @@ declare class CavosSolana {
|
|
|
431
435
|
addApprover(pubkey: DevicePublicKey): Promise<{
|
|
432
436
|
transactionHash?: string;
|
|
433
437
|
}>;
|
|
438
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
439
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
440
|
+
hasPasskey(): Promise<boolean>;
|
|
441
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
442
|
+
* Used to poll for readiness after a passkey approval before it's indexed. */
|
|
443
|
+
isReady(): Promise<boolean>;
|
|
434
444
|
/**
|
|
435
445
|
* From a fresh browser (status `needs-device-approval`), approve adding THIS
|
|
436
446
|
* device with the user's synced passkey. Gasless via the relayer — the bundle
|
|
@@ -613,6 +623,8 @@ declare class CavosStellar {
|
|
|
613
623
|
private readonly sourceKeypair?;
|
|
614
624
|
/** Discriminant for the `CavosWallet` union — narrows `execute()` per chain. */
|
|
615
625
|
readonly chain: "stellar";
|
|
626
|
+
/** True when this connect just created a brand-new account (first sign-up). */
|
|
627
|
+
isNewAccount: boolean;
|
|
616
628
|
private constructor();
|
|
617
629
|
get publicKey(): DevicePublicKey;
|
|
618
630
|
static connect(opts: ConnectStellarOptions): Promise<CavosStellar>;
|
|
@@ -631,6 +643,12 @@ declare class CavosStellar {
|
|
|
631
643
|
addApprover(pubkey: DevicePublicKey): Promise<{
|
|
632
644
|
transactionHash?: string;
|
|
633
645
|
}>;
|
|
646
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
647
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
648
|
+
hasPasskey(): Promise<boolean>;
|
|
649
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
650
|
+
* Used to poll for readiness after a passkey approval before it's indexed. */
|
|
651
|
+
isReady(): Promise<boolean>;
|
|
634
652
|
/**
|
|
635
653
|
* From a fresh browser (status `needs-device-approval`), approve adding THIS
|
|
636
654
|
* device using the user's synced passkey. Gasless via the relayer — the call
|
|
@@ -863,6 +881,9 @@ declare class Cavos {
|
|
|
863
881
|
readonly chain: "starknet";
|
|
864
882
|
/** Request id of the pending device-addition, when status is needs-device-approval. */
|
|
865
883
|
pendingRequestId: string | null;
|
|
884
|
+
/** True when this connect just created & deployed a brand-new account (first
|
|
885
|
+
* sign-up), so the UI can offer a one-time "secure your account" step. */
|
|
886
|
+
isNewAccount: boolean;
|
|
866
887
|
private constructor();
|
|
867
888
|
/**
|
|
868
889
|
* Unified entry point. Pick a `chain` and an `network` environment; the kit
|
|
@@ -906,6 +927,13 @@ declare class Cavos {
|
|
|
906
927
|
addApprover(pubkey: DevicePublicKey): Promise<{
|
|
907
928
|
transactionHash?: string;
|
|
908
929
|
}>;
|
|
930
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
931
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
932
|
+
hasPasskey(): Promise<boolean>;
|
|
933
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
934
|
+
* Cheap and side-effect free — used to poll for readiness after a passkey /
|
|
935
|
+
* device approval submits, before the new signer is indexed. */
|
|
936
|
+
isReady(): Promise<boolean>;
|
|
909
937
|
/**
|
|
910
938
|
* From a brand-new browser (status `needs-device-approval`), use the user's
|
|
911
939
|
* synced passkey to authorize adding THIS device — no trip back to an already-
|
|
@@ -988,7 +1016,8 @@ interface PasskeyApprovable {
|
|
|
988
1016
|
*/
|
|
989
1017
|
declare function approveDeviceEverywhere(wallets: PasskeyApprovable[], passkey: PasskeySigner): Promise<{
|
|
990
1018
|
chain: string;
|
|
991
|
-
transactionHash
|
|
1019
|
+
transactionHash?: string;
|
|
1020
|
+
error?: string;
|
|
992
1021
|
}[]>;
|
|
993
1022
|
|
|
994
1023
|
export { batchChallenge as $, type AuthProvider as A, type RecoverStellarOptions as B, type ChainAdapter as C, type DevicePublicKey as D, type EnrolledPasskey as E, FACTORY_CONTRACT_ID as F, type RecoveryOptions as G, SECP256R1_PROGRAM_ID as H, type Identity as I, SOLANA_NETWORKS as J, STELLAR_NETWORKS as K, SolanaAdapter as L, type SolanaAdapterOptions as M, NATIVE_SAC_ID as N, type SolanaNetwork as O, type PendingDeviceRequest as P, SolanaRelayer as Q, type RegisteredWallet as R, type StellarNetwork as S, type SolanaRelayerOptions as T, StaticIdentity as U, StellarRelayer as V, type WalletRegistry as W, type StellarRelayerOptions as X, anchorDiscriminator as Y, approveDeviceEverywhere as Z, base64urlEncode as _, type RecoveryClient as a, buildSecp256r1Instruction as a0, compressedPubkey as a1, encodeLowSSignature as a2, lowS as a3, recoverCandidatePublicKeys as a4, serializeInstructions as a5, webauthnDigest as a6, type DeviceSigner as b, type DeviceSignature as c, type ComputeAddressParams as d, type ChainCall as e, type PasskeyAssertion as f, Cavos as g, CavosSolana as h, CavosStellar as i, type CavosWallet as j, type Chain as k, type ConnectOptions as l, type ConnectSolanaOptions as m, type ConnectStatus as n, type ConnectStellarOptions as o, DEVICE_ACCOUNT_PROGRAM_ID as p, DEVICE_ACCOUNT_WASM_HASH as q, InMemoryWalletRegistry as r, type InstructionAccount as s, type InstructionData as t, type NetworkEnv as u, type PasskeyApprovable as v, type PasskeyEnrollParams as w, PasskeySigner as x, type PasskeySignerOptions as y, type RecoverSolanaOptions as z };
|
|
@@ -209,6 +209,8 @@ declare class SolanaAdapter {
|
|
|
209
209
|
*/
|
|
210
210
|
buildAddSignerViaPasskey(account: string, newSigner: DevicePublicKey, passkey: DevicePublicKey, leaves: Uint8Array[], leafIndex: number, assertion: PasskeyAssertion): TransactionInstruction[];
|
|
211
211
|
/** Read whether `passkey` is a registered approver. */
|
|
212
|
+
/** True if the account has at least one passkey registered as an approver. */
|
|
213
|
+
hasPasskeyApprover(account: string): Promise<boolean>;
|
|
212
214
|
isApprover(account: string, passkey: DevicePublicKey): Promise<boolean>;
|
|
213
215
|
/** Read the current passkey-approval nonce. */
|
|
214
216
|
passkeyNonce(account: string): Promise<bigint>;
|
|
@@ -413,6 +415,8 @@ declare class CavosSolana {
|
|
|
413
415
|
private readonly feePayer?;
|
|
414
416
|
/** Discriminant for the `CavosWallet` union — narrows `execute()` per chain. */
|
|
415
417
|
readonly chain: "solana";
|
|
418
|
+
/** True when this connect just created a brand-new account (first sign-up). */
|
|
419
|
+
isNewAccount: boolean;
|
|
416
420
|
private constructor();
|
|
417
421
|
get publicKey(): DevicePublicKey;
|
|
418
422
|
static connect(opts: ConnectSolanaOptions): Promise<CavosSolana>;
|
|
@@ -431,6 +435,12 @@ declare class CavosSolana {
|
|
|
431
435
|
addApprover(pubkey: DevicePublicKey): Promise<{
|
|
432
436
|
transactionHash?: string;
|
|
433
437
|
}>;
|
|
438
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
439
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
440
|
+
hasPasskey(): Promise<boolean>;
|
|
441
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
442
|
+
* Used to poll for readiness after a passkey approval before it's indexed. */
|
|
443
|
+
isReady(): Promise<boolean>;
|
|
434
444
|
/**
|
|
435
445
|
* From a fresh browser (status `needs-device-approval`), approve adding THIS
|
|
436
446
|
* device with the user's synced passkey. Gasless via the relayer — the bundle
|
|
@@ -613,6 +623,8 @@ declare class CavosStellar {
|
|
|
613
623
|
private readonly sourceKeypair?;
|
|
614
624
|
/** Discriminant for the `CavosWallet` union — narrows `execute()` per chain. */
|
|
615
625
|
readonly chain: "stellar";
|
|
626
|
+
/** True when this connect just created a brand-new account (first sign-up). */
|
|
627
|
+
isNewAccount: boolean;
|
|
616
628
|
private constructor();
|
|
617
629
|
get publicKey(): DevicePublicKey;
|
|
618
630
|
static connect(opts: ConnectStellarOptions): Promise<CavosStellar>;
|
|
@@ -631,6 +643,12 @@ declare class CavosStellar {
|
|
|
631
643
|
addApprover(pubkey: DevicePublicKey): Promise<{
|
|
632
644
|
transactionHash?: string;
|
|
633
645
|
}>;
|
|
646
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
647
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
648
|
+
hasPasskey(): Promise<boolean>;
|
|
649
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
650
|
+
* Used to poll for readiness after a passkey approval before it's indexed. */
|
|
651
|
+
isReady(): Promise<boolean>;
|
|
634
652
|
/**
|
|
635
653
|
* From a fresh browser (status `needs-device-approval`), approve adding THIS
|
|
636
654
|
* device using the user's synced passkey. Gasless via the relayer — the call
|
|
@@ -863,6 +881,9 @@ declare class Cavos {
|
|
|
863
881
|
readonly chain: "starknet";
|
|
864
882
|
/** Request id of the pending device-addition, when status is needs-device-approval. */
|
|
865
883
|
pendingRequestId: string | null;
|
|
884
|
+
/** True when this connect just created & deployed a brand-new account (first
|
|
885
|
+
* sign-up), so the UI can offer a one-time "secure your account" step. */
|
|
886
|
+
isNewAccount: boolean;
|
|
866
887
|
private constructor();
|
|
867
888
|
/**
|
|
868
889
|
* Unified entry point. Pick a `chain` and an `network` environment; the kit
|
|
@@ -906,6 +927,13 @@ declare class Cavos {
|
|
|
906
927
|
addApprover(pubkey: DevicePublicKey): Promise<{
|
|
907
928
|
transactionHash?: string;
|
|
908
929
|
}>;
|
|
930
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
931
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
932
|
+
hasPasskey(): Promise<boolean>;
|
|
933
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
934
|
+
* Cheap and side-effect free — used to poll for readiness after a passkey /
|
|
935
|
+
* device approval submits, before the new signer is indexed. */
|
|
936
|
+
isReady(): Promise<boolean>;
|
|
909
937
|
/**
|
|
910
938
|
* From a brand-new browser (status `needs-device-approval`), use the user's
|
|
911
939
|
* synced passkey to authorize adding THIS device — no trip back to an already-
|
|
@@ -988,7 +1016,8 @@ interface PasskeyApprovable {
|
|
|
988
1016
|
*/
|
|
989
1017
|
declare function approveDeviceEverywhere(wallets: PasskeyApprovable[], passkey: PasskeySigner): Promise<{
|
|
990
1018
|
chain: string;
|
|
991
|
-
transactionHash
|
|
1019
|
+
transactionHash?: string;
|
|
1020
|
+
error?: string;
|
|
992
1021
|
}[]>;
|
|
993
1022
|
|
|
994
1023
|
export { batchChallenge as $, type AuthProvider as A, type RecoverStellarOptions as B, type ChainAdapter as C, type DevicePublicKey as D, type EnrolledPasskey as E, FACTORY_CONTRACT_ID as F, type RecoveryOptions as G, SECP256R1_PROGRAM_ID as H, type Identity as I, SOLANA_NETWORKS as J, STELLAR_NETWORKS as K, SolanaAdapter as L, type SolanaAdapterOptions as M, NATIVE_SAC_ID as N, type SolanaNetwork as O, type PendingDeviceRequest as P, SolanaRelayer as Q, type RegisteredWallet as R, type StellarNetwork as S, type SolanaRelayerOptions as T, StaticIdentity as U, StellarRelayer as V, type WalletRegistry as W, type StellarRelayerOptions as X, anchorDiscriminator as Y, approveDeviceEverywhere as Z, base64urlEncode as _, type RecoveryClient as a, buildSecp256r1Instruction as a0, compressedPubkey as a1, encodeLowSSignature as a2, lowS as a3, recoverCandidatePublicKeys as a4, serializeInstructions as a5, webauthnDigest as a6, type DeviceSigner as b, type DeviceSignature as c, type ComputeAddressParams as d, type ChainCall as e, type PasskeyAssertion as f, Cavos as g, CavosSolana as h, CavosStellar as i, type CavosWallet as j, type Chain as k, type ConnectOptions as l, type ConnectSolanaOptions as m, type ConnectStatus as n, type ConnectStellarOptions as o, DEVICE_ACCOUNT_PROGRAM_ID as p, DEVICE_ACCOUNT_WASM_HASH as q, InMemoryWalletRegistry as r, type InstructionAccount as s, type InstructionData as t, type NetworkEnv as u, type PasskeyApprovable as v, type PasskeyEnrollParams as w, PasskeySigner as x, type PasskeySignerOptions as y, type RecoverSolanaOptions as z };
|
|
@@ -254,6 +254,17 @@ var StarknetAdapter = class {
|
|
|
254
254
|
});
|
|
255
255
|
return BigInt(res[0] ?? 0) !== 0n;
|
|
256
256
|
}
|
|
257
|
+
/** True if the account has at least one passkey registered as an approver.
|
|
258
|
+
* Lets the UI decide whether to offer passkey approval before prompting. */
|
|
259
|
+
async hasPasskeyApprover(accountAddress) {
|
|
260
|
+
if (!this.opts.provider) throw new Error("kit/starknet: provider required for reads");
|
|
261
|
+
const res = await this.opts.provider.callContract({
|
|
262
|
+
contractAddress: accountAddress,
|
|
263
|
+
entrypoint: "get_approver_count",
|
|
264
|
+
calldata: []
|
|
265
|
+
});
|
|
266
|
+
return BigInt(res[0] ?? 0) > 0n;
|
|
267
|
+
}
|
|
257
268
|
async getPasskeyNonce(accountAddress) {
|
|
258
269
|
if (!this.opts.provider) throw new Error("kit/starknet: provider required for reads");
|
|
259
270
|
const res = await this.opts.provider.callContract({
|
|
@@ -590,6 +601,11 @@ var SolanaAdapter = class {
|
|
|
590
601
|
return [precompileIx, ix];
|
|
591
602
|
}
|
|
592
603
|
/** Read whether `passkey` is a registered approver. */
|
|
604
|
+
/** True if the account has at least one passkey registered as an approver. */
|
|
605
|
+
async hasPasskeyApprover(account) {
|
|
606
|
+
const approvers = await this.fetchApprovers(new PublicKey(account));
|
|
607
|
+
return approvers.length > 0;
|
|
608
|
+
}
|
|
593
609
|
async isApprover(account, passkey) {
|
|
594
610
|
const approvers = await this.fetchApprovers(new PublicKey(account));
|
|
595
611
|
const target = Buffer.from(compressedPubkey(passkey)).toString("hex");
|
|
@@ -808,8 +824,8 @@ function u64le(n) {
|
|
|
808
824
|
new DataView(b.buffer, b.byteOffset, 8).setBigUint64(0, BigInt(n), true);
|
|
809
825
|
return b;
|
|
810
826
|
}
|
|
811
|
-
function readU64le(
|
|
812
|
-
return new DataView(
|
|
827
|
+
function readU64le(buf2, offset) {
|
|
828
|
+
return new DataView(buf2.buffer, buf2.byteOffset, buf2.length).getBigUint64(
|
|
813
829
|
offset,
|
|
814
830
|
true
|
|
815
831
|
);
|
|
@@ -1280,6 +1296,8 @@ var CavosSolana = class _CavosSolana {
|
|
|
1280
1296
|
this.feePayer = feePayer;
|
|
1281
1297
|
/** Discriminant for the `CavosWallet` union — narrows `execute()` per chain. */
|
|
1282
1298
|
this.chain = "solana";
|
|
1299
|
+
/** True when this connect just created a brand-new account (first sign-up). */
|
|
1300
|
+
this.isNewAccount = false;
|
|
1283
1301
|
}
|
|
1284
1302
|
get publicKey() {
|
|
1285
1303
|
return this.devicePubkey;
|
|
@@ -1330,7 +1348,7 @@ var CavosSolana = class _CavosSolana {
|
|
|
1330
1348
|
}
|
|
1331
1349
|
await registry.register({ userId: identity.userId, address, initialSigner: devicePubkey });
|
|
1332
1350
|
const isSigner = await adapter.isAuthorizedSigner(address, devicePubkey);
|
|
1333
|
-
|
|
1351
|
+
const wallet = new _CavosSolana(
|
|
1334
1352
|
identity,
|
|
1335
1353
|
address,
|
|
1336
1354
|
isSigner ? "ready" : "needs-device-approval",
|
|
@@ -1340,6 +1358,8 @@ var CavosSolana = class _CavosSolana {
|
|
|
1340
1358
|
relayer,
|
|
1341
1359
|
opts.feePayer
|
|
1342
1360
|
);
|
|
1361
|
+
wallet.isNewAccount = !deployed && isSigner;
|
|
1362
|
+
return wallet;
|
|
1343
1363
|
}
|
|
1344
1364
|
/** Authorize an additional device signer (device-signed via precompile). */
|
|
1345
1365
|
async addSigner(pubkey) {
|
|
@@ -1366,6 +1386,16 @@ var CavosSolana = class _CavosSolana {
|
|
|
1366
1386
|
const transactionHash = await this.send(ixs);
|
|
1367
1387
|
return { transactionHash };
|
|
1368
1388
|
}
|
|
1389
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
1390
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
1391
|
+
async hasPasskey() {
|
|
1392
|
+
return this.adapter.hasPasskeyApprover(this.address);
|
|
1393
|
+
}
|
|
1394
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
1395
|
+
* Used to poll for readiness after a passkey approval before it's indexed. */
|
|
1396
|
+
async isReady() {
|
|
1397
|
+
return this.adapter.isAuthorizedSigner(this.address, this.devicePubkey);
|
|
1398
|
+
}
|
|
1369
1399
|
/**
|
|
1370
1400
|
* From a fresh browser (status `needs-device-approval`), approve adding THIS
|
|
1371
1401
|
* device with the user's synced passkey. Gasless via the relayer — the bundle
|
|
@@ -1655,6 +1685,25 @@ var StellarAdapter = class {
|
|
|
1655
1685
|
]);
|
|
1656
1686
|
}
|
|
1657
1687
|
/** Read whether `passkey` is a registered approver (read-only simulation). */
|
|
1688
|
+
/** True if the account has at least one passkey registered as an approver.
|
|
1689
|
+
* Reads the contract's `approvers` view and checks the list is non-empty. */
|
|
1690
|
+
async hasPasskeyApprover(accountAddress, readSource) {
|
|
1691
|
+
if (!await this.isDeployed(accountAddress)) return false;
|
|
1692
|
+
const { Account: Account3, TransactionBuilder: TransactionBuilder2, BASE_FEE: BASE_FEE2 } = await import('@stellar/stellar-sdk');
|
|
1693
|
+
const src = new Account3(readSource, "0");
|
|
1694
|
+
const op = Operation.invokeHostFunction({
|
|
1695
|
+
func: invokeFunc(accountAddress, "approvers", []),
|
|
1696
|
+
auth: []
|
|
1697
|
+
});
|
|
1698
|
+
const tx2 = new TransactionBuilder2(src, { fee: BASE_FEE2, networkPassphrase: this.passphrase }).addOperation(op).setTimeout(30).build();
|
|
1699
|
+
const sim = await this.server().simulateTransaction(tx2);
|
|
1700
|
+
if (rpc.Api.isSimulationError(sim)) {
|
|
1701
|
+
throw new Error(`kit/stellar: approvers simulation failed: ${sim.error}`);
|
|
1702
|
+
}
|
|
1703
|
+
if (!sim.result?.retval) return false;
|
|
1704
|
+
const list = scValToNative(sim.result.retval);
|
|
1705
|
+
return Array.isArray(list) && list.length > 0;
|
|
1706
|
+
}
|
|
1658
1707
|
async isApprover(accountAddress, passkey, readSource) {
|
|
1659
1708
|
if (!await this.isDeployed(accountAddress)) return false;
|
|
1660
1709
|
const { Account: Account3, TransactionBuilder: TransactionBuilder2, BASE_FEE: BASE_FEE2 } = await import('@stellar/stellar-sdk');
|
|
@@ -1857,6 +1906,8 @@ var CavosStellar = class _CavosStellar {
|
|
|
1857
1906
|
this.sourceKeypair = sourceKeypair;
|
|
1858
1907
|
/** Discriminant for the `CavosWallet` union — narrows `execute()` per chain. */
|
|
1859
1908
|
this.chain = "stellar";
|
|
1909
|
+
/** True when this connect just created a brand-new account (first sign-up). */
|
|
1910
|
+
this.isNewAccount = false;
|
|
1860
1911
|
}
|
|
1861
1912
|
get publicKey() {
|
|
1862
1913
|
return this.devicePubkey;
|
|
@@ -1885,13 +1936,16 @@ var CavosStellar = class _CavosStellar {
|
|
|
1885
1936
|
return build(existing.address, isSigner2 ? "ready" : "needs-device-approval");
|
|
1886
1937
|
}
|
|
1887
1938
|
const address = adapter.computeAddress(addressSeed, devicePubkey);
|
|
1888
|
-
|
|
1939
|
+
const wasDeployed = await adapter.isDeployed(address);
|
|
1940
|
+
if (!wasDeployed) {
|
|
1889
1941
|
const func = adapter.buildDeploy(addressSeed, devicePubkey);
|
|
1890
1942
|
await self.submitHostFunction(func, void 0);
|
|
1891
1943
|
}
|
|
1892
1944
|
await registry.register({ userId: identity.userId, address, initialSigner: devicePubkey });
|
|
1893
1945
|
const isSigner = await adapter.isAuthorizedSigner(address, devicePubkey, readSource);
|
|
1894
|
-
|
|
1946
|
+
const wallet = build(address, isSigner ? "ready" : "needs-device-approval");
|
|
1947
|
+
wallet.isNewAccount = !wasDeployed && isSigner;
|
|
1948
|
+
return wallet;
|
|
1895
1949
|
}
|
|
1896
1950
|
/** Authorize an additional device signer (device-signed via `__check_auth`). */
|
|
1897
1951
|
async addSigner(pubkey) {
|
|
@@ -1919,6 +1973,18 @@ var CavosStellar = class _CavosStellar {
|
|
|
1919
1973
|
const transactionHash = await this.submitHostFunction(func, this.address);
|
|
1920
1974
|
return { transactionHash };
|
|
1921
1975
|
}
|
|
1976
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
1977
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
1978
|
+
async hasPasskey() {
|
|
1979
|
+
const readSource = await this.resolveSource();
|
|
1980
|
+
return this.adapter.hasPasskeyApprover(this.address, readSource);
|
|
1981
|
+
}
|
|
1982
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
1983
|
+
* Used to poll for readiness after a passkey approval before it's indexed. */
|
|
1984
|
+
async isReady() {
|
|
1985
|
+
const readSource = await this.resolveSource();
|
|
1986
|
+
return this.adapter.isAuthorizedSigner(this.address, this.devicePubkey, readSource);
|
|
1987
|
+
}
|
|
1922
1988
|
/**
|
|
1923
1989
|
* From a fresh browser (status `needs-device-approval`), approve adding THIS
|
|
1924
1990
|
* device using the user's synced passkey. Gasless via the relayer — the call
|
|
@@ -2226,6 +2292,9 @@ var Cavos = class _Cavos {
|
|
|
2226
2292
|
this.chain = "starknet";
|
|
2227
2293
|
/** Request id of the pending device-addition, when status is needs-device-approval. */
|
|
2228
2294
|
this.pendingRequestId = null;
|
|
2295
|
+
/** True when this connect just created & deployed a brand-new account (first
|
|
2296
|
+
* sign-up), so the UI can offer a one-time "secure your account" step. */
|
|
2297
|
+
this.isNewAccount = false;
|
|
2229
2298
|
}
|
|
2230
2299
|
/**
|
|
2231
2300
|
* Unified entry point. Pick a `chain` and an `network` environment; the kit
|
|
@@ -2321,7 +2390,7 @@ var Cavos = class _Cavos {
|
|
|
2321
2390
|
if (existing) {
|
|
2322
2391
|
const account2 = makeAccount(existing.address);
|
|
2323
2392
|
const isSigner2 = await adapter.isAuthorizedSigner(existing.address, devicePubkey);
|
|
2324
|
-
const
|
|
2393
|
+
const cavos2 = new _Cavos(
|
|
2325
2394
|
identity,
|
|
2326
2395
|
existing.address,
|
|
2327
2396
|
isSigner2 ? "ready" : "needs-device-approval",
|
|
@@ -2335,7 +2404,7 @@ var Cavos = class _Cavos {
|
|
|
2335
2404
|
const fresh = dedup && Date.now() - dedup.requestedAt < DEVICE_REQUEST_DEDUP_MS;
|
|
2336
2405
|
try {
|
|
2337
2406
|
if (fresh) {
|
|
2338
|
-
|
|
2407
|
+
cavos2.pendingRequestId = dedup.requestId;
|
|
2339
2408
|
} else {
|
|
2340
2409
|
const { requestId } = await recovery.requestDeviceAddition({
|
|
2341
2410
|
userId: identity.userId,
|
|
@@ -2343,14 +2412,14 @@ var Cavos = class _Cavos {
|
|
|
2343
2412
|
newSigner: devicePubkey,
|
|
2344
2413
|
...identity.email ? { email: identity.email } : {}
|
|
2345
2414
|
});
|
|
2346
|
-
|
|
2415
|
+
cavos2.pendingRequestId = requestId;
|
|
2347
2416
|
lastDeviceRequest.set(identity.userId, { requestId, requestedAt: Date.now() });
|
|
2348
2417
|
}
|
|
2349
2418
|
} catch (e) {
|
|
2350
2419
|
console.warn("[Cavos] requestDeviceAddition failed:", e);
|
|
2351
2420
|
}
|
|
2352
2421
|
}
|
|
2353
|
-
return
|
|
2422
|
+
return cavos2;
|
|
2354
2423
|
}
|
|
2355
2424
|
const address = adapter.computeAddress({ addressSeed, initialSigner: devicePubkey });
|
|
2356
2425
|
const account = makeAccount(address);
|
|
@@ -2381,7 +2450,7 @@ var Cavos = class _Cavos {
|
|
|
2381
2450
|
console.warn("[Cavos] isAuthorizedSigner read failed:", e);
|
|
2382
2451
|
isSigner = !alreadyDeployed;
|
|
2383
2452
|
}
|
|
2384
|
-
|
|
2453
|
+
const cavos = new _Cavos(
|
|
2385
2454
|
identity,
|
|
2386
2455
|
address,
|
|
2387
2456
|
isSigner ? "ready" : "needs-device-approval",
|
|
@@ -2390,6 +2459,8 @@ var Cavos = class _Cavos {
|
|
|
2390
2459
|
devicePubkey,
|
|
2391
2460
|
paymasterConfig
|
|
2392
2461
|
);
|
|
2462
|
+
cavos.isNewAccount = !alreadyDeployed && isSigner;
|
|
2463
|
+
return cavos;
|
|
2393
2464
|
}
|
|
2394
2465
|
/** This device's public key (e.g. to request addition to an existing wallet). */
|
|
2395
2466
|
get publicKey() {
|
|
@@ -2435,8 +2506,24 @@ var Cavos = class _Cavos {
|
|
|
2435
2506
|
const { transactionHash } = await this.execute([
|
|
2436
2507
|
this.adapter.buildAddApprover(this.address, pubkey)
|
|
2437
2508
|
]);
|
|
2509
|
+
try {
|
|
2510
|
+
await this.account.waitForTransaction(transactionHash);
|
|
2511
|
+
} catch (e) {
|
|
2512
|
+
console.warn("[Cavos] add_approver receipt wait failed:", e);
|
|
2513
|
+
}
|
|
2438
2514
|
return { transactionHash };
|
|
2439
2515
|
}
|
|
2516
|
+
/** True if this account already has a passkey enrolled as an approver, so a
|
|
2517
|
+
* new device can be approved with the passkey instead of the email flow. */
|
|
2518
|
+
async hasPasskey() {
|
|
2519
|
+
return this.adapter.hasPasskeyApprover(this.address);
|
|
2520
|
+
}
|
|
2521
|
+
/** Re-read (from chain) whether THIS device is now an authorized signer.
|
|
2522
|
+
* Cheap and side-effect free — used to poll for readiness after a passkey /
|
|
2523
|
+
* device approval submits, before the new signer is indexed. */
|
|
2524
|
+
async isReady() {
|
|
2525
|
+
return this.adapter.isAuthorizedSigner(this.address, this.devicePubkey);
|
|
2526
|
+
}
|
|
2440
2527
|
/**
|
|
2441
2528
|
* From a brand-new browser (status `needs-device-approval`), use the user's
|
|
2442
2529
|
* synced passkey to authorize adding THIS device — no trip back to an already-
|
|
@@ -2588,17 +2675,15 @@ async function approveDeviceEverywhere(wallets, passkey) {
|
|
|
2588
2675
|
const infos = await Promise.all(targets.map((w) => w.passkeyLeafForThisDevice()));
|
|
2589
2676
|
const leaves = infos.map((i) => i.leaf);
|
|
2590
2677
|
const assertion = await passkey.assert(batchChallenge(leaves));
|
|
2591
|
-
const
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
i,
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
}
|
|
2601
|
-
return out;
|
|
2678
|
+
const settled = await Promise.allSettled(
|
|
2679
|
+
targets.map((w, i) => w.submitPasskeyApproval(assertion, leaves, i, infos[i].nonce))
|
|
2680
|
+
);
|
|
2681
|
+
return settled.map(
|
|
2682
|
+
(r, i) => r.status === "fulfilled" ? { chain: targets[i].chain, transactionHash: r.value.transactionHash } : {
|
|
2683
|
+
chain: targets[i].chain,
|
|
2684
|
+
error: r.reason instanceof Error ? r.reason.message : String(r.reason)
|
|
2685
|
+
}
|
|
2686
|
+
);
|
|
2602
2687
|
}
|
|
2603
2688
|
async function paymasterExecuteDirect(paymaster, userAddress, call) {
|
|
2604
2689
|
const body = {
|
|
@@ -2771,7 +2856,91 @@ function bytesToChunks(bytes) {
|
|
|
2771
2856
|
for (const b of bytes.subarray(0, 31)) w = w << 8n | BigInt(b);
|
|
2772
2857
|
return w;
|
|
2773
2858
|
}
|
|
2859
|
+
var PasskeySigner = class {
|
|
2860
|
+
constructor(opts = {}) {
|
|
2861
|
+
if (typeof window === "undefined" || !navigator.credentials) {
|
|
2862
|
+
throw new Error("kit/passkey: WebAuthn is only available in a browser");
|
|
2863
|
+
}
|
|
2864
|
+
this.rpId = opts.rpId ?? window.location.hostname;
|
|
2865
|
+
this.rpName = opts.rpName ?? this.rpId;
|
|
2866
|
+
if (isIpAddress(this.rpId)) {
|
|
2867
|
+
throw new Error(
|
|
2868
|
+
`kit/passkey: passkeys can't use an IP address as the domain ("${this.rpId}"). Use http://localhost, a real HTTPS domain, or a tunnel (cloudflared/ngrok) \u2014 or pass an explicit \`rpId\`. (The silent device key works over an IP; passkeys don't.)`
|
|
2869
|
+
);
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
/** True if this platform advertises a usable passkey (platform authenticator). */
|
|
2873
|
+
static async isSupported() {
|
|
2874
|
+
if (typeof window === "undefined" || !window.PublicKeyCredential) return false;
|
|
2875
|
+
try {
|
|
2876
|
+
return await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
|
|
2877
|
+
} catch {
|
|
2878
|
+
return false;
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
/** Create a new synced passkey and return its P-256 public key. */
|
|
2882
|
+
async enroll(params) {
|
|
2883
|
+
const challenge = crypto.getRandomValues(new Uint8Array(32));
|
|
2884
|
+
const cred = await navigator.credentials.create({
|
|
2885
|
+
publicKey: {
|
|
2886
|
+
challenge: buf(challenge),
|
|
2887
|
+
rp: { id: this.rpId, name: this.rpName },
|
|
2888
|
+
user: {
|
|
2889
|
+
id: buf(userHandle(params.userId)),
|
|
2890
|
+
name: params.userName,
|
|
2891
|
+
displayName: params.displayName ?? params.userName
|
|
2892
|
+
},
|
|
2893
|
+
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
|
|
2894
|
+
// ES256 (P-256)
|
|
2895
|
+
authenticatorSelection: {
|
|
2896
|
+
residentKey: "required",
|
|
2897
|
+
requireResidentKey: true,
|
|
2898
|
+
userVerification: "preferred"
|
|
2899
|
+
},
|
|
2900
|
+
attestation: "none"
|
|
2901
|
+
}
|
|
2902
|
+
});
|
|
2903
|
+
if (!cred) throw new Error("kit/passkey: enrollment cancelled");
|
|
2904
|
+
const response = cred.response;
|
|
2905
|
+
const spki = new Uint8Array(response.getPublicKey());
|
|
2906
|
+
return { publicKey: spkiToPublicKey(spki), credentialId: new Uint8Array(cred.rawId) };
|
|
2907
|
+
}
|
|
2908
|
+
/**
|
|
2909
|
+
* Produce a WebAuthn assertion over `challenge` (a 32-byte value the caller
|
|
2910
|
+
* derives from the signer being added + the on-chain nonce). Uses discoverable
|
|
2911
|
+
* credentials — no `allowCredentials` — so it works on a brand-new browser.
|
|
2912
|
+
*/
|
|
2913
|
+
async assert(challenge) {
|
|
2914
|
+
const cred = await navigator.credentials.get({
|
|
2915
|
+
publicKey: {
|
|
2916
|
+
challenge: buf(challenge),
|
|
2917
|
+
rpId: this.rpId,
|
|
2918
|
+
allowCredentials: [],
|
|
2919
|
+
userVerification: "preferred"
|
|
2920
|
+
}
|
|
2921
|
+
});
|
|
2922
|
+
if (!cred) throw new Error("kit/passkey: assertion cancelled");
|
|
2923
|
+
const response = cred.response;
|
|
2924
|
+
const authenticatorData = new Uint8Array(response.authenticatorData);
|
|
2925
|
+
const clientDataJSON = new Uint8Array(response.clientDataJSON);
|
|
2926
|
+
const { r, s } = derToRs(new Uint8Array(response.signature));
|
|
2927
|
+
const challengeOffset = challengeOffsetOf(clientDataJSON, base64urlEncode(challenge));
|
|
2928
|
+
return { authenticatorData, clientDataJSON, r, s, challengeOffset };
|
|
2929
|
+
}
|
|
2930
|
+
};
|
|
2931
|
+
function isIpAddress(host) {
|
|
2932
|
+
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) return true;
|
|
2933
|
+
if (host.includes(":")) return true;
|
|
2934
|
+
return false;
|
|
2935
|
+
}
|
|
2936
|
+
function userHandle(userId) {
|
|
2937
|
+
const bytes = new TextEncoder().encode(userId);
|
|
2938
|
+
return bytes.length <= 64 ? bytes : sha256(bytes);
|
|
2939
|
+
}
|
|
2940
|
+
function buf(bytes) {
|
|
2941
|
+
return bytes.slice();
|
|
2942
|
+
}
|
|
2774
2943
|
|
|
2775
|
-
export { BackupSigner, Cavos, CavosAuth, CavosSolana, CavosStellar, DEVICE_ACCOUNT_CLASS_HASH, DEVICE_ACCOUNT_PROGRAM_ID, DEVICE_ACCOUNT_WASM_HASH, FACTORY_CONTRACT_ID, HttpRecoveryClient, HttpWalletRegistry, InMemoryWalletRegistry, NATIVE_SAC_ID, SECP256R1_PROGRAM_ID, SOLANA_NETWORKS, STARKNET_NETWORKS, STELLAR_NETWORKS, SolanaAdapter, SolanaRelayer, StarknetAdapter, StarknetDeviceSigner, StellarAdapter, StellarRelayer, UDC_ADDRESS, WebCryptoSigner, anchorDiscriminator, approveDeviceEverywhere, base64urlEncode, batchChallenge, bigIntTo32Bytes, buildSecp256r1Instruction, bytesToBigInt, bytesToHex,
|
|
2776
|
-
//# sourceMappingURL=chunk-
|
|
2777
|
-
//# sourceMappingURL=chunk-
|
|
2944
|
+
export { BackupSigner, Cavos, CavosAuth, CavosSolana, CavosStellar, DEVICE_ACCOUNT_CLASS_HASH, DEVICE_ACCOUNT_PROGRAM_ID, DEVICE_ACCOUNT_WASM_HASH, FACTORY_CONTRACT_ID, HttpRecoveryClient, HttpWalletRegistry, InMemoryWalletRegistry, NATIVE_SAC_ID, PasskeySigner, SECP256R1_PROGRAM_ID, SOLANA_NETWORKS, STARKNET_NETWORKS, STELLAR_NETWORKS, SolanaAdapter, SolanaRelayer, StarknetAdapter, StarknetDeviceSigner, StellarAdapter, StellarRelayer, UDC_ADDRESS, WebCryptoSigner, anchorDiscriminator, approveDeviceEverywhere, base64urlEncode, batchChallenge, bigIntTo32Bytes, buildSecp256r1Instruction, bytesToBigInt, bytesToHex, compressedPubkey, deriveAddressSeed, deriveAddressSeedSolana, deriveAddressSeedStellar, deriveBackupKey, deviceSignatureScVal, encodeLowSSignature, encodeLowSSignature2, generateRecoveryCode, hexToBytes, lowS, recoverCandidatePublicKeys, recoverYParity, sec1Pubkey, serializeInstructions, signatureToFelts, u256ToFelts, webauthnDigest };
|
|
2945
|
+
//# sourceMappingURL=chunk-F2J25XSL.mjs.map
|
|
2946
|
+
//# sourceMappingURL=chunk-F2J25XSL.mjs.map
|