feat: add support for signature received notifications (#15946)

* feat: add support for signature received notifications

* chore: update type comments
This commit is contained in:
Justin Starry 2021-03-19 09:30:36 +08:00 committed by GitHub
parent 02b81dd05d
commit f4db9e4275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 96 additions and 15 deletions

View File

@ -403,6 +403,11 @@ const SignatureStatusResult = pick({
err: TransactionErrorResult, err: TransactionErrorResult,
}); });
/**
* Transaction signature received notification
*/
const SignatureReceivedResult = literal('receivedSignature');
export type Version = { export type Version = {
'solana-core': string; 'solana-core': string;
'feature-set'?: number; 'feature-set'?: number;
@ -1009,7 +1014,9 @@ const SlotNotificationResult = pick({
*/ */
const SignatureNotificationResult = pick({ const SignatureNotificationResult = pick({
subscription: number(), subscription: number(),
result: notificationResultAndContext(SignatureStatusResult), result: notificationResultAndContext(
union([SignatureStatusResult, SignatureReceivedResult]),
),
}); });
/** /**
@ -1456,20 +1463,51 @@ type SlotSubscriptionInfo = {
}; };
/** /**
* Callback function for signature notifications * Callback function for signature status notifications
*/ */
export type SignatureResultCallback = ( export type SignatureResultCallback = (
signatureResult: SignatureResult, signatureResult: SignatureResult,
context: Context, context: Context,
) => void; ) => void;
/**
* Signature status notification with transaction result
*/
export type SignatureStatusNotification = {
type: 'status';
result: SignatureResult;
};
/**
* Signature received notification
*/
export type SignatureReceivedNotification = {
type: 'received';
};
/**
* Callback function for signature notifications
*/
export type SignatureSubscriptionCallback = (
notification: SignatureStatusNotification | SignatureReceivedNotification,
context: Context,
) => void;
/**
* Signature subscription options
*/
export type SignatureSubscriptionOptions = {
commitment?: Commitment;
enableReceivedNotification?: boolean;
};
/** /**
* @internal * @internal
*/ */
type SignatureSubscriptionInfo = { type SignatureSubscriptionInfo = {
signature: TransactionSignature; // TransactionSignature as a base 58 string signature: TransactionSignature; // TransactionSignature as a base 58 string
callback: SignatureResultCallback; callback: SignatureSubscriptionCallback;
commitment?: Commitment; options?: SignatureSubscriptionOptions;
subscriptionId: SubscriptionId | null; // null when there's no current server subscription id subscriptionId: SubscriptionId | null; // null when there's no current server subscription id
}; };
@ -2943,11 +2981,9 @@ export class Connection {
for (let id of signatureKeys) { for (let id of signatureKeys) {
const sub = this._signatureSubscriptions[id]; const sub = this._signatureSubscriptions[id];
this._subscribe( const args: any[] = [sub.signature];
sub, if (sub.options) args.push(sub.options);
'signatureSubscribe', this._subscribe(sub, 'signatureSubscribe', args);
this._buildArgs([sub.signature], sub.commitment),
);
} }
for (let id of rootKeys) { for (let id of rootKeys) {
@ -3148,11 +3184,26 @@ export class Connection {
const res = create(notification, SignatureNotificationResult); const res = create(notification, SignatureNotificationResult);
for (const [id, sub] of Object.entries(this._signatureSubscriptions)) { for (const [id, sub] of Object.entries(this._signatureSubscriptions)) {
if (sub.subscriptionId === res.subscription) { if (sub.subscriptionId === res.subscription) {
// Signatures subscriptions are auto-removed by the RPC service so if (res.result.value === 'receivedSignature') {
// no need to explicitly send an unsubscribe message sub.callback(
delete this._signatureSubscriptions[Number(id)]; {
this._updateSubscriptions(); type: 'received',
sub.callback(res.result.value, res.result.context); },
res.result.context,
);
} else {
// Signatures subscriptions are auto-removed by the RPC service so
// no need to explicitly send an unsubscribe message
delete this._signatureSubscriptions[Number(id)];
this._updateSubscriptions();
sub.callback(
{
type: 'status',
result: res.result.value,
},
res.result.context,
);
}
return; return;
} }
} }
@ -3170,12 +3221,42 @@ export class Connection {
signature: TransactionSignature, signature: TransactionSignature,
callback: SignatureResultCallback, callback: SignatureResultCallback,
commitment?: Commitment, commitment?: Commitment,
): number {
const id = ++this._signatureSubscriptionCounter;
this._signatureSubscriptions[id] = {
signature,
callback: (notification, context) => {
if (notification.type === 'status') {
callback(notification.result, context);
}
},
options: {commitment},
subscriptionId: null,
};
this._updateSubscriptions();
return id;
}
/**
* Register a callback to be invoked when a transaction is
* received and/or processed.
*
* @param signature Transaction signature string in base 58
* @param callback Function to invoke on signature notifications
* @param options Enable received notifications and set the commitment
* level that signature must reach before notification
* @return subscription id
*/
onSignatureWithOptions(
signature: TransactionSignature,
callback: SignatureSubscriptionCallback,
options?: SignatureSubscriptionOptions,
): number { ): number {
const id = ++this._signatureSubscriptionCounter; const id = ++this._signatureSubscriptionCounter;
this._signatureSubscriptions[id] = { this._signatureSubscriptions[id] = {
signature, signature,
callback, callback,
commitment, options,
subscriptionId: null, subscriptionId: null,
}; };
this._updateSubscriptions(); this._updateSubscriptions();