odin-connect 1.2.1 → 1.3.0
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/.github/workflows/pr.yml +24 -24
- package/demo/README.md +69 -69
- package/demo/eslint.config.js +23 -23
- package/demo/index.html +13 -13
- package/demo/package-lock.json +3495 -3495
- package/demo/package.json +32 -32
- package/demo/public/icon.svg +5 -5
- package/demo/tsconfig.app.json +27 -27
- package/demo/tsconfig.node.json +25 -25
- package/demo/vite.config.ts +7 -7
- package/dist/services/canister.d.ts +7 -0
- package/dist/services/canister.d.ts.map +1 -1
- package/dist/services/canister.js +17 -0
- package/dist/services/connected-user.d.ts +2 -1
- package/dist/services/connected-user.d.ts.map +1 -1
- package/dist/services/connected-user.js +6 -0
- package/package.json +51 -51
- package/readme.md +468 -205
- package/vitest.config.ts +7 -7
- package/dist/services/connect.test.d.ts +0 -2
- package/dist/services/connect.test.d.ts.map +0 -1
- package/dist/services/connect.test.js +0 -323
package/vitest.config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
export default defineConfig({
|
|
3
|
-
test: {
|
|
4
|
-
globals: true,
|
|
5
|
-
environment: "jsdom", // or 'jsdom' for frontend
|
|
6
|
-
},
|
|
7
|
-
});
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
export default defineConfig({
|
|
3
|
+
test: {
|
|
4
|
+
globals: true,
|
|
5
|
+
environment: "jsdom", // or 'jsdom' for frontend
|
|
6
|
+
},
|
|
7
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connect.test.d.ts","sourceRoot":"","sources":["../../src/services/connect.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll, vi, afterEach } from "vitest";
|
|
2
|
-
import { Connect } from "./connect";
|
|
3
|
-
const mockTokens = [
|
|
4
|
-
{
|
|
5
|
-
id: "2jjj",
|
|
6
|
-
ticker: "TEST",
|
|
7
|
-
},
|
|
8
|
-
];
|
|
9
|
-
describe("Connect", () => {
|
|
10
|
-
let connect;
|
|
11
|
-
beforeAll(() => {
|
|
12
|
-
connect = new Connect({ name: "TestApp", env: "local" });
|
|
13
|
-
connect["_api"].getUser = vi.fn().mockResolvedValue({
|
|
14
|
-
principal: "user-principal",
|
|
15
|
-
username: "username",
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
vi.restoreAllMocks();
|
|
20
|
-
});
|
|
21
|
-
it("should initialize Connect instance", () => {
|
|
22
|
-
expect(connect).toBeDefined();
|
|
23
|
-
expect(connect).toBeInstanceOf(Connect);
|
|
24
|
-
expect(connect["_appInfo"]?.name).toBe("TestApp");
|
|
25
|
-
expect(connect["origin"])?.toBe("http://localhost:5173");
|
|
26
|
-
});
|
|
27
|
-
it("should say hello", () => {
|
|
28
|
-
const consoleLogSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
29
|
-
connect.hello();
|
|
30
|
-
expect(consoleLogSpy).toHaveBeenCalledWith("Hello from Odin Connect!");
|
|
31
|
-
consoleLogSpy.mockRestore();
|
|
32
|
-
});
|
|
33
|
-
it("should create authorization URL", () => {
|
|
34
|
-
const url = connect["createUrl"]("authorize/test");
|
|
35
|
-
expect(url).toBeInstanceOf(URL);
|
|
36
|
-
expect(url.pathname).toBe("/authorize/test");
|
|
37
|
-
expect(url.searchParams.get("app_name")).toBe("TestApp");
|
|
38
|
-
expect(url.searchParams.get("referrer")).toBeDefined();
|
|
39
|
-
});
|
|
40
|
-
it("should open the connect window", () => {
|
|
41
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
42
|
-
const getUserSpy = vi.spyOn(connect["_api"], "getUser").mockResolvedValue({
|
|
43
|
-
principal: "user-principal",
|
|
44
|
-
username: "username",
|
|
45
|
-
});
|
|
46
|
-
const connectPromise = connect.connect({ requires_api: false });
|
|
47
|
-
connectPromise.then((res) => {
|
|
48
|
-
expect(res).toBeDefined();
|
|
49
|
-
expect(res.user.username).toBe("username");
|
|
50
|
-
expect(res.user.principal).toBe("user-principal");
|
|
51
|
-
expect(connect.apiClient.apiKey).toBeNull();
|
|
52
|
-
}, (e) => {
|
|
53
|
-
expect(true).toBe(false);
|
|
54
|
-
});
|
|
55
|
-
const url = openSpy.mock.calls[0][0];
|
|
56
|
-
expect(url).toBeInstanceOf(URL);
|
|
57
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/connect?");
|
|
58
|
-
const params = new URLSearchParams(url?.search);
|
|
59
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
60
|
-
expect(params.get("referrer")).toBeDefined();
|
|
61
|
-
expect(params.get("requires_api")).toBe("0");
|
|
62
|
-
simulateMessage("authorize/connect", {
|
|
63
|
-
principal: "user-principal",
|
|
64
|
-
jwt: null,
|
|
65
|
-
});
|
|
66
|
-
expect(getUserSpy).toHaveBeenCalledWith("user-principal");
|
|
67
|
-
});
|
|
68
|
-
it("should open connect window with API requirement", () => {
|
|
69
|
-
vi.spyOn(connect["_api"], "getUser").mockResolvedValue({
|
|
70
|
-
principal: "user-principal",
|
|
71
|
-
username: "username",
|
|
72
|
-
});
|
|
73
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
74
|
-
const connectPromise = connect.connect({ requires_api: true });
|
|
75
|
-
connectPromise.then((res) => {
|
|
76
|
-
console.log(res);
|
|
77
|
-
expect(res).toBeDefined();
|
|
78
|
-
expect(res.user.username).toBe("username");
|
|
79
|
-
expect(res.user.principal).toBe("user-principal");
|
|
80
|
-
expect(connect.apiClient.apiKey).toBe("test-jwt");
|
|
81
|
-
}, () => {
|
|
82
|
-
expect(true).toBe(false);
|
|
83
|
-
});
|
|
84
|
-
const url = openSpy.mock.calls[0][0];
|
|
85
|
-
expect(url).toBeInstanceOf(URL);
|
|
86
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/connect?");
|
|
87
|
-
const params = new URLSearchParams(url?.search);
|
|
88
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
89
|
-
expect(params.get("referrer")).toBeDefined();
|
|
90
|
-
expect(params.get("requires_api")).toBe("1");
|
|
91
|
-
simulateMessage("authorize/connect", {
|
|
92
|
-
principal: "user-principal",
|
|
93
|
-
jwt: "test-jwt",
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
it("should handle rejected connection", () => {
|
|
97
|
-
const connectPromise = connect.connect({ requires_api: false });
|
|
98
|
-
connectPromise.then(() => expect(false).toBe(true), (e) => {
|
|
99
|
-
expect(e).toBeInstanceOf(Error);
|
|
100
|
-
expect(e.message).toContain("rejected");
|
|
101
|
-
});
|
|
102
|
-
simulateRejectMessage("authorize/connect");
|
|
103
|
-
});
|
|
104
|
-
it("should open the buy authorization window", () => {
|
|
105
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
106
|
-
const result = connect.buy({
|
|
107
|
-
token: "2jjj",
|
|
108
|
-
btcAmount: 20001n,
|
|
109
|
-
principal: "test-principal",
|
|
110
|
-
});
|
|
111
|
-
result.catch((e) => {
|
|
112
|
-
console.log(e);
|
|
113
|
-
expect(e).toBeInstanceOf(Error);
|
|
114
|
-
});
|
|
115
|
-
expect(openSpy).toHaveBeenCalled();
|
|
116
|
-
const url = openSpy.mock.calls[0][0];
|
|
117
|
-
expect(url).toBeInstanceOf(URL);
|
|
118
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/buy?");
|
|
119
|
-
const params = new URLSearchParams(url?.search);
|
|
120
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
121
|
-
expect(params.get("token")).toBe("2jjj");
|
|
122
|
-
expect(params.get("amount")).toBe("20001");
|
|
123
|
-
expect(params.get("principal")).toBe("test-principal");
|
|
124
|
-
});
|
|
125
|
-
it("should open the sell authorization window", () => {
|
|
126
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
127
|
-
const sellPromise = connect.sell({
|
|
128
|
-
token: "2jjj",
|
|
129
|
-
tokenAmount: 32000n,
|
|
130
|
-
principal: "test-principal",
|
|
131
|
-
});
|
|
132
|
-
sellPromise.then((result) => {
|
|
133
|
-
expect(result).toBe(true);
|
|
134
|
-
});
|
|
135
|
-
expect(openSpy).toHaveBeenCalled();
|
|
136
|
-
const url = openSpy.mock.calls[0][0];
|
|
137
|
-
expect(url).toBeInstanceOf(URL);
|
|
138
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/sell?");
|
|
139
|
-
const params = new URLSearchParams(url?.search);
|
|
140
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
141
|
-
expect(params.get("token")).toBe("2jjj");
|
|
142
|
-
expect(params.get("amount")).toBe("32000");
|
|
143
|
-
expect(params.get("principal")).toBe("test-principal");
|
|
144
|
-
simulateMessage("authorize/sell", "sold");
|
|
145
|
-
});
|
|
146
|
-
it("should handle rejected sell", () => {
|
|
147
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
148
|
-
const sellPromise = connect.sell({
|
|
149
|
-
token: "2jjj",
|
|
150
|
-
tokenAmount: 32000n,
|
|
151
|
-
principal: "test-principal",
|
|
152
|
-
});
|
|
153
|
-
sellPromise.then(() => {
|
|
154
|
-
expect(true).toBe(false); // should not be called
|
|
155
|
-
}, (e) => {
|
|
156
|
-
expect(e).toBeInstanceOf(Error);
|
|
157
|
-
expect(e.message).toContain("failed");
|
|
158
|
-
});
|
|
159
|
-
expect(openSpy).toHaveBeenCalled();
|
|
160
|
-
simulateRejectMessage("authorize/sell");
|
|
161
|
-
});
|
|
162
|
-
it("should open the transfer authorization window", () => {
|
|
163
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
164
|
-
const result = connect.transfer({
|
|
165
|
-
token: "2jjj",
|
|
166
|
-
amount: 45000n,
|
|
167
|
-
destination: "to-principal",
|
|
168
|
-
principal: "from-principal",
|
|
169
|
-
});
|
|
170
|
-
result.catch((e) => {
|
|
171
|
-
expect(e).toBeInstanceOf(Error);
|
|
172
|
-
});
|
|
173
|
-
expect(openSpy).toHaveBeenCalled();
|
|
174
|
-
const url = openSpy.mock.calls[0][0];
|
|
175
|
-
expect(url).toBeInstanceOf(URL);
|
|
176
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/transfer?");
|
|
177
|
-
const params = new URLSearchParams(url?.search);
|
|
178
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
179
|
-
expect(params.get("token")).toBe("2jjj");
|
|
180
|
-
expect(params.get("amount")).toBe("45000");
|
|
181
|
-
expect(params.get("destination")).toBe("to-principal");
|
|
182
|
-
expect(params.get("principal")).toBe("from-principal");
|
|
183
|
-
});
|
|
184
|
-
it("should handle rejected transfer", () => {
|
|
185
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
186
|
-
const transferPromise = connect.transfer({
|
|
187
|
-
token: "2jjj",
|
|
188
|
-
amount: 45000n,
|
|
189
|
-
destination: "to-principal",
|
|
190
|
-
principal: "from-principal",
|
|
191
|
-
});
|
|
192
|
-
transferPromise.then(() => expect(true).toBe(false), // should not be called
|
|
193
|
-
(e) => {
|
|
194
|
-
expect(e).toBeInstanceOf(Error);
|
|
195
|
-
expect(e.message).toContain("failed");
|
|
196
|
-
});
|
|
197
|
-
expect(openSpy).toHaveBeenCalled();
|
|
198
|
-
simulateRejectMessage("authorize/transfer");
|
|
199
|
-
});
|
|
200
|
-
it("should open the add liquidity authorization window", () => {
|
|
201
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
202
|
-
const addLiquidityPromise = connect.addLiquidity({
|
|
203
|
-
token: "2jjj",
|
|
204
|
-
btcAmount: 10000n,
|
|
205
|
-
principal: "test-principal",
|
|
206
|
-
});
|
|
207
|
-
addLiquidityPromise.then((result) => expect(result).toBe(true), () => expect(true).toBe(false) // should not be called
|
|
208
|
-
);
|
|
209
|
-
expect(openSpy).toHaveBeenCalled();
|
|
210
|
-
const url = openSpy.mock.calls[0][0];
|
|
211
|
-
expect(url).toBeInstanceOf(URL);
|
|
212
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/add_liquidity?");
|
|
213
|
-
const params = new URLSearchParams(url?.search);
|
|
214
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
215
|
-
expect(params.get("token")).toBe("2jjj");
|
|
216
|
-
expect(params.get("amount")).toBe("10000");
|
|
217
|
-
expect(params.get("principal")).toBe("test-principal");
|
|
218
|
-
simulateMessage("authorize/add_liquidity", "addedLiquidity");
|
|
219
|
-
});
|
|
220
|
-
it("should handle rejected add liquidity", () => {
|
|
221
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
222
|
-
const addLiquidityPromise = connect.addLiquidity({
|
|
223
|
-
token: "2jjj",
|
|
224
|
-
btcAmount: 10000n,
|
|
225
|
-
principal: "test-principal",
|
|
226
|
-
});
|
|
227
|
-
addLiquidityPromise.then(() => expect(true).toBe(false), // should not be called
|
|
228
|
-
(e) => {
|
|
229
|
-
expect(e).toBeInstanceOf(Error);
|
|
230
|
-
expect(e.message).toContain("failed");
|
|
231
|
-
});
|
|
232
|
-
expect(openSpy).toHaveBeenCalled();
|
|
233
|
-
simulateRejectMessage("authorize/add_liquidity");
|
|
234
|
-
});
|
|
235
|
-
it("should open the remove liquidity authorization window", () => {
|
|
236
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
237
|
-
const removeLiquidityPromise = connect.removeLiquidity({
|
|
238
|
-
token: "2jjj",
|
|
239
|
-
lpAmount: 15000n,
|
|
240
|
-
principal: "test-principal",
|
|
241
|
-
});
|
|
242
|
-
removeLiquidityPromise.then((result) => expect(result).toBe(true), () => expect(true).toBe(false) // should not be called
|
|
243
|
-
);
|
|
244
|
-
expect(openSpy).toHaveBeenCalled();
|
|
245
|
-
const url = openSpy.mock.calls[0][0];
|
|
246
|
-
expect(url).toBeInstanceOf(URL);
|
|
247
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/remove_liquidity?");
|
|
248
|
-
const params = new URLSearchParams(url?.search);
|
|
249
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
250
|
-
expect(params.get("token")).toBe("2jjj");
|
|
251
|
-
expect(params.get("amount")).toBe("15000");
|
|
252
|
-
expect(params.get("principal")).toBe("test-principal");
|
|
253
|
-
simulateMessage("authorize/remove_liquidity", "removedLiquidity");
|
|
254
|
-
});
|
|
255
|
-
it("should handle rejected remove liquidity", () => {
|
|
256
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
257
|
-
const removeLiquidityPromise = connect.removeLiquidity({
|
|
258
|
-
token: "2jjj",
|
|
259
|
-
lpAmount: 15000n,
|
|
260
|
-
principal: "test-principal",
|
|
261
|
-
});
|
|
262
|
-
removeLiquidityPromise.then(() => expect(true).toBe(false), // should not be called
|
|
263
|
-
(e) => {
|
|
264
|
-
expect(e).toBeInstanceOf(Error);
|
|
265
|
-
expect(e.message).toContain("failed");
|
|
266
|
-
});
|
|
267
|
-
expect(openSpy).toHaveBeenCalled();
|
|
268
|
-
simulateRejectMessage("authorize/remove_liquidity");
|
|
269
|
-
});
|
|
270
|
-
it("should create a base action", async () => {
|
|
271
|
-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
|
272
|
-
const action = () => connect["baseAction"]({
|
|
273
|
-
params: { test: "param" },
|
|
274
|
-
odinPath: "authorize/test_action",
|
|
275
|
-
receivedMessageFromOrigin(message) {
|
|
276
|
-
return message === "OK";
|
|
277
|
-
},
|
|
278
|
-
resolve: {
|
|
279
|
-
success: (message) => {
|
|
280
|
-
return message + "!";
|
|
281
|
-
},
|
|
282
|
-
failure: "test failed",
|
|
283
|
-
close: "rejected",
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
action().then((res) => {
|
|
287
|
-
expect(res).toBe("OK!");
|
|
288
|
-
});
|
|
289
|
-
expect(openSpy).toHaveBeenCalled();
|
|
290
|
-
const url = openSpy.mock.calls[0][0];
|
|
291
|
-
expect(url).toBeInstanceOf(URL);
|
|
292
|
-
expect(url?.toString()).toContain("http://localhost:5173/authorize/test_action?");
|
|
293
|
-
const params = new URLSearchParams(url?.search);
|
|
294
|
-
expect(params.get("app_name")).toBe("TestApp");
|
|
295
|
-
expect(params.get("test")).toBe("param");
|
|
296
|
-
simulateMessage("authorize/test_action", "OK");
|
|
297
|
-
action().then(() => expect(true).toBe(false), (e) => {
|
|
298
|
-
expect(e).toBeInstanceOf(Error);
|
|
299
|
-
expect(e.message).toBe("test failed");
|
|
300
|
-
});
|
|
301
|
-
simulateRejectMessage("authorize/test_action");
|
|
302
|
-
});
|
|
303
|
-
});
|
|
304
|
-
function simulateRejectMessage(path) {
|
|
305
|
-
const messageEvent = new MessageEvent("message", {
|
|
306
|
-
data: {
|
|
307
|
-
path: "/" + path,
|
|
308
|
-
message: "rejected",
|
|
309
|
-
},
|
|
310
|
-
origin: "http://localhost:5173",
|
|
311
|
-
});
|
|
312
|
-
window.dispatchEvent(messageEvent);
|
|
313
|
-
}
|
|
314
|
-
function simulateMessage(path, data) {
|
|
315
|
-
const messageEvent = new MessageEvent("message", {
|
|
316
|
-
data: {
|
|
317
|
-
path: "/" + path,
|
|
318
|
-
message: data,
|
|
319
|
-
},
|
|
320
|
-
origin: "http://localhost:5173",
|
|
321
|
-
});
|
|
322
|
-
window.dispatchEvent(messageEvent);
|
|
323
|
-
}
|