Skip to content

Commit e5931a3

Browse files
authored
feat: add support for signature received notifications (#15946)
* feat: add support for signature received notifications * chore: update type comments
1 parent ed746f9 commit e5931a3

File tree

1 file changed

+96
-15
lines changed

1 file changed

+96
-15
lines changed

src/connection.ts

Lines changed: 96 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,11 @@ const SignatureStatusResult = pick({
403403
err: TransactionErrorResult,
404404
});
405405

406+
/**
407+
* Transaction signature received notification
408+
*/
409+
const SignatureReceivedResult = literal('receivedSignature');
410+
406411
export type Version = {
407412
'solana-core': string;
408413
'feature-set'?: number;
@@ -1009,7 +1014,9 @@ const SlotNotificationResult = pick({
10091014
*/
10101015
const SignatureNotificationResult = pick({
10111016
subscription: number(),
1012-
result: notificationResultAndContext(SignatureStatusResult),
1017+
result: notificationResultAndContext(
1018+
union([SignatureStatusResult, SignatureReceivedResult]),
1019+
),
10131020
});
10141021

10151022
/**
@@ -1456,20 +1463,51 @@ type SlotSubscriptionInfo = {
14561463
};
14571464

14581465
/**
1459-
* Callback function for signature notifications
1466+
* Callback function for signature status notifications
14601467
*/
14611468
export type SignatureResultCallback = (
14621469
signatureResult: SignatureResult,
14631470
context: Context,
14641471
) => void;
14651472

1473+
/**
1474+
* Signature status notification with transaction result
1475+
*/
1476+
export type SignatureStatusNotification = {
1477+
type: 'status';
1478+
result: SignatureResult;
1479+
};
1480+
1481+
/**
1482+
* Signature received notification
1483+
*/
1484+
export type SignatureReceivedNotification = {
1485+
type: 'received';
1486+
};
1487+
1488+
/**
1489+
* Callback function for signature notifications
1490+
*/
1491+
export type SignatureSubscriptionCallback = (
1492+
notification: SignatureStatusNotification | SignatureReceivedNotification,
1493+
context: Context,
1494+
) => void;
1495+
1496+
/**
1497+
* Signature subscription options
1498+
*/
1499+
export type SignatureSubscriptionOptions = {
1500+
commitment?: Commitment;
1501+
enableReceivedNotification?: boolean;
1502+
};
1503+
14661504
/**
14671505
* @internal
14681506
*/
14691507
type SignatureSubscriptionInfo = {
14701508
signature: TransactionSignature; // TransactionSignature as a base 58 string
1471-
callback: SignatureResultCallback;
1472-
commitment?: Commitment;
1509+
callback: SignatureSubscriptionCallback;
1510+
options?: SignatureSubscriptionOptions;
14731511
subscriptionId: SubscriptionId | null; // null when there's no current server subscription id
14741512
};
14751513

@@ -2943,11 +2981,9 @@ export class Connection {
29432981

29442982
for (let id of signatureKeys) {
29452983
const sub = this._signatureSubscriptions[id];
2946-
this._subscribe(
2947-
sub,
2948-
'signatureSubscribe',
2949-
this._buildArgs([sub.signature], sub.commitment),
2950-
);
2984+
const args: any[] = [sub.signature];
2985+
if (sub.options) args.push(sub.options);
2986+
this._subscribe(sub, 'signatureSubscribe', args);
29512987
}
29522988

29532989
for (let id of rootKeys) {
@@ -3148,11 +3184,26 @@ export class Connection {
31483184
const res = create(notification, SignatureNotificationResult);
31493185
for (const [id, sub] of Object.entries(this._signatureSubscriptions)) {
31503186
if (sub.subscriptionId === res.subscription) {
3151-
// Signatures subscriptions are auto-removed by the RPC service so
3152-
// no need to explicitly send an unsubscribe message
3153-
delete this._signatureSubscriptions[Number(id)];
3154-
this._updateSubscriptions();
3155-
sub.callback(res.result.value, res.result.context);
3187+
if (res.result.value === 'receivedSignature') {
3188+
sub.callback(
3189+
{
3190+
type: 'received',
3191+
},
3192+
res.result.context,
3193+
);
3194+
} else {
3195+
// Signatures subscriptions are auto-removed by the RPC service so
3196+
// no need to explicitly send an unsubscribe message
3197+
delete this._signatureSubscriptions[Number(id)];
3198+
this._updateSubscriptions();
3199+
sub.callback(
3200+
{
3201+
type: 'status',
3202+
result: res.result.value,
3203+
},
3204+
res.result.context,
3205+
);
3206+
}
31563207
return;
31573208
}
31583209
}
@@ -3170,12 +3221,42 @@ export class Connection {
31703221
signature: TransactionSignature,
31713222
callback: SignatureResultCallback,
31723223
commitment?: Commitment,
3224+
): number {
3225+
const id = ++this._signatureSubscriptionCounter;
3226+
this._signatureSubscriptions[id] = {
3227+
signature,
3228+
callback: (notification, context) => {
3229+
if (notification.type === 'status') {
3230+
callback(notification.result, context);
3231+
}
3232+
},
3233+
options: {commitment},
3234+
subscriptionId: null,
3235+
};
3236+
this._updateSubscriptions();
3237+
return id;
3238+
}
3239+
3240+
/**
3241+
* Register a callback to be invoked when a transaction is
3242+
* received and/or processed.
3243+
*
3244+
* @param signature Transaction signature string in base 58
3245+
* @param callback Function to invoke on signature notifications
3246+
* @param options Enable received notifications and set the commitment
3247+
* level that signature must reach before notification
3248+
* @return subscription id
3249+
*/
3250+
onSignatureWithOptions(
3251+
signature: TransactionSignature,
3252+
callback: SignatureSubscriptionCallback,
3253+
options?: SignatureSubscriptionOptions,
31733254
): number {
31743255
const id = ++this._signatureSubscriptionCounter;
31753256
this._signatureSubscriptions[id] = {
31763257
signature,
31773258
callback,
3178-
commitment,
3259+
options,
31793260
subscriptionId: null,
31803261
};
31813262
this._updateSubscriptions();

0 commit comments

Comments
 (0)