thirdweb 5.105.21 → 5.105.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/cjs/extensions/erc1155/read/getOwnedNFTs.js +1 -0
  2. package/dist/cjs/extensions/erc1155/read/getOwnedNFTs.js.map +1 -1
  3. package/dist/cjs/extensions/erc721/read/getOwnedNFTs.js +1 -0
  4. package/dist/cjs/extensions/erc721/read/getOwnedNFTs.js.map +1 -1
  5. package/dist/cjs/insight/get-nfts.js +3 -3
  6. package/dist/cjs/insight/get-nfts.js.map +1 -1
  7. package/dist/cjs/insight/get-tokens.js +3 -2
  8. package/dist/cjs/insight/get-tokens.js.map +1 -1
  9. package/dist/cjs/react/web/wallets/shared/WalletConnectConnection.js +7 -33
  10. package/dist/cjs/react/web/wallets/shared/WalletConnectConnection.js.map +1 -1
  11. package/dist/cjs/transaction/actions/estimate-gas.js +3 -24
  12. package/dist/cjs/transaction/actions/estimate-gas.js.map +1 -1
  13. package/dist/cjs/utils/web/isMobile.js +0 -2
  14. package/dist/cjs/utils/web/isMobile.js.map +1 -1
  15. package/dist/cjs/version.js +1 -1
  16. package/dist/cjs/wallets/coinbase/coinbase-web.js +56 -0
  17. package/dist/cjs/wallets/coinbase/coinbase-web.js.map +1 -1
  18. package/dist/cjs/wallets/create-wallet.js +21 -4
  19. package/dist/cjs/wallets/create-wallet.js.map +1 -1
  20. package/dist/cjs/wallets/eip5792/get-calls-status.js +40 -63
  21. package/dist/cjs/wallets/eip5792/get-calls-status.js.map +1 -1
  22. package/dist/cjs/wallets/eip5792/get-capabilities.js +14 -49
  23. package/dist/cjs/wallets/eip5792/get-capabilities.js.map +1 -1
  24. package/dist/cjs/wallets/eip5792/send-calls.js +34 -48
  25. package/dist/cjs/wallets/eip5792/send-calls.js.map +1 -1
  26. package/dist/cjs/wallets/in-app/core/{eip5972 → eip5792}/in-app-wallet-calls.js +1 -5
  27. package/dist/cjs/wallets/in-app/core/eip5792/in-app-wallet-calls.js.map +1 -0
  28. package/dist/cjs/wallets/in-app/core/eip7702/minimal-account.js +650 -5
  29. package/dist/cjs/wallets/in-app/core/eip7702/minimal-account.js.map +1 -1
  30. package/dist/cjs/wallets/in-app/core/wallet/enclave-wallet.js +32 -1
  31. package/dist/cjs/wallets/in-app/core/wallet/enclave-wallet.js.map +1 -1
  32. package/dist/cjs/wallets/injected/index.js +55 -0
  33. package/dist/cjs/wallets/injected/index.js.map +1 -1
  34. package/dist/cjs/wallets/smart/index.js +61 -0
  35. package/dist/cjs/wallets/smart/index.js.map +1 -1
  36. package/dist/cjs/wallets/wallet-connect/controller.js +27 -25
  37. package/dist/cjs/wallets/wallet-connect/controller.js.map +1 -1
  38. package/dist/esm/extensions/erc1155/read/getOwnedNFTs.js +1 -0
  39. package/dist/esm/extensions/erc1155/read/getOwnedNFTs.js.map +1 -1
  40. package/dist/esm/extensions/erc721/read/getOwnedNFTs.js +1 -0
  41. package/dist/esm/extensions/erc721/read/getOwnedNFTs.js.map +1 -1
  42. package/dist/esm/insight/get-nfts.js +3 -3
  43. package/dist/esm/insight/get-nfts.js.map +1 -1
  44. package/dist/esm/insight/get-tokens.js +3 -2
  45. package/dist/esm/insight/get-tokens.js.map +1 -1
  46. package/dist/esm/react/web/wallets/shared/WalletConnectConnection.js +8 -34
  47. package/dist/esm/react/web/wallets/shared/WalletConnectConnection.js.map +1 -1
  48. package/dist/esm/transaction/actions/estimate-gas.js +3 -24
  49. package/dist/esm/transaction/actions/estimate-gas.js.map +1 -1
  50. package/dist/esm/utils/web/isMobile.js +2 -2
  51. package/dist/esm/utils/web/isMobile.js.map +1 -1
  52. package/dist/esm/version.js +1 -1
  53. package/dist/esm/wallets/coinbase/coinbase-web.js +56 -0
  54. package/dist/esm/wallets/coinbase/coinbase-web.js.map +1 -1
  55. package/dist/esm/wallets/create-wallet.js +21 -4
  56. package/dist/esm/wallets/create-wallet.js.map +1 -1
  57. package/dist/esm/wallets/eip5792/get-calls-status.js +39 -63
  58. package/dist/esm/wallets/eip5792/get-calls-status.js.map +1 -1
  59. package/dist/esm/wallets/eip5792/get-capabilities.js +13 -49
  60. package/dist/esm/wallets/eip5792/get-capabilities.js.map +1 -1
  61. package/dist/esm/wallets/eip5792/send-calls.js +33 -48
  62. package/dist/esm/wallets/eip5792/send-calls.js.map +1 -1
  63. package/dist/esm/wallets/in-app/core/{eip5972 → eip5792}/in-app-wallet-calls.js +1 -5
  64. package/dist/esm/wallets/in-app/core/eip5792/in-app-wallet-calls.js.map +1 -0
  65. package/dist/esm/wallets/in-app/core/eip7702/minimal-account.js +650 -5
  66. package/dist/esm/wallets/in-app/core/eip7702/minimal-account.js.map +1 -1
  67. package/dist/esm/wallets/in-app/core/wallet/enclave-wallet.js +32 -1
  68. package/dist/esm/wallets/in-app/core/wallet/enclave-wallet.js.map +1 -1
  69. package/dist/esm/wallets/injected/index.js +56 -1
  70. package/dist/esm/wallets/injected/index.js.map +1 -1
  71. package/dist/esm/wallets/smart/index.js +61 -0
  72. package/dist/esm/wallets/smart/index.js.map +1 -1
  73. package/dist/esm/wallets/wallet-connect/controller.js +27 -25
  74. package/dist/esm/wallets/wallet-connect/controller.js.map +1 -1
  75. package/dist/types/bridge/Webhook.d.ts +2 -2
  76. package/dist/types/insight/get-nfts.d.ts +1 -0
  77. package/dist/types/insight/get-nfts.d.ts.map +1 -1
  78. package/dist/types/insight/get-tokens.d.ts +1 -0
  79. package/dist/types/insight/get-tokens.d.ts.map +1 -1
  80. package/dist/types/react/core/hooks/wallets/useWaitForCallsReceipt.d.ts +1 -1
  81. package/dist/types/react/core/utils/storage.d.ts +1 -1
  82. package/dist/types/react/web/utils/storage.d.ts +1 -1
  83. package/dist/types/react/web/wallets/shared/WalletConnectConnection.d.ts.map +1 -1
  84. package/dist/types/transaction/actions/estimate-gas.d.ts.map +1 -1
  85. package/dist/types/utils/web/isMobile.d.ts +0 -8
  86. package/dist/types/utils/web/isMobile.d.ts.map +1 -1
  87. package/dist/types/version.d.ts +1 -1
  88. package/dist/types/wallets/coinbase/coinbase-web.d.ts.map +1 -1
  89. package/dist/types/wallets/create-wallet.d.ts.map +1 -1
  90. package/dist/types/wallets/eip5792/get-calls-status.d.ts +2 -1
  91. package/dist/types/wallets/eip5792/get-calls-status.d.ts.map +1 -1
  92. package/dist/types/wallets/eip5792/get-capabilities.d.ts +1 -0
  93. package/dist/types/wallets/eip5792/get-capabilities.d.ts.map +1 -1
  94. package/dist/types/wallets/eip5792/send-calls.d.ts +6 -1
  95. package/dist/types/wallets/eip5792/send-calls.d.ts.map +1 -1
  96. package/dist/types/wallets/in-app/core/{eip5972 → eip5792}/in-app-wallet-calls.d.ts +3 -2
  97. package/dist/types/wallets/in-app/core/eip5792/in-app-wallet-calls.d.ts.map +1 -0
  98. package/dist/types/wallets/in-app/core/eip7702/minimal-account.d.ts.map +1 -1
  99. package/dist/types/wallets/in-app/core/wallet/enclave-wallet.d.ts.map +1 -1
  100. package/dist/types/wallets/injected/index.d.ts.map +1 -1
  101. package/dist/types/wallets/interfaces/wallet.d.ts +22 -0
  102. package/dist/types/wallets/interfaces/wallet.d.ts.map +1 -1
  103. package/dist/types/wallets/smart/index.d.ts.map +1 -1
  104. package/dist/types/wallets/wallet-connect/controller.d.ts.map +1 -1
  105. package/package.json +3 -3
  106. package/src/extensions/erc1155/read/getOwnedNFTs.ts +1 -0
  107. package/src/extensions/erc721/read/getOwnedNFTs.ts +1 -0
  108. package/src/insight/get-nfts.ts +4 -3
  109. package/src/insight/get-tokens.ts +4 -2
  110. package/src/react/web/wallets/shared/WalletConnectConnection.tsx +11 -46
  111. package/src/transaction/actions/estimate-gas.ts +14 -42
  112. package/src/utils/web/isMobile.ts +2 -2
  113. package/src/version.ts +1 -1
  114. package/src/wallets/coinbase/coinbase-web.ts +66 -0
  115. package/src/wallets/create-wallet.ts +53 -31
  116. package/src/wallets/eip5792/get-calls-status.test.ts +156 -146
  117. package/src/wallets/eip5792/get-calls-status.ts +44 -73
  118. package/src/wallets/eip5792/get-capabilities.test.ts +216 -205
  119. package/src/wallets/eip5792/get-capabilities.ts +23 -64
  120. package/src/wallets/eip5792/send-calls.test.ts +183 -189
  121. package/src/wallets/eip5792/send-calls.ts +53 -71
  122. package/src/wallets/in-app/core/{eip5972 → eip5792}/in-app-wallet-calls.ts +4 -8
  123. package/src/wallets/in-app/core/eip7702/minimal-account.ts +666 -5
  124. package/src/wallets/in-app/core/wallet/enclave-wallet.ts +36 -1
  125. package/src/wallets/injected/index.ts +63 -0
  126. package/src/wallets/interfaces/wallet.ts +31 -0
  127. package/src/wallets/smart/index.ts +69 -1
  128. package/src/wallets/wallet-connect/controller.ts +28 -25
  129. package/dist/cjs/wallets/in-app/core/eip5972/in-app-wallet-calls.js.map +0 -1
  130. package/dist/cjs/wallets/in-app/core/eip5972/in-app-wallet-capabilities.js +0 -41
  131. package/dist/cjs/wallets/in-app/core/eip5972/in-app-wallet-capabilities.js.map +0 -1
  132. package/dist/cjs/wallets/smart/lib/smart-wallet-capabilities.js +0 -30
  133. package/dist/cjs/wallets/smart/lib/smart-wallet-capabilities.js.map +0 -1
  134. package/dist/esm/wallets/in-app/core/eip5972/in-app-wallet-calls.js.map +0 -1
  135. package/dist/esm/wallets/in-app/core/eip5972/in-app-wallet-capabilities.js +0 -38
  136. package/dist/esm/wallets/in-app/core/eip5972/in-app-wallet-capabilities.js.map +0 -1
  137. package/dist/esm/wallets/smart/lib/smart-wallet-capabilities.js +0 -27
  138. package/dist/esm/wallets/smart/lib/smart-wallet-capabilities.js.map +0 -1
  139. package/dist/types/wallets/in-app/core/eip5972/in-app-wallet-calls.d.ts.map +0 -1
  140. package/dist/types/wallets/in-app/core/eip5972/in-app-wallet-capabilities.d.ts +0 -20
  141. package/dist/types/wallets/in-app/core/eip5972/in-app-wallet-capabilities.d.ts.map +0 -1
  142. package/dist/types/wallets/smart/lib/smart-wallet-capabilities.d.ts +0 -20
  143. package/dist/types/wallets/smart/lib/smart-wallet-capabilities.d.ts.map +0 -1
  144. package/src/wallets/in-app/core/eip5972/in-app-wallet-capabilities.ts +0 -47
  145. package/src/wallets/smart/lib/smart-wallet-capabilities.ts +0 -32
@@ -1,12 +1,6 @@
1
1
  import type { ThirdwebClient } from "../../client/client.js";
2
2
  import { hexToBigInt, hexToNumber } from "../../utils/encoding/hex.js";
3
- import { isCoinbaseSDKWallet } from "../coinbase/coinbase-web.js";
4
- import { isInAppWallet } from "../in-app/core/wallet/index.js";
5
- import { getInjectedProvider } from "../injected/index.js";
6
- import type { Ethereum } from "../interfaces/ethereum.js";
7
3
  import type { Wallet } from "../interfaces/wallet.js";
8
- import { isSmartWallet } from "../smart/index.js";
9
- import { isWalletConnect } from "../wallet-connect/controller.js";
10
4
  import type {
11
5
  GetCallsStatusRawResponse,
12
6
  GetCallsStatusResponse,
@@ -59,81 +53,58 @@ export async function getCallsStatus({
59
53
  );
60
54
  }
61
55
 
62
- // These conveniently operate the same
63
- if (isSmartWallet(wallet) || isInAppWallet(wallet)) {
64
- const { inAppWalletGetCallsStatus } = await import(
65
- "../in-app/core/eip5972/in-app-wallet-calls.js"
56
+ const chain = wallet.getChain();
57
+ if (!chain) {
58
+ throw new Error(
59
+ `Failed to get call status, no chain found for wallet ${wallet.id}`,
66
60
  );
67
- return inAppWalletGetCallsStatus({ client, id, wallet });
68
- }
69
-
70
- if (isWalletConnect(wallet)) {
71
- throw new Error("getCallsStatus is not yet supported for Wallet Connect");
72
61
  }
73
62
 
74
- let provider: Ethereum;
75
- if (isCoinbaseSDKWallet(wallet)) {
76
- const { getCoinbaseWebProvider } = await import(
77
- "../coinbase/coinbase-web.js"
78
- );
79
- const config = wallet.getConfig();
80
- provider = (await getCoinbaseWebProvider(config)) as Ethereum;
81
- } else {
82
- provider = getInjectedProvider(wallet.id);
63
+ if (account.getCallsStatus) {
64
+ return account.getCallsStatus({ id, chain, client });
83
65
  }
84
66
 
85
- try {
86
- const {
87
- atomic = false,
88
- chainId,
89
- receipts,
90
- version = "2.0.0",
91
- ...response
92
- } = (await provider.request({
93
- method: "wallet_getCallsStatus",
94
- params: [id],
95
- })) as GetCallsStatusRawResponse;
96
- const [status, statusCode] = (() => {
97
- const statusCode = response.status;
98
- if (statusCode >= 100 && statusCode < 200)
99
- return ["pending", statusCode] as const;
100
- if (statusCode >= 200 && statusCode < 300)
101
- return ["success", statusCode] as const;
102
- if (statusCode >= 300 && statusCode < 700)
103
- return ["failure", statusCode] as const;
104
- // @ts-expect-error: for backwards compatibility
105
- if (statusCode === "CONFIRMED") return ["success", 200] as const;
106
- // @ts-expect-error: for backwards compatibility
107
- if (statusCode === "PENDING") return ["pending", 100] as const;
108
- return [undefined, statusCode];
109
- })();
110
- return {
111
- ...response,
112
- atomic,
113
- // @ts-expect-error: for backwards compatibility
114
- chainId: chainId ? hexToNumber(chainId) : undefined,
115
- receipts:
116
- receipts?.map((receipt) => ({
117
- ...receipt,
118
- blockNumber: hexToBigInt(receipt.blockNumber),
119
- gasUsed: hexToBigInt(receipt.gasUsed),
120
- status: receiptStatuses[receipt.status as "0x0" | "0x1"],
121
- })) ?? [],
122
- status,
123
- statusCode,
124
- version,
125
- };
126
- } catch (error) {
127
- if (/unsupport|not support/i.test((error as Error).message)) {
128
- throw new Error(
129
- `${wallet.id} does not support wallet_getCallsStatus, reach out to them directly to request EIP-5792 support.`,
130
- );
131
- }
132
- throw error;
133
- }
67
+ throw new Error(
68
+ `Failed to get call status, wallet ${wallet.id} does not support EIP-5792`,
69
+ );
134
70
  }
135
71
 
136
72
  const receiptStatuses = {
137
73
  "0x0": "reverted",
138
74
  "0x1": "success",
139
75
  } as const;
76
+
77
+ export function toGetCallsStatusResponse(
78
+ response: GetCallsStatusRawResponse,
79
+ ): GetCallsStatusResponse {
80
+ const [status, statusCode] = (() => {
81
+ const statusCode = response.status;
82
+ if (statusCode >= 100 && statusCode < 200)
83
+ return ["pending", statusCode] as const;
84
+ if (statusCode >= 200 && statusCode < 300)
85
+ return ["success", statusCode] as const;
86
+ if (statusCode >= 300 && statusCode < 700)
87
+ return ["failure", statusCode] as const;
88
+ // @ts-expect-error: for backwards compatibility
89
+ if (statusCode === "CONFIRMED") return ["success", 200] as const;
90
+ // @ts-expect-error: for backwards compatibility
91
+ if (statusCode === "PENDING") return ["pending", 100] as const;
92
+ return [undefined, statusCode];
93
+ })();
94
+ return {
95
+ ...response,
96
+ atomic: response.atomic,
97
+ // @ts-expect-error: for backwards compatibility
98
+ chainId: response.chainId ? hexToNumber(response.chainId) : undefined,
99
+ receipts:
100
+ response.receipts?.map((receipt) => ({
101
+ ...receipt,
102
+ blockNumber: hexToBigInt(receipt.blockNumber),
103
+ gasUsed: hexToBigInt(receipt.gasUsed),
104
+ status: receiptStatuses[receipt.status as "0x0" | "0x1"],
105
+ })) ?? [],
106
+ status,
107
+ statusCode,
108
+ version: response.version,
109
+ };
110
+ }
@@ -1,261 +1,242 @@
1
- import { afterEach, beforeAll, describe, expect, it, test, vi } from "vitest";
2
- import {
3
- ANVIL_CHAIN,
4
- FORKED_ETHEREUM_CHAIN,
5
- } from "../../../test/src/chains.js";
1
+ import { afterEach, describe, expect, test, vi } from "vitest";
2
+ import { ANVIL_CHAIN } from "../../../test/src/chains.js";
6
3
  import { TEST_ACCOUNT_A } from "../../../test/src/test-wallets.js";
7
4
  import { METAMASK } from "../constants.js";
8
5
  import { createWallet } from "../create-wallet.js";
9
6
  import type { Wallet } from "../interfaces/wallet.js";
10
- import { getCapabilities } from "./get-capabilities.js";
11
-
12
- const SUPPORTED_RESPONSE = {
13
- 1: {
14
- paymasterService: {
15
- supported: true,
16
- },
17
- sessionKeys: {
18
- supported: true,
19
- },
20
- },
21
- };
22
-
23
- const RAW_UNSUPPORTED_ERROR = {
24
- code: -32601,
25
- message: "some nonsense the wallet sends us about not supporting",
26
- };
27
-
28
- const UNSUPPORTED_RESPONSE_STRING = "does not support wallet_getCapabilities";
7
+ import {
8
+ type GetCapabilitiesOptions,
9
+ getCapabilities,
10
+ } from "./get-capabilities.js";
29
11
 
30
12
  const mocks = vi.hoisted(() => ({
31
- injectedRequest: vi.fn(),
13
+ getCapabilities: vi.fn(),
32
14
  }));
33
15
 
34
- vi.mock("../injected/index.js", () => {
35
- return {
36
- getInjectedProvider: vi.fn().mockReturnValue({
37
- request: mocks.injectedRequest,
38
- }),
39
- };
40
- });
41
-
42
- describe.sequential("injected wallet", async () => {
16
+ describe.sequential("getCapabilities general", () => {
43
17
  const wallet: Wallet = createWallet(METAMASK);
44
- describe.sequential("supported", () => {
45
- beforeAll(() => {
46
- mocks.injectedRequest.mockResolvedValue(SUPPORTED_RESPONSE);
47
- });
48
-
49
- afterEach(() => {
50
- mocks.injectedRequest.mockClear();
51
- });
52
18
 
53
- test("without account should return no capabilities", async () => {
54
- wallet.getAccount = vi.fn().mockReturnValue(undefined);
19
+ afterEach(() => {
20
+ vi.clearAllMocks();
21
+ });
55
22
 
56
- const capabilities = await getCapabilities({
57
- wallet,
58
- });
23
+ test("without account should return message", async () => {
24
+ wallet.getAccount = vi.fn().mockReturnValue(undefined);
59
25
 
60
- expect(mocks.injectedRequest).not.toHaveBeenCalled();
61
- expect(capabilities).toEqual({
62
- message:
63
- "Can't get capabilities, no account connected for wallet: io.metamask",
64
- });
26
+ const capabilities = await getCapabilities({
27
+ wallet,
65
28
  });
66
29
 
67
- test("with account should return capabilities", async () => {
68
- wallet.getAccount = vi.fn().mockReturnValue(TEST_ACCOUNT_A);
69
-
70
- const capabilities = await getCapabilities({
71
- wallet,
72
- });
73
-
74
- expect(mocks.injectedRequest).toHaveBeenCalledWith({
75
- method: "wallet_getCapabilities",
76
- params: [TEST_ACCOUNT_A.address],
77
- });
78
- expect(capabilities).toEqual(SUPPORTED_RESPONSE);
30
+ expect(capabilities).toEqual({
31
+ message:
32
+ "Can't get capabilities, no account connected for wallet: io.metamask",
79
33
  });
80
34
  });
81
35
 
82
- describe("unsupported", () => {
83
- beforeAll(() => {
84
- mocks.injectedRequest.mockRejectedValue(RAW_UNSUPPORTED_ERROR);
36
+ test("without getCapabilities support should fail", async () => {
37
+ wallet.getAccount = vi.fn().mockReturnValue({
38
+ ...TEST_ACCOUNT_A,
39
+ // no getCapabilities method
85
40
  });
86
41
 
87
- afterEach(() => {
88
- mocks.injectedRequest.mockClear();
42
+ const promise = getCapabilities({
43
+ wallet,
89
44
  });
90
45
 
91
- it("should return clean unsupported response", async () => {
92
- wallet.getAccount = vi.fn().mockReturnValue(TEST_ACCOUNT_A);
93
- wallet.getChain = vi.fn().mockReturnValue(ANVIL_CHAIN);
94
- const capabilities = await getCapabilities({
95
- wallet,
96
- });
97
-
98
- expect(mocks.injectedRequest).toHaveBeenCalledWith({
99
- method: "wallet_getCapabilities",
100
- params: [TEST_ACCOUNT_A.address],
101
- });
102
- if ("message" in capabilities) {
103
- expect(capabilities.message).toContain(UNSUPPORTED_RESPONSE_STRING);
104
- } else {
105
- throw new Error("capabilities does not contain message");
106
- }
107
- });
46
+ await expect(promise).rejects.toMatchInlineSnapshot(
47
+ "[Error: Failed to get capabilities, wallet io.metamask does not support EIP-5792]",
48
+ );
108
49
  });
109
- });
110
50
 
111
- describe.sequential("in-app wallet", async () => {
112
- let wallet: Wallet = createWallet("inApp");
51
+ test("should delegate to account.getCapabilities", async () => {
52
+ const mockResponse = {
53
+ [ANVIL_CHAIN.id]: {
54
+ paymasterService: {
55
+ supported: true,
56
+ },
57
+ sessionKeys: {
58
+ supported: true,
59
+ },
60
+ },
61
+ };
113
62
 
114
- test("should return no support", async () => {
115
- wallet.getChain = vi.fn().mockReturnValue(ANVIL_CHAIN);
116
- wallet.getAccount = vi.fn().mockReturnValue(TEST_ACCOUNT_A);
63
+ const mockAccount = {
64
+ ...TEST_ACCOUNT_A,
65
+ getCapabilities: mocks.getCapabilities.mockResolvedValue(mockResponse),
66
+ };
117
67
 
118
- const capabilities = await getCapabilities({
68
+ wallet.getAccount = vi.fn().mockReturnValue(mockAccount);
69
+
70
+ const result = await getCapabilities({
119
71
  wallet,
120
72
  });
121
73
 
122
- expect(capabilities).toEqual({
123
- [ANVIL_CHAIN.id]: {
124
- atomic: {
125
- status: "unsupported",
126
- },
127
- paymasterService: {
128
- supported: false,
129
- },
130
- },
74
+ expect(result).toEqual(mockResponse);
75
+ expect(mocks.getCapabilities).toHaveBeenCalledWith({
76
+ chainId: undefined,
131
77
  });
132
78
  });
133
79
 
134
- test("with no account should return no capabilities", async () => {
135
- wallet.getAccount = vi.fn().mockReturnValue(undefined);
80
+ test("should delegate to account.getCapabilities with chainId", async () => {
81
+ const mockResponse = {
82
+ paymasterService: {
83
+ supported: true,
84
+ },
85
+ sessionKeys: {
86
+ supported: true,
87
+ },
88
+ };
136
89
 
137
- const capabilities = await getCapabilities({
90
+ const mockAccount = {
91
+ ...TEST_ACCOUNT_A,
92
+ getCapabilities: mocks.getCapabilities.mockResolvedValue(mockResponse),
93
+ };
94
+
95
+ wallet.getAccount = vi.fn().mockReturnValue(mockAccount);
96
+
97
+ const result = await getCapabilities({
138
98
  wallet,
99
+ chainId: ANVIL_CHAIN.id,
139
100
  });
140
101
 
141
- expect(capabilities).toEqual({
142
- message: "Can't get capabilities, no account connected for wallet: inApp",
102
+ expect(result).toEqual(mockResponse);
103
+ expect(mocks.getCapabilities).toHaveBeenCalledWith({
104
+ chainId: ANVIL_CHAIN.id,
143
105
  });
144
106
  });
107
+ });
145
108
 
146
- describe.sequential("with smart account", async () => {
147
- test("with sponsorGas should support paymasterService and atomicBatch", async () => {
148
- wallet = createWallet("inApp", {
149
- smartAccount: {
150
- chain: ANVIL_CHAIN,
151
- sponsorGas: true,
152
- },
153
- });
154
-
155
- wallet.getAccount = vi.fn().mockReturnValue({
156
- ...TEST_ACCOUNT_A,
157
- sendBatchTransaction: vi.fn(),
158
- });
159
- wallet.getChain = vi.fn().mockReturnValue(ANVIL_CHAIN);
160
-
161
- const capabilities = await getCapabilities({
162
- wallet,
163
- });
109
+ describe.sequential("injected wallet account.getCapabilities", () => {
110
+ // These tests verify the behavior of the getCapabilities method on injected wallet accounts
111
+ // The actual implementation would be in packages/thirdweb/src/wallets/injected/index.ts
164
112
 
165
- expect(capabilities).toEqual({
113
+ test("should handle successful getCapabilities", async () => {
114
+ const mockProvider = {
115
+ request: vi.fn().mockResolvedValue({
166
116
  [ANVIL_CHAIN.id]: {
167
- atomic: {
168
- status: "supported",
169
- },
170
117
  paymasterService: {
171
118
  supported: true,
172
119
  },
120
+ sessionKeys: {
121
+ supported: true,
122
+ },
173
123
  },
174
- });
124
+ }),
125
+ };
126
+
127
+ // Mock what an injected account with getCapabilities would look like
128
+ const injectedAccount = {
129
+ ...TEST_ACCOUNT_A,
130
+ getCapabilities: async (_options: any) => {
131
+ // This mimics the implementation in injected/index.ts
132
+ const response = await mockProvider.request({
133
+ method: "wallet_getCapabilities",
134
+ params: [injectedAccount.address],
135
+ });
136
+ return response;
137
+ },
138
+ };
139
+
140
+ const wallet: Wallet = createWallet(METAMASK);
141
+ wallet.getAccount = vi.fn().mockReturnValue(injectedAccount);
142
+
143
+ const result = await getCapabilities({
144
+ wallet,
175
145
  });
176
146
 
177
- test("without sponsorGas should support atomicBatch", async () => {
178
- wallet = createWallet("inApp", {
179
- smartAccount: {
180
- chain: ANVIL_CHAIN,
181
- sponsorGas: false,
147
+ expect(result).toEqual({
148
+ [ANVIL_CHAIN.id]: {
149
+ paymasterService: {
150
+ supported: true,
182
151
  },
183
- });
184
- wallet.getAccount = vi.fn().mockReturnValue({
185
- ...TEST_ACCOUNT_A,
186
- sendBatchTransaction: vi.fn(),
187
- });
188
- wallet.getChain = vi.fn().mockReturnValue(ANVIL_CHAIN);
189
-
190
- const capabilities = await getCapabilities({
191
- wallet,
192
- });
193
-
194
- expect(capabilities).toEqual({
195
- [ANVIL_CHAIN.id]: {
196
- atomic: {
197
- status: "supported",
198
- },
199
- paymasterService: {
200
- supported: false,
201
- },
152
+ sessionKeys: {
153
+ supported: true,
202
154
  },
203
- });
155
+ },
156
+ });
157
+ expect(mockProvider.request).toHaveBeenCalledWith({
158
+ method: "wallet_getCapabilities",
159
+ params: [TEST_ACCOUNT_A.address],
204
160
  });
205
161
  });
206
- });
207
162
 
208
- describe.sequential("smart wallet", async () => {
209
- let wallet: Wallet = createWallet("smart", {
210
- chain: FORKED_ETHEREUM_CHAIN,
211
- sponsorGas: true,
212
- });
213
- const smartAccount = {
214
- ...TEST_ACCOUNT_A,
215
- sendBatchTransaction: vi.fn(),
216
- };
163
+ test("should handle provider errors", async () => {
164
+ const mockProvider = {
165
+ request: vi.fn().mockRejectedValue({
166
+ code: -32601,
167
+ message: "some nonsense the wallet sends us about not supporting",
168
+ }),
169
+ };
170
+
171
+ const injectedAccount = {
172
+ ...TEST_ACCOUNT_A,
173
+ getCapabilities: async (_options: any) => {
174
+ try {
175
+ return await mockProvider.request({
176
+ method: "wallet_getCapabilities",
177
+ params: [injectedAccount.address],
178
+ });
179
+ } catch {
180
+ return {
181
+ message: `io.metamask does not support wallet_getCapabilities, reach out to them directly to request EIP-5792 support.`,
182
+ };
183
+ }
184
+ },
185
+ };
217
186
 
218
- test("with no chain should return no capabilities", async () => {
219
- wallet.getAccount = vi.fn().mockReturnValue(smartAccount);
220
- wallet.getChain = vi.fn().mockReturnValue(undefined);
187
+ const wallet: Wallet = createWallet(METAMASK);
188
+ wallet.getAccount = vi.fn().mockReturnValue(injectedAccount);
221
189
 
222
- const capabilities = await getCapabilities({
190
+ const result = await getCapabilities({
223
191
  wallet,
224
192
  });
225
193
 
226
- expect(capabilities).toEqual({
194
+ expect(result).toEqual({
227
195
  message:
228
- "Can't get capabilities, no active chain found for wallet: smart",
196
+ "io.metamask does not support wallet_getCapabilities, reach out to them directly to request EIP-5792 support.",
229
197
  });
230
198
  });
199
+ });
231
200
 
232
- test("with no account should return no capabilities", async () => {
233
- wallet.getAccount = vi.fn().mockReturnValue(undefined);
234
- wallet.getChain = vi.fn().mockReturnValue(FORKED_ETHEREUM_CHAIN);
235
-
236
- const capabilities = await getCapabilities({
237
- wallet,
238
- });
201
+ describe.sequential("in-app wallet", () => {
202
+ const wallet: Wallet = createWallet("inApp");
239
203
 
240
- expect(capabilities).toEqual({
241
- message: "Can't get capabilities, no account connected for wallet: smart",
242
- });
204
+ afterEach(() => {
205
+ vi.clearAllMocks();
243
206
  });
244
207
 
245
- test("with sponsorGas should support paymasterService and atomicBatch", async () => {
246
- wallet = createWallet("smart", {
247
- chain: ANVIL_CHAIN,
248
- sponsorGas: true,
249
- });
250
- wallet.getAccount = vi.fn().mockReturnValue(smartAccount);
251
- wallet.getChain = vi.fn().mockReturnValue(FORKED_ETHEREUM_CHAIN);
208
+ test("should delegate to in-app wallet getCapabilities implementation", async () => {
209
+ const mockResponse = {
210
+ [ANVIL_CHAIN.id]: {
211
+ atomic: {
212
+ status: "unsupported",
213
+ },
214
+ paymasterService: {
215
+ supported: false,
216
+ },
217
+ },
218
+ };
252
219
 
253
- const capabilities = await getCapabilities({
220
+ const inAppAccount = {
221
+ ...TEST_ACCOUNT_A,
222
+ getCapabilities: async (_options: GetCapabilitiesOptions) => {
223
+ // This would be the actual in-app wallet implementation
224
+ return mockResponse;
225
+ },
226
+ };
227
+
228
+ wallet.getAccount = vi.fn().mockReturnValue(inAppAccount);
229
+
230
+ const result = await getCapabilities({
254
231
  wallet,
255
232
  });
256
233
 
257
- expect(capabilities).toEqual({
258
- [FORKED_ETHEREUM_CHAIN.id]: {
234
+ expect(result).toEqual(mockResponse);
235
+ });
236
+
237
+ test("should handle smart account capabilities", async () => {
238
+ const mockResponse = {
239
+ [ANVIL_CHAIN.id]: {
259
240
  atomic: {
260
241
  status: "supported",
261
242
  },
@@ -263,32 +244,62 @@ describe.sequential("smart wallet", async () => {
263
244
  supported: true,
264
245
  },
265
246
  },
266
- });
267
- });
247
+ };
248
+
249
+ const smartAccount = {
250
+ ...TEST_ACCOUNT_A,
251
+ sendBatchTransaction: vi.fn(), // indicates it's a smart account
252
+ getCapabilities: async (_options: GetCapabilitiesOptions) => {
253
+ return mockResponse;
254
+ },
255
+ };
268
256
 
269
- test("without sponsorGas should return atomicBatch", async () => {
270
- wallet = createWallet("smart", {
271
- chain: FORKED_ETHEREUM_CHAIN,
272
- sponsorGas: false,
273
- });
274
- wallet.getChain = vi.fn().mockReturnValue(FORKED_ETHEREUM_CHAIN);
275
257
  wallet.getAccount = vi.fn().mockReturnValue(smartAccount);
276
258
 
277
- const capabilities = await getCapabilities({
259
+ const result = await getCapabilities({
278
260
  wallet,
279
261
  });
280
262
 
281
- expect(capabilities).toEqual({
282
- [FORKED_ETHEREUM_CHAIN.id]: {
263
+ expect(result).toEqual(mockResponse);
264
+ });
265
+ });
266
+
267
+ describe.sequential("smart wallet", () => {
268
+ const wallet: Wallet = createWallet("smart", {
269
+ chain: ANVIL_CHAIN,
270
+ sponsorGas: true,
271
+ });
272
+
273
+ afterEach(() => {
274
+ vi.clearAllMocks();
275
+ });
276
+
277
+ test("should delegate to smart wallet getCapabilities implementation", async () => {
278
+ const mockResponse = {
279
+ [ANVIL_CHAIN.id]: {
283
280
  atomic: {
284
281
  status: "supported",
285
282
  },
286
283
  paymasterService: {
287
- supported: false,
284
+ supported: true,
288
285
  },
289
286
  },
287
+ };
288
+
289
+ const smartAccount = {
290
+ ...TEST_ACCOUNT_A,
291
+ sendBatchTransaction: vi.fn(),
292
+ getCapabilities: async (_options: GetCapabilitiesOptions) => {
293
+ return mockResponse;
294
+ },
295
+ };
296
+
297
+ wallet.getAccount = vi.fn().mockReturnValue(smartAccount);
298
+
299
+ const result = await getCapabilities({
300
+ wallet,
290
301
  });
302
+
303
+ expect(result).toEqual(mockResponse);
291
304
  });
292
305
  });
293
-
294
- // TODO: Coinbase SDK Tests