@ar.io/sdk 4.0.0-solana.22 → 4.0.0-solana.24
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 +105 -0
- package/lib/esm/cli/commands/escrowCommands.js +10 -3
- package/lib/esm/cli/utils.js +18 -7
- package/lib/esm/solana/ant-readable.js +7 -6
- package/lib/esm/solana/index.js +7 -1
- package/lib/esm/solana/io-readable.js +7 -6
- package/lib/esm/solana/io-writeable.js +300 -4
- package/lib/esm/solana/json-rpc.js +5 -4
- package/lib/esm/solana/predict-prescribed-observers.js +95 -0
- package/lib/esm/solana/retry.js +102 -0
- package/lib/esm/solana/rpc-circuit-breaker.js +75 -0
- package/lib/esm/solana/send.js +243 -3
- package/lib/esm/version.js +1 -1
- package/lib/types/solana/index.d.ts +6 -1
- package/lib/types/solana/io-writeable.d.ts +128 -2
- package/lib/types/solana/predict-prescribed-observers.d.ts +28 -0
- package/lib/types/solana/retry.d.ts +47 -0
- package/lib/types/solana/rpc-circuit-breaker.d.ts +49 -0
- package/lib/types/solana/send.d.ts +80 -2
- package/lib/types/version.d.ts +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -3140,6 +3140,110 @@ In the example above, the query will return ArNS records where:
|
|
|
3140
3140
|
|
|
3141
3141
|
## Advanced
|
|
3142
3142
|
|
|
3143
|
+
### RPC Configuration
|
|
3144
|
+
|
|
3145
|
+
The SDK accepts any `@solana/kit` RPC client. For read-only usage, only
|
|
3146
|
+
`rpc` is required. Write operations additionally need `rpcSubscriptions`
|
|
3147
|
+
(WebSocket) for transaction confirmation and a `signer`.
|
|
3148
|
+
|
|
3149
|
+
#### Basic (read-only)
|
|
3150
|
+
|
|
3151
|
+
```ts
|
|
3152
|
+
import { ARIO } from '@ar.io/sdk';
|
|
3153
|
+
import { createSolanaRpc } from '@solana/kit';
|
|
3154
|
+
|
|
3155
|
+
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
|
|
3156
|
+
const ario = ARIO.init({ rpc });
|
|
3157
|
+
```
|
|
3158
|
+
|
|
3159
|
+
#### With writes (signer + WebSocket subscriptions)
|
|
3160
|
+
|
|
3161
|
+
```ts
|
|
3162
|
+
import { ARIO } from '@ar.io/sdk';
|
|
3163
|
+
import {
|
|
3164
|
+
createSolanaRpc,
|
|
3165
|
+
createSolanaRpcSubscriptions,
|
|
3166
|
+
createKeyPairSignerFromBytes,
|
|
3167
|
+
} from '@solana/kit';
|
|
3168
|
+
|
|
3169
|
+
const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
|
|
3170
|
+
const rpcSubscriptions = createSolanaRpcSubscriptions(
|
|
3171
|
+
'wss://api.mainnet-beta.solana.com',
|
|
3172
|
+
);
|
|
3173
|
+
const signer = await createKeyPairSignerFromBytes(/* ... */);
|
|
3174
|
+
|
|
3175
|
+
const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
|
|
3176
|
+
```
|
|
3177
|
+
|
|
3178
|
+
> **Note:** `rpcSubscriptions` opens a WebSocket connection and is only
|
|
3179
|
+
> needed for writes. If your RPC provider doesn't expose a WebSocket
|
|
3180
|
+
> endpoint, omit it and use the SDK in read-only mode.
|
|
3181
|
+
|
|
3182
|
+
### Circuit Breaker
|
|
3183
|
+
|
|
3184
|
+
The SDK ships an [opossum]-backed circuit breaker that wraps the RPC
|
|
3185
|
+
transport. When the primary endpoint starts failing (429 rate-limits,
|
|
3186
|
+
5xx errors, network timeouts) the circuit opens and subsequent calls
|
|
3187
|
+
route transparently to a fallback RPC until the primary recovers.
|
|
3188
|
+
|
|
3189
|
+
```ts
|
|
3190
|
+
import { ARIO, createCircuitBreakerRpc } from '@ar.io/sdk';
|
|
3191
|
+
|
|
3192
|
+
const rpc = createCircuitBreakerRpc({
|
|
3193
|
+
primaryUrl: 'https://my-premium-rpc.example.com',
|
|
3194
|
+
fallbackUrl: 'https://api.mainnet-beta.solana.com',
|
|
3195
|
+
});
|
|
3196
|
+
|
|
3197
|
+
const ario = ARIO.init({ rpc });
|
|
3198
|
+
```
|
|
3199
|
+
|
|
3200
|
+
Use `defaultFallbackUrl()` to auto-pick mainnet or devnet based on the
|
|
3201
|
+
primary URL:
|
|
3202
|
+
|
|
3203
|
+
```ts
|
|
3204
|
+
import {
|
|
3205
|
+
createCircuitBreakerRpc,
|
|
3206
|
+
defaultFallbackUrl,
|
|
3207
|
+
} from '@ar.io/sdk';
|
|
3208
|
+
|
|
3209
|
+
const primaryUrl = 'https://my-premium-rpc.example.com';
|
|
3210
|
+
const rpc = createCircuitBreakerRpc({
|
|
3211
|
+
primaryUrl,
|
|
3212
|
+
fallbackUrl: defaultFallbackUrl(primaryUrl), // → mainnet public RPC
|
|
3213
|
+
});
|
|
3214
|
+
```
|
|
3215
|
+
|
|
3216
|
+
Tuning knobs (all optional):
|
|
3217
|
+
|
|
3218
|
+
| Option | Default | Description |
|
|
3219
|
+
|---|---|---|
|
|
3220
|
+
| `timeout` | `10000` | ms before a single request is timed out (`false` to disable) |
|
|
3221
|
+
| `errorThresholdPercentage` | `50` | error % at which to open the circuit |
|
|
3222
|
+
| `resetTimeout` | `30000` | ms to wait before probing the primary again (half-open) |
|
|
3223
|
+
| `volumeThreshold` | `5` | minimum requests in the rolling window before the circuit can trip |
|
|
3224
|
+
|
|
3225
|
+
### Automatic Retries
|
|
3226
|
+
|
|
3227
|
+
All RPC **read** calls (account fetches, `getProgramAccounts`, etc.)
|
|
3228
|
+
automatically retry on transient transport errors with exponential
|
|
3229
|
+
back-off. Writes are **not** retried (to avoid double-sends).
|
|
3230
|
+
|
|
3231
|
+
Retried errors: HTTP 429/5xx, `fetch failed`, `ECONNRESET`,
|
|
3232
|
+
`ETIMEDOUT`, `AbortError` / timeouts. Non-retryable errors (account
|
|
3233
|
+
not found, invalid params, deserialization) throw immediately.
|
|
3234
|
+
|
|
3235
|
+
Defaults: **6 attempts**, 500 ms base delay, 5 s max delay. Override
|
|
3236
|
+
per-call with the exported `withRetry` helper:
|
|
3237
|
+
|
|
3238
|
+
```ts
|
|
3239
|
+
import { withRetry } from '@ar.io/sdk';
|
|
3240
|
+
|
|
3241
|
+
const result = await withRetry(() => rpc.getAccountInfo(addr).send(), {
|
|
3242
|
+
maxAttempts: 3,
|
|
3243
|
+
baseDelayMs: 1000,
|
|
3244
|
+
});
|
|
3245
|
+
```
|
|
3246
|
+
|
|
3143
3247
|
### Generated instruction builders
|
|
3144
3248
|
|
|
3145
3249
|
For custom transaction building, import Codama-emitted typed clients
|
|
@@ -3230,6 +3334,7 @@ For more information on how to contribute, please see [CONTRIBUTING.md].
|
|
|
3230
3334
|
[ar-io-node repository]: https://github.com/ar-io/ar-io-node
|
|
3231
3335
|
[ar.io Gateway Documentation]: https://docs.ar.io/gateways/ar-io-node/overview/
|
|
3232
3336
|
[ANS-104]: https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md
|
|
3337
|
+
[opossum]: https://nodeshift.dev/opossum/
|
|
3233
3338
|
|
|
3234
3339
|
```
|
|
3235
3340
|
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
* - Ethereum: `--recipient-ethereum 0x...` parses the 20-byte hex address.
|
|
22
22
|
*/
|
|
23
23
|
import { readFileSync } from 'node:fs';
|
|
24
|
-
import { address, createKeyPairSignerFromBytes,
|
|
24
|
+
import { address, createKeyPairSignerFromBytes, createSolanaRpcSubscriptions, } from '@solana/kit';
|
|
25
25
|
import bs58 from 'bs58';
|
|
26
26
|
import { ARIO_ANT_ESCROW_PROGRAM_ID } from '../../solana/constants.js';
|
|
27
27
|
import { ANTEscrow } from '../../solana/escrow.js';
|
|
28
|
+
import { createCircuitBreakerRpc, defaultFallbackUrl, } from '../../solana/rpc-circuit-breaker.js';
|
|
28
29
|
// =========================================
|
|
29
30
|
// Wiring helpers
|
|
30
31
|
// =========================================
|
|
@@ -39,7 +40,10 @@ function escrowProgramIdFrom(options) {
|
|
|
39
40
|
async function readEscrowReader(options) {
|
|
40
41
|
const rpcUrl = options.rpcUrl ?? 'https://api.mainnet-beta.solana.com';
|
|
41
42
|
return ANTEscrow.init({
|
|
42
|
-
rpc:
|
|
43
|
+
rpc: createCircuitBreakerRpc({
|
|
44
|
+
primaryUrl: rpcUrl,
|
|
45
|
+
fallbackUrl: defaultFallbackUrl(rpcUrl),
|
|
46
|
+
}),
|
|
43
47
|
programId: escrowProgramIdFrom(options),
|
|
44
48
|
});
|
|
45
49
|
}
|
|
@@ -58,7 +62,10 @@ async function writeEscrowFromOptions(options) {
|
|
|
58
62
|
const signer = await createKeyPairSignerFromBytes(secretKey);
|
|
59
63
|
const rpcUrl = options.rpcUrl ?? 'https://api.mainnet-beta.solana.com';
|
|
60
64
|
return ANTEscrow.init({
|
|
61
|
-
rpc:
|
|
65
|
+
rpc: createCircuitBreakerRpc({
|
|
66
|
+
primaryUrl: rpcUrl,
|
|
67
|
+
fallbackUrl: defaultFallbackUrl(rpcUrl),
|
|
68
|
+
}),
|
|
62
69
|
rpcSubscriptions: createSolanaRpcSubscriptions(wsUrlFromRpcUrl(rpcUrl)),
|
|
63
70
|
signer,
|
|
64
71
|
programId: escrowProgramIdFrom(options),
|
package/lib/esm/cli/utils.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { readFileSync } from 'fs';
|
|
17
|
-
import { address, createKeyPairSignerFromBytes,
|
|
17
|
+
import { address, createKeyPairSignerFromBytes, createSolanaRpcSubscriptions, } from '@solana/kit';
|
|
18
18
|
import bs58 from 'bs58';
|
|
19
19
|
import { program } from 'commander';
|
|
20
20
|
import prompts from 'prompts';
|
|
@@ -22,6 +22,7 @@ import { ANTRegistry } from '../common/ant-registry.js';
|
|
|
22
22
|
import { ANT } from '../common/ant.js';
|
|
23
23
|
import { ARIO } from '../common/io.js';
|
|
24
24
|
import { Logger } from '../common/logger.js';
|
|
25
|
+
import { createCircuitBreakerRpc, defaultFallbackUrl, } from '../solana/rpc-circuit-breaker.js';
|
|
25
26
|
import { fundFromOptions, isValidFundFrom, isValidIntent, validIntents, } from '../types/io.js';
|
|
26
27
|
import { ARIOToken, mARIOToken } from '../types/token.js';
|
|
27
28
|
import { globalOptions } from './options.js';
|
|
@@ -84,7 +85,7 @@ export function readARIOFromOptions(options) {
|
|
|
84
85
|
setLoggerIfDebug(options);
|
|
85
86
|
const rpcUrl = options.rpcUrl ?? 'https://api.mainnet-beta.solana.com';
|
|
86
87
|
return ARIO.init({
|
|
87
|
-
rpc:
|
|
88
|
+
rpc: createCliRpc(rpcUrl),
|
|
88
89
|
...(options.coreProgramId
|
|
89
90
|
? { coreProgramId: address(options.coreProgramId) }
|
|
90
91
|
: {}),
|
|
@@ -100,7 +101,7 @@ export async function readANTRegistryFromOptions(options) {
|
|
|
100
101
|
setLoggerIfDebug(options);
|
|
101
102
|
const rpcUrl = options.rpcUrl ?? 'https://api.mainnet-beta.solana.com';
|
|
102
103
|
return ANTRegistry.init({
|
|
103
|
-
rpc:
|
|
104
|
+
rpc: createCliRpc(rpcUrl),
|
|
104
105
|
...(options.antProgramId
|
|
105
106
|
? { antProgramId: address(options.antProgramId) }
|
|
106
107
|
: {}),
|
|
@@ -129,6 +130,16 @@ function wsUrlFromRpcUrl(rpcUrl) {
|
|
|
129
130
|
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
130
131
|
return url.toString().replace(/\/$/, '');
|
|
131
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Create a {@link SolanaRpc} wrapped with a circuit-breaker that falls back to
|
|
135
|
+
* the cluster's public RPC when the primary endpoint becomes unhealthy.
|
|
136
|
+
*/
|
|
137
|
+
function createCliRpc(rpcUrl) {
|
|
138
|
+
return createCircuitBreakerRpc({
|
|
139
|
+
primaryUrl: rpcUrl,
|
|
140
|
+
fallbackUrl: defaultFallbackUrl(rpcUrl),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
132
143
|
/**
|
|
133
144
|
* Load a Solana KeyPairSigner from --private-key (base58) or --wallet-file
|
|
134
145
|
* (JSON array of bytes). Throws with a helpful message if neither is set.
|
|
@@ -155,7 +166,7 @@ export async function writeARIOFromOptions(options) {
|
|
|
155
166
|
const signer = await loadSolanaSignerFromOptions(options);
|
|
156
167
|
return {
|
|
157
168
|
ario: ARIO.init({
|
|
158
|
-
rpc:
|
|
169
|
+
rpc: createCliRpc(rpcUrl),
|
|
159
170
|
rpcSubscriptions: createSolanaRpcSubscriptions(wsUrlFromRpcUrl(rpcUrl)),
|
|
160
171
|
signer,
|
|
161
172
|
// Forward program-id overrides so localnet / devnet writes target the
|
|
@@ -427,7 +438,7 @@ export async function readANTFromOptions(options) {
|
|
|
427
438
|
const rpcUrl = options.rpcUrl ?? 'https://api.mainnet-beta.solana.com';
|
|
428
439
|
return ANT.init({
|
|
429
440
|
processId: requiredProcessIdFromOptions(options),
|
|
430
|
-
rpc:
|
|
441
|
+
rpc: createCliRpc(rpcUrl),
|
|
431
442
|
...(options.antProgramId
|
|
432
443
|
? { antProgramId: address(options.antProgramId) }
|
|
433
444
|
: {}),
|
|
@@ -438,7 +449,7 @@ export async function writeANTFromOptions(options) {
|
|
|
438
449
|
const kitSigner = await loadSolanaSignerFromOptions(options);
|
|
439
450
|
return ANT.init({
|
|
440
451
|
processId: requiredProcessIdFromOptions(options),
|
|
441
|
-
rpc:
|
|
452
|
+
rpc: createCliRpc(rpcUrl),
|
|
442
453
|
rpcSubscriptions: createSolanaRpcSubscriptions(wsUrlFromRpcUrl(rpcUrl)),
|
|
443
454
|
signer: kitSigner,
|
|
444
455
|
...(options.antProgramId
|
|
@@ -524,7 +535,7 @@ export async function spawnSolanaANTFromOptions(options) {
|
|
|
524
535
|
'See sdk/scripts/devnet-validation/populate-ant.ts for an end-to-end example.');
|
|
525
536
|
}
|
|
526
537
|
return spawnSolanaANT({
|
|
527
|
-
rpc:
|
|
538
|
+
rpc: createCliRpc(rpcUrl),
|
|
528
539
|
rpcSubscriptions: createSolanaRpcSubscriptions(wsUrlFromRpcUrl(rpcUrl)),
|
|
529
540
|
signer: kitSigner,
|
|
530
541
|
state: {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { address, fetchEncodedAccount, } from '@solana/kit';
|
|
11
11
|
import bs58 from 'bs58';
|
|
12
|
+
import { withRetry } from './retry.js';
|
|
12
13
|
// AntRecordMetadata discriminator — regenerate via `yarn codegen` after IDL rebase
|
|
13
14
|
// to expose ANT_RECORD_METADATA_DISCRIMINATOR. Until then, compute inline.
|
|
14
15
|
import { createHash as __createHash } from 'crypto';
|
|
@@ -102,9 +103,9 @@ export class SolanaANTReadable {
|
|
|
102
103
|
});
|
|
103
104
|
}
|
|
104
105
|
async getAccount(pda) {
|
|
105
|
-
return fetchEncodedAccount(this.rpc, pda, {
|
|
106
|
+
return withRetry(() => fetchEncodedAccount(this.rpc, pda, {
|
|
106
107
|
commitment: this.commitment,
|
|
107
|
-
});
|
|
108
|
+
}));
|
|
108
109
|
}
|
|
109
110
|
// =========================================
|
|
110
111
|
// Config reads
|
|
@@ -204,20 +205,20 @@ export class SolanaANTReadable {
|
|
|
204
205
|
},
|
|
205
206
|
];
|
|
206
207
|
const [recordAccounts, metaAccounts] = (await Promise.all([
|
|
207
|
-
this.rpc
|
|
208
|
+
withRetry(() => this.rpc
|
|
208
209
|
.getProgramAccounts(this.antProgram, {
|
|
209
210
|
commitment: this.commitment,
|
|
210
211
|
encoding: 'base64',
|
|
211
212
|
filters: gpaFilter(bs58.encode(ANT_RECORD_DISCRIMINATOR)),
|
|
212
213
|
})
|
|
213
|
-
.send(),
|
|
214
|
-
this.rpc
|
|
214
|
+
.send()),
|
|
215
|
+
withRetry(() => this.rpc
|
|
215
216
|
.getProgramAccounts(this.antProgram, {
|
|
216
217
|
commitment: this.commitment,
|
|
217
218
|
encoding: 'base64',
|
|
218
219
|
filters: gpaFilter(bs58.encode(ANT_RECORD_METADATA_DISCRIMINATOR)),
|
|
219
220
|
})
|
|
220
|
-
.send(),
|
|
221
|
+
.send()),
|
|
221
222
|
]));
|
|
222
223
|
// Index metadata by undername hash for O(1) lookup.
|
|
223
224
|
// AntRecordMetadata has undername_hash at offset 40 (8 disc + 32 mint).
|
package/lib/esm/solana/index.js
CHANGED
|
@@ -54,7 +54,7 @@ export { ARWEAVE_TX_REGEX, AR_IO_PROTOCOL, arweaveUri, FQDN_REGEX, MARIO_PER_ARI
|
|
|
54
54
|
// Solana implementation classes (still exported for advanced/direct usage —
|
|
55
55
|
// the `ARIO` / `ANT` factories above wrap these).
|
|
56
56
|
export { SolanaARIOReadable } from './io-readable.js';
|
|
57
|
-
export { SolanaARIOWriteable } from './io-writeable.js';
|
|
57
|
+
export { isInvalidGatewayAccountError, SolanaARIOWriteable, } from './io-writeable.js';
|
|
58
58
|
// ANT classes
|
|
59
59
|
export { SolanaANTReadable } from './ant-readable.js';
|
|
60
60
|
export { SolanaANTWriteable } from './ant-writeable.js';
|
|
@@ -88,6 +88,8 @@ export { hashName, getArioConfigPDA, getBalancePDA, getVaultPDA, getVaultCounter
|
|
|
88
88
|
// `ANT_RECORD_DISCRIMINATOR`). Pull them from there instead of asking
|
|
89
89
|
// this module — single source of truth, derived from the IDL.
|
|
90
90
|
export { BorshReader, BorshWriter, deserializeGateway, deserializeArnsRecord, deserializeVault, deserializeDelegation, deserializeBalance, deserializeEpochSettings, deserializeArioConfig, deserializeDemandFactor, deserializeReservedName, deserializeReturnedName, deserializeWithdrawal, deserializeRedelegationRecord, deserializePrimaryNameRequest, deserializePrimaryName, deserializeAllowlist, deserializeGarSettings, deserializeEpochSettingsFull, deserializeEpoch, deserializeObservation, deserializeAntConfig, deserializeAntControllers, deserializeAntRecord, deserializeAclConfig, deserializeAclPage, } from './deserialize.js';
|
|
91
|
+
// Off-chain prediction of prescribe_epoch's observer selection (cranker helper)
|
|
92
|
+
export { predictPrescribedObservers, } from './predict-prescribed-observers.js';
|
|
91
93
|
// Constants
|
|
92
94
|
export * from './constants.js';
|
|
93
95
|
// Cluster-specific deployment constants (devnet program IDs, RPC URL,
|
|
@@ -95,6 +97,10 @@ export * from './constants.js';
|
|
|
95
97
|
// `/devnet-config.json` — kept in sync via the drift guard test
|
|
96
98
|
// `clusters.test.ts`.
|
|
97
99
|
export * from './clusters.js';
|
|
100
|
+
// RPC circuit breaker (opossum-backed transparent fallback)
|
|
101
|
+
export { createCircuitBreakerRpc, defaultFallbackUrl, } from './rpc-circuit-breaker.js';
|
|
102
|
+
// Retry utility (exponential back-off for transient RPC errors)
|
|
103
|
+
export { withRetry, isRetryableError } from './retry.js';
|
|
98
104
|
// Event decoders
|
|
99
105
|
//
|
|
100
106
|
// `parseTransactionEvents(rpc, signature)` and `parseEventsFromLogs(logs)`
|
|
@@ -18,6 +18,7 @@ import { computeLiveDelegationBalance } from './delegation-math.js';
|
|
|
18
18
|
import { deserializeAllowlist, deserializeArioConfig, deserializeArnsRecord, deserializeDelegation, deserializeDemandFactor, deserializeEpoch, deserializeEpochSettings, deserializeEpochSettingsFull, deserializeGarSettings, deserializeGarSupplyCounters, deserializeGateway, deserializeGatewayWithAccumulator, deserializeObservation, deserializePrimaryName, deserializePrimaryNameRequest, deserializeRedelegationRecord, deserializeReservedName, deserializeReturnedName, deserializeVault, deserializeWithdrawal, } from './deserialize.js';
|
|
19
19
|
import { TOKEN_PROGRAM_ADDRESS } from './instruction.js';
|
|
20
20
|
import { getArioConfigPDA, getArnsRecordPDA, getArnsRecordPDAFromHash, getArnsSettingsPDA, getDemandFactorPDA, getEpochPDA, getEpochSettingsPDA, getGarSettingsPDA, getGatewayPDA, getGatewayRegistryPDA, getObserverLookupPDA, getPrimaryNamePDA, getPrimaryNameRequestPDA, getReservedNamePDA, getReturnedNamePDA, getVaultPDA, } from './pda.js';
|
|
21
|
+
import { withRetry } from './retry.js';
|
|
21
22
|
const addressDecoder = getAddressDecoder();
|
|
22
23
|
/** All-zero address — equivalent of web3.js `PublicKey.default`. */
|
|
23
24
|
const DEFAULT_ADDRESS = address('11111111111111111111111111111111');
|
|
@@ -141,9 +142,9 @@ export class SolanaARIOReadable {
|
|
|
141
142
|
}
|
|
142
143
|
/** Helper to fetch an encoded account (kit's replacement for Connection.getAccountInfo). */
|
|
143
144
|
async getAccount(pda) {
|
|
144
|
-
return fetchEncodedAccount(this.rpc, pda, {
|
|
145
|
+
return withRetry(() => fetchEncodedAccount(this.rpc, pda, {
|
|
145
146
|
commitment: this.commitment,
|
|
146
|
-
});
|
|
147
|
+
}));
|
|
147
148
|
}
|
|
148
149
|
/**
|
|
149
150
|
* Helper for `getProgramAccounts` with a discriminator memcmp filter.
|
|
@@ -168,7 +169,7 @@ export class SolanaARIOReadable {
|
|
|
168
169
|
// when called without `withContext: true`. With `encoding: 'base64'`, each
|
|
169
170
|
// account's `data` is a `[base64, 'base64']` tuple. We bypass kit's strict
|
|
170
171
|
// generic overload typing here with a cast — the runtime shape is stable.
|
|
171
|
-
const result =
|
|
172
|
+
const result = await withRetry(() => this.rpc
|
|
172
173
|
.getProgramAccounts(programId, {
|
|
173
174
|
commitment: this.commitment,
|
|
174
175
|
encoding: 'base64',
|
|
@@ -195,9 +196,9 @@ export class SolanaARIOReadable {
|
|
|
195
196
|
if (unique.length === 0)
|
|
196
197
|
return new Map();
|
|
197
198
|
const pdas = await Promise.all(unique.map(async (op) => (await getGatewayPDA(address(op), this.garProgram))[0]));
|
|
198
|
-
const accounts = await fetchEncodedAccounts(this.rpc, pdas, {
|
|
199
|
+
const accounts = await withRetry(() => fetchEncodedAccounts(this.rpc, pdas, {
|
|
199
200
|
commitment: this.commitment,
|
|
200
|
-
});
|
|
201
|
+
}));
|
|
201
202
|
const out = new Map();
|
|
202
203
|
for (let i = 0; i < accounts.length; i++) {
|
|
203
204
|
const acct = accounts[i];
|
|
@@ -387,7 +388,7 @@ export class SolanaARIOReadable {
|
|
|
387
388
|
},
|
|
388
389
|
},
|
|
389
390
|
];
|
|
390
|
-
const result =
|
|
391
|
+
const result = await withRetry(() => this.rpc
|
|
391
392
|
.getProgramAccounts(TOKEN_PROGRAM_ADDRESS, {
|
|
392
393
|
commitment: this.commitment,
|
|
393
394
|
encoding: 'base64',
|