@pushchain/core 6.0.25 → 6.0.26

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.
Files changed (32) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/package.json +1 -1
  3. package/src/lib/constants/chain.js +1 -1
  4. package/src/lib/constants/index.d.ts +5 -3
  5. package/src/lib/constants/index.js +1 -0
  6. package/src/lib/constants/read-state.d.ts +6 -2
  7. package/src/lib/constants/read-state.js +7 -3
  8. package/src/lib/index.d.ts +1 -1
  9. package/src/lib/index.js +3 -2
  10. package/src/lib/progress-hook/progress-hook.js +21 -0
  11. package/src/lib/progress-hook/progress-hook.types.d.ts +4 -1
  12. package/src/lib/progress-hook/progress-hook.types.js +3 -0
  13. package/src/lib/push-chain/push-chain.d.ts +2 -1
  14. package/src/lib/push-chain/push-chain.js +4 -3
  15. package/src/lib/push-client/push-client.d.ts +7 -0
  16. package/src/lib/push-client/push-client.js +41 -15
  17. package/src/lib/read-state/envelopes/evm.js +2 -3
  18. package/src/lib/read-state/envelopes/svm.js +11 -1
  19. package/src/lib/read-state/read-executor.js +4 -0
  20. package/src/lib/read-state/read-params.d.ts +68 -23
  21. package/src/lib/read-state/read-params.js +57 -13
  22. package/src/lib/read-state/read-state.types.d.ts +41 -0
  23. package/src/lib/read-state/read-state.types.js +23 -1
  24. package/src/lib/read-state/read-tracker.d.ts +6 -1
  25. package/src/lib/read-state/read-tracker.js +81 -15
  26. package/src/lib/read-state/registry.js +2 -3
  27. package/src/lib/read-state/result-decoder.js +6 -0
  28. package/src/lib/read-state/spec-builder.js +1 -1
  29. package/src/lib/read-state/svm-account.d.ts +20 -0
  30. package/src/lib/read-state/svm-account.js +114 -0
  31. package/src/lib/read-state/svm-pda.d.ts +13 -0
  32. package/src/lib/read-state/svm-pda.js +147 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,69 @@
1
+ @pushchain/core@6.0.26 (2026-09-23)
2
+
3
+ - docs: changelog for read-state docs parity
4
+ - feat: align read-state API with the Universal Read docs
5
+ - fix: race prune and archive for Push receipts and block results
6
+ - feat: add Solana account reads and update read registry
7
+
8
+ ---
9
+
10
+ @pushchain/core (unreleased)
11
+
12
+ Changes on `feature/readstate-docs-parity` since 6.0.25, aligning Universal Read with the
13
+ push-chain-website docs (PR #1244).
14
+
15
+ ### Breaking
16
+
17
+ - Solana token reads detect SPL Token vs Token-2022 from the mint's owner. The
18
+ `tokenProgram` option is removed and now throws.
19
+ - The Donut Universal Read Registry default is
20
+ `0x00000000000000000000000000000000000000b2`. Results stored on the previous
21
+ registry stay there; tracking by request ID still works.
22
+ - `READ-TX-199-01` (level SUCCESS) now fires only when `outcome` is `SUCCESS`. A
23
+ FULFILLED read that did not work (source error, callback failure, undecodable
24
+ result, unconfirmed delivery) ends on `READ-TX-199-02`, whose `status` is the
25
+ outcome name.
26
+
27
+ ### Added
28
+
29
+ - Solana account reads with `idl`, the counterpart of `abi`. The account layout is
30
+ picked by its 8-byte discriminator; the optional `functionName` names the layout
31
+ (snake, camel or Pascal case) and types `value`. With the program id as the
32
+ subject, `functionName` plus positional `args` derive the PDA from the seeds the
33
+ IDL declares. `accountName` is not supported and throws with a hint.
34
+ - EVM contract-call reads accept any ABI function, including `nonpayable` and
35
+ `payable`. Validators run the call as an `eth_call` simulation at the pinned
36
+ block, so it returns data and never executes.
37
+ - `response.outcome` (`PushChain.CONSTANTS.READ.OUTCOME`): one answer to "did it
38
+ work" — `SUCCESS`, `SOURCE_ERROR`, `CALLBACK_FAILED`, `DECODE_FAILED`,
39
+ `EXPIRED`, `FAILED`, `ABORTED`, `PENDING`, or `UNKNOWN` (delivery unconfirmed).
40
+ - `response.requestIdUint`: the request ID as the `uint256` contracts key results by.
41
+ - Progress events: `READ-TX-104-03` Looking Up Request, `104-04` Request Found,
42
+ `104-05` Request Not Found (lookup timeout), `105-04` Approaching Expiry (once per
43
+ `wait()`, at 30 or fewer Push blocks left) and `102-04` Preflight Stale (a read
44
+ prepared more than 60 s before `executeReads`).
45
+
46
+ ### Improved
47
+
48
+ - `trackRead` on a settled read returns in about 1 s instead of about 19 s on
49
+ Donut. Fulfil and settle receipts are fetched in parallel, and Push receipts
50
+ are requested from the prune RPC and the archive at the same time.
51
+ - `callback.gasLimit` is optional for custom targets and defaults to `500_000n`,
52
+ like the registry. Unused callback budget is refunded.
53
+ - Refund events `READ-TX-106-05/06` also fire for expired reads.
54
+ - `value` is typed `unknown` for ABIs not declared `as const`; a single-output
55
+ function decodes to the bare value, not an array.
56
+
57
+ ### Fixed
58
+
59
+ - `explorerUrl` and Donut's viem `blockExplorers` pointed at
60
+ `explorer.donut.push.org`, which does not resolve. They now use
61
+ `https://donut.push.network`.
62
+ - Refunds of expired reads older than the prune window came back `undefined`.
63
+ Cosmos block results now fall back to the archive RPC.
64
+
65
+ ---
66
+
1
67
  @pushchain/core@6.0.25 (2026-09-16)
2
68
 
3
69
  - docs: document read-state and transaction fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushchain/core",
3
- "version": "6.0.25",
3
+ "version": "6.0.26",
4
4
  "homepage": "https://push.org",
5
5
  "keywords": [
6
6
  "pushchain",
@@ -210,7 +210,7 @@ exports.CHAIN_INFO = {
210
210
  confirmations: 1,
211
211
  fastConfirmations: 0,
212
212
  timeout: 30000,
213
- explorerUrl: 'https://explorer.donut.push.org',
213
+ explorerUrl: 'https://donut.push.network',
214
214
  // Push Chain AMM - Uniswap V3
215
215
  // Source: https://push.org/agents/contract-addresses.json
216
216
  dex: {
@@ -1,6 +1,6 @@
1
1
  import { CHAIN, LIBRARY, PUSH_NETWORK } from './enums';
2
2
  import { TypedDataDomain, TypedData } from '../universal/signer/signer.types';
3
- import { UNIVERSAL_READ_STATUS, READ_STATUS, READ_ERROR_CODE } from '../read-state/read-state.types';
3
+ import { UNIVERSAL_READ_STATUS, READ_STATUS, READ_ERROR_CODE, READ_OUTCOME } from '../read-state/read-state.types';
4
4
  /** `PushChain.CONSTANTS.READ` — cross-chain read state. Values verified against the deployed UniversalCallback. */
5
5
  export declare const READ_CONSTANTS: {
6
6
  /** Read-only Web2 destination. Equivalent to `CHAIN.WEB2`. */
@@ -16,7 +16,7 @@ export declare const READ_CONSTANTS: {
16
16
  readonly CALLBACK_BUDGET_BUFFER: 3;
17
17
  readonly REGISTRY_CALLBACK_GAS: 500000n;
18
18
  readonly UNIVERSAL_READ_REGISTRY_ADDRESS: {
19
- readonly TESTNET_DONUT: "0x91b09DAd1774bAfDE679F9ebB5F9046AE2b928C8";
19
+ readonly TESTNET_DONUT: "0x00000000000000000000000000000000000000b2";
20
20
  };
21
21
  readonly WEB2_MAX_EXTRACT_ENTRIES: 16;
22
22
  readonly WEB2_DEFAULT_TIMEOUT_MS: 5000;
@@ -25,6 +25,7 @@ export declare const READ_CONSTANTS: {
25
25
  readonly STATUS: typeof UNIVERSAL_READ_STATUS;
26
26
  readonly RESULT_STATUS: typeof READ_STATUS;
27
27
  readonly ERROR_CODE: typeof READ_ERROR_CODE;
28
+ readonly OUTCOME: typeof READ_OUTCOME;
28
29
  };
29
30
  export type { MoveableToken, PayableToken, PushChainMoveableToken, ChainSuffixAccessor, UsdcChainSuffixAccessor, PushChainMoveableTokenAccessor, MoveableTokenConstantsMap, PayableTokenConstantsMap, } from './tokens';
30
31
  export declare const CONSTANTS: {
@@ -51,7 +52,7 @@ export declare const CONSTANTS: {
51
52
  readonly CALLBACK_BUDGET_BUFFER: 3;
52
53
  readonly REGISTRY_CALLBACK_GAS: 500000n;
53
54
  readonly UNIVERSAL_READ_REGISTRY_ADDRESS: {
54
- readonly TESTNET_DONUT: "0x91b09DAd1774bAfDE679F9ebB5F9046AE2b928C8";
55
+ readonly TESTNET_DONUT: "0x00000000000000000000000000000000000000b2";
55
56
  };
56
57
  readonly WEB2_MAX_EXTRACT_ENTRIES: 16;
57
58
  readonly WEB2_DEFAULT_TIMEOUT_MS: 5000;
@@ -60,6 +61,7 @@ export declare const CONSTANTS: {
60
61
  readonly STATUS: typeof UNIVERSAL_READ_STATUS;
61
62
  readonly RESULT_STATUS: typeof READ_STATUS;
62
63
  readonly ERROR_CODE: typeof READ_ERROR_CODE;
64
+ readonly OUTCOME: typeof READ_OUTCOME;
63
65
  };
64
66
  };
65
67
  export type { TypedDataDomain, TypedData };
@@ -25,6 +25,7 @@ exports.READ_CONSTANTS = {
25
25
  STATUS: read_state_types_1.UNIVERSAL_READ_STATUS,
26
26
  RESULT_STATUS: read_state_types_1.READ_STATUS,
27
27
  ERROR_CODE: read_state_types_1.READ_ERROR_CODE,
28
+ OUTCOME: read_state_types_1.READ_OUTCOME,
28
29
  };
29
30
  // NOTE - Only include enums & constants which need to be exported to end user.
30
31
  exports.CONSTANTS = {
@@ -7,11 +7,11 @@
7
7
  */
8
8
  /** Hard upper bound on the gas an app callback may declare — `ReadTypes.sol:50`. */
9
9
  export declare const MAX_CALLBACK_GAS_LIMIT = 1000000n;
10
- /** Registry default; large results may need an explicit override up to the maximum. */
10
+ /** Default callback gas (registry and custom targets); large results may need an explicit override up to the maximum. */
11
11
  export declare const REGISTRY_CALLBACK_GAS = 500000n;
12
12
  /** Verified proxy on Donut. Other networks intentionally have no default receiver. */
13
13
  export declare const UNIVERSAL_READ_REGISTRY_ADDRESS: {
14
- readonly TESTNET_DONUT: "0x91b09DAd1774bAfDE679F9ebB5F9046AE2b928C8";
14
+ readonly TESTNET_DONUT: "0x00000000000000000000000000000000000000b2";
15
15
  };
16
16
  /** Contract rejects anything below this — `ReadTypes.sol:43`. */
17
17
  export declare const MIN_CONFIRMATIONS_FLOOR = 1;
@@ -49,5 +49,9 @@ export declare const READ_TRACK_POLL_INTERVAL_MS = 2000;
49
49
  export declare const READ_TRACK_MIN_POLL_INTERVAL_MS = 500;
50
50
  /** Default `wait()` timeout is `expiryBlocks × PUSH_BLOCK_TIME_MS`, capped here. */
51
51
  export declare const READ_TRACK_MAX_TIMEOUT_MS = 180000;
52
+ /** A prepared read older than this is announced stale (READ-TX-102-04) and revalidated against fresh preflight. */
53
+ export declare const READ_PREFLIGHT_STALE_MS = 60000;
54
+ /** `wait()` announces READ-TX-105-04 once this few Push blocks (~40 s) remain before expiry. */
55
+ export declare const READ_EXPIRY_WARNING_BLOCKS = 30n;
52
56
  /** How long `trackRead` keeps looking for a record the node has not ingested yet. */
53
57
  export declare const READ_TRACK_LOOKUP_TIMEOUT_MS = 30000;
@@ -7,14 +7,14 @@
7
7
  * `read-state/__tests__/abi-selectors.spec.ts`.
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.READ_TRACK_LOOKUP_TIMEOUT_MS = exports.READ_TRACK_MAX_TIMEOUT_MS = exports.READ_TRACK_MIN_POLL_INTERVAL_MS = exports.READ_TRACK_POLL_INTERVAL_MS = exports.PUSH_BLOCK_TIME_MS = exports.READ_NAMESPACE = exports.WEB2_DESTINATION = exports.WEB2_MAX_TIMEOUT_MS = exports.WEB2_DEFAULT_TIMEOUT_MS = exports.WEB2_MAX_EXTRACT_ENTRIES = exports.CALLBACK_BUDGET_BUFFER = exports.DEFAULT_EXPIRY_BLOCKS = exports.MIN_CONFIRMATIONS_FLOOR = exports.UNIVERSAL_READ_REGISTRY_ADDRESS = exports.REGISTRY_CALLBACK_GAS = exports.MAX_CALLBACK_GAS_LIMIT = void 0;
10
+ exports.READ_TRACK_LOOKUP_TIMEOUT_MS = exports.READ_EXPIRY_WARNING_BLOCKS = exports.READ_PREFLIGHT_STALE_MS = exports.READ_TRACK_MAX_TIMEOUT_MS = exports.READ_TRACK_MIN_POLL_INTERVAL_MS = exports.READ_TRACK_POLL_INTERVAL_MS = exports.PUSH_BLOCK_TIME_MS = exports.READ_NAMESPACE = exports.WEB2_DESTINATION = exports.WEB2_MAX_TIMEOUT_MS = exports.WEB2_DEFAULT_TIMEOUT_MS = exports.WEB2_MAX_EXTRACT_ENTRIES = exports.CALLBACK_BUDGET_BUFFER = exports.DEFAULT_EXPIRY_BLOCKS = exports.MIN_CONFIRMATIONS_FLOOR = exports.UNIVERSAL_READ_REGISTRY_ADDRESS = exports.REGISTRY_CALLBACK_GAS = exports.MAX_CALLBACK_GAS_LIMIT = void 0;
11
11
  /** Hard upper bound on the gas an app callback may declare — `ReadTypes.sol:50`. */
12
12
  exports.MAX_CALLBACK_GAS_LIMIT = 1000000n;
13
- /** Registry default; large results may need an explicit override up to the maximum. */
13
+ /** Default callback gas (registry and custom targets); large results may need an explicit override up to the maximum. */
14
14
  exports.REGISTRY_CALLBACK_GAS = 500000n;
15
15
  /** Verified proxy on Donut. Other networks intentionally have no default receiver. */
16
16
  exports.UNIVERSAL_READ_REGISTRY_ADDRESS = {
17
- TESTNET_DONUT: '0x91b09DAd1774bAfDE679F9ebB5F9046AE2b928C8',
17
+ TESTNET_DONUT: '0x00000000000000000000000000000000000000b2',
18
18
  };
19
19
  /** Contract rejects anything below this — `ReadTypes.sol:43`. */
20
20
  exports.MIN_CONFIRMATIONS_FLOOR = 1;
@@ -54,6 +54,10 @@ exports.READ_TRACK_POLL_INTERVAL_MS = 2_000;
54
54
  exports.READ_TRACK_MIN_POLL_INTERVAL_MS = 500;
55
55
  /** Default `wait()` timeout is `expiryBlocks × PUSH_BLOCK_TIME_MS`, capped here. */
56
56
  exports.READ_TRACK_MAX_TIMEOUT_MS = 180_000;
57
+ /** A prepared read older than this is announced stale (READ-TX-102-04) and revalidated against fresh preflight. */
58
+ exports.READ_PREFLIGHT_STALE_MS = 60_000;
59
+ /** `wait()` announces READ-TX-105-04 once this few Push blocks (~40 s) remain before expiry. */
60
+ exports.READ_EXPIRY_WARNING_BLOCKS = 30n;
57
61
  /** How long `trackRead` keeps looking for a record the node has not ingested yet. */
58
62
  exports.READ_TRACK_LOOKUP_TIMEOUT_MS = 30_000;
59
63
  //# sourceMappingURL=read-state.js.map
@@ -14,7 +14,7 @@ export { getCEAAddress, getPushAccountForCEA, isCEA, chainSupportsCEA, chainSupp
14
14
  export { encodeSvmExecutePayload, isSvmChain, isValidSolanaHexAddress, buildMigrationPayload, buildErc20WithdrawalMulticall, } from './orchestrator/payload-builders';
15
15
  export type { ReadChain, ReadDestination, ResolvedDestination, ReadQuery, EvmReadQuery, SvmReadQuery, Web2ReadQuery, Web2Extract, Web2ValueType, EncodedReadQuery, ReadResultShape, DecodedReadResult, ReadPreflight, ReadSpec, ReadSpecTuple, BuildReadSpecParams, PreparedRead, ReadCallback, SimulateReadResult, ParsedReadRequest, FulfilOutcome, ReceiptLike, ReadRef, ReadLifecycleOptions, ReadFees, UniversalReadResponse, ReadResponseTuple, BatchReadResponse, } from './read-state/read-state.types';
16
16
  export type { ReadOptions, ReadPrepareOptions, ReadQueryOptions, ReadCallbackOptions, ReadValue, ValidateReadCall, ReadWeb2Options, ReadTrackOptions, ReadExecuteOptions } from './read-state/read-params';
17
- export { UNIVERSAL_READ_STATUS, READ_STATUS, READ_ERROR_CODE, CONTRACT_REQUEST_STATUS, TERMINAL_READ_STATUSES, } from './read-state/read-state.types';
17
+ export { UNIVERSAL_READ_STATUS, READ_STATUS, READ_ERROR_CODE, READ_OUTCOME, CONTRACT_REQUEST_STATUS, TERMINAL_READ_STATUSES, } from './read-state/read-state.types';
18
18
  export { ReadStateError, InvalidReadQueryError, InvalidReadSpecError, ReadHeightUnavailableError, UnsupportedReadDestinationError, ReadDecodeError, ReadTimeoutError, ReadNotFoundError, ReadRegistryUnavailableError, } from './read-state/errors';
19
19
  export type { ReadSpecViolation } from './read-state/errors';
20
20
  export { resolveDestination, encodeReadQuery, decodeReadResult, parseReadRequestsFromReceipt, parseFulfilOutcome, buildReadSpecFromPreflight, validateReadSpec, toCallData, sizeCallbackBudget, inferResultShape, toRequestIdHex, toReadQuery, } from './read-state';
package/src/lib/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ReadNotFoundError = exports.ReadTimeoutError = exports.ReadDecodeError = exports.UnsupportedReadDestinationError = exports.ReadHeightUnavailableError = exports.InvalidReadSpecError = exports.InvalidReadQueryError = exports.ReadStateError = exports.TERMINAL_READ_STATUSES = exports.CONTRACT_REQUEST_STATUS = exports.READ_ERROR_CODE = exports.READ_STATUS = exports.UNIVERSAL_READ_STATUS = exports.buildErc20WithdrawalMulticall = exports.buildMigrationPayload = exports.isValidSolanaHexAddress = exports.isSvmChain = exports.encodeSvmExecutePayload = exports.getAllCEAAddresses = exports.getCEAFactoryAddress = exports.chainSupportsOutbound = exports.chainSupportsCEA = exports.isCEA = exports.getPushAccountForCEA = exports.getCEAAddress = exports.quoteMaxPCForGasCapFromNativeValue = exports.quoteMaxPCForGasCap = exports.MAX_PC_FOR_GAS_BUFFER_BPS_LIMIT = exports.DEFAULT_MAX_PC_FOR_GAS_BUFFER_BPS = exports.isChainTarget = exports.detectRoute = exports.TransactionRoute = exports.parseUEAVersion = exports.PC20UnsafeEmptyPayloadError = exports.PC20ExportRevertedError = exports.PC20WrapperPredictionUnavailableError = exports.PC20UnknownChainNamespaceError = exports.InsufficientPC20BalanceError = exports.UnsupportedPC20DestinationError = exports.PC20AmbiguousAddressError = exports.PC20ExpectedButPRC20Error = exports.InvalidPC20MetadataError = exports.PC20FactoryMismatchError = exports.PC20RegistryMismatchError = exports.PC20WrapperNotRegisteredError = exports.PC20TokenChainMismatchError = exports.InvalidPC20AddressError = exports.PC20Error = exports.isPC20Reference = exports.CHAIN = void 0;
4
- exports.PushChain = exports.UNIVERSAL_READ_REGISTRY_EVM = exports.UNIVERSAL_CALLBACK_EVM = exports.toReadQuery = exports.toRequestIdHex = exports.inferResultShape = exports.sizeCallbackBudget = exports.toCallData = exports.validateReadSpec = exports.buildReadSpecFromPreflight = exports.parseFulfilOutcome = exports.parseReadRequestsFromReceipt = exports.decodeReadResult = exports.encodeReadQuery = exports.resolveDestination = exports.ReadRegistryUnavailableError = void 0;
3
+ exports.ReadTimeoutError = exports.ReadDecodeError = exports.UnsupportedReadDestinationError = exports.ReadHeightUnavailableError = exports.InvalidReadSpecError = exports.InvalidReadQueryError = exports.ReadStateError = exports.TERMINAL_READ_STATUSES = exports.CONTRACT_REQUEST_STATUS = exports.READ_OUTCOME = exports.READ_ERROR_CODE = exports.READ_STATUS = exports.UNIVERSAL_READ_STATUS = exports.buildErc20WithdrawalMulticall = exports.buildMigrationPayload = exports.isValidSolanaHexAddress = exports.isSvmChain = exports.encodeSvmExecutePayload = exports.getAllCEAAddresses = exports.getCEAFactoryAddress = exports.chainSupportsOutbound = exports.chainSupportsCEA = exports.isCEA = exports.getPushAccountForCEA = exports.getCEAAddress = exports.quoteMaxPCForGasCapFromNativeValue = exports.quoteMaxPCForGasCap = exports.MAX_PC_FOR_GAS_BUFFER_BPS_LIMIT = exports.DEFAULT_MAX_PC_FOR_GAS_BUFFER_BPS = exports.isChainTarget = exports.detectRoute = exports.TransactionRoute = exports.parseUEAVersion = exports.PC20UnsafeEmptyPayloadError = exports.PC20ExportRevertedError = exports.PC20WrapperPredictionUnavailableError = exports.PC20UnknownChainNamespaceError = exports.InsufficientPC20BalanceError = exports.UnsupportedPC20DestinationError = exports.PC20AmbiguousAddressError = exports.PC20ExpectedButPRC20Error = exports.InvalidPC20MetadataError = exports.PC20FactoryMismatchError = exports.PC20RegistryMismatchError = exports.PC20WrapperNotRegisteredError = exports.PC20TokenChainMismatchError = exports.InvalidPC20AddressError = exports.PC20Error = exports.isPC20Reference = exports.CHAIN = void 0;
4
+ exports.PushChain = exports.UNIVERSAL_READ_REGISTRY_EVM = exports.UNIVERSAL_CALLBACK_EVM = exports.toReadQuery = exports.toRequestIdHex = exports.inferResultShape = exports.sizeCallbackBudget = exports.toCallData = exports.validateReadSpec = exports.buildReadSpecFromPreflight = exports.parseFulfilOutcome = exports.parseReadRequestsFromReceipt = exports.decodeReadResult = exports.encodeReadQuery = exports.resolveDestination = exports.ReadRegistryUnavailableError = exports.ReadNotFoundError = void 0;
5
5
  const push_chain_1 = require("./push-chain/push-chain");
6
6
  Object.defineProperty(exports, "PushChain", { enumerable: true, get: function () { return push_chain_1.PushChain; } });
7
7
  var enums_1 = require("./constants/enums");
@@ -58,6 +58,7 @@ var read_state_types_1 = require("./read-state/read-state.types");
58
58
  Object.defineProperty(exports, "UNIVERSAL_READ_STATUS", { enumerable: true, get: function () { return read_state_types_1.UNIVERSAL_READ_STATUS; } });
59
59
  Object.defineProperty(exports, "READ_STATUS", { enumerable: true, get: function () { return read_state_types_1.READ_STATUS; } });
60
60
  Object.defineProperty(exports, "READ_ERROR_CODE", { enumerable: true, get: function () { return read_state_types_1.READ_ERROR_CODE; } });
61
+ Object.defineProperty(exports, "READ_OUTCOME", { enumerable: true, get: function () { return read_state_types_1.READ_OUTCOME; } });
61
62
  Object.defineProperty(exports, "CONTRACT_REQUEST_STATUS", { enumerable: true, get: function () { return read_state_types_1.CONTRACT_REQUEST_STATUS; } });
62
63
  Object.defineProperty(exports, "TERMINAL_READ_STATUSES", { enumerable: true, get: function () { return read_state_types_1.TERMINAL_READ_STATUSES; } });
63
64
  var errors_2 = require("./read-state/errors");
@@ -1058,6 +1058,27 @@ const RAW_HOOKS_READ = {
1058
1058
  response: { txHash, requestId, logIndex },
1059
1059
  level: 'SUCCESS',
1060
1060
  }),
1061
+ [progress_hook_types_1.PROGRESS_HOOK.READ_TX_104_03]: (ref) => ({
1062
+ id: progress_hook_types_1.PROGRESS_HOOK.READ_TX_104_03,
1063
+ title: 'Looking Up Request',
1064
+ message: `Looking up ${'requestId' in ref ? `read ${ref.requestId}` : `reads in ${ref.txHash}`} on Push Chain`,
1065
+ response: { ...ref },
1066
+ level: 'INFO',
1067
+ }),
1068
+ [progress_hook_types_1.PROGRESS_HOOK.READ_TX_104_04]: (requestId, status) => ({
1069
+ id: progress_hook_types_1.PROGRESS_HOOK.READ_TX_104_04,
1070
+ title: 'Request Found',
1071
+ message: `Read ${requestId} found (status ${status})`,
1072
+ response: { requestId, status },
1073
+ level: 'SUCCESS',
1074
+ }),
1075
+ [progress_hook_types_1.PROGRESS_HOOK.READ_TX_104_05]: (ref, elapsedMs) => ({
1076
+ id: progress_hook_types_1.PROGRESS_HOOK.READ_TX_104_05,
1077
+ title: 'Request Not Found',
1078
+ message: `No read found for ${'requestId' in ref ? ref.requestId : ref.txHash} after ${Math.round(elapsedMs / 1000)}s`,
1079
+ response: { ...ref, elapsedMs },
1080
+ level: 'ERROR',
1081
+ }),
1061
1082
  [progress_hook_types_1.PROGRESS_HOOK.READ_TX_105_01]: (requestId) => ({
1062
1083
  id: progress_hook_types_1.PROGRESS_HOOK.READ_TX_105_01,
1063
1084
  title: 'Awaiting Quorum',
@@ -106,6 +106,9 @@ export declare enum PROGRESS_HOOK {
106
106
  READ_TX_103_03 = "READ-TX-103-03",
107
107
  READ_TX_104_01 = "READ-TX-104-01",
108
108
  READ_TX_104_02 = "READ-TX-104-02",
109
+ READ_TX_104_03 = "READ-TX-104-03",
110
+ READ_TX_104_04 = "READ-TX-104-04",
111
+ READ_TX_104_05 = "READ-TX-104-05",
109
112
  READ_TX_105_01 = "READ-TX-105-01",
110
113
  READ_TX_105_02 = "READ-TX-105-02",
111
114
  READ_TX_105_03 = "READ-TX-105-03",
@@ -138,5 +141,5 @@ export type PROGRESS_HOOK_R2 = PROGRESS_HOOK.SEND_TX_201 | PROGRESS_HOOK.SEND_TX
138
141
  export type PROGRESS_HOOK_R3 = PROGRESS_HOOK.SEND_TX_301 | PROGRESS_HOOK.SEND_TX_302_01 | PROGRESS_HOOK.SEND_TX_302_02 | PROGRESS_HOOK.SEND_TX_303_01 | PROGRESS_HOOK.SEND_TX_303_02 | PROGRESS_HOOK.SEND_TX_303_03_01 | PROGRESS_HOOK.SEND_TX_303_03_02 | PROGRESS_HOOK.SEND_TX_303_03_03 | PROGRESS_HOOK.SEND_TX_303_04 | PROGRESS_HOOK.SEND_TX_303_05 | PROGRESS_HOOK.SEND_TX_303_06 | PROGRESS_HOOK.SEND_TX_304_01 | PROGRESS_HOOK.SEND_TX_304_02 | PROGRESS_HOOK.SEND_TX_304_03 | PROGRESS_HOOK.SEND_TX_304_04 | PROGRESS_HOOK.SEND_TX_307 | PROGRESS_HOOK.SEND_TX_309_01 | PROGRESS_HOOK.SEND_TX_309_02 | PROGRESS_HOOK.SEND_TX_309_03 | PROGRESS_HOOK.SEND_TX_310_01 | PROGRESS_HOOK.SEND_TX_310_02 | PROGRESS_HOOK.SEND_TX_399_01 | PROGRESS_HOOK.SEND_TX_399_02 | PROGRESS_HOOK.SEND_TX_399_03 | PROGRESS_HOOK.SEND_TX_399_99;
139
142
  export type PROGRESS_HOOK_MULTICHAIN = PROGRESS_HOOK.SEND_TX_001 | PROGRESS_HOOK.SEND_TX_002_01 | PROGRESS_HOOK.SEND_TX_002_99_99 | PROGRESS_HOOK.SEND_TX_003_03 | PROGRESS_HOOK.SEND_TX_003_04 | PROGRESS_HOOK.SEND_TX_003_05 | PROGRESS_HOOK.SEND_TX_999_01 | PROGRESS_HOOK.SEND_TX_999_02 | PROGRESS_HOOK.SEND_TX_999_03;
140
143
  export type PROGRESS_HOOK_MIG = PROGRESS_HOOK.UEA_MIG_01 | PROGRESS_HOOK.UEA_MIG_02 | PROGRESS_HOOK.UEA_MIG_03 | PROGRESS_HOOK.UEA_MIG_9901 | PROGRESS_HOOK.UEA_MIG_9902 | PROGRESS_HOOK.UEA_MIG_9903;
141
- export type PROGRESS_HOOK_READ = PROGRESS_HOOK.READ_TX_101 | PROGRESS_HOOK.READ_TX_102_01 | PROGRESS_HOOK.READ_TX_102_02 | PROGRESS_HOOK.READ_TX_102_03 | PROGRESS_HOOK.READ_TX_102_04 | PROGRESS_HOOK.READ_TX_102_05 | PROGRESS_HOOK.READ_TX_103_01 | PROGRESS_HOOK.READ_TX_103_02 | PROGRESS_HOOK.READ_TX_103_03 | PROGRESS_HOOK.READ_TX_104_01 | PROGRESS_HOOK.READ_TX_104_02 | PROGRESS_HOOK.READ_TX_105_01 | PROGRESS_HOOK.READ_TX_105_02 | PROGRESS_HOOK.READ_TX_105_03 | PROGRESS_HOOK.READ_TX_105_04 | PROGRESS_HOOK.READ_TX_106_01 | PROGRESS_HOOK.READ_TX_106_02 | PROGRESS_HOOK.READ_TX_106_03 | PROGRESS_HOOK.READ_TX_106_04 | PROGRESS_HOOK.READ_TX_106_05 | PROGRESS_HOOK.READ_TX_106_06 | PROGRESS_HOOK.READ_TX_199_01 | PROGRESS_HOOK.READ_TX_199_02 | PROGRESS_HOOK.READ_TX_199_03 | PROGRESS_HOOK.READ_TX_199_99 | PROGRESS_HOOK.READ_TX_001 | PROGRESS_HOOK.READ_TX_002_01 | PROGRESS_HOOK.READ_TX_002_99_99 | PROGRESS_HOOK.READ_TX_999_01 | PROGRESS_HOOK.READ_TX_999_02 | PROGRESS_HOOK.READ_TX_999_03;
144
+ export type PROGRESS_HOOK_READ = PROGRESS_HOOK.READ_TX_101 | PROGRESS_HOOK.READ_TX_102_01 | PROGRESS_HOOK.READ_TX_102_02 | PROGRESS_HOOK.READ_TX_102_03 | PROGRESS_HOOK.READ_TX_102_04 | PROGRESS_HOOK.READ_TX_102_05 | PROGRESS_HOOK.READ_TX_103_01 | PROGRESS_HOOK.READ_TX_103_02 | PROGRESS_HOOK.READ_TX_103_03 | PROGRESS_HOOK.READ_TX_104_01 | PROGRESS_HOOK.READ_TX_104_02 | PROGRESS_HOOK.READ_TX_104_03 | PROGRESS_HOOK.READ_TX_104_04 | PROGRESS_HOOK.READ_TX_104_05 | PROGRESS_HOOK.READ_TX_105_01 | PROGRESS_HOOK.READ_TX_105_02 | PROGRESS_HOOK.READ_TX_105_03 | PROGRESS_HOOK.READ_TX_105_04 | PROGRESS_HOOK.READ_TX_106_01 | PROGRESS_HOOK.READ_TX_106_02 | PROGRESS_HOOK.READ_TX_106_03 | PROGRESS_HOOK.READ_TX_106_04 | PROGRESS_HOOK.READ_TX_106_05 | PROGRESS_HOOK.READ_TX_106_06 | PROGRESS_HOOK.READ_TX_199_01 | PROGRESS_HOOK.READ_TX_199_02 | PROGRESS_HOOK.READ_TX_199_03 | PROGRESS_HOOK.READ_TX_199_99 | PROGRESS_HOOK.READ_TX_001 | PROGRESS_HOOK.READ_TX_002_01 | PROGRESS_HOOK.READ_TX_002_99_99 | PROGRESS_HOOK.READ_TX_999_01 | PROGRESS_HOOK.READ_TX_999_02 | PROGRESS_HOOK.READ_TX_999_03;
142
145
  export {};
@@ -117,6 +117,9 @@ var PROGRESS_HOOK;
117
117
  PROGRESS_HOOK["READ_TX_103_03"] = "READ-TX-103-03";
118
118
  PROGRESS_HOOK["READ_TX_104_01"] = "READ-TX-104-01";
119
119
  PROGRESS_HOOK["READ_TX_104_02"] = "READ-TX-104-02";
120
+ PROGRESS_HOOK["READ_TX_104_03"] = "READ-TX-104-03";
121
+ PROGRESS_HOOK["READ_TX_104_04"] = "READ-TX-104-04";
122
+ PROGRESS_HOOK["READ_TX_104_05"] = "READ-TX-104-05";
120
123
  PROGRESS_HOOK["READ_TX_105_01"] = "READ-TX-105-01";
121
124
  PROGRESS_HOOK["READ_TX_105_02"] = "READ-TX-105-02";
122
125
  PROGRESS_HOOK["READ_TX_105_03"] = "READ-TX-105-03";
@@ -48,7 +48,7 @@ export declare class PushChain {
48
48
  readonly CALLBACK_BUDGET_BUFFER: 3;
49
49
  readonly REGISTRY_CALLBACK_GAS: 500000n;
50
50
  readonly UNIVERSAL_READ_REGISTRY_ADDRESS: {
51
- readonly TESTNET_DONUT: "0x91b09DAd1774bAfDE679F9ebB5F9046AE2b928C8";
51
+ readonly TESTNET_DONUT: "0x00000000000000000000000000000000000000b2";
52
52
  };
53
53
  readonly WEB2_MAX_EXTRACT_ENTRIES: 16;
54
54
  readonly WEB2_DEFAULT_TIMEOUT_MS: 5000;
@@ -57,6 +57,7 @@ export declare class PushChain {
57
57
  readonly STATUS: typeof import("../read-state/read-state.types").UNIVERSAL_READ_STATUS;
58
58
  readonly RESULT_STATUS: typeof import("../read-state/read-state.types").READ_STATUS;
59
59
  readonly ERROR_CODE: typeof import("../read-state/read-state.types").READ_ERROR_CODE;
60
+ readonly OUTCOME: typeof import("../read-state/read-state.types").READ_OUTCOME;
60
61
  };
61
62
  };
62
63
  /**
@@ -120,7 +120,7 @@ class PushChain {
120
120
  },
121
121
  // Only read()/executeReads() send transactions; prepare/simulate/track remain read-only.
122
122
  read: async (subject, options) => {
123
- const params = (0, read_params_1.toBuildReadSpecParams)(subject, options, orchestrator.getNetwork());
123
+ const params = await (0, read_params_1.resolveReadSpecParams)(subject, options, orchestrator.getNetwork(), orchestrator.getRpcUrls());
124
124
  (0, read_executor_1.assertRequestEntrypoint)(params.callback, 'read');
125
125
  if (this.isReadMode)
126
126
  throw new Error('Read only mode cannot call read function');
@@ -128,8 +128,9 @@ class PushChain {
128
128
  const { reads: [response] } = await (0, read_executor_1.executeReads)(orchestrator, [prepared], options);
129
129
  return response;
130
130
  },
131
- prepareRead: (subject, options) => {
132
- return orchestrator.prepareRead.bind(orchestrator)((0, read_params_1.toBuildReadSpecParams)(subject, options, orchestrator.getNetwork()));
131
+ prepareRead: async (subject, options) => {
132
+ const params = await (0, read_params_1.resolveReadSpecParams)(subject, options, orchestrator.getNetwork(), orchestrator.getRpcUrls());
133
+ return orchestrator.prepareRead(params);
133
134
  },
134
135
  executeReads: (async (reads, options) => {
135
136
  reads.forEach((r) => (0, read_executor_1.assertRequestEntrypoint)(r.callback));
@@ -54,6 +54,13 @@ export declare class PushClient extends EvmClient {
54
54
  */
55
55
  private readonly archiveTendermintRpc;
56
56
  private readonly archivePublicClient?;
57
+ /**
58
+ * Prune endpoints with transport retries off, raced against the archive. A
59
+ * receipt miss on the prune node answers -32002 "Requested resource not
60
+ * available" after ~8 s (measured on Donut 2026-09-23), and the shared
61
+ * client's `http({ retryCount: 5 })` would retry that on top.
62
+ */
63
+ private readonly pruneProbeClient?;
57
64
  constructor(clientOptions: PushClientOptions);
58
65
  /**
59
66
  * Executes an operation with automatic fallback to next RPC endpoint on failure.
@@ -48,6 +48,13 @@ class PushClient extends evm_client_1.EvmClient {
48
48
  */
49
49
  archiveTendermintRpc;
50
50
  archivePublicClient;
51
+ /**
52
+ * Prune endpoints with transport retries off, raced against the archive. A
53
+ * receipt miss on the prune node answers -32002 "Requested resource not
54
+ * available" after ~8 s (measured on Donut 2026-09-23), and the shared
55
+ * client's `http({ retryCount: 5 })` would retry that on top.
56
+ */
57
+ pruneProbeClient;
51
58
  constructor(clientOptions) {
52
59
  const pushChainKey = pushNetworkToChain(clientOptions.network);
53
60
  const chain = clientOptions.chain ?? (0, chain_1.getPushViemChain)(pushChainKey);
@@ -66,6 +73,10 @@ class PushClient extends evm_client_1.EvmClient {
66
73
  chain,
67
74
  transport: (0, viem_1.fallback)(archiveEvmUrls.map((url) => (0, viem_1.http)(url, { retryCount: 5, retryDelay: 500 }))),
68
75
  });
76
+ this.pruneProbeClient = (0, viem_1.createPublicClient)({
77
+ chain,
78
+ transport: (0, viem_1.fallback)(clientOptions.rpcUrls.map((url) => (0, viem_1.http)(url, { retryCount: 0 }))),
79
+ });
69
80
  }
70
81
  this.ephemeralKey = (0, accounts_1.generatePrivateKey)();
71
82
  this.ephemeralAccount = (0, accounts_1.privateKeyToAccount)(this.ephemeralKey);
@@ -357,17 +368,20 @@ class PushClient extends evm_client_1.EvmClient {
357
368
  * no EVM-indexed tx or receipt. Attribute values are plain strings.
358
369
  */
359
370
  async getBlockResultEvents(height) {
360
- return this.executeWithRpcFallback(async (rpcUrl) => {
371
+ // Prune nodes drop old heights ("height N is not available"); the archive keeps them.
372
+ return this.executeWithArchiveFallback(async (rpcUrl) => {
361
373
  const url = `${rpcUrl.replace(/\/+$/, '')}/block_results?height=${height}`;
362
374
  const res = await fetch(url);
363
- if (!res.ok)
364
- throw new Error(`HTTP request failed: ${res.status} ${url}`);
365
- const body = (await res.json());
366
- if (body.error)
375
+ // CometBFT answers a pruned height with HTTP 500 plus a JSON-RPC error. Surface that
376
+ // error so it reads as a definite miss (→ archive), not a transient HTTP failure to retry.
377
+ const body = (await res.json().catch(() => undefined));
378
+ if (body?.error)
367
379
  throw new Error(`block_results ${height}: ${body.error.data ?? body.error.message ?? 'error'}`);
380
+ if (!res.ok || !body)
381
+ throw new Error(`HTTP request failed: ${res.status} ${url}`);
368
382
  const events = body.result?.finalize_block_events ?? body.result?.end_block_events ?? [];
369
383
  return events;
370
- }, 'getBlockResultEvents');
384
+ }, 'getBlockResultEvents', () => false);
371
385
  }
372
386
  /**
373
387
  * Queries x/ucallback for every read a Push transaction requested. One tx can emit
@@ -479,17 +493,29 @@ class PushClient extends evm_client_1.EvmClient {
479
493
  * Prune first; on not-found, retry the archive EVM client if configured.
480
494
  */
481
495
  async getTransactionReceiptWithArchiveFallback(txHash) {
482
- try {
483
- return await this.publicClient.getTransactionReceipt({ hash: txHash });
484
- }
485
- catch (error) {
486
- if (!this.hasArchiveEvm)
487
- throw error;
488
- return this.archivePublicClient.getTransactionReceipt({
489
- hash: txHash,
490
- });
496
+ if (!this.hasArchiveEvm || !this.pruneProbeClient) {
497
+ return this.publicClient.getTransactionReceipt({ hash: txHash });
491
498
  }
499
+ // Race prune and archive; the first receipt wins. A pruned receipt costs one
500
+ // archive round trip, a fresh one the prune round trip (if the archive lags).
501
+ const prune = this.pruneProbeClient.getTransactionReceipt({ hash: txHash });
502
+ const archive = this.archivePublicClient.getTransactionReceipt({
503
+ hash: txHash,
504
+ });
505
+ return firstFulfilled([archive, prune]);
492
506
  }
493
507
  }
494
508
  exports.PushClient = PushClient;
509
+ /** First promise to resolve; if all reject, the last rejection. */
510
+ function firstFulfilled(promises) {
511
+ return new Promise((resolve, reject) => {
512
+ let pending = promises.length;
513
+ for (const p of promises) {
514
+ p.then(resolve, (error) => {
515
+ if (--pending === 0)
516
+ reject(error);
517
+ });
518
+ }
519
+ });
520
+ }
495
521
  //# sourceMappingURL=push-client.js.map
@@ -104,9 +104,8 @@ function encodeEvmQueryEnvelope(query, options) {
104
104
  if (!item || item.type !== 'function') {
105
105
  throw new errors_1.InvalidReadQueryError(`function not found in abi: ${query.functionName}`);
106
106
  }
107
- if (item.stateMutability !== 'view' && item.stateMutability !== 'pure') {
108
- throw new errors_1.InvalidReadQueryError(`${query.functionName} is ${item.stateMutability}; reads must target view/pure functions`);
109
- }
107
+ // Any mutability: validators run the call as an eth_call simulation at the
108
+ // pinned block, so nonpayable/payable functions return data and never execute.
110
109
  callData = (0, viem_1.encodeFunctionData)({
111
110
  abi: query.abi,
112
111
  functionName: query.functionName,
@@ -11,6 +11,7 @@ const bs58_1 = tslib_1.__importDefault(require("bs58"));
11
11
  const viem_1 = require("viem");
12
12
  const read_state_1 = require("../../constants/read-state");
13
13
  const errors_1 = require("../errors");
14
+ const svm_account_1 = require("../svm-account");
14
15
  /** `universalClient/externalchains/svm/read_envelope.go` — solanaQueryType. */
15
16
  exports.SVM_QUERY_TYPE = {
16
17
  LAMPORT_BALANCE: 0,
@@ -83,7 +84,16 @@ function encodeSvmQueryEnvelope(query, options = {}) {
83
84
  break;
84
85
  case 'rawAccountData':
85
86
  queryType = exports.SVM_QUERY_TYPE.RAW_ACCOUNT_DATA;
86
- resultShape = { kind: 'raw' };
87
+ if (query.idl !== undefined) {
88
+ (0, svm_account_1.validateIdl)(query.idl);
89
+ const accountName = query.accountName === undefined ? undefined : (0, svm_account_1.resolveAccountName)(query.idl, query.accountName);
90
+ resultShape = accountName === undefined ? { kind: 'svmAccount', idl: query.idl } : { kind: 'svmAccount', idl: query.idl, accountName };
91
+ }
92
+ else if (query.accountName !== undefined) {
93
+ throw new errors_1.InvalidReadQueryError('accountName needs idl');
94
+ }
95
+ else
96
+ resultShape = { kind: 'raw' };
87
97
  break;
88
98
  default:
89
99
  throw new errors_1.InvalidReadQueryError(`unknown SVM query type: ${query.type}`);
@@ -11,6 +11,7 @@ const spec_builder_1 = require("./spec-builder");
11
11
  const progress_hook_1 = tslib_1.__importDefault(require("../progress-hook/progress-hook"));
12
12
  const progress_hook_types_1 = require("../progress-hook/progress-hook.types");
13
13
  const read_state_types_1 = require("./read-state.types");
14
+ const read_state_1 = require("../constants/read-state");
14
15
  /**
15
16
  * The custom-receiver contract of `read()` / `executeReads()`: a non-zero target and the
16
17
  * app's request entrypoint. Pure — call it before any preflight so a malformed request
@@ -58,6 +59,9 @@ async function executeReads(deps, reads, options = {}) {
58
59
  failedAt = i + 1;
59
60
  if (batch)
60
61
  emit(progress_hook_types_1.PROGRESS_HOOK.READ_TX_002_01, i + 1, reads.length, prepared.preflight.destination.caip2);
62
+ const ageMs = Date.now() - prepared.preflight.fetchedAt;
63
+ if (ageMs > read_state_1.READ_PREFLIGHT_STALE_MS)
64
+ emit(progress_hook_types_1.PROGRESS_HOOK.READ_TX_102_04, prepared.preflight.fetchedAt, ageMs);
61
65
  await deps.revalidateRead(prepared);
62
66
  }
63
67
  failedAt = 0;