Skip to content

Commit b0631e7

Browse files
authored
Account Unlinking (#107)
1 parent 429187d commit b0631e7

File tree

8 files changed

+101
-5
lines changed

8 files changed

+101
-5
lines changed

Thirdweb.Console/Program.cs

+8-5
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@
241241

242242
#region Account Linking
243243

244-
// var inAppWalletMain = await InAppWallet.Create(client: client, authProvider: AuthProvider.Google);
244+
// var inAppWalletMain = await InAppWallet.Create(client: client, authProvider: AuthProvider.Telegram);
245245
// if (!await inAppWalletMain.IsConnected())
246246
// {
247247
// _ = await inAppWalletMain.LoginWithOauth(
@@ -260,12 +260,15 @@
260260
// var oldLinkedAccounts = await inAppWalletMain.GetLinkedAccounts();
261261
// Console.WriteLine($"Old linked accounts: {JsonConvert.SerializeObject(oldLinkedAccounts, Formatting.Indented)}");
262262

263-
// var inAppWalletToLink = await InAppWallet.Create(client: client, authProvider: AuthProvider.Guest);
264-
// _ = await inAppWalletMain.LinkAccount(walletToLink: inAppWalletToLink);
265-
266-
// var linkedAccounts = await inAppWalletMain.GetLinkedAccounts();
263+
// // External wallet variant
264+
// var externalWallet = await PrivateKeyWallet.Generate(client: client);
265+
// var inAppWalletToLink = await InAppWallet.Create(client: client, authProvider: AuthProvider.Siwe, siweSigner: externalWallet);
266+
// var linkedAccounts = await inAppWalletMain.LinkAccount(walletToLink: inAppWalletToLink, chainId: 421614);
267267
// Console.WriteLine($"Linked accounts: {JsonConvert.SerializeObject(linkedAccounts, Formatting.Indented)}");
268268

269+
// var unlinkingResult = await inAppWalletMain.UnlinkAccount(linkedAccounts.First(linkedAccounts => linkedAccounts.Type == "siwe"));
270+
// Console.WriteLine($"Unlinking result: {JsonConvert.SerializeObject(unlinkingResult, Formatting.Indented)}");
271+
269272
#endregion
270273

271274
#region Smart Wallet - Authenticate

Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs

+6
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ Task<List<LinkedAccount>> LinkAccount(
155155
string payload = null
156156
);
157157

158+
/// <summary>
159+
/// Unlinks an account (auth method) from the current wallet.
160+
/// </summary>
161+
/// <param name="accountToUnlink">The linked account to unlink. Same type returned by <see cref="GetLinkedAccounts"/>.</param>
162+
Task<List<LinkedAccount>> UnlinkAccount(LinkedAccount accountToUnlink);
163+
158164
/// <summary>
159165
/// Returns a list of linked accounts to the current wallet.
160166
/// </summary>

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

+30
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,36 @@ public string GenerateExternalLoginLink(string redirectUrl)
332332

333333
#region Account Linking
334334

335+
public async Task<List<LinkedAccount>> UnlinkAccount(LinkedAccount accountToUnlink)
336+
{
337+
if (!await this.IsConnected().ConfigureAwait(false))
338+
{
339+
throw new InvalidOperationException("Cannot unlink account with a wallet that is not connected. Please login to the wallet before unlinking other wallets.");
340+
}
341+
342+
var currentAccountToken = this.EmbeddedWallet.GetSessionData()?.AuthToken;
343+
344+
var serverLinkedAccounts = await this.EmbeddedWallet.UnlinkAccountAsync(currentAccountToken, accountToUnlink).ConfigureAwait(false);
345+
var linkedAccounts = new List<LinkedAccount>();
346+
foreach (var linkedAccount in serverLinkedAccounts)
347+
{
348+
linkedAccounts.Add(
349+
new LinkedAccount
350+
{
351+
Type = linkedAccount.Type,
352+
Details = new LinkedAccount.LinkedAccountDetails
353+
{
354+
Email = linkedAccount.Details?.Email,
355+
Address = linkedAccount.Details?.Address,
356+
Phone = linkedAccount.Details?.Phone,
357+
Id = linkedAccount.Details?.Id
358+
}
359+
}
360+
);
361+
}
362+
return linkedAccounts;
363+
}
364+
335365
public async Task<List<LinkedAccount>> LinkAccount(
336366
IThirdwebWallet walletToLink,
337367
string otp = null,

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

+16
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace Thirdweb.EWS;
66

77
internal abstract class ServerBase
88
{
9+
internal abstract Task<List<Server.LinkedAccount>> UnlinkAccountAsync(string currentAccountToken, Server.LinkedAccount linkedAccount);
910
internal abstract Task<List<Server.LinkedAccount>> LinkAccountAsync(string currentAccountToken, string authTokenToConnect);
1011
internal abstract Task<List<Server.LinkedAccount>> GetLinkedAccountsAsync(string currentAccountToken);
1112

@@ -50,6 +51,21 @@ internal Server(ThirdwebClient client, IThirdwebHttpClient httpClient)
5051
this._httpClient = httpClient;
5152
}
5253

54+
// account/disconnect
55+
internal override async Task<List<LinkedAccount>> UnlinkAccountAsync(string currentAccountToken, LinkedAccount linkedAccount)
56+
{
57+
var uri = MakeUri2024("/account/disconnect");
58+
var request = new HttpRequestMessage(HttpMethod.Post, uri)
59+
{
60+
Content = MakeHttpContent(linkedAccount)
61+
};
62+
var response = await this.SendHttpWithAuthAsync(request, currentAccountToken).ConfigureAwait(false);
63+
await CheckStatusCodeAsync(response).ConfigureAwait(false);
64+
65+
var res = await DeserializeAsync<AccountConnectResponse>(response).ConfigureAwait(false);
66+
return res == null || res.LinkedAccounts == null || res.LinkedAccounts.Count == 0 ? throw new InvalidOperationException("No linked accounts returned") : res.LinkedAccounts;
67+
}
68+
5369
// account/connect
5470
internal override async Task<List<LinkedAccount>> LinkAccountAsync(string currentAccountToken, string authTokenToConnect)
5571
{

Thirdweb/Thirdweb.Wallets/InAppWallet/EmbeddedWallet/EmbeddedWallet.AccountLinking.cs

+16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
internal partial class EmbeddedWallet
44
{
5+
public async Task<List<Server.LinkedAccount>> UnlinkAccountAsync(string currentAccountToken, LinkedAccount linkedAccount)
6+
{
7+
var serverLinkedAccount = new Server.LinkedAccount
8+
{
9+
Type = linkedAccount.Type,
10+
Details = new Server.LinkedAccount.LinkedAccountDetails
11+
{
12+
Email = linkedAccount.Details.Email,
13+
Address = linkedAccount.Details.Address,
14+
Phone = linkedAccount.Details.Phone,
15+
Id = linkedAccount.Details.Id
16+
}
17+
};
18+
return await this._server.UnlinkAccountAsync(currentAccountToken, serverLinkedAccount).ConfigureAwait(false);
19+
}
20+
521
public async Task<List<Server.LinkedAccount>> LinkAccountAsync(string currentAccountToken, string authTokenToConnect)
622
{
723
return await this._server.LinkAccountAsync(currentAccountToken, authTokenToConnect).ConfigureAwait(false);

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

+10
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,24 @@ public enum AuthProvider
3131
/// </summary>
3232
public struct LinkedAccount
3333
{
34+
[JsonProperty("type")]
3435
public string Type { get; set; }
36+
37+
[JsonProperty("details")]
3538
public LinkedAccountDetails Details { get; set; }
3639

3740
public struct LinkedAccountDetails
3841
{
42+
[JsonProperty("email")]
3943
public string Email { get; set; }
44+
45+
[JsonProperty("name")]
4046
public string Address { get; set; }
47+
48+
[JsonProperty("phone")]
4149
public string Phone { get; set; }
50+
51+
[JsonProperty("id")]
4252
public string Id { get; set; }
4353
}
4454

Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs

+5
Original file line numberDiff line numberDiff line change
@@ -380,5 +380,10 @@ public virtual Task<List<LinkedAccount>> GetLinkedAccounts()
380380
throw new InvalidOperationException("GetLinkedAccounts is not supported for private key wallets.");
381381
}
382382

383+
public Task<List<LinkedAccount>> UnlinkAccount(LinkedAccount accountToUnlink)
384+
{
385+
throw new InvalidOperationException("UnlinkAccount is not supported for private key wallets.");
386+
}
387+
383388
#endregion
384389
}

Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs

+10
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,16 @@ public Task Disconnect()
11671167
return Task.CompletedTask;
11681168
}
11691169

1170+
public async Task<List<LinkedAccount>> UnlinkAccount(LinkedAccount accountToUnlink)
1171+
{
1172+
var personalWallet = await this.GetPersonalWallet().ConfigureAwait(false);
1173+
if (personalWallet is not InAppWallet and not EcosystemWallet)
1174+
{
1175+
throw new Exception("SmartWallet.UnlinkAccount is only supported if the signer is an InAppWallet or EcosystemWallet");
1176+
}
1177+
return await personalWallet.UnlinkAccount(accountToUnlink).ConfigureAwait(false);
1178+
}
1179+
11701180
public async Task<List<LinkedAccount>> LinkAccount(
11711181
IThirdwebWallet walletToLink,
11721182
string otp = null,

0 commit comments

Comments
 (0)