From 68ad62f1d5c319392a7598d747a1400341bcc170 Mon Sep 17 00:00:00 2001 From: ElasticBottle Date: Wed, 4 Dec 2024 02:01:50 +0000 Subject: [PATCH] [SDK] Fix: Type `wallet` doesn't exists in `getUser` (#5593) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://linear.app/thirdweb/issue/CNCT-2523/remapping-of-siwe-wallet-type-in-typescript-sdk --- ## PR-Codex overview This PR focuses on updating the `getUser` function in the `Profiles` to align with TypeScript types and enhancing its test coverage. ### Detailed summary - Updated the `type` in `getUser` to correctly classify profile types as either "wallet" or their original type. - Added unit tests to handle various scenarios: missing secret key, missing query parameters, and handling fetch errors. - Verified correct API URL calls for different query parameters (email, phone, id, externalWalletAddress). - Included tests for fetching user profiles and handling cases where no user is found. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` --- .changeset/curly-ligers-exist.md | 5 + .../wallets/in-app/core/users/getUser.test.ts | 216 ++++++++++++++++++ .../src/wallets/in-app/core/users/getUser.ts | 7 +- 3 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 .changeset/curly-ligers-exist.md create mode 100644 packages/thirdweb/src/wallets/in-app/core/users/getUser.test.ts diff --git a/.changeset/curly-ligers-exist.md b/.changeset/curly-ligers-exist.md new file mode 100644 index 00000000000..d9d64cf50da --- /dev/null +++ b/.changeset/curly-ligers-exist.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +update `type` in `getUser` `Profiles` to match tyepscript types diff --git a/packages/thirdweb/src/wallets/in-app/core/users/getUser.test.ts b/packages/thirdweb/src/wallets/in-app/core/users/getUser.test.ts new file mode 100644 index 00000000000..fe58598acb4 --- /dev/null +++ b/packages/thirdweb/src/wallets/in-app/core/users/getUser.test.ts @@ -0,0 +1,216 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { createThirdwebClient } from "../../../../client/client.js"; +import { getClientFetch } from "../../../../utils/fetch.js"; +import { getUser } from "./getUser.js"; + +vi.mock("../../../../utils/fetch.js", () => ({ + getClientFetch: vi.fn(), +})); + +describe("getUser", () => { + const mockClient = createThirdwebClient({ + secretKey: "secret", + }); + + const mockFetch = vi.fn(); + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(getClientFetch).mockReturnValue(mockFetch); + }); + + it("should throw an error if no secret key is provided", async () => { + await expect( + getUser({ + client: { ...mockClient, secretKey: undefined }, + walletAddress: "0x123", + }), + ).rejects.toThrow( + "A secret key is required to query for users. If you're making this request from the server, please add a secret key to your client.", + ); + }); + + it("should throw an error if no query parameter is provided", async () => { + await expect( + getUser({ + client: mockClient, + }), + ).rejects.toThrow( + "Please provide a walletAddress, email, phone, id, or externalWalletAddress to query for users.", + ); + }); + + it("should call the correct URL with email", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => [ + { + userId: "user1", + walletAddress: "0x123", + email: "test@test.com", + createdAt: "2023-01-01T00:00:00Z", + linkedAccounts: [], + }, + ], + }); + + const result = await getUser({ + client: mockClient, + email: "test@test.com", + }); + + expect(mockFetch).toHaveBeenCalledWith( + "https://embedded-wallet.thirdweb.com/api/2023-11-30/embedded-wallet/user-details?queryBy=email&email=test%40test.com", + ); + expect(result).toEqual({ + userId: "user1", + walletAddress: "0x123", + email: "test@test.com", + createdAt: "2023-01-01T00:00:00Z", + profiles: [], + }); + }); + + it("should call the correct URL with phone", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => [ + { + userId: "user1", + walletAddress: "0x123", + phone: "+1234567890", + createdAt: "2023-01-01T00:00:00Z", + linkedAccounts: [], + }, + ], + }); + + const result = await getUser({ + client: mockClient, + phone: "+1234567890", + }); + + expect(mockFetch).toHaveBeenCalledWith( + "https://embedded-wallet.thirdweb.com/api/2023-11-30/embedded-wallet/user-details?queryBy=phone&phone=%2B1234567890", + ); + expect(result).toEqual({ + userId: "user1", + walletAddress: "0x123", + phone: "+1234567890", + createdAt: "2023-01-01T00:00:00Z", + profiles: [], + }); + }); + + it("should call the correct URL with id", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => [ + { + userId: "user1", + walletAddress: "0x123", + createdAt: "2023-01-01T00:00:00Z", + linkedAccounts: [ + { + type: "id", + details: { + id: "0x456", + }, + }, + ], + }, + ], + }); + + const result = await getUser({ + client: mockClient, + id: "user1", + }); + + expect(mockFetch).toHaveBeenCalledWith( + "https://embedded-wallet.thirdweb.com/api/2023-11-30/embedded-wallet/user-details?queryBy=id&id=user1", + ); + expect(result).toEqual({ + userId: "user1", + walletAddress: "0x123", + createdAt: "2023-01-01T00:00:00Z", + profiles: [ + { + type: "id", + details: { + id: "0x456", + }, + }, + ], + }); + }); + + it("should call the correct URL with externalWalletAddress", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => [ + { + userId: "user1", + walletAddress: "0x123", + createdAt: "2023-01-01T00:00:00Z", + linkedAccounts: [ + { + type: "siwe", + details: { + address: "0x456", + }, + }, + ], + }, + ], + }); + + const result = await getUser({ + client: mockClient, + externalWalletAddress: "0x456", + }); + + expect(mockFetch).toHaveBeenCalledWith( + "https://embedded-wallet.thirdweb.com/api/2023-11-30/embedded-wallet/user-details?queryBy=externalWalletAddress&externalWalletAddress=0x456", + ); + expect(result).toEqual({ + userId: "user1", + walletAddress: "0x123", + createdAt: "2023-01-01T00:00:00Z", + profiles: [ + { + type: "wallet", + details: { + address: "0x456", + }, + }, + ], + }); + }); + + it("should handle fetch errors", async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + }); + + await expect( + getUser({ + client: mockClient, + walletAddress: "0x123", + }), + ).rejects.toThrow("Failed to get profiles"); + }); + + it("should return null if no user is found", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => [], + }); + + const result = await getUser({ + client: mockClient, + walletAddress: "0x123", + }); + + expect(result).toBeNull(); + }); +}); diff --git a/packages/thirdweb/src/wallets/in-app/core/users/getUser.ts b/packages/thirdweb/src/wallets/in-app/core/users/getUser.ts index 3296897f183..3ebce686836 100644 --- a/packages/thirdweb/src/wallets/in-app/core/users/getUser.ts +++ b/packages/thirdweb/src/wallets/in-app/core/users/getUser.ts @@ -113,7 +113,12 @@ export async function getUser({ email: item.email, phone: item.phone, createdAt: item.createdAt, - profiles: item.linkedAccounts, + profiles: item.linkedAccounts.map((profile) => { + return { + type: (profile.type as string) === "siwe" ? "wallet" : profile.type, + details: profile.details, + }; + }), }))[0] || null ); }