@fourt/sdk 1.1.6 → 1.2.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.
- package/dist/index.cjs +268 -139
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -41
- package/dist/index.d.ts +66 -41
- package/dist/index.js +270 -141
- package/dist/index.js.map +1 -1
- package/package.json +14 -15
package/dist/index.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
// src/session/index.ts
|
|
2
2
|
import { createStore } from "zustand";
|
|
3
|
-
import {
|
|
3
|
+
import { persist, createJSONStorage } from "zustand/middleware";
|
|
4
4
|
var SessionStore = class {
|
|
5
5
|
_store;
|
|
6
|
-
/**
|
|
7
|
-
* Initializes a new instance of the `SessionStore` class by creating a new `zustand`store with the initial state.
|
|
8
|
-
*/
|
|
9
6
|
constructor() {
|
|
10
7
|
this._store = createStore()(
|
|
11
8
|
persist(this._getInitialState, {
|
|
12
|
-
name: "fourt
|
|
13
|
-
storage: createJSONStorage(() => localStorage)
|
|
9
|
+
name: "fourt-session",
|
|
10
|
+
storage: createJSONStorage(() => localStorage),
|
|
11
|
+
// keep only these keys in persisted storage
|
|
12
|
+
partialize: (state) => ({ bundle: state.bundle, type: state.type })
|
|
14
13
|
})
|
|
15
14
|
);
|
|
16
15
|
}
|
|
@@ -366,26 +365,29 @@ var UserModule = class {
|
|
|
366
365
|
this._webSignerClient = _webSignerClient;
|
|
367
366
|
}
|
|
368
367
|
/**
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
* @returns {User | undefined} user information.
|
|
368
|
+
* Retrieves information for the authenticated user.
|
|
369
|
+
* Assumes a user is already logged in, otherwise it will throw an error.
|
|
372
370
|
*/
|
|
373
|
-
|
|
374
|
-
return this._webSignerClient.
|
|
371
|
+
async getInfo() {
|
|
372
|
+
return this._webSignerClient.getUser();
|
|
375
373
|
}
|
|
376
|
-
/**
|
|
377
|
-
*
|
|
378
|
-
* @returns {string | undefined} user token.
|
|
374
|
+
/**
|
|
375
|
+
* Checks if a user is currently logged in to the fourt.io SDK.
|
|
379
376
|
*/
|
|
380
|
-
|
|
377
|
+
async isLoggedIn() {
|
|
378
|
+
return this._webSignerClient.isLoggedIn();
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Generates an access token with a lifespan of 15 minutes.
|
|
382
|
+
* Assumes a user is already logged in, otherwise it will throw an error.
|
|
383
|
+
*/
|
|
384
|
+
async getToken() {
|
|
381
385
|
return this._webSignerClient.getToken();
|
|
382
386
|
}
|
|
383
387
|
/**
|
|
384
388
|
* Logs out the user.
|
|
385
|
-
*
|
|
386
|
-
* @returns {void}
|
|
387
389
|
*/
|
|
388
|
-
logout() {
|
|
390
|
+
async logout() {
|
|
389
391
|
return this._webSignerClient.logout();
|
|
390
392
|
}
|
|
391
393
|
};
|
|
@@ -452,24 +454,28 @@ var UnauthenticatedError = class _UnauthenticatedError extends SDKError {
|
|
|
452
454
|
}
|
|
453
455
|
};
|
|
454
456
|
|
|
455
|
-
// src/types/
|
|
457
|
+
// src/types/routes.ts
|
|
456
458
|
var ROUTE_METHOD_MAP = {
|
|
457
459
|
"/v1/signup": "POST",
|
|
458
460
|
"/v1/email-auth": "POST",
|
|
459
461
|
"/v1/lookup": "POST",
|
|
460
462
|
"/v1/signin": "POST",
|
|
461
463
|
"/v1/sign": "POST",
|
|
462
|
-
"v1/oauth/init": "POST"
|
|
464
|
+
"/v1/oauth/init": "POST",
|
|
465
|
+
"/v1/refresh": "POST",
|
|
466
|
+
"/v1/logout": "POST",
|
|
467
|
+
"/v1/me": "GET"
|
|
463
468
|
};
|
|
464
469
|
|
|
465
470
|
// src/signer/index.ts
|
|
466
471
|
import { jwtDecode } from "jwt-decode";
|
|
467
|
-
import {
|
|
472
|
+
import { differenceInMilliseconds, isBefore, subMinutes } from "date-fns";
|
|
468
473
|
var SignerClient = class {
|
|
469
474
|
_turnkeyClient;
|
|
470
475
|
_configuration;
|
|
471
476
|
_sessionStore;
|
|
472
|
-
|
|
477
|
+
_refreshPromise;
|
|
478
|
+
_refreshTimer;
|
|
473
479
|
constructor({
|
|
474
480
|
stamper,
|
|
475
481
|
configuration: { apiUrl, paymasterRpcUrl, ...requiredConfiguration }
|
|
@@ -485,54 +491,97 @@ var SignerClient = class {
|
|
|
485
491
|
};
|
|
486
492
|
this._sessionStore = new SessionStore();
|
|
487
493
|
}
|
|
488
|
-
logout() {
|
|
489
|
-
this._user = void 0;
|
|
490
|
-
this.sessionStore.clearAll();
|
|
491
|
-
}
|
|
492
494
|
get configuration() {
|
|
493
495
|
return this._configuration;
|
|
494
496
|
}
|
|
495
|
-
|
|
496
|
-
if (this.
|
|
497
|
-
|
|
498
|
-
this.
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
497
|
+
async getUser() {
|
|
498
|
+
if (this._sessionStore.user) return this._sessionStore.user;
|
|
499
|
+
try {
|
|
500
|
+
const user = await this.request("/v1/me");
|
|
501
|
+
this._sessionStore.user = user;
|
|
502
|
+
return user;
|
|
503
|
+
} catch (error) {
|
|
504
|
+
if (error instanceof UnauthorizedError) {
|
|
505
|
+
try {
|
|
506
|
+
await this._refreshToken();
|
|
507
|
+
const user = await this.request("/v1/me");
|
|
508
|
+
this._sessionStore.user = user;
|
|
509
|
+
return user;
|
|
510
|
+
} catch (error2) {
|
|
511
|
+
throw error2;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
throw error;
|
|
505
515
|
}
|
|
506
|
-
if (this.sessionStore.user) this._user = this.sessionStore.user;
|
|
507
|
-
return this._user;
|
|
508
516
|
}
|
|
509
|
-
|
|
510
|
-
|
|
517
|
+
async isLoggedIn() {
|
|
518
|
+
const token = this._sessionStore.token;
|
|
519
|
+
if (token && !this._isTokenExpired(token)) return true;
|
|
520
|
+
try {
|
|
521
|
+
await this._refreshToken();
|
|
522
|
+
return !!this._sessionStore.token;
|
|
523
|
+
} catch {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
511
526
|
}
|
|
512
|
-
|
|
513
|
-
this.
|
|
527
|
+
async getToken() {
|
|
528
|
+
if (!this._sessionStore.token) {
|
|
529
|
+
try {
|
|
530
|
+
await this._refreshToken();
|
|
531
|
+
} catch {
|
|
532
|
+
throw new UnauthorizedError({
|
|
533
|
+
message: "No token found, user might not be logged in"
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
} else if (this._isTokenExpired(this._sessionStore.token)) {
|
|
537
|
+
try {
|
|
538
|
+
await this._refreshToken();
|
|
539
|
+
} catch {
|
|
540
|
+
throw new UnauthorizedError({
|
|
541
|
+
message: "Token expired and refresh failed"
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const token = this._sessionStore.token;
|
|
546
|
+
if (!token) {
|
|
547
|
+
throw new UnauthorizedError({
|
|
548
|
+
message: "No token found, user might not be logged in"
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
return token;
|
|
514
552
|
}
|
|
515
|
-
|
|
516
|
-
|
|
553
|
+
_isTokenExpired(token) {
|
|
554
|
+
try {
|
|
555
|
+
const decoded = jwtDecode(token);
|
|
556
|
+
if (decoded.exp) {
|
|
557
|
+
return decoded.exp * 1e3 <= Date.now();
|
|
558
|
+
}
|
|
559
|
+
return true;
|
|
560
|
+
} catch {
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
517
563
|
}
|
|
518
|
-
|
|
519
|
-
|
|
564
|
+
async logout() {
|
|
565
|
+
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
566
|
+
this._refreshTimer = void 0;
|
|
567
|
+
await this.request("/v1/logout");
|
|
568
|
+
this._sessionStore.clearAll();
|
|
520
569
|
}
|
|
521
570
|
async signRawMessage(msg) {
|
|
522
|
-
if (!this.
|
|
571
|
+
if (!this._sessionStore.token || !this._sessionStore.user) {
|
|
523
572
|
throw new UnauthorizedError({
|
|
524
573
|
message: "SignerClient must be authenticated to sign a message"
|
|
525
574
|
});
|
|
526
575
|
}
|
|
527
576
|
const stampedRequest = await this._turnkeyClient.stampSignRawPayload({
|
|
528
|
-
organizationId: this.
|
|
577
|
+
organizationId: this._sessionStore.user.subOrgId,
|
|
529
578
|
type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
|
|
530
579
|
timestampMs: Date.now().toString(),
|
|
531
580
|
parameters: {
|
|
532
581
|
encoding: "PAYLOAD_ENCODING_HEXADECIMAL",
|
|
533
582
|
hashFunction: "HASH_FUNCTION_NO_OP",
|
|
534
583
|
payload: msg,
|
|
535
|
-
signWith: this.
|
|
584
|
+
signWith: this._sessionStore.user.walletAddress
|
|
536
585
|
}
|
|
537
586
|
});
|
|
538
587
|
const { signature } = await this.request("/v1/sign", {
|
|
@@ -540,8 +589,11 @@ var SignerClient = class {
|
|
|
540
589
|
});
|
|
541
590
|
return signature;
|
|
542
591
|
}
|
|
543
|
-
|
|
544
|
-
|
|
592
|
+
set stamper(stamper) {
|
|
593
|
+
this._turnkeyClient.stamper = stamper;
|
|
594
|
+
}
|
|
595
|
+
get stamper() {
|
|
596
|
+
return this._turnkeyClient.stamper;
|
|
545
597
|
}
|
|
546
598
|
async lookUpUser(email) {
|
|
547
599
|
try {
|
|
@@ -561,7 +613,7 @@ var SignerClient = class {
|
|
|
561
613
|
}
|
|
562
614
|
}
|
|
563
615
|
async whoAmI(subOrgId) {
|
|
564
|
-
const orgId = subOrgId || this.
|
|
616
|
+
const orgId = subOrgId || this._sessionStore.user?.subOrgId;
|
|
565
617
|
if (!orgId) throw new BadRequestError({ message: "No orgId provided" });
|
|
566
618
|
const stampedRequest = await this._turnkeyClient.stampGetWhoami({
|
|
567
619
|
organizationId: orgId
|
|
@@ -576,19 +628,20 @@ var SignerClient = class {
|
|
|
576
628
|
return void 0;
|
|
577
629
|
}
|
|
578
630
|
})();
|
|
579
|
-
this.
|
|
631
|
+
this._sessionStore.user = {
|
|
580
632
|
...user,
|
|
581
633
|
credentialId
|
|
582
634
|
};
|
|
583
|
-
this.
|
|
584
|
-
this.
|
|
635
|
+
this._sessionStore.token = token;
|
|
636
|
+
this._scheduleRefresh(token);
|
|
585
637
|
}
|
|
586
638
|
async request(route, body) {
|
|
587
639
|
const url = new URL(`${route}`, this._configuration.apiUrl);
|
|
588
|
-
const token = this.
|
|
640
|
+
const token = this._sessionStore.token;
|
|
589
641
|
const headers = {
|
|
590
642
|
"Content-Type": "application/json",
|
|
591
|
-
"X-FOURT-KEY": this._configuration.apiKey
|
|
643
|
+
"X-FOURT-KEY": this._configuration.apiKey,
|
|
644
|
+
"X-CSRF-TOKEN": this._getCookie("csrfToken") ?? ""
|
|
592
645
|
};
|
|
593
646
|
if (token) {
|
|
594
647
|
headers["Authorization"] = `Bearer ${token}`;
|
|
@@ -603,7 +656,6 @@ var SignerClient = class {
|
|
|
603
656
|
if (error) {
|
|
604
657
|
switch (error.kind) {
|
|
605
658
|
case "UnauthorizedError": {
|
|
606
|
-
this.logout();
|
|
607
659
|
throw new UnauthorizedError({ message: error.message });
|
|
608
660
|
}
|
|
609
661
|
case "NotFoundError": {
|
|
@@ -619,11 +671,88 @@ var SignerClient = class {
|
|
|
619
671
|
}
|
|
620
672
|
return { ...data };
|
|
621
673
|
}
|
|
674
|
+
_scheduleRefresh(token) {
|
|
675
|
+
try {
|
|
676
|
+
const decoded = jwtDecode(token);
|
|
677
|
+
if (!decoded.exp) return;
|
|
678
|
+
const expiryDate = new Date(decoded.exp * 1e3);
|
|
679
|
+
const refreshDate = subMinutes(expiryDate, 2);
|
|
680
|
+
const delay = isBefore(refreshDate, /* @__PURE__ */ new Date()) ? 0 : differenceInMilliseconds(refreshDate, /* @__PURE__ */ new Date());
|
|
681
|
+
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
682
|
+
this._refreshTimer = setTimeout(() => {
|
|
683
|
+
this._refreshTimer = void 0;
|
|
684
|
+
this._refreshToken();
|
|
685
|
+
}, delay);
|
|
686
|
+
} catch {
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
async _refreshToken() {
|
|
690
|
+
if (this._refreshPromise) return this._refreshPromise;
|
|
691
|
+
this._refreshPromise = (async () => {
|
|
692
|
+
const TIMEOUT_MS = 1e4;
|
|
693
|
+
const RETRY_DELAY_MS = 5e3;
|
|
694
|
+
try {
|
|
695
|
+
const refreshPromise = this.request("/v1/refresh");
|
|
696
|
+
const data = await Promise.race([
|
|
697
|
+
refreshPromise,
|
|
698
|
+
new Promise(
|
|
699
|
+
(_, reject) => setTimeout(() => reject(new Error("Refresh timeout")), TIMEOUT_MS)
|
|
700
|
+
)
|
|
701
|
+
]);
|
|
702
|
+
if (!data || !data.token) {
|
|
703
|
+
throw new UnauthorizedError({
|
|
704
|
+
message: "Refresh did not return a token"
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
this._sessionStore.token = data.token;
|
|
708
|
+
this._scheduleRefresh(data.token);
|
|
709
|
+
} catch (error) {
|
|
710
|
+
if (error instanceof UnauthorizedError) {
|
|
711
|
+
try {
|
|
712
|
+
this._sessionStore.clearAll();
|
|
713
|
+
} catch {
|
|
714
|
+
}
|
|
715
|
+
throw error;
|
|
716
|
+
}
|
|
717
|
+
if (this._refreshTimer) clearTimeout(this._refreshTimer);
|
|
718
|
+
const MAX_RETRIES = 5;
|
|
719
|
+
let retryCount = 0;
|
|
720
|
+
this._refreshTimer = setTimeout(() => {
|
|
721
|
+
this._refreshTimer = void 0;
|
|
722
|
+
void this._refreshToken().catch(() => {
|
|
723
|
+
retryCount++;
|
|
724
|
+
if (retryCount <= MAX_RETRIES) {
|
|
725
|
+
const nextDelay = Math.min(
|
|
726
|
+
RETRY_DELAY_MS * 2 ** (retryCount - 1),
|
|
727
|
+
6e4
|
|
728
|
+
);
|
|
729
|
+
this._refreshTimer = setTimeout(() => {
|
|
730
|
+
this._refreshTimer = void 0;
|
|
731
|
+
void this._refreshToken().catch(() => {
|
|
732
|
+
});
|
|
733
|
+
}, nextDelay);
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
}, RETRY_DELAY_MS);
|
|
737
|
+
throw error;
|
|
738
|
+
} finally {
|
|
739
|
+
this._refreshPromise = void 0;
|
|
740
|
+
}
|
|
741
|
+
})();
|
|
742
|
+
return this._refreshPromise;
|
|
743
|
+
}
|
|
744
|
+
_getCookie(name) {
|
|
745
|
+
if (typeof document === "undefined") return null;
|
|
746
|
+
const match = document.cookie.match(new RegExp("(^| )" + name + "=([^;]+)"));
|
|
747
|
+
return match ? decodeURIComponent(match[2]) : null;
|
|
748
|
+
}
|
|
622
749
|
};
|
|
623
750
|
|
|
624
751
|
// src/signer/web.ts
|
|
625
752
|
var WebSignerClient = class extends SignerClient {
|
|
626
|
-
|
|
753
|
+
iframeStamper;
|
|
754
|
+
webauthnStamper;
|
|
755
|
+
iframeConfig;
|
|
627
756
|
oauthConfiguration;
|
|
628
757
|
/**
|
|
629
758
|
* Initializes a new instance of the `WebSignerClient` class.
|
|
@@ -636,54 +765,56 @@ var WebSignerClient = class extends SignerClient {
|
|
|
636
765
|
iframe,
|
|
637
766
|
oauth
|
|
638
767
|
}) {
|
|
639
|
-
const
|
|
768
|
+
const iframeConfig = {
|
|
769
|
+
iframeElementId: iframe?.iframeElementId ?? "turnkey-iframe",
|
|
770
|
+
iframeContainerId: iframe?.iframeContainerId ?? "signer-iframe-container"
|
|
771
|
+
};
|
|
640
772
|
const iframeContainer = document.createElement("div");
|
|
641
|
-
iframeContainer.id = iframeContainerId;
|
|
773
|
+
iframeContainer.id = iframeConfig.iframeContainerId;
|
|
642
774
|
iframeContainer.style.display = "none";
|
|
643
775
|
document.body.appendChild(iframeContainer);
|
|
644
|
-
const webauthnStamper = new WebauthnStamper({ rpId: webauthn.rpId });
|
|
645
776
|
const iframeStamper = new IframeStamper({
|
|
646
777
|
iframeUrl: "https://auth.turnkey.com",
|
|
647
|
-
iframeElementId:
|
|
648
|
-
iframeContainer: document.getElementById(iframeContainerId)
|
|
778
|
+
iframeElementId: iframeConfig.iframeElementId,
|
|
779
|
+
iframeContainer: document.getElementById(iframeConfig.iframeContainerId)
|
|
649
780
|
});
|
|
650
781
|
super({
|
|
651
782
|
stamper: iframeStamper,
|
|
652
783
|
// Initialized to iframeStamper; can be either webauthnStamper or iframeStamper
|
|
653
784
|
configuration
|
|
654
785
|
});
|
|
655
|
-
this.
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
};
|
|
786
|
+
this.iframeStamper = iframeStamper;
|
|
787
|
+
this.iframeConfig = iframeConfig;
|
|
788
|
+
this.webauthnStamper = new WebauthnStamper({ rpId: webauthn.rpId });
|
|
659
789
|
this.oauthConfiguration = oauth;
|
|
660
790
|
}
|
|
791
|
+
async logout() {
|
|
792
|
+
super.logout();
|
|
793
|
+
this.iframeStamper.clear();
|
|
794
|
+
const stamper = new IframeStamper({
|
|
795
|
+
iframeUrl: "https://auth.turnkey.com",
|
|
796
|
+
iframeElementId: this.iframeConfig.iframeElementId,
|
|
797
|
+
iframeContainer: document.getElementById(
|
|
798
|
+
this.iframeConfig.iframeContainerId
|
|
799
|
+
)
|
|
800
|
+
});
|
|
801
|
+
this.iframeStamper = stamper;
|
|
802
|
+
await this._initIframeStamper();
|
|
803
|
+
}
|
|
661
804
|
async signRawMessage(msg) {
|
|
662
|
-
await this.
|
|
805
|
+
await this._updateStamper();
|
|
663
806
|
return super.signRawMessage(msg);
|
|
664
807
|
}
|
|
665
|
-
async logout() {
|
|
666
|
-
this._stampers.iframe.clear();
|
|
667
|
-
await this._stampers.iframe.init();
|
|
668
|
-
return super.logout();
|
|
669
|
-
}
|
|
670
808
|
/**
|
|
671
|
-
*
|
|
809
|
+
* Get the pre-filled URL for initiating oauth with a specific provider.
|
|
672
810
|
*
|
|
811
|
+
* @param {string} provider provider for which we are getting the URL, currently google or apple
|
|
673
812
|
*/
|
|
674
|
-
async
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
} else {
|
|
680
|
-
this.stamper = this._stampers.iframe;
|
|
681
|
-
await this.completeAuthWithBundle({
|
|
682
|
-
bundle: this._sessionStore.bundle,
|
|
683
|
-
subOrgId: this.user?.subOrgId,
|
|
684
|
-
sessionType: this._sessionStore.type
|
|
685
|
-
});
|
|
686
|
-
}
|
|
813
|
+
async getOAuthInitUrl(provider) {
|
|
814
|
+
const { url } = await this.request("/v1/oauth/init", {
|
|
815
|
+
provider
|
|
816
|
+
});
|
|
817
|
+
return url;
|
|
687
818
|
}
|
|
688
819
|
/**
|
|
689
820
|
* Signs in a user with webauthn.
|
|
@@ -695,15 +826,15 @@ var WebSignerClient = class extends SignerClient {
|
|
|
695
826
|
if (!existingUserSubOrgId) {
|
|
696
827
|
await this._createAccount({ method: "webauthn", email });
|
|
697
828
|
} else {
|
|
698
|
-
this.stamper = this.
|
|
829
|
+
this.stamper = this.webauthnStamper;
|
|
699
830
|
await this.whoAmI(existingUserSubOrgId);
|
|
700
831
|
this._sessionStore.type = "passkeys" /* Passkeys */;
|
|
701
|
-
if (!this.user || !this.user.credentialId) {
|
|
832
|
+
if (!this._sessionStore.user || !this._sessionStore.user.credentialId) {
|
|
702
833
|
return;
|
|
703
834
|
}
|
|
704
|
-
this.
|
|
835
|
+
this.webauthnStamper.allowCredentials = [
|
|
705
836
|
{
|
|
706
|
-
id: LibBase64.toBuffer(this.user.credentialId),
|
|
837
|
+
id: LibBase64.toBuffer(this._sessionStore.user.credentialId),
|
|
707
838
|
type: "public-key",
|
|
708
839
|
transports: ["internal", "usb"]
|
|
709
840
|
}
|
|
@@ -726,23 +857,6 @@ var WebSignerClient = class extends SignerClient {
|
|
|
726
857
|
async getIframePublicKey() {
|
|
727
858
|
return await this._initIframeStamper();
|
|
728
859
|
}
|
|
729
|
-
/**
|
|
730
|
-
* Signs in a user with email.
|
|
731
|
-
*
|
|
732
|
-
* @param {EmailInitializeAuthParams} params params for the sign in
|
|
733
|
-
*/
|
|
734
|
-
async _signInWithEmail({
|
|
735
|
-
email,
|
|
736
|
-
expirationSeconds,
|
|
737
|
-
redirectUrl
|
|
738
|
-
}) {
|
|
739
|
-
return this.request("/v1/email-auth", {
|
|
740
|
-
email,
|
|
741
|
-
targetPublicKey: await this.getIframePublicKey(),
|
|
742
|
-
expirationSeconds,
|
|
743
|
-
redirectUrl: redirectUrl.toString()
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
860
|
/**
|
|
747
861
|
* Completes the authentication process with a credential bundle.
|
|
748
862
|
*
|
|
@@ -754,7 +868,7 @@ var WebSignerClient = class extends SignerClient {
|
|
|
754
868
|
sessionType
|
|
755
869
|
}) {
|
|
756
870
|
await this._initIframeStamper();
|
|
757
|
-
const result = await this.
|
|
871
|
+
const result = await this.iframeStamper.injectCredentialBundle(bundle);
|
|
758
872
|
if (!result) {
|
|
759
873
|
throw new Error("Failed to inject credential bundle");
|
|
760
874
|
}
|
|
@@ -762,6 +876,40 @@ var WebSignerClient = class extends SignerClient {
|
|
|
762
876
|
this._sessionStore.type = sessionType;
|
|
763
877
|
this._sessionStore.bundle = bundle;
|
|
764
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Checks for an existing session and if exists, updates the stamper accordingly.
|
|
881
|
+
*/
|
|
882
|
+
async _updateStamper() {
|
|
883
|
+
if (this._sessionStore.type === void 0 && (this._sessionStore.bundle === void 0 || this._sessionStore.token === void 0))
|
|
884
|
+
return;
|
|
885
|
+
if (this._sessionStore.type === "passkeys" /* Passkeys */) {
|
|
886
|
+
this.stamper = this.webauthnStamper;
|
|
887
|
+
} else {
|
|
888
|
+
this.stamper = this.iframeStamper;
|
|
889
|
+
await this.completeAuthWithBundle({
|
|
890
|
+
bundle: this._sessionStore.bundle,
|
|
891
|
+
subOrgId: this._sessionStore.user?.subOrgId,
|
|
892
|
+
sessionType: this._sessionStore.type
|
|
893
|
+
});
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Signs in a user with email.
|
|
898
|
+
*
|
|
899
|
+
* @param {EmailInitializeAuthParams} params params for the sign in
|
|
900
|
+
*/
|
|
901
|
+
async _signInWithEmail({
|
|
902
|
+
email,
|
|
903
|
+
expirationSeconds,
|
|
904
|
+
redirectUrl
|
|
905
|
+
}) {
|
|
906
|
+
return this.request("/v1/email-auth", {
|
|
907
|
+
email,
|
|
908
|
+
targetPublicKey: await this.getIframePublicKey(),
|
|
909
|
+
expirationSeconds,
|
|
910
|
+
redirectUrl: redirectUrl.toString()
|
|
911
|
+
});
|
|
912
|
+
}
|
|
765
913
|
/**
|
|
766
914
|
* Creates a passkey account using the webauthn stamper.
|
|
767
915
|
*
|
|
@@ -771,28 +919,20 @@ var WebSignerClient = class extends SignerClient {
|
|
|
771
919
|
const { challenge, attestation } = await this._webauthnGenerateAttestation(
|
|
772
920
|
params.email
|
|
773
921
|
);
|
|
774
|
-
const {
|
|
775
|
-
token,
|
|
776
|
-
user: { id, email, subOrgId, walletAddress, salt, smartAccountAddress }
|
|
777
|
-
} = await this.request("/v1/signup", {
|
|
922
|
+
const { token, user } = await this.request("/v1/signup", {
|
|
778
923
|
passkey: {
|
|
779
924
|
challenge: LibBase64.fromBuffer(challenge),
|
|
780
925
|
attestation
|
|
781
926
|
},
|
|
782
927
|
email: params.email
|
|
783
928
|
});
|
|
784
|
-
this.user = {
|
|
785
|
-
|
|
786
|
-
email,
|
|
787
|
-
subOrgId,
|
|
788
|
-
walletAddress,
|
|
789
|
-
salt,
|
|
790
|
-
smartAccountAddress,
|
|
929
|
+
this._sessionStore.user = {
|
|
930
|
+
...user,
|
|
791
931
|
credentialId: attestation.credentialId
|
|
792
932
|
};
|
|
793
|
-
this._sessionStore.user = this.user;
|
|
794
933
|
this._sessionStore.type = "passkeys" /* Passkeys */;
|
|
795
934
|
this._sessionStore.token = token;
|
|
935
|
+
this._scheduleRefresh(token);
|
|
796
936
|
}
|
|
797
937
|
/**
|
|
798
938
|
* Creates an email account using the iframe stamper.
|
|
@@ -863,22 +1003,11 @@ var WebSignerClient = class extends SignerClient {
|
|
|
863
1003
|
return { challenge, attestation, authenticatorUserId };
|
|
864
1004
|
}
|
|
865
1005
|
async _initIframeStamper() {
|
|
866
|
-
if (!this.
|
|
867
|
-
await this.
|
|
1006
|
+
if (!this.iframeStamper.publicKey()) {
|
|
1007
|
+
await this.iframeStamper.init();
|
|
868
1008
|
}
|
|
869
|
-
this.stamper = this.
|
|
870
|
-
return this.
|
|
871
|
-
}
|
|
872
|
-
/**
|
|
873
|
-
* Get the pre-filled URL for initiating oauth with a specific provider.
|
|
874
|
-
*
|
|
875
|
-
* @param {string} provider provider for which we are getting the URL, currently google or apple
|
|
876
|
-
*/
|
|
877
|
-
async getOAuthInitUrl(provider) {
|
|
878
|
-
const { url } = await this.request("v1/oauth/init", {
|
|
879
|
-
provider
|
|
880
|
-
});
|
|
881
|
-
return url;
|
|
1009
|
+
this.stamper = this.iframeStamper;
|
|
1010
|
+
return this.iframeStamper.publicKey();
|
|
882
1011
|
}
|
|
883
1012
|
};
|
|
884
1013
|
|
|
@@ -902,13 +1031,13 @@ var ViemModule = class {
|
|
|
902
1031
|
this._signerClient = _signerClient;
|
|
903
1032
|
}
|
|
904
1033
|
async toLocalAccount() {
|
|
905
|
-
const user = this._signerClient.
|
|
1034
|
+
const user = await this._signerClient.getUser();
|
|
906
1035
|
if (!user) {
|
|
907
1036
|
throw new UnauthenticatedError({ message: "Signer not authenticated" });
|
|
908
1037
|
}
|
|
909
1038
|
return toAccount({
|
|
910
1039
|
address: user.walletAddress,
|
|
911
|
-
signMessage: (
|
|
1040
|
+
signMessage: ({ message }) => this.signMessage(message),
|
|
912
1041
|
signTypedData: (typedDataDefinition) => this.signTypedData(typedDataDefinition),
|
|
913
1042
|
signTransaction: this.signTransaction
|
|
914
1043
|
});
|
|
@@ -917,7 +1046,7 @@ var ViemModule = class {
|
|
|
917
1046
|
client,
|
|
918
1047
|
owner
|
|
919
1048
|
}) {
|
|
920
|
-
const user = this._signerClient.
|
|
1049
|
+
const user = await this._signerClient.getUser();
|
|
921
1050
|
if (!user) {
|
|
922
1051
|
throw new UnauthenticatedError({ message: "Signer not authenticated" });
|
|
923
1052
|
}
|
|
@@ -953,7 +1082,7 @@ var ViemModule = class {
|
|
|
953
1082
|
}
|
|
954
1083
|
async signTransaction(transaction, options) {
|
|
955
1084
|
const serializeFn = options?.serializer ?? serializeTransaction;
|
|
956
|
-
const serializedTx = serializeFn(transaction);
|
|
1085
|
+
const serializedTx = await serializeFn(transaction);
|
|
957
1086
|
const signatureHex = await this._signerClient.signRawMessage(
|
|
958
1087
|
keccak256(serializedTx)
|
|
959
1088
|
);
|