mirror of
https://github.com/lux-tel/websites.git
synced 2026-10-30 20:31:36 +00:00
270 lines
7.1 KiB
TypeScript
270 lines
7.1 KiB
TypeScript
import type { Address } from 'viem';
|
|
import type { Ed25519PublicKey } from './refine';
|
|
import type {
|
|
BlsExitSignatureResponse,
|
|
BlsRewardsResponse,
|
|
BlsRewardsSignatureResponse,
|
|
ContributionContractByKeyResponse,
|
|
ContributionContractResponse,
|
|
DailyRewardsResponse,
|
|
ExitLiquidationListResponse,
|
|
NetworkInfoResponse,
|
|
NodesBlsKeysResponse,
|
|
RegistrationsResponse,
|
|
StakesResponse,
|
|
} from './schema';
|
|
|
|
export interface RequestOptions {
|
|
endpoint: string;
|
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
body?: BodyInit;
|
|
}
|
|
|
|
export interface StakingBackendResponse<T> {
|
|
data: T | null;
|
|
status: number;
|
|
statusText: string;
|
|
}
|
|
|
|
export interface SSBClientConfig {
|
|
baseUrl: string;
|
|
logger?: typeof console;
|
|
errorOn404?: boolean;
|
|
debug?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Client for interacting with the Session Staking Backend API.
|
|
*/
|
|
export class SessionStakingClient {
|
|
readonly baseUrl: string;
|
|
private readonly debug?: boolean;
|
|
private readonly logger = console;
|
|
private readonly errorOn404: boolean = false;
|
|
|
|
constructor(config: SSBClientConfig) {
|
|
const { baseUrl, debug, logger, errorOn404 } = config;
|
|
this.debug = debug;
|
|
|
|
if (this.debug) {
|
|
this.logger.debug('Initializing session staking backend client');
|
|
}
|
|
|
|
if (logger) {
|
|
this.logger = logger;
|
|
}
|
|
|
|
this.baseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
|
|
if (!this.baseUrl) {
|
|
throw new Error('baseUrl is required');
|
|
}
|
|
|
|
if (errorOn404) {
|
|
this.errorOn404 = errorOn404;
|
|
}
|
|
}
|
|
|
|
private async request<T>({
|
|
endpoint,
|
|
method,
|
|
body,
|
|
}: RequestOptions): Promise<StakingBackendResponse<T>> {
|
|
const url = `${this.baseUrl}${endpoint}`;
|
|
|
|
try {
|
|
if (this.debug) {
|
|
this.logger.time(url);
|
|
if (body) this.logger.debug(body);
|
|
}
|
|
const res = await fetch(url, {
|
|
method,
|
|
body,
|
|
});
|
|
|
|
let data: T | null = null;
|
|
if (!res.ok) {
|
|
const errorMessage = `Staking Backend request failed (${res.status}): ${res.statusText}`;
|
|
if (this.errorOn404) {
|
|
throw new Error(errorMessage);
|
|
}
|
|
this.logger.error(errorMessage);
|
|
data = null;
|
|
} else {
|
|
data = await res.json();
|
|
}
|
|
|
|
return { data, status: res.status, statusText: res.statusText };
|
|
} finally {
|
|
if (this.debug) this.logger.timeEnd(url);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieves general network information.
|
|
* @returns Network information.
|
|
*/
|
|
public async getNetworkInfo(): Promise<StakingBackendResponse<NetworkInfoResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: '/info',
|
|
method: 'GET',
|
|
};
|
|
return await this.request<NetworkInfoResponse>(options);
|
|
}
|
|
|
|
public async getContributionContracts(): Promise<
|
|
StakingBackendResponse<ContributionContractResponse>
|
|
> {
|
|
const options: RequestOptions = {
|
|
endpoint: '/contract/contribution',
|
|
method: 'GET',
|
|
};
|
|
return await this.request<ContributionContractResponse>(options);
|
|
}
|
|
|
|
public async getContributionContractForNodePubkey({
|
|
nodePubKey,
|
|
}: {
|
|
nodePubKey: string;
|
|
}): Promise<StakingBackendResponse<ContributionContractByKeyResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/contract/contribution/${nodePubKey}`,
|
|
method: 'GET',
|
|
};
|
|
return await this.request<ContributionContractByKeyResponse>(options);
|
|
}
|
|
|
|
/**
|
|
* Retrieves service nodes associated with the given wallet address.
|
|
* @param address Wallet address.
|
|
* @returns stakes, historical stakes, and wallet information.
|
|
*/
|
|
public async getStakesForWalletAddress({
|
|
address,
|
|
}: {
|
|
address: string;
|
|
}): Promise<StakingBackendResponse<StakesResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/stakes/${address}`,
|
|
method: 'GET',
|
|
};
|
|
return await this.request<StakesResponse>(options);
|
|
}
|
|
|
|
public async getNodesBlsKeys(): Promise<StakingBackendResponse<NodesBlsKeysResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: '/nodes/bls',
|
|
method: 'GET',
|
|
};
|
|
return await this.request<NodesBlsKeysResponse>(options);
|
|
}
|
|
|
|
public async getRewardsInfo({
|
|
address,
|
|
}: {
|
|
address: string;
|
|
}): Promise<StakingBackendResponse<BlsRewardsResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/rewards/${address}`,
|
|
method: 'GET',
|
|
};
|
|
return await this.request<BlsRewardsResponse>(options);
|
|
}
|
|
|
|
/**
|
|
* Fetches the daily rewards information for a given address.
|
|
*
|
|
* @param address The address to fetch daily rewards information for.
|
|
* @returns daily rewards info.
|
|
*/
|
|
public async getDailyRewardsInfo({
|
|
address,
|
|
}: {
|
|
address: string;
|
|
}): Promise<StakingBackendResponse<DailyRewardsResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/daily-rewards/${address}`,
|
|
method: 'GET',
|
|
};
|
|
return await this.request<DailyRewardsResponse>(options);
|
|
}
|
|
|
|
public async getRewardsClaimSignature({
|
|
address,
|
|
}: {
|
|
address: string;
|
|
}): Promise<StakingBackendResponse<BlsRewardsSignatureResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/rewards/${address}`,
|
|
method: 'POST',
|
|
};
|
|
return await this.request<BlsRewardsSignatureResponse>(options);
|
|
}
|
|
|
|
public async getNodeExitSignatures({
|
|
nodePubKey,
|
|
}: {
|
|
nodePubKey: string;
|
|
}): Promise<StakingBackendResponse<BlsExitSignatureResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/exit/${nodePubKey}`,
|
|
method: 'GET',
|
|
};
|
|
return await this.request<BlsExitSignatureResponse>(options);
|
|
}
|
|
|
|
public async getNodeLiquidation({
|
|
nodePubKey,
|
|
}: {
|
|
nodePubKey: string;
|
|
}): Promise<StakingBackendResponse<BlsExitSignatureResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/liquidation/${nodePubKey}`,
|
|
method: 'GET',
|
|
};
|
|
return await this.request<BlsExitSignatureResponse>(options);
|
|
}
|
|
|
|
public async exitLiquidationList() {
|
|
const options: RequestOptions = {
|
|
endpoint: '/exit_liquidation_list',
|
|
method: 'GET',
|
|
};
|
|
return await this.request<ExitLiquidationListResponse>(options);
|
|
}
|
|
|
|
public async getNodes(): Promise<StakingBackendResponse<StakesResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: '/nodes',
|
|
method: 'GET',
|
|
};
|
|
return await this.request<StakesResponse>(options);
|
|
}
|
|
|
|
/**
|
|
* Retrieves stored registrations associated with the given operator wallet.
|
|
* @param operator Operator wallet address (Ethereum).
|
|
* @returns Registrations.
|
|
*/
|
|
public async getOperatorRegistrations({
|
|
operator,
|
|
}: {
|
|
operator: Address | Ed25519PublicKey;
|
|
}): Promise<StakingBackendResponse<RegistrationsResponse>> {
|
|
const options: RequestOptions = {
|
|
endpoint: `/registrations/${operator}`,
|
|
method: 'GET',
|
|
};
|
|
return await this.request<RegistrationsResponse>(options);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance of the SessionStakingClient.
|
|
*
|
|
* @param config The configuration object for the SSB client.
|
|
* @returns A new instance of the SessionStakingClient.
|
|
*/
|
|
export const createSessionStakingClient = (config: SSBClientConfig): SessionStakingClient =>
|
|
new SessionStakingClient(config);
|