@ar.io/sdk 3.24.0 → 4.0.0-alpha.2

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 (169) hide show
  1. package/README.md +757 -589
  2. package/lib/esm/cli/cli.js +188 -152
  3. package/lib/esm/cli/commands/antCommands.js +23 -58
  4. package/lib/esm/cli/commands/arnsPurchaseCommands.js +48 -30
  5. package/lib/esm/cli/commands/escrowCommands.js +227 -0
  6. package/lib/esm/cli/commands/gatewayWriteCommands.js +140 -23
  7. package/lib/esm/cli/commands/pruneCommands.js +154 -0
  8. package/lib/esm/cli/commands/readCommands.js +22 -3
  9. package/lib/esm/cli/commands/transfer.js +6 -6
  10. package/lib/esm/cli/options.js +124 -58
  11. package/lib/esm/cli/utils.js +303 -175
  12. package/lib/esm/common/ant-registry.js +17 -143
  13. package/lib/esm/common/ant.js +44 -1167
  14. package/lib/esm/common/faucet.js +17 -6
  15. package/lib/esm/common/index.js +0 -4
  16. package/lib/esm/common/io.js +25 -1412
  17. package/lib/esm/constants.js +13 -19
  18. package/lib/esm/solana/ant-readable.js +724 -0
  19. package/lib/esm/solana/ant-registry-readable.js +133 -0
  20. package/lib/esm/solana/ant-registry-writeable.js +472 -0
  21. package/lib/esm/solana/ant-writeable.js +384 -0
  22. package/lib/esm/solana/ata.js +70 -0
  23. package/lib/esm/solana/canonical-message.js +128 -0
  24. package/lib/esm/solana/clusters.js +111 -0
  25. package/lib/esm/solana/constants.js +146 -0
  26. package/lib/esm/solana/delegation-math.js +112 -0
  27. package/lib/esm/solana/deserialize.js +711 -0
  28. package/lib/esm/solana/escrow.js +839 -0
  29. package/lib/{cjs/utils/json.js → esm/solana/events.js} +15 -10
  30. package/lib/esm/solana/funding-plan.js +699 -0
  31. package/lib/esm/solana/index.js +126 -0
  32. package/lib/esm/solana/instruction.js +39 -0
  33. package/lib/esm/solana/io-readable.js +2182 -0
  34. package/lib/esm/solana/io-writeable.js +3196 -0
  35. package/lib/esm/solana/json-rpc.js +90 -0
  36. package/lib/esm/solana/metadata.js +81 -0
  37. package/lib/esm/solana/mpl-core.js +192 -0
  38. package/lib/esm/solana/pda.js +332 -0
  39. package/lib/esm/solana/predict-prescribed-observers.js +110 -0
  40. package/lib/esm/solana/retry.js +117 -0
  41. package/lib/esm/solana/rpc-circuit-breaker.js +258 -0
  42. package/lib/esm/solana/send.js +372 -0
  43. package/lib/esm/solana/spawn-ant.js +224 -0
  44. package/lib/esm/solana/types.js +1 -0
  45. package/lib/esm/types/ant.js +27 -15
  46. package/lib/esm/types/io.js +8 -11
  47. package/lib/esm/utils/ant.js +0 -63
  48. package/lib/esm/utils/index.js +0 -3
  49. package/lib/esm/version.js +1 -1
  50. package/lib/types/cli/commands/antCommands.d.ts +5 -13
  51. package/lib/types/cli/commands/arnsPurchaseCommands.d.ts +33 -7
  52. package/lib/types/cli/commands/escrowCommands.d.ts +68 -0
  53. package/lib/types/cli/commands/gatewayWriteCommands.d.ts +12 -11
  54. package/lib/types/cli/commands/pruneCommands.d.ts +31 -0
  55. package/lib/types/cli/commands/readCommands.d.ts +27 -22
  56. package/lib/types/cli/commands/transfer.d.ts +9 -9
  57. package/lib/types/cli/options.d.ts +76 -21
  58. package/lib/types/cli/types.d.ts +11 -13
  59. package/lib/types/cli/utils.d.ts +71 -31
  60. package/lib/types/common/ant-registry.d.ts +49 -47
  61. package/lib/types/common/ant.d.ts +54 -539
  62. package/lib/types/common/faucet.d.ts +20 -8
  63. package/lib/types/common/index.d.ts +0 -3
  64. package/lib/types/common/io.d.ts +66 -258
  65. package/lib/types/constants.d.ts +11 -18
  66. package/lib/types/solana/ant-readable.d.ts +180 -0
  67. package/lib/types/solana/ant-registry-readable.d.ts +105 -0
  68. package/lib/types/solana/ant-registry-writeable.d.ts +249 -0
  69. package/lib/types/solana/ant-writeable.d.ts +177 -0
  70. package/lib/types/solana/ata.d.ts +44 -0
  71. package/lib/types/solana/canonical-message.d.ts +121 -0
  72. package/lib/types/solana/clusters.d.ts +109 -0
  73. package/lib/types/solana/constants.d.ts +119 -0
  74. package/lib/types/solana/delegation-math.d.ts +45 -0
  75. package/lib/types/solana/deserialize.d.ts +262 -0
  76. package/lib/types/solana/escrow.d.ts +480 -0
  77. package/lib/types/solana/events.d.ts +38 -0
  78. package/lib/types/solana/funding-plan.d.ts +225 -0
  79. package/lib/types/solana/index.d.ts +87 -0
  80. package/lib/types/solana/instruction.d.ts +39 -0
  81. package/lib/types/solana/io-readable.d.ts +499 -0
  82. package/lib/types/solana/io-writeable.d.ts +893 -0
  83. package/lib/types/solana/json-rpc.d.ts +47 -0
  84. package/lib/types/solana/metadata.d.ts +84 -0
  85. package/lib/types/solana/mpl-core.d.ts +120 -0
  86. package/lib/types/solana/pda.d.ts +95 -0
  87. package/lib/types/solana/predict-prescribed-observers.d.ts +28 -0
  88. package/lib/types/solana/retry.d.ts +62 -0
  89. package/lib/types/solana/rpc-circuit-breaker.d.ts +78 -0
  90. package/lib/types/solana/send.d.ts +94 -0
  91. package/lib/types/solana/spawn-ant.d.ts +145 -0
  92. package/lib/types/solana/types.d.ts +82 -0
  93. package/lib/types/types/ant-registry.d.ts +43 -4
  94. package/lib/types/types/ant.d.ts +114 -96
  95. package/lib/types/types/common.d.ts +18 -74
  96. package/lib/types/types/faucet.d.ts +2 -2
  97. package/lib/types/types/io.d.ts +244 -158
  98. package/lib/types/types/token.d.ts +0 -12
  99. package/lib/types/utils/ant.d.ts +1 -12
  100. package/lib/types/utils/index.d.ts +0 -3
  101. package/lib/types/version.d.ts +1 -1
  102. package/package.json +36 -33
  103. package/lib/cjs/cli/cli.js +0 -822
  104. package/lib/cjs/cli/commands/antCommands.js +0 -113
  105. package/lib/cjs/cli/commands/arnsPurchaseCommands.js +0 -212
  106. package/lib/cjs/cli/commands/gatewayWriteCommands.js +0 -210
  107. package/lib/cjs/cli/commands/readCommands.js +0 -215
  108. package/lib/cjs/cli/commands/transfer.js +0 -159
  109. package/lib/cjs/cli/options.js +0 -470
  110. package/lib/cjs/cli/types.js +0 -2
  111. package/lib/cjs/cli/utils.js +0 -639
  112. package/lib/cjs/common/ant-registry.js +0 -155
  113. package/lib/cjs/common/ant-versions.js +0 -93
  114. package/lib/cjs/common/ant.js +0 -1182
  115. package/lib/cjs/common/arweave.js +0 -27
  116. package/lib/cjs/common/contracts/ao-process.js +0 -224
  117. package/lib/cjs/common/error.js +0 -64
  118. package/lib/cjs/common/faucet.js +0 -150
  119. package/lib/cjs/common/hyperbeam/hb.js +0 -173
  120. package/lib/cjs/common/index.js +0 -42
  121. package/lib/cjs/common/io.js +0 -1423
  122. package/lib/cjs/common/logger.js +0 -83
  123. package/lib/cjs/common/loggers/winston.js +0 -68
  124. package/lib/cjs/common/marketplace.js +0 -731
  125. package/lib/cjs/common/turbo.js +0 -223
  126. package/lib/cjs/constants.js +0 -41
  127. package/lib/cjs/node/index.js +0 -39
  128. package/lib/cjs/package.json +0 -1
  129. package/lib/cjs/types/ant-registry.js +0 -2
  130. package/lib/cjs/types/ant.js +0 -168
  131. package/lib/cjs/types/common.js +0 -2
  132. package/lib/cjs/types/faucet.js +0 -2
  133. package/lib/cjs/types/index.js +0 -37
  134. package/lib/cjs/types/io.js +0 -51
  135. package/lib/cjs/types/token.js +0 -116
  136. package/lib/cjs/utils/ant.js +0 -108
  137. package/lib/cjs/utils/ao.js +0 -432
  138. package/lib/cjs/utils/arweave.js +0 -285
  139. package/lib/cjs/utils/base64.js +0 -62
  140. package/lib/cjs/utils/hash.js +0 -56
  141. package/lib/cjs/utils/index.js +0 -38
  142. package/lib/cjs/utils/processes.js +0 -173
  143. package/lib/cjs/utils/random.js +0 -30
  144. package/lib/cjs/utils/schema.js +0 -15
  145. package/lib/cjs/utils/url.js +0 -37
  146. package/lib/cjs/version.js +0 -20
  147. package/lib/cjs/web/index.js +0 -41
  148. package/lib/esm/common/ant-versions.js +0 -87
  149. package/lib/esm/common/arweave.js +0 -21
  150. package/lib/esm/common/contracts/ao-process.js +0 -220
  151. package/lib/esm/common/hyperbeam/hb.js +0 -169
  152. package/lib/esm/common/marketplace.js +0 -724
  153. package/lib/esm/common/turbo.js +0 -215
  154. package/lib/esm/node/index.js +0 -20
  155. package/lib/esm/utils/ao.js +0 -420
  156. package/lib/esm/utils/arweave.js +0 -271
  157. package/lib/esm/utils/processes.js +0 -167
  158. package/lib/esm/web/index.js +0 -20
  159. package/lib/types/common/ant-versions.d.ts +0 -39
  160. package/lib/types/common/arweave.d.ts +0 -17
  161. package/lib/types/common/contracts/ao-process.d.ts +0 -47
  162. package/lib/types/common/hyperbeam/hb.d.ts +0 -88
  163. package/lib/types/common/marketplace.d.ts +0 -568
  164. package/lib/types/common/turbo.d.ts +0 -61
  165. package/lib/types/node/index.d.ts +0 -20
  166. package/lib/types/utils/ao.d.ts +0 -80
  167. package/lib/types/utils/arweave.d.ts +0 -79
  168. package/lib/types/utils/processes.d.ts +0 -39
  169. package/lib/types/web/index.d.ts +0 -20
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Helpers for JSON-RPC reads against {@link SolanaRpc} that return a
18
+ * web3.js-shaped `AccountInfo` (Buffer-backed `data`, plain Address strings).
19
+ * Used by the ACL/AntRegistry path so the deserializers can stay agnostic of
20
+ * the RPC client's response shape.
21
+ */
22
+ import { type Address } from '@solana/kit';
23
+ import type { SolanaRpc } from './types.js';
24
+ /** Raw account layout used by SDK readers (matches legacy web3 `AccountInfo` fields). */
25
+ export type SolanaAccountInfo = {
26
+ data: Buffer;
27
+ owner: Address;
28
+ lamports: number;
29
+ executable: boolean;
30
+ rentEpoch: number;
31
+ };
32
+ /**
33
+ * Fetch a single account and decode its data into a Buffer-backed shape that
34
+ * looks like the legacy `web3.js` `AccountInfo`. Returns `null` if the account
35
+ * doesn't exist (so callers can handle "missing PDA" without try/catch).
36
+ */
37
+ export declare function getAccountInfoLegacy(rpc: SolanaRpc, pda: Address, commitment: string | undefined): Promise<SolanaAccountInfo | null>;
38
+ /**
39
+ * Fetch multiple accounts in a single RPC round-trip and decode each into
40
+ * the legacy `AccountInfo` shape. Missing accounts come back as `null`,
41
+ * preserving 1:1 alignment with the input `pdas` array.
42
+ *
43
+ * Used by paginated readers (ACL pages, etc.) to load all sibling pages
44
+ * via `getMultipleAccountsInfo` rather than firing N parallel
45
+ * `getAccountInfo` calls.
46
+ */
47
+ export declare function getMultipleAccountsInfoLegacy(rpc: SolanaRpc, pdas: Address[], commitment: string | undefined): Promise<(SolanaAccountInfo | null)[]>;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Metaplex-standard JSON metadata builder for AR.IO ANT NFTs.
18
+ *
19
+ * The Core asset's `uri` field on chain points at a JSON file with this
20
+ * shape; marketplaces and DAS providers fetch + parse it for their
21
+ * inline name/image/description display. The 3 ArNS traits (`ArNS Name`,
22
+ * `Type`, `Undername Limit`) live in the on-chain Attributes plugin, NOT
23
+ * in this JSON — see ADR-012.
24
+ *
25
+ * This helper produces the exact same JSON shape as the migration import
26
+ * (`migration/import/src/metadata.ts::buildAntMetadata`); the two paths
27
+ * MUST stay in lock-step or migrated and freshly-spawned ANTs will
28
+ * render differently in marketplace UIs. A regression test in
29
+ * `spawn-ant.test.ts` asserts byte-equality between the two for matching
30
+ * inputs.
31
+ *
32
+ * Pure function. No network, no Turbo, no dependencies. Caller handles
33
+ * uploading the resulting JSON to Arweave (e.g. via `@ardrive/turbo-sdk`
34
+ * with a `HexSolanaSigner` — free for files under 100 KiB) and passes the
35
+ * resulting `ar://${txid}` to `spawnSolanaANT`'s `state.uri`.
36
+ */
37
+ export { ARIO_LOGO_TX_ID, AR_IO_PROTOCOL as AR_PROTOCOL, } from '../constants.js';
38
+ /** Metaplex-standard JSON metadata shape. */
39
+ export interface NftMetadataJson {
40
+ name: string;
41
+ symbol: string;
42
+ description: string;
43
+ image: string;
44
+ external_url?: string;
45
+ properties?: {
46
+ files?: Array<{
47
+ uri: string;
48
+ type: string;
49
+ }>;
50
+ /** Metaplex standard categories: image | video | audio | vr | html. */
51
+ category?: string;
52
+ };
53
+ }
54
+ /** Inputs to `buildAntMetadata`. */
55
+ export interface AntMetadataParams {
56
+ /** Display name for the NFT — usually the ArNS name when one is set. */
57
+ name: string;
58
+ /** ArNS name this ANT controls (if any). When set, becomes the JSON
59
+ * `name` and is also used in `external_url`. */
60
+ arnsName?: string;
61
+ /** Ticker / symbol. Defaults to "ANT". */
62
+ ticker?: string;
63
+ /** Description. Auto-generated from arnsName when omitted. */
64
+ description?: string;
65
+ /** Logo TX id (43-char Arweave id). Defaults to the AR.IO logo. */
66
+ logoTxId?: string;
67
+ /**
68
+ * Optional gateway hostname (e.g. `"turbo-gateway.com"` or `"arweave.net"`).
69
+ * When provided, all Arweave references in the JSON resolve to
70
+ * `https://${gateway}/raw/${txid}` instead of `ar://${txid}`. Useful when
71
+ * you need consumers (like Helius DAS or the Metaplex Core explorer) to
72
+ * fetch the JSON immediately without waiting for Wayfinder-aware
73
+ * resolution; ADR-012's canonical scheme is still `ar://`.
74
+ */
75
+ gateway?: string;
76
+ }
77
+ /**
78
+ * Build ANT NFT JSON metadata.
79
+ *
80
+ * Output is byte-identical to the migration import's `buildAntMetadata`
81
+ * for matching inputs. Defaults to `ar://` URLs (ADR-012 canonical); pass
82
+ * `gateway` to opt into https URLs.
83
+ */
84
+ export declare function buildAntMetadata(params: AntMetadataParams): NftMetadataJson;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Reader for the on-chain Metaplex Core asset (`AssetV1` + plugin chain).
18
+ *
19
+ * The codama-generated decoders in `generated/mpl-core` only cover the
20
+ * fixed-shape header section (`AssetV1`, `PluginHeaderV1`, etc.) — they
21
+ * don't know how to follow the variable-offset registry chain to a
22
+ * specific plugin payload. This module fills that gap with a small
23
+ * walker that:
24
+ *
25
+ * 1. decodes the `AssetV1` prefix (key + owner + update authority +
26
+ * name + uri + seq);
27
+ * 2. follows the `PluginHeaderV1.pluginRegistryOffset` to the
28
+ * `PluginRegistryV1`;
29
+ * 3. iterates registry records to find the requested plugin variant;
30
+ * 4. decodes the `Plugin` enum at the registry record's offset.
31
+ *
32
+ * The same walk lives on-chain in `programs/ario-arns/src/state/mod.rs`
33
+ * (`read_mpl_core_attribute`) and `programs/ario-core/src/mpl_core.rs`
34
+ * (`read_ant_program`). The three implementations are pinned against
35
+ * each other by the migration import's edge-case fixtures and unit
36
+ * tests at all three layers.
37
+ *
38
+ * Reading is best-effort: any parse failure returns `null` rather than
39
+ * throwing, so callers can fall back to canonical defaults
40
+ * (e.g. `ARIO_ANT_PROGRAM_ID`) when an asset was minted without the
41
+ * `ANT Program` attribute or has a layout the walker doesn't recognise.
42
+ */
43
+ import { type Address, type FetchAccountConfig, type ReadonlyUint8Array, fetchEncodedAccount } from '@solana/kit';
44
+ /**
45
+ * On-chain trait keys. Marketplaces and DAS indexers query these by
46
+ * exact string match — keep in lock-step with:
47
+ * - `migration/import/src/phases/phase2-ants.ts`
48
+ * - `programs/ario-arns/src/mpl_core_cpi.rs::TRAIT_KEY_*`
49
+ * - `programs/ario-core/src/mpl_core.rs::TRAIT_KEY_ANT_PROGRAM`
50
+ */
51
+ export declare const TRAIT_KEY_ARNS_NAME: "ArNS Name";
52
+ export declare const TRAIT_KEY_TYPE: "Type";
53
+ export declare const TRAIT_KEY_UNDERNAME_LIMIT: "Undername Limit";
54
+ export declare const TRAIT_KEY_ANT_PROGRAM: "ANT Program";
55
+ /**
56
+ * Read a single attribute value from a Metaplex Core asset's Attributes
57
+ * plugin. Returns `null` when the asset has no plugin section, has no
58
+ * Attributes plugin, the requested key is absent, or any layer of the
59
+ * walk fails to decode. This is a best-effort lookup — callers should
60
+ * use a canonical default rather than treating absence as an error.
61
+ *
62
+ * `data` is the raw account data (post-discriminator? no — MPL Core
63
+ * doesn't use the 8-byte Anchor discriminator, the asset is the
64
+ * account's full data starting from the `Key` enum byte).
65
+ */
66
+ export declare function readAttribute(data: Uint8Array | ReadonlyUint8Array, key: string): string | null;
67
+ /**
68
+ * Convenience wrapper: fetch the asset account and parse its
69
+ * `ANT Program` attribute. Returns `null` when the account doesn't
70
+ * exist, has no `ANT Program` trait, or the value can't be parsed —
71
+ * callers should fall back to the canonical `ARIO_ANT_PROGRAM_ID`.
72
+ *
73
+ * Importing this here (rather than wiring it directly into the resolver
74
+ * paths) lets `ant-readable.ts` keep its constructor synchronous and
75
+ * have a separate async `fromAsset(rpc, mint)` factory that does the
76
+ * lookup once and caches the result.
77
+ */
78
+ export declare function fetchAntProgramFromAsset(rpc: Parameters<typeof fetchEncodedAccount>[0], mint: Address, config?: FetchAccountConfig): Promise<Address | null>;
79
+ /**
80
+ * Decide which ANT program id to trust for a SIGNING (write) transaction.
81
+ *
82
+ * The `ANT Program` trait returned by {@link fetchAntProgramFromAsset} is read
83
+ * from Metaplex Core asset / RPC data and is NOT authenticated — a malicious
84
+ * asset owner, or a spoofed/compromised RPC response, can set it to an
85
+ * attacker-controlled program. Write instructions use this value as the
86
+ * instruction `programAddress` while including the caller as a signer, so
87
+ * silently trusting a non-canonical detected value would let an attacker route
88
+ * a victim's signed transaction to their own program and inherit signer /
89
+ * writable privileges over the included accounts.
90
+ *
91
+ * Trust rules — BYO-ANT (ADR-016 / BD-100) stays supported, but only via
92
+ * explicit opt-in:
93
+ * - An `explicit` program id (the caller passed `antProgramId`) is always
94
+ * honored — the caller has taken responsibility for it.
95
+ * - Otherwise a detected value is honored only when it is `null` (no trait)
96
+ * or equals the canonical {@link ARIO_ANT_PROGRAM_ID}.
97
+ * - A detected NON-canonical value with no explicit opt-in throws, rather
98
+ * than silently signing against an untrusted program.
99
+ *
100
+ * Read-only paths never sign, so they may auto-detect freely; this guard is
101
+ * only for the write path.
102
+ */
103
+ export declare function resolveWriteAntProgram(args: {
104
+ explicit?: Address;
105
+ detected: Address | null;
106
+ canonical?: Address;
107
+ }): Address;
108
+ /**
109
+ * Fetch the current owner of an MPL Core asset. Returns `null` when the
110
+ * account doesn't exist or the AssetV1 layout can't be decoded.
111
+ *
112
+ * Used by `SolanaARIOWriteable` to decide whether to bundle
113
+ * `ant.sync_attributes` into a buy / manage tx. The Attributes plugin's
114
+ * `BasePluginAuthority` is `Owner`, so only the current asset holder
115
+ * can sign the inner CPI; if the caller isn't the holder, bundling
116
+ * would abort the whole tx (BD-095 — non-holder ArNS lease management
117
+ * must continue to succeed; the actual ANT owner can call the public
118
+ * `syncAttributes` later to converge state).
119
+ */
120
+ export declare function fetchMplCoreOwner(rpc: Parameters<typeof fetchEncodedAccount>[0], mint: Address, config?: FetchAccountConfig): Promise<Address | null>;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * PDA derivation helpers for AR.IO Solana programs.
3
+ *
4
+ * Each function derives the on-chain address for a given account type,
5
+ * mirroring the seeds defined in the Anchor programs.
6
+ *
7
+ * All helpers are async — kit's `getProgramDerivedAddress` is async because
8
+ * it may perform bump-seed search off the main thread in some environments.
9
+ */
10
+ import { type Address } from '@solana/kit';
11
+ /** Return shape for every PDA helper: `[pdaAddress, bumpSeed]`. */
12
+ export type Pda = readonly [Address, number];
13
+ /**
14
+ * Hash a variable-length name for use as PDA seed.
15
+ * Matches Rust: hash(name.to_lowercase().as_bytes())
16
+ */
17
+ export declare function hashName(name: string): Buffer;
18
+ export declare function getArioConfigPDA(programId?: Address): Promise<Pda>;
19
+ export declare function getBalancePDA(owner: Address, programId?: Address): Promise<Pda>;
20
+ export declare function getVaultPDA(owner: Address, vaultId: bigint | number, programId?: Address): Promise<Pda>;
21
+ export declare function getVaultCounterPDA(owner: Address, programId?: Address): Promise<Pda>;
22
+ export declare function getPrimaryNamePDA(owner: Address, programId?: Address): Promise<Pda>;
23
+ export declare function getPrimaryNameRequestPDA(initiator: Address, programId?: Address): Promise<Pda>;
24
+ export declare function getPrimaryNameReversePDA(name: string, programId?: Address): Promise<Pda>;
25
+ export declare function getGatewayRegistryPDA(programId?: Address): Promise<Pda>;
26
+ export declare function getGarSettingsPDA(programId?: Address): Promise<Pda>;
27
+ export declare function getGatewayPDA(operator: Address, programId?: Address): Promise<Pda>;
28
+ export declare function getDelegationPDA(gateway: Address, delegator: Address, programId?: Address): Promise<Pda>;
29
+ export declare function getWithdrawalPDA(owner: Address, withdrawalId: bigint | number, programId?: Address): Promise<Pda>;
30
+ export declare function getWithdrawalCounterPDA(owner: Address, programId?: Address): Promise<Pda>;
31
+ export declare function getAllowlistPDA(gateway: Address, delegate: Address, programId?: Address): Promise<Pda>;
32
+ export declare function getEpochPDA(epochIndex: number, programId?: Address): Promise<Pda>;
33
+ export declare function getEpochSettingsPDA(programId?: Address): Promise<Pda>;
34
+ export declare function getRedelegationRecordPDA(delegator: Address, programId?: Address): Promise<Pda>;
35
+ export declare function getObservationPDA(epochIndex: number, observer: Address, programId?: Address): Promise<Pda>;
36
+ export declare function getObserverLookupPDA(observerAddress: Address, programId?: Address): Promise<Pda>;
37
+ export declare function getArnsRegistryPDA(programId?: Address): Promise<Pda>;
38
+ export declare function getArnsSettingsPDA(programId?: Address): Promise<Pda>;
39
+ export declare function getArnsRecordPDA(name: string, programId?: Address): Promise<Pda>;
40
+ /**
41
+ * Derive ArNS record PDA from a raw 32-byte name hash.
42
+ * Used when resolving prescribed name hashes from Epoch data.
43
+ */
44
+ export declare function getArnsRecordPDAFromHash(nameHash: Buffer, programId?: Address): Promise<Pda>;
45
+ export declare function getReservedNamePDA(name: string, programId?: Address): Promise<Pda>;
46
+ export declare function getReturnedNamePDA(name: string, programId?: Address): Promise<Pda>;
47
+ export declare function getDemandFactorPDA(programId?: Address): Promise<Pda>;
48
+ export declare function getAntConfigPDA(mint: Address, programId?: Address): Promise<Pda>;
49
+ export declare function getAntControllersPDA(mint: Address, programId?: Address): Promise<Pda>;
50
+ export declare function getAntRecordPDA(mint: Address, undername: string, programId?: Address): Promise<Pda>;
51
+ export declare function getAntRecordMetadataPDA(mint: Address, undername: string, programId?: Address): Promise<Pda>;
52
+ /**
53
+ * Derive the `AclConfig` head PDA for a given wallet address.
54
+ *
55
+ * Seeds: `["acl_config", user]` under the ario-ant program.
56
+ *
57
+ * See ADR-012 (docs/DECISIONS.md): `AclConfig` is the head record for a
58
+ * user's paginated ACL. It tracks `page_count` (how many `AclPage` PDAs
59
+ * exist) and `total_entries` (sum across pages). Frontends point-read
60
+ * this once, then fan out to each `AclPage` via `getMultipleAccountsInfo`.
61
+ */
62
+ export declare function getAclConfigPDA(user: Address, programId?: Address): Promise<Pda>;
63
+ /**
64
+ * Derive an `AclPage` PDA for a given user + page index.
65
+ *
66
+ * Seeds: `["acl_page", user, page_idx_le]` where `page_idx_le` is the
67
+ * 8-byte little-endian encoding of `u64` (matches the contract).
68
+ *
69
+ * Each page address is content-derivable from `(user, page_idx)`, so any
70
+ * single page can be loaded in O(1) without scanning sibling pages.
71
+ */
72
+ export declare function getAclPagePDA(user: Address, pageIdx: bigint | number, programId?: Address): Promise<Pda>;
73
+ /**
74
+ * Derive the EscrowAnt PDA for a given ANT mint. Exactly one escrow per
75
+ * ANT — re-deriving the address tells you whether an escrow already
76
+ * exists (look up the account and check `data.length`).
77
+ *
78
+ * Seeds: ["escrow_ant", ant_mint]
79
+ * Source: contracts/programs/ario-ant-escrow/src/state.rs::ESCROW_ANT_SEED
80
+ */
81
+ export declare function getEscrowAntPDA(antMint: Address, programId?: Address): Promise<Pda>;
82
+ /**
83
+ * Derive the EscrowToken PDA for a given depositor and asset ID.
84
+ *
85
+ * Seeds: ["escrow_token", depositor, asset_id]
86
+ * Source: contracts/programs/ario-ant-escrow/src/state.rs::ESCROW_TOKEN_SEED
87
+ */
88
+ export declare function getEscrowTokenPDA(depositor: Address, assetId: Uint8Array, programId?: Address): Promise<Pda>;
89
+ /**
90
+ * Derive the EscrowVault PDA for a given depositor and asset ID.
91
+ *
92
+ * Seeds: ["escrow_vault", depositor, asset_id]
93
+ * Source: contracts/programs/ario-ant-escrow/src/state.rs::ESCROW_VAULT_SEED
94
+ */
95
+ export declare function getEscrowVaultPDA(depositor: Address, assetId: Uint8Array, programId?: Address): Promise<Pda>;
@@ -0,0 +1,28 @@
1
+ import { type Address } from '@solana/kit';
2
+ /** One registry slot's selection-relevant fields (`GatewaySlot`). */
3
+ export interface RegistrySlotWeight {
4
+ /** `GatewaySlot.address` — the operator pubkey. Gateway PDAs derive from this. */
5
+ address: Address;
6
+ /** `GatewaySlot.composite_weight` (u64, mARIO-scaled). */
7
+ compositeWeight: bigint;
8
+ }
9
+ /**
10
+ * Predict the operator pubkeys `prescribe_epoch` will select as observers.
11
+ *
12
+ * Returns the selected `GatewaySlot.address` values (operator pubkeys) in
13
+ * selection order, at most `maxObservers`. These correspond 1:1 to the on-chain
14
+ * `epoch.prescribed_observer_gateways` array, and are what Gateway PDAs are
15
+ * derived from (`[GATEWAY_SEED, operator]`). NOTE this is NOT
16
+ * `epoch.prescribed_observers`, which `prescribe_epoch` later overwrites with
17
+ * each gateway's resolved `observer_address`.
18
+ *
19
+ * @param epochHashchain `epoch.hashchain` — exactly 32 bytes, frozen at
20
+ * `create_epoch`.
21
+ * @param slots `registry.gateways[0 .. epoch.active_gateway_count]` in registry
22
+ * (slot-index) order. Pass the whole prefix including any zero-weight slots —
23
+ * order and the live weight sum must match the on-chain walk exactly. Empty /
24
+ * zero-weight slots contribute nothing and can never be selected.
25
+ * @param maxObservers `epoch_settings.prescribed_observer_count`. Clamped to
26
+ * `slots.length` (the on-chain `min(prescribed_observer_count, active_count)`).
27
+ */
28
+ export declare function predictPrescribedObservers(epochHashchain: Uint8Array, slots: RegistrySlotWeight[], maxObservers: number): Address[];
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Lightweight retry helper with exponential back-off + jitter for Solana RPC
18
+ * read calls.
19
+ *
20
+ * Wraps any async function so transient transport errors (HTTP 429/5xx,
21
+ * network timeouts, etc.) are retried automatically while "normal" failures
22
+ * (account-not-found, deserialization) bubble immediately.
23
+ *
24
+ * Usage:
25
+ * ```ts
26
+ * const account = await withRetry(() => fetchEncodedAccount(rpc, pda));
27
+ * ```
28
+ */
29
+ export interface RetryOptions {
30
+ /** Maximum number of attempts (first call + retries). @default 3 */
31
+ maxAttempts?: number;
32
+ /** Base delay in ms before the first retry. Doubled each attempt. @default 1_000 */
33
+ baseDelayMs?: number;
34
+ /** Cap on any single delay in ms. @default 10_000 */
35
+ maxDelayMs?: number;
36
+ /** Predicate that decides whether a thrown error is retryable.
37
+ * Defaults to {@link isRetryableError}. */
38
+ isRetryable?: (error: unknown) => boolean;
39
+ }
40
+ /**
41
+ * Default retryable-error heuristic.
42
+ *
43
+ * We retry on:
44
+ * - Network / fetch errors (`TypeError: fetch failed`)
45
+ * - HTTP 429 (rate-limit) and 5xx (server) surfaced by kit's transport as
46
+ * `SolanaError` with "HTTP error (4xx|5xx)" in the message.
47
+ * - Timeout errors from opossum or native `AbortError`.
48
+ *
49
+ * We do NOT retry on:
50
+ * - JSON-RPC application errors (account not found, invalid params, etc.)
51
+ * - Deserialization / decoding errors
52
+ * - Any error without a recognisable transport signature
53
+ */
54
+ export declare function isRetryableError(error: unknown): boolean;
55
+ /**
56
+ * Execute `fn` with automatic retries on transient failures.
57
+ *
58
+ * ```ts
59
+ * const data = await withRetry(() => rpc.getAccountInfo(addr).send());
60
+ * ```
61
+ */
62
+ export declare function withRetry<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>;
@@ -0,0 +1,78 @@
1
+ import type { SolanaRpc } from './types.js';
2
+ export interface CircuitBreakerRpcOptions {
3
+ /**
4
+ * Time in ms before a single RPC request is considered timed-out.
5
+ * Set to `false` to disable the opossum-level timeout (rely on the
6
+ * underlying transport timeout only).
7
+ * @default 10_000
8
+ */
9
+ timeout?: number | false;
10
+ /**
11
+ * Error percentage (0-100) at which to open the circuit.
12
+ * @default 25
13
+ */
14
+ errorThresholdPercentage?: number;
15
+ /**
16
+ * Time in ms to wait before entering half-open state and retrying
17
+ * the primary.
18
+ * @default 60_000
19
+ */
20
+ resetTimeout?: number;
21
+ /**
22
+ * Minimum number of requests within the rolling window before the
23
+ * circuit can trip. Prevents opening the circuit after a single failure.
24
+ * @default 3
25
+ */
26
+ volumeThreshold?: number;
27
+ /**
28
+ * Ceiling for requests allowed through per second. Implemented as an
29
+ * adaptive token bucket *in front of* the breaker: excess requests are
30
+ * queued (FIFO) until a token frees, smoothing bursts so you stay under a
31
+ * provider's rate limit (avoids HTTP 429 / Solana error #8100002).
32
+ *
33
+ * The bucket auto-tunes on 429s: it honors `Retry-After`, drops to
34
+ * `x-ratelimit-rps-limit` when the provider advertises one (public Solana
35
+ * RPC does; QuickNode generally does not), otherwise halves the rate
36
+ * (AIMD). It recovers back up toward this ceiling on sustained success.
37
+ *
38
+ * The queue wait happens *before* `breaker.fire`, so it does NOT count
39
+ * against {@link CircuitBreakerRpcOptions.timeout}.
40
+ *
41
+ * Throttling is always on; omitting this (or passing `<= 0`) uses the
42
+ * {@link DEFAULT_MAX_RPS} default. To effectively remove the limit, pass a
43
+ * very large number.
44
+ * @default 10
45
+ */
46
+ maxRequestsPerSecond?: number;
47
+ /**
48
+ * Maximum number of concurrent in-flight requests (opossum `capacity`
49
+ * semaphore). Unlike {@link CircuitBreakerRpcOptions.maxRequestsPerSecond},
50
+ * excess requests are **rejected immediately** rather than queued — this is
51
+ * concurrency control, not a rate limit. For avoiding 429s you usually want
52
+ * `maxRequestsPerSecond` instead.
53
+ * @default undefined (unlimited)
54
+ */
55
+ maxConcurrent?: number;
56
+ }
57
+ export interface CircuitBreakerRpcConfig {
58
+ /** URL for the primary (preferred) RPC endpoint. */
59
+ primaryUrl: string;
60
+ /** URL for the fallback RPC endpoint (used when the circuit opens). */
61
+ fallbackUrl: string;
62
+ /** Opossum circuit-breaker tuning knobs. */
63
+ circuitBreakerOptions?: CircuitBreakerRpcOptions;
64
+ }
65
+ /**
66
+ * Create a {@link SolanaRpc} whose transport is backed by an opossum circuit
67
+ * breaker. Reads and writes flow through the primary transport; when it
68
+ * becomes unhealthy the circuit opens and subsequent calls are routed to
69
+ * the fallback transport until the primary recovers.
70
+ */
71
+ export declare function createCircuitBreakerRpc({ primaryUrl, fallbackUrl, circuitBreakerOptions: opts, }: CircuitBreakerRpcConfig): SolanaRpc;
72
+ /**
73
+ * Convenience: pick a sensible public fallback URL based on the primary URL.
74
+ *
75
+ * - Primary contains `devnet` → devnet public RPC
76
+ * - Everything else → mainnet-beta public RPC
77
+ */
78
+ export declare function defaultFallbackUrl(primaryUrl: string): string;
@@ -0,0 +1,94 @@
1
+ import { type Address, type Commitment, type Instruction, type TransactionSigner } from '@solana/kit';
2
+ import type { SolanaRpc, SolanaRpcSubscriptions } from './types.js';
3
+ /**
4
+ * Build, sign, send, and confirm a transaction in one call.
5
+ *
6
+ * The caller supplies the core instructions; a compute-unit-limit instruction
7
+ * is prepended automatically.
8
+ */
9
+ export declare function sendAndConfirm({ rpc, rpcSubscriptions, signer, instructions, commitment, computeUnitLimit, addressLookupTables, }: {
10
+ rpc: SolanaRpc;
11
+ rpcSubscriptions: SolanaRpcSubscriptions;
12
+ signer: TransactionSigner;
13
+ instructions: Instruction[];
14
+ commitment?: Commitment;
15
+ computeUnitLimit?: number;
16
+ /**
17
+ * Address Lookup Tables to compress the (v0) message against, as
18
+ * `{ [tableAddress]: addresses }`. Accounts present in a table are referenced
19
+ * by 1-byte index instead of their 32-byte key, shrinking the transaction —
20
+ * required when an instruction touches more accounts than fit inline (e.g.
21
+ * `prescribe_epoch` with ~50 observer PDAs). The tables MUST already be
22
+ * on-chain and active. See {@link sendWithEphemeralLookupTable}.
23
+ */
24
+ addressLookupTables?: Record<string, Address[]>;
25
+ }): Promise<string>;
26
+ /**
27
+ * Submit `instruction` in a v0 transaction whose `lookupAddresses` (read-only
28
+ * accounts) are served from a freshly-created, ephemeral Address Lookup Table,
29
+ * so an instruction touching far more accounts than fit inline (e.g.
30
+ * `prescribe_epoch` with ≤50 observer PDAs + NameRegistry, ~2 KB of keys) still
31
+ * fits Solana's 1232-byte transaction-size limit.
32
+ *
33
+ * Three confirmed steps: create the table, extend it with the addresses (in
34
+ * ≤20-address batches to stay within the extend tx size), then send
35
+ * `instruction` compressed against the table. The sequential confirmations
36
+ * satisfy the rule that appended addresses are only usable the slot AFTER they
37
+ * are added. `signer` is the table's authority + payer; the table's (tiny) rent
38
+ * is left allocated — a future cleanup pass can deactivate + close it.
39
+ */
40
+ export declare function sendWithEphemeralLookupTable({ rpc, rpcSubscriptions, signer, instruction, lookupAddresses, commitment, computeUnitLimit, }: {
41
+ rpc: SolanaRpc;
42
+ rpcSubscriptions: SolanaRpcSubscriptions;
43
+ signer: TransactionSigner;
44
+ instruction: Instruction;
45
+ lookupAddresses: Address[];
46
+ commitment?: Commitment;
47
+ computeUnitLimit?: number;
48
+ }): Promise<string>;
49
+ /**
50
+ * Reclaim rent from the ephemeral Address Lookup Tables `signer` created for
51
+ * prescribe (see {@link sendWithEphemeralLookupTable}). Each prescribe leaves a
52
+ * single-use table allocated (~0.0126 SOL of rent); reclaiming needs a
53
+ * deactivate → ~513-slot cooldown → close sequence, so it can't run inline — a
54
+ * throttled permissionless cleanup pass (cranker / observer) calls this.
55
+ *
56
+ * Discovery is RPC-portable. `getProgramAccounts` on the Address Lookup Table
57
+ * program is rejected by Agave RPCs (`Invalid param: WrongSize`, on public
58
+ * devnet/mainnet-beta and dedicated providers alike — the ALT program can't be
59
+ * enumerated), so instead we read the signer's own transaction history
60
+ * (`getSignaturesForAddress` + `getTransaction`) and collect the tables it
61
+ * referenced via `message.addressTableLookups` — a prescribe ALT is used in
62
+ * exactly one transaction.
63
+ *
64
+ * Safety fingerprint: a candidate is only touched when EVERY one of its entries
65
+ * is owned by a program in `allowedEntryOwners` (the GAR + ArNS programs — i.e.
66
+ * observer Gateway PDAs + the ArNS NameRegistry). That composition uniquely
67
+ * identifies a prescribe ephemeral, so the pass never deactivates/closes an
68
+ * unrelated table even if `signer` is also used to author Address Lookup Tables
69
+ * for other purposes.
70
+ *
71
+ * DEACTIVATES still-active matches (starts the cooldown) and CLOSES deactivated
72
+ * matches past the cooldown (refunding rent to `signer`). At most `maxTables`
73
+ * submissions per call; scans at most `scanLimit` recent signatures. Best-effort:
74
+ * per-table failures are skipped and retried on the next pass.
75
+ */
76
+ export declare function reclaimLookupTablesForSigner({ rpc, rpcSubscriptions, signer, allowedEntryOwners, commitment, maxTables, scanLimit, }: {
77
+ rpc: SolanaRpc;
78
+ rpcSubscriptions: SolanaRpcSubscriptions;
79
+ signer: TransactionSigner;
80
+ /**
81
+ * Program IDs that EVERY entry of a reclaimable prescribe ALT must be owned by
82
+ * — pass the GAR + ArNS program IDs. The fingerprint that keeps reclamation
83
+ * from touching unrelated lookup tables.
84
+ */
85
+ allowedEntryOwners: Address[];
86
+ commitment?: Commitment;
87
+ maxTables?: number;
88
+ scanLimit?: number;
89
+ }): Promise<{
90
+ deactivated: number;
91
+ closed: number;
92
+ candidates: number;
93
+ scannedSignatures: number;
94
+ }>;