Skip to content

Commit e6a5f7e

Browse files
committed
fix: onProgramAccountChange() and onAccountChange() now accept an encoding
1 parent 6572045 commit e6a5f7e

File tree

2 files changed

+193
-3
lines changed

2 files changed

+193
-3
lines changed

packages/library-legacy/src/connection.ts

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2787,6 +2787,39 @@ export type GetNonceAndContextConfig = {
27872787
minContextSlot?: number;
27882788
};
27892789

2790+
export type AccountSubscriptionConfig = Readonly<{
2791+
/** Optional commitment level */
2792+
commitment?: Commitment;
2793+
/**
2794+
* Encoding format for Account data
2795+
* - `base58` is slow.
2796+
* - `jsonParsed` encoding attempts to use program-specific state parsers to return more
2797+
* human-readable and explicit account state data
2798+
* - If `jsonParsed` is requested but a parser cannot be found, the field falls back to `base64`
2799+
* encoding, detectable when the `data` field is type `string`.
2800+
*/
2801+
encoding?: 'base58' | 'base64' | 'base64+zstd' | 'jsonParsed';
2802+
}>;
2803+
2804+
export type ProgramAccountSubscriptionConfig = Readonly<{
2805+
/** Optional commitment level */
2806+
commitment?: Commitment;
2807+
/**
2808+
* Encoding format for Account data
2809+
* - `base58` is slow.
2810+
* - `jsonParsed` encoding attempts to use program-specific state parsers to return more
2811+
* human-readable and explicit account state data
2812+
* - If `jsonParsed` is requested but a parser cannot be found, the field falls back to `base64`
2813+
* encoding, detectable when the `data` field is type `string`.
2814+
*/
2815+
encoding?: 'base58' | 'base64' | 'base64+zstd' | 'jsonParsed';
2816+
/**
2817+
* Filter results using various filter objects
2818+
* The resultant account must meet ALL filter criteria to be included in the returned results
2819+
*/
2820+
filters?: GetProgramAccountsFilter[];
2821+
}>;
2822+
27902823
/**
27912824
* Information describing an account
27922825
*/
@@ -6337,15 +6370,31 @@ export class Connection {
63376370
* @param commitment Specify the commitment level account changes must reach before notification
63386371
* @return subscription id
63396372
*/
6373+
onAccountChange(
6374+
publicKey: PublicKey,
6375+
callback: AccountChangeCallback,
6376+
config: AccountSubscriptionConfig,
6377+
): ClientSubscriptionId;
6378+
/** @deprecated Instead, pass in an {@link AccountSubscriptionConfig} */
6379+
// eslint-disable-next-line no-dupe-class-members
63406380
onAccountChange(
63416381
publicKey: PublicKey,
63426382
callback: AccountChangeCallback,
63436383
commitment?: Commitment,
6384+
): ClientSubscriptionId;
6385+
// eslint-disable-next-line no-dupe-class-members
6386+
onAccountChange(
6387+
publicKey: PublicKey,
6388+
callback: AccountChangeCallback,
6389+
commitmentOrConfig?: Commitment | AccountSubscriptionConfig,
63446390
): ClientSubscriptionId {
6391+
const {commitment, config} =
6392+
extractCommitmentFromConfig(commitmentOrConfig);
63456393
const args = this._buildArgs(
63466394
[publicKey.toBase58()],
63476395
commitment || this._commitment || 'finalized', // Apply connection/server default.
63486396
'base64',
6397+
config,
63496398
);
63506399
return this._makeSubscription(
63516400
{
@@ -6398,17 +6447,37 @@ export class Connection {
63986447
* @param filters The program account filters to pass into the RPC method
63996448
* @return subscription id
64006449
*/
6450+
onProgramAccountChange(
6451+
programId: PublicKey,
6452+
callback: ProgramAccountChangeCallback,
6453+
config: ProgramAccountSubscriptionConfig,
6454+
): ClientSubscriptionId;
6455+
/** @deprecated Instead, pass in a {@link ProgramAccountSubscriptionConfig} */
6456+
// eslint-disable-next-line no-dupe-class-members
64016457
onProgramAccountChange(
64026458
programId: PublicKey,
64036459
callback: ProgramAccountChangeCallback,
64046460
commitment?: Commitment,
64056461
filters?: GetProgramAccountsFilter[],
6462+
): ClientSubscriptionId;
6463+
// eslint-disable-next-line no-dupe-class-members
6464+
onProgramAccountChange(
6465+
programId: PublicKey,
6466+
callback: ProgramAccountChangeCallback,
6467+
commitmentOrConfig?: Commitment | ProgramAccountSubscriptionConfig,
6468+
maybeFilters?: GetProgramAccountsFilter[],
64066469
): ClientSubscriptionId {
6470+
const {commitment, config} =
6471+
extractCommitmentFromConfig(commitmentOrConfig);
64076472
const args = this._buildArgs(
64086473
[programId.toBase58()],
64096474
commitment || this._commitment || 'finalized', // Apply connection/server default.
64106475
'base64' /* encoding */,
6411-
filters ? {filters: filters} : undefined /* extra */,
6476+
config
6477+
? config
6478+
: maybeFilters
6479+
? {filters: maybeFilters}
6480+
: undefined /* extra */,
64126481
);
64136482
return this._makeSubscription(
64146483
{

packages/library-legacy/test/connection.test.ts

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {expect, use} from 'chai';
44
import chaiAsPromised from 'chai-as-promised';
55
import {Agent as HttpAgent} from 'http';
66
import {Agent as HttpsAgent} from 'https';
7-
import {match, mock, spy, useFakeTimers, SinonFakeTimers} from 'sinon';
7+
import {match, mock, spy, stub, useFakeTimers, SinonFakeTimers} from 'sinon';
88
import sinonChai from 'sinon-chai';
99
import {fail} from 'assert';
1010

@@ -5914,7 +5914,7 @@ describe('Connection', function () {
59145914
subscriptionId = connection.onAccountChange(
59155915
owner.publicKey,
59165916
resolve,
5917-
'confirmed',
5917+
{commitment: 'confirmed'},
59185918
);
59195919
},
59205920
);
@@ -6394,4 +6394,125 @@ describe('Connection', function () {
63946394
});
63956395
}).timeout(5 * 1000);
63966396
}
6397+
6398+
it(`passes the commitment/encoding to the RPC when calling \`onAccountChange\``, () => {
6399+
const connection = new Connection(url);
6400+
const rpcRequestMethod = stub(
6401+
connection,
6402+
// @ts-expect-error This method is private, but none the less this spy will work.
6403+
'_makeSubscription',
6404+
);
6405+
const mockCallback = () => {};
6406+
connection.onAccountChange(PublicKey.default, mockCallback, {
6407+
commitment: 'processed',
6408+
encoding: 'base64+zstd',
6409+
});
6410+
expect(rpcRequestMethod).to.have.been.calledWithExactly(
6411+
{
6412+
callback: mockCallback,
6413+
method: 'accountSubscribe',
6414+
unsubscribeMethod: 'accountUnsubscribe',
6415+
},
6416+
[
6417+
match.any,
6418+
match
6419+
.has('commitment', 'processed')
6420+
.and(match.has('encoding', 'base64+zstd')),
6421+
],
6422+
);
6423+
});
6424+
it(`passes the commitment to the RPC when the deprecated signature of \`onAccountChange\` is used`, () => {
6425+
const connection = new Connection(url);
6426+
const rpcRequestMethod = stub(
6427+
connection,
6428+
// @ts-expect-error This method is private, but none the less this spy will work.
6429+
'_makeSubscription',
6430+
);
6431+
const mockCallback = () => {};
6432+
connection.onAccountChange(PublicKey.default, mockCallback, 'processed');
6433+
expect(rpcRequestMethod).to.have.been.calledWithExactly(
6434+
{
6435+
callback: mockCallback,
6436+
method: 'accountSubscribe',
6437+
unsubscribeMethod: 'accountUnsubscribe',
6438+
},
6439+
[match.any, match.has('commitment', 'processed')],
6440+
);
6441+
});
6442+
it(`passes the commitment to the RPC when the deprecated signature of \`onProgramAccountChange\` is used`, () => {
6443+
const connection = new Connection(url);
6444+
const rpcRequestMethod = stub(
6445+
connection,
6446+
// @ts-expect-error This method is private, but none the less this spy will work.
6447+
'_makeSubscription',
6448+
);
6449+
const mockCallback = () => {};
6450+
connection.onProgramAccountChange(
6451+
PublicKey.default,
6452+
mockCallback,
6453+
'processed' /* commitment */,
6454+
);
6455+
expect(rpcRequestMethod).to.have.been.calledWithExactly(
6456+
{
6457+
callback: mockCallback,
6458+
method: 'programSubscribe',
6459+
unsubscribeMethod: 'programUnsubscribe',
6460+
},
6461+
[match.any, match.has('commitment', 'processed')],
6462+
);
6463+
});
6464+
it(`passes the filters to the RPC when the deprecated signature of \`onProgramAccountChange\` is used`, () => {
6465+
const connection = new Connection(url);
6466+
const rpcRequestMethod = stub(
6467+
connection,
6468+
// @ts-expect-error This method is private, but none the less this spy will work.
6469+
'_makeSubscription',
6470+
);
6471+
const mockCallback = () => {};
6472+
connection.onProgramAccountChange(
6473+
PublicKey.default,
6474+
mockCallback,
6475+
/* commitment */ undefined,
6476+
/* filters */ [{dataSize: 123}],
6477+
);
6478+
expect(rpcRequestMethod).to.have.been.calledWithExactly(
6479+
{
6480+
callback: mockCallback,
6481+
method: 'programSubscribe',
6482+
unsubscribeMethod: 'programUnsubscribe',
6483+
},
6484+
[match.any, match.has('filters', [{dataSize: 123}])],
6485+
);
6486+
});
6487+
it(`passes the commitment/encoding/filters to the RPC when calling \`onProgramAccountChange\``, () => {
6488+
const connection = new Connection(url);
6489+
const rpcRequestMethod = stub(
6490+
connection,
6491+
// @ts-expect-error This method is private, but none the less this spy will work.
6492+
'_makeSubscription',
6493+
);
6494+
const mockCallback = () => {};
6495+
connection.onProgramAccountChange(PublicKey.default, mockCallback, {
6496+
commitment: 'processed',
6497+
encoding: 'base64+zstd',
6498+
filters: [{dataSize: 123}],
6499+
});
6500+
expect(rpcRequestMethod).to.have.been.calledWithExactly(
6501+
{
6502+
callback: mockCallback,
6503+
method: 'programSubscribe',
6504+
unsubscribeMethod: 'programUnsubscribe',
6505+
},
6506+
[
6507+
match.any,
6508+
match
6509+
.has('commitment', 'processed')
6510+
.and(
6511+
match
6512+
.has('encoding', 'base64+zstd')
6513+
.and(match.has('filters', [{dataSize: 123}])),
6514+
),
6515+
],
6516+
);
6517+
});
63976518
});

0 commit comments

Comments
 (0)