From 3a940498dbc33fd20ede697b3f0ed01599b5333f Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Fri, 5 Apr 2024 23:59:49 +0300 Subject: [PATCH] Phone Number Login --- Thirdweb.Console/Program.cs | 15 ++++-- Thirdweb.Console/Thirdweb.Console.csproj | 2 +- Thirdweb.Tests/Thirdweb.Tests.csproj | 2 +- .../EmbeddedAccount/EmbeddedAccount.cs | 54 +++++++++++++++---- 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index aa66567..e6cf7fe 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -28,9 +28,9 @@ private static async Task Main(string[] args) Console.WriteLine($"Contract read result: {readResult}"); // Create accounts - var privateKeyAccount = new PrivateKeyAccount(client, privateKey); - var embeddedAccount = new EmbeddedAccount(client, "firekeeper+7121271d@thirdweb.com"); - var smartAccount = new SmartAccount(client, embeddedAccount, "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", true, 421614); + var privateKeyAccount = new PrivateKeyAccount(client: client, privateKeyHex: privateKey); + var embeddedAccount = new EmbeddedAccount(client: client, email: "firekeeper+7121271d@thirdweb.com"); + var smartAccount = new SmartAccount(client: client, personalAccount: embeddedAccount, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614); // Attempt to connect pk accounts await privateKeyAccount.Connect(); @@ -73,7 +73,14 @@ private static async Task Main(string[] args) ); // Reconnect to same smart account with pk account as signer - smartAccount = new SmartAccount(client, privateKeyAccount, "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", true, 421614, await smartAccount.GetAddress()); + smartAccount = new SmartAccount( + client: client, + personalAccount: privateKeyAccount, + factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", + gasless: true, + chainId: 421614, + accountAddressOverride: await smartAccount.GetAddress() + ); await smartAccount.Connect(); // Log addresses diff --git a/Thirdweb.Console/Thirdweb.Console.csproj b/Thirdweb.Console/Thirdweb.Console.csproj index 7d6573c..2acaa4b 100644 --- a/Thirdweb.Console/Thirdweb.Console.csproj +++ b/Thirdweb.Console/Thirdweb.Console.csproj @@ -3,7 +3,7 @@ Exe - net7.0 + net8.0 enable enable false diff --git a/Thirdweb.Tests/Thirdweb.Tests.csproj b/Thirdweb.Tests/Thirdweb.Tests.csproj index 2f9b75f..439baa6 100644 --- a/Thirdweb.Tests/Thirdweb.Tests.csproj +++ b/Thirdweb.Tests/Thirdweb.Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable false diff --git a/Thirdweb/Thirdweb.Wallets/EmbeddedAccount/EmbeddedAccount.cs b/Thirdweb/Thirdweb.Wallets/EmbeddedAccount/EmbeddedAccount.cs index bc797ec..4deb193 100644 --- a/Thirdweb/Thirdweb.Wallets/EmbeddedAccount/EmbeddedAccount.cs +++ b/Thirdweb/Thirdweb.Wallets/EmbeddedAccount/EmbeddedAccount.cs @@ -21,16 +21,18 @@ public class EmbeddedAccount : IThirdwebAccount private User _user; private EthECKey _ecKey; private string _email; + private string _phoneNumber; - public EmbeddedAccount(ThirdwebClient client, string email) + public EmbeddedAccount(ThirdwebClient client, string email = null, string phoneNumber = null) { - if (string.IsNullOrEmpty(email)) + if (string.IsNullOrEmpty(email) && string.IsNullOrEmpty(phoneNumber)) { - throw new ArgumentException("Email must be provided to use Embedded Wallets."); + throw new ArgumentException("Email or Phone Number must be provided to login."); } _embeddedWallet = new EmbeddedWallet(client); _email = email; + _phoneNumber = phoneNumber; _client = client; } @@ -38,7 +40,7 @@ public async Task Connect() { try { - _user = await _embeddedWallet.GetUserAsync(_email, "EmailOTP"); + _user = await _embeddedWallet.GetUserAsync(_email, _email == null ? "PhoneOTP" : "EmailOTP"); _ecKey = new EthECKey(_user.Account.PrivateKey); } catch @@ -49,19 +51,31 @@ public async Task Connect() } } - #region Email OTP Flow + #region OTP Flow public async Task SendOTP() { - if (string.IsNullOrEmpty(_email)) + if (string.IsNullOrEmpty(_email) && string.IsNullOrEmpty(_phoneNumber)) { - throw new Exception("Email is required for OTP login"); + throw new Exception("Email or Phone Number is required for OTP login"); } try { - (bool isNewUser, bool isNewDevice, bool needsRecoveryCode) = await _embeddedWallet.SendOtpEmailAsync(_email); - Console.WriteLine("OTP sent to email. Please call EmbeddedAccount.SubmitOTP to login."); + if (_email != null) + { + (var isNewUser, var isNewDevice, var needsRecoveryCode) = await _embeddedWallet.SendOtpEmailAsync(_email); + } + else if (_phoneNumber != null) + { + (var isNewUser, var isNewDevice, var needsRecoveryCode) = await _embeddedWallet.SendOtpPhoneAsync(_phoneNumber); + } + else + { + throw new Exception("Email or Phone Number must be provided to login."); + } + + Console.WriteLine("OTP sent to user. Please call EmbeddedAccount.SubmitOTP to login."); } catch (Exception e) { @@ -71,7 +85,17 @@ public async Task SendOTP() public async Task<(string, bool)> SubmitOTP(string otp) { - var res = await _embeddedWallet.VerifyOtpAsync(_email, otp, null); + if (string.IsNullOrEmpty(otp)) + { + throw new ArgumentNullException(nameof(otp), "OTP cannot be null or empty."); + } + + if (string.IsNullOrEmpty(_email) && string.IsNullOrEmpty(_phoneNumber)) + { + throw new Exception("Email or Phone Number is required for OTP login"); + } + + var res = _email == null ? await _embeddedWallet.VerifyPhoneOtpAsync(_phoneNumber, otp, null) : await _embeddedWallet.VerifyOtpAsync(_email, otp, null); if (res.User == null) { var canRetry = res.CanRetry; @@ -93,6 +117,16 @@ public async Task SendOTP() } } + public Task GetEmail() + { + return Task.FromResult(_email); + } + + public Task GetPhoneNumber() + { + return Task.FromResult(_phoneNumber); + } + #endregion public Task GetAddress()