Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embedded Wallet Phone Number SIgn In #157

Merged
merged 7 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Assets/Thirdweb/Core/Plugin/thirdweb.jslib
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var plugin = {
chainId,
password,
email,
phoneNumber,
personalWallet,
authOptions,
smartWalletAccountOverride,
Expand All @@ -74,6 +75,7 @@ var plugin = {
UTF8ToString(chainId),
UTF8ToString(password),
UTF8ToString(email),
UTF8ToString(phoneNumber),
UTF8ToString(personalWallet),
UTF8ToString(authOptions),
UTF8ToString(smartWalletAccountOverride)
Expand Down
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!224 &1834539732908528857
RectTransform:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -1647,6 +1647,9 @@ MonoBehaviour:
RecoveryCodesCanvas: {fileID: 3065337689055971296}
RecoveryCodesText: {fileID: 4840930599477263590}
RecoveryCodesCopy: {fileID: 7908066674043299061}
OnEmailOTPVerificationFailed:
m_PersistentCalls:
m_Calls: []
--- !u!1 &3462065987877024667
GameObject:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -2440,7 +2443,7 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Enter the code sent to your email
m_text: Enter the code sent to you
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
Expand All @@ -2467,7 +2470,7 @@ MonoBehaviour:
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 40.75
m_fontSize: 44.75
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
Expand Down
3 changes: 2 additions & 1 deletion Assets/Thirdweb/Core/Scripts/Bridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public static async Task<string> Connect(WalletConnection walletConnection)
walletConnection.chainId.ToString(),
string.IsNullOrEmpty(walletConnection.password) ? Utils.GetDeviceIdentifier() : walletConnection.password,
walletConnection.email,
walletConnection.phoneNumber,
walletConnection.personalWallet.ToString()[..1].ToLower() + walletConnection.personalWallet.ToString()[1..],
JsonConvert.SerializeObject(walletConnection.authOptions),
walletConnection.smartWalletAccountOverride,
Expand Down Expand Up @@ -457,7 +458,7 @@ public static async Task<string> ResolveAddressFromENS(string ens)
[DllImport("__Internal")]
private static extern string ThirdwebInitialize(string chainOrRPC, string options);
[DllImport("__Internal")]
private static extern string ThirdwebConnect(string taskId, string wallet, string chainId, string password, string email, string personalWallet, string authOptions, string smartWalletAccountOverride, Action<string, string, string> cb);
private static extern string ThirdwebConnect(string taskId, string wallet, string chainId, string password, string email, string phoneNumber, string personalWallet, string authOptions, string smartWalletAccountOverride, Action<string, string, string> cb);
[DllImport("__Internal")]
private static extern string ThirdwebDisconnect(string taskId, Action<string, string, string> cb);
[DllImport("__Internal")]
Expand Down
6 changes: 6 additions & 0 deletions Assets/Thirdweb/Core/Scripts/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,12 @@ public static string HashMessage(this string message)
return sha3.CalculateHash(message);
}

public static bool IsValidEmail(string email)
{
var emailRegex = new System.Text.RegularExpressions.Regex(@"^\S+@\S+\.\S+$");
return emailRegex.IsMatch(email.Replace("+", ""));
}

public static string GenerateRandomString(int v)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Expand Down
8 changes: 8 additions & 0 deletions Assets/Thirdweb/Core/Scripts/Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,7 @@ public class WalletConnection
public BigInteger chainId;
public string password;
public string email;
public string phoneNumber;
public WalletProvider personalWallet;
public AuthOptions authOptions;
public string smartWalletAccountOverride;
Expand All @@ -985,6 +986,7 @@ public WalletConnection(
BigInteger chainId,
string password = null,
string email = null,
string phoneNumber = null,
WalletProvider personalWallet = WalletProvider.LocalWallet,
AuthOptions authOptions = null,
string smartWalletAccountOverride = null
Expand All @@ -994,6 +996,7 @@ public WalletConnection(
this.chainId = chainId;
this.password = password;
this.email = email;
this.phoneNumber = phoneNumber;
this.personalWallet = personalWallet;
this.authOptions = authOptions ?? new AuthOptions(authProvider: AuthProvider.EmailOTP, jwtOrPayload: null, encryptionKey: null);
this.smartWalletAccountOverride = smartWalletAccountOverride;
Expand Down Expand Up @@ -1076,5 +1079,10 @@ public enum AuthProvider
/// Custom Authentication Flow, checks payload against developer-set Auth Endpoint.
/// </summary>
AuthEndpoint,

/// <summary>
/// Phone Number OTP Flow.
/// </summary>
PhoneOTP
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public async Task<string> Connect(WalletConnection walletConnection, string rpc)
GameObject.Instantiate(ThirdwebManager.Instance.EmbeddedWalletPrefab);
}

var user = await EmbeddedWalletUI.Instance.Connect(_embeddedWallet, walletConnection.email, walletConnection.authOptions);
var user = await EmbeddedWalletUI.Instance.Connect(_embeddedWallet, walletConnection.email, walletConnection.phoneNumber, walletConnection.authOptions);
_account = user.Account;
_email = user.EmailAddress;
_web3 = new Web3(_account, rpc);
Expand Down
77 changes: 73 additions & 4 deletions Assets/Thirdweb/Core/Scripts/WalletsUI/EmbeddedWalletUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ public class EmbeddedWalletUI : MonoBehaviour
public Button RecoveryCodesCopy;

[Tooltip("Invoked when the user submits an invalid OTP and can retry.")]
public UnityEvent OnEmailOTPVerificationFailed;
public UnityEvent OnOTPVerificationFailed;

protected EmbeddedWallet _embeddedWallet;
protected string _email;
protected string _phone;
protected User _user;
protected Exception _exception;
protected string _callbackUrl;
Expand Down Expand Up @@ -61,14 +62,15 @@ private void Awake()

#region Connection Flow

public virtual async Task<User> Connect(EmbeddedWallet embeddedWallet, string email, AuthOptions authOptions)
public virtual async Task<User> Connect(EmbeddedWallet embeddedWallet, string email, string phoneNumber, AuthOptions authOptions)
{
var config = Resources.Load<ThirdwebConfig>("ThirdwebConfig");
_customScheme = config != null ? config.customScheme : null;
if (!string.IsNullOrEmpty(_customScheme))
_customScheme = _customScheme.EndsWith("://") ? _customScheme : $"{_customScheme}://";
_embeddedWallet = embeddedWallet;
_email = email;
_phone = phoneNumber;
_user = null;
_exception = null;
OTPInput.text = "";
Expand All @@ -88,6 +90,7 @@ public virtual async Task<User> Connect(EmbeddedWallet embeddedWallet, string em
AuthProvider.Apple => "Apple",
AuthProvider.Facebook => "Facebook",
AuthProvider.JWT => "CustomAuth",
AuthProvider.PhoneOTP => "PhoneOTP",
_ => throw new UnityException($"Unsupported auth provider: {authOptions.authProvider}"),
};
return await _embeddedWallet.GetUserAsync(_email, authProvider);
Expand Down Expand Up @@ -119,6 +122,9 @@ public virtual async Task<User> Connect(EmbeddedWallet embeddedWallet, string em
case AuthProvider.AuthEndpoint:
await LoginWithAuthEndpoint(authOptions.jwtOrPayload, authOptions.encryptionKey);
break;
case AuthProvider.PhoneOTP:
await LoginWithPhoneNumber();
break;
default:
throw new UnityException($"Unsupported auth provider: {authOptions.authProvider}");
}
Expand Down Expand Up @@ -180,9 +186,72 @@ public virtual async void OnSubmitOTP()
var res = await _embeddedWallet.VerifyOtpAsync(_email, otp, string.IsNullOrEmpty(RecoveryInput.text) ? null : RecoveryInput.text);
if (res.User == null)
{
if (res.CanRetry && OnEmailOTPVerificationFailed.GetPersistentEventCount() > 0)
if (res.CanRetry && OnOTPVerificationFailed.GetPersistentEventCount() > 0)
{
OnOTPVerificationFailed.Invoke();
return;
}
_exception = new UnityException("User OTP Verification Failed.");
return;
}
_user = res.User;
ShowRecoveryCodes(res);
}
catch (Exception e)
{
_exception = e;
}
finally
{
OTPInput.interactable = true;
RecoveryInput.interactable = true;
SubmitButton.interactable = true;
}
}

#endregion

#region Phone Number Flow

public virtual async Task LoginWithPhoneNumber()
{
if (_phone == null)
throw new UnityException("Phone number is required!");

SubmitButton.onClick.AddListener(OnSubmitPhoneOTP);
await OnSendPhoneOTP();
EmbeddedWalletCanvas.SetActive(true);
}

public virtual async Task OnSendPhoneOTP()
{
try
{
(bool isNewUser, bool isNewDevice, bool needsRecoveryCode) = await _embeddedWallet.SendOtpPhoneAsync(_phone);
if (needsRecoveryCode && !isNewUser && isNewDevice)
DisplayRecoveryInput(false);
ThirdwebDebug.Log($"finished sending OTP: isNewUser {isNewUser}, isNewDevice {isNewDevice}");
}
catch (Exception e)
{
_exception = e;
}
}

public virtual async void OnSubmitPhoneOTP()
{
OTPInput.interactable = false;
RecoveryInput.interactable = false;
SubmitButton.interactable = false;
try
{
string otp = OTPInput.text;
var res = await _embeddedWallet.VerifyPhoneOtpAsync(_phone, otp, string.IsNullOrEmpty(RecoveryInput.text) ? null : RecoveryInput.text);
if (res.User == null)
{
if (res.CanRetry && OnOTPVerificationFailed.GetPersistentEventCount() > 0)
{
OnEmailOTPVerificationFailed.Invoke();
OnOTPVerificationFailed.Invoke();
return;
}
_exception = new UnityException("User OTP Verification Failed.");
Expand Down
12 changes: 6 additions & 6 deletions Assets/Thirdweb/Examples/Prefabs/Prefab_ConnectWallet.prefab
Original file line number Diff line number Diff line change
Expand Up @@ -1196,7 +1196,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
m_IsActive: 1
--- !u!224 &894485209110800966
RectTransform:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -2946,7 +2946,7 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Email
m_text: Email & Phone
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
Expand Down Expand Up @@ -6419,7 +6419,7 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Enter your email address
m_text: Enter your email address or phone number
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
Expand Down Expand Up @@ -10157,14 +10157,14 @@ MonoBehaviour:
m_VerticalScrollbarEventHandler: {fileID: 0}
m_LayoutGroup: {fileID: 0}
m_ScrollSensitivity: 1
m_ContentType: 6
m_ContentType: 0
m_InputType: 0
m_AsteriskChar: 42
m_KeyboardType: 7
m_KeyboardType: 0
m_LineType: 0
m_HideMobileInput: 0
m_HideSoftKeyboard: 0
m_CharacterValidation: 7
m_CharacterValidation: 0
m_RegexValue:
m_GlobalPointSize: 14
m_CharacterLimit: 0
Expand Down
Loading
Loading