Skip to content

Commit 456fd10

Browse files
Add account deletion support when unlinking profiles
1 parent 0299034 commit 456fd10

File tree

11 files changed

+141
-9
lines changed

11 files changed

+141
-9
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
**Add account deletion support when unlinking profiles**
6+
7+
Added optional `allowAccountDeletion` parameter to `useUnlinkProfile` hook and `unlinkProfile` function. When set to `true`, this allows deleting the entire account when unlinking the last profile associated with it.
8+
9+
**React Hook Example:**
10+
11+
```tsx
12+
import { useUnlinkProfile } from "thirdweb/react";
13+
14+
const { mutate: unlinkProfile } = useUnlinkProfile();
15+
16+
const handleUnlink = () => {
17+
unlinkProfile({
18+
client,
19+
profileToUnlink: connectedProfiles[0],
20+
allowAccountDeletion: true, // Delete account if last profile
21+
});
22+
};
23+
```
24+
25+
**Direct Function Example:**
26+
27+
```ts
28+
import { unlinkProfile } from "thirdweb/wallets/in-app";
29+
30+
const updatedProfiles = await unlinkProfile({
31+
client,
32+
profileToUnlink: profiles[0],
33+
allowAccountDeletion: true, // Delete account if last profile
34+
});
35+
```

packages/thirdweb/src/react/native/hooks/wallets/useUnlinkProfile.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ import { useConnectedWallets } from "../../../core/hooks/wallets/useConnectedWal
3131
* };
3232
* ```
3333
*
34+
* ### Unlinking an email account with account deletion
35+
*
36+
* ```jsx
37+
* import { useUnlinkProfile } from "thirdweb/react";
38+
*
39+
* const { mutate: unlinkProfile } = useUnlinkProfile();
40+
*
41+
* const onClick = () => {
42+
* unlinkProfile({
43+
* client,
44+
* // Select the profile you want to unlink
45+
* profileToUnlink: connectedProfiles[0],
46+
* allowAccountDeletion: true, // This will delete the account if it's the last profile linked to the account
47+
* });
48+
* };
49+
* ```
50+
*
3451
* @wallet
3552
*/
3653
export function useUnlinkProfile() {
@@ -40,7 +57,12 @@ export function useUnlinkProfile() {
4057
mutationFn: async ({
4158
client,
4259
profileToUnlink,
43-
}: { client: ThirdwebClient; profileToUnlink: Profile }) => {
60+
allowAccountDeletion = false,
61+
}: {
62+
client: ThirdwebClient;
63+
profileToUnlink: Profile;
64+
allowAccountDeletion?: boolean;
65+
}) => {
4466
const ecosystemWallet = wallets.find((w) => isEcosystemWallet(w));
4567
const ecosystem: Ecosystem | undefined = ecosystemWallet
4668
? {
@@ -53,6 +75,7 @@ export function useUnlinkProfile() {
5375
client,
5476
ecosystem,
5577
profileToUnlink,
78+
allowAccountDeletion,
5679
});
5780
},
5881
onSuccess: () => {

packages/thirdweb/src/react/web/hooks/wallets/useUnlinkProfile.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ import { useConnectedWallets } from "../../../core/hooks/wallets/useConnectedWal
3131
* };
3232
* ```
3333
*
34+
* ### Unlinking an email account with account deletion
35+
*
36+
* ```jsx
37+
* import { useUnlinkProfile } from "thirdweb/react";
38+
*
39+
* const { mutate: unlinkProfile } = useUnlinkProfile();
40+
*
41+
* const onClick = () => {
42+
* unlinkProfile({
43+
* client,
44+
* // Select the profile you want to unlink
45+
* profileToUnlink: connectedProfiles[0],
46+
* allowAccountDeletion: true, // This will delete the account if it's the last profile linked to the account
47+
* });
48+
* };
49+
* ```
50+
*
3451
* @wallet
3552
*/
3653
export function useUnlinkProfile() {
@@ -40,7 +57,12 @@ export function useUnlinkProfile() {
4057
mutationFn: async ({
4158
client,
4259
profileToUnlink,
43-
}: { client: ThirdwebClient; profileToUnlink: Profile }) => {
60+
allowAccountDeletion = false,
61+
}: {
62+
client: ThirdwebClient;
63+
profileToUnlink: Profile;
64+
allowAccountDeletion?: boolean;
65+
}) => {
4466
const ecosystemWallet = wallets.find((w) => isEcosystemWallet(w));
4567
const ecosystem: Ecosystem | undefined = ecosystemWallet
4668
? {
@@ -53,6 +75,7 @@ export function useUnlinkProfile() {
5375
client,
5476
ecosystem,
5577
profileToUnlink,
78+
allowAccountDeletion,
5679
});
5780
},
5881
onSuccess: () => {

packages/thirdweb/src/wallets/in-app/core/authentication/linkAccount.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ describe("Account linking functions", () => {
9090
Authorization: "Bearer iaw-auth-token:mock-token",
9191
"Content-Type": "application/json",
9292
},
93-
body: JSON.stringify(profileToUnlink),
93+
body: JSON.stringify({
94+
type: profileToUnlink.type,
95+
details: profileToUnlink.details,
96+
allowAccountDeletion: false,
97+
}),
9498
},
9599
);
96100
expect(result).toEqual(mockLinkedAccounts);

packages/thirdweb/src/wallets/in-app/core/authentication/linkAccount.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,13 @@ export async function unlinkAccount({
6666
client,
6767
ecosystem,
6868
profileToUnlink,
69+
allowAccountDeletion = false,
6970
storage,
7071
}: {
7172
client: ThirdwebClient;
7273
ecosystem?: Ecosystem;
7374
profileToUnlink: Profile;
75+
allowAccountDeletion?: boolean;
7476
storage: ClientScopedStorage;
7577
}): Promise<Profile[]> {
7678
const clientFetch = getClientFetch(client, ecosystem);
@@ -90,7 +92,11 @@ export async function unlinkAccount({
9092
{
9193
method: "POST",
9294
headers,
93-
body: stringify(profileToUnlink),
95+
body: stringify({
96+
type: profileToUnlink.type,
97+
details: profileToUnlink.details,
98+
allowAccountDeletion,
99+
}),
94100
},
95101
);
96102

packages/thirdweb/src/wallets/in-app/core/authentication/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,5 @@ export type UnlinkParams = {
259259
client: ThirdwebClient;
260260
ecosystem?: Ecosystem;
261261
profileToUnlink: Profile;
262+
allowAccountDeletion?: boolean;
262263
};

packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ export interface InAppConnector {
3737
): Promise<AuthLoginReturnType>;
3838
logout(): Promise<LogoutReturnType>;
3939
linkProfile(args: AuthArgsType): Promise<Profile[]>;
40-
unlinkProfile(args: Profile): Promise<Profile[]>;
40+
unlinkProfile(
41+
args: Profile,
42+
allowAccountDeletion?: boolean,
43+
): Promise<Profile[]>;
4144
getProfiles(): Promise<Profile[]>;
4245
storage: ClientScopedStorage;
4346
}

packages/thirdweb/src/wallets/in-app/native/auth/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,10 @@ export async function linkProfile(args: AuthArgsType) {
203203
*/
204204
export async function unlinkProfile(args: UnlinkParams) {
205205
const connector = await getInAppWalletConnector(args.client, args.ecosystem);
206-
return await connector.unlinkProfile(args.profileToUnlink);
206+
return await connector.unlinkProfile(
207+
args.profileToUnlink,
208+
args.allowAccountDeletion,
209+
);
207210
}
208211

209212
/**

packages/thirdweb/src/wallets/in-app/native/native-connector.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ export class InAppNativeConnector implements InAppConnector {
367367
});
368368
}
369369

370-
async unlinkProfile(profile: Profile) {
370+
async unlinkProfile(profile: Profile, allowAccountDeletion?: boolean) {
371371
const { unlinkAccount } = await import(
372372
"../core/authentication/linkAccount.js"
373373
);
@@ -376,6 +376,7 @@ export class InAppNativeConnector implements InAppConnector {
376376
ecosystem: this.ecosystem,
377377
storage: this.storage,
378378
profileToUnlink: profile,
379+
allowAccountDeletion,
379380
});
380381
}
381382

packages/thirdweb/src/wallets/in-app/web/lib/auth/index.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ export async function linkProfile(args: AuthArgsType) {
224224
* @throws If the unlinking fails. This can happen if the account has no other associated profiles or if the profile that is being unlinked doesn't exists for the current logged in user.
225225
*
226226
* @example
227+
* ### Unlinking an authentication method
228+
*
227229
* ```ts
228230
* import { inAppWallet } from "thirdweb/wallets";
229231
*
@@ -239,11 +241,41 @@ export async function linkProfile(args: AuthArgsType) {
239241
* profileToUnlink: profiles[0],
240242
* });
241243
* ```
244+
*
245+
* ### Unlinking an authentication for ecosystems
246+
*
247+
* ```ts
248+
* import { unlinkProfile } from "thirdweb/wallets/in-app";
249+
*
250+
* const updatedProfiles = await unlinkProfile({
251+
* client,
252+
* ecosystem: {
253+
* id: "ecosystem.your-ecosystem-id",
254+
* },
255+
* profileToUnlink: profiles[0],
256+
* });
257+
* ```
258+
*
259+
* ### Unlinking an authentication method with account deletion
260+
*
261+
* ```ts
262+
* import { unlinkProfile } from "thirdweb/wallets/in-app";
263+
*
264+
* const updatedProfiles = await unlinkProfile({
265+
* client,
266+
* profileToUnlink: profiles[0],
267+
* allowAccountDeletion: true, // This will delete the account if it's the last profile linked to the account
268+
* });
269+
* ```
270+
*
242271
* @wallet
243272
*/
244273
export async function unlinkProfile(args: UnlinkParams) {
245274
const connector = await getInAppWalletConnector(args.client, args.ecosystem);
246-
return await connector.unlinkProfile(args.profileToUnlink);
275+
return await connector.unlinkProfile(
276+
args.profileToUnlink,
277+
args.allowAccountDeletion,
278+
);
247279
}
248280

249281
/**

0 commit comments

Comments
 (0)