Once you have installed the client dependency, you can initialize it as follows:
import Client from"@triton-one/yellowstone-grpc";constclient=newClient("https://api.rpcpool.com:443","<insert your token here>");// now you can call the client methods, e.g.:constversion=awaitclient.getVersion(); // gets the version informationconsole.log(version);
Please note that the client is asynchronous, so it is expected that all calls are executed inside an async block or async function.
Subscription Streams
You can get updates and send requests through the subscription stream. You can create it by calling the client.subscribe() method:
import { SubscribeRequest } from"@triton-one/yellowstone-grpc";// Create a subscription stream.conststream=client.subscribe();// Collecting all incoming events.stream.on("data", (data) => {console.log("data", data);});// Create a subscription request.constrequest:SubscribeRequest= {// you can use the standard JSON request format here.// the following documentation describes available requests and filters....};// Sending a subscription request.awaitnewPromise<void>((resolve, reject) => {stream.write(request, (err) => {if (err ===null|| err ===undefined) {resolve(); } else {reject(err); } });}).catch((reason) => {console.error(reason);throw reason;});
grpcurl Client
grpcurl is a good client for testing. You will also need the following two Protobuf proto files to describe the protocol:
Once you have these two downloaded, you can access Triton's staging environment with your token (contact Triton customer support for a token) to run gRPC requests:
The gRPC streams happen by default on the processed commitment level.
Triton also supports specifying confirmed and finalized commitment levels. In these cases, Dragon's Mouth will buffer the incoming updates for you and release them once the updates have become confirmed or finalized.
For maximum performance, however, it is recommended to use handling commitment levels client side.
To specify commitment level in your Dragon's Mouth gRPC calls provide the following values:
The benefit of working on processed is that you can process transactions as soon as they arrive, but only commit to them once you know whether they are confirmed or finalized. This means that you can get faster response times in your UI by doing a lot of the processing work at a lower commitment level and then be able to surface the changes as soon as you see that the event is committed.
How to manage `confirmed` and `finalized`
To manage confirmed and finalized you need to buffer events by slot. Each event (transaction or account write) will have a slot attached to it. You store these events in a buffer ordered by slot.
You then also make sure you subscribe to slot notifications. This will give you information about when a slot is confirmed or finalized. Depending on the commitment level you are interested in, you should release your buffer when you receive the slot notification for a particular slot at a particular commitment level.
You will receive all the transaction notifications or account write notifications for the slot before you receive the "confirmed" and "finalized" notification for that slot.
The special thing about finalized
Unfortunately, due to a quirk in the way that Geyser works on SVM not every slot finalized notification is issued. This means that you need some special processing if you want to handle finalized correctly.
The special handling is the following: whenever you see a finalized slot notification, you need to check the parents and grand parents (and great-grandparents and so on) of that slot and mark those as finalized too even if you didn't receive a notification for them.