@@ -46,6 +46,7 @@ import type {
46
46
SignInFutureSSOParams ,
47
47
SignInFutureTicketParams ,
48
48
SignInFutureTOTPVerifyParams ,
49
+ SignInFutureWeb3Params ,
49
50
SignInIdentifier ,
50
51
SignInJSON ,
51
52
SignInJSONSnapshot ,
@@ -871,6 +872,77 @@ class SignInFuture implements SignInFutureResource {
871
872
} ) ;
872
873
}
873
874
875
+ async web3 ( params : SignInFutureWeb3Params ) : Promise < { error : unknown } > {
876
+ const { strategy } = params ;
877
+ const provider = strategy . replace ( 'web3_' , '' ) . replace ( '_signature' , '' ) as Web3Provider ;
878
+
879
+ return runAsyncResourceTask ( this . resource , async ( ) => {
880
+ let identifier ;
881
+ let generateSignature ;
882
+ switch ( provider ) {
883
+ case 'metamask' :
884
+ identifier = await getMetamaskIdentifier ( ) ;
885
+ generateSignature = generateSignatureWithMetamask ;
886
+ break ;
887
+ case 'coinbase_wallet' :
888
+ identifier = await getCoinbaseWalletIdentifier ( ) ;
889
+ generateSignature = generateSignatureWithCoinbaseWallet ;
890
+ break ;
891
+ case 'base' :
892
+ identifier = await getBaseIdentifier ( ) ;
893
+ generateSignature = generateSignatureWithBase ;
894
+ break ;
895
+ case 'okx_wallet' :
896
+ identifier = await getOKXWalletIdentifier ( ) ;
897
+ generateSignature = generateSignatureWithOKXWallet ;
898
+ break ;
899
+ default :
900
+ throw new Error ( `Unsupported Web3 provider: ${ provider } ` ) ;
901
+ }
902
+
903
+ await this . create ( { identifier } ) ;
904
+
905
+ const web3FirstFactor = this . resource . supportedFirstFactors ?. find (
906
+ f => f . strategy === strategy ,
907
+ ) as Web3SignatureFactor ;
908
+ if ( ! web3FirstFactor ) {
909
+ throw new Error ( 'Web3 first factor not found' ) ;
910
+ }
911
+
912
+ await this . resource . __internal_basePost ( {
913
+ body : { web3WalletId : web3FirstFactor . web3WalletId , strategy } ,
914
+ action : 'prepare_first_factor' ,
915
+ } ) ;
916
+
917
+ const { message } = this . firstFactorVerification ;
918
+ if ( ! message ) {
919
+ throw new Error ( 'Web3 nonce not found' ) ;
920
+ }
921
+
922
+ let signature : string ;
923
+ try {
924
+ signature = await generateSignature ( { identifier, nonce : message } ) ;
925
+ } catch ( err ) {
926
+ // There is a chance that as a user when you try to setup and use the Coinbase Wallet with an existing
927
+ // Passkey in order to authenticate, the initial generate signature request to be rejected. For this
928
+ // reason we retry the request once more in order for the flow to be able to be completed successfully.
929
+ //
930
+ // error code 4001 means the user rejected the request
931
+ // Reference: https://docs.cdp.coinbase.com/wallet-sdk/docs/errors
932
+ if ( provider === 'coinbase_wallet' && err . code === 4001 ) {
933
+ signature = await generateSignature ( { identifier, nonce : message } ) ;
934
+ } else {
935
+ throw err ;
936
+ }
937
+ }
938
+
939
+ await this . resource . __internal_basePost ( {
940
+ body : { signature, strategy } ,
941
+ action : 'attempt_first_factor' ,
942
+ } ) ;
943
+ } ) ;
944
+ }
945
+
874
946
async sendMFAPhoneCode ( ) : Promise < { error : unknown } > {
875
947
return runAsyncResourceTask ( this . resource , async ( ) => {
876
948
const phoneCodeFactor = this . resource . supportedSecondFactors ?. find ( f => f . strategy === 'phone_code' ) ;
0 commit comments