Skip to content

Commit

Permalink
Phone Number Login
Browse files Browse the repository at this point in the history
  • Loading branch information
0xFirekeeper committed Apr 5, 2024
1 parent 6bb26aa commit 3a94049
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
15 changes: 11 additions & 4 deletions Thirdweb.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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, "[email protected]");
var smartAccount = new SmartAccount(client, embeddedAccount, "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", true, 421614);
var privateKeyAccount = new PrivateKeyAccount(client: client, privateKeyHex: privateKey);
var embeddedAccount = new EmbeddedAccount(client: client, email: "[email protected]");
var smartAccount = new SmartAccount(client: client, personalAccount: embeddedAccount, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614);

// Attempt to connect pk accounts
await privateKeyAccount.Connect();
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Thirdweb.Console/Thirdweb.Console.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
Expand Down
2 changes: 1 addition & 1 deletion Thirdweb.Tests/Thirdweb.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
Expand Down
54 changes: 44 additions & 10 deletions Thirdweb/Thirdweb.Wallets/EmbeddedAccount/EmbeddedAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,26 @@ 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;
}

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
Expand All @@ -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)
{
Expand All @@ -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;
Expand All @@ -93,6 +117,16 @@ public async Task SendOTP()
}
}

public Task<string> GetEmail()
{
return Task.FromResult(_email);
}

public Task<string> GetPhoneNumber()
{
return Task.FromResult(_phoneNumber);
}

#endregion

public Task<string> GetAddress()
Expand Down

0 comments on commit 3a94049

Please sign in to comment.