@solana/web3.js 1.68.1 → 1.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -13
- package/lib/index.browser.cjs.js +47 -9
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +47 -9
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +66 -14
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +247 -234
- package/lib/index.esm.js +65 -13
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +47 -9
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +2 -2
- package/lib/index.iife.min.js.map +1 -1
- package/lib/index.native.js +47 -9
- package/lib/index.native.js.map +1 -1
- package/package.json +6 -5
- package/src/connection.ts +120 -31
- package/src/epoch-schedule.ts +1 -1
- package/src/utils/send-and-confirm-transaction.ts +14 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/web3.js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.70.0",
|
|
4
4
|
"description": "Solana Javascript API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"pretty": "prettier --check '{,{src,test}/**/}*.{j,t}s'",
|
|
52
52
|
"pretty:fix": "prettier --write '{,{src,test}/**/}*.{j,t}s'",
|
|
53
53
|
"re": "semantic-release --repository-url git@github.com:solana-labs/solana-web3.js.git",
|
|
54
|
-
"test": "cross-env TS_NODE_COMPILER_OPTIONS='{ \"module\": \"commonjs\", \"target\": \"es2019\" }' ts-mocha --require esm './test/**/*.test.ts'",
|
|
54
|
+
"test": "cross-env NODE_ENV=test TS_NODE_COMPILER_OPTIONS='{ \"module\": \"commonjs\", \"target\": \"es2019\" }' ts-mocha --require esm './test/**/*.test.ts'",
|
|
55
55
|
"test:cover": "nyc --reporter=lcov npm run test",
|
|
56
56
|
"test:live": "TEST_LIVE=1 npm run test",
|
|
57
57
|
"test:live-with-test-validator": "start-server-and-test 'solana-test-validator --reset --quiet' http://localhost:8899/health test:live"
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"@types/express-serve-static-core": "^4.17.21",
|
|
96
96
|
"@types/mocha": "^10.0.0",
|
|
97
97
|
"@types/mz": "^2.7.3",
|
|
98
|
-
"@types/node": "^
|
|
98
|
+
"@types/node": "^18.11.10",
|
|
99
99
|
"@types/node-fetch": "2",
|
|
100
100
|
"@types/sinon": "^10.0.0",
|
|
101
101
|
"@types/sinon-chai": "^3.2.8",
|
|
@@ -114,6 +114,7 @@
|
|
|
114
114
|
"mocha": "^10.1.0",
|
|
115
115
|
"mockttp": "^2.0.1",
|
|
116
116
|
"mz": "^2.7.0",
|
|
117
|
+
"node-abort-controller": "^3.0.1",
|
|
117
118
|
"npm-run-all": "^4.1.5",
|
|
118
119
|
"nyc": "^15.1.0",
|
|
119
120
|
"prettier": "^2.3.0",
|
|
@@ -129,8 +130,8 @@
|
|
|
129
130
|
"ts-mocha": "^10.0.0",
|
|
130
131
|
"ts-node": "^10.0.0",
|
|
131
132
|
"tslib": "^2.1.0",
|
|
132
|
-
"typedoc": "^0.
|
|
133
|
-
"typescript": "^4.
|
|
133
|
+
"typedoc": "^0.23",
|
|
134
|
+
"typescript": "^4.9"
|
|
134
135
|
},
|
|
135
136
|
"engines": {
|
|
136
137
|
"node": ">=12.20.0"
|
package/src/connection.ts
CHANGED
|
@@ -2,6 +2,8 @@ import bs58 from 'bs58';
|
|
|
2
2
|
import {Buffer} from 'buffer';
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import fastStableStringify from 'fast-stable-stringify';
|
|
5
|
+
import type {Agent as HttpAgent} from 'http';
|
|
6
|
+
import {Agent as HttpsAgent} from 'https';
|
|
5
7
|
import {
|
|
6
8
|
type as pick,
|
|
7
9
|
number,
|
|
@@ -311,9 +313,39 @@ export type BlockhashWithExpiryBlockHeight = Readonly<{
|
|
|
311
313
|
* A strategy for confirming transactions that uses the last valid
|
|
312
314
|
* block height for a given blockhash to check for transaction expiration.
|
|
313
315
|
*/
|
|
314
|
-
export type BlockheightBasedTransactionConfirmationStrategy =
|
|
316
|
+
export type BlockheightBasedTransactionConfirmationStrategy =
|
|
317
|
+
BaseTransactionConfirmationStrategy & BlockhashWithExpiryBlockHeight;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* A strategy for confirming durable nonce transactions.
|
|
321
|
+
*/
|
|
322
|
+
export type DurableNonceTransactionConfirmationStrategy =
|
|
323
|
+
BaseTransactionConfirmationStrategy & {
|
|
324
|
+
/**
|
|
325
|
+
* The lowest slot at which to fetch the nonce value from the
|
|
326
|
+
* nonce account. This should be no lower than the slot at
|
|
327
|
+
* which the last-known value of the nonce was fetched.
|
|
328
|
+
*/
|
|
329
|
+
minContextSlot: number;
|
|
330
|
+
/**
|
|
331
|
+
* The account where the current value of the nonce is stored.
|
|
332
|
+
*/
|
|
333
|
+
nonceAccountPubkey: PublicKey;
|
|
334
|
+
/**
|
|
335
|
+
* The nonce value that was used to sign the transaction
|
|
336
|
+
* for which confirmation is being sought.
|
|
337
|
+
*/
|
|
338
|
+
nonceValue: DurableNonce;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Properties shared by all transaction confirmation strategies
|
|
343
|
+
*/
|
|
344
|
+
export type BaseTransactionConfirmationStrategy = Readonly<{
|
|
345
|
+
/** A signal that, when aborted, cancels any outstanding transaction confirmation operations */
|
|
346
|
+
abortSignal?: AbortSignal;
|
|
315
347
|
signature: TransactionSignature;
|
|
316
|
-
}
|
|
348
|
+
}>;
|
|
317
349
|
|
|
318
350
|
/* @internal */
|
|
319
351
|
function assertEndpointUrl(putativeUrl: string) {
|
|
@@ -340,28 +372,6 @@ function extractCommitmentFromConfig<TConfig>(
|
|
|
340
372
|
return {commitment, config};
|
|
341
373
|
}
|
|
342
374
|
|
|
343
|
-
/**
|
|
344
|
-
* A strategy for confirming durable nonce transactions.
|
|
345
|
-
*/
|
|
346
|
-
export type DurableNonceTransactionConfirmationStrategy = {
|
|
347
|
-
/**
|
|
348
|
-
* The lowest slot at which to fetch the nonce value from the
|
|
349
|
-
* nonce account. This should be no lower than the slot at
|
|
350
|
-
* which the last-known value of the nonce was fetched.
|
|
351
|
-
*/
|
|
352
|
-
minContextSlot: number;
|
|
353
|
-
/**
|
|
354
|
-
* The account where the current value of the nonce is stored.
|
|
355
|
-
*/
|
|
356
|
-
nonceAccountPubkey: PublicKey;
|
|
357
|
-
/**
|
|
358
|
-
* The nonce value that was used to sign the transaction
|
|
359
|
-
* for which confirmation is being sought.
|
|
360
|
-
*/
|
|
361
|
-
nonceValue: DurableNonce;
|
|
362
|
-
signature: TransactionSignature;
|
|
363
|
-
};
|
|
364
|
-
|
|
365
375
|
/**
|
|
366
376
|
* @internal
|
|
367
377
|
*/
|
|
@@ -1442,11 +1452,47 @@ function createRpcClient(
|
|
|
1442
1452
|
customFetch?: FetchFn,
|
|
1443
1453
|
fetchMiddleware?: FetchMiddleware,
|
|
1444
1454
|
disableRetryOnRateLimit?: boolean,
|
|
1455
|
+
httpAgent?: HttpAgent | HttpsAgent | false,
|
|
1445
1456
|
): RpcClient {
|
|
1446
1457
|
const fetch = customFetch ? customFetch : fetchImpl;
|
|
1447
|
-
let agentManager:
|
|
1448
|
-
|
|
1449
|
-
|
|
1458
|
+
let agentManager:
|
|
1459
|
+
| {requestEnd(): void; requestStart(): HttpAgent | HttpsAgent}
|
|
1460
|
+
| undefined;
|
|
1461
|
+
if (process.env.BROWSER) {
|
|
1462
|
+
if (httpAgent != null) {
|
|
1463
|
+
console.warn(
|
|
1464
|
+
'You have supplied an `httpAgent` when creating a `Connection` in a browser environment.' +
|
|
1465
|
+
'It has been ignored; `httpAgent` is only used in Node environments.',
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
} else {
|
|
1469
|
+
if (httpAgent == null) {
|
|
1470
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
1471
|
+
agentManager = new AgentManager(
|
|
1472
|
+
url.startsWith('https:') /* useHttps */,
|
|
1473
|
+
);
|
|
1474
|
+
}
|
|
1475
|
+
} else {
|
|
1476
|
+
if (httpAgent !== false) {
|
|
1477
|
+
const isHttps = url.startsWith('https:');
|
|
1478
|
+
if (isHttps && !(httpAgent instanceof HttpsAgent)) {
|
|
1479
|
+
throw new Error(
|
|
1480
|
+
'The endpoint `' +
|
|
1481
|
+
url +
|
|
1482
|
+
'` can only be paired with an `https.Agent`. You have, instead, supplied an ' +
|
|
1483
|
+
'`http.Agent` through `httpAgent`.',
|
|
1484
|
+
);
|
|
1485
|
+
} else if (!isHttps && httpAgent instanceof HttpsAgent) {
|
|
1486
|
+
throw new Error(
|
|
1487
|
+
'The endpoint `' +
|
|
1488
|
+
url +
|
|
1489
|
+
'` can only be paired with an `http.Agent`. You have, instead, supplied an ' +
|
|
1490
|
+
'`https.Agent` through `httpAgent`.',
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
agentManager = {requestEnd() {}, requestStart: () => httpAgent};
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1450
1496
|
}
|
|
1451
1497
|
|
|
1452
1498
|
let fetchWithMiddleware: FetchFn | undefined;
|
|
@@ -2847,6 +2893,12 @@ export type FetchMiddleware = (
|
|
|
2847
2893
|
* Configuration for instantiating a Connection
|
|
2848
2894
|
*/
|
|
2849
2895
|
export type ConnectionConfig = {
|
|
2896
|
+
/**
|
|
2897
|
+
* An `http.Agent` that will be used to manage socket connections (eg. to implement connection
|
|
2898
|
+
* persistence). Set this to `false` to create a connection that uses no agent. This applies to
|
|
2899
|
+
* Node environments only.
|
|
2900
|
+
*/
|
|
2901
|
+
httpAgent?: HttpAgent | HttpsAgent | false;
|
|
2850
2902
|
/** Optional commitment level */
|
|
2851
2903
|
commitment?: Commitment;
|
|
2852
2904
|
/** Optional endpoint URL to the fullnode JSON RPC PubSub WebSocket Endpoint */
|
|
@@ -2964,6 +3016,7 @@ export class Connection {
|
|
|
2964
3016
|
let fetch;
|
|
2965
3017
|
let fetchMiddleware;
|
|
2966
3018
|
let disableRetryOnRateLimit;
|
|
3019
|
+
let httpAgent;
|
|
2967
3020
|
if (commitmentOrConfig && typeof commitmentOrConfig === 'string') {
|
|
2968
3021
|
this._commitment = commitmentOrConfig;
|
|
2969
3022
|
} else if (commitmentOrConfig) {
|
|
@@ -2975,6 +3028,7 @@ export class Connection {
|
|
|
2975
3028
|
fetch = commitmentOrConfig.fetch;
|
|
2976
3029
|
fetchMiddleware = commitmentOrConfig.fetchMiddleware;
|
|
2977
3030
|
disableRetryOnRateLimit = commitmentOrConfig.disableRetryOnRateLimit;
|
|
3031
|
+
httpAgent = commitmentOrConfig.httpAgent;
|
|
2978
3032
|
}
|
|
2979
3033
|
|
|
2980
3034
|
this._rpcEndpoint = assertEndpointUrl(endpoint);
|
|
@@ -2986,6 +3040,7 @@ export class Connection {
|
|
|
2986
3040
|
fetch,
|
|
2987
3041
|
fetchMiddleware,
|
|
2988
3042
|
disableRetryOnRateLimit,
|
|
3043
|
+
httpAgent,
|
|
2989
3044
|
);
|
|
2990
3045
|
this._rpcRequest = createRpcRequest(this._rpcClient);
|
|
2991
3046
|
this._rpcBatchRequest = createRpcBatchRequest(this._rpcClient);
|
|
@@ -3571,6 +3626,9 @@ export class Connection {
|
|
|
3571
3626
|
const config = strategy as
|
|
3572
3627
|
| BlockheightBasedTransactionConfirmationStrategy
|
|
3573
3628
|
| DurableNonceTransactionConfirmationStrategy;
|
|
3629
|
+
if (config.abortSignal?.aborted) {
|
|
3630
|
+
return Promise.reject(config.abortSignal.reason);
|
|
3631
|
+
}
|
|
3574
3632
|
rawSignature = config.signature;
|
|
3575
3633
|
}
|
|
3576
3634
|
|
|
@@ -3602,6 +3660,21 @@ export class Connection {
|
|
|
3602
3660
|
}
|
|
3603
3661
|
}
|
|
3604
3662
|
|
|
3663
|
+
private getCancellationPromise(signal?: AbortSignal): Promise<never> {
|
|
3664
|
+
return new Promise<never>((_, reject) => {
|
|
3665
|
+
if (signal == null) {
|
|
3666
|
+
return;
|
|
3667
|
+
}
|
|
3668
|
+
if (signal.aborted) {
|
|
3669
|
+
reject(signal.reason);
|
|
3670
|
+
} else {
|
|
3671
|
+
signal.addEventListener('abort', () => {
|
|
3672
|
+
reject(signal.reason);
|
|
3673
|
+
});
|
|
3674
|
+
}
|
|
3675
|
+
});
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3605
3678
|
private getTransactionConfirmationPromise({
|
|
3606
3679
|
commitment,
|
|
3607
3680
|
signature,
|
|
@@ -3722,7 +3795,7 @@ export class Connection {
|
|
|
3722
3795
|
|
|
3723
3796
|
private async confirmTransactionUsingBlockHeightExceedanceStrategy({
|
|
3724
3797
|
commitment,
|
|
3725
|
-
strategy: {lastValidBlockHeight, signature},
|
|
3798
|
+
strategy: {abortSignal, lastValidBlockHeight, signature},
|
|
3726
3799
|
}: {
|
|
3727
3800
|
commitment?: Commitment;
|
|
3728
3801
|
strategy: BlockheightBasedTransactionConfirmationStrategy;
|
|
@@ -3753,9 +3826,14 @@ export class Connection {
|
|
|
3753
3826
|
});
|
|
3754
3827
|
const {abortConfirmation, confirmationPromise} =
|
|
3755
3828
|
this.getTransactionConfirmationPromise({commitment, signature});
|
|
3829
|
+
const cancellationPromise = this.getCancellationPromise(abortSignal);
|
|
3756
3830
|
let result: RpcResponseAndContext<SignatureResult>;
|
|
3757
3831
|
try {
|
|
3758
|
-
const outcome = await Promise.race([
|
|
3832
|
+
const outcome = await Promise.race([
|
|
3833
|
+
cancellationPromise,
|
|
3834
|
+
confirmationPromise,
|
|
3835
|
+
expiryPromise,
|
|
3836
|
+
]);
|
|
3759
3837
|
if (outcome.__type === TransactionStatus.PROCESSED) {
|
|
3760
3838
|
result = outcome.response;
|
|
3761
3839
|
} else {
|
|
@@ -3770,7 +3848,13 @@ export class Connection {
|
|
|
3770
3848
|
|
|
3771
3849
|
private async confirmTransactionUsingDurableNonceStrategy({
|
|
3772
3850
|
commitment,
|
|
3773
|
-
strategy: {
|
|
3851
|
+
strategy: {
|
|
3852
|
+
abortSignal,
|
|
3853
|
+
minContextSlot,
|
|
3854
|
+
nonceAccountPubkey,
|
|
3855
|
+
nonceValue,
|
|
3856
|
+
signature,
|
|
3857
|
+
},
|
|
3774
3858
|
}: {
|
|
3775
3859
|
commitment?: Commitment;
|
|
3776
3860
|
strategy: DurableNonceTransactionConfirmationStrategy;
|
|
@@ -3821,9 +3905,14 @@ export class Connection {
|
|
|
3821
3905
|
});
|
|
3822
3906
|
const {abortConfirmation, confirmationPromise} =
|
|
3823
3907
|
this.getTransactionConfirmationPromise({commitment, signature});
|
|
3908
|
+
const cancellationPromise = this.getCancellationPromise(abortSignal);
|
|
3824
3909
|
let result: RpcResponseAndContext<SignatureResult>;
|
|
3825
3910
|
try {
|
|
3826
|
-
const outcome = await Promise.race([
|
|
3911
|
+
const outcome = await Promise.race([
|
|
3912
|
+
cancellationPromise,
|
|
3913
|
+
confirmationPromise,
|
|
3914
|
+
expiryPromise,
|
|
3915
|
+
]);
|
|
3827
3916
|
if (outcome.__type === TransactionStatus.PROCESSED) {
|
|
3828
3917
|
result = outcome.response;
|
|
3829
3918
|
} else {
|
package/src/epoch-schedule.ts
CHANGED
|
@@ -26,7 +26,7 @@ function nextPowerOfTwo(n: number) {
|
|
|
26
26
|
/**
|
|
27
27
|
* Epoch schedule
|
|
28
28
|
* (see https://docs.solana.com/terminology#epoch)
|
|
29
|
-
* Can be retrieved with the {@link
|
|
29
|
+
* Can be retrieved with the {@link Connection.getEpochSchedule} method
|
|
30
30
|
*/
|
|
31
31
|
export class EpochSchedule {
|
|
32
32
|
/** The maximum number of slots in each epoch */
|
|
@@ -19,7 +19,11 @@ export async function sendAndConfirmTransaction(
|
|
|
19
19
|
connection: Connection,
|
|
20
20
|
transaction: Transaction,
|
|
21
21
|
signers: Array<Signer>,
|
|
22
|
-
options?: ConfirmOptions
|
|
22
|
+
options?: ConfirmOptions &
|
|
23
|
+
Readonly<{
|
|
24
|
+
// A signal that, when aborted, cancels any outstanding transaction confirmation operations
|
|
25
|
+
abortSignal?: AbortSignal;
|
|
26
|
+
}>,
|
|
23
27
|
): Promise<TransactionSignature> {
|
|
24
28
|
const sendOptions = options && {
|
|
25
29
|
skipPreflight: options.skipPreflight,
|
|
@@ -42,6 +46,7 @@ export async function sendAndConfirmTransaction(
|
|
|
42
46
|
status = (
|
|
43
47
|
await connection.confirmTransaction(
|
|
44
48
|
{
|
|
49
|
+
abortSignal: options?.abortSignal,
|
|
45
50
|
signature: signature,
|
|
46
51
|
blockhash: transaction.recentBlockhash,
|
|
47
52
|
lastValidBlockHeight: transaction.lastValidBlockHeight,
|
|
@@ -58,6 +63,7 @@ export async function sendAndConfirmTransaction(
|
|
|
58
63
|
status = (
|
|
59
64
|
await connection.confirmTransaction(
|
|
60
65
|
{
|
|
66
|
+
abortSignal: options?.abortSignal,
|
|
61
67
|
minContextSlot: transaction.minNonceContextSlot,
|
|
62
68
|
nonceAccountPubkey,
|
|
63
69
|
nonceValue: transaction.nonceInfo.nonce,
|
|
@@ -67,6 +73,13 @@ export async function sendAndConfirmTransaction(
|
|
|
67
73
|
)
|
|
68
74
|
).value;
|
|
69
75
|
} else {
|
|
76
|
+
if (options?.abortSignal != null) {
|
|
77
|
+
console.warn(
|
|
78
|
+
'sendAndConfirmTransaction(): A transaction with a deprecated confirmation strategy was ' +
|
|
79
|
+
'supplied along with an `abortSignal`. Only transactions having `lastValidBlockHeight` ' +
|
|
80
|
+
'or a combination of `nonceInfo` and `minNonceContextSlot` are abortable.',
|
|
81
|
+
);
|
|
82
|
+
}
|
|
70
83
|
status = (
|
|
71
84
|
await connection.confirmTransaction(
|
|
72
85
|
signature,
|