@solsdk/jito-ts
Version:
## What is it and why do you need it?
157 lines (137 loc) • 5.08 kB
text/typescript
import {
ChannelCredentials,
ChannelOptions,
ClientReadableStream,
ServiceError,
} from '@grpc/grpc-js';
import {PublicKey} from '@solana/web3.js';
import {authInterceptor} from './auth';
import {
GetHeartbeatIntervalResponse,
GeyserClient as GeyserClientStub,
TimestampedAccountUpdate,
TimestampedBlockUpdate,
} from '../../gen/geyser/geyser';
export class GeyserClient {
private client: GeyserClientStub;
constructor(client: GeyserClientStub) {
this.client = client;
}
/**
* Retrieves the heartbeat interval in milliseconds from the server.
*
* @returns A Promise that resolves to a number representing the heartbeat interval in milliseconds.
* @throws A ServiceError if there's an issue with the server while fetching the heartbeat interval.
*/
async getHeartbeatIntervalMillis(): Promise<number> {
return new Promise((resolve, reject) => {
this.client.getHeartbeatInterval(
{},
async (e: ServiceError | null, resp: GetHeartbeatIntervalResponse) => {
if (e) {
reject(e);
} else {
resolve(resp.heartbeatIntervalMs);
}
}
);
});
}
/**
* Triggers the supplied callback on an update of the provided accounts of interest.
*
* @param accountsOfInterest - An array of PublicKeys of the accounts to subscribe for updates.
* @param successCallback - A callback function that receives a TimestampedAccountUpdate object whenever updates are available.
* @param errorCallback - A callback function that is triggered whenever an error occurs during the subscription process.
* @returns A function that can be called to cancel the subscription.
*/
onAccountUpdate(
accountsOfInterest: PublicKey[],
successCallback: (resp: TimestampedAccountUpdate) => void,
errorCallback: (e: Error) => void
): () => void {
const accounts = accountsOfInterest.map(a => a.toBytes());
const stream: ClientReadableStream<TimestampedAccountUpdate> =
this.client.subscribeAccountUpdates({accounts});
stream.on('readable', () => {
const msg = stream.read(1);
if (msg) {
successCallback(msg);
}
});
stream.on('error', e =>
errorCallback(new Error(`Stream error: ${e.message}`))
);
return () => stream.cancel();
}
/**
* Triggers the supplied callback on an account update owned by the provided programs of interest.
*
* @param programsOfInterest - An array of PublicKeys of the programs to subscribe for updates.
* @param successCallback - A callback function that receives a TimestampedAccountUpdate object whenever updates are available.
* @param errorCallback - A callback function that is triggered whenever an error occurs during the subscription process.
* @returns A function that can be called to cancel the subscription.
*/
onProgramUpdate(
programsOfInterest: PublicKey[],
successCallback: (resp: TimestampedAccountUpdate) => void,
errorCallback: (e: Error) => void
): () => void {
const programs = programsOfInterest.map(a => a.toBytes());
const stream: ClientReadableStream<TimestampedAccountUpdate> =
this.client.subscribeProgramUpdates({programs});
stream.on('readable', () => {
const msg = stream.read(1);
if (msg) {
successCallback(msg);
}
});
stream.on('error', e =>
errorCallback(new Error(`Stream error: ${e.message}`))
);
return () => stream.cancel();
}
/**
* Triggers the supplied callback for every processed block.
*
* @param successCallback - A callback function that receives a TimestampedBlockUpdate object whenever a block update is available.
* @param errorCallback - A callback function that is triggered whenever an error occurs during the subscription process.
* @returns A function that can be called to cancel the subscription.
*/
onProcessedBlock(
successCallback: (resp: TimestampedBlockUpdate) => void,
errorCallback: (e: Error) => void
): () => void {
const stream: ClientReadableStream<TimestampedBlockUpdate> =
this.client.subscribeBlockUpdates({});
stream.on('readable', () => {
const msg = stream.read(1);
if (msg) {
successCallback(msg);
}
});
stream.on('error', e =>
errorCallback(new Error(`Stream error: ${e.message}`))
);
return () => stream.cancel();
}
}
/**
* Creates and returns a new GeyserClient instance.
*
* @param url - The gRPC server endpoint URL.
* @param accessToken - The access token required for authentication.
* @param grpcOptions - Optional configuration options for the gRPC client
* @returns A GeyserClient instance with the specified configuration.
*/
export const geyserClient = (
url: string,
accessToken: string,
grpcOptions?: Partial<ChannelOptions>
): GeyserClient => {
const client = new GeyserClientStub(url, ChannelCredentials.createSsl(), {
interceptors: [authInterceptor(accessToken)],
...grpcOptions,
});
return new GeyserClient(client);
};