@codex-data/sdk 1.0.9 → 1.0.11
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/resources/graphql.d.ts +177 -681
- package/dist/resources/graphql.d.ts.map +1 -1
- package/dist/resources/graphql.js +67 -79
- package/dist/resources/graphql.js.map +1 -1
- package/dist/sdk/Mutation.d.ts +2 -2
- package/dist/sdk/Mutation.d.ts.map +1 -1
- package/dist/sdk/Mutation.js +2 -2
- package/dist/sdk/Mutation.js.map +1 -1
- package/dist/sdk/Query.d.ts +57 -52
- package/dist/sdk/Query.d.ts.map +1 -1
- package/dist/sdk/Query.js +56 -51
- package/dist/sdk/Query.js.map +1 -1
- package/dist/sdk/Subscribe.d.ts +17 -18
- package/dist/sdk/Subscribe.d.ts.map +1 -1
- package/dist/sdk/Subscribe.js +126 -133
- package/dist/sdk/Subscribe.js.map +1 -1
- package/dist/sdk/generated/gql.d.ts +135 -104
- package/dist/sdk/generated/gql.d.ts.map +1 -1
- package/dist/sdk/generated/gql.js +44 -40
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.d.ts +1612 -1103
- package/dist/sdk/generated/graphql.d.ts.map +1 -1
- package/dist/sdk/generated/graphql.js +113 -121
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/index.d.ts +45 -0
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +83 -5
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/index.test.js +232 -7
- package/dist/sdk/index.test.js.map +1 -1
- package/package.json +1 -1
- package/src/resources/generated_queries/Balances.graphql +15 -0
- package/src/resources/generated_queries/DetailedWalletStats.graphql +4 -0
- package/src/resources/generated_queries/FilterNetworkWallets.graphql +57 -0
- package/src/resources/generated_queries/FilterNftPoolCollections.graphql +8 -0
- package/src/resources/generated_queries/FilterNftPools.graphql +7 -0
- package/src/resources/generated_queries/FilterPairs.graphql +60 -0
- package/src/resources/generated_queries/FilterTokenWallets.graphql +16 -0
- package/src/resources/generated_queries/FilterTokens.graphql +47 -0
- package/src/resources/generated_queries/FilterWallets.graphql +1 -0
- package/src/resources/generated_queries/GetBars.graphql +31 -0
- package/src/resources/generated_queries/GetCommunityNotes.graphql +16 -0
- package/src/resources/generated_queries/GetDetailedPairStats.graphql +30 -0
- package/src/resources/generated_queries/GetDetailedPairsStats.graphql +30 -0
- package/src/resources/generated_queries/GetDetailedStats.graphql +338 -0
- package/src/resources/generated_queries/GetLatestPairs.graphql +57 -0
- package/src/resources/generated_queries/GetLatestTokens.graphql +39 -0
- package/src/resources/generated_queries/GetNftEvents.graphql +9 -0
- package/src/resources/generated_queries/GetNftPool.graphql +2 -0
- package/src/resources/generated_queries/GetNftPoolCollection.graphql +8 -0
- package/src/resources/generated_queries/GetNftPoolCollectionsByExchange.graphql +8 -0
- package/src/resources/generated_queries/GetNftPoolEvents.graphql +2 -0
- package/src/resources/generated_queries/GetNftPoolsByCollectionAndExchange.graphql +2 -0
- package/src/resources/generated_queries/GetNftPoolsByOwner.graphql +2 -0
- package/src/resources/generated_queries/Holders.graphql +15 -0
- package/src/resources/generated_queries/LiquidityLocks.graphql +1 -0
- package/src/resources/generated_queries/ListPairsForToken.graphql +30 -0
- package/src/resources/generated_queries/ListPairsWithMetadataForToken.graphql +60 -0
- package/src/resources/generated_queries/ListTopTokens.graphql +55 -0
- package/src/resources/generated_queries/PairMetadata.graphql +30 -0
- package/src/resources/generated_queries/PrimeHolders.graphql +15 -0
- package/src/resources/generated_queries/SearchTokens.graphql +67 -0
- package/src/resources/generated_queries/Token.graphql +15 -0
- package/src/resources/generated_queries/Tokens.graphql +15 -0
- package/src/resources/generated_queries/WalletChart.graphql +1 -0
- package/src/resources/generated_subscriptions/OnBalanceUpdated.graphql +15 -0
- package/src/resources/generated_subscriptions/OnBarsUpdated.graphql +2 -10
- package/src/resources/generated_subscriptions/OnDetailedStatsUpdated.graphql +1 -6
- package/src/resources/generated_subscriptions/OnEventsCreated.graphql +0 -2
- package/src/resources/generated_subscriptions/OnHoldersUpdated.graphql +15 -0
- package/src/resources/generated_subscriptions/OnLaunchpadTokenEvent.graphql +15 -0
- package/src/resources/generated_subscriptions/OnNftEventsCreated.graphql +9 -0
- package/src/resources/generated_subscriptions/OnNftPoolEventsCreated.graphql +2 -0
- package/src/resources/generated_subscriptions/OnPairMetadataUpdated.graphql +32 -10
- package/src/resources/generated_subscriptions/OnTokenBarsUpdated.graphql +2 -10
- package/src/resources/graphql.schema.json +457 -5137
- package/src/resources/graphql.ts +183 -743
- package/src/resources/schema.graphql +6752 -11058
- package/src/sdk/Mutation.ts +4 -4
- package/src/sdk/Query.ts +128 -109
- package/src/sdk/Subscribe.ts +208 -223
- package/src/sdk/generated/gql.ts +106 -86
- package/src/sdk/generated/graphql.ts +320 -842
- package/src/sdk/index.test.ts +361 -10
- package/src/sdk/index.ts +89 -6
- package/src/resources/generated_queries/GetSimulateTokenContractResults.graphql +0 -128
- package/src/resources/generated_subscriptions/OnSimulateTokenContract.graphql +0 -121
package/src/sdk/index.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DocumentNode } from "graphql";
|
|
2
2
|
|
|
3
|
-
import { Codex } from "./index";
|
|
3
|
+
import { ApiConfig, Codex } from "./index";
|
|
4
4
|
|
|
5
5
|
const getNetworksDocument = {
|
|
6
6
|
kind: "Document",
|
|
@@ -34,45 +34,396 @@ const subscribePriceUpdatedString = `subscription onPriceUpdated($address: Strin
|
|
|
34
34
|
|
|
35
35
|
describe("Codex", () => {
|
|
36
36
|
let sdk: Codex;
|
|
37
|
+
|
|
37
38
|
beforeEach(() => {
|
|
38
39
|
sdk = new Codex("dummy-key");
|
|
39
40
|
});
|
|
40
41
|
|
|
42
|
+
describe("constructor", () => {
|
|
43
|
+
it("should initialize with default config when no apiConfig provided", () => {
|
|
44
|
+
const sdkInstance = new Codex("test-key");
|
|
45
|
+
expect(sdkInstance).toBeInstanceOf(Codex);
|
|
46
|
+
expect(sdkInstance.queries).toBeDefined();
|
|
47
|
+
expect(sdkInstance.mutations).toBeDefined();
|
|
48
|
+
expect(sdkInstance.subscriptions).toBeDefined();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should throw error when apiKey is not provided", () => {
|
|
52
|
+
expect(() => new Codex("")).toThrow("apiKey must be defined");
|
|
53
|
+
expect(() => new Codex(null as any)).toThrow("apiKey must be defined");
|
|
54
|
+
expect(() => new Codex(undefined as any)).toThrow(
|
|
55
|
+
"apiKey must be defined",
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should initialize with custom apiConfig", () => {
|
|
60
|
+
const customConfig: Partial<ApiConfig> = {
|
|
61
|
+
apiUrl: "https://custom.api.com/graphql",
|
|
62
|
+
apiRealtimeUrl: "wss://custom.api.com/graphql",
|
|
63
|
+
headers: { "Custom-Header": "value" },
|
|
64
|
+
wsHeaders: { "WS-Header": "ws-value" },
|
|
65
|
+
ws: false,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const sdkInstance = new Codex("test-key", customConfig);
|
|
69
|
+
expect(sdkInstance).toBeInstanceOf(Codex);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should merge custom config with default config", () => {
|
|
73
|
+
const customConfig: Partial<ApiConfig> = {
|
|
74
|
+
headers: { "Custom-Header": "value" },
|
|
75
|
+
ws: false,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Mock the createGraphQLClient and createWebsocketClient to verify they're called with merged config
|
|
79
|
+
const createGraphQLClientSpy = jest.spyOn(
|
|
80
|
+
Codex.prototype as any,
|
|
81
|
+
"createGraphQLClient",
|
|
82
|
+
);
|
|
83
|
+
const createWebsocketClientSpy = jest.spyOn(
|
|
84
|
+
Codex.prototype as any,
|
|
85
|
+
"createWebsocketClient",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
new Codex("test-key", customConfig);
|
|
89
|
+
|
|
90
|
+
// Verify the merged config was used
|
|
91
|
+
expect(createGraphQLClientSpy).toHaveBeenCalledWith(
|
|
92
|
+
expect.objectContaining({
|
|
93
|
+
apiUrl: "https://graph.codex.io/graphql", // default
|
|
94
|
+
apiRealtimeUrl: "wss://graph.codex.io/graphql", // default
|
|
95
|
+
headers: { "Custom-Header": "value" }, // custom
|
|
96
|
+
ws: false, // custom
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
createGraphQLClientSpy.mockRestore();
|
|
101
|
+
createWebsocketClientSpy.mockRestore();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe("updateConfig", () => {
|
|
106
|
+
it("should update configuration and recreate clients", () => {
|
|
107
|
+
const disposeSpy = jest.spyOn(sdk, "dispose");
|
|
108
|
+
const createGraphQLClientSpy = jest.spyOn(
|
|
109
|
+
sdk as any,
|
|
110
|
+
"createGraphQLClient",
|
|
111
|
+
);
|
|
112
|
+
const createWebsocketClientSpy = jest.spyOn(
|
|
113
|
+
sdk as any,
|
|
114
|
+
"createWebsocketClient",
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const newConfig: Partial<ApiConfig> = {
|
|
118
|
+
apiUrl: "https://new-api.com/graphql",
|
|
119
|
+
headers: { "New-Header": "new-value" },
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
sdk.updateConfig(newConfig);
|
|
123
|
+
|
|
124
|
+
expect(disposeSpy).toHaveBeenCalled();
|
|
125
|
+
expect(createGraphQLClientSpy).toHaveBeenCalled();
|
|
126
|
+
expect(createWebsocketClientSpy).toHaveBeenCalled();
|
|
127
|
+
|
|
128
|
+
disposeSpy.mockRestore();
|
|
129
|
+
createGraphQLClientSpy.mockRestore();
|
|
130
|
+
createWebsocketClientSpy.mockRestore();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should merge new config with existing config", () => {
|
|
134
|
+
const initialConfig: Partial<ApiConfig> = {
|
|
135
|
+
headers: { "Initial-Header": "initial-value" },
|
|
136
|
+
ws: true,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const sdkWithConfig = new Codex("test-key", initialConfig);
|
|
140
|
+
const parseConfigSpy = jest.spyOn(sdkWithConfig as any, "parseConfig");
|
|
141
|
+
|
|
142
|
+
const updateConfig: Partial<ApiConfig> = {
|
|
143
|
+
headers: { "Updated-Header": "updated-value" },
|
|
144
|
+
apiUrl: "https://updated-api.com/graphql",
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
sdkWithConfig.updateConfig(updateConfig);
|
|
148
|
+
|
|
149
|
+
// Verify parseConfig was called with merged configuration
|
|
150
|
+
expect(parseConfigSpy).toHaveBeenCalledWith(
|
|
151
|
+
expect.objectContaining({
|
|
152
|
+
headers: { "Updated-Header": "updated-value" },
|
|
153
|
+
apiUrl: "https://updated-api.com/graphql",
|
|
154
|
+
ws: true, // from initial config
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
parseConfigSpy.mockRestore();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should dispose existing websocket connection before creating new one", () => {
|
|
162
|
+
// Mock wsClient
|
|
163
|
+
const mockDispose = jest.fn();
|
|
164
|
+
(sdk as any).wsClient = { dispose: mockDispose };
|
|
165
|
+
|
|
166
|
+
const disposeSpy = jest.spyOn(sdk, "dispose");
|
|
167
|
+
|
|
168
|
+
sdk.updateConfig({ headers: { "New-Header": "value" } });
|
|
169
|
+
|
|
170
|
+
expect(disposeSpy).toHaveBeenCalled();
|
|
171
|
+
disposeSpy.mockRestore();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe("getRequestHeaders", () => {
|
|
176
|
+
it("should return static headers when no dynamic headers are configured", async () => {
|
|
177
|
+
const staticHeaders = { "Static-Header": "static-value" };
|
|
178
|
+
const sdkWithHeaders = new Codex("test-key", { headers: staticHeaders });
|
|
179
|
+
|
|
180
|
+
const headers = await (sdkWithHeaders as any).getRequestHeaders();
|
|
181
|
+
|
|
182
|
+
expect(headers).toEqual(staticHeaders);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("should return dynamic headers when applyHeaders is configured", async () => {
|
|
186
|
+
const dynamicHeaders = { "Dynamic-Header": "dynamic-value" };
|
|
187
|
+
const applyHeaders = jest.fn().mockResolvedValue(dynamicHeaders);
|
|
188
|
+
|
|
189
|
+
const sdkWithDynamicHeaders = new Codex("test-key", { applyHeaders });
|
|
190
|
+
|
|
191
|
+
const headers = await (sdkWithDynamicHeaders as any).getRequestHeaders();
|
|
192
|
+
|
|
193
|
+
expect(applyHeaders).toHaveBeenCalled();
|
|
194
|
+
expect(headers).toEqual(dynamicHeaders);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("should merge static and dynamic headers with dynamic taking precedence", async () => {
|
|
198
|
+
const staticHeaders = { "Header-1": "static", "Header-2": "static" };
|
|
199
|
+
const dynamicHeaders = { "Header-2": "dynamic", "Header-3": "dynamic" };
|
|
200
|
+
const applyHeaders = jest.fn().mockResolvedValue(dynamicHeaders);
|
|
201
|
+
|
|
202
|
+
const sdkWithBothHeaders = new Codex("test-key", {
|
|
203
|
+
headers: staticHeaders,
|
|
204
|
+
applyHeaders,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const headers = await (sdkWithBothHeaders as any).getRequestHeaders();
|
|
208
|
+
|
|
209
|
+
expect(headers).toEqual({
|
|
210
|
+
"Header-1": "static",
|
|
211
|
+
"Header-2": "dynamic", // dynamic overrides static
|
|
212
|
+
"Header-3": "dynamic",
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should handle applyHeaders returning undefined", async () => {
|
|
217
|
+
const staticHeaders = { "Static-Header": "static-value" };
|
|
218
|
+
const applyHeaders = jest.fn().mockResolvedValue(undefined);
|
|
219
|
+
|
|
220
|
+
const sdkWithUndefinedDynamic = new Codex("test-key", {
|
|
221
|
+
headers: staticHeaders,
|
|
222
|
+
applyHeaders,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const headers = await (
|
|
226
|
+
sdkWithUndefinedDynamic as any
|
|
227
|
+
).getRequestHeaders();
|
|
228
|
+
|
|
229
|
+
expect(headers).toEqual(staticHeaders);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe("dispose", () => {
|
|
234
|
+
it("should dispose websocket client when it exists", async () => {
|
|
235
|
+
const mockDispose = jest.fn();
|
|
236
|
+
(sdk as any).wsClient = { dispose: mockDispose };
|
|
237
|
+
|
|
238
|
+
await sdk.dispose();
|
|
239
|
+
|
|
240
|
+
expect(mockDispose).toHaveBeenCalled();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("should not throw error when websocket client is undefined", async () => {
|
|
244
|
+
(sdk as any).wsClient = undefined;
|
|
245
|
+
|
|
246
|
+
await expect(sdk.dispose()).resolves.not.toThrow();
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
describe("websocket configuration", () => {
|
|
251
|
+
it("should create websocket client when ws is true (default)", () => {
|
|
252
|
+
const createWebsocketClientSpy = jest.spyOn(
|
|
253
|
+
Codex.prototype as any,
|
|
254
|
+
"createWebsocketClient",
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
new Codex("test-key");
|
|
258
|
+
|
|
259
|
+
expect(createWebsocketClientSpy).toHaveBeenCalledWith(
|
|
260
|
+
expect.objectContaining({ ws: true }),
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
createWebsocketClientSpy.mockRestore();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("should not create websocket client when ws is false", () => {
|
|
267
|
+
const createWebsocketClientSpy = jest.spyOn(
|
|
268
|
+
Codex.prototype as any,
|
|
269
|
+
"createWebsocketClient",
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
new Codex("test-key", { ws: false });
|
|
273
|
+
|
|
274
|
+
expect(createWebsocketClientSpy).toHaveBeenCalledWith(
|
|
275
|
+
expect.objectContaining({ ws: false }),
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
createWebsocketClientSpy.mockRestore();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("should throw error when trying to subscribe without websocket enabled", () => {
|
|
282
|
+
const sdkWithoutWs = new Codex("test-key", { ws: false });
|
|
283
|
+
|
|
284
|
+
expect(() => {
|
|
285
|
+
sdkWithoutWs.subscribe(
|
|
286
|
+
subscribePriceUpdatedString,
|
|
287
|
+
{ address: "0xtoken", networkId: 1 },
|
|
288
|
+
{ next: jest.fn(), error: jest.fn(), complete: jest.fn() },
|
|
289
|
+
);
|
|
290
|
+
}).toThrow("Websocket is not enabled in the config");
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
41
294
|
describe("query", () => {
|
|
42
|
-
it("send a fetch request with the correct params", async () => {
|
|
295
|
+
it("should send a fetch request with the correct params", async () => {
|
|
43
296
|
const fetchSpy = jest
|
|
44
297
|
.spyOn(sdk["client"], "request")
|
|
45
298
|
.mockResolvedValue({} as unknown);
|
|
299
|
+
|
|
46
300
|
await sdk.query(getNetworksDocument, {});
|
|
301
|
+
|
|
47
302
|
expect(fetchSpy).toHaveBeenCalledWith(getNetworksDocument, {}, {});
|
|
48
303
|
});
|
|
304
|
+
|
|
305
|
+
it("should include request headers in the request", async () => {
|
|
306
|
+
const mockHeaders = { "Test-Header": "test-value" };
|
|
307
|
+
const getRequestHeadersSpy = jest
|
|
308
|
+
.spyOn(sdk as any, "getRequestHeaders")
|
|
309
|
+
.mockResolvedValue(mockHeaders);
|
|
310
|
+
const fetchSpy = jest
|
|
311
|
+
.spyOn(sdk["client"], "request")
|
|
312
|
+
.mockResolvedValue({} as unknown);
|
|
313
|
+
|
|
314
|
+
await sdk.query(getNetworksDocument, {});
|
|
315
|
+
|
|
316
|
+
expect(getRequestHeadersSpy).toHaveBeenCalled();
|
|
317
|
+
expect(fetchSpy).toHaveBeenCalledWith(
|
|
318
|
+
getNetworksDocument,
|
|
319
|
+
{},
|
|
320
|
+
mockHeaders,
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
getRequestHeadersSpy.mockRestore();
|
|
324
|
+
});
|
|
49
325
|
});
|
|
326
|
+
|
|
327
|
+
describe("mutation", () => {
|
|
328
|
+
it("should send a request with the correct params", async () => {
|
|
329
|
+
const fetchSpy = jest
|
|
330
|
+
.spyOn(sdk["client"], "request")
|
|
331
|
+
.mockResolvedValue({} as unknown);
|
|
332
|
+
|
|
333
|
+
await sdk.mutation(getNetworksDocument, {});
|
|
334
|
+
|
|
335
|
+
expect(fetchSpy).toHaveBeenCalledWith(getNetworksDocument, {}, {});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it("should include request headers in the request", async () => {
|
|
339
|
+
const mockHeaders = { "Test-Header": "test-value" };
|
|
340
|
+
const getRequestHeadersSpy = jest
|
|
341
|
+
.spyOn(sdk as any, "getRequestHeaders")
|
|
342
|
+
.mockResolvedValue(mockHeaders);
|
|
343
|
+
const fetchSpy = jest
|
|
344
|
+
.spyOn(sdk["client"], "request")
|
|
345
|
+
.mockResolvedValue({} as unknown);
|
|
346
|
+
|
|
347
|
+
await sdk.mutation(getNetworksDocument, {});
|
|
348
|
+
|
|
349
|
+
expect(getRequestHeadersSpy).toHaveBeenCalled();
|
|
350
|
+
expect(fetchSpy).toHaveBeenCalledWith(
|
|
351
|
+
getNetworksDocument,
|
|
352
|
+
{},
|
|
353
|
+
mockHeaders,
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
getRequestHeadersSpy.mockRestore();
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
50
360
|
describe("send", () => {
|
|
51
361
|
it("should return the results of the query", async () => {
|
|
52
362
|
const fetchSpy = jest
|
|
53
363
|
.spyOn(sdk["client"], "request")
|
|
54
364
|
.mockResolvedValue({} as unknown);
|
|
365
|
+
|
|
55
366
|
await sdk.send(getNetworksString, {});
|
|
367
|
+
|
|
56
368
|
expect(fetchSpy).toHaveBeenCalledWith(getNetworksString, {}, {});
|
|
57
369
|
});
|
|
370
|
+
|
|
371
|
+
it("should include request headers in the request", async () => {
|
|
372
|
+
const mockHeaders = { "Test-Header": "test-value" };
|
|
373
|
+
const getRequestHeadersSpy = jest
|
|
374
|
+
.spyOn(sdk as any, "getRequestHeaders")
|
|
375
|
+
.mockResolvedValue(mockHeaders);
|
|
376
|
+
const fetchSpy = jest
|
|
377
|
+
.spyOn(sdk["client"], "request")
|
|
378
|
+
.mockResolvedValue({} as unknown);
|
|
379
|
+
|
|
380
|
+
await sdk.send(getNetworksString, {});
|
|
381
|
+
|
|
382
|
+
expect(getRequestHeadersSpy).toHaveBeenCalled();
|
|
383
|
+
expect(fetchSpy).toHaveBeenCalledWith(getNetworksString, {}, mockHeaders);
|
|
384
|
+
|
|
385
|
+
getRequestHeadersSpy.mockRestore();
|
|
386
|
+
});
|
|
58
387
|
});
|
|
388
|
+
|
|
59
389
|
describe("subscribe", () => {
|
|
60
390
|
it("should return a cleanup function", () => {
|
|
61
|
-
const next = jest.fn()
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const sink = {
|
|
65
|
-
|
|
66
|
-
error,
|
|
67
|
-
complete,
|
|
68
|
-
};
|
|
391
|
+
const next = jest.fn();
|
|
392
|
+
const error = jest.fn();
|
|
393
|
+
const complete = jest.fn();
|
|
394
|
+
const sink = { next, error, complete };
|
|
395
|
+
|
|
69
396
|
jest.spyOn(sdk["wsClient"] as any, "subscribe").mockReturnValue(() => {});
|
|
397
|
+
|
|
70
398
|
const cleanup = sdk.subscribe(
|
|
71
399
|
subscribePriceUpdatedString,
|
|
72
400
|
{ address: "0xtoken", networkId: 1 },
|
|
73
401
|
sink,
|
|
74
402
|
);
|
|
403
|
+
|
|
75
404
|
expect(typeof cleanup).toBe("function");
|
|
76
405
|
});
|
|
406
|
+
|
|
407
|
+
it("should call wsClient.subscribe with correct parameters", () => {
|
|
408
|
+
const next = jest.fn();
|
|
409
|
+
const error = jest.fn();
|
|
410
|
+
const complete = jest.fn();
|
|
411
|
+
const sink = { next, error, complete };
|
|
412
|
+
const variables = { address: "0xtoken", networkId: 1 };
|
|
413
|
+
|
|
414
|
+
const subscribeSpy = jest
|
|
415
|
+
.spyOn(sdk["wsClient"] as any, "subscribe")
|
|
416
|
+
.mockReturnValue(() => {});
|
|
417
|
+
|
|
418
|
+
sdk.subscribe(subscribePriceUpdatedString, variables, sink);
|
|
419
|
+
|
|
420
|
+
expect(subscribeSpy).toHaveBeenCalledWith(
|
|
421
|
+
{
|
|
422
|
+
query: subscribePriceUpdatedString,
|
|
423
|
+
variables,
|
|
424
|
+
},
|
|
425
|
+
sink,
|
|
426
|
+
);
|
|
427
|
+
});
|
|
77
428
|
});
|
|
78
429
|
});
|
package/src/sdk/index.ts
CHANGED
|
@@ -48,17 +48,34 @@ export class Codex {
|
|
|
48
48
|
public mutations: Mutation;
|
|
49
49
|
public subscriptions: Subscribe;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @param apiKey - The api key to use for the requests.
|
|
53
|
+
* @param apiConfig - The configuration to use for the requests.
|
|
54
|
+
*/
|
|
51
55
|
constructor(
|
|
52
56
|
private apiKey: string,
|
|
53
57
|
private apiConfig?: Partial<ApiConfig>,
|
|
54
58
|
) {
|
|
55
|
-
|
|
56
|
-
const config = Object.assign({}, defaultConfig, apiConfig);
|
|
57
|
-
|
|
59
|
+
const config = this.parseConfig(this.apiConfig ?? {});
|
|
58
60
|
this.queries = new Query(this);
|
|
59
61
|
this.mutations = new Mutation(this);
|
|
60
62
|
this.subscriptions = new Subscribe(this);
|
|
61
|
-
|
|
63
|
+
|
|
64
|
+
this.client = this.createGraphQLClient(config);
|
|
65
|
+
this.wsClient = this.createWebsocketClient(config);
|
|
66
|
+
|
|
67
|
+
this.wsClient?.on("error", (error) => {
|
|
68
|
+
console.error("Websocket error: ", error);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private parseConfig(config: Partial<ApiConfig>) {
|
|
73
|
+
invariant(this.apiKey, "apiKey must be defined");
|
|
74
|
+
return Object.assign({}, defaultConfig, config);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private createGraphQLClient(config: ApiConfig) {
|
|
78
|
+
return new GraphQLClient(config.apiUrl, {
|
|
62
79
|
method: "POST",
|
|
63
80
|
headers: new Headers({
|
|
64
81
|
"Content-Type": "application/json",
|
|
@@ -67,7 +84,10 @@ export class Codex {
|
|
|
67
84
|
...config.headers,
|
|
68
85
|
}),
|
|
69
86
|
});
|
|
70
|
-
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private createWebsocketClient(config: ApiConfig) {
|
|
90
|
+
return config.ws
|
|
71
91
|
? createClient({
|
|
72
92
|
webSocketImpl: WebSocket,
|
|
73
93
|
keepAlive: 10_000, // ping server every 10 seconds
|
|
@@ -91,6 +111,51 @@ export class Codex {
|
|
|
91
111
|
return headers;
|
|
92
112
|
}
|
|
93
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Need to update the headers on the websocket connection.
|
|
116
|
+
* This is useful if the api key changes, or you need to modify the connection init params at all.
|
|
117
|
+
* NOTE: it will dispose of the old connection, so all existing subscriptions will be closed.
|
|
118
|
+
*/
|
|
119
|
+
public updateConfig(incomingConfig: Partial<ApiConfig>) {
|
|
120
|
+
// If we have an existing websocket connection, dispose of it.
|
|
121
|
+
if (this.wsClient) this.dispose();
|
|
122
|
+
|
|
123
|
+
// Merge the incoming config with the existing config.
|
|
124
|
+
const config = this.parseConfig(
|
|
125
|
+
Object.assign({}, this.apiConfig, incomingConfig),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// Create a new websocket connection with the new headers.
|
|
129
|
+
this.wsClient = this.createWebsocketClient(config);
|
|
130
|
+
this.client = this.createGraphQLClient(config);
|
|
131
|
+
|
|
132
|
+
this.wsClient?.on("error", (error) => {
|
|
133
|
+
console.error("Websocket error: ", error);
|
|
134
|
+
});
|
|
135
|
+
this.wsClient?.on("closed", (er) => {
|
|
136
|
+
console.log("Websocket closed", er);
|
|
137
|
+
});
|
|
138
|
+
this.wsClient?.on("connecting", () => {
|
|
139
|
+
console.log("Websocket connecting");
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Call this to dispose of the websocket connection, and make this class ready for garbage collection.
|
|
145
|
+
* This will also close any open subscriptions.
|
|
146
|
+
*
|
|
147
|
+
* It's useful for when you need to modify some of the configuration, or when you're done with the class.
|
|
148
|
+
*/
|
|
149
|
+
public async dispose() {
|
|
150
|
+
this.wsClient?.dispose();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* This is the preferred way to execute queries.
|
|
155
|
+
* @param doc - The graphql document node to execute.
|
|
156
|
+
* @param args - The variables to pass to the document.
|
|
157
|
+
* @returns The result of the query.
|
|
158
|
+
*/
|
|
94
159
|
public async query<TResults, TVars extends Variables>(
|
|
95
160
|
doc: TypedDocumentNode<TResults, TVars>,
|
|
96
161
|
args: TVars = {} as TVars,
|
|
@@ -103,6 +168,12 @@ export class Codex {
|
|
|
103
168
|
return res as TResults;
|
|
104
169
|
}
|
|
105
170
|
|
|
171
|
+
/**
|
|
172
|
+
* This is functionally the same thing as the `query` method, but it's more expressive.
|
|
173
|
+
* @param doc - The graphql document node to execute.
|
|
174
|
+
* @param args - The variables to pass to the document.
|
|
175
|
+
* @returns The result of the mutation.
|
|
176
|
+
*/
|
|
106
177
|
public async mutation<TResults, TVars extends Variables>(
|
|
107
178
|
doc: TypedDocumentNode<TResults, TVars>,
|
|
108
179
|
args: TVars = {} as TVars,
|
|
@@ -115,7 +186,13 @@ export class Codex {
|
|
|
115
186
|
return res as TResults;
|
|
116
187
|
}
|
|
117
188
|
|
|
118
|
-
|
|
189
|
+
/**
|
|
190
|
+
* This should be used when you don't want to use graphql libaries to create a document node,
|
|
191
|
+
* and would rather just pass in a string.
|
|
192
|
+
* @param gqlString - The graphql document string to execute.
|
|
193
|
+
* @param args - The variables to pass to the document.
|
|
194
|
+
* @returns The result of the mutation.
|
|
195
|
+
*/
|
|
119
196
|
public async send<TResults, V extends Variables = Variables>(
|
|
120
197
|
gqlString: string,
|
|
121
198
|
args: V = {} as V,
|
|
@@ -128,6 +205,12 @@ export class Codex {
|
|
|
128
205
|
return res;
|
|
129
206
|
}
|
|
130
207
|
|
|
208
|
+
/**
|
|
209
|
+
* @param doc - The graphql document string to execute.
|
|
210
|
+
* @param args - The variables to pass to the document.
|
|
211
|
+
* @param sink - The sink to receive the results.
|
|
212
|
+
* @returns A cleanup function to unsubscribe from the subscription.
|
|
213
|
+
*/
|
|
131
214
|
public subscribe<
|
|
132
215
|
TResults,
|
|
133
216
|
TVars extends Record<string, unknown> = Record<string, never>,
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
query GetSimulateTokenContractResults(
|
|
2
|
-
$contractAddress: String!
|
|
3
|
-
$cursor: String
|
|
4
|
-
$limit: Int
|
|
5
|
-
$networkId: Int!
|
|
6
|
-
$simulationId: String
|
|
7
|
-
) {
|
|
8
|
-
getSimulateTokenContractResults(
|
|
9
|
-
contractAddress: $contractAddress
|
|
10
|
-
cursor: $cursor
|
|
11
|
-
limit: $limit
|
|
12
|
-
networkId: $networkId
|
|
13
|
-
simulationId: $simulationId
|
|
14
|
-
) {
|
|
15
|
-
cursor
|
|
16
|
-
results {
|
|
17
|
-
analysisType
|
|
18
|
-
blockNumber
|
|
19
|
-
contractBalance {
|
|
20
|
-
tokenContractEthBalance
|
|
21
|
-
tokenContractTokenBalance
|
|
22
|
-
}
|
|
23
|
-
contractHashKey
|
|
24
|
-
creator {
|
|
25
|
-
creatorAddress
|
|
26
|
-
creatorEthBalance
|
|
27
|
-
creatorTokenBalance
|
|
28
|
-
}
|
|
29
|
-
deploy {
|
|
30
|
-
deploySuccess
|
|
31
|
-
tokenMintedToDeployer
|
|
32
|
-
}
|
|
33
|
-
errors {
|
|
34
|
-
contractBalanceErrors {
|
|
35
|
-
tokenContractEthBalanceError
|
|
36
|
-
tokenContractTokenBalanceError
|
|
37
|
-
}
|
|
38
|
-
creatorErrors {
|
|
39
|
-
creatorEthBalanceError
|
|
40
|
-
creatorTokenBalanceError
|
|
41
|
-
}
|
|
42
|
-
deployErrors {
|
|
43
|
-
deployError
|
|
44
|
-
tokenMintedToDeployerError
|
|
45
|
-
}
|
|
46
|
-
liquidityErrors {
|
|
47
|
-
addLiquidityError
|
|
48
|
-
lpTotalSupplyError
|
|
49
|
-
postLiquidityEnableTradingError
|
|
50
|
-
preLiquidityEnableTradingError
|
|
51
|
-
}
|
|
52
|
-
ownerErrors {
|
|
53
|
-
ownerAddressError
|
|
54
|
-
ownerEthBalanceError
|
|
55
|
-
ownerTokenBalanceError
|
|
56
|
-
}
|
|
57
|
-
simulatorError
|
|
58
|
-
swapErrors {
|
|
59
|
-
buyError
|
|
60
|
-
buyErrorEnum
|
|
61
|
-
sellError
|
|
62
|
-
sellErrorEnum
|
|
63
|
-
}
|
|
64
|
-
tokenErrors {
|
|
65
|
-
canRenounceOwnershipError
|
|
66
|
-
canTransferOwnershipError
|
|
67
|
-
decimalsError
|
|
68
|
-
tokenNameError
|
|
69
|
-
tokenSymbolError
|
|
70
|
-
totalSupplyError
|
|
71
|
-
}
|
|
72
|
-
transferErrors {
|
|
73
|
-
tokenContractApprovalError
|
|
74
|
-
tokenTransferredToContractError
|
|
75
|
-
userApprovalError
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
id
|
|
79
|
-
liquidity {
|
|
80
|
-
addLiquiditySuccess
|
|
81
|
-
liquiditySetByPreLiquidityOpenTradingCall
|
|
82
|
-
lpTotalSupply
|
|
83
|
-
pairAddress
|
|
84
|
-
postLiquidityEnableTradingCall
|
|
85
|
-
postLiquidityEnableTradingSuccess
|
|
86
|
-
preLiquidityEnableTradingCall
|
|
87
|
-
preLiquidityEnableTradingSuccess
|
|
88
|
-
preLiquidityEnableTradingSupportsTransfer
|
|
89
|
-
}
|
|
90
|
-
networkId
|
|
91
|
-
owner {
|
|
92
|
-
ownerAddress
|
|
93
|
-
ownerEthBalance
|
|
94
|
-
ownerTokenBalance
|
|
95
|
-
}
|
|
96
|
-
sortKey
|
|
97
|
-
status
|
|
98
|
-
swap {
|
|
99
|
-
buyGasUsed
|
|
100
|
-
buySuccess
|
|
101
|
-
buyTax
|
|
102
|
-
maxBuyAmount
|
|
103
|
-
maxSellAmount
|
|
104
|
-
sellGasUsed
|
|
105
|
-
sellSuccess
|
|
106
|
-
sellTax
|
|
107
|
-
}
|
|
108
|
-
timestamp
|
|
109
|
-
token {
|
|
110
|
-
canRenounceOwnership
|
|
111
|
-
canTransferOwnership
|
|
112
|
-
contractAddress
|
|
113
|
-
decimals
|
|
114
|
-
isOwnerRenounced
|
|
115
|
-
tokenName
|
|
116
|
-
tokenSymbol
|
|
117
|
-
totalSupply
|
|
118
|
-
}
|
|
119
|
-
transfer {
|
|
120
|
-
tokenContractApprovalSuccess
|
|
121
|
-
tokenTransferredToContractSuccess
|
|
122
|
-
userApprovalSuccess
|
|
123
|
-
}
|
|
124
|
-
uuid
|
|
125
|
-
uuidHashKey
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|