@ar.io/sdk 3.24.0 → 4.0.0-solana.10

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 (547) hide show
  1. package/README.md +143 -23
  2. package/lib/esm/cli/cli.js +200 -40
  3. package/lib/esm/cli/commands/antCommands.js +40 -14
  4. package/lib/esm/cli/commands/arnsPurchaseCommands.js +46 -7
  5. package/lib/esm/cli/commands/escrowCommands.js +208 -0
  6. package/lib/esm/cli/commands/gatewayWriteCommands.js +132 -22
  7. package/lib/esm/cli/commands/pruneCommands.js +166 -0
  8. package/lib/esm/cli/commands/readCommands.js +10 -2
  9. package/lib/esm/cli/commands/transfer.js +6 -6
  10. package/lib/esm/cli/options.js +141 -2
  11. package/lib/esm/cli/utils.js +280 -39
  12. package/lib/esm/common/ant-registry.js +25 -3
  13. package/lib/esm/common/ant.js +50 -5
  14. package/lib/esm/common/contracts/ao-process.js +4 -6
  15. package/lib/esm/common/io.js +41 -0
  16. package/lib/esm/common/marketplace.js +24 -79
  17. package/lib/esm/constants.js +13 -1
  18. package/lib/esm/solana/ant-readable.js +387 -0
  19. package/lib/esm/solana/ant-registry-readable.js +118 -0
  20. package/lib/esm/solana/ant-registry-writeable.js +457 -0
  21. package/lib/esm/solana/ant-writeable.js +352 -0
  22. package/lib/esm/solana/ata.js +55 -0
  23. package/lib/esm/solana/canonical-message.js +92 -0
  24. package/lib/esm/solana/clusters.js +62 -0
  25. package/lib/esm/solana/constants.js +130 -0
  26. package/lib/esm/solana/delegation-math.js +63 -0
  27. package/lib/esm/solana/deserialize.js +1182 -0
  28. package/lib/esm/solana/escrow.js +797 -0
  29. package/lib/esm/solana/events.js +210 -0
  30. package/lib/esm/solana/funding-plan.js +682 -0
  31. package/lib/esm/solana/generated/ant/events/aclEntryAddedEvent.js +21 -0
  32. package/lib/esm/solana/generated/ant/events/aclEntryRemovedEvent.js +21 -0
  33. package/lib/esm/solana/generated/ant/events/antMetadataUpdatedEvent.js +21 -0
  34. package/lib/esm/solana/generated/ant/events/antReconciledEvent.js +21 -0
  35. package/lib/esm/solana/generated/ant/events/antTransferredEvent.js +21 -0
  36. package/lib/esm/solana/generated/ant/events/attributesClearedEvent.js +21 -0
  37. package/lib/esm/solana/generated/ant/events/attributesSyncedEvent.js +21 -0
  38. package/lib/esm/solana/generated/ant/events/controllerAddedEvent.js +21 -0
  39. package/lib/esm/solana/generated/ant/events/controllerRemovedEvent.js +21 -0
  40. package/lib/esm/solana/generated/ant/events/index.js +16 -0
  41. package/lib/esm/solana/generated/ant/events/recordMetadataPrunedEvent.js +21 -0
  42. package/lib/esm/solana/generated/ant/events/recordMetadataRemovedEvent.js +21 -0
  43. package/lib/esm/solana/generated/ant/events/recordMetadataUpdatedEvent.js +21 -0
  44. package/lib/esm/solana/generated/ant/events/recordRemovedEvent.js +21 -0
  45. package/lib/esm/solana/generated/ant/events/recordSetEvent.js +21 -0
  46. package/lib/esm/solana/generated/ant/events/recordTransferredEvent.js +21 -0
  47. package/lib/esm/solana/generated/ant-escrow/events/escrowCancelledEvent.js +21 -0
  48. package/lib/esm/solana/generated/ant-escrow/events/escrowClaimedEvent.js +21 -0
  49. package/lib/esm/solana/generated/ant-escrow/events/escrowDepositedEvent.js +21 -0
  50. package/lib/esm/solana/generated/ant-escrow/events/escrowRecipientUpdatedEvent.js +21 -0
  51. package/lib/esm/solana/generated/ant-escrow/events/index.js +5 -0
  52. package/lib/esm/solana/generated/arns/events/demandFactorUpdatedEvent.js +21 -0
  53. package/lib/esm/solana/generated/arns/events/index.js +13 -0
  54. package/lib/esm/solana/generated/arns/events/leaseExtendedEvent.js +21 -0
  55. package/lib/esm/solana/generated/arns/events/namePurchasedEvent.js +21 -0
  56. package/lib/esm/solana/generated/arns/events/nameReassignedEvent.js +21 -0
  57. package/lib/esm/solana/generated/arns/events/nameReleasedEvent.js +21 -0
  58. package/lib/esm/solana/generated/arns/events/nameReservedEvent.js +21 -0
  59. package/lib/esm/solana/generated/arns/events/nameUnreservedEvent.js +21 -0
  60. package/lib/esm/solana/generated/arns/events/nameUpgradedEvent.js +21 -0
  61. package/lib/esm/solana/generated/arns/events/namesPrunedEvent.js +21 -0
  62. package/lib/esm/solana/generated/arns/events/reservedNameClaimedEvent.js +21 -0
  63. package/lib/esm/solana/generated/arns/events/returnedNamePurchasedEvent.js +21 -0
  64. package/lib/esm/solana/generated/arns/events/undernameIncreasedEvent.js +21 -0
  65. package/lib/esm/solana/generated/core/events/configUpdatedEvent.js +21 -0
  66. package/lib/esm/solana/generated/core/events/coreMigrationFinalizedEvent.js +21 -0
  67. package/lib/esm/solana/generated/core/events/index.js +14 -0
  68. package/lib/esm/solana/generated/core/events/primaryNameRemovedEvent.js +21 -0
  69. package/lib/esm/solana/generated/core/events/primaryNameRequestExpiredEvent.js +21 -0
  70. package/lib/esm/solana/generated/core/events/primaryNameRequestedEvent.js +21 -0
  71. package/lib/esm/solana/generated/core/events/primaryNameSetEvent.js +21 -0
  72. package/lib/esm/solana/generated/core/events/supplyFinalizedEvent.js +21 -0
  73. package/lib/esm/solana/generated/core/events/transferEvent.js +21 -0
  74. package/lib/esm/solana/generated/core/events/vaultCreatedEvent.js +21 -0
  75. package/lib/esm/solana/generated/core/events/vaultExtendedEvent.js +21 -0
  76. package/lib/esm/solana/generated/core/events/vaultIncreasedEvent.js +21 -0
  77. package/lib/esm/solana/generated/core/events/vaultReleasedEvent.js +21 -0
  78. package/lib/esm/solana/generated/core/events/vaultRevokedEvent.js +21 -0
  79. package/lib/esm/solana/generated/gar/events/allowlistToggledEvent.js +21 -0
  80. package/lib/esm/solana/generated/gar/events/delegateAllowlistedEvent.js +21 -0
  81. package/lib/esm/solana/generated/gar/events/delegationClosedEvent.js +21 -0
  82. package/lib/esm/solana/generated/gar/events/delegationDecreasedEvent.js +21 -0
  83. package/lib/esm/solana/generated/gar/events/delegationEvent.js +21 -0
  84. package/lib/esm/solana/generated/gar/events/epochClosedEvent.js +21 -0
  85. package/lib/esm/solana/generated/gar/events/epochCreatedEvent.js +21 -0
  86. package/lib/esm/solana/generated/gar/events/epochDistributedEvent.js +21 -0
  87. package/lib/esm/solana/generated/gar/events/epochPrescribedEvent.js +21 -0
  88. package/lib/esm/solana/generated/gar/events/epochWeightsTalliedEvent.js +21 -0
  89. package/lib/esm/solana/generated/gar/events/epochsToggledEvent.js +21 -0
  90. package/lib/esm/solana/generated/gar/events/fundingPlanAppliedEvent.js +21 -0
  91. package/lib/esm/solana/generated/gar/events/garMigrationFinalizedEvent.js +21 -0
  92. package/lib/esm/solana/generated/gar/events/gatewayFinalizedEvent.js +21 -0
  93. package/lib/esm/solana/generated/gar/events/gatewayJoinedEvent.js +21 -0
  94. package/lib/esm/solana/generated/gar/events/gatewayLeavingEvent.js +21 -0
  95. package/lib/esm/solana/generated/gar/events/gatewayPrunedEvent.js +21 -0
  96. package/lib/esm/solana/generated/gar/events/gatewaySettingsUpdatedEvent.js +21 -0
  97. package/lib/esm/solana/generated/gar/events/index.js +31 -0
  98. package/lib/esm/solana/generated/gar/events/instantWithdrawalEvent.js +21 -0
  99. package/lib/esm/solana/generated/gar/events/observationSubmittedEvent.js +21 -0
  100. package/lib/esm/solana/generated/gar/events/observerAddressUpdatedEvent.js +21 -0
  101. package/lib/esm/solana/generated/gar/events/operatorStakeIncreasedEvent.js +21 -0
  102. package/lib/esm/solana/generated/gar/events/redelegationEvent.js +21 -0
  103. package/lib/esm/solana/generated/gar/events/residueVaultCreatedEvent.js +21 -0
  104. package/lib/esm/solana/generated/gar/events/rewardsCompoundedEvent.js +21 -0
  105. package/lib/esm/solana/generated/gar/events/stakePaymentEvent.js +21 -0
  106. package/lib/esm/solana/generated/gar/events/withdrawalCancelledEvent.js +21 -0
  107. package/lib/esm/solana/generated/gar/events/withdrawalClaimedEvent.js +21 -0
  108. package/lib/esm/solana/generated/gar/events/withdrawalCreatedEvent.js +21 -0
  109. package/lib/esm/solana/generated/gar/events/withdrawalPaymentEvent.js +21 -0
  110. package/lib/esm/solana/generated/mpl-core/accounts/assetV1.js +42 -0
  111. package/lib/esm/solana/generated/mpl-core/accounts/collectionV1.js +42 -0
  112. package/lib/esm/solana/generated/mpl-core/accounts/hashedAssetV1.js +45 -0
  113. package/lib/esm/solana/generated/mpl-core/accounts/index.js +12 -0
  114. package/lib/esm/solana/generated/mpl-core/accounts/pluginHeaderV1.js +45 -0
  115. package/lib/esm/solana/generated/mpl-core/accounts/pluginRegistryV1.js +42 -0
  116. package/lib/esm/solana/generated/mpl-core/errors/index.js +8 -0
  117. package/lib/esm/solana/generated/mpl-core/errors/mplCore.js +136 -0
  118. package/lib/esm/solana/generated/mpl-core/index.js +8 -0
  119. package/lib/esm/solana/generated/mpl-core/instructions/addCollectionExternalPluginAdapterV1.js +53 -0
  120. package/lib/esm/solana/generated/mpl-core/instructions/addCollectionPluginV1.js +53 -0
  121. package/lib/esm/solana/generated/mpl-core/instructions/addExternalPluginAdapterV1.js +53 -0
  122. package/lib/esm/solana/generated/mpl-core/instructions/addPluginV1.js +53 -0
  123. package/lib/esm/solana/generated/mpl-core/instructions/approveCollectionPluginAuthorityV1.js +53 -0
  124. package/lib/esm/solana/generated/mpl-core/instructions/approvePluginAuthorityV1.js +53 -0
  125. package/lib/esm/solana/generated/mpl-core/instructions/burnCollectionV1.js +49 -0
  126. package/lib/esm/solana/generated/mpl-core/instructions/burnV1.js +49 -0
  127. package/lib/esm/solana/generated/mpl-core/instructions/collect.js +42 -0
  128. package/lib/esm/solana/generated/mpl-core/instructions/compressV1.js +50 -0
  129. package/lib/esm/solana/generated/mpl-core/instructions/createCollectionV1.js +53 -0
  130. package/lib/esm/solana/generated/mpl-core/instructions/createCollectionV2.js +53 -0
  131. package/lib/esm/solana/generated/mpl-core/instructions/createV1.js +53 -0
  132. package/lib/esm/solana/generated/mpl-core/instructions/createV2.js +53 -0
  133. package/lib/esm/solana/generated/mpl-core/instructions/decompressV1.js +53 -0
  134. package/lib/esm/solana/generated/mpl-core/instructions/executeV1.js +56 -0
  135. package/lib/esm/solana/generated/mpl-core/instructions/index.js +40 -0
  136. package/lib/esm/solana/generated/mpl-core/instructions/removeCollectionExternalPluginAdapterV1.js +53 -0
  137. package/lib/esm/solana/generated/mpl-core/instructions/removeCollectionPluginV1.js +53 -0
  138. package/lib/esm/solana/generated/mpl-core/instructions/removeExternalPluginAdapterV1.js +53 -0
  139. package/lib/esm/solana/generated/mpl-core/instructions/removePluginV1.js +53 -0
  140. package/lib/esm/solana/generated/mpl-core/instructions/revokeCollectionPluginAuthorityV1.js +53 -0
  141. package/lib/esm/solana/generated/mpl-core/instructions/revokePluginAuthorityV1.js +53 -0
  142. package/lib/esm/solana/generated/mpl-core/instructions/transferV1.js +49 -0
  143. package/lib/esm/solana/generated/mpl-core/instructions/updateCollectionExternalPluginAdapterV1.js +53 -0
  144. package/lib/esm/solana/generated/mpl-core/instructions/updateCollectionInfoV1.js +45 -0
  145. package/lib/esm/solana/generated/mpl-core/instructions/updateCollectionPluginV1.js +53 -0
  146. package/lib/esm/solana/generated/mpl-core/instructions/updateCollectionV1.js +52 -0
  147. package/lib/esm/solana/generated/mpl-core/instructions/updateExternalPluginAdapterV1.js +53 -0
  148. package/lib/esm/solana/generated/mpl-core/instructions/updatePluginV1.js +53 -0
  149. package/lib/esm/solana/generated/mpl-core/instructions/updateV1.js +53 -0
  150. package/lib/esm/solana/generated/mpl-core/instructions/updateV2.js +53 -0
  151. package/lib/esm/solana/generated/mpl-core/instructions/writeCollectionExternalPluginAdapterDataV1.js +53 -0
  152. package/lib/esm/solana/generated/mpl-core/instructions/writeExternalPluginAdapterDataV1.js +53 -0
  153. package/lib/esm/solana/generated/mpl-core/program-address.js +1 -0
  154. package/lib/esm/solana/generated/mpl-core/types/addAssetsToGroupV1Args.js +17 -0
  155. package/lib/esm/solana/generated/mpl-core/types/addBlocker.js +17 -0
  156. package/lib/esm/solana/generated/mpl-core/types/addCollectionsToGroupV1Args.js +17 -0
  157. package/lib/esm/solana/generated/mpl-core/types/addGroupsToGroupV1Args.js +17 -0
  158. package/lib/esm/solana/generated/mpl-core/types/agentIdentity.js +17 -0
  159. package/lib/esm/solana/generated/mpl-core/types/agentIdentityInitInfo.js +18 -0
  160. package/lib/esm/solana/generated/mpl-core/types/agentIdentityUpdateInfo.js +18 -0
  161. package/lib/esm/solana/generated/mpl-core/types/appData.js +18 -0
  162. package/lib/esm/solana/generated/mpl-core/types/appDataInitInfo.js +18 -0
  163. package/lib/esm/solana/generated/mpl-core/types/appDataUpdateInfo.js +18 -0
  164. package/lib/esm/solana/generated/mpl-core/types/attribute.js +17 -0
  165. package/lib/esm/solana/generated/mpl-core/types/attributes.js +18 -0
  166. package/lib/esm/solana/generated/mpl-core/types/authority.js +24 -0
  167. package/lib/esm/solana/generated/mpl-core/types/autograph.js +18 -0
  168. package/lib/esm/solana/generated/mpl-core/types/autographSignature.js +17 -0
  169. package/lib/esm/solana/generated/mpl-core/types/bubblegumV2.js +17 -0
  170. package/lib/esm/solana/generated/mpl-core/types/burnDelegate.js +17 -0
  171. package/lib/esm/solana/generated/mpl-core/types/closeGroupV1Args.js +17 -0
  172. package/lib/esm/solana/generated/mpl-core/types/compressionProof.js +18 -0
  173. package/lib/esm/solana/generated/mpl-core/types/creator.js +17 -0
  174. package/lib/esm/solana/generated/mpl-core/types/dataSection.js +18 -0
  175. package/lib/esm/solana/generated/mpl-core/types/dataSectionInitInfo.js +18 -0
  176. package/lib/esm/solana/generated/mpl-core/types/dataSectionUpdateInfo.js +17 -0
  177. package/lib/esm/solana/generated/mpl-core/types/dataState.js +23 -0
  178. package/lib/esm/solana/generated/mpl-core/types/edition.js +17 -0
  179. package/lib/esm/solana/generated/mpl-core/types/externalCheckResult.js +17 -0
  180. package/lib/esm/solana/generated/mpl-core/types/externalPluginAdapter.js +25 -0
  181. package/lib/esm/solana/generated/mpl-core/types/externalPluginAdapterInitInfo.js +25 -0
  182. package/lib/esm/solana/generated/mpl-core/types/externalPluginAdapterKey.js +25 -0
  183. package/lib/esm/solana/generated/mpl-core/types/externalPluginAdapterSchema.js +24 -0
  184. package/lib/esm/solana/generated/mpl-core/types/externalPluginAdapterType.js +28 -0
  185. package/lib/esm/solana/generated/mpl-core/types/externalPluginAdapterUpdateInfo.js +25 -0
  186. package/lib/esm/solana/generated/mpl-core/types/externalRegistryRecord.js +18 -0
  187. package/lib/esm/solana/generated/mpl-core/types/externalValidationResult.js +24 -0
  188. package/lib/esm/solana/generated/mpl-core/types/extraAccount.js +25 -0
  189. package/lib/esm/solana/generated/mpl-core/types/freezeDelegate.js +17 -0
  190. package/lib/esm/solana/generated/mpl-core/types/freezeExecute.js +17 -0
  191. package/lib/esm/solana/generated/mpl-core/types/groups.js +17 -0
  192. package/lib/esm/solana/generated/mpl-core/types/hashablePluginSchema.js +18 -0
  193. package/lib/esm/solana/generated/mpl-core/types/hashedAssetSchema.js +17 -0
  194. package/lib/esm/solana/generated/mpl-core/types/hookableLifecycleEvent.js +26 -0
  195. package/lib/esm/solana/generated/mpl-core/types/immutableMetadata.js +17 -0
  196. package/lib/esm/solana/generated/mpl-core/types/index.js +89 -0
  197. package/lib/esm/solana/generated/mpl-core/types/key.js +28 -0
  198. package/lib/esm/solana/generated/mpl-core/types/lifecycleHook.js +18 -0
  199. package/lib/esm/solana/generated/mpl-core/types/lifecycleHookInitInfo.js +18 -0
  200. package/lib/esm/solana/generated/mpl-core/types/lifecycleHookUpdateInfo.js +18 -0
  201. package/lib/esm/solana/generated/mpl-core/types/linkedAppData.js +18 -0
  202. package/lib/esm/solana/generated/mpl-core/types/linkedAppDataInitInfo.js +18 -0
  203. package/lib/esm/solana/generated/mpl-core/types/linkedAppDataUpdateInfo.js +18 -0
  204. package/lib/esm/solana/generated/mpl-core/types/linkedDataKey.js +25 -0
  205. package/lib/esm/solana/generated/mpl-core/types/linkedLifecycleHook.js +18 -0
  206. package/lib/esm/solana/generated/mpl-core/types/linkedLifecycleHookInitInfo.js +18 -0
  207. package/lib/esm/solana/generated/mpl-core/types/linkedLifecycleHookUpdateInfo.js +18 -0
  208. package/lib/esm/solana/generated/mpl-core/types/masterEdition.js +17 -0
  209. package/lib/esm/solana/generated/mpl-core/types/oracle.js +18 -0
  210. package/lib/esm/solana/generated/mpl-core/types/oracleInitInfo.js +18 -0
  211. package/lib/esm/solana/generated/mpl-core/types/oracleUpdateInfo.js +18 -0
  212. package/lib/esm/solana/generated/mpl-core/types/oracleValidation.js +25 -0
  213. package/lib/esm/solana/generated/mpl-core/types/permanentBurnDelegate.js +17 -0
  214. package/lib/esm/solana/generated/mpl-core/types/permanentFreezeDelegate.js +17 -0
  215. package/lib/esm/solana/generated/mpl-core/types/permanentFreezeExecute.js +17 -0
  216. package/lib/esm/solana/generated/mpl-core/types/permanentTransferDelegate.js +17 -0
  217. package/lib/esm/solana/generated/mpl-core/types/plugin.js +25 -0
  218. package/lib/esm/solana/generated/mpl-core/types/pluginAuthorityPair.js +18 -0
  219. package/lib/esm/solana/generated/mpl-core/types/pluginType.js +40 -0
  220. package/lib/esm/solana/generated/mpl-core/types/registryRecord.js +18 -0
  221. package/lib/esm/solana/generated/mpl-core/types/relationshipKind.js +25 -0
  222. package/lib/esm/solana/generated/mpl-core/types/removeAssetsFromGroupV1Args.js +17 -0
  223. package/lib/esm/solana/generated/mpl-core/types/removeCollectionsFromGroupV1Args.js +17 -0
  224. package/lib/esm/solana/generated/mpl-core/types/removeGroupsFromGroupV1Args.js +17 -0
  225. package/lib/esm/solana/generated/mpl-core/types/royalties.js +18 -0
  226. package/lib/esm/solana/generated/mpl-core/types/ruleSet.js +24 -0
  227. package/lib/esm/solana/generated/mpl-core/types/seed.js +24 -0
  228. package/lib/esm/solana/generated/mpl-core/types/transferDelegate.js +17 -0
  229. package/lib/esm/solana/generated/mpl-core/types/updateAuthority.js +24 -0
  230. package/lib/esm/solana/generated/mpl-core/types/updateDelegate.js +17 -0
  231. package/lib/esm/solana/generated/mpl-core/types/updateGroupV1Args.js +17 -0
  232. package/lib/esm/solana/generated/mpl-core/types/updateType.js +24 -0
  233. package/lib/esm/solana/generated/mpl-core/types/validationResult.js +25 -0
  234. package/lib/esm/solana/generated/mpl-core/types/validationResultsOffset.js +24 -0
  235. package/lib/esm/solana/generated/mpl-core/types/verifiedCreators.js +18 -0
  236. package/lib/esm/solana/generated/mpl-core/types/verifiedCreatorsSignature.js +17 -0
  237. package/lib/esm/solana/index.js +85 -0
  238. package/lib/esm/solana/instruction.js +24 -0
  239. package/lib/esm/solana/io-readable.js +1752 -0
  240. package/lib/esm/solana/io-writeable.js +2215 -0
  241. package/lib/esm/solana/json-rpc.js +74 -0
  242. package/lib/esm/solana/metadata.js +66 -0
  243. package/lib/esm/solana/mpl-core.js +142 -0
  244. package/lib/esm/solana/pda.js +317 -0
  245. package/lib/esm/solana/send.js +117 -0
  246. package/lib/esm/solana/spawn-ant.js +210 -0
  247. package/lib/esm/solana/types.js +1 -0
  248. package/lib/esm/types/ant.js +19 -7
  249. package/lib/esm/types/io.js +8 -1
  250. package/lib/esm/utils/ant.js +1 -0
  251. package/lib/esm/utils/ao.js +1 -0
  252. package/lib/esm/version.js +1 -1
  253. package/lib/types/cli/commands/antCommands.d.ts +2 -7
  254. package/lib/types/cli/commands/arnsPurchaseCommands.d.ts +12 -0
  255. package/lib/types/cli/commands/escrowCommands.d.ts +62 -0
  256. package/lib/types/cli/commands/pruneCommands.d.ts +31 -0
  257. package/lib/types/cli/commands/readCommands.d.ts +2 -0
  258. package/lib/types/cli/options.d.ts +112 -0
  259. package/lib/types/cli/types.d.ts +6 -0
  260. package/lib/types/cli/utils.d.ts +43 -5
  261. package/lib/types/common/ant-registry.d.ts +41 -0
  262. package/lib/types/common/ant.d.ts +35 -2
  263. package/lib/types/common/contracts/ao-process.d.ts +2 -16
  264. package/lib/types/common/io.d.ts +42 -2
  265. package/lib/types/common/marketplace.d.ts +2 -14
  266. package/lib/types/constants.d.ts +11 -1
  267. package/lib/types/solana/ant-readable.d.ts +121 -0
  268. package/lib/types/solana/ant-registry-readable.d.ts +90 -0
  269. package/lib/types/solana/ant-registry-writeable.d.ts +234 -0
  270. package/lib/types/solana/ant-writeable.d.ts +162 -0
  271. package/lib/types/solana/ata.d.ts +29 -0
  272. package/lib/types/solana/canonical-message.d.ts +82 -0
  273. package/lib/types/solana/clusters.d.ts +62 -0
  274. package/lib/types/solana/constants.d.ts +103 -0
  275. package/lib/types/solana/delegation-math.d.ts +20 -0
  276. package/lib/types/solana/deserialize.d.ts +440 -0
  277. package/lib/types/solana/escrow.d.ts +403 -0
  278. package/lib/types/solana/events.d.ts +156 -0
  279. package/lib/types/solana/funding-plan.d.ts +210 -0
  280. package/lib/types/solana/generated/ant/events/aclEntryAddedEvent.d.ts +26 -0
  281. package/lib/types/solana/generated/ant/events/aclEntryRemovedEvent.d.ts +26 -0
  282. package/lib/types/solana/generated/ant/events/antMetadataUpdatedEvent.d.ts +28 -0
  283. package/lib/types/solana/generated/ant/events/antReconciledEvent.d.ts +28 -0
  284. package/lib/types/solana/generated/ant/events/antTransferredEvent.d.ts +26 -0
  285. package/lib/types/solana/generated/ant/events/attributesClearedEvent.d.ts +26 -0
  286. package/lib/types/solana/generated/ant/events/attributesSyncedEvent.d.ts +24 -0
  287. package/lib/types/solana/generated/ant/events/controllerAddedEvent.d.ts +26 -0
  288. package/lib/types/solana/generated/ant/events/controllerRemovedEvent.d.ts +26 -0
  289. package/lib/types/solana/generated/ant/events/index.d.ts +15 -0
  290. package/lib/types/solana/generated/ant/events/recordMetadataPrunedEvent.d.ts +26 -0
  291. package/lib/types/solana/generated/ant/events/recordMetadataRemovedEvent.d.ts +26 -0
  292. package/lib/types/solana/generated/ant/events/recordMetadataUpdatedEvent.d.ts +28 -0
  293. package/lib/types/solana/generated/ant/events/recordRemovedEvent.d.ts +26 -0
  294. package/lib/types/solana/generated/ant/events/recordSetEvent.d.ts +34 -0
  295. package/lib/types/solana/generated/ant/events/recordTransferredEvent.d.ts +30 -0
  296. package/lib/types/solana/generated/ant-escrow/events/escrowCancelledEvent.d.ts +28 -0
  297. package/lib/types/solana/generated/ant-escrow/events/escrowClaimedEvent.d.ts +32 -0
  298. package/lib/types/solana/generated/ant-escrow/events/escrowDepositedEvent.d.ts +36 -0
  299. package/lib/types/solana/generated/ant-escrow/events/escrowRecipientUpdatedEvent.d.ts +26 -0
  300. package/lib/types/solana/generated/ant-escrow/events/index.d.ts +4 -0
  301. package/lib/types/solana/generated/arns/events/demandFactorUpdatedEvent.d.ts +28 -0
  302. package/lib/types/solana/generated/arns/events/index.d.ts +12 -0
  303. package/lib/types/solana/generated/arns/events/leaseExtendedEvent.d.ts +32 -0
  304. package/lib/types/solana/generated/arns/events/namePurchasedEvent.d.ts +34 -0
  305. package/lib/types/solana/generated/arns/events/nameReassignedEvent.d.ts +28 -0
  306. package/lib/types/solana/generated/arns/events/nameReleasedEvent.d.ts +24 -0
  307. package/lib/types/solana/generated/arns/events/nameReservedEvent.d.ts +28 -0
  308. package/lib/types/solana/generated/arns/events/nameUnreservedEvent.d.ts +24 -0
  309. package/lib/types/solana/generated/arns/events/nameUpgradedEvent.d.ts +28 -0
  310. package/lib/types/solana/generated/arns/events/namesPrunedEvent.d.ts +26 -0
  311. package/lib/types/solana/generated/arns/events/reservedNameClaimedEvent.d.ts +24 -0
  312. package/lib/types/solana/generated/arns/events/returnedNamePurchasedEvent.d.ts +32 -0
  313. package/lib/types/solana/generated/arns/events/undernameIncreasedEvent.d.ts +32 -0
  314. package/lib/types/solana/generated/core/events/configUpdatedEvent.d.ts +26 -0
  315. package/lib/types/solana/generated/core/events/coreMigrationFinalizedEvent.d.ts +26 -0
  316. package/lib/types/solana/generated/core/events/index.d.ts +13 -0
  317. package/lib/types/solana/generated/core/events/primaryNameRemovedEvent.d.ts +26 -0
  318. package/lib/types/solana/generated/core/events/primaryNameRequestExpiredEvent.d.ts +26 -0
  319. package/lib/types/solana/generated/core/events/primaryNameRequestedEvent.d.ts +30 -0
  320. package/lib/types/solana/generated/core/events/primaryNameSetEvent.d.ts +24 -0
  321. package/lib/types/solana/generated/core/events/supplyFinalizedEvent.d.ts +26 -0
  322. package/lib/types/solana/generated/core/events/transferEvent.d.ts +26 -0
  323. package/lib/types/solana/generated/core/events/vaultCreatedEvent.d.ts +28 -0
  324. package/lib/types/solana/generated/core/events/vaultExtendedEvent.d.ts +26 -0
  325. package/lib/types/solana/generated/core/events/vaultIncreasedEvent.d.ts +28 -0
  326. package/lib/types/solana/generated/core/events/vaultReleasedEvent.d.ts +26 -0
  327. package/lib/types/solana/generated/core/events/vaultRevokedEvent.d.ts +28 -0
  328. package/lib/types/solana/generated/gar/events/allowlistToggledEvent.d.ts +24 -0
  329. package/lib/types/solana/generated/gar/events/delegateAllowlistedEvent.d.ts +26 -0
  330. package/lib/types/solana/generated/gar/events/delegationClosedEvent.d.ts +24 -0
  331. package/lib/types/solana/generated/gar/events/delegationDecreasedEvent.d.ts +28 -0
  332. package/lib/types/solana/generated/gar/events/delegationEvent.d.ts +28 -0
  333. package/lib/types/solana/generated/gar/events/epochClosedEvent.d.ts +24 -0
  334. package/lib/types/solana/generated/gar/events/epochCreatedEvent.d.ts +26 -0
  335. package/lib/types/solana/generated/gar/events/epochDistributedEvent.d.ts +26 -0
  336. package/lib/types/solana/generated/gar/events/epochPrescribedEvent.d.ts +28 -0
  337. package/lib/types/solana/generated/gar/events/epochWeightsTalliedEvent.d.ts +26 -0
  338. package/lib/types/solana/generated/gar/events/epochsToggledEvent.d.ts +24 -0
  339. package/lib/types/solana/generated/gar/events/fundingPlanAppliedEvent.d.ts +28 -0
  340. package/lib/types/solana/generated/gar/events/garMigrationFinalizedEvent.d.ts +26 -0
  341. package/lib/types/solana/generated/gar/events/gatewayFinalizedEvent.d.ts +24 -0
  342. package/lib/types/solana/generated/gar/events/gatewayJoinedEvent.d.ts +26 -0
  343. package/lib/types/solana/generated/gar/events/gatewayLeavingEvent.d.ts +22 -0
  344. package/lib/types/solana/generated/gar/events/gatewayPrunedEvent.d.ts +26 -0
  345. package/lib/types/solana/generated/gar/events/gatewaySettingsUpdatedEvent.d.ts +24 -0
  346. package/lib/types/solana/generated/gar/events/index.d.ts +30 -0
  347. package/lib/types/solana/generated/gar/events/instantWithdrawalEvent.d.ts +30 -0
  348. package/lib/types/solana/generated/gar/events/observationSubmittedEvent.d.ts +28 -0
  349. package/lib/types/solana/generated/gar/events/observerAddressUpdatedEvent.d.ts +24 -0
  350. package/lib/types/solana/generated/gar/events/operatorStakeIncreasedEvent.d.ts +26 -0
  351. package/lib/types/solana/generated/gar/events/redelegationEvent.d.ts +30 -0
  352. package/lib/types/solana/generated/gar/events/residueVaultCreatedEvent.d.ts +30 -0
  353. package/lib/types/solana/generated/gar/events/rewardsCompoundedEvent.d.ts +26 -0
  354. package/lib/types/solana/generated/gar/events/stakePaymentEvent.d.ts +28 -0
  355. package/lib/types/solana/generated/gar/events/withdrawalCancelledEvent.d.ts +30 -0
  356. package/lib/types/solana/generated/gar/events/withdrawalClaimedEvent.d.ts +26 -0
  357. package/lib/types/solana/generated/gar/events/withdrawalCreatedEvent.d.ts +28 -0
  358. package/lib/types/solana/generated/gar/events/withdrawalPaymentEvent.d.ts +28 -0
  359. package/lib/types/solana/generated/mpl-core/accounts/assetV1.d.ts +37 -0
  360. package/lib/types/solana/generated/mpl-core/accounts/collectionV1.d.ts +37 -0
  361. package/lib/types/solana/generated/mpl-core/accounts/hashedAssetV1.d.ts +30 -0
  362. package/lib/types/solana/generated/mpl-core/accounts/index.d.ts +12 -0
  363. package/lib/types/solana/generated/mpl-core/accounts/pluginHeaderV1.d.ts +30 -0
  364. package/lib/types/solana/generated/mpl-core/accounts/pluginRegistryV1.d.ts +31 -0
  365. package/lib/types/solana/generated/mpl-core/errors/index.d.ts +8 -0
  366. package/lib/types/solana/generated/mpl-core/errors/mplCore.d.ts +133 -0
  367. package/lib/types/solana/generated/mpl-core/index.d.ts +8 -0
  368. package/lib/types/solana/generated/mpl-core/instructions/addCollectionExternalPluginAdapterV1.d.ts +56 -0
  369. package/lib/types/solana/generated/mpl-core/instructions/addCollectionPluginV1.d.ts +59 -0
  370. package/lib/types/solana/generated/mpl-core/instructions/addExternalPluginAdapterV1.d.ts +60 -0
  371. package/lib/types/solana/generated/mpl-core/instructions/addPluginV1.d.ts +63 -0
  372. package/lib/types/solana/generated/mpl-core/instructions/approveCollectionPluginAuthorityV1.d.ts +59 -0
  373. package/lib/types/solana/generated/mpl-core/instructions/approvePluginAuthorityV1.d.ts +63 -0
  374. package/lib/types/solana/generated/mpl-core/instructions/burnCollectionV1.d.ts +52 -0
  375. package/lib/types/solana/generated/mpl-core/instructions/burnV1.d.ts +60 -0
  376. package/lib/types/solana/generated/mpl-core/instructions/collect.d.ts +39 -0
  377. package/lib/types/solana/generated/mpl-core/instructions/compressV1.d.ts +55 -0
  378. package/lib/types/solana/generated/mpl-core/instructions/createCollectionV1.d.ts +58 -0
  379. package/lib/types/solana/generated/mpl-core/instructions/createCollectionV2.d.ts +61 -0
  380. package/lib/types/solana/generated/mpl-core/instructions/createV1.d.ts +77 -0
  381. package/lib/types/solana/generated/mpl-core/instructions/createV2.d.ts +80 -0
  382. package/lib/types/solana/generated/mpl-core/instructions/decompressV1.d.ts +60 -0
  383. package/lib/types/solana/generated/mpl-core/instructions/executeV1.d.ts +63 -0
  384. package/lib/types/solana/generated/mpl-core/instructions/index.d.ts +40 -0
  385. package/lib/types/solana/generated/mpl-core/instructions/removeCollectionExternalPluginAdapterV1.d.ts +56 -0
  386. package/lib/types/solana/generated/mpl-core/instructions/removeCollectionPluginV1.d.ts +56 -0
  387. package/lib/types/solana/generated/mpl-core/instructions/removeExternalPluginAdapterV1.d.ts +60 -0
  388. package/lib/types/solana/generated/mpl-core/instructions/removePluginV1.d.ts +60 -0
  389. package/lib/types/solana/generated/mpl-core/instructions/revokeCollectionPluginAuthorityV1.d.ts +56 -0
  390. package/lib/types/solana/generated/mpl-core/instructions/revokePluginAuthorityV1.d.ts +60 -0
  391. package/lib/types/solana/generated/mpl-core/instructions/transferV1.d.ts +64 -0
  392. package/lib/types/solana/generated/mpl-core/instructions/updateCollectionExternalPluginAdapterV1.d.ts +59 -0
  393. package/lib/types/solana/generated/mpl-core/instructions/updateCollectionInfoV1.d.ts +47 -0
  394. package/lib/types/solana/generated/mpl-core/instructions/updateCollectionPluginV1.d.ts +56 -0
  395. package/lib/types/solana/generated/mpl-core/instructions/updateCollectionV1.d.ts +62 -0
  396. package/lib/types/solana/generated/mpl-core/instructions/updateExternalPluginAdapterV1.d.ts +63 -0
  397. package/lib/types/solana/generated/mpl-core/instructions/updatePluginV1.d.ts +60 -0
  398. package/lib/types/solana/generated/mpl-core/instructions/updateV1.d.ts +66 -0
  399. package/lib/types/solana/generated/mpl-core/instructions/updateV2.d.ts +70 -0
  400. package/lib/types/solana/generated/mpl-core/instructions/writeCollectionExternalPluginAdapterDataV1.d.ts +63 -0
  401. package/lib/types/solana/generated/mpl-core/instructions/writeExternalPluginAdapterDataV1.d.ts +67 -0
  402. package/lib/types/solana/generated/mpl-core/program-address.d.ts +7 -0
  403. package/lib/types/solana/generated/mpl-core/types/addAssetsToGroupV1Args.d.ts +13 -0
  404. package/lib/types/solana/generated/mpl-core/types/addBlocker.d.ts +13 -0
  405. package/lib/types/solana/generated/mpl-core/types/addCollectionsToGroupV1Args.d.ts +13 -0
  406. package/lib/types/solana/generated/mpl-core/types/addGroupsToGroupV1Args.d.ts +15 -0
  407. package/lib/types/solana/generated/mpl-core/types/agentIdentity.d.ts +15 -0
  408. package/lib/types/solana/generated/mpl-core/types/agentIdentityInitInfo.d.ts +22 -0
  409. package/lib/types/solana/generated/mpl-core/types/agentIdentityUpdateInfo.d.ts +20 -0
  410. package/lib/types/solana/generated/mpl-core/types/appData.d.ts +20 -0
  411. package/lib/types/solana/generated/mpl-core/types/appDataInitInfo.d.ts +22 -0
  412. package/lib/types/solana/generated/mpl-core/types/appDataUpdateInfo.d.ts +18 -0
  413. package/lib/types/solana/generated/mpl-core/types/attribute.d.ts +16 -0
  414. package/lib/types/solana/generated/mpl-core/types/attributes.d.ts +18 -0
  415. package/lib/types/solana/generated/mpl-core/types/authority.d.ts +29 -0
  416. package/lib/types/solana/generated/mpl-core/types/autograph.d.ts +18 -0
  417. package/lib/types/solana/generated/mpl-core/types/autographSignature.d.ts +16 -0
  418. package/lib/types/solana/generated/mpl-core/types/bubblegumV2.d.ts +13 -0
  419. package/lib/types/solana/generated/mpl-core/types/burnDelegate.d.ts +13 -0
  420. package/lib/types/solana/generated/mpl-core/types/closeGroupV1Args.d.ts +13 -0
  421. package/lib/types/solana/generated/mpl-core/types/compressionProof.d.ts +28 -0
  422. package/lib/types/solana/generated/mpl-core/types/creator.d.ts +16 -0
  423. package/lib/types/solana/generated/mpl-core/types/dataSection.d.ts +20 -0
  424. package/lib/types/solana/generated/mpl-core/types/dataSectionInitInfo.d.ts +20 -0
  425. package/lib/types/solana/generated/mpl-core/types/dataSectionUpdateInfo.d.ts +13 -0
  426. package/lib/types/solana/generated/mpl-core/types/dataState.d.ts +16 -0
  427. package/lib/types/solana/generated/mpl-core/types/edition.d.ts +15 -0
  428. package/lib/types/solana/generated/mpl-core/types/externalCheckResult.d.ts +15 -0
  429. package/lib/types/solana/generated/mpl-core/types/externalPluginAdapter.d.ts +66 -0
  430. package/lib/types/solana/generated/mpl-core/types/externalPluginAdapterInitInfo.d.ts +66 -0
  431. package/lib/types/solana/generated/mpl-core/types/externalPluginAdapterKey.d.ts +64 -0
  432. package/lib/types/solana/generated/mpl-core/types/externalPluginAdapterSchema.d.ts +17 -0
  433. package/lib/types/solana/generated/mpl-core/types/externalPluginAdapterType.d.ts +21 -0
  434. package/lib/types/solana/generated/mpl-core/types/externalPluginAdapterUpdateInfo.d.ts +59 -0
  435. package/lib/types/solana/generated/mpl-core/types/externalRegistryRecord.d.ts +28 -0
  436. package/lib/types/solana/generated/mpl-core/types/externalValidationResult.d.ts +17 -0
  437. package/lib/types/solana/generated/mpl-core/types/extraAccount.d.ts +86 -0
  438. package/lib/types/solana/generated/mpl-core/types/freezeDelegate.d.ts +15 -0
  439. package/lib/types/solana/generated/mpl-core/types/freezeExecute.d.ts +15 -0
  440. package/lib/types/solana/generated/mpl-core/types/groups.d.ts +15 -0
  441. package/lib/types/solana/generated/mpl-core/types/hashablePluginSchema.d.ts +22 -0
  442. package/lib/types/solana/generated/mpl-core/types/hashedAssetSchema.d.ts +16 -0
  443. package/lib/types/solana/generated/mpl-core/types/hookableLifecycleEvent.d.ts +19 -0
  444. package/lib/types/solana/generated/mpl-core/types/immutableMetadata.d.ts +13 -0
  445. package/lib/types/solana/generated/mpl-core/types/index.d.ts +89 -0
  446. package/lib/types/solana/generated/mpl-core/types/key.d.ts +21 -0
  447. package/lib/types/solana/generated/mpl-core/types/lifecycleHook.d.ts +24 -0
  448. package/lib/types/solana/generated/mpl-core/types/lifecycleHookInitInfo.d.ts +28 -0
  449. package/lib/types/solana/generated/mpl-core/types/lifecycleHookUpdateInfo.d.ts +22 -0
  450. package/lib/types/solana/generated/mpl-core/types/linkedAppData.d.ts +20 -0
  451. package/lib/types/solana/generated/mpl-core/types/linkedAppDataInitInfo.d.ts +22 -0
  452. package/lib/types/solana/generated/mpl-core/types/linkedAppDataUpdateInfo.d.ts +18 -0
  453. package/lib/types/solana/generated/mpl-core/types/linkedDataKey.d.ts +31 -0
  454. package/lib/types/solana/generated/mpl-core/types/linkedLifecycleHook.d.ts +24 -0
  455. package/lib/types/solana/generated/mpl-core/types/linkedLifecycleHookInitInfo.d.ts +28 -0
  456. package/lib/types/solana/generated/mpl-core/types/linkedLifecycleHookUpdateInfo.d.ts +22 -0
  457. package/lib/types/solana/generated/mpl-core/types/masterEdition.d.ts +21 -0
  458. package/lib/types/solana/generated/mpl-core/types/oracle.d.ts +22 -0
  459. package/lib/types/solana/generated/mpl-core/types/oracleInitInfo.d.ts +26 -0
  460. package/lib/types/solana/generated/mpl-core/types/oracleUpdateInfo.d.ts +22 -0
  461. package/lib/types/solana/generated/mpl-core/types/oracleValidation.d.ts +35 -0
  462. package/lib/types/solana/generated/mpl-core/types/permanentBurnDelegate.d.ts +13 -0
  463. package/lib/types/solana/generated/mpl-core/types/permanentFreezeDelegate.d.ts +15 -0
  464. package/lib/types/solana/generated/mpl-core/types/permanentFreezeExecute.d.ts +15 -0
  465. package/lib/types/solana/generated/mpl-core/types/permanentTransferDelegate.d.ts +13 -0
  466. package/lib/types/solana/generated/mpl-core/types/plugin.d.ts +150 -0
  467. package/lib/types/solana/generated/mpl-core/types/pluginAuthorityPair.d.ts +20 -0
  468. package/lib/types/solana/generated/mpl-core/types/pluginType.d.ts +33 -0
  469. package/lib/types/solana/generated/mpl-core/types/registryRecord.d.ts +22 -0
  470. package/lib/types/solana/generated/mpl-core/types/relationshipKind.d.ts +18 -0
  471. package/lib/types/solana/generated/mpl-core/types/removeAssetsFromGroupV1Args.d.ts +15 -0
  472. package/lib/types/solana/generated/mpl-core/types/removeCollectionsFromGroupV1Args.d.ts +15 -0
  473. package/lib/types/solana/generated/mpl-core/types/removeGroupsFromGroupV1Args.d.ts +15 -0
  474. package/lib/types/solana/generated/mpl-core/types/royalties.d.ts +22 -0
  475. package/lib/types/solana/generated/mpl-core/types/ruleSet.d.ts +27 -0
  476. package/lib/types/solana/generated/mpl-core/types/seed.d.ts +36 -0
  477. package/lib/types/solana/generated/mpl-core/types/transferDelegate.d.ts +13 -0
  478. package/lib/types/solana/generated/mpl-core/types/updateAuthority.d.ts +27 -0
  479. package/lib/types/solana/generated/mpl-core/types/updateDelegate.d.ts +15 -0
  480. package/lib/types/solana/generated/mpl-core/types/updateGroupV1Args.d.ts +19 -0
  481. package/lib/types/solana/generated/mpl-core/types/updateType.d.ts +17 -0
  482. package/lib/types/solana/generated/mpl-core/types/validationResult.d.ts +18 -0
  483. package/lib/types/solana/generated/mpl-core/types/validationResultsOffset.d.ts +33 -0
  484. package/lib/types/solana/generated/mpl-core/types/verifiedCreators.d.ts +18 -0
  485. package/lib/types/solana/generated/mpl-core/types/verifiedCreatorsSignature.d.ts +16 -0
  486. package/lib/types/solana/index.d.ts +63 -0
  487. package/lib/types/solana/instruction.d.ts +24 -0
  488. package/lib/types/solana/io-readable.d.ts +360 -0
  489. package/lib/types/solana/io-writeable.d.ts +533 -0
  490. package/lib/types/solana/json-rpc.d.ts +32 -0
  491. package/lib/types/solana/metadata.d.ts +69 -0
  492. package/lib/types/solana/mpl-core.d.ts +76 -0
  493. package/lib/types/solana/pda.d.ts +95 -0
  494. package/lib/types/solana/send.d.ts +16 -0
  495. package/lib/types/solana/spawn-ant.d.ts +130 -0
  496. package/lib/types/solana/types.d.ts +67 -0
  497. package/lib/types/types/ant-registry.d.ts +39 -0
  498. package/lib/types/types/ant.d.ts +22 -4
  499. package/lib/types/types/io.d.ts +56 -1
  500. package/lib/types/version.d.ts +1 -1
  501. package/package.json +33 -16
  502. package/lib/cjs/cli/cli.js +0 -822
  503. package/lib/cjs/cli/commands/antCommands.js +0 -113
  504. package/lib/cjs/cli/commands/arnsPurchaseCommands.js +0 -212
  505. package/lib/cjs/cli/commands/gatewayWriteCommands.js +0 -210
  506. package/lib/cjs/cli/commands/readCommands.js +0 -215
  507. package/lib/cjs/cli/commands/transfer.js +0 -159
  508. package/lib/cjs/cli/options.js +0 -470
  509. package/lib/cjs/cli/types.js +0 -2
  510. package/lib/cjs/cli/utils.js +0 -639
  511. package/lib/cjs/common/ant-registry.js +0 -155
  512. package/lib/cjs/common/ant-versions.js +0 -93
  513. package/lib/cjs/common/ant.js +0 -1182
  514. package/lib/cjs/common/arweave.js +0 -27
  515. package/lib/cjs/common/contracts/ao-process.js +0 -224
  516. package/lib/cjs/common/error.js +0 -64
  517. package/lib/cjs/common/faucet.js +0 -150
  518. package/lib/cjs/common/hyperbeam/hb.js +0 -173
  519. package/lib/cjs/common/index.js +0 -42
  520. package/lib/cjs/common/io.js +0 -1423
  521. package/lib/cjs/common/logger.js +0 -83
  522. package/lib/cjs/common/loggers/winston.js +0 -68
  523. package/lib/cjs/common/marketplace.js +0 -731
  524. package/lib/cjs/common/turbo.js +0 -223
  525. package/lib/cjs/constants.js +0 -41
  526. package/lib/cjs/node/index.js +0 -39
  527. package/lib/cjs/package.json +0 -1
  528. package/lib/cjs/types/ant-registry.js +0 -2
  529. package/lib/cjs/types/ant.js +0 -168
  530. package/lib/cjs/types/common.js +0 -2
  531. package/lib/cjs/types/faucet.js +0 -2
  532. package/lib/cjs/types/index.js +0 -37
  533. package/lib/cjs/types/io.js +0 -51
  534. package/lib/cjs/types/token.js +0 -116
  535. package/lib/cjs/utils/ant.js +0 -108
  536. package/lib/cjs/utils/ao.js +0 -432
  537. package/lib/cjs/utils/arweave.js +0 -285
  538. package/lib/cjs/utils/base64.js +0 -62
  539. package/lib/cjs/utils/hash.js +0 -56
  540. package/lib/cjs/utils/index.js +0 -38
  541. package/lib/cjs/utils/json.js +0 -26
  542. package/lib/cjs/utils/processes.js +0 -173
  543. package/lib/cjs/utils/random.js +0 -30
  544. package/lib/cjs/utils/schema.js +0 -15
  545. package/lib/cjs/utils/url.js +0 -37
  546. package/lib/cjs/version.js +0 -20
  547. package/lib/cjs/web/index.js +0 -41
@@ -0,0 +1,1752 @@
1
+ /**
2
+ * Solana implementation of the AoARIORead interface.
3
+ *
4
+ * Reads AR.IO protocol state directly from Solana PDAs using RPC,
5
+ * returning the same types that the AO implementation returns.
6
+ * This allows consumers to switch backends transparently.
7
+ */
8
+ import { address, fetchEncodedAccount, fetchEncodedAccounts, getAddressDecoder, } from '@solana/kit';
9
+ import bs58 from 'bs58';
10
+ import { ARNS_RECORD_DISCRIMINATOR, RESERVED_NAME_DISCRIMINATOR, RETURNED_NAME_DISCRIMINATOR, getArnsConfigDecoder, getArnsRecordDecoder, getReservedNameDecoder, getReturnedNameDecoder, } from '@ar.io/solana-contracts/arns';
11
+ import { PRIMARY_NAME_DISCRIMINATOR, PRIMARY_NAME_REQUEST_DISCRIMINATOR, VAULT_DISCRIMINATOR, getPrimaryNameRequestDecoder, getVaultDecoder, } from '@ar.io/solana-contracts/core';
12
+ import { ALLOWLIST_ENTRY_DISCRIMINATOR, DELEGATION_DISCRIMINATOR, GATEWAY_DISCRIMINATOR, GatewayStatus, OBSERVATION_DISCRIMINATOR, WITHDRAWAL_DISCRIMINATOR, getDelegationDecoder, getGatewayDecoder, getWithdrawalDecoder, } from '@ar.io/solana-contracts/gar';
13
+ import { Logger } from '../common/logger.js';
14
+ import { SolanaANTRegistryReadable } from './ant-registry-readable.js';
15
+ import { getAssociatedTokenAddressKit } from './ata.js';
16
+ import { ARIO_ANT_PROGRAM_ID, ARIO_ARNS_PROGRAM_ID, ARIO_CORE_PROGRAM_ID, ARIO_GAR_PROGRAM_ID, ARNS_RECORD_ANT_OFFSET, RATE_SCALE, } from './constants.js';
17
+ import { computeLiveDelegationBalance } from './delegation-math.js';
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
+ import { TOKEN_PROGRAM_ADDRESS } from './instruction.js';
20
+ import { getArioConfigPDA, getArnsRecordPDA, getArnsRecordPDAFromHash, getArnsSettingsPDA, getDemandFactorPDA, getEpochPDA, getEpochSettingsPDA, getGarSettingsPDA, getGatewayPDA, getGatewayRegistryPDA, getObserverLookupPDA, getPrimaryNamePDA, getPrimaryNameRequestPDA, getReservedNamePDA, getReturnedNamePDA, getVaultPDA, } from './pda.js';
21
+ const addressDecoder = getAddressDecoder();
22
+ /** All-zero address — equivalent of web3.js `PublicKey.default`. */
23
+ const DEFAULT_ADDRESS = address('11111111111111111111111111111111');
24
+ // =========================================
25
+ // Pagination helper
26
+ // =========================================
27
+ /**
28
+ * Normalize whatever `params.filters?.processId` shape came in (undefined,
29
+ * single string, or array — `PaginationParams` widens it past what ArNS
30
+ * actually supports) into a flat `string[]` ANT-mint list.
31
+ */
32
+ function normalizeProcessIdFilter(raw) {
33
+ if (raw == null)
34
+ return [];
35
+ if (typeof raw === 'string')
36
+ return [raw];
37
+ if (Array.isArray(raw))
38
+ return raw.filter((v) => typeof v === 'string');
39
+ return [];
40
+ }
41
+ /**
42
+ * On-chain timestamps in the Solana programs are stored in **seconds**
43
+ * (matching the Lua-source convention as ported), but the public SDK
44
+ * surface — shared with the AO backend — exposes them in **milliseconds**
45
+ * because every JS consumer (UI, cranker, migration tools) feeds them into
46
+ * `new Date()`/`Date.now()` arithmetic. This boundary helper converts at
47
+ * the read-path projection layer so internal arithmetic in this file can
48
+ * keep working in seconds against the deserializer output, but everything
49
+ * we hand back to a caller is in JS-millisecond units.
50
+ *
51
+ * Use `toMsTimestamps(obj)` for projection-layer return values, and
52
+ * `secToMs(n)` for one-off scalars.
53
+ */
54
+ const TIMESTAMP_FIELDS_MS = [
55
+ 'startTimestamp',
56
+ 'endTimestamp',
57
+ 'distributionTimestamp',
58
+ ];
59
+ function secToMs(n) {
60
+ return n * 1000;
61
+ }
62
+ function toMsTimestamps(obj) {
63
+ const out = { ...obj };
64
+ for (const f of TIMESTAMP_FIELDS_MS) {
65
+ const v = out[f];
66
+ if (typeof v === 'number')
67
+ out[f] = v * 1000;
68
+ }
69
+ return out;
70
+ }
71
+ /**
72
+ * Drop the SDK-internal extras (`name`, `owner`) and the `processId` re-key
73
+ * that `deserializeArnsRecord` adds, projecting back to the cross-backend
74
+ * `AoArNSNameDataWithName` shape consumers expect.
75
+ *
76
+ * Timestamps are converted from on-chain seconds to JS milliseconds here
77
+ * (see `toMsTimestamps` above for rationale).
78
+ */
79
+ function arnsRecordToWithName(record) {
80
+ return {
81
+ name: record.name,
82
+ processId: record.processId,
83
+ startTimestamp: secToMs(record.startTimestamp),
84
+ undernameLimit: record.undernameLimit,
85
+ purchasePrice: record.purchasePrice,
86
+ type: record.type,
87
+ ...('endTimestamp' in record
88
+ ? { endTimestamp: secToMs(record.endTimestamp) }
89
+ : {}),
90
+ };
91
+ }
92
+ function paginate(items, params) {
93
+ const limit = params?.limit ?? 100;
94
+ const startIdx = params?.cursor ? parseInt(params.cursor, 10) : 0;
95
+ const page = items.slice(startIdx, startIdx + limit);
96
+ const hasMore = startIdx + limit < items.length;
97
+ return {
98
+ items: page,
99
+ limit,
100
+ totalItems: items.length,
101
+ sortOrder: params?.sortOrder ?? 'asc',
102
+ hasMore,
103
+ nextCursor: hasMore ? String(startIdx + limit) : undefined,
104
+ };
105
+ }
106
+ /**
107
+ * Solana-backed read-only client for the AR.IO protocol.
108
+ *
109
+ * Usage:
110
+ * ```ts
111
+ * import { createSolanaRpc } from '@solana/kit';
112
+ * import { SolanaARIOReadable } from '@ar.io/sdk/solana';
113
+ *
114
+ * const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
115
+ * const ario = new SolanaARIOReadable({ rpc });
116
+ *
117
+ * const gateway = await ario.getGateway({ address: 'GatewayOperatorPubkey...' });
118
+ * const record = await ario.getArNSRecord({ name: 'ardrive' });
119
+ * ```
120
+ */
121
+ export class SolanaARIOReadable {
122
+ rpc;
123
+ commitment;
124
+ logger;
125
+ // Allow overriding program IDs (e.g., for devnet/localnet)
126
+ coreProgram;
127
+ garProgram;
128
+ arnsProgram;
129
+ antProgram;
130
+ // Memoized ARIO mint address (read once from ArioConfig.mint and reused
131
+ // for every SPL-ATA derivation in getBalance/getBalances).
132
+ _arioMint;
133
+ constructor(config) {
134
+ this.rpc = config.rpc;
135
+ this.commitment = config.commitment ?? 'confirmed';
136
+ this.logger = config.logger ?? Logger.default;
137
+ this.coreProgram = config.coreProgramId ?? ARIO_CORE_PROGRAM_ID;
138
+ this.garProgram = config.garProgramId ?? ARIO_GAR_PROGRAM_ID;
139
+ this.arnsProgram = config.arnsProgramId ?? ARIO_ARNS_PROGRAM_ID;
140
+ this.antProgram = config.antProgramId ?? ARIO_ANT_PROGRAM_ID;
141
+ }
142
+ /** Helper to fetch an encoded account (kit's replacement for Connection.getAccountInfo). */
143
+ async getAccount(pda) {
144
+ return fetchEncodedAccount(this.rpc, pda, {
145
+ commitment: this.commitment,
146
+ });
147
+ }
148
+ /**
149
+ * Helper for `getProgramAccounts` with a discriminator memcmp filter.
150
+ *
151
+ * Pass the Codama-generated `<NAME>_DISCRIMINATOR: Uint8Array` constant
152
+ * directly — kit's RPC requires a base58 string for `memcmp.bytes`, so
153
+ * we bs58-encode here to keep call sites from doing it inline (and to
154
+ * keep the IDL-derived bytes as the single source of truth).
155
+ */
156
+ async getAccountsByDiscriminator(programId, discriminator, extraFilters = []) {
157
+ const filters = [
158
+ {
159
+ memcmp: {
160
+ offset: 0n,
161
+ bytes: bs58.encode(discriminator),
162
+ encoding: 'base58',
163
+ },
164
+ },
165
+ ...extraFilters,
166
+ ];
167
+ // Note: kit's getProgramAccounts returns a plain array (no context wrapper)
168
+ // when called without `withContext: true`. With `encoding: 'base64'`, each
169
+ // account's `data` is a `[base64, 'base64']` tuple. We bypass kit's strict
170
+ // generic overload typing here with a cast — the runtime shape is stable.
171
+ const result = (await this.rpc
172
+ .getProgramAccounts(programId, {
173
+ commitment: this.commitment,
174
+ encoding: 'base64',
175
+ filters,
176
+ })
177
+ .send());
178
+ return result.map((entry) => ({
179
+ pubkey: entry.pubkey,
180
+ data: Buffer.from(entry.account.data[0], 'base64'),
181
+ }));
182
+ }
183
+ /**
184
+ * Batch-fetch the `cumulative_reward_per_token` accumulator for every gateway
185
+ * in `operatorAddresses`. Returns a Map keyed by base58 operator address.
186
+ * Used by the delegate readers below to compute the live delegation balance
187
+ * without an on-chain settlement call (see {@link computeLiveDelegationBalance}
188
+ * and `INVARIANTS.md` in the contracts repo). Missing gateways are silently
189
+ * skipped — callers fall back to the stale `Delegation.amount` for those
190
+ * (the accumulator delta is 0 and live == stored anyway when the gateway
191
+ * has no rewards to distribute).
192
+ */
193
+ async getGatewayAccumulators(operatorAddresses) {
194
+ const unique = Array.from(new Set(operatorAddresses));
195
+ if (unique.length === 0)
196
+ return new Map();
197
+ 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
+ commitment: this.commitment,
200
+ });
201
+ const out = new Map();
202
+ for (let i = 0; i < accounts.length; i++) {
203
+ const acct = accounts[i];
204
+ if (!acct.exists)
205
+ continue;
206
+ try {
207
+ // Internal variant: surfaces the u128 accumulator that the public
208
+ // `deserializeGateway` deliberately drops (BigInt is not
209
+ // JSON-serializable and would leak through getGateway).
210
+ const gw = deserializeGatewayWithAccumulator(Buffer.from(acct.data));
211
+ out.set(unique[i], gw.cumulativeRewardPerToken);
212
+ }
213
+ catch {
214
+ // Skip malformed; the caller will fall back to the raw delegation amount.
215
+ }
216
+ }
217
+ return out;
218
+ }
219
+ /** Read the gateway registry and return addresses in registry index order */
220
+ async getRegistryGatewayAddresses() {
221
+ const [registryPda] = await getGatewayRegistryPDA(this.garProgram);
222
+ const registryAccount = await this.getAccount(registryPda);
223
+ if (!registryAccount.exists)
224
+ return [];
225
+ const registryData = Buffer.from(registryAccount.data);
226
+ const count = registryData.readUInt32LE(40); // 8 disc + 32 authority
227
+ const slotsOffset = 48; // 8 + 32 + 4 + 4
228
+ // GatewaySlot: address(32) + composite_weight(8) + start_timestamp(8)
229
+ // + status(1) + _padding(7) = 56 bytes (see ario-gar
230
+ // state/mod.rs::GatewaySlot).
231
+ const SLOT_STRIDE = 56;
232
+ const addresses = [];
233
+ for (let i = 0; i < count && i < 3000; i++) {
234
+ const slotOffset = slotsOffset + i * SLOT_STRIDE;
235
+ const addr = addressDecoder.decode(registryData.subarray(slotOffset, slotOffset + 32));
236
+ addresses.push(addr);
237
+ }
238
+ return addresses;
239
+ }
240
+ // =========================================
241
+ // Protocol info
242
+ // =========================================
243
+ async getInfo() {
244
+ const [[configPda], [epochSettingsPda]] = await Promise.all([
245
+ getArioConfigPDA(this.coreProgram),
246
+ getEpochSettingsPDA(this.garProgram),
247
+ ]);
248
+ const [configAccount, epochAccount] = await Promise.all([
249
+ this.getAccount(configPda),
250
+ this.getAccount(epochSettingsPda),
251
+ ]);
252
+ const config = configAccount.exists
253
+ ? deserializeArioConfig(Buffer.from(configAccount.data))
254
+ : null;
255
+ const epoch = epochAccount.exists
256
+ ? deserializeEpochSettings(Buffer.from(epochAccount.data))
257
+ : null;
258
+ return {
259
+ Ticker: 'ARIO',
260
+ Name: 'AR.IO',
261
+ Logo: '',
262
+ Denomination: 6,
263
+ Handlers: [],
264
+ LastCreatedEpochIndex: 0,
265
+ LastDistributedEpochIndex: 0,
266
+ ...(config
267
+ ? {
268
+ totalSupply: config.totalSupply,
269
+ protocolBalance: config.protocolBalance,
270
+ }
271
+ : {}),
272
+ ...(epoch ? { epochSettings: epoch } : {}),
273
+ };
274
+ }
275
+ async getTokenSupply() {
276
+ const [configPda] = await getArioConfigPDA(this.coreProgram);
277
+ const [garSettingsPda] = await getGarSettingsPDA(this.garProgram);
278
+ const [configAccount, garSettingsAccount] = await Promise.all([
279
+ this.getAccount(configPda),
280
+ this.getAccount(garSettingsPda),
281
+ ]);
282
+ if (!configAccount.exists) {
283
+ throw new Error('ArioConfig account not found');
284
+ }
285
+ const config = deserializeArioConfig(Buffer.from(configAccount.data));
286
+ // Supply counters from GatewaySettings (staked/delegated/withdrawn).
287
+ // Falls back to 0 if GatewaySettings doesn't exist yet or is at the
288
+ // old size (pre-supply-counters layout).
289
+ let staked = 0;
290
+ let delegated = 0;
291
+ let withdrawn = 0;
292
+ if (garSettingsAccount.exists) {
293
+ try {
294
+ const counters = deserializeGarSupplyCounters(Buffer.from(garSettingsAccount.data));
295
+ staked = counters.totalStaked;
296
+ delegated = counters.totalDelegated;
297
+ withdrawn = counters.totalWithdrawn;
298
+ }
299
+ catch {
300
+ // Old-layout account without supply counters — fall back to 0
301
+ }
302
+ }
303
+ return {
304
+ total: config.totalSupply,
305
+ circulating: config.circulatingSupply,
306
+ locked: config.lockedSupply,
307
+ staked,
308
+ delegated,
309
+ withdrawn,
310
+ protocolBalance: config.protocolBalance,
311
+ };
312
+ }
313
+ // =========================================
314
+ // Balance read methods
315
+ // =========================================
316
+ /**
317
+ * Resolve the ARIO SPL mint address from the on-chain `ArioConfig`.
318
+ *
319
+ * `ArioConfig` layout: [8 disc][32 authority][32 mint][...]. We decode
320
+ * the mint at offset 40 and cache it for the lifetime of this instance —
321
+ * the mint never changes once the protocol is deployed.
322
+ */
323
+ async getArioMint() {
324
+ if (this._arioMint)
325
+ return this._arioMint;
326
+ const [configPda] = await getArioConfigPDA(this.coreProgram);
327
+ const account = await this.getAccount(configPda);
328
+ if (!account.exists) {
329
+ throw new Error(`ArioConfig not found at ${configPda} on coreProgram ${this.coreProgram} — is the program deployed and initialized?`);
330
+ }
331
+ const data = Buffer.from(account.data);
332
+ const mint = addressDecoder.decode(data.subarray(40, 72));
333
+ this._arioMint = mint;
334
+ return mint;
335
+ }
336
+ /**
337
+ * Liquid ARIO balance for an address.
338
+ *
339
+ * On Solana the ARIO token is a real SPL mint, so the canonical liquid
340
+ * balance lives on the user's Associated Token Account — *not* the
341
+ * `ario-core::Balance` PDA. The Balance PDA is only populated by the
342
+ * one-shot AO-to-Solana migration importer for legacy snapshot accounts;
343
+ * spending it requires a separate claim flow that mints/transfers SPL
344
+ * tokens to the user's ATA. Steady-state instructions like `buy_name`,
345
+ * gateway/delegate stake, and ARIO transfers all move SPL tokens, so the
346
+ * ATA is what every UI and on-chain caller cares about.
347
+ *
348
+ * Returns 0 if the user has no ATA initialized yet.
349
+ */
350
+ async getBalance({ address: owner, }) {
351
+ const mint = await this.getArioMint();
352
+ const ata = await getAssociatedTokenAddressKit(mint, address(owner));
353
+ const account = await this.getAccount(ata);
354
+ if (!account.exists)
355
+ return 0;
356
+ // SPL Token Account layout: [0..32]=mint, [32..64]=owner, [64..72]=amount(u64 LE), …
357
+ const data = account.data;
358
+ if (data.length < 72)
359
+ return 0;
360
+ // NOTE: avoid `Buffer.readBigUInt64LE` — some browser bundlers (notably
361
+ // arns-react's Vite output) strip the BigInt readers from the
362
+ // `buffer@6.0.3` shim's prototype. Manual little-endian u64 decode is
363
+ // portable across every JS runtime.
364
+ let amount = 0n;
365
+ for (let i = 7; i >= 0; i--) {
366
+ amount = (amount << 8n) | BigInt(data[64 + i]);
367
+ }
368
+ // ARIO supply caps at 1B * 1e6 mARIO ≈ 2^50, well under Number.MAX_SAFE_INTEGER.
369
+ return Number(amount);
370
+ }
371
+ /**
372
+ * Enumerate liquid ARIO balances by querying the SPL Token program for
373
+ * every initialized token account on the ARIO mint.
374
+ *
375
+ * Filters: token-account size = 165, mint at offset 0. We then decode
376
+ * `owner` (offset 32) and `amount` (offset 64) from each.
377
+ */
378
+ async getBalances(params) {
379
+ const mint = await this.getArioMint();
380
+ const filters = [
381
+ { dataSize: 165n },
382
+ {
383
+ memcmp: {
384
+ offset: 0n,
385
+ bytes: mint,
386
+ encoding: 'base58',
387
+ },
388
+ },
389
+ ];
390
+ const result = (await this.rpc
391
+ .getProgramAccounts(TOKEN_PROGRAM_ADDRESS, {
392
+ commitment: this.commitment,
393
+ encoding: 'base64',
394
+ filters,
395
+ })
396
+ .send());
397
+ const items = [];
398
+ for (const entry of result) {
399
+ try {
400
+ const data = Buffer.from(entry.account.data[0], 'base64');
401
+ if (data.length < 72)
402
+ continue;
403
+ const ownerAddress = addressDecoder.decode(data.subarray(32, 64));
404
+ const amount = Number(data.readBigUInt64LE(64));
405
+ if (amount > 0) {
406
+ items.push({ address: ownerAddress, balance: amount });
407
+ }
408
+ }
409
+ catch {
410
+ // Skip malformed accounts
411
+ }
412
+ }
413
+ return paginate(items, params);
414
+ }
415
+ // =========================================
416
+ // Vault read methods
417
+ // =========================================
418
+ async getVault({ address: owner, vaultId, }) {
419
+ const [pda] = await getVaultPDA(address(owner), BigInt(vaultId), this.coreProgram);
420
+ const account = await this.getAccount(pda);
421
+ if (!account.exists) {
422
+ throw new Error(`Vault not found for ${owner}:${vaultId}`);
423
+ }
424
+ const vault = deserializeVault(Buffer.from(account.data));
425
+ return {
426
+ balance: vault.balance,
427
+ startTimestamp: secToMs(vault.startTimestamp),
428
+ endTimestamp: secToMs(vault.endTimestamp),
429
+ controller: vault.controller,
430
+ };
431
+ }
432
+ async getVaults(params) {
433
+ const accounts = await this.getAccountsByDiscriminator(this.coreProgram, VAULT_DISCRIMINATOR);
434
+ const items = [];
435
+ for (const { pubkey, data } of accounts) {
436
+ try {
437
+ const vault = deserializeVault(data);
438
+ items.push({
439
+ address: vault.owner,
440
+ vaultId: pubkey,
441
+ balance: vault.balance,
442
+ startTimestamp: secToMs(vault.startTimestamp),
443
+ endTimestamp: secToMs(vault.endTimestamp),
444
+ controller: vault.controller,
445
+ });
446
+ }
447
+ catch {
448
+ // Skip malformed accounts
449
+ }
450
+ }
451
+ return paginate(items, params);
452
+ }
453
+ // =========================================
454
+ // Gateway read methods
455
+ // =========================================
456
+ async getGateway({ address: addr }) {
457
+ const [pda] = await getGatewayPDA(address(addr), this.garProgram);
458
+ const account = await this.getAccount(pda);
459
+ if (!account.exists) {
460
+ throw new Error(`Gateway not found for operator ${addr}`);
461
+ }
462
+ const gw = deserializeGateway(Buffer.from(account.data));
463
+ const { operator: _, ...gateway } = gw;
464
+ return toMsTimestamps(gateway);
465
+ }
466
+ async getGateways(params) {
467
+ const [registryPda] = await getGatewayRegistryPDA(this.garProgram);
468
+ const registryAccount = await this.getAccount(registryPda);
469
+ if (!registryAccount.exists) {
470
+ return paginate([], params);
471
+ }
472
+ const registryData = Buffer.from(registryAccount.data);
473
+ const count = registryData.readUInt32LE(40);
474
+ const slotsOffset = 48;
475
+ // GatewaySlot = address(32) + composite_weight(8) + start_timestamp(8)
476
+ // + status(1) + _padding(7) = 56 bytes (see ario-gar
477
+ // state/mod.rs::GatewaySlot). A previous off-by-16-bytes-per-slot
478
+ // stride silently read garbage for slots 1+, returning at most
479
+ // one gateway no matter how many had joined.
480
+ const SLOT_STRIDE = 56;
481
+ const gatewayAddresses = [];
482
+ for (let i = 0; i < count && i < 3000; i++) {
483
+ const slotOffset = slotsOffset + i * SLOT_STRIDE;
484
+ const addr = addressDecoder.decode(registryData.subarray(slotOffset, slotOffset + 32));
485
+ if (addr !== DEFAULT_ADDRESS) {
486
+ gatewayAddresses.push(addr);
487
+ }
488
+ }
489
+ // Batch fetch gateway PDAs (kit has no hard limit but keep 100-at-a-time
490
+ // for sensible RPC request sizes).
491
+ const allItems = [];
492
+ for (let i = 0; i < gatewayAddresses.length; i += 100) {
493
+ const batch = gatewayAddresses.slice(i, i + 100);
494
+ const pdas = await Promise.all(batch.map(async (addr) => (await getGatewayPDA(addr, this.garProgram))[0]));
495
+ const accounts = await fetchEncodedAccounts(this.rpc, pdas, {
496
+ commitment: this.commitment,
497
+ });
498
+ for (const acct of accounts) {
499
+ if (!acct.exists)
500
+ continue;
501
+ try {
502
+ const gw = deserializeGateway(Buffer.from(acct.data));
503
+ allItems.push(toMsTimestamps({ ...gw, gatewayAddress: gw.operator }));
504
+ }
505
+ catch {
506
+ // Skip malformed
507
+ }
508
+ }
509
+ }
510
+ return paginate(allItems, params);
511
+ }
512
+ async getGatewayDelegates(params) {
513
+ const gateway = address(params.address);
514
+ // Filter delegations by gateway pubkey at offset 8 (after discriminator)
515
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, DELEGATION_DISCRIMINATOR, [
516
+ {
517
+ memcmp: { offset: 8n, bytes: gateway, encoding: 'base58' },
518
+ },
519
+ ]);
520
+ // Fetch this gateway's current reward accumulator so we can return live
521
+ // balances (raw `Delegation.amount` is stale between settlements — see
522
+ // INVARIANTS.md and `computeLiveDelegationBalance`).
523
+ const accumulators = await this.getGatewayAccumulators([gateway]);
524
+ const cumulative = accumulators.get(gateway) ?? 0n;
525
+ const items = [];
526
+ for (const { data } of accounts) {
527
+ try {
528
+ const del = deserializeDelegation(data);
529
+ items.push({
530
+ address: del.delegator,
531
+ delegatedStake: computeLiveDelegationBalance({
532
+ delegatedStake: del.delegatedStake,
533
+ rewardDebt: del.rewardDebt,
534
+ cumulativeRewardPerToken: cumulative,
535
+ }),
536
+ startTimestamp: secToMs(del.startTimestamp),
537
+ });
538
+ }
539
+ catch {
540
+ // Skip malformed
541
+ }
542
+ }
543
+ return paginate(items, params);
544
+ }
545
+ async getGatewayDelegateAllowList(params) {
546
+ const gateway = address(params.address);
547
+ // Filter allowlist entries by gateway pubkey at offset 8
548
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, ALLOWLIST_ENTRY_DISCRIMINATOR, [
549
+ {
550
+ memcmp: { offset: 8n, bytes: gateway, encoding: 'base58' },
551
+ },
552
+ ]);
553
+ const items = [];
554
+ for (const { data } of accounts) {
555
+ try {
556
+ const entry = deserializeAllowlist(data);
557
+ items.push(entry.delegate);
558
+ }
559
+ catch {
560
+ // Skip malformed
561
+ }
562
+ }
563
+ return paginate(items, params);
564
+ }
565
+ async getDelegations(params) {
566
+ const delegator = address(params.address);
567
+ // Filter delegations by delegator pubkey at offset 40 (8 disc + 32 gateway)
568
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, DELEGATION_DISCRIMINATOR, [
569
+ {
570
+ memcmp: {
571
+ offset: 40n,
572
+ bytes: delegator,
573
+ encoding: 'base58',
574
+ },
575
+ },
576
+ ]);
577
+ const decoded = [];
578
+ for (const { pubkey, data } of accounts) {
579
+ try {
580
+ decoded.push({
581
+ pubkey: pubkey,
582
+ del: deserializeDelegation(data),
583
+ });
584
+ }
585
+ catch {
586
+ // Skip malformed
587
+ }
588
+ }
589
+ // Batch-fetch each referenced gateway's reward accumulator so we can
590
+ // return live balances. See INVARIANTS.md and `computeLiveDelegationBalance`.
591
+ const accumulators = await this.getGatewayAccumulators(decoded.map(({ del }) => del.gateway));
592
+ const items = decoded.map(({ pubkey, del }) => ({
593
+ type: 'stake',
594
+ gatewayAddress: del.gateway,
595
+ delegationId: pubkey,
596
+ startTimestamp: secToMs(del.startTimestamp),
597
+ balance: computeLiveDelegationBalance({
598
+ delegatedStake: del.delegatedStake,
599
+ rewardDebt: del.rewardDebt,
600
+ cumulativeRewardPerToken: accumulators.get(del.gateway) ?? 0n,
601
+ }),
602
+ }));
603
+ return paginate(items, params);
604
+ }
605
+ async getAllowedDelegates(params) {
606
+ return this.getGatewayDelegateAllowList(params);
607
+ }
608
+ async getGatewayVaults(params) {
609
+ const gateway = address(params.address);
610
+ // Withdrawal: disc(8) + owner(32) + withdrawal_id(8) + gateway(32)
611
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, WITHDRAWAL_DISCRIMINATOR, [
612
+ {
613
+ memcmp: { offset: 48n, bytes: gateway, encoding: 'base58' },
614
+ },
615
+ ]);
616
+ const items = [];
617
+ for (const { pubkey, data } of accounts) {
618
+ try {
619
+ const w = deserializeWithdrawal(data);
620
+ if (!w.isDelegate) {
621
+ items.push({
622
+ cursorId: pubkey,
623
+ vaultId: w.vaultId,
624
+ balance: w.balance,
625
+ startTimestamp: secToMs(w.startTimestamp),
626
+ endTimestamp: secToMs(w.endTimestamp),
627
+ });
628
+ }
629
+ }
630
+ catch {
631
+ // Skip malformed
632
+ }
633
+ }
634
+ return paginate(items, params);
635
+ }
636
+ // =========================================
637
+ // ArNS read methods
638
+ // =========================================
639
+ async getArNSRecord({ name }) {
640
+ const [pda] = await getArnsRecordPDA(name, this.arnsProgram);
641
+ const account = await this.getAccount(pda);
642
+ if (!account.exists) {
643
+ throw new Error(`ArNS record not found: ${name}`);
644
+ }
645
+ const record = deserializeArnsRecord(Buffer.from(account.data));
646
+ const { name: _, owner: __, ...nameData } = record;
647
+ return nameData;
648
+ }
649
+ async getArNSRecords(params) {
650
+ // `processId` is the only filter the AO backend supports today and the
651
+ // only one that maps to a fixed-offset memcmp on `ArnsRecord` (the
652
+ // `ant` field, see `ARNS_RECORD_ANT_OFFSET`). When supplied we
653
+ // dispatch through the bulk-by-mint path so the RPC does the
654
+ // filtering instead of streaming every record back to the client.
655
+ const filterMints = normalizeProcessIdFilter(params?.filters?.processId);
656
+ if (filterMints.length > 0) {
657
+ const items = await this.fetchArnsRecordsByAntMints(filterMints);
658
+ return paginate(items, params);
659
+ }
660
+ const accounts = await this.getAccountsByDiscriminator(this.arnsProgram, ARNS_RECORD_DISCRIMINATOR);
661
+ const items = [];
662
+ for (const { data } of accounts) {
663
+ try {
664
+ items.push(arnsRecordToWithName(deserializeArnsRecord(data)));
665
+ }
666
+ catch {
667
+ // Skip accounts that don't match
668
+ }
669
+ }
670
+ return paginate(items, params);
671
+ }
672
+ /**
673
+ * Fetch every `ArnsRecord` whose `ant` field equals one of `mints`.
674
+ *
675
+ * Issues one `getProgramAccounts` per mint with a memcmp filter at
676
+ * `ARNS_RECORD_ANT_OFFSET`, in parallel. Cheaper than scanning the
677
+ * whole registry as soon as the caller has fewer mints than the
678
+ * registry has records (today the break-even is ≈ a few hundred
679
+ * mints against ≈ 4k records, and rises as the registry grows).
680
+ *
681
+ * The shape mirrors `getArNSRecord` / `getArNSRecords` — same
682
+ * `AoArNSNameDataWithName` items, no pagination wrapper. Callers
683
+ * that want pagination should drive it via `getArNSRecords({
684
+ * filters: { processId: mints } })` instead.
685
+ */
686
+ async getArNSRecordsByAntMints({ mints, }) {
687
+ return this.fetchArnsRecordsByAntMints(mints);
688
+ }
689
+ async fetchArnsRecordsByAntMints(mints) {
690
+ const unique = Array.from(new Set(mints));
691
+ if (unique.length === 0)
692
+ return [];
693
+ // Parallel fan-out: one filtered gPA per mint. Each request is
694
+ // selective (matches at most one record on a healthy registry),
695
+ // so the marginal cost is mostly the round trip; major RPCs index
696
+ // memcmp filters at stable offsets, keeping this O(N) in network
697
+ // round trips rather than O(N) in registry size.
698
+ const perMint = await Promise.all(unique.map((mint) => this.getAccountsByDiscriminator(this.arnsProgram, ARNS_RECORD_DISCRIMINATOR, [
699
+ {
700
+ memcmp: {
701
+ offset: BigInt(ARNS_RECORD_ANT_OFFSET),
702
+ bytes: mint,
703
+ encoding: 'base58',
704
+ },
705
+ },
706
+ ])));
707
+ const items = [];
708
+ const seen = new Set();
709
+ for (const accounts of perMint) {
710
+ for (const { pubkey, data } of accounts) {
711
+ const key = String(pubkey);
712
+ if (seen.has(key))
713
+ continue;
714
+ seen.add(key);
715
+ try {
716
+ items.push(arnsRecordToWithName(deserializeArnsRecord(data)));
717
+ }
718
+ catch {
719
+ // Skip malformed
720
+ }
721
+ }
722
+ }
723
+ return items;
724
+ }
725
+ /**
726
+ * Resolve every ArNS record currently controlled by `address`.
727
+ *
728
+ * Mirrors the AO backend: walk the on-chain ANT ACL for the wallet
729
+ * (`Owned ∪ Controlled`), then issue point-queries against the
730
+ * ArNS registry for those mints. This is semantically *not* a query
731
+ * over `ArnsRecord.owner` — that field is a write-once "purchase
732
+ * receipt" and never reflects current control on Solana (see
733
+ * ISSUES.md). Authoritative control flows through the ANT NFT
734
+ * owner / `AntControllers`, which is exactly what the ACL
735
+ * indexes.
736
+ */
737
+ async getArNSRecordsForAddress(params) {
738
+ const registry = new SolanaANTRegistryReadable({
739
+ rpc: this.rpc,
740
+ commitment: this.commitment,
741
+ logger: this.logger,
742
+ antProgramId: this.antProgram,
743
+ });
744
+ const { Owned = [], Controlled = [] } = await registry.accessControlList({
745
+ address: params.address,
746
+ });
747
+ const mints = Array.from(new Set([...Owned, ...Controlled]));
748
+ if (mints.length === 0) {
749
+ return {
750
+ items: [],
751
+ hasMore: false,
752
+ nextCursor: undefined,
753
+ limit: params.limit ?? 100,
754
+ totalItems: 0,
755
+ sortOrder: params.sortOrder ?? 'asc',
756
+ };
757
+ }
758
+ const items = await this.fetchArnsRecordsByAntMints(mints);
759
+ return paginate(items, params);
760
+ }
761
+ async getArNSReservedNames(params) {
762
+ const accounts = await this.getAccountsByDiscriminator(this.arnsProgram, RESERVED_NAME_DISCRIMINATOR);
763
+ const items = [];
764
+ for (const { data } of accounts) {
765
+ try {
766
+ const reserved = deserializeReservedName(data);
767
+ items.push({
768
+ name: reserved.name,
769
+ target: reserved.target,
770
+ endTimestamp: typeof reserved.endTimestamp === 'number'
771
+ ? secToMs(reserved.endTimestamp)
772
+ : reserved.endTimestamp,
773
+ });
774
+ }
775
+ catch {
776
+ // Skip malformed
777
+ }
778
+ }
779
+ return paginate(items, params);
780
+ }
781
+ async getArNSReservedName({ name, }) {
782
+ const [pda] = await getReservedNamePDA(name, this.arnsProgram);
783
+ const account = await this.getAccount(pda);
784
+ if (!account.exists) {
785
+ throw new Error(`Reserved name not found: ${name}`);
786
+ }
787
+ const reserved = deserializeReservedName(Buffer.from(account.data));
788
+ return {
789
+ target: reserved.target,
790
+ endTimestamp: typeof reserved.endTimestamp === 'number'
791
+ ? secToMs(reserved.endTimestamp)
792
+ : reserved.endTimestamp,
793
+ };
794
+ }
795
+ async getArNSReturnedNames(params) {
796
+ const accounts = await this.getAccountsByDiscriminator(this.arnsProgram, RETURNED_NAME_DISCRIMINATOR);
797
+ const items = [];
798
+ for (const { data } of accounts) {
799
+ try {
800
+ items.push(toMsTimestamps(deserializeReturnedName(data)));
801
+ }
802
+ catch {
803
+ // Skip malformed
804
+ }
805
+ }
806
+ return paginate(items, params);
807
+ }
808
+ async getArNSReturnedName({ name, }) {
809
+ const [pda] = await getReturnedNamePDA(name, this.arnsProgram);
810
+ const account = await this.getAccount(pda);
811
+ if (!account.exists) {
812
+ throw new Error(`Returned name not found: ${name}`);
813
+ }
814
+ return toMsTimestamps(deserializeReturnedName(Buffer.from(account.data)));
815
+ }
816
+ // =========================================
817
+ // Epoch read methods
818
+ // =========================================
819
+ async getEpochSettings() {
820
+ const [pda] = await getEpochSettingsPDA(this.garProgram);
821
+ const account = await this.getAccount(pda);
822
+ if (!account.exists) {
823
+ throw new Error('Epoch settings account not found');
824
+ }
825
+ return deserializeEpochSettings(Buffer.from(account.data));
826
+ }
827
+ /**
828
+ * Resolve an EpochInput to an epoch index number.
829
+ * - undefined: returns current epoch index from EpochSettings
830
+ * - { epochIndex }: returns directly
831
+ * - { timestamp }: computes from genesis timestamp and epoch duration
832
+ */
833
+ async resolveEpochIndex(epoch) {
834
+ if (epoch && 'epochIndex' in epoch) {
835
+ return epoch.epochIndex;
836
+ }
837
+ const [pda] = await getEpochSettingsPDA(this.garProgram);
838
+ const account = await this.getAccount(pda);
839
+ if (!account.exists)
840
+ throw new Error('EpochSettings account not found');
841
+ const settings = deserializeEpochSettingsFull(Buffer.from(account.data));
842
+ if (!epoch) {
843
+ // On-chain `current_epoch_index` is "NEXT epoch to be created"
844
+ // (incremented inside `create_epoch` AFTER the PDA is initialized
845
+ // — see programs/ario-gar/src/instructions/epoch.rs:161). The
846
+ // currently-active epoch is therefore one back. Floor at 0 for
847
+ // the pre-bootstrap edge case where no epochs have been created
848
+ // yet. Without this adjustment, every call to getEpoch(undefined)
849
+ // sits in the cranker's close_epoch ↔ create_epoch gap and throws
850
+ // "Epoch N not found" — which broke ContractEpochSource on a
851
+ // live cluster (May 2026 devnet).
852
+ return Math.max(0, settings.currentEpochIndex - 1);
853
+ }
854
+ // { timestamp } — compute epoch index. The public API takes `timestamp`
855
+ // in JS milliseconds (matching the AO contract convention), but
856
+ // genesisTimestamp/epochDuration come straight off chain in seconds, so
857
+ // normalize to seconds before doing the division.
858
+ const tsSeconds = Math.floor(epoch.timestamp / 1000);
859
+ const elapsed = tsSeconds - settings.genesisTimestamp;
860
+ return Math.floor(elapsed / settings.epochDuration);
861
+ }
862
+ /** Fetch and deserialize an Epoch account by index */
863
+ async fetchEpoch(epochIndex) {
864
+ const [pda] = await getEpochPDA(epochIndex, this.garProgram);
865
+ const account = await this.getAccount(pda);
866
+ if (!account.exists) {
867
+ throw new Error(`Epoch ${epochIndex} not found`);
868
+ }
869
+ return deserializeEpoch(Buffer.from(account.data));
870
+ }
871
+ async getEpoch(epoch) {
872
+ const epochIndex = await this.resolveEpochIndex(epoch);
873
+ const epochData = await this.fetchEpoch(epochIndex);
874
+ // Build prescribed observers list (only up to observerCount)
875
+ const prescribedObservers = [];
876
+ for (let i = 0; i < epochData.observerCount; i++) {
877
+ const observerAddress = epochData.prescribedObservers[i];
878
+ const gatewayAddress = epochData.prescribedObserverGateways[i];
879
+ if (observerAddress === DEFAULT_ADDRESS)
880
+ continue;
881
+ // Try to fetch gateway data for weights
882
+ let weights = {
883
+ stakeWeight: 0,
884
+ tenureWeight: 0,
885
+ gatewayRewardRatioWeight: 0,
886
+ observerRewardRatioWeight: 0,
887
+ gatewayPerformanceRatio: 0,
888
+ observerPerformanceRatio: 0,
889
+ compositeWeight: 0,
890
+ normalizedCompositeWeight: 0,
891
+ };
892
+ let stake = 0;
893
+ let startTimestamp = 0;
894
+ try {
895
+ const gw = await this.getGateway({ address: gatewayAddress });
896
+ weights = gw.weights;
897
+ stake = gw.operatorStake;
898
+ // gw.startTimestamp is already converted to ms by getGateway.
899
+ startTimestamp = gw.startTimestamp;
900
+ }
901
+ catch {
902
+ // Gateway may no longer exist
903
+ }
904
+ prescribedObservers.push({
905
+ gatewayAddress: gatewayAddress,
906
+ observerAddress: observerAddress,
907
+ stake,
908
+ startTimestamp,
909
+ ...weights,
910
+ });
911
+ }
912
+ // Build prescribed names list by resolving hashes → ArnsRecord PDAs
913
+ const prescribedNames = [];
914
+ const zeroHash = Buffer.alloc(32);
915
+ for (let i = 0; i < epochData.nameCount; i++) {
916
+ const nameHash = epochData.prescribedNameHashes[i];
917
+ if (!nameHash || nameHash.equals(zeroHash))
918
+ continue;
919
+ try {
920
+ const [recordPda] = await getArnsRecordPDAFromHash(nameHash, this.arnsProgram);
921
+ const recordAccount = await this.getAccount(recordPda);
922
+ if (recordAccount.exists) {
923
+ const record = deserializeArnsRecord(Buffer.from(recordAccount.data));
924
+ prescribedNames.push(record.name);
925
+ }
926
+ }
927
+ catch {
928
+ // Record may have been removed
929
+ }
930
+ }
931
+ // Build observations from Observation PDAs
932
+ const observations = await this.getObservations({ epochIndex });
933
+ // Build distribution totals
934
+ const distributions = {
935
+ totalEligibleGateways: epochData.activeGatewayCount,
936
+ totalEligibleRewards: epochData.totalEligibleRewards,
937
+ totalEligibleObserverReward: epochData.perObserverReward * epochData.observerCount,
938
+ totalEligibleGatewayReward: epochData.perGatewayReward * epochData.activeGatewayCount,
939
+ };
940
+ return {
941
+ epochIndex,
942
+ startHeight: 0, // Solana doesn't use AO block heights
943
+ startTimestamp: secToMs(epochData.startTimestamp),
944
+ endTimestamp: secToMs(epochData.endTimestamp),
945
+ distributionTimestamp: secToMs(epochData.endTimestamp),
946
+ observations,
947
+ prescribedObservers,
948
+ prescribedNames,
949
+ distributions,
950
+ arnsStats: {
951
+ totalReturnedNames: 0,
952
+ totalActiveNames: 0,
953
+ totalGracePeriodNames: 0,
954
+ totalReservedNames: 0,
955
+ },
956
+ };
957
+ }
958
+ async getCurrentEpoch() {
959
+ return this.getEpoch(undefined);
960
+ }
961
+ async getPrescribedObservers(epoch) {
962
+ const epochData = await this.getEpoch(epoch);
963
+ return epochData.prescribedObservers;
964
+ }
965
+ async getPrescribedNames(epoch) {
966
+ const epochIndex = await this.resolveEpochIndex(epoch);
967
+ const epochData = await this.fetchEpoch(epochIndex);
968
+ const names = [];
969
+ const zeroHash = Buffer.alloc(32);
970
+ for (let i = 0; i < epochData.nameCount; i++) {
971
+ const nameHash = epochData.prescribedNameHashes[i];
972
+ if (!nameHash || nameHash.equals(zeroHash))
973
+ continue;
974
+ try {
975
+ const [recordPda] = await getArnsRecordPDAFromHash(nameHash, this.arnsProgram);
976
+ const recordAccount = await this.getAccount(recordPda);
977
+ if (recordAccount.exists) {
978
+ const record = deserializeArnsRecord(Buffer.from(recordAccount.data));
979
+ names.push(record.name);
980
+ }
981
+ }
982
+ catch {
983
+ // Record may have been removed
984
+ }
985
+ }
986
+ return names;
987
+ }
988
+ async getObservations(epoch) {
989
+ const epochIndex = await this.resolveEpochIndex(epoch);
990
+ // Fetch all Observation accounts for this epoch
991
+ const epochIndexBuf = Buffer.alloc(8);
992
+ epochIndexBuf.writeBigUInt64LE(BigInt(epochIndex));
993
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, OBSERVATION_DISCRIMINATOR, [
994
+ {
995
+ memcmp: {
996
+ offset: 8n,
997
+ bytes: bs58.encode(epochIndexBuf),
998
+ encoding: 'base58',
999
+ },
1000
+ },
1001
+ ]);
1002
+ const failureSummaries = {};
1003
+ const reports = {};
1004
+ // Read gateway registry to get index-to-address mapping (matches bitfield order)
1005
+ const gatewayAddresses = await this.getRegistryGatewayAddresses();
1006
+ for (const { data } of accounts) {
1007
+ try {
1008
+ const obs = deserializeObservation(data);
1009
+ reports[obs.observer] = obs.reportTxId;
1010
+ // Parse gateway_results bitmap — 1 = passed, 0 = failed (on-chain convention)
1011
+ for (let i = 0; i < obs.gatewayCount && i < gatewayAddresses.length; i++) {
1012
+ const byteIdx = Math.floor(i / 8);
1013
+ const bitIdx = i % 8;
1014
+ const passed = (obs.gatewayResults[byteIdx] >> bitIdx) & 1;
1015
+ if (!passed) {
1016
+ const gwAddr = gatewayAddresses[i];
1017
+ if (!failureSummaries[gwAddr]) {
1018
+ failureSummaries[gwAddr] = [];
1019
+ }
1020
+ failureSummaries[gwAddr].push(obs.observer);
1021
+ }
1022
+ }
1023
+ }
1024
+ catch {
1025
+ // Skip malformed
1026
+ }
1027
+ }
1028
+ return { failureSummaries, reports };
1029
+ }
1030
+ async getDistributions(epoch) {
1031
+ const epochIndex = await this.resolveEpochIndex(epoch);
1032
+ const epochData = await this.fetchEpoch(epochIndex);
1033
+ return {
1034
+ totalEligibleGateways: epochData.activeGatewayCount,
1035
+ totalEligibleRewards: epochData.totalEligibleRewards,
1036
+ totalEligibleObserverReward: epochData.perObserverReward * epochData.observerCount,
1037
+ totalEligibleGatewayReward: epochData.perGatewayReward * epochData.activeGatewayCount,
1038
+ };
1039
+ }
1040
+ async getEligibleEpochRewards(epoch, params) {
1041
+ const epochIndex = await this.resolveEpochIndex(epoch);
1042
+ const epochData = await this.fetchEpoch(epochIndex);
1043
+ const items = [];
1044
+ // Each gateway operator gets a gateway reward
1045
+ const gatewayAccounts = await this.getAccountsByDiscriminator(this.garProgram, GATEWAY_DISCRIMINATOR);
1046
+ for (const { data } of gatewayAccounts) {
1047
+ try {
1048
+ const gw = deserializeGateway(data);
1049
+ if (gw.status !== 'joined')
1050
+ continue;
1051
+ items.push({
1052
+ type: 'operatorReward',
1053
+ recipient: gw.operator,
1054
+ eligibleReward: epochData.perGatewayReward,
1055
+ gatewayAddress: gw.operator,
1056
+ cursorId: gw.operator,
1057
+ });
1058
+ }
1059
+ catch {
1060
+ // skip
1061
+ }
1062
+ }
1063
+ // Each prescribed observer gets an observer reward
1064
+ for (let i = 0; i < epochData.observerCount; i++) {
1065
+ const observerAddr = epochData.prescribedObservers[i];
1066
+ const gatewayAddr = epochData.prescribedObserverGateways[i];
1067
+ if (observerAddr === DEFAULT_ADDRESS)
1068
+ continue;
1069
+ items.push({
1070
+ type: 'operatorReward',
1071
+ recipient: gatewayAddr,
1072
+ eligibleReward: epochData.perObserverReward,
1073
+ gatewayAddress: gatewayAddr,
1074
+ cursorId: `${gatewayAddr}-observer`,
1075
+ });
1076
+ }
1077
+ return paginate(items, params);
1078
+ }
1079
+ // =========================================
1080
+ // Pricing / cost read methods
1081
+ // =========================================
1082
+ /**
1083
+ * Compute the token cost for an ArNS operation.
1084
+ *
1085
+ * Mirrors the Rust pricing functions in ario-arns/src/pricing.rs.
1086
+ * Uses BigInt for u128-equivalent overflow-safe arithmetic.
1087
+ */
1088
+ async getTokenCost(params) {
1089
+ const [dfPda] = await getDemandFactorPDA(this.arnsProgram);
1090
+ const dfAccount = await this.getAccount(dfPda);
1091
+ if (!dfAccount.exists)
1092
+ throw new Error('DemandFactor account not found');
1093
+ const df = deserializeDemandFactor(Buffer.from(dfAccount.data));
1094
+ const name = params.name.toLowerCase();
1095
+ const nameLen = Math.min(Math.max(name.length, 1), 51);
1096
+ const baseFee = df.fees[nameLen - 1] ?? df.fees[df.fees.length - 1];
1097
+ // currentDemandFactor is already divided by RATE_SCALE in deserializer,
1098
+ // but we need the raw scaled value for integer math
1099
+ const demandFactorRaw = BigInt(Math.round(df.currentDemandFactor * RATE_SCALE));
1100
+ const scale = BigInt(RATE_SCALE);
1101
+ const bf = BigInt(baseFee);
1102
+ let cost;
1103
+ switch (params.intent) {
1104
+ case 'Buy-Name':
1105
+ case 'Buy-Record': {
1106
+ const purchaseType = params.type ?? 'lease';
1107
+ if (purchaseType === 'permabuy') {
1108
+ cost = (bf * demandFactorRaw * 5n) / scale;
1109
+ }
1110
+ else {
1111
+ const years = BigInt(params.years ?? 1);
1112
+ const annualPct = 200000n;
1113
+ const yearFactor = scale + annualPct * years;
1114
+ cost = (bf * demandFactorRaw * yearFactor) / scale / scale;
1115
+ }
1116
+ try {
1117
+ const returned = await this.getArNSReturnedName({ name });
1118
+ if (returned) {
1119
+ // returned.startTimestamp is in ms (public API convention),
1120
+ // so the rest of this comparison is in ms too.
1121
+ const now = Date.now();
1122
+ const elapsed = now - returned.startTimestamp;
1123
+ const duration = 14 * 86_400_000;
1124
+ if (elapsed < duration) {
1125
+ const remaining = BigInt(duration - elapsed);
1126
+ const dur = BigInt(duration);
1127
+ const pctRemaining = (remaining * scale) / dur;
1128
+ const multiplier = 50n * pctRemaining;
1129
+ cost = (cost * multiplier) / scale;
1130
+ }
1131
+ }
1132
+ }
1133
+ catch {
1134
+ // Not a returned name — no premium
1135
+ }
1136
+ break;
1137
+ }
1138
+ case 'Extend-Lease': {
1139
+ const years = BigInt(params.years ?? 1);
1140
+ const annualPct = 200000n;
1141
+ cost = (bf * demandFactorRaw * annualPct * years) / scale / scale;
1142
+ break;
1143
+ }
1144
+ case 'Increase-Undername-Limit': {
1145
+ const qty = BigInt(params.quantity ?? 1);
1146
+ let isPermabuy = false;
1147
+ try {
1148
+ const record = await this.getArNSRecord({ name });
1149
+ isPermabuy = record.type === 'permabuy';
1150
+ }
1151
+ catch {
1152
+ // default to lease pricing
1153
+ }
1154
+ const pct = isPermabuy ? 5000n : 1000n;
1155
+ cost = (bf * demandFactorRaw * pct * qty) / scale / scale;
1156
+ break;
1157
+ }
1158
+ case 'Upgrade-Name': {
1159
+ const permabuyCost = (bf * demandFactorRaw * 5n) / scale;
1160
+ cost = permabuyCost;
1161
+ break;
1162
+ }
1163
+ case 'Primary-Name-Request': {
1164
+ const primaryBaseFee = BigInt(df.fees[50]);
1165
+ const annualPct = 200000n;
1166
+ const yearFactor = scale + annualPct;
1167
+ cost = (primaryBaseFee * demandFactorRaw * yearFactor) / scale / scale;
1168
+ break;
1169
+ }
1170
+ default:
1171
+ throw new Error(`Unknown intent: ${params.intent}`);
1172
+ }
1173
+ return Number(cost);
1174
+ }
1175
+ async getCostDetails(params) {
1176
+ const tokenCost = await this.getTokenCost(params);
1177
+ const discounts = [];
1178
+ if (params.fromAddress) {
1179
+ try {
1180
+ const gw = await this.getGateway({ address: params.fromAddress });
1181
+ if (gw.status === 'joined') {
1182
+ const discountAmount = Math.floor((tokenCost * 200_000) / RATE_SCALE);
1183
+ discounts.push({
1184
+ name: 'Gateway Operator',
1185
+ discountTotal: discountAmount,
1186
+ multiplier: 0.8,
1187
+ });
1188
+ }
1189
+ }
1190
+ catch {
1191
+ // Not a gateway operator — no discount
1192
+ }
1193
+ }
1194
+ const totalDiscount = discounts.reduce((sum, d) => sum + d.discountTotal, 0);
1195
+ return {
1196
+ tokenCost: tokenCost - totalDiscount,
1197
+ discounts,
1198
+ };
1199
+ }
1200
+ async getRegistrationFees() {
1201
+ const [dfPda] = await getDemandFactorPDA(this.arnsProgram);
1202
+ const account = await this.getAccount(dfPda);
1203
+ if (!account.exists) {
1204
+ throw new Error('DemandFactor account not found');
1205
+ }
1206
+ const df = deserializeDemandFactor(Buffer.from(account.data));
1207
+ const result = {};
1208
+ for (let len = 1; len <= 51; len++) {
1209
+ const baseFee = df.fees[len - 1] ?? 0;
1210
+ result[len] = {
1211
+ lease: {
1212
+ 1: Math.floor(baseFee * (1 + 0.2 * 1) * df.currentDemandFactor),
1213
+ 2: Math.floor(baseFee * (1 + 0.2 * 2) * df.currentDemandFactor),
1214
+ 3: Math.floor(baseFee * (1 + 0.2 * 3) * df.currentDemandFactor),
1215
+ 4: Math.floor(baseFee * (1 + 0.2 * 4) * df.currentDemandFactor),
1216
+ 5: Math.floor(baseFee * (1 + 0.2 * 5) * df.currentDemandFactor),
1217
+ },
1218
+ permabuy: Math.floor(baseFee * 5 * df.currentDemandFactor),
1219
+ };
1220
+ }
1221
+ return result;
1222
+ }
1223
+ async getDemandFactor() {
1224
+ const [pda] = await getDemandFactorPDA(this.arnsProgram);
1225
+ const account = await this.getAccount(pda);
1226
+ if (!account.exists) {
1227
+ throw new Error('DemandFactor account not found');
1228
+ }
1229
+ return deserializeDemandFactor(Buffer.from(account.data))
1230
+ .currentDemandFactor;
1231
+ }
1232
+ async getDemandFactorSettings() {
1233
+ const [pda] = await getDemandFactorPDA(this.arnsProgram);
1234
+ const account = await this.getAccount(pda);
1235
+ if (!account.exists) {
1236
+ throw new Error('DemandFactor account not found');
1237
+ }
1238
+ const df = deserializeDemandFactor(Buffer.from(account.data));
1239
+ return {
1240
+ periodZeroStartTimestamp: df.periodZeroStartTimestamp,
1241
+ movingAvgPeriodCount: 7,
1242
+ periodLengthMs: 86_400 * 1000,
1243
+ demandFactorBaseValue: 1,
1244
+ demandFactorMin: 0.5,
1245
+ demandFactorUpAdjustmentRate: 50,
1246
+ demandFactorDownAdjustmentRate: 25,
1247
+ maxPeriodsAtMinDemandFactor: df.consecutivePeriodsWithMinDemandFactor,
1248
+ criteria: 'revenue',
1249
+ };
1250
+ }
1251
+ // =========================================
1252
+ // Primary name read methods
1253
+ // =========================================
1254
+ async getPrimaryName(params) {
1255
+ // On-chain `PrimaryName` stores only {owner, name, set_at}. The ANT mint
1256
+ // that AoPrimaryName.processId expects lives on the matching ArnsRecord
1257
+ // (looked up by the base name). Both lookup paths below deserialize the
1258
+ // on-chain account and then enrich with the ArnsRecord lookup.
1259
+ const baseNameOf = (n) => {
1260
+ const parts = n.toLowerCase().split('_');
1261
+ return parts.length === 2 ? parts[1] : parts[0];
1262
+ };
1263
+ const enrich = async (pn) => {
1264
+ const rec = await this.getArNSRecord({ name: baseNameOf(pn.name) });
1265
+ return { ...pn, processId: rec.processId };
1266
+ };
1267
+ if ('address' in params) {
1268
+ const [pda] = await getPrimaryNamePDA(address(params.address), this.coreProgram);
1269
+ const account = await this.getAccount(pda);
1270
+ if (!account.exists) {
1271
+ throw new Error(`Primary name not found for address ${params.address}`);
1272
+ }
1273
+ return enrich(deserializePrimaryName(Buffer.from(account.data)));
1274
+ }
1275
+ // Lookup by name — scan all primary name accounts
1276
+ const accounts = await this.getAccountsByDiscriminator(this.coreProgram, PRIMARY_NAME_DISCRIMINATOR);
1277
+ for (const { data } of accounts) {
1278
+ try {
1279
+ const pn = deserializePrimaryName(data);
1280
+ if (pn.name === params.name) {
1281
+ return enrich(pn);
1282
+ }
1283
+ }
1284
+ catch {
1285
+ // Skip malformed
1286
+ }
1287
+ }
1288
+ throw new Error(`Primary name not found: ${params.name}`);
1289
+ }
1290
+ async getPrimaryNameRequest(params) {
1291
+ const [pda] = await getPrimaryNameRequestPDA(address(params.initiator), this.coreProgram);
1292
+ const account = await this.getAccount(pda);
1293
+ if (!account.exists) {
1294
+ throw new Error(`Primary name request not found for ${params.initiator}`);
1295
+ }
1296
+ return deserializePrimaryNameRequest(Buffer.from(account.data));
1297
+ }
1298
+ async getPrimaryNameRequests(params) {
1299
+ const accounts = await this.getAccountsByDiscriminator(this.coreProgram, PRIMARY_NAME_REQUEST_DISCRIMINATOR);
1300
+ const items = [];
1301
+ for (const { data } of accounts) {
1302
+ try {
1303
+ items.push(deserializePrimaryNameRequest(data));
1304
+ }
1305
+ catch {
1306
+ // Skip malformed
1307
+ }
1308
+ }
1309
+ return paginate(items, params);
1310
+ }
1311
+ async getPrimaryNames(params) {
1312
+ const accounts = await this.getAccountsByDiscriminator(this.coreProgram, PRIMARY_NAME_DISCRIMINATOR);
1313
+ // Enrich each on-chain PrimaryName with its ArnsRecord.processId (the
1314
+ // on-chain account doesn't store it; see deserializePrimaryName).
1315
+ // Records that no longer have a matching ArnsRecord are silently
1316
+ // skipped — same forgiveness the per-name lookup already applies.
1317
+ const baseNameOf = (n) => {
1318
+ const parts = n.toLowerCase().split('_');
1319
+ return parts.length === 2 ? parts[1] : parts[0];
1320
+ };
1321
+ const items = [];
1322
+ for (const { data } of accounts) {
1323
+ try {
1324
+ const pn = deserializePrimaryName(data);
1325
+ const rec = await this.getArNSRecord({ name: baseNameOf(pn.name) });
1326
+ items.push({ ...pn, processId: rec.processId });
1327
+ }
1328
+ catch {
1329
+ // Skip malformed or orphaned (ArnsRecord missing).
1330
+ }
1331
+ }
1332
+ return paginate(items, params);
1333
+ }
1334
+ // =========================================
1335
+ // Redelegation fee
1336
+ // =========================================
1337
+ async getRedelegationFee(params) {
1338
+ const { getRedelegationRecordPDA } = await import('./pda.js');
1339
+ const [pda] = await getRedelegationRecordPDA(address(params.address), this.garProgram);
1340
+ const account = await this.getAccount(pda);
1341
+ if (!account.exists) {
1342
+ return { redelegationFeeRate: 0, feeResetTimestamp: 0 };
1343
+ }
1344
+ const record = deserializeRedelegationRecord(Buffer.from(account.data));
1345
+ const now = Math.floor(Date.now() / 1000);
1346
+ if (now >= record.feeResetAt) {
1347
+ return { redelegationFeeRate: 0, feeResetTimestamp: record.feeResetAt };
1348
+ }
1349
+ const feeRate = Math.min(record.redelegationCount * 10, 60);
1350
+ return {
1351
+ redelegationFeeRate: feeRate,
1352
+ feeResetTimestamp: record.feeResetAt,
1353
+ };
1354
+ }
1355
+ // =========================================
1356
+ // Gateway registry settings
1357
+ // =========================================
1358
+ async getGatewayRegistrySettings() {
1359
+ const [pda] = await getGarSettingsPDA(this.garProgram);
1360
+ const account = await this.getAccount(pda);
1361
+ if (!account.exists) {
1362
+ throw new Error('GarSettings account not found');
1363
+ }
1364
+ return deserializeGarSettings(Buffer.from(account.data));
1365
+ }
1366
+ // =========================================
1367
+ // Aggregate queries
1368
+ // =========================================
1369
+ async getAllDelegates(params) {
1370
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, DELEGATION_DISCRIMINATOR);
1371
+ const decoded = [];
1372
+ for (const { pubkey, data } of accounts) {
1373
+ try {
1374
+ decoded.push({
1375
+ pubkey: pubkey,
1376
+ del: deserializeDelegation(data),
1377
+ });
1378
+ }
1379
+ catch {
1380
+ // Skip malformed
1381
+ }
1382
+ }
1383
+ // Batch-fetch each referenced gateway's reward accumulator so we can
1384
+ // return live balances. See INVARIANTS.md and `computeLiveDelegationBalance`.
1385
+ const accumulators = await this.getGatewayAccumulators(decoded.map(({ del }) => del.gateway));
1386
+ const items = decoded.map(({ pubkey, del }) => ({
1387
+ address: del.delegator,
1388
+ gatewayAddress: del.gateway,
1389
+ delegatedStake: computeLiveDelegationBalance({
1390
+ delegatedStake: del.delegatedStake,
1391
+ rewardDebt: del.rewardDebt,
1392
+ cumulativeRewardPerToken: accumulators.get(del.gateway) ?? 0n,
1393
+ }),
1394
+ startTimestamp: secToMs(del.startTimestamp),
1395
+ vaultedStake: 0,
1396
+ cursorId: pubkey,
1397
+ }));
1398
+ return paginate(items, params);
1399
+ }
1400
+ async getAllGatewayVaults(params) {
1401
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, WITHDRAWAL_DISCRIMINATOR);
1402
+ const items = [];
1403
+ for (const { pubkey, data } of accounts) {
1404
+ try {
1405
+ const w = deserializeWithdrawal(data);
1406
+ items.push({
1407
+ cursorId: pubkey,
1408
+ vaultId: w.vaultId,
1409
+ balance: w.balance,
1410
+ startTimestamp: secToMs(w.startTimestamp),
1411
+ endTimestamp: secToMs(w.endTimestamp),
1412
+ gatewayAddress: w.gateway,
1413
+ });
1414
+ }
1415
+ catch {
1416
+ // Skip malformed
1417
+ }
1418
+ }
1419
+ return paginate(items, params);
1420
+ }
1421
+ // =========================================
1422
+ // Prune / cleanup discovery (Solana-only)
1423
+ // =========================================
1424
+ //
1425
+ // These helpers enumerate accounts eligible for the permissionless prune
1426
+ // ix surface (see SolanaARIOWriteable). All read on-chain via
1427
+ // `getProgramAccounts` + the Codama decoders, then post-filter
1428
+ // client-side because most eligibility predicates can't be expressed as
1429
+ // memcmp filters (variable-length names shift offsets; Option<i64>
1430
+ // adds a tag byte). Volume is bounded — the cranker is expected to
1431
+ // call these once per epoch cycle, not per-tx.
1432
+ //
1433
+ // See `docs/CRANKER_PRUNING_PLAN.md` for the design.
1434
+ /**
1435
+ * Enumerate ArnsRecord PDAs whose lease has fully expired
1436
+ * (`end_timestamp + grace_period + return_auction_duration <= now`).
1437
+ * Permabuys (no `end_timestamp`) are excluded. Pass a unix-seconds `now`.
1438
+ */
1439
+ async getExpiredArnsRecords(now) {
1440
+ const [arnsConfigPda] = await getArnsSettingsPDA(this.arnsProgram);
1441
+ const cfgAccount = await this.getAccount(arnsConfigPda);
1442
+ if (!cfgAccount.exists)
1443
+ return [];
1444
+ const cfg = getArnsConfigDecoder().decode(cfgAccount.data);
1445
+ const grace = Number(cfg.gracePeriodSeconds);
1446
+ const auction = Number(cfg.returnAuctionDurationSeconds);
1447
+ const accounts = await this.getAccountsByDiscriminator(this.arnsProgram, ARNS_RECORD_DISCRIMINATOR);
1448
+ const decoder = getArnsRecordDecoder();
1449
+ const out = [];
1450
+ for (const { pubkey, data } of accounts) {
1451
+ try {
1452
+ const r = decoder.decode(data);
1453
+ if (r.endTimestamp.__option !== 'Some')
1454
+ continue;
1455
+ const end = Number(r.endTimestamp.value);
1456
+ if (end + grace + auction <= now) {
1457
+ out.push({
1458
+ pubkey,
1459
+ name: r.name,
1460
+ endTimestamp: r.endTimestamp.value,
1461
+ });
1462
+ }
1463
+ }
1464
+ catch {
1465
+ // skip malformed
1466
+ }
1467
+ }
1468
+ return out;
1469
+ }
1470
+ /**
1471
+ * Enumerate ReturnedName PDAs whose Dutch auction window has fully
1472
+ * elapsed (`returned_at + return_auction_duration <= now`).
1473
+ */
1474
+ async getExpiredReturnedNames(now) {
1475
+ const [arnsConfigPda] = await getArnsSettingsPDA(this.arnsProgram);
1476
+ const cfgAccount = await this.getAccount(arnsConfigPda);
1477
+ if (!cfgAccount.exists)
1478
+ return [];
1479
+ const cfg = getArnsConfigDecoder().decode(cfgAccount.data);
1480
+ const auction = Number(cfg.returnAuctionDurationSeconds);
1481
+ const accounts = await this.getAccountsByDiscriminator(this.arnsProgram, RETURNED_NAME_DISCRIMINATOR);
1482
+ const decoder = getReturnedNameDecoder();
1483
+ const out = [];
1484
+ for (const { pubkey, data } of accounts) {
1485
+ try {
1486
+ const r = decoder.decode(data);
1487
+ if (Number(r.returnedAt) + auction <= now) {
1488
+ out.push({ pubkey, name: r.name, returnedAt: r.returnedAt });
1489
+ }
1490
+ }
1491
+ catch {
1492
+ // skip malformed
1493
+ }
1494
+ }
1495
+ return out;
1496
+ }
1497
+ /**
1498
+ * Enumerate ReservedName PDAs whose `expires_at` has passed.
1499
+ * Permanent reservations (`expires_at: None`) are excluded.
1500
+ */
1501
+ async getExpiredReservations(now) {
1502
+ const accounts = await this.getAccountsByDiscriminator(this.arnsProgram, RESERVED_NAME_DISCRIMINATOR);
1503
+ const decoder = getReservedNameDecoder();
1504
+ const out = [];
1505
+ for (const { pubkey, data } of accounts) {
1506
+ try {
1507
+ const r = decoder.decode(data);
1508
+ if (r.expiresAt.__option !== 'Some')
1509
+ continue;
1510
+ if (Number(r.expiresAt.value) <= now) {
1511
+ out.push({ pubkey, name: r.name });
1512
+ }
1513
+ }
1514
+ catch {
1515
+ // skip malformed
1516
+ }
1517
+ }
1518
+ return out;
1519
+ }
1520
+ /**
1521
+ * Enumerate Gateway PDAs in `Joined` status with
1522
+ * `stats.failed_consecutive >= maxFailures`. These are eligible for
1523
+ * `pruneGateway` (slash + remove from registry).
1524
+ */
1525
+ async getDeficientGateways(maxFailures) {
1526
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, GATEWAY_DISCRIMINATOR);
1527
+ const decoder = getGatewayDecoder();
1528
+ const out = [];
1529
+ for (const { pubkey, data } of accounts) {
1530
+ try {
1531
+ const g = decoder.decode(data);
1532
+ if (g.status !== GatewayStatus.Joined)
1533
+ continue;
1534
+ if (g.stats.failedConsecutive >= maxFailures) {
1535
+ out.push({
1536
+ pubkey,
1537
+ operator: g.operator,
1538
+ failedConsecutive: g.stats.failedConsecutive,
1539
+ });
1540
+ }
1541
+ }
1542
+ catch {
1543
+ // skip malformed
1544
+ }
1545
+ }
1546
+ return out;
1547
+ }
1548
+ /**
1549
+ * Enumerate Gateway PDAs whose `status == Gone` (already left the
1550
+ * network but PDA not yet GC'd). Eligible for `finalizeGone`.
1551
+ */
1552
+ async getGoneGateways() {
1553
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, GATEWAY_DISCRIMINATOR);
1554
+ const decoder = getGatewayDecoder();
1555
+ const out = [];
1556
+ for (const { pubkey, data } of accounts) {
1557
+ try {
1558
+ const g = decoder.decode(data);
1559
+ if (g.status === GatewayStatus.Gone) {
1560
+ out.push({ pubkey, operator: g.operator });
1561
+ }
1562
+ }
1563
+ catch {
1564
+ // skip malformed
1565
+ }
1566
+ }
1567
+ return out;
1568
+ }
1569
+ /**
1570
+ * Enumerate Delegation PDAs with `amount == 0`. Eligible for
1571
+ * `closeEmptyDelegation` (rent refund to the original delegator).
1572
+ */
1573
+ async getEmptyDelegations() {
1574
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, DELEGATION_DISCRIMINATOR);
1575
+ const decoder = getDelegationDecoder();
1576
+ const out = [];
1577
+ for (const { pubkey, data } of accounts) {
1578
+ try {
1579
+ const d = decoder.decode(data);
1580
+ if (d.amount === 0n) {
1581
+ out.push({ pubkey, gateway: d.gateway, delegator: d.delegator });
1582
+ }
1583
+ }
1584
+ catch {
1585
+ // skip malformed
1586
+ }
1587
+ }
1588
+ return out;
1589
+ }
1590
+ /**
1591
+ * Enumerate Withdrawal PDAs with `amount == 0` (drained via
1592
+ * fund-from-withdrawal payments). Eligible for `closeDrainedWithdrawal`
1593
+ * (rent refund to owner).
1594
+ */
1595
+ async getDrainedWithdrawals() {
1596
+ const accounts = await this.getAccountsByDiscriminator(this.garProgram, WITHDRAWAL_DISCRIMINATOR);
1597
+ const decoder = getWithdrawalDecoder();
1598
+ const out = [];
1599
+ for (const { pubkey, data } of accounts) {
1600
+ try {
1601
+ const w = decoder.decode(data);
1602
+ if (w.amount === 0n) {
1603
+ out.push({ pubkey, owner: w.owner, withdrawalId: w.withdrawalId });
1604
+ }
1605
+ }
1606
+ catch {
1607
+ // skip malformed
1608
+ }
1609
+ }
1610
+ return out;
1611
+ }
1612
+ /**
1613
+ * Enumerate Vault PDAs whose `end_timestamp` has passed (eligible for
1614
+ * `releaseVault`). Note: `releaseVault` is owner-signed, so the cranker
1615
+ * can only release its own vaults — the helper still surfaces every
1616
+ * expired vault so other consumers (UIs, indexers) can use it too.
1617
+ */
1618
+ async getExpiredVaults(now) {
1619
+ const accounts = await this.getAccountsByDiscriminator(this.coreProgram, VAULT_DISCRIMINATOR);
1620
+ const decoder = getVaultDecoder();
1621
+ const out = [];
1622
+ for (const { pubkey, data } of accounts) {
1623
+ try {
1624
+ const v = decoder.decode(data);
1625
+ if (Number(v.endTimestamp) <= now) {
1626
+ out.push({
1627
+ pubkey,
1628
+ owner: v.owner,
1629
+ vaultId: v.vaultId,
1630
+ endTimestamp: v.endTimestamp,
1631
+ });
1632
+ }
1633
+ }
1634
+ catch {
1635
+ // skip malformed
1636
+ }
1637
+ }
1638
+ return out;
1639
+ }
1640
+ /**
1641
+ * Enumerate PrimaryNameRequest PDAs whose `expires_at` has passed.
1642
+ * Eligible for `closeExpiredRequest` (rent refund to original initiator).
1643
+ */
1644
+ async getExpiredPrimaryNameRequests(now) {
1645
+ const accounts = await this.getAccountsByDiscriminator(this.coreProgram, PRIMARY_NAME_REQUEST_DISCRIMINATOR);
1646
+ const decoder = getPrimaryNameRequestDecoder();
1647
+ const out = [];
1648
+ for (const { pubkey, data } of accounts) {
1649
+ try {
1650
+ const r = decoder.decode(data);
1651
+ if (Number(r.expiresAt) <= now) {
1652
+ out.push({ pubkey, initiator: r.initiator });
1653
+ }
1654
+ }
1655
+ catch {
1656
+ // skip malformed
1657
+ }
1658
+ }
1659
+ return out;
1660
+ }
1661
+ /**
1662
+ * Read the live `ArnsConfig` (used by the cranker to gate
1663
+ * `pruneExpiredNames` / `pruneReturnedNames` on the
1664
+ * `next_*_prune_timestamp` hints).
1665
+ */
1666
+ async getArnsConfigRaw() {
1667
+ const [pda] = await getArnsSettingsPDA(this.arnsProgram);
1668
+ const account = await this.getAccount(pda);
1669
+ if (!account.exists)
1670
+ return null;
1671
+ const cfg = getArnsConfigDecoder().decode(account.data);
1672
+ return {
1673
+ nextRecordsPruneTimestamp: cfg.nextRecordsPruneTimestamp,
1674
+ nextReturnedNamesPruneTimestamp: cfg.nextReturnedNamesPruneTimestamp,
1675
+ gracePeriodSeconds: cfg.gracePeriodSeconds,
1676
+ returnAuctionDurationSeconds: cfg.returnAuctionDurationSeconds,
1677
+ };
1678
+ }
1679
+ // =========================================
1680
+ // Name resolution (ArNSNameResolver)
1681
+ // =========================================
1682
+ async resolveArNSName({ name }) {
1683
+ const parts = name.split('_');
1684
+ const baseName = parts.length > 1 ? parts[parts.length - 1] : parts[0];
1685
+ const record = await this.getArNSRecord({ name: baseName });
1686
+ // TODO: resolve undername via ANT program when undername !== '@'
1687
+ return {
1688
+ name: baseName,
1689
+ txId: '',
1690
+ type: record.type,
1691
+ processId: record.processId,
1692
+ ttlSeconds: 3600,
1693
+ undernameLimit: record.undernameLimit,
1694
+ };
1695
+ }
1696
+ // =========================================================================
1697
+ // Observer helpers (Solana-only; used by gateway-side report submission)
1698
+ // =========================================================================
1699
+ /**
1700
+ * Resolve the gateway operator pubkey backing a given observer pubkey.
1701
+ * The `ObserverLookup` PDA is written at `join_network` (and rotated by
1702
+ * `update_observer_address`); when present its `gateway` field is the
1703
+ * operator pubkey. Returns `undefined` when the observer isn't
1704
+ * registered on any gateway.
1705
+ */
1706
+ async getObserverLookup(observer) {
1707
+ const [pda] = await getObserverLookupPDA(observer, this.garProgram);
1708
+ const account = await this.getAccount(pda);
1709
+ if (!account.exists)
1710
+ return undefined;
1711
+ const data = Buffer.from(account.data);
1712
+ // Layout: 8 disc + 32 gateway + 1 bump.
1713
+ const gateway = addressDecoder.decode(data.subarray(8, 40));
1714
+ const bump = data.readUInt8(40);
1715
+ return { gateway, bump };
1716
+ }
1717
+ /**
1718
+ * Pre-flight gate for `save_observations` submission. Reads the Epoch
1719
+ * account once and reports whether the given observer pubkey is:
1720
+ * - `prescribed`: in `epoch.prescribed_observers[..observer_count]`
1721
+ * - `observerIdx`: position in the array (matches the `has_observed`
1722
+ * bit index when prescribed)
1723
+ * - `alreadyObserved`: whether the bit at `observerIdx` is set
1724
+ * - `windowOpen`: whether `now < epoch.end_timestamp`
1725
+ *
1726
+ * Use this from a sink/wrapper to skip cheap-to-skip cases before
1727
+ * paying for a transaction simulation that would just bounce.
1728
+ */
1729
+ async getEpochObservationStatus(epochIndex, observer) {
1730
+ const epoch = await this.fetchEpoch(epochIndex);
1731
+ let observerIdx = -1;
1732
+ for (let i = 0; i < epoch.observerCount; i++) {
1733
+ if (epoch.prescribedObservers[i] === observer) {
1734
+ observerIdx = i;
1735
+ break;
1736
+ }
1737
+ }
1738
+ const prescribed = observerIdx !== -1;
1739
+ const alreadyObserved = prescribed &&
1740
+ ((epoch.hasObserved[Math.floor(observerIdx / 8)] >> (observerIdx % 8)) &
1741
+ 1) ===
1742
+ 1;
1743
+ const nowSec = Math.floor(Date.now() / 1000);
1744
+ return {
1745
+ prescribed,
1746
+ observerIdx,
1747
+ alreadyObserved,
1748
+ windowOpen: nowSec < epoch.endTimestamp,
1749
+ endTimestampSec: epoch.endTimestamp,
1750
+ };
1751
+ }
1752
+ }