Skip to content

Commit 1362405

Browse files
committed
enclave iaw unlocked, cleanup
1 parent 59945f1 commit 1362405

File tree

7 files changed

+59
-151
lines changed

7 files changed

+59
-151
lines changed

Thirdweb/Thirdweb.Wallets/InAppWallet/EcosystemWallet/EcosystemWallet.Types.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace Thirdweb;
44

55
public partial class EcosystemWallet
66
{
7-
internal class EnclaveUserStatusResponse
7+
public class EnclaveUserStatusResponse
88
{
99
[JsonProperty("linkedAccounts")]
1010
internal List<LinkedAccount> LinkedAccounts { get; set; }

Thirdweb/Thirdweb.Wallets/InAppWallet/EcosystemWallet/EcosystemWallet.cs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ public partial class EcosystemWallet : IThirdwebWallet
2424
internal readonly string PhoneNumber;
2525
internal readonly string AuthProvider;
2626

27+
internal string Address;
28+
2729
private readonly string _ecosystemId;
2830
private readonly string _ecosystemPartnerId;
2931

30-
private string _address;
31-
3232
private const string EMBEDDED_WALLET_BASE_PATH = "https://embedded-wallet.thirdweb.com/api";
3333
private const string EMBEDDED_WALLET_PATH_2024 = $"{EMBEDDED_WALLET_BASE_PATH}/2024-05-05";
3434
private const string EMBEDDED_WALLET_PATH_V1 = $"{EMBEDDED_WALLET_BASE_PATH}/v1";
@@ -128,12 +128,12 @@ public static async Task<EcosystemWallet> Create(
128128
try
129129
{
130130
var userAddress = await ResumeEnclaveSession(enclaveHttpClient, embeddedWallet, email, phoneNumber, authproviderStr).ConfigureAwait(false);
131-
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner) { _address = userAddress };
131+
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner) { Address = userAddress };
132132
}
133133
catch
134134
{
135135
enclaveHttpClient.RemoveHeader("Authorization");
136-
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner) { _address = null };
136+
return new EcosystemWallet(ecosystemId, ecosystemPartnerId, client, embeddedWallet, enclaveHttpClient, email, phoneNumber, authproviderStr, siweSigner) { Address = null };
137137
}
138138
}
139139

@@ -156,6 +156,7 @@ private static async Task<string> ResumeEnclaveSession(IThirdwebHttpClient httpC
156156
httpClient.AddHeader("Authorization", $"Bearer embedded-wallet-token:{sessionData.AuthToken}");
157157

158158
var userStatus = await GetUserStatus(httpClient).ConfigureAwait(false);
159+
Console.WriteLine($"User status: {JsonConvert.SerializeObject(userStatus)}");
159160
if (userStatus.Wallets[0].Type == "enclave")
160161
{
161162
return userStatus.Wallets[0].Address.ToChecksumAddress();
@@ -223,8 +224,8 @@ private async Task<string> PostAuth(Server.VerifyResult result)
223224
else
224225
{
225226
CreateEnclaveSession(this.EmbeddedWallet, result.AuthToken, this.Email, this.PhoneNumber, this.AuthProvider, result.AuthIdentifier);
226-
this._address = address.ToChecksumAddress();
227-
return this._address;
227+
this.Address = address.ToChecksumAddress();
228+
return this.Address;
228229
}
229230
}
230231

@@ -254,11 +255,22 @@ private async Task<string> MigrateShardToEnclave(Server.VerifyResult authResult)
254255

255256
#region Wallet Specific
256257

258+
/// <summary>
259+
/// Gets the user details from the enclave wallet.
260+
/// </summary>
261+
/// <returns>A task that represents the asynchronous operation. The task result contains the user details.</returns>
262+
public async Task<EnclaveUserStatusResponse> GetUserDetails()
263+
{
264+
return await GetUserStatus(this.HttpClient).ConfigureAwait(false);
265+
}
266+
267+
[Obsolete("Use GetUserDetails instead.")]
257268
public string GetEmail()
258269
{
259270
return this.Email;
260271
}
261272

273+
[Obsolete("Use GetUserDetails instead.")]
262274
public string GetPhoneNumber()
263275
{
264276
return this.PhoneNumber;
@@ -408,7 +420,7 @@ public async Task<List<LinkedAccount>> GetLinkedAccounts()
408420

409421
#region OTP Auth
410422

411-
public async Task<(bool isNewUser, bool isNewDevice)> SendOTP()
423+
public async Task SendOTP()
412424
{
413425
if (string.IsNullOrEmpty(this.Email) && string.IsNullOrEmpty(this.PhoneNumber))
414426
{
@@ -417,9 +429,14 @@ public async Task<List<LinkedAccount>> GetLinkedAccounts()
417429

418430
try
419431
{
420-
return this.Email == null
421-
? await this.EmbeddedWallet.SendPhoneOtpAsync(this.PhoneNumber).ConfigureAwait(false)
422-
: await this.EmbeddedWallet.SendEmailOtpAsync(this.Email).ConfigureAwait(false);
432+
if (this.Email == null)
433+
{
434+
await this.EmbeddedWallet.SendPhoneOtpAsync(this.PhoneNumber).ConfigureAwait(false);
435+
}
436+
else
437+
{
438+
await this.EmbeddedWallet.SendEmailOtpAsync(this.Email).ConfigureAwait(false);
439+
}
423440
}
424441
catch (Exception e)
425442
{
@@ -629,13 +646,13 @@ public async Task<string> LoginWithAuthEndpoint(string payload)
629646

630647
public Task<string> GetAddress()
631648
{
632-
if (!string.IsNullOrEmpty(this._address))
649+
if (!string.IsNullOrEmpty(this.Address))
633650
{
634-
return Task.FromResult(this._address.ToChecksumAddress());
651+
return Task.FromResult(this.Address.ToChecksumAddress());
635652
}
636653
else
637654
{
638-
return Task.FromResult(this._address);
655+
return Task.FromResult(this.Address);
639656
}
640657
}
641658

@@ -763,7 +780,7 @@ public async Task<string> SignTransaction(ThirdwebTransactionInput transaction)
763780

764781
public Task<bool> IsConnected()
765782
{
766-
return Task.FromResult(this._address != null);
783+
return Task.FromResult(this.Address != null);
767784
}
768785

769786
public Task<string> SendTransaction(ThirdwebTransactionInput transaction)
@@ -778,7 +795,7 @@ public Task<ThirdwebTransactionReceipt> ExecuteTransaction(ThirdwebTransactionIn
778795

779796
public async Task Disconnect()
780797
{
781-
this._address = null;
798+
this.Address = null;
782799
await this.EmbeddedWallet.SignOutAsync().ConfigureAwait(false);
783800
}
784801

Thirdweb/Thirdweb.Wallets/InAppWallet/EmbeddedWallet.Authentication/Server.cs

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ internal abstract class ServerBase
99
internal abstract Task<List<Server.LinkedAccount>> LinkAccountAsync(string currentAccountToken, string authTokenToConnect);
1010
internal abstract Task<List<Server.LinkedAccount>> GetLinkedAccountsAsync(string currentAccountToken);
1111

12-
internal abstract Task<Server.UserWallet> FetchUserDetailsAsync(string emailAddress, string authToken);
13-
internal abstract Task StoreAddressAndSharesAsync(string walletAddress, string authShare, string encryptedRecoveryShare, string authToken);
14-
1512
internal abstract Task<(string authShare, string recoveryShare)> FetchAuthAndRecoverySharesAsync(string authToken);
1613
internal abstract Task<string> FetchAuthShareAsync(string authToken);
1714

@@ -79,46 +76,6 @@ internal override async Task<List<LinkedAccount>> GetLinkedAccountsAsync(string
7976
return res == null || res.LinkedAccounts == null || res.LinkedAccounts.Count == 0 ? [] : res.LinkedAccounts;
8077
}
8178

82-
// embedded-wallet/embedded-wallet-user-details
83-
internal override async Task<UserWallet> FetchUserDetailsAsync(string emailOrPhone, string authToken)
84-
{
85-
Dictionary<string, string> queryParams = new();
86-
if (emailOrPhone == null && authToken == null)
87-
{
88-
throw new InvalidOperationException("Must provide either email address or auth token");
89-
}
90-
91-
queryParams.Add("email", emailOrPhone ?? "uninitialized");
92-
queryParams.Add("clientId", this._clientId);
93-
94-
var uri = MakeUri2023("/embedded-wallet/embedded-wallet-user-details", queryParams);
95-
var response = await this.SendHttpWithAuthAsync(uri, authToken ?? "").ConfigureAwait(false);
96-
await CheckStatusCodeAsync(response).ConfigureAwait(false);
97-
var rv = await DeserializeAsync<UserWallet>(response).ConfigureAwait(false);
98-
return rv;
99-
}
100-
101-
// embedded-wallet/embedded-wallet-shares POST
102-
internal override async Task StoreAddressAndSharesAsync(string walletAddress, string authShare, string encryptedRecoveryShare, string authToken)
103-
{
104-
var encryptedRecoveryShares = new[] { new { share = encryptedRecoveryShare, isClientEncrypted = "true" } };
105-
106-
HttpRequestMessage httpRequestMessage =
107-
new(HttpMethod.Post, MakeUri2023("/embedded-wallet/embedded-wallet-shares"))
108-
{
109-
Content = MakeHttpContent(
110-
new
111-
{
112-
authShare,
113-
maybeEncryptedRecoveryShares = encryptedRecoveryShares,
114-
walletAddress,
115-
}
116-
),
117-
};
118-
var response = await this.SendHttpWithAuthAsync(httpRequestMessage, authToken).ConfigureAwait(false);
119-
await CheckStatusCodeAsync(response).ConfigureAwait(false);
120-
}
121-
12279
// embedded-wallet/embedded-wallet-shares GET
12380
internal override async Task<(string authShare, string recoveryShare)> FetchAuthAndRecoverySharesAsync(string authToken)
12481
{

Thirdweb/Thirdweb.Wallets/InAppWallet/EmbeddedWallet/EmbeddedWallet.EmailOTP.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22

33
internal partial class EmbeddedWallet
44
{
5-
public async Task<(bool isNewUser, bool isNewDevice)> SendEmailOtpAsync(string emailAddress)
5+
public async Task SendEmailOtpAsync(string emailAddress)
66
{
77
emailAddress = emailAddress.ToLower();
8-
var userWallet = await this._server.FetchUserDetailsAsync(emailAddress, null).ConfigureAwait(false);
98
_ = await this._server.SendEmailOtpAsync(emailAddress).ConfigureAwait(false);
10-
var isNewDevice = userWallet.IsNewUser || this._localStorage.Data?.WalletUserId != userWallet.WalletUserId;
11-
return (userWallet.IsNewUser, isNewDevice);
129
}
1310

1411
public async Task<Server.VerifyResult> VerifyEmailOtpAsync(string emailAddress, string otp)

Thirdweb/Thirdweb.Wallets/InAppWallet/EmbeddedWallet/EmbeddedWallet.Misc.cs

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -15,93 +15,12 @@ internal async void UpdateSessionData(LocalStorage.DataStorage data)
1515
await this._localStorage.SaveDataAsync(data).ConfigureAwait(false);
1616
}
1717

18-
internal async Task<VerifyResult> PostAuthSetup(Server.VerifyResult result, string twManagedRecoveryCodeOverride, string authProvider)
19-
{
20-
var mainRecoveryCode = (twManagedRecoveryCodeOverride ?? result.RecoveryCode) ?? throw new InvalidOperationException("Server failed to return recovery code.");
21-
22-
(var account, var deviceShare) = result.IsNewUser
23-
? await this.CreateAccountAsync(result.AuthToken, mainRecoveryCode).ConfigureAwait(false)
24-
: await this.RecoverAccountAsync(result.AuthToken, mainRecoveryCode).ConfigureAwait(false);
25-
var user = this.MakeUserAsync(result.Email, result.PhoneNumber, account, result.AuthToken, result.WalletUserId, deviceShare, authProvider, result.AuthIdentifier);
26-
return new VerifyResult(user, mainRecoveryCode);
27-
}
28-
2918
public async Task SignOutAsync()
3019
{
3120
this._user = null;
3221
await this._localStorage.SaveDataAsync(new LocalStorage.DataStorage(null, null, null, null, null, null, null)).ConfigureAwait(false);
3322
}
3423

35-
public async Task<User> GetUserAsync(string email, string phone, string authProvider)
36-
{
37-
email = email?.ToLower();
38-
39-
if (this._user != null)
40-
{
41-
return this._user;
42-
}
43-
else if (this._localStorage.Data?.AuthToken == null)
44-
{
45-
throw new InvalidOperationException("User is not signed in");
46-
}
47-
48-
var userWallet = await this._server.FetchUserDetailsAsync(null, this._localStorage.Data.AuthToken).ConfigureAwait(false);
49-
switch (userWallet.Status)
50-
{
51-
case "Logged Out":
52-
throw new InvalidOperationException("User is logged out");
53-
case "Logged In, Wallet Uninitialized":
54-
throw new InvalidOperationException("User is logged in but wallet is uninitialized");
55-
case "Logged In, Wallet Initialized":
56-
if (string.IsNullOrEmpty(this._localStorage.Data?.DeviceShare))
57-
{
58-
throw new InvalidOperationException("User is logged in but wallet is uninitialized");
59-
}
60-
61-
var authShare = await this._server.FetchAuthShareAsync(this._localStorage.Data.AuthToken).ConfigureAwait(false);
62-
var emailAddress = userWallet.StoredToken?.AuthDetails.Email;
63-
var phoneNumber = userWallet.StoredToken?.AuthDetails.PhoneNumber;
64-
65-
if ((email != null && email != emailAddress) || (phone != null && phone != phoneNumber))
66-
{
67-
throw new InvalidOperationException("User email or phone number do not match");
68-
}
69-
else if (email == null && this._localStorage.Data.AuthProvider != authProvider)
70-
{
71-
throw new InvalidOperationException($"User auth provider does not match. Expected {this._localStorage.Data.AuthProvider}, got {authProvider}");
72-
}
73-
else if (authShare == null)
74-
{
75-
throw new InvalidOperationException("Server failed to return auth share");
76-
}
77-
78-
this._user = new User(MakeAccountFromShares(new[] { authShare, this._localStorage.Data.DeviceShare }), emailAddress, phoneNumber);
79-
return this._user;
80-
default:
81-
break;
82-
}
83-
throw new InvalidOperationException($"Unexpected user status '{userWallet.Status}'");
84-
}
85-
86-
private User MakeUserAsync(string emailAddress, string phoneNumber, Account account, string authToken, string walletUserId, string deviceShare, string authProvider, string authIdentifier)
87-
{
88-
var data = new LocalStorage.DataStorage(authToken, deviceShare, emailAddress, phoneNumber, walletUserId, authProvider, authIdentifier);
89-
this.UpdateSessionData(data);
90-
this._user = new User(account, emailAddress, phoneNumber);
91-
return this._user;
92-
}
93-
94-
private async Task<(Account account, string deviceShare)> CreateAccountAsync(string authToken, string recoveryCode)
95-
{
96-
var secret = Secrets.Random(KEY_SIZE);
97-
98-
(var deviceShare, var recoveryShare, var authShare) = CreateShares(secret);
99-
var encryptedRecoveryShare = await this.EncryptShareAsync(recoveryShare, recoveryCode).ConfigureAwait(false);
100-
Account account = new(secret);
101-
await this._server.StoreAddressAndSharesAsync(account.Address, authShare, encryptedRecoveryShare, authToken).ConfigureAwait(false);
102-
return (account, deviceShare);
103-
}
104-
10524
internal async Task<(Account account, string deviceShare)> RecoverAccountAsync(string authToken, string recoveryCode)
10625
{
10726
(var authShare, var encryptedRecoveryShare) = await this._server.FetchAuthAndRecoverySharesAsync(authToken).ConfigureAwait(false);

Thirdweb/Thirdweb.Wallets/InAppWallet/EmbeddedWallet/EmbeddedWallet.PhoneOTP.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22

33
internal partial class EmbeddedWallet
44
{
5-
public async Task<(bool isNewUser, bool isNewDevice)> SendPhoneOtpAsync(string phoneNumber)
5+
public async Task SendPhoneOtpAsync(string phoneNumber)
66
{
7-
var userWallet = await this._server.FetchUserDetailsAsync(phoneNumber, null).ConfigureAwait(false);
87
_ = await this._server.SendPhoneOtpAsync(phoneNumber).ConfigureAwait(false);
9-
var isNewDevice = userWallet.IsNewUser || this._localStorage.Data?.WalletUserId != userWallet.WalletUserId;
10-
return (userWallet.IsNewUser, isNewDevice);
118
}
129

1310
public async Task<Server.VerifyResult> VerifyPhoneOtpAsync(string phoneNumber, string otp)

Thirdweb/Thirdweb.Wallets/InAppWallet/InAppWallet.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,20 @@ namespace Thirdweb;
77
/// </summary>
88
public class InAppWallet : EcosystemWallet
99
{
10-
internal InAppWallet(ThirdwebClient client, EmbeddedWallet embeddedWallet, IThirdwebHttpClient httpClient, string email, string phoneNumber, string authProvider, IThirdwebWallet siweSigner)
11-
: base(null, null, client, embeddedWallet, httpClient, email, phoneNumber, authProvider, siweSigner) { }
10+
internal InAppWallet(
11+
ThirdwebClient client,
12+
EmbeddedWallet embeddedWallet,
13+
IThirdwebHttpClient httpClient,
14+
string email,
15+
string phoneNumber,
16+
string authProvider,
17+
IThirdwebWallet siweSigner,
18+
string address
19+
)
20+
: base(null, null, client, embeddedWallet, httpClient, email, phoneNumber, authProvider, siweSigner)
21+
{
22+
this.Address = address;
23+
}
1224

1325
/// <summary>
1426
/// Creates a new instance of the <see cref="InAppWallet"/> class.
@@ -32,6 +44,15 @@ public static async Task<InAppWallet> Create(
3244
{
3345
storageDirectoryPath ??= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Thirdweb", "InAppWallet");
3446
var ecoWallet = await Create(client, null, null, email, phoneNumber, authProvider, storageDirectoryPath, siweSigner);
35-
return new InAppWallet(ecoWallet.Client, ecoWallet.EmbeddedWallet, ecoWallet.HttpClient, ecoWallet.Email, ecoWallet.PhoneNumber, ecoWallet.AuthProvider, ecoWallet.SiweSigner);
47+
return new InAppWallet(
48+
ecoWallet.Client,
49+
ecoWallet.EmbeddedWallet,
50+
ecoWallet.HttpClient,
51+
ecoWallet.Email,
52+
ecoWallet.PhoneNumber,
53+
ecoWallet.AuthProvider,
54+
ecoWallet.SiweSigner,
55+
ecoWallet.Address
56+
);
3657
}
3758
}

0 commit comments

Comments
 (0)