diff --git a/package-lock.json b/package-lock.json index 3dec735..dfa328b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "darchlabs", - "version": "5.0.0", + "version": "6.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "darchlabs", - "version": "5.0.0", + "version": "6.0.0", "license": "ISC", "dependencies": { "axios": "^1.3.4", "body-parser": "^1.20.2", "buffer": "^6.0.3", "ethers": "^6.7.1", + "eventemitter3": "^5.0.1", "express": "^4.18.2" }, "devDependencies": { @@ -1995,6 +1996,11 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -6060,6 +6066,11 @@ } } }, + "eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, "execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", diff --git a/package.json b/package.json index ca0af7d..f97ea76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "darchlabs", - "version": "6.0.0", + "version": "6.3.0", "description": "The DarchLabs client is a Node.js library for interacting with the Synchronizers, Nodes and Jobs APIs. It provides an easy-to-use interface for managing data.", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -9,6 +9,7 @@ "body-parser": "^1.20.2", "buffer": "^6.0.3", "ethers": "^6.7.1", + "eventemitter3": "^5.0.1", "express": "^4.18.2" }, "scripts": { diff --git a/src/client.ts b/src/client.ts index 8c69aa0..aff0bd7 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,10 +1,12 @@ -import { Syncronizer } from "./synchronizers/synchronizers"; -import Axios from "axios"; +import EventEmitter from "eventemitter3"; +import { Syncronizers } from "./synchronizers/synchronizers"; +import { Jobs } from "./jobs/jobs"; +import Axios, { AxiosInstance } from "axios"; -type Services = "synchronizers" | "jobs" | "nodes"; +export type Service = "synchronizers" | "jobs" | "nodes"; -type ApiEndpointUrls = { - [key in Services]: string +export type ApiEndpointUrls = { + [key in Service]: string } const DEFAULT_URLS: ApiEndpointUrls = { @@ -13,46 +15,48 @@ const DEFAULT_URLS: ApiEndpointUrls = { "nodes": "https://nodes.darchlabs.com/" } -export class Darchlabs { - private apiKey: string; +export class Darchlabs extends EventEmitter { + private _apiKey: string; private _apiEndpoints: ApiEndpointUrls; - private _synchronizers: Syncronizer; + private _synchronizers: Syncronizers; + private _jobs: Jobs; constructor(apiKey: string = "", ApiEndpointUrls: ApiEndpointUrls = DEFAULT_URLS) { - this.apiKey = apiKey; + super(); + + this._apiKey = apiKey; this._apiEndpoints = ApiEndpointUrls; - const clientBase = { - headers: { - 'Content-Type': 'application/json', - } - }; + this._synchronizers = new Syncronizers(this.generateClient(this._apiKey, "synchronizers")) + this._jobs = new Jobs(this.generateClient(this._apiKey, "jobs")) + } - if (!apiKey || apiKey !== "") { - clientBase.headers["Authorization"] = `Bearer ${this.apiKey}` - } + public updateApiKey(apiKey: string) { + this._apiKey = apiKey; - this._synchronizers = new Syncronizer(Axios.create({ ...clientBase, baseURL: this._apiEndpoints.synchronizers })) + this._synchronizers = new Syncronizers(this.generateClient(this._apiKey, "synchronizers")) + this._jobs = new Jobs(this.generateClient(this._apiKey, "jobs")) } - public updateApiKey(apiKey: string) { - this.apiKey = apiKey; + get synchronizers() { + return this._synchronizers; + } + + get jobs() { + return this._jobs; + } - // define new client + private generateClient(token: string, service: Service): AxiosInstance { const clientBase = { headers: { 'Content-Type': 'application/json', } }; - if (!apiKey || apiKey !== "") { - clientBase.headers["Authorization"] = `Bearer ${this.apiKey}` + if (!token || token !== "") { + clientBase.headers["Authorization"] = `Bearer ${token}` } - this._synchronizers.setClient(Axios.create({ ...clientBase, baseURL: this._apiEndpoints.synchronizers })) - } - - get synchronizers() { - return this._synchronizers; + return Axios.create({ ...clientBase, baseURL: this._apiEndpoints[service] }) } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index ed965a5..4effae0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,8 @@ export * from "./nodes"; -export * from "./jobs"; export * from "./backoffice" import * as synchronizers from "./synchronizers" +import * as jobs from "./jobs" import * as utils from "./utils"; import * as webhooks from "./webhooks" @@ -10,6 +10,7 @@ import * as pagination from "./utils/pagination"; import * as abi from "./utils/abi"; import * as network from "./utils/network"; +export * from "./client" import { Darchlabs } from "./client" export default Darchlabs; @@ -17,6 +18,7 @@ import * as server from "./server"; export { synchronizers, + jobs, utils, webhooks, diff --git a/src/jobs/index.ts b/src/jobs/index.ts index b133371..74f1791 100644 --- a/src/jobs/index.ts +++ b/src/jobs/index.ts @@ -1 +1,17 @@ -export * from "./types"; \ No newline at end of file +import { + JobsNetwork as Network, + JobsNetwoks as Networks, + JobStatus, + Job, + JobInput, + Provider, +} from "./types" + +export { + Network, + Networks, + JobStatus, + Job, + JobInput, + Provider, +} diff --git a/src/jobs/jobs.ts b/src/jobs/jobs.ts new file mode 100644 index 0000000..92ed8a4 --- /dev/null +++ b/src/jobs/jobs.ts @@ -0,0 +1,66 @@ +import { AxiosInstance, AxiosResponse, isAxiosError } from "axios"; +import { JobInput, Job } from "./types"; + +export class Jobs { + private _client: AxiosInstance; + + constructor(client: AxiosInstance) { + this._client = client; + } + + public setClient(client: AxiosInstance) { + this._client = client; + } + + private async handleRequest(requestPromise: Promise>): Promise { + try { + // make request and check if response is valid + const response = await requestPromise; + if (!response) { + throw new Error("Error: Server did not respond, please try again later."); + } + + // get data and status code from response + const { status, data } = response; + if (status !== 200 && status !== 201) { + if (data?.error) { + throw new Error(data.error); + } + + throw new Error(`Error: Received status code ${status}`); + } + + return data?.data!; + } catch (err) { + if (isAxiosError(err) && err?.response?.data?.error) { + throw new Error(err.response.data.error); + } + throw err; + } + } + + public async createJob(job: JobInput): Promise { + const url = `/api/v1/jobs`; + return await this.handleRequest(this._client.post<{ data: Job, error?: string }>(url, { job })); + } + + public async listJobs(): Promise { + const url = `/api/v1/jobs`; + return await this.handleRequest(this._client.get<{ data: Job[], error?: string }>(url)); + } + + public async startJob(id: string): Promise { + const url = `/api/v1/jobs/${id}/start`; + await this.handleRequest(this._client.post<{ error?: string }>(url)); + } + + public async stopJob(id: string): Promise { + const url = `/api/v1/jobs/${id}/stop`; + await this.handleRequest(this._client.post<{ error?: string }>(url)); + } + + public async deleteJob(id: string): Promise { + const url = `/api/v1/jobs/${id}`; + await this.handleRequest(this._client.delete<{ error?: string }>(url)); + } +} \ No newline at end of file diff --git a/src/jobs/types.ts b/src/jobs/types.ts index a5c1571..cbb9630 100644 --- a/src/jobs/types.ts +++ b/src/jobs/types.ts @@ -1,5 +1,46 @@ import { type Subset } from "../utils"; import { Network } from "../utils/network"; -export type JobNetwork = Subset; -export const JobNetwoks: JobNetwork[] = ["ethereum", "polygon", "mumbai"]; \ No newline at end of file +export type JobsNetwork = Subset; +export const JobsNetwoks: JobsNetwork[] = ["ethereum", "polygon", "mumbai"]; + +export type JobStatus = "idle" | "running" | "stopped" | "autoStopped" | "error"; + +export type Job = { + id: string; + name: string; + providerId: string; + status: JobStatus; + network: Network; + address: string; + abi: string; + nodeUrl: string; + privateKey: string; + type: string; + cronjob: string; + checkMethod: string; + actionMethod: string; + createdAt: string; + updatedAt: string; + logs: string[]; +}; + +export type Provider = { + id: string; + name: string; + networks: Network[]; +}; + +export type JobInput = { + name: string; + providerId: string; + network: Network; + address: string; + nodeUrl: string; + privateKey: string; + abi: string; + type: "cronjob"; + cronjob: string; + checkMethod: string; + actionMethod: string; +}; diff --git a/src/server/evm-trigger-method.ts b/src/server/evm-trigger-method.ts index 834634b..8504b87 100644 --- a/src/server/evm-trigger-method.ts +++ b/src/server/evm-trigger-method.ts @@ -12,7 +12,7 @@ export type TriggerEVMMethodConfig = { export const TriggerEVMMethod = async (config: TriggerEVMMethodConfig): Promise => { - if (typeof window === "undefined") { + if (typeof window !== "undefined") { throw new Error("This function cannot be executed in a Browser environment"); } diff --git a/src/synchronizers/contracts/contracts.ts b/src/synchronizers/contracts/contracts.ts index 244e597..b669e3a 100644 --- a/src/synchronizers/contracts/contracts.ts +++ b/src/synchronizers/contracts/contracts.ts @@ -1,8 +1,7 @@ -import { AxiosInstance } from "axios"; +import { AxiosInstance, AxiosResponse, isAxiosError } from "axios"; import { Options, Pagination } from "../../utils/pagination"; import { ContractsResponse } from "./responses"; - -import { Contract, type ContractInput } from "./types"; +import { Contract, ContractInput } from "./types"; export class ContractClient { private _client: AxiosInstance; @@ -15,16 +14,39 @@ export class ContractClient { this._client = client; } - public async createContract(contract: ContractInput): Promise { - const url = `/api/v1/smartcontracts`; - const { data } = await this._client.post<{ data: Contract, error: string }>(url, { smartcontract: contract }); - // TODO(ca): check status code - - if (data?.error && data?.error !== "") { - throw new Error(data.error) + private async handleRequest( + requestPromise: Promise> + ): Promise<{ data: T; meta: any }> { + try { + // make request and check if response is valid + const response = await requestPromise; + if (!response) { + throw new Error("Error: Server did not respond, please try again later."); + } + + // get data and status code from response + const { status, data } = response; + if (status !== 200 && status !== 201) { + if (data?.error) { + throw new Error(data.error); + } + throw new Error(`Error: Received status code ${status}`); + } + + return { data: data?.data, meta: data?.meta }; + } catch (err) { + if (isAxiosError(err) && err?.response?.data?.error) { + throw new Error(err.response.data.error); + } + + throw err; } + } - return data?.data; + public async createContract(contract: ContractInput): Promise { + const url = `/api/v1/smartcontracts`; + const response = await this.handleRequest(this._client.post<{ data: Contract, error?: string }>(url, { smartcontract: contract })); + return response.data; } public async listContracts(options?: Options): Promise { @@ -34,36 +56,28 @@ export class ContractClient { if (options?.sort) params.sort = options.sort; const url = `/api/v1/smartcontracts`; - const { data } = await this._client.get<{ data: Contract[], meta: { pagination: Pagination } }>(url, { params }); - // TODO(ca): check status code + const response = await this.handleRequest( + this._client.get<{ data: Contract[], meta: { pagination: Pagination }, error?: string }>(url, { params }) + ); - return { contracts: data?.data, pagination: data?.meta?.pagination }; + return { contracts: response.data, pagination: response.meta?.pagination }; } public async deleteContractByAddress(address: string): Promise { const url = `/api/v1/smartcontracts/${address}`; - await this._client.delete(url); - // TODO(ca): check status code - - return + await this.handleRequest(this._client.delete<{ error?: string }>(url)); } public async restartContractByAddress(address: string): Promise { const url = `/api/v1/smartcontracts/${address}/restart`; - await this._client.post(url); - // TODO(ca): check status code - - return + await this.handleRequest(this._client.post<{ error?: string }>(url)); } public async updateContract( address: string, - data: { name: string; nodeURL: string; webhook: string } + input: { name: string; nodeURL: string; webhook: string } ): Promise { const url = `/api/v1/smartcontracts/${address}`; - await this._client.patch(url, { smartcontract: data }); - // TODO(ca): check status code - - return + await this.handleRequest(this._client.patch<{ error?: string }>(url, { smartcontract: input })); } } diff --git a/src/synchronizers/events/events.ts b/src/synchronizers/events/events.ts index d2f2aec..7eba287 100644 --- a/src/synchronizers/events/events.ts +++ b/src/synchronizers/events/events.ts @@ -1,4 +1,4 @@ -import { AxiosInstance } from "axios"; +import { AxiosInstance, AxiosResponse, isAxiosError } from "axios"; import { Options, Pagination } from "../../utils/pagination"; import { Event, EventData } from "./types"; import { @@ -17,6 +17,35 @@ export class EventClient { this._client = client; } + private async handleRequest( + requestPromise: Promise> + ): Promise<{ data: T; meta: any }> { + try { + // make request and check if response is valid + const response = await requestPromise; + if (!response) { + throw new Error("Error: Server did not respond, please try again later."); + } + + // get data and status code from response + const { status, data } = response; + if (status !== 200 && status !== 201) { + if (data?.error) { + throw new Error(data.error); + } + throw new Error(`Error: Received status code ${status}`); + } + + return { data: data?.data, meta: data?.meta }; + } catch (err) { + if (isAxiosError(err) && err?.response?.data?.error) { + throw new Error(err.response.data.error); + } + + throw err; + } + } + public async listEventsByAddress(address: string, options?: Options): Promise { const params: any = {}; if (options?.limit) params.limit = options.limit; @@ -24,10 +53,11 @@ export class EventClient { if (options?.sort) params.sort = options.sort; const url = `/api/v1/events/${address}`; - const { data } = await this._client.get<{ data: Event[], meta: { pagination: Pagination } }>(url, { params }); - // TODO(ca): check status code + const response = await this.handleRequest( + this._client.get<{ data: Event[], meta: { pagination: Pagination }, error?: string }>(url, { params }) + ); - return { events: data?.data, pagination: data?.meta?.pagination }; + return { events: response.data, pagination: response.meta?.pagination }; } public async listEventData( @@ -41,9 +71,10 @@ export class EventClient { if (options?.sort) params.sort = options.sort; const url = `/api/v1/events/${address}/${eventName}/data`; - const { data } = await this._client.get<{ data: EventData[], meta: { pagination: Pagination, event: Event } }>(url, { params }); - // TODO(ca): check status code + const response = await this.handleRequest( + this._client.get<{ data: EventData[], meta: { pagination: Pagination, event: Event }, error?: string }>(url, { params }) + ); - return { datas: data?.data, pagination: data?.meta?.pagination, event: data?.meta?.event }; + return { datas: response.data, pagination: response.meta?.pagination, event: response.meta?.event }; } -} +} \ No newline at end of file diff --git a/src/synchronizers/synchronizers.ts b/src/synchronizers/synchronizers.ts index c6bcb6d..2b8885f 100644 --- a/src/synchronizers/synchronizers.ts +++ b/src/synchronizers/synchronizers.ts @@ -2,7 +2,7 @@ import { AxiosInstance } from "axios"; import { ContractClient } from "./contracts/contracts"; import { EventClient } from "./events/events"; -export class Syncronizer { +export class Syncronizers { private _contracts: ContractClient; private _events: EventClient; diff --git a/src/tests/base.ts b/src/tests/base.ts deleted file mode 100644 index fa597dd..0000000 --- a/src/tests/base.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { EventInput } from "../index"; - -export const baseAddress = "0xc13530546feA5fC787A2d126bB39bDeC20C4cc9e"; - -export const baseEventInput: EventInput = { - network: "polygon", - nodeURL: "https://polygon-mumbai.g.alchemy.com/v2/_fQt29PoLS69dpof_XX_P6ziiJY7-U4I", - abi: { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: "uint256", - name: "amount", - type: "uint256", - }, - { - indexed: true, - internalType: "address", - name: "userAddr", - type: "address", - }, - { - indexed: false, - internalType: "uint256", - name: "amount1", - type: "uint256", - }, - { - indexed: true, - internalType: "uint256", - name: "num", - type: "uint256", - }, - { - indexed: true, - internalType: "string", - name: "lala", - type: "string", - }, - { - indexed: false, - internalType: "string", - name: "lala2", - type: "string", - }, - ], - name: "Example", - type: "event", - }, -}; - -export type baseEventDataExample = { - num: number; - lala: string; - lala2: string; - amount: number; - amount1: number; - userAddr: string; -}; - -export const baseEventStatuses = ["synching", "running", "stopped", "error"]; - -export const Sleep = (ms: number): Promise => { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, ms); - }); -}; diff --git a/src/tests/synchonizers/delete-event.test.ts b/src/tests/synchonizers/delete-event.test.ts deleted file mode 100644 index 079cf8c..0000000 --- a/src/tests/synchonizers/delete-event.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { EventInput, Synchronizers, DeleteEventResponse } from "../../index"; -import { baseAddress, baseEventInput } from "../base"; - -describe("Synchronizers", () => { - console.log("======="); - console.log("======="); - console.log("======="); - console.log("======="); - console.log("======="); - console.log("======="); - console.log("=======", process.env.BASE_URL); - - const baseUrl = process.env.BASE_URL!; - const eventInput: EventInput = baseEventInput; - const addressInput = baseAddress; - let synchronizers: Synchronizers; - - beforeAll(async () => { - synchronizers = new Synchronizers(baseUrl); - await synchronizers.insertEvent(addressInput, eventInput); - }); - - test("deletes event successfully", async () => { - // Delete the event - const deleteResponse: DeleteEventResponse = await synchronizers.deleteEvent(addressInput, eventInput.abi.name); - expect(deleteResponse).toBeDefined(); - }); - - test("throws 500 error when trying to delete non-existent event", async () => { - try { - await synchronizers.deleteEvent(addressInput, eventInput.abi.name); - } catch (error) { - expect(error).toBeDefined(); - expect(error.response.status).toBe(409); - expect(error.response.data.error).toBe( - `event does not exist with address=${addressInput} event_name=${eventInput.abi.name}` - ); - } - }); -}); diff --git a/src/tests/synchonizers/get-event.test.ts b/src/tests/synchonizers/get-event.test.ts deleted file mode 100644 index 4d18d2f..0000000 --- a/src/tests/synchonizers/get-event.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { EventInput, Synchronizers, GetEventResponse } from "../../index"; -import { baseAddress, baseEventInput, baseEventStatuses } from "../base"; - -describe("Synchronizers", () => { - const baseUrl = process.env.BASE_URL!; - const eventInput: EventInput = baseEventInput; - const addressInput = baseAddress; - let synchronizers: Synchronizers; - - beforeAll(async () => { - synchronizers = new Synchronizers(baseUrl); - await synchronizers.insertEvent(addressInput, eventInput); - }); - - afterAll(async () => { - await synchronizers.deleteEvent(addressInput, eventInput.abi.name); - }); - - describe("getEvent", () => { - test("should return the event with the given address and name", async () => { - const response: GetEventResponse = await synchronizers.getEvent(addressInput, eventInput.abi.name); - expect(response).toBeDefined(); - expect(response.data.address).toBe(addressInput); - expect(response.data.network).toBe(eventInput.network); - expect(response.data.latestBlockNumber).toBeGreaterThanOrEqual(0); - expect(response.data.nodeURL).toBe(eventInput.nodeURL); - expect(baseEventStatuses).toContain(response.data.status); - expect(response.data.createdAt).toBeDefined(); - expect(response.data.updatedAt).toBeDefined(); - }); - - test("should return an error when the requested event does not exist", async () => { - const address = "0x1234567890abcdef1234567890abcdef12345678"; - const eventName = "NonexistentEvent"; - - try { - await synchronizers.getEvent(address, eventName); - } catch (error) { - expect(error.response.status).toBe(409); - expect(error.response.data.error).toBe("sql: no rows in result set"); - } - }); - }); -}); diff --git a/src/tests/synchonizers/insert-event.test.ts b/src/tests/synchonizers/insert-event.test.ts deleted file mode 100644 index 23d254d..0000000 --- a/src/tests/synchonizers/insert-event.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Synchronizers, EventInput, InsertEventResponse } from "../../index"; -import { baseAddress, baseEventInput, baseEventStatuses } from "../base"; - -describe("Synchronizers", () => { - const baseUrl = process.env.BASE_URL!; - const eventInput: EventInput = baseEventInput; - const addressInput = baseAddress; - let synchronizers: Synchronizers; - - beforeAll(async () => { - synchronizers = new Synchronizers(baseUrl); - }); - - afterAll(async () => { - await synchronizers.deleteEvent(addressInput, eventInput.abi.name); - }); - - describe("insertEvent tests", () => { - it("should insert an event successfully", async () => { - const response: InsertEventResponse = await synchronizers.insertEvent(addressInput, eventInput); - expect(response).toBeDefined(); - - const { data: event } = response; - expect(event.id).toBeDefined(); - expect(event.address).toBe(addressInput); - expect(event.network).toBe(eventInput.network); - expect(event.latestBlockNumber).toBeGreaterThanOrEqual(0); - expect(event.nodeURL).toBe(eventInput.nodeURL); - expect(baseEventStatuses).toContain(event.status); - expect(event.createdAt).toBeDefined(); - expect(event.updatedAt).toBeDefined(); - - // TODO(ca): test inside abi object and abi inputs array - expect(event.abi.name).toBe(eventInput.abi.name); - }); - - test("should throw an error if trying to insert an existing event", async () => { - try { - await synchronizers.insertEvent(addressInput, eventInput); - } catch (error) { - expect(error).toBeDefined(); - expect(error.response.status).toBe(500); - expect(error.response.data.error).toBe( - `event already exists with address=${addressInput} and eventName=${eventInput.abi.name}` - ); - } - }); - }); -}); diff --git a/src/tests/synchonizers/list-event-data.test.ts b/src/tests/synchonizers/list-event-data.test.ts deleted file mode 100644 index 1972689..0000000 --- a/src/tests/synchonizers/list-event-data.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { Synchronizers, ListEventDataResponse, EventInput, Options } from "../../index"; -import { baseAddress, baseEventDataExample, baseEventInput, baseEventStatuses, Sleep } from "../base"; - -describe("Synchronizers", () => { - const baseUrl = process.env.BASE_URL!; - const eventInput: EventInput = baseEventInput; - const addressInput = baseAddress; - let synchronizers: Synchronizers; - - beforeAll(async () => { - synchronizers = new Synchronizers(baseUrl); - await synchronizers.insertEvent(addressInput, eventInput); - await Sleep(10000); - }); - - afterAll(async () => { - await synchronizers.deleteEvent(addressInput, eventInput.abi.name); - }); - - describe("listEvents", () => { - test("should get a list of events data without options", async () => { - const response: ListEventDataResponse = - await synchronizers.listEventData(addressInput, eventInput.abi.name); - - expect(response).toBeDefined(); - expect(response.data).toBeInstanceOf(Array); - expect(response.meta).toBeDefined(); - const { cronjob, pagination, event } = response.meta; - - const [eventData] = response.data; - expect(eventData).toBeDefined(); - expect(eventData.id).toBeDefined(); - expect(eventData.eventId).toBe(response.meta.event.id); - expect(eventData.blockNumber).toBeGreaterThanOrEqual(0); - expect(eventData.createdAt).toBeDefined(); - - const { data } = eventData; - expect(data.num).toBeDefined(); - expect(data.lala).toBeDefined(); - expect(data.lala2).toBeDefined(); - expect(data.amount).toBeDefined(); - expect(data.amount1).toBeDefined(); - expect(data.userAddr).toBeDefined(); - - expect(cronjob).toBeDefined(); - expect(cronjob.error).toBeDefined(); - expect(cronjob.seconds).toBeDefined(); - expect(cronjob.status).toBeDefined(); - - expect(pagination).toBeDefined(); - expect(pagination.limit).toBeDefined(); - expect(pagination.page).toBeDefined(); - expect(pagination.sort).toBeDefined(); - expect(pagination.totalElements).toBeDefined(); - expect(pagination.totalPages).toBeDefined(); - - expect(event).toBeDefined(); - expect(event.id).toBeDefined(); - expect(event.address).toBe(addressInput); - expect(event.network).toBe(eventInput.network); - expect(event.latestBlockNumber).toBeGreaterThanOrEqual(0); - expect(event.nodeURL).toBe(eventInput.nodeURL); - expect(baseEventStatuses).toContain(event.status); - expect(event.createdAt).toBeDefined(); - expect(event.updatedAt).toBeDefined(); - - // TODO(ca): test inside abi object and abi inputs array - expect(event.abi.name).toBe(eventInput.abi.name); - }); - - test("should get a list of events data with options", async () => { - const opts: Options = { - limit: 10, - page: 1, - sort: "desc", - }; - - const response: ListEventDataResponse = - await synchronizers.listEventData(addressInput, eventInput.abi.name, opts); - - expect(response).toBeDefined(); - expect(response.data).toBeInstanceOf(Array); - expect(response.meta).toBeDefined(); - const { cronjob, pagination, event } = response.meta; - - const [eventData] = response.data; - expect(eventData).toBeDefined(); - expect(eventData.id).toBeDefined(); - expect(eventData.eventId).toBe(response.meta.event.id); - expect(eventData.blockNumber).toBeGreaterThanOrEqual(0); - expect(eventData.createdAt).toBeDefined(); - - const { data } = eventData; - expect(data.num).toBeDefined(); - expect(data.lala).toBeDefined(); - expect(data.lala2).toBeDefined(); - expect(data.amount).toBeDefined(); - expect(data.amount1).toBeDefined(); - expect(data.userAddr).toBeDefined(); - - expect(cronjob).toBeDefined(); - expect(cronjob.error).toBeDefined(); - expect(cronjob.seconds).toBeDefined(); - expect(cronjob.status).toBeDefined(); - - expect(pagination).toBeDefined(); - expect(pagination.limit).toBeDefined(); - expect(pagination.page).toBeDefined(); - expect(pagination.sort).toBeDefined(); - expect(pagination.totalElements).toBeDefined(); - expect(pagination.totalPages).toBeDefined(); - - expect(event).toBeDefined(); - expect(event.id).toBeDefined(); - expect(event.address).toBe(addressInput); - expect(event.network).toBe(eventInput.network); - expect(event.latestBlockNumber).toBeGreaterThanOrEqual(0); - expect(event.nodeURL).toBe(eventInput.nodeURL); - expect(baseEventStatuses).toContain(event.status); - expect(event.createdAt).toBeDefined(); - expect(event.updatedAt).toBeDefined(); - - // TODO(ca): test inside abi object and abi inputs array - expect(event.abi.name).toBe(eventInput.abi.name); - }); - }); -}); diff --git a/src/tests/synchonizers/list-events.test.ts b/src/tests/synchonizers/list-events.test.ts deleted file mode 100644 index 94562c0..0000000 --- a/src/tests/synchonizers/list-events.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Synchronizers, Options, ListEventsResponse, EventInput } from "../../index"; -import { baseAddress, baseEventInput, baseEventStatuses } from "../base"; - -describe("Synchronizers", () => { - const baseUrl = process.env.BASE_URL!; - const eventInput: EventInput = baseEventInput; - const addressInput = baseAddress; - let synchronizers: Synchronizers; - - beforeAll(async () => { - synchronizers = new Synchronizers(baseUrl); - await synchronizers.insertEvent(addressInput, eventInput); - }); - - afterAll(async () => { - await synchronizers.deleteEvent(addressInput, eventInput.abi.name); - }); - - describe("listEvents", () => { - test("should get a list of events without options", async () => { - const response: ListEventsResponse = await synchronizers.listEvents(); - expect(response).toBeDefined(); - expect(response.data).toBeInstanceOf(Array); - expect(response.meta).toBeDefined(); - const { cronjob, pagination } = response.meta; - - const event = response.data.find((e) => e.address === addressInput)!; - expect(event).toBeDefined(); - expect(event.address).toBe(addressInput); - expect(event.network).toBe(eventInput.network); - expect(event.latestBlockNumber).toBeGreaterThanOrEqual(0); - expect(event.nodeURL).toBe(eventInput.nodeURL); - expect(baseEventStatuses).toContain(event.status); - expect(event.createdAt).toBeDefined(); - expect(event.updatedAt).toBeDefined(); - - // TODO(ca): test inside abi object and abi inputs array - expect(event.abi.name).toBe(eventInput.abi.name); - - expect(cronjob).toBeDefined(); - expect(cronjob.error).toBeDefined(); - expect(cronjob.seconds).toBeDefined(); - expect(cronjob.status).toBeDefined(); - - expect(pagination).toBeDefined(); - expect(pagination.limit).toBeDefined(); - expect(pagination.page).toBeDefined(); - expect(pagination.sort).toBeDefined(); - expect(pagination.totalElements).toBeDefined(); - expect(pagination.totalPages).toBeDefined(); - }); - - test("should get a list of events with options", async () => { - const opts: Options = { - limit: 10, - page: 1, - sort: "asc", - }; - const response: ListEventsResponse = await synchronizers.listEvents(opts); - expect(response).toBeDefined(); - expect(response.data).toBeInstanceOf(Array); - expect(response.meta).toBeDefined(); - const { cronjob, pagination } = response.meta; - - const event = response.data.find((e) => e.address === addressInput)!; - expect(event).toBeDefined(); - expect(event.id).toBeDefined(); - expect(event.address).toBe(addressInput); - expect(event.network).toBe(eventInput.network); - expect(event.latestBlockNumber).toBeGreaterThanOrEqual(0); - expect(event.nodeURL).toBe(eventInput.nodeURL); - expect(baseEventStatuses).toContain(event.status); - expect(event.createdAt).toBeDefined(); - expect(event.updatedAt).toBeDefined(); - - // TODO(ca): test inside abi object and abi inputs array - expect(event.abi.name).toBe(eventInput.abi.name); - - expect(cronjob).toBeDefined(); - expect(cronjob.error).toBeDefined(); - expect(cronjob.seconds).toBeDefined(); - expect(cronjob.status).toBeDefined(); - - expect(pagination.limit).toBeDefined(); - expect(pagination.page).toBeDefined(); - expect(pagination.sort).toBeDefined(); - expect(pagination.totalElements).toBeDefined(); - expect(pagination.totalPages).toBeDefined(); - }); - }); -});