Skip to content
This repository was archived by the owner on Feb 22, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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": {
Expand Down
60 changes: 32 additions & 28 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -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] })
}
}
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
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"

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;

import * as server from "./server";

export {
synchronizers,
jobs,
utils,
webhooks,

Expand Down
18 changes: 17 additions & 1 deletion src/jobs/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
export * from "./types";
import {
JobsNetwork as Network,
JobsNetwoks as Networks,
JobStatus,
Job,
JobInput,
Provider,
} from "./types"

export {
Network,
Networks,
JobStatus,
Job,
JobInput,
Provider,
}
66 changes: 66 additions & 0 deletions src/jobs/jobs.ts
Original file line number Diff line number Diff line change
@@ -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<T>(requestPromise: Promise<AxiosResponse<{ data?: T, error?: string }>>): Promise<T> {
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<Job> {
const url = `/api/v1/jobs`;
return await this.handleRequest(this._client.post<{ data: Job, error?: string }>(url, { job }));
}

public async listJobs(): Promise<Job[]> {
const url = `/api/v1/jobs`;
return await this.handleRequest(this._client.get<{ data: Job[], error?: string }>(url));
}

public async startJob(id: string): Promise<void> {
const url = `/api/v1/jobs/${id}/start`;
await this.handleRequest(this._client.post<{ error?: string }>(url));
}

public async stopJob(id: string): Promise<void> {
const url = `/api/v1/jobs/${id}/stop`;
await this.handleRequest(this._client.post<{ error?: string }>(url));
}

public async deleteJob(id: string): Promise<void> {
const url = `/api/v1/jobs/${id}`;
await this.handleRequest(this._client.delete<{ error?: string }>(url));
}
}
45 changes: 43 additions & 2 deletions src/jobs/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,46 @@
import { type Subset } from "../utils";
import { Network } from "../utils/network";

export type JobNetwork = Subset<Network, "ethereum" | "polygon" | "mumbai">;
export const JobNetwoks: JobNetwork[] = ["ethereum", "polygon", "mumbai"];
export type JobsNetwork = Subset<Network, "ethereum" | "polygon" | "mumbai">;
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;
};
2 changes: 1 addition & 1 deletion src/server/evm-trigger-method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type TriggerEVMMethodConfig = {


export const TriggerEVMMethod = async (config: TriggerEVMMethodConfig): Promise<any> => {
if (typeof window === "undefined") {
if (typeof window !== "undefined") {
throw new Error("This function cannot be executed in a Browser environment");
}

Expand Down
Loading