Skip to content

Instantly share code, notes, and snippets.

@zhe-t
Created January 18, 2025 23:13
Show Gist options
  • Save zhe-t/9b9cf1b18e9204dc2c4ecead9a4ad037 to your computer and use it in GitHub Desktop.
Save zhe-t/9b9cf1b18e9204dc2c4ecead9a4ad037 to your computer and use it in GitHub Desktop.
HeliusAPIClient.ts
/**
* External dependencies
*/
import fetch from 'node-fetch';
/**
* Helius API request/response types
*/
type Webhook = {
webhookID: string;
wallet: string;
webhookURL: string;
transactionTypes: string[];
accountAddresses: string[];
webhookType: string;
authHeader: string;
}
type CreateWebhookData = {
webhookURL: string;
transactionTypes: string[];
accountAddresses: string[];
webhookType: string;
authHeader?: string;
}
type CreateWebhookResponse = Webhook;
type UpdateWebhookData = CreateWebhookData;
type UpdateWebhookResponse = Webhook;
type GetWebhookResponse = Webhook;
type GetAllWebhooksResponse = Webhook[];
enum HttpMethod {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
DELETE = 'DELETE',
}
/**
* Helius API client
*/
class HeliusAPIClient {
/**
* API key
*/
private readonly apiKey: string;
/**
* Base URL
*/
private readonly baseUrl: string;
constructor(apiKey: string, baseUrl: string = 'https://api.helius.xyz') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
static builder() {
return new HeliusAPIClientBuilder();
}
private async request<T, D = any>(method: HttpMethod, path: string, data?: D): Promise<T> {
if (!path) {
throw new Error('Path is required');
}
const url = `${this.baseUrl}/v0${path}?api-key=${this.apiKey}`;
const options: fetch.RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
};
if (method === HttpMethod.POST || method === HttpMethod.PUT) {
if (!data) {
throw new Error('Data is required for POST/PUT requests');
}
options.body = JSON.stringify(data);
}
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
}
const json = await response.json() as T;
return json;
} catch (error) {
throw new Error(`API request failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Creates a new webhook
*
* @param {CreateWebhookData} data - The webhook data
* @returns {Promise<CreateWebhookResponse>} The created webhook
*
* @example
* const webhook = await heliusClient.createWebhook({
* webhookURL: 'https://example.com/webhook',
* transactionTypes: ['transaction'],
* accountAddresses: ['0x123'],
* webhookType: 'transaction',
* authHeader: 'Bearer 123'
* });
*/
async createWebhook(data: CreateWebhookData): Promise<CreateWebhookResponse> {
return await this.request<CreateWebhookResponse, CreateWebhookData>(HttpMethod.POST, '/webhooks', data);
}
/**
* Updates an existing webhook
*
* @param {string} webhookId - The ID of the webhook to update
* @param {UpdateWebhookData} data - The webhook data
* @returns {Promise<UpdateWebhookResponse>} The updated webhook
*
* @example
* const webhook = await heliusClient.updateWebhook('123', {
* webhookURL: 'https://example.com/webhook',
* transactionTypes: ['transaction'],
* accountAddresses: ['0x123'],
* webhookType: 'transaction',
* authHeader: 'Bearer 123'
* });
*/
async updateWebhook(webhookId: string, data: UpdateWebhookData): Promise<UpdateWebhookResponse> {
return await this.request<UpdateWebhookResponse, UpdateWebhookData>(HttpMethod.PUT, `/webhooks/${webhookId}`, data);
}
/**
* Retrieves a webhook by its ID
*
* @param {string} webhookId - The ID of the webhook to retrieve
* @returns {Promise<GetWebhookResponse>} The retrieved webhook
*
* @example
* const webhook = await heliusClient.getWebhook('123');
*/
async getWebhook(webhookId: string): Promise<GetWebhookResponse> {
return await this.request<GetWebhookResponse>(HttpMethod.GET, `/webhooks/${webhookId}`);
}
/**
* Retrieves all webhooks
*
* @returns {Promise<GetAllWebhooksResponse>} The list of webhooks
*/
async getAllWebhooks(): Promise<GetAllWebhooksResponse> {
return await this.request<GetAllWebhooksResponse>(HttpMethod.GET, '/webhooks');
}
/**
* Deletes a webhook by its ID
*
* @param {string} webhookId - The ID of the webhook to delete
* @returns {Promise<boolean>} Whether the webhook was deleted successfully
*/
async deleteWebhook(webhookId: string): Promise<boolean> {
return await this.request<boolean>(HttpMethod.DELETE, `/webhooks/${webhookId}`);
}
}
/**
* Helius API client builder
*
* @example
* const heliusClient = HeliusAPIClient.builder()
* .withApiKey('sk-123')
* .build();
*/
class HeliusAPIClientBuilder {
private apiKey: string;
private baseUrl?: string;
withApiKey(apiKey: string) {
if (!apiKey) throw new Error('API key cannot be empty');
this.apiKey = apiKey;
return this;
}
withBaseUrl(baseUrl: string) {
if (!baseUrl) throw new Error('Base URL cannot be empty');
this.baseUrl = baseUrl;
return this;
}
build(): HeliusAPIClient {
if (!this.apiKey) {
throw new Error('API key is required');
}
return new HeliusAPIClient(this.apiKey, this.baseUrl);
}
}
export {
HeliusAPIClient,
HeliusAPIClientBuilder
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment