@tomo-inc/wallet-adaptor-base 0.0.20 → 0.0.22
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.
- package/dist/index.cjs +18 -22
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +18 -22
- package/package.json +7 -2
- package/project.json +1 -1
- package/src/__tests__/WalletConnectProvider.test.ts +535 -0
- package/src/__tests__/WalletConnectSolanaProvider.test.ts +537 -0
- package/src/__tests__/browsers.test.ts +263 -0
- package/src/__tests__/chainId.test.ts +66 -0
- package/src/__tests__/chains-utils.test.ts +49 -0
- package/src/__tests__/defaultConnectors.test.ts +8 -5
- package/src/__tests__/detector.test.ts +402 -0
- package/src/__tests__/index.test.ts +275 -0
- package/src/__tests__/isMobile.test.ts +187 -0
- package/src/__tests__/log.test.ts +40 -0
- package/src/__tests__/utils.test.ts +66 -0
- package/src/__tests__/wallet-api.test.ts +1755 -0
- package/src/__tests__/wallet-config.test.ts +75 -0
- package/src/__tests__/wallet-eip6963.test.ts +377 -0
- package/src/__tests__/wallet-standard.test.ts +41 -3
- package/src/__tests__/wallet-walletconnect.test.ts +370 -0
- package/src/__tests__/wallets/index.test.ts +42 -0
- package/src/type.ts +4 -0
- package/src/utils/chainId.ts +6 -5
- package/src/utils/wallet-config.ts +2 -9
- package/src/wallet-api/connect.ts +4 -2
- package/src/wallets/detector.ts +3 -4
- package/src/wallets/providers/WalletConnectProvider.ts +5 -4
- package/src/wallets/providers/WalletConnectSolanaProvider.ts +1 -1
- package/src/wallets/wallet-eip6963.ts +1 -1
- package/vitest.config.ts +20 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { isSafari, isArc, getBrowser, BrowserType, openUri } from "../utils/browsers";
|
|
3
|
+
|
|
4
|
+
describe("browsers", () => {
|
|
5
|
+
let originalNavigator: typeof navigator;
|
|
6
|
+
let originalDocument: typeof document;
|
|
7
|
+
let originalWindow: typeof window;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
originalNavigator = global.navigator;
|
|
11
|
+
originalDocument = global.document;
|
|
12
|
+
originalWindow = global.window;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
global.navigator = originalNavigator;
|
|
17
|
+
global.document = originalDocument;
|
|
18
|
+
global.window = originalWindow;
|
|
19
|
+
vi.restoreAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("isSafari", () => {
|
|
23
|
+
it("should return true for Safari user agent", () => {
|
|
24
|
+
Object.defineProperty(global, "navigator", {
|
|
25
|
+
value: {
|
|
26
|
+
userAgent:
|
|
27
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15",
|
|
28
|
+
},
|
|
29
|
+
writable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
});
|
|
32
|
+
expect(isSafari()).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should return false for non-Safari user agent", () => {
|
|
36
|
+
Object.defineProperty(global, "navigator", {
|
|
37
|
+
value: {
|
|
38
|
+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
39
|
+
},
|
|
40
|
+
writable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
});
|
|
43
|
+
expect(isSafari()).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("should return false when navigator is undefined", () => {
|
|
47
|
+
Object.defineProperty(global, "navigator", {
|
|
48
|
+
value: undefined,
|
|
49
|
+
writable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
});
|
|
52
|
+
expect(isSafari()).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("isArc", () => {
|
|
57
|
+
it("should return true when Arc CSS variable is present", () => {
|
|
58
|
+
const mockGetComputedStyle = vi.fn(() => ({
|
|
59
|
+
getPropertyValue: vi.fn((prop: string) => {
|
|
60
|
+
if (prop === "--arc-palette-focus") return "some-value";
|
|
61
|
+
return "";
|
|
62
|
+
}),
|
|
63
|
+
}));
|
|
64
|
+
|
|
65
|
+
Object.defineProperty(global, "document", {
|
|
66
|
+
value: {
|
|
67
|
+
body: {},
|
|
68
|
+
},
|
|
69
|
+
writable: true,
|
|
70
|
+
configurable: true,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
global.getComputedStyle = mockGetComputedStyle as any;
|
|
74
|
+
expect(isArc()).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should return false when Arc CSS variable is not present", () => {
|
|
78
|
+
const mockGetComputedStyle = vi.fn(() => ({
|
|
79
|
+
getPropertyValue: vi.fn(() => ""),
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
Object.defineProperty(global, "document", {
|
|
83
|
+
value: {
|
|
84
|
+
body: {},
|
|
85
|
+
},
|
|
86
|
+
writable: true,
|
|
87
|
+
configurable: true,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
global.getComputedStyle = mockGetComputedStyle as any;
|
|
91
|
+
expect(isArc()).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("should return false when document is undefined", () => {
|
|
95
|
+
Object.defineProperty(global, "document", {
|
|
96
|
+
value: undefined,
|
|
97
|
+
writable: true,
|
|
98
|
+
configurable: true,
|
|
99
|
+
});
|
|
100
|
+
expect(isArc()).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe("getBrowser", () => {
|
|
105
|
+
it("should return BrowserType.Browser when navigator is undefined", () => {
|
|
106
|
+
Object.defineProperty(global, "navigator", {
|
|
107
|
+
value: undefined,
|
|
108
|
+
writable: true,
|
|
109
|
+
configurable: true,
|
|
110
|
+
});
|
|
111
|
+
expect(getBrowser()).toBe(BrowserType.Browser);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should return BrowserType.Brave when brave.isBrave is true", () => {
|
|
115
|
+
Object.defineProperty(global, "navigator", {
|
|
116
|
+
value: {
|
|
117
|
+
userAgent: "test",
|
|
118
|
+
brave: {
|
|
119
|
+
isBrave: true,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
writable: true,
|
|
123
|
+
configurable: true,
|
|
124
|
+
});
|
|
125
|
+
expect(getBrowser()).toBe(BrowserType.Brave);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("should return BrowserType.Edge for Edge user agent", () => {
|
|
129
|
+
Object.defineProperty(global, "navigator", {
|
|
130
|
+
value: {
|
|
131
|
+
userAgent:
|
|
132
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59",
|
|
133
|
+
},
|
|
134
|
+
writable: true,
|
|
135
|
+
configurable: true,
|
|
136
|
+
});
|
|
137
|
+
expect(getBrowser()).toBe(BrowserType.Edge);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("should return BrowserType.Opera for Opera user agent", () => {
|
|
141
|
+
Object.defineProperty(global, "navigator", {
|
|
142
|
+
value: {
|
|
143
|
+
userAgent:
|
|
144
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 OPR/77.0.4054.203",
|
|
145
|
+
},
|
|
146
|
+
writable: true,
|
|
147
|
+
configurable: true,
|
|
148
|
+
});
|
|
149
|
+
expect(getBrowser()).toBe(BrowserType.Opera);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("should return BrowserType.Chrome for Chrome user agent", () => {
|
|
153
|
+
Object.defineProperty(global, "navigator", {
|
|
154
|
+
value: {
|
|
155
|
+
userAgent:
|
|
156
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
|
|
157
|
+
},
|
|
158
|
+
writable: true,
|
|
159
|
+
configurable: true,
|
|
160
|
+
});
|
|
161
|
+
expect(getBrowser()).toBe(BrowserType.Chrome);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("should return BrowserType.Firefox for Firefox user agent", () => {
|
|
165
|
+
Object.defineProperty(global, "navigator", {
|
|
166
|
+
value: {
|
|
167
|
+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
|
|
168
|
+
},
|
|
169
|
+
writable: true,
|
|
170
|
+
configurable: true,
|
|
171
|
+
});
|
|
172
|
+
expect(getBrowser()).toBe(BrowserType.Firefox);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("should return BrowserType.Safari for Safari user agent", () => {
|
|
176
|
+
Object.defineProperty(global, "navigator", {
|
|
177
|
+
value: {
|
|
178
|
+
userAgent:
|
|
179
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15",
|
|
180
|
+
},
|
|
181
|
+
writable: true,
|
|
182
|
+
configurable: true,
|
|
183
|
+
});
|
|
184
|
+
expect(getBrowser()).toBe(BrowserType.Safari);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("should return BrowserType.Arc when Arc CSS variable is present", () => {
|
|
188
|
+
const mockGetComputedStyle = vi.fn(() => ({
|
|
189
|
+
getPropertyValue: vi.fn((prop: string) => (prop === "--arc-palette-focus" ? "some-value" : "")),
|
|
190
|
+
}));
|
|
191
|
+
Object.defineProperty(global, "navigator", {
|
|
192
|
+
value: { userAgent: "Mozilla/5.0 (generic) Chrome/120.0", brave: undefined },
|
|
193
|
+
writable: true,
|
|
194
|
+
configurable: true,
|
|
195
|
+
});
|
|
196
|
+
Object.defineProperty(global, "document", {
|
|
197
|
+
value: { body: {}, createElement: document.createElement?.bind(document) },
|
|
198
|
+
writable: true,
|
|
199
|
+
configurable: true,
|
|
200
|
+
});
|
|
201
|
+
(global as any).getComputedStyle = mockGetComputedStyle;
|
|
202
|
+
expect(getBrowser()).toBe(BrowserType.Arc);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("should return BrowserType.Browser when no known browser matches", () => {
|
|
206
|
+
Object.defineProperty(global, "navigator", {
|
|
207
|
+
value: {
|
|
208
|
+
userAgent: "Mozilla/5.0 (compatible; UnknownBot/1.0)",
|
|
209
|
+
brave: undefined,
|
|
210
|
+
},
|
|
211
|
+
writable: true,
|
|
212
|
+
configurable: true,
|
|
213
|
+
});
|
|
214
|
+
const mockGetComputedStyle = vi.fn(() => ({
|
|
215
|
+
getPropertyValue: vi.fn(() => ""),
|
|
216
|
+
}));
|
|
217
|
+
(global as any).getComputedStyle = mockGetComputedStyle;
|
|
218
|
+
expect(getBrowser()).toBe(BrowserType.Browser);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe("openUri", () => {
|
|
223
|
+
it("should open http URI in new tab", () => {
|
|
224
|
+
const mockClick = vi.fn();
|
|
225
|
+
const mockLink = {
|
|
226
|
+
href: "",
|
|
227
|
+
target: "",
|
|
228
|
+
rel: "",
|
|
229
|
+
click: mockClick,
|
|
230
|
+
};
|
|
231
|
+
const mockCreateElement = vi.fn(() => mockLink);
|
|
232
|
+
|
|
233
|
+
Object.defineProperty(global, "document", {
|
|
234
|
+
value: {
|
|
235
|
+
createElement: mockCreateElement,
|
|
236
|
+
},
|
|
237
|
+
writable: true,
|
|
238
|
+
configurable: true,
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
openUri("https://example.com");
|
|
242
|
+
expect(mockCreateElement).toHaveBeenCalledWith("a");
|
|
243
|
+
expect(mockLink.href).toBe("https://example.com");
|
|
244
|
+
expect(mockLink.target).toBe("_blank");
|
|
245
|
+
expect(mockLink.rel).toBe("noreferrer noopener");
|
|
246
|
+
expect(mockClick).toHaveBeenCalled();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("should navigate to non-http URI", () => {
|
|
250
|
+
const mockLocation = { href: "" };
|
|
251
|
+
Object.defineProperty(global, "window", {
|
|
252
|
+
value: {
|
|
253
|
+
location: mockLocation,
|
|
254
|
+
},
|
|
255
|
+
writable: true,
|
|
256
|
+
configurable: true,
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
openUri("custom://protocol");
|
|
260
|
+
expect(mockLocation.href).toBe("custom://protocol");
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { isHexChainId, isSameAddress, getAllTypeChainIds } from "../utils/chainId";
|
|
3
|
+
|
|
4
|
+
describe("chainId", () => {
|
|
5
|
+
describe("isHexChainId", () => {
|
|
6
|
+
it("should return true for valid hex chain ID", () => {
|
|
7
|
+
expect(isHexChainId("0x1")).toBe(true);
|
|
8
|
+
expect(isHexChainId("0x01")).toBe(true);
|
|
9
|
+
expect(isHexChainId("0x123abc")).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should return false for invalid hex chain ID", () => {
|
|
13
|
+
expect(isHexChainId("1")).toBe(false);
|
|
14
|
+
expect(isHexChainId("0xgh")).toBe(false);
|
|
15
|
+
expect(isHexChainId("")).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("isSameAddress", () => {
|
|
20
|
+
it("should return true for same addresses", () => {
|
|
21
|
+
// Use valid Ethereum addresses (40 hex characters)
|
|
22
|
+
const addr1 = "0x1234567890123456789012345678901234567890";
|
|
23
|
+
const addr2 = "0x1234567890123456789012345678901234567890";
|
|
24
|
+
expect(isSameAddress(addr1, addr2)).toBe(true);
|
|
25
|
+
expect(
|
|
26
|
+
isSameAddress("0xAbCdEf1234567890123456789012345678901234", "0xabcdef1234567890123456789012345678901234"),
|
|
27
|
+
).toBe(true); // Case insensitive
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should return false for different addresses", () => {
|
|
31
|
+
const addr1 = "0x1234567890123456789012345678901234567890";
|
|
32
|
+
const addr2 = "0x9876543210987654321098765432109876543210";
|
|
33
|
+
expect(isSameAddress(addr1, addr2)).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("getAllTypeChainIds", () => {
|
|
38
|
+
it("should convert hex chain ID to number and hex", () => {
|
|
39
|
+
const result = getAllTypeChainIds({ chainId: "0x1", chainType: "evm" });
|
|
40
|
+
expect(result.chainId).toBe("1");
|
|
41
|
+
expect(result.chainIdHex).toBe("0x1");
|
|
42
|
+
expect(result.chainUid).toBe("evm:1");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should convert number chain ID to hex", () => {
|
|
46
|
+
const result = getAllTypeChainIds({ chainId: 1, chainType: "evm" });
|
|
47
|
+
expect(result.chainId).toBe("1");
|
|
48
|
+
expect(result.chainIdHex).toBe("0x1");
|
|
49
|
+
expect(result.chainUid).toBe("evm:1");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should convert string number chain ID to hex", () => {
|
|
53
|
+
const result = getAllTypeChainIds({ chainId: "56", chainType: "bsc" });
|
|
54
|
+
expect(result.chainId).toBe("56");
|
|
55
|
+
expect(result.chainIdHex).toBe("0x38");
|
|
56
|
+
expect(result.chainUid).toBe("bsc:56");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should handle large chain IDs", () => {
|
|
60
|
+
const result = getAllTypeChainIds({ chainId: "0x89", chainType: "polygon" });
|
|
61
|
+
expect(result.chainId).toBe("137");
|
|
62
|
+
expect(result.chainIdHex).toBe("0x89");
|
|
63
|
+
expect(result.chainUid).toBe("polygon:137");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { chainInfoAdapter } from "../chains/utils";
|
|
3
|
+
|
|
4
|
+
describe("chains/utils", () => {
|
|
5
|
+
let originalConsoleLog: typeof console.log;
|
|
6
|
+
let consoleLogSpy: ReturnType<typeof vi.spyOn>;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
originalConsoleLog = console.log;
|
|
10
|
+
consoleLogSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
console.log = originalConsoleLog;
|
|
15
|
+
vi.restoreAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("chainInfoAdapter", () => {
|
|
19
|
+
it("should return null for wagmi type", () => {
|
|
20
|
+
const chainConfig = { id: 1, name: "Ethereum" };
|
|
21
|
+
const result = chainInfoAdapter(chainConfig as any, "wagmi", "evm");
|
|
22
|
+
expect(result).toBeNull();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should return null for tomo type", () => {
|
|
26
|
+
const chainConfig = { id: 1, name: "Ethereum" };
|
|
27
|
+
const result = chainInfoAdapter(chainConfig as any, "tomo", "evm");
|
|
28
|
+
expect(result).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should return null for default case", () => {
|
|
32
|
+
const chainConfig = { id: 1, name: "Ethereum" };
|
|
33
|
+
const result = chainInfoAdapter(chainConfig as any, "unknown", "evm");
|
|
34
|
+
expect(result).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should log chainConfig for evm chainType", () => {
|
|
38
|
+
const chainConfig = { id: 1, name: "Ethereum" };
|
|
39
|
+
chainInfoAdapter(chainConfig as any, "wagmi", "evm");
|
|
40
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(chainConfig);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should not log for non-evm chainType", () => {
|
|
44
|
+
const chainConfig = { id: 1, name: "Solana" };
|
|
45
|
+
chainInfoAdapter(chainConfig as any, "wagmi", "solana");
|
|
46
|
+
expect(consoleLogSpy).not.toHaveBeenCalled();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -67,11 +67,14 @@ describe("defaultConnectors", () => {
|
|
|
67
67
|
const customBaseUrl = "https://custom-api.example.com";
|
|
68
68
|
await getDefaultConnectors(customBaseUrl);
|
|
69
69
|
|
|
70
|
-
expect(mockConnectorDector).toHaveBeenCalledWith(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
expect(mockConnectorDector).toHaveBeenCalledWith(
|
|
71
|
+
expect.objectContaining({
|
|
72
|
+
id: "wallet1",
|
|
73
|
+
name: "Wallet 1",
|
|
74
|
+
icon: "https://custom-api.example.com/icon1.png",
|
|
75
|
+
}),
|
|
76
|
+
"tomo",
|
|
77
|
+
);
|
|
75
78
|
});
|
|
76
79
|
|
|
77
80
|
it("should return cached connectors on second call", async () => {
|