@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,2215 @@
1
+ /**
2
+ * Solana implementation of AoARIOWrite interface.
3
+ *
4
+ * Extends SolanaARIOReadable with write operations that build and send
5
+ * Solana transactions via Codama-generated instruction builders.
6
+ *
7
+ * All instruction encoding (discriminators, account ordering, Borsh codecs,
8
+ * default value resolution for token/system programs) is delegated to the
9
+ * generated builders in `./generated/{core,gar,arns}/instructions/`. The
10
+ * builders are derived from the on-chain IDL and stay in sync via codegen.
11
+ *
12
+ * This file's job is just to:
13
+ * 1. Translate the AO-style SDK params into the builder's input shape.
14
+ * 2. Pre-derive the PDAs that the *Async builders can't infer (the ones
15
+ * whose seeds depend on runtime state — e.g. the next withdrawal id
16
+ * from the on-chain counter, or the buyer's ATA from a runtime mint).
17
+ * 3. Append remaining_accounts (gateway PDAs, name registry) for the
18
+ * epoch crank instructions, since Codama doesn't generate a typed
19
+ * surface for them.
20
+ */
21
+ import { AccountRole, address, fetchEncodedAccount, getAddressDecoder, } from '@solana/kit';
22
+ import { PurchaseType, getBuyNameFromDelegationInstructionAsync, getBuyNameFromFundingPlanInstructionAsync, getBuyNameFromOperatorStakeInstructionAsync, getBuyNameFromWithdrawalInstructionAsync, getBuyNameInstructionAsync, getBuyReturnedNameFromDelegationInstructionAsync, getBuyReturnedNameFromFundingPlanInstructionAsync, getBuyReturnedNameFromOperatorStakeInstructionAsync, getBuyReturnedNameFromWithdrawalInstructionAsync, getBuyReturnedNameInstructionAsync, getExtendLeaseFromDelegationInstructionAsync, getExtendLeaseFromFundingPlanInstructionAsync, getExtendLeaseFromOperatorStakeInstructionAsync, getExtendLeaseFromWithdrawalInstructionAsync, getExtendLeaseInstructionAsync, getIncreaseUndernameLimitFromDelegationInstructionAsync, getIncreaseUndernameLimitFromFundingPlanInstructionAsync, getIncreaseUndernameLimitFromOperatorStakeInstructionAsync, getIncreaseUndernameLimitFromWithdrawalInstructionAsync, getIncreaseUndernameLimitInstructionAsync, getPruneExpiredNamesInstructionAsync, getPruneExpiredReservationInstruction, getPruneNameToReturnedInstructionAsync, getPruneReturnedNamesInstructionAsync, getReassignNameInstructionAsync, getReleaseNameInstructionAsync, getUpgradeNameFromDelegationInstructionAsync, getUpgradeNameFromFundingPlanInstructionAsync, getUpgradeNameFromOperatorStakeInstructionAsync, getUpgradeNameFromWithdrawalInstructionAsync, getUpgradeNameInstructionAsync, } from '@ar.io/solana-contracts/arns';
23
+ import { FundingSourceKind as GeneratedFundingSourceKindEnum } from '@ar.io/solana-contracts/gar';
24
+ import { buildCreateAtaIdempotentIx, getAssociatedTokenAddressKit, } from './ata.js';
25
+ import { deserializeArnsRecord, deserializeEpochSettingsFull, } from './deserialize.js';
26
+ import { buildFundingPlan as buildFundingPlanCore, buildFundingPlanRemainingAccounts, computeResidueIndexes, predictResidueVaults, } from './funding-plan.js';
27
+ /** Maps the SDK's user-facing FundingSourceKind string union to the
28
+ * Codama-generated enum used by the on-chain ix payload. */
29
+ function toGeneratedFundingSourceSpec(s) {
30
+ const kindMap = {
31
+ balance: GeneratedFundingSourceKindEnum.Balance,
32
+ delegation: GeneratedFundingSourceKindEnum.Delegation,
33
+ operatorStake: GeneratedFundingSourceKindEnum.OperatorStake,
34
+ withdrawal: GeneratedFundingSourceKindEnum.Withdrawal,
35
+ };
36
+ return { kind: kindMap[s.kind], amount: s.amount };
37
+ }
38
+ import { getSyncAttributesInstruction } from '@ar.io/solana-contracts/ant';
39
+ import { getApprovePrimaryNameInstructionAsync, getCloseExpiredRequestInstruction, getCreateVaultInstructionAsync, getExtendVaultInstructionAsync, getIncreaseVaultInstructionAsync, getReleaseVaultInstructionAsync, getRequestAndSetPrimaryNameFromFundingPlanInstructionAsync, getRequestAndSetPrimaryNameInstructionAsync, getRequestPrimaryNameFromFundingPlanInstructionAsync, getRequestPrimaryNameInstructionAsync, getRevokeVaultInstructionAsync, getVaultedTransferInstructionAsync, } from '@ar.io/solana-contracts/core';
40
+ import { getDelegationDecoder, getGatewayDecoder, } from '@ar.io/solana-contracts/gar';
41
+ import { Protocol, getAllowDelegateInstructionAsync, getCancelWithdrawalInstruction, getClaimDelegateFromLeavingGatewayInstructionAsync, getClaimWithdrawalInstructionAsync, getCloseDrainedWithdrawalInstruction, getCloseEmptyDelegationInstruction, getCloseEpochInstructionAsync, getCloseObservationInstructionAsync, getCreateEpochInstructionAsync, getDecreaseDelegateStakeInstructionAsync, getDecreaseOperatorStakeInstructionAsync, getDelegateStakeInstructionAsync, getDisallowDelegateInstructionAsync, getDistributeEpochInstructionAsync, getFinalizeGoneInstructionAsync, getIncreaseOperatorStakeInstructionAsync, getInstantWithdrawalInstructionAsync, getJoinNetworkInstructionAsync, getLeaveNetworkInstructionAsync, getPrescribeEpochInstructionAsync, getPruneGatewayInstructionAsync, getRedelegateStakeInstructionAsync, getSaveObservationsInstructionAsync, getSetAllowlistEnabledInstructionAsync, getTallyWeightsInstructionAsync, getUpdateGatewaySettingsInstructionAsync, } from '@ar.io/solana-contracts/gar';
42
+ import { getTransferCheckedInstruction } from '@solana-program/token';
43
+ import { TOKEN_DECIMALS } from './constants.js';
44
+ import { SolanaARIOReadable } from './io-readable.js';
45
+ import { getAntRecordPDA, getArioConfigPDA, getArnsRecordPDA, getArnsRegistryPDA, getArnsSettingsPDA, getDelegationPDA, getDemandFactorPDA, getEpochPDA, getEpochSettingsPDA, getGarSettingsPDA, getGatewayPDA, getGatewayRegistryPDA, getObservationPDA, getObserverLookupPDA, getPrimaryNamePDA, getPrimaryNameRequestPDA, getPrimaryNameReversePDA, getReservedNamePDA, getReturnedNamePDA, getVaultPDA, getWithdrawalCounterPDA, getWithdrawalPDA, hashName, } from './pda.js';
46
+ import { sendAndConfirm } from './send.js';
47
+ const addressDecoder = getAddressDecoder();
48
+ /** Resolve mARIOToken | number to a plain number */
49
+ function toAmount(qty) {
50
+ if (typeof qty === 'number')
51
+ return qty;
52
+ return qty.valueOf();
53
+ }
54
+ /**
55
+ * Append additional `AccountMeta`s to a Codama-generated instruction.
56
+ *
57
+ * The generated `getXInstruction[Async]` builders return frozen objects with
58
+ * a typed, fixed `accounts` tuple. The Solana program accepts extra
59
+ * `remaining_accounts` for epoch crank ops (gateway PDAs, name registry) and
60
+ * for primary-name authorization (arnsRecord, demandFactor, antRecord — see
61
+ * `_buildPrimaryNameValidationAccounts`), but
62
+ * Codama has no typed surface for them — so we splice them in here.
63
+ */
64
+ function withRemainingAccounts(ix, remaining) {
65
+ const accounts = [
66
+ ...(ix.accounts ?? []),
67
+ ...remaining,
68
+ ];
69
+ return { ...ix, accounts };
70
+ }
71
+ /**
72
+ * Split a primary name into its undername + base parts using the same rule
73
+ * as the on-chain `splitn(2, '_')` in `programs/ario-core/src/instructions/primary_name.rs`:
74
+ * everything before the first '_' is the undername, the rest is the base.
75
+ *
76
+ * Exposed as a top-level helper so it can be unit-tested without spinning up
77
+ * an `SolanaARIOWriteable`. Lowercases the input to match contract behavior.
78
+ */
79
+ export function splitPrimaryName(name) {
80
+ const lower = name.toLowerCase();
81
+ const ix = lower.indexOf('_');
82
+ if (ix === -1) {
83
+ return { isUndername: false, baseName: lower, undername: null };
84
+ }
85
+ return {
86
+ isUndername: true,
87
+ baseName: lower.slice(ix + 1),
88
+ undername: lower.slice(0, ix),
89
+ };
90
+ }
91
+ /**
92
+ * Solana-backed read-write client for the AR.IO protocol.
93
+ *
94
+ * Usage:
95
+ * ```ts
96
+ * import {
97
+ * createSolanaRpc,
98
+ * createSolanaRpcSubscriptions,
99
+ * generateKeyPairSigner,
100
+ * } from '@solana/kit';
101
+ * import { SolanaARIOWriteable } from '@ar.io/sdk/solana';
102
+ *
103
+ * const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
104
+ * const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');
105
+ * const signer = await generateKeyPairSigner();
106
+ * const ario = new SolanaARIOWriteable({ rpc, rpcSubscriptions, signer });
107
+ *
108
+ * await ario.transfer({ target: 'RecipientPubkey...', qty: 100_000_000 });
109
+ * ```
110
+ */
111
+ // =========================================================================
112
+ // save_observations encoding helpers
113
+ // =========================================================================
114
+ // Extracted as pure functions so the bitmap-pack + base64url-decode logic
115
+ // can be unit-tested without standing up the rpc/signer plumbing of the
116
+ // SolanaARIOWriteable class. The on-chain ABI:
117
+ // - gateway_results: [u8; 375] bit i = 1 (pass) / 0 (fail) for the
118
+ // gateway at registry index i.
119
+ // - gateway_count: u16 must equal epoch.active_gateway_count.
120
+ // - report_tx_id: [u8; 32] raw 32-byte Arweave hash (base64url
121
+ // decoded from its 43-char string form).
122
+ /** Build the gateway_results bitmap for save_observations.
123
+ * All bits start as 1 (pass) for the first `registryAddresses.length`
124
+ * positions; positions named in `failedGateways` get cleared to 0; all
125
+ * positions beyond `registryAddresses.length` are 0. */
126
+ export function buildObservationBitmap(registryAddresses, failedGateways) {
127
+ const buf = Buffer.alloc(375, 0xff);
128
+ const failedSet = new Set(failedGateways);
129
+ for (let i = 0; i < registryAddresses.length; i++) {
130
+ if (failedSet.has(registryAddresses[i])) {
131
+ buf[Math.floor(i / 8)] &= ~(1 << (i % 8));
132
+ }
133
+ }
134
+ // Clear bits beyond the active gateway count so the bitmap is exactly
135
+ // the prescribed shape (1s only at indices < gatewayCount that passed).
136
+ for (let i = registryAddresses.length; i < 3000; i++) {
137
+ buf[Math.floor(i / 8)] &= ~(1 << (i % 8));
138
+ }
139
+ return buf;
140
+ }
141
+ /** Encode an Arweave TX ID into the on-chain `[u8; 32]` slot.
142
+ *
143
+ * An Arweave TX ID **is** a 32-byte SHA-256 hash; the 43-char base64url
144
+ * string is just its presentation encoding. We decode here so the
145
+ * on-chain bytes are the raw hash — lossless and trivially reversible
146
+ * via base64url-encode on the consumer side. Without this, on-chain
147
+ * bytes alone couldn't be used to look up the original report bundle
148
+ * on permaweb (the whole point of recording the txid for auditability).
149
+ *
150
+ * Empty / undefined input → 32 zero bytes ("no permaweb archive
151
+ * configured for this submission" — the report still lives off-chain
152
+ * in the observer's local sinks but isn't anchored on Arweave).
153
+ *
154
+ * Throws on malformed input: the base64url string must be exactly 43
155
+ * chars and decode to 32 bytes. Strict validation here is desirable —
156
+ * silently truncating or accepting bad input would erode the
157
+ * auditability that the field exists for.
158
+ */
159
+ export function encodeReportTxId(reportTxId) {
160
+ const out = Buffer.alloc(32);
161
+ if (reportTxId === undefined || reportTxId === '') {
162
+ return out;
163
+ }
164
+ // base64url → base64. The 43-char Arweave form has no padding; add it
165
+ // back so Node's `Buffer.from(_, 'base64')` accepts the input.
166
+ const padded = reportTxId
167
+ .replace(/-/g, '+')
168
+ .replace(/_/g, '/')
169
+ .padEnd(Math.ceil(reportTxId.length / 4) * 4, '=');
170
+ // Reject non-base64url chars up front — `Buffer.from` silently
171
+ // tolerates them, which would mask typos.
172
+ if (!/^[A-Za-z0-9+/=]+$/.test(padded)) {
173
+ throw new Error(`reportTxId contains non-base64url characters: "${reportTxId}". ` +
174
+ `Expected a 43-char Arweave TX ID using A-Z, a-z, 0-9, -, _.`);
175
+ }
176
+ const decoded = Buffer.from(padded, 'base64');
177
+ if (decoded.length !== 32) {
178
+ throw new Error(`reportTxId must be a 43-char base64url Arweave TX ID decoding to 32 bytes; ` +
179
+ `got ${reportTxId.length} chars decoding to ${decoded.length} bytes.`);
180
+ }
181
+ decoded.copy(out);
182
+ return out;
183
+ }
184
+ export class SolanaARIOWriteable extends SolanaARIOReadable {
185
+ signer;
186
+ rpcSubscriptions;
187
+ constructor(config) {
188
+ super(config);
189
+ this.signer = config.signer;
190
+ this.rpcSubscriptions = config.rpcSubscriptions;
191
+ }
192
+ /** The signer's on-chain address. */
193
+ get signerAddress() {
194
+ return this.signer.address;
195
+ }
196
+ async sendTransaction(instructions, computeUnitLimit = 400_000) {
197
+ return sendAndConfirm({
198
+ rpc: this.rpc,
199
+ rpcSubscriptions: this.rpcSubscriptions,
200
+ signer: this.signer,
201
+ instructions,
202
+ commitment: this.commitment,
203
+ computeUnitLimit,
204
+ });
205
+ }
206
+ /** Helper to get the ARIO mint and treasury from ArioConfig */
207
+ async getCoreConfig() {
208
+ const [configPda] = await getArioConfigPDA(this.coreProgram);
209
+ const account = await fetchEncodedAccount(this.rpc, configPda, {
210
+ commitment: this.commitment,
211
+ });
212
+ if (!account.exists)
213
+ throw new Error('ArioConfig not found');
214
+ const data = Buffer.from(account.data);
215
+ // ArioConfig: [8 disc][32 authority][32 mint][32 arns_program][32 treasury]
216
+ const mint = addressDecoder.decode(data.subarray(40, 72));
217
+ const treasury = addressDecoder.decode(data.subarray(104, 136));
218
+ return { mint, treasury };
219
+ }
220
+ async getMint() {
221
+ return (await this.getCoreConfig()).mint;
222
+ }
223
+ /** Helper to get ArNS config fields (mint and treasury) */
224
+ async getArnsConfig() {
225
+ const [settingsPda] = await getArnsSettingsPDA(this.arnsProgram);
226
+ const account = await fetchEncodedAccount(this.rpc, settingsPda, {
227
+ commitment: this.commitment,
228
+ });
229
+ if (!account.exists)
230
+ throw new Error('ArnsConfig not found');
231
+ const data = Buffer.from(account.data);
232
+ // ArnsConfig layout: [8 disc][32 authority][32 mint][32 treasury]...
233
+ const mint = addressDecoder.decode(data.subarray(40, 72));
234
+ const treasury = addressDecoder.decode(data.subarray(72, 104));
235
+ return { mint, treasury };
236
+ }
237
+ /** Helper to get GAR config fields (mint, stake pool, protocol pool) */
238
+ async getGarConfig() {
239
+ const [settingsPda] = await getGarSettingsPDA(this.garProgram);
240
+ const account = await fetchEncodedAccount(this.rpc, settingsPda, {
241
+ commitment: this.commitment,
242
+ });
243
+ if (!account.exists)
244
+ throw new Error('GarSettings not found');
245
+ const data = Buffer.from(account.data);
246
+ // GarSettings: [8 disc][32 authority][32 mint][8+8+8+8+8+8=48 u64s][4 u32][1 bool]
247
+ // [32 migration_authority][32 stake_token_account][32 protocol_token_account][1 bump]
248
+ const mint = addressDecoder.decode(data.subarray(40, 72));
249
+ const stakeTokenAccount = addressDecoder.decode(data.subarray(157, 189));
250
+ const protocolTokenAccount = addressDecoder.decode(data.subarray(189, 221));
251
+ return { mint, stakeTokenAccount, protocolTokenAccount };
252
+ }
253
+ // =========================================
254
+ // Codama default-PDA injection helpers
255
+ // =========================================
256
+ //
257
+ // Codama's auto-generated `getXInstructionAsync` builders fall back to
258
+ // calling `find<Account>Pda()` (no args) when a "defaultable" account is
259
+ // omitted from the input. Those `find*Pda` helpers default to the
260
+ // **placeholder** program addresses baked into the generated client
261
+ // (`ARioArnsProgXXX...`, `ArioCoreProgXXX...`, etc.), *not* the env- or
262
+ // constructor-overridden program ID we actually deploy at. The result is a
263
+ // PDA derived against the wrong program id, which on-chain shows up as
264
+ // Anchor `AccountNotInitialized` (#3012) for `config` / `demand_factor` /
265
+ // `name_registry` / `settings` / etc.
266
+ //
267
+ // The wrappers below pre-derive each program's defaultable PDAs against
268
+ // the **real** program id and merge them into the input so codama never
269
+ // touches its placeholder defaults. Caller-provided values still win
270
+ // because spread order is `(...defaults, ...input)`.
271
+ /**
272
+ * Inject ARNS default PDAs (config, demandFactor, nameRegistry).
273
+ *
274
+ * Extra fields not consumed by a given builder are harmlessly ignored
275
+ * (codama only reads the named keys from `input`).
276
+ */
277
+ async withArnsDefaults(input) {
278
+ const [config] = await getArnsSettingsPDA(this.arnsProgram);
279
+ const [demandFactor] = await getDemandFactorPDA(this.arnsProgram);
280
+ const [nameRegistry] = await getArnsRegistryPDA(this.arnsProgram);
281
+ return { config, demandFactor, nameRegistry, ...input };
282
+ }
283
+ /** Inject ARIO core default PDAs (config). */
284
+ async withCoreDefaults(input) {
285
+ const [config] = await getArioConfigPDA(this.coreProgram);
286
+ return { config, ...input };
287
+ }
288
+ /** Inject GAR default PDAs (settings, epochSettings, registry). */
289
+ async withGarDefaults(input) {
290
+ const [settings] = await getGarSettingsPDA(this.garProgram);
291
+ const [epochSettings] = await getEpochSettingsPDA(this.garProgram);
292
+ const [registry] = await getGatewayRegistryPDA(this.garProgram);
293
+ return { settings, epochSettings, registry, ...input };
294
+ }
295
+ /** Read WithdrawalCounter's next_id (returns 0n if not yet created) */
296
+ async getNextWithdrawalId(owner) {
297
+ const [counterPda] = await getWithdrawalCounterPDA(owner, this.garProgram);
298
+ const account = await fetchEncodedAccount(this.rpc, counterPda, {
299
+ commitment: this.commitment,
300
+ });
301
+ if (!account.exists)
302
+ return 0n;
303
+ // WithdrawalCounter: [8 disc][32 owner][8 next_id]
304
+ return Buffer.from(account.data).readBigUInt64LE(40);
305
+ }
306
+ // =========================================
307
+ // Token operations (ario-core)
308
+ // =========================================
309
+ async transfer(params, _options) {
310
+ const amount = toAmount(params.qty);
311
+ const recipient = address(params.target);
312
+ const mint = await this.getMint();
313
+ const fromATA = await getAssociatedTokenAddressKit(mint, this.signer.address);
314
+ const toATA = await getAssociatedTokenAddressKit(mint, recipient);
315
+ // SPL `transferChecked` requires the recipient ATA to exist; bundle
316
+ // an idempotent ATA-create so fresh recipients just work. Same
317
+ // pattern as `vaultedTransfer` below.
318
+ const createToAtaIx = buildCreateAtaIdempotentIx(this.signer.address, toATA, recipient, mint);
319
+ // Standard SPL Token `transferChecked`. The custom `ario-core::transfer`
320
+ // ix is deprecated — it added no protocol-level accounting, just wrapped
321
+ // this same CPI plus a `TransferEvent` emission that no major Solana
322
+ // indexer needs (Helius, Solscan, etc. all track SPL transfers natively).
323
+ // See `docs/REMOVE_CUSTOM_TRANSFER_PLAN.md` in `ar-io/solana-ar-io`.
324
+ // `transferChecked` (vs `transfer`) validates the mint + decimals
325
+ // on-chain, preventing cross-mint mistakes.
326
+ const ix = getTransferCheckedInstruction({
327
+ source: fromATA,
328
+ mint,
329
+ destination: toATA,
330
+ authority: this.signer,
331
+ amount,
332
+ decimals: TOKEN_DECIMALS,
333
+ });
334
+ const sig = await this.sendTransaction([createToAtaIx, ix]);
335
+ return { id: sig };
336
+ }
337
+ async vaultedTransfer(params, _options) {
338
+ const amount = toAmount(params.quantity);
339
+ const lockSeconds = Math.floor(params.lockLengthMs / 1000);
340
+ const recipient = address(params.recipient);
341
+ const mint = await this.getMint();
342
+ // Vault PDA depends on the recipient's *current* vault counter id, which
343
+ // the codegen builder can't infer — derive it manually.
344
+ const nextId = await this.getNextVaultId(recipient);
345
+ const [vaultPda] = await getVaultPDA(recipient, nextId, this.coreProgram);
346
+ const senderATA = await getAssociatedTokenAddressKit(mint, this.signer.address);
347
+ const vaultATA = await getAssociatedTokenAddressKit(mint, vaultPda, true);
348
+ const ix = await getVaultedTransferInstructionAsync(await this.withCoreDefaults({
349
+ vault: vaultPda,
350
+ senderTokenAccount: senderATA,
351
+ vaultTokenAccount: vaultATA,
352
+ recipient,
353
+ sender: this.signer,
354
+ amount,
355
+ lockDurationSeconds: lockSeconds,
356
+ revocable: params.revokable ?? false,
357
+ }), { programAddress: this.coreProgram });
358
+ // The on-chain CreateVault / VaultedTransfer constraint is
359
+ // `Account<TokenAccount>` (NOT `init`) — Anchor expects the vault ATA to
360
+ // already exist. Bundle an idempotent CreateAssociatedTokenAccount in
361
+ // the same tx so the caller doesn't need a separate setup step.
362
+ const createVaultAtaIx = buildCreateAtaIdempotentIx(this.signer.address, vaultATA, vaultPda, mint);
363
+ const sig = await this.sendTransaction([createVaultAtaIx, ix]);
364
+ return { id: sig };
365
+ }
366
+ async createVault(params, _options) {
367
+ const amount = toAmount(params.quantity);
368
+ const lockSeconds = Math.floor(params.lockLengthMs / 1000);
369
+ const mint = await this.getMint();
370
+ const nextId = await this.getNextVaultId(this.signer.address);
371
+ const [vaultPda] = await getVaultPDA(this.signer.address, nextId, this.coreProgram);
372
+ const ownerATA = await getAssociatedTokenAddressKit(mint, this.signer.address);
373
+ const vaultATA = await getAssociatedTokenAddressKit(mint, vaultPda, true);
374
+ const ix = await getCreateVaultInstructionAsync(await this.withCoreDefaults({
375
+ vault: vaultPda,
376
+ ownerTokenAccount: ownerATA,
377
+ vaultTokenAccount: vaultATA,
378
+ owner: this.signer,
379
+ amount,
380
+ lockDurationSeconds: lockSeconds,
381
+ }), { programAddress: this.coreProgram });
382
+ // See note in vaultedTransfer above — vault ATA is not init'd by the
383
+ // on-chain handler; bundle the create.
384
+ const createVaultAtaIx = buildCreateAtaIdempotentIx(this.signer.address, vaultATA, vaultPda, mint);
385
+ const sig = await this.sendTransaction([createVaultAtaIx, ix]);
386
+ return { id: sig };
387
+ }
388
+ /** Read VaultCounter's next_id (returns 0n if not yet created). */
389
+ async getNextVaultId(owner) {
390
+ // VaultCounter PDA derivation lives in pda.ts as getVaultCounterPDA.
391
+ const { getVaultCounterPDA } = await import('./pda.js');
392
+ const [counterPda] = await getVaultCounterPDA(owner, this.coreProgram);
393
+ const account = await fetchEncodedAccount(this.rpc, counterPda, {
394
+ commitment: this.commitment,
395
+ });
396
+ if (!account.exists)
397
+ return 0n;
398
+ return Buffer.from(account.data).readBigUInt64LE(40);
399
+ }
400
+ async extendVault(params, _options) {
401
+ const additionalSeconds = Math.floor(params.extendLengthMs / 1000);
402
+ const [vaultPda] = await getVaultPDA(this.signer.address, BigInt(params.vaultId), this.coreProgram);
403
+ const ix = await getExtendVaultInstructionAsync(await this.withCoreDefaults({
404
+ vault: vaultPda,
405
+ owner: this.signer,
406
+ additionalSeconds,
407
+ }), { programAddress: this.coreProgram });
408
+ const sig = await this.sendTransaction([ix]);
409
+ return { id: sig };
410
+ }
411
+ async increaseVault(params, _options) {
412
+ const amount = toAmount(params.quantity);
413
+ const mint = await this.getMint();
414
+ const [vaultPda] = await getVaultPDA(this.signer.address, BigInt(params.vaultId), this.coreProgram);
415
+ const ownerATA = await getAssociatedTokenAddressKit(mint, this.signer.address);
416
+ const vaultATA = await getAssociatedTokenAddressKit(mint, vaultPda, true);
417
+ const ix = await getIncreaseVaultInstructionAsync(await this.withCoreDefaults({
418
+ vault: vaultPda,
419
+ ownerTokenAccount: ownerATA,
420
+ vaultTokenAccount: vaultATA,
421
+ owner: this.signer,
422
+ amount,
423
+ }), { programAddress: this.coreProgram });
424
+ const sig = await this.sendTransaction([ix]);
425
+ return { id: sig };
426
+ }
427
+ async revokeVault(params, _options) {
428
+ const recipient = address(params.recipient);
429
+ const mint = await this.getMint();
430
+ const [vaultPda] = await getVaultPDA(recipient, BigInt(params.vaultId), this.coreProgram);
431
+ const vaultATA = await getAssociatedTokenAddressKit(mint, vaultPda, true);
432
+ const controllerATA = await getAssociatedTokenAddressKit(mint, this.signer.address);
433
+ const ix = await getRevokeVaultInstructionAsync(await this.withCoreDefaults({
434
+ vault: vaultPda,
435
+ vaultTokenAccount: vaultATA,
436
+ controllerTokenAccount: controllerATA,
437
+ controller: this.signer,
438
+ }), { programAddress: this.coreProgram });
439
+ const sig = await this.sendTransaction([ix]);
440
+ return { id: sig };
441
+ }
442
+ // =========================================
443
+ // Gateway operations (ario-gar)
444
+ // =========================================
445
+ async joinNetwork(params, _options) {
446
+ const garConfig = await this.getGarConfig();
447
+ const operatorATA = await getAssociatedTokenAddressKit(garConfig.mint, this.signer.address);
448
+ const observerAddress = params.observerAddress
449
+ ? address(params.observerAddress)
450
+ : this.signer.address;
451
+ const [observerLookupPda] = await getObserverLookupPDA(observerAddress, this.garProgram);
452
+ const ix = await getJoinNetworkInstructionAsync(await this.withGarDefaults({
453
+ operatorTokenAccount: operatorATA,
454
+ stakeTokenAccount: garConfig.stakeTokenAccount,
455
+ observerLookup: observerLookupPda,
456
+ operator: this.signer,
457
+ operatorStake: BigInt(params.operatorStake),
458
+ label: params.label ?? '',
459
+ fqdn: params.fqdn ?? '',
460
+ port: params.port ?? 443,
461
+ protocol: Protocol.Https,
462
+ properties: params.properties ?? null,
463
+ note: params.note ?? null,
464
+ allowDelegatedStaking: params.allowDelegatedStaking === true ||
465
+ params.allowDelegatedStaking === 'allowlist',
466
+ delegateRewardShareRatio: params.delegateRewardShareRatio ?? 0,
467
+ minDelegateStake: params.minDelegatedStake !== undefined
468
+ ? BigInt(params.minDelegatedStake)
469
+ : null,
470
+ observerAddress,
471
+ }), { programAddress: this.garProgram });
472
+ const sig = await this.sendTransaction([ix], 1_000_000);
473
+ return { id: sig };
474
+ }
475
+ async leaveNetwork(_options) {
476
+ // BD-102: leave_network may produce 1 or 2 Withdrawal PDAs. The
477
+ // protected exit vault uses `next_id`; the optional excess vault
478
+ // uses `next_id + 1`. The SDK always derives both PDAs and passes
479
+ // them to the codama-emitted builder — the contract's
480
+ // `Option<UncheckedAccount>` excess slot is consumed only when the
481
+ // post-stake excess is positive. Passing it unconditionally keeps
482
+ // the SDK side stateless (no need to fetch gateway.operator_stake +
483
+ // settings.min_operator_stake to decide).
484
+ const nextId = await this.getNextWithdrawalId(this.signer.address);
485
+ const [exitVaultPda] = await getWithdrawalPDA(this.signer.address, nextId, this.garProgram);
486
+ const [excessVaultPda] = await getWithdrawalPDA(this.signer.address, nextId + 1n, this.garProgram);
487
+ const ix = await getLeaveNetworkInstructionAsync(await this.withGarDefaults({
488
+ withdrawal: exitVaultPda,
489
+ excessWithdrawal: excessVaultPda,
490
+ operator: this.signer,
491
+ }), { programAddress: this.garProgram });
492
+ const sig = await this.sendTransaction([ix], 1_000_000);
493
+ return { id: sig };
494
+ }
495
+ async updateGatewaySettings(params, _options) {
496
+ const ix = await getUpdateGatewaySettingsInstructionAsync(await this.withGarDefaults({
497
+ operator: this.signer,
498
+ label: params.label ?? null,
499
+ fqdn: params.fqdn ?? null,
500
+ port: params.port ?? null,
501
+ // Codama exposes `protocol` as Option<Protocol>. We only ever updated
502
+ // the URL parts above, so leave protocol untouched (None).
503
+ protocol: null,
504
+ properties: params.properties ?? null,
505
+ note: params.note ?? null,
506
+ allowDelegatedStaking: typeof params.allowDelegatedStaking === 'boolean'
507
+ ? params.allowDelegatedStaking
508
+ : null,
509
+ delegateRewardShareRatio: params.delegateRewardShareRatio ?? null,
510
+ minDelegateStake: params.minDelegatedStake !== undefined
511
+ ? BigInt(params.minDelegatedStake)
512
+ : null,
513
+ }), { programAddress: this.garProgram });
514
+ const sig = await this.sendTransaction([ix], 1_000_000);
515
+ return { id: sig };
516
+ }
517
+ async increaseOperatorStake(params, _options) {
518
+ const amount = toAmount(params.increaseQty);
519
+ const garConfig = await this.getGarConfig();
520
+ const operatorATA = await getAssociatedTokenAddressKit(garConfig.mint, this.signer.address);
521
+ const ix = await getIncreaseOperatorStakeInstructionAsync(await this.withGarDefaults({
522
+ operatorTokenAccount: operatorATA,
523
+ stakeTokenAccount: garConfig.stakeTokenAccount,
524
+ operator: this.signer,
525
+ amount,
526
+ }), { programAddress: this.garProgram });
527
+ const sig = await this.sendTransaction([ix], 1_000_000);
528
+ return { id: sig };
529
+ }
530
+ async decreaseOperatorStake(params, _options) {
531
+ const amount = toAmount(params.decreaseQty);
532
+ const nextId = await this.getNextWithdrawalId(this.signer.address);
533
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, nextId, this.garProgram);
534
+ const ix = await getDecreaseOperatorStakeInstructionAsync(await this.withGarDefaults({
535
+ withdrawal: withdrawalPda,
536
+ operator: this.signer,
537
+ amount,
538
+ }), { programAddress: this.garProgram });
539
+ const sig = await this.sendTransaction([ix], 1_000_000);
540
+ return { id: sig };
541
+ }
542
+ async delegateStake(params, _options) {
543
+ const amount = toAmount(params.stakeQty);
544
+ const target = address(params.target);
545
+ const garConfig = await this.getGarConfig();
546
+ const [gatewayPda] = await getGatewayPDA(target, this.garProgram);
547
+ const [delegationPda] = await getDelegationPDA(target, this.signer.address, this.garProgram);
548
+ const delegatorATA = await getAssociatedTokenAddressKit(garConfig.mint, this.signer.address);
549
+ const ix = await getDelegateStakeInstructionAsync(await this.withGarDefaults({
550
+ gateway: gatewayPda,
551
+ delegation: delegationPda,
552
+ delegatorTokenAccount: delegatorATA,
553
+ stakeTokenAccount: garConfig.stakeTokenAccount,
554
+ delegator: this.signer,
555
+ amount,
556
+ }), { programAddress: this.garProgram });
557
+ const sig = await this.sendTransaction([ix], 1_000_000);
558
+ return { id: sig };
559
+ }
560
+ async decreaseDelegateStake(params, _options) {
561
+ const amount = toAmount(params.decreaseQty);
562
+ const target = address(params.target);
563
+ const [gatewayPda] = await getGatewayPDA(target, this.garProgram);
564
+ const [delegationPda] = await getDelegationPDA(target, this.signer.address, this.garProgram);
565
+ const nextId = await this.getNextWithdrawalId(this.signer.address);
566
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, nextId, this.garProgram);
567
+ const ix = await getDecreaseDelegateStakeInstructionAsync(await this.withGarDefaults({
568
+ gateway: gatewayPda,
569
+ delegation: delegationPda,
570
+ withdrawal: withdrawalPda,
571
+ delegator: this.signer,
572
+ amount,
573
+ }), { programAddress: this.garProgram });
574
+ const sig = await this.sendTransaction([ix], 1_000_000);
575
+ return { id: sig };
576
+ }
577
+ async instantWithdrawal(params, _options) {
578
+ const garConfig = await this.getGarConfig();
579
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, BigInt(params.vaultId), this.garProgram);
580
+ const ownerATA = await getAssociatedTokenAddressKit(garConfig.mint, this.signer.address);
581
+ const ix = await getInstantWithdrawalInstructionAsync(await this.withGarDefaults({
582
+ withdrawal: withdrawalPda,
583
+ stakeTokenAccount: garConfig.stakeTokenAccount,
584
+ ownerTokenAccount: ownerATA,
585
+ protocolTokenAccount: garConfig.protocolTokenAccount,
586
+ owner: this.signer,
587
+ }), { programAddress: this.garProgram });
588
+ const sig = await this.sendTransaction([ix], 1_000_000);
589
+ return { id: sig };
590
+ }
591
+ async cancelWithdrawal(params, _options) {
592
+ const gateway = params.gatewayAddress
593
+ ? address(params.gatewayAddress)
594
+ : this.signer.address;
595
+ const [gatewayPda] = await getGatewayPDA(gateway, this.garProgram);
596
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, BigInt(params.vaultId), this.garProgram);
597
+ const isDelegate = gateway !== this.signer.address;
598
+ const delegation = isDelegate
599
+ ? (await getDelegationPDA(gateway, this.signer.address, this.garProgram))[0]
600
+ : undefined;
601
+ const [settingsPda] = await getGarSettingsPDA(this.garProgram);
602
+ const ix = getCancelWithdrawalInstruction({
603
+ settings: settingsPda,
604
+ gateway: gatewayPda,
605
+ withdrawal: withdrawalPda,
606
+ delegation,
607
+ owner: this.signer,
608
+ }, { programAddress: this.garProgram });
609
+ const sig = await this.sendTransaction([ix], 1_000_000);
610
+ return { id: sig };
611
+ }
612
+ async saveObservations(params, _options) {
613
+ let epochIndex;
614
+ if (params.epochIndex !== undefined) {
615
+ epochIndex = params.epochIndex;
616
+ }
617
+ else {
618
+ const [settingsPda] = await getEpochSettingsPDA(this.garProgram);
619
+ const settingsAccount = await fetchEncodedAccount(this.rpc, settingsPda, {
620
+ commitment: this.commitment,
621
+ });
622
+ if (!settingsAccount.exists)
623
+ throw new Error('EpochSettings not found');
624
+ const settings = deserializeEpochSettingsFull(Buffer.from(settingsAccount.data));
625
+ epochIndex = settings.currentEpochIndex;
626
+ }
627
+ // Build the [u8; 375] gateway_results bitfield. On-chain convention:
628
+ // bit set (1) = passed, bit clear (0) = failed.
629
+ let resultsBuf;
630
+ let gatewayCount;
631
+ if (params.gatewayResults) {
632
+ resultsBuf = Buffer.alloc(375);
633
+ resultsBuf.set(params.gatewayResults.subarray(0, 375));
634
+ gatewayCount = params.gatewayCount ?? 0;
635
+ }
636
+ else {
637
+ const registryAddresses = await this.getRegistryGatewayAddresses();
638
+ gatewayCount = registryAddresses.length;
639
+ resultsBuf = buildObservationBitmap(registryAddresses, params.failedGateways);
640
+ }
641
+ const reportTxId = encodeReportTxId(params.reportTxId);
642
+ const ix = await getSaveObservationsInstructionAsync({
643
+ observer: this.signer,
644
+ epochIndex: BigInt(epochIndex),
645
+ gatewayResults: new Uint8Array(resultsBuf),
646
+ gatewayCount,
647
+ reportTxId: new Uint8Array(reportTxId),
648
+ }, { programAddress: this.garProgram });
649
+ const sig = await this.sendTransaction([ix], 1_000_000);
650
+ return { id: sig };
651
+ }
652
+ async redelegateStake(params, _options) {
653
+ const amount = toAmount(params.stakeQty);
654
+ const source = address(params.source);
655
+ const target = address(params.target);
656
+ const garConfig = await this.getGarConfig();
657
+ const [sourceGatewayPda] = await getGatewayPDA(source, this.garProgram);
658
+ const [targetGatewayPda] = await getGatewayPDA(target, this.garProgram);
659
+ const [sourceDelegationPda] = await getDelegationPDA(source, this.signer.address, this.garProgram);
660
+ const [targetDelegationPda] = await getDelegationPDA(target, this.signer.address, this.garProgram);
661
+ const delegatorATA = await getAssociatedTokenAddressKit(garConfig.mint, this.signer.address);
662
+ const ix = await getRedelegateStakeInstructionAsync(await this.withGarDefaults({
663
+ sourceGateway: sourceGatewayPda,
664
+ targetGateway: targetGatewayPda,
665
+ sourceDelegation: sourceDelegationPda,
666
+ targetDelegation: targetDelegationPda,
667
+ delegatorTokenAccount: delegatorATA,
668
+ stakeTokenAccount: garConfig.stakeTokenAccount,
669
+ protocolTokenAccount: garConfig.protocolTokenAccount,
670
+ delegator: this.signer,
671
+ amount,
672
+ }), { programAddress: this.garProgram });
673
+ const sig = await this.sendTransaction([ix], 1_000_000);
674
+ return { id: sig };
675
+ }
676
+ // =========================================
677
+ // ArNS operations (ario-arns)
678
+ // =========================================
679
+ async buyRecord(params, _options) {
680
+ const arnsConfig = await this.getArnsConfig();
681
+ const buyerATA = await getAssociatedTokenAddressKit(arnsConfig.mint, this.signer.address);
682
+ const antPubkey = address(params.processId ?? '11111111111111111111111111111111');
683
+ const [arnsRecord] = await getArnsRecordPDA(params.name, this.arnsProgram);
684
+ const [reservedNameCheck] = await getReservedNamePDA(params.name, this.arnsProgram);
685
+ const [returnedNameCheck] = await getReturnedNamePDA(params.name, this.arnsProgram);
686
+ const buyNameParams = {
687
+ name: params.name,
688
+ purchaseType: params.type === 'permabuy' ? PurchaseType.Permabuy : PurchaseType.Lease,
689
+ years: params.years ?? 1,
690
+ ant: antPubkey,
691
+ };
692
+ // Phase 4 of FUND_FROM_PLAN.md: dispatch on params.fundFrom. The pre-Phase-4
693
+ // path always fell through to the balance-funded `buyName` ix even when
694
+ // CLI-set `--fund-from stakes`; we now route to the corresponding on-chain
695
+ // wrapper for each mode.
696
+ let ix;
697
+ if (params.fundFrom === 'stakes' && params.gatewayAddress) {
698
+ const gatewayAddr = address(params.gatewayAddress);
699
+ const garConfig = await this.getGarConfig();
700
+ const [garSettings] = await getGarSettingsPDA(this.garProgram);
701
+ const [gatewayPda] = await getGatewayPDA(gatewayAddr, this.garProgram);
702
+ const baseShared = {
703
+ config: await this.arnsConfigPda(),
704
+ demandFactor: await this.demandFactorPda(),
705
+ arnsRecord,
706
+ nameRegistry: await this.nameRegistryPda(),
707
+ reservedNameCheck,
708
+ returnedNameCheck,
709
+ garSettings,
710
+ gateway: gatewayPda,
711
+ stakeTokenAccount: garConfig.stakeTokenAccount,
712
+ protocolTokenAccount: arnsConfig.treasury,
713
+ buyer: this.signer,
714
+ garProgram: this.garProgram,
715
+ params: buyNameParams,
716
+ };
717
+ if (params.fundAsOperator) {
718
+ ix = await getBuyNameFromOperatorStakeInstructionAsync(baseShared, {
719
+ programAddress: this.arnsProgram,
720
+ });
721
+ }
722
+ else {
723
+ const [delegationPda] = await getDelegationPDA(gatewayAddr, this.signer.address, this.garProgram);
724
+ ix = await getBuyNameFromDelegationInstructionAsync({ ...baseShared, delegation: delegationPda }, { programAddress: this.arnsProgram });
725
+ }
726
+ }
727
+ else if (params.fundFrom === 'withdrawal' &&
728
+ params.withdrawalId !== undefined) {
729
+ const garConfig = await this.getGarConfig();
730
+ const [garSettings] = await getGarSettingsPDA(this.garProgram);
731
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, params.withdrawalId, this.garProgram);
732
+ ix = await getBuyNameFromWithdrawalInstructionAsync({
733
+ config: await this.arnsConfigPda(),
734
+ demandFactor: await this.demandFactorPda(),
735
+ arnsRecord,
736
+ nameRegistry: await this.nameRegistryPda(),
737
+ reservedNameCheck,
738
+ returnedNameCheck,
739
+ garSettings,
740
+ withdrawal: withdrawalPda,
741
+ stakeTokenAccount: garConfig.stakeTokenAccount,
742
+ protocolTokenAccount: arnsConfig.treasury,
743
+ buyer: this.signer,
744
+ garProgram: this.garProgram,
745
+ params: buyNameParams,
746
+ }, { programAddress: this.arnsProgram });
747
+ }
748
+ else if (params.fundFrom === 'plan' || params.fundFrom === 'any') {
749
+ ix = await this._buildBuyNameFromFundingPlanIx({
750
+ params,
751
+ antPubkey,
752
+ arnsRecord,
753
+ reservedNameCheck,
754
+ returnedNameCheck,
755
+ buyNameParams,
756
+ arnsConfig,
757
+ });
758
+ }
759
+ else {
760
+ // 'balance' or undefined falls through to the original direct-buy path.
761
+ ix = await getBuyNameInstructionAsync(await this.withArnsDefaults({
762
+ arnsRecord,
763
+ buyerTokenAccount: buyerATA,
764
+ protocolTokenAccount: arnsConfig.treasury,
765
+ reservedNameCheck,
766
+ returnedNameCheck,
767
+ buyer: this.signer,
768
+ params: buyNameParams,
769
+ }), { programAddress: this.arnsProgram });
770
+ }
771
+ // Sprint 4 / ADR-016: bundle `ant.sync_attributes` IFF the buyer
772
+ // owns the ANT (preserves BD-096 — non-holder buys defer the trait
773
+ // sync to a later `syncAttributes()` call by the actual owner).
774
+ // Pass `antPubkey` as assetOverride: the ArnsRecord PDA is CREATED
775
+ // by the buy_name ix, so it doesn't exist on-chain at SDK build
776
+ // time — the helper would 404 if it tried to read it.
777
+ const syncIx = await this._buildSyncAttributesIxIfOwner(params.name, antPubkey);
778
+ const sig = await this.sendTransaction(syncIx ? [ix, syncIx] : [ix]);
779
+ return { id: sig };
780
+ }
781
+ /**
782
+ * Resolve a `FundingPlan` for a fee-paying ArNS ix. When `params.sources`
783
+ * is set, use it verbatim (caller-supplied plan); otherwise discover the
784
+ * user's sources and build a plan via the Lua-faithful planner.
785
+ *
786
+ * Throws `InsufficientFundingError` (as a thrown Error with the structured
787
+ * payload as `cause`) when no plan covers `amountNeeded`.
788
+ */
789
+ async _resolveFundingPlan(params, amountNeeded) {
790
+ // `'plan'` is the explicit "I'll supply my own sources, skip discovery"
791
+ // mode (per FUNDING_MODES.md). Fail loudly if a caller picks `'plan'`
792
+ // without sources — pre-2026-05 the SDK silently fell through to
793
+ // discovery, making `'plan'` a synonym for `'any'`. The new semantic
794
+ // matches the doc: `'any'` discovers, `'plan'` uses what you give it.
795
+ if (params.fundFrom === 'plan' && !params.sources?.length) {
796
+ throw new Error("fundFrom: 'plan' requires explicit `sources`. Pass them via " +
797
+ "params.sources, or use fundFrom: 'any' to let the SDK discover " +
798
+ 'and plan automatically.');
799
+ }
800
+ if (params.sources?.length) {
801
+ // Caller supplied an explicit plan; build the FundingPlan envelope
802
+ // around it without source discovery. Each Delegation/OperatorStake
803
+ // source MUST carry an explicit `gateway` field so the executor knows
804
+ // which gateway PDA to slot in. Earlier single-gateway flows used
805
+ // `params.gatewayAddress` as a fallback for the first stake source —
806
+ // we preserve that for back-compat in the explicit-plan path.
807
+ const hasBalance = params.sources.some((s) => s.kind === 'balance');
808
+ const fallbackGateway = params.gatewayAddress
809
+ ? address(params.gatewayAddress)
810
+ : undefined;
811
+ const gatewayPerSource = params.sources.map((s) => {
812
+ if (s.kind !== 'delegation' && s.kind !== 'operatorStake')
813
+ return undefined;
814
+ const explicit = s.gateway;
815
+ if (explicit)
816
+ return address(explicit);
817
+ if (fallbackGateway)
818
+ return fallbackGateway;
819
+ throw new Error('sources includes delegation/operatorStake but no gateway is set on that source and gatewayAddress is unset');
820
+ });
821
+ // Auto-detect residue: for each Delegation source, fetch the live
822
+ // Delegation + Gateway PDAs and compute the post-drain. If it lands
823
+ // in (0, min_delegation_amount), that source will trigger an on-
824
+ // chain residue auto-vault and we must reserve a residue PDA slot.
825
+ const residueDelegationIndexes = await this._detectResidueIndexes(params.sources, gatewayPerSource);
826
+ return {
827
+ sources: params.sources.map((s) => ({
828
+ kind: s.kind,
829
+ amount: s.amount,
830
+ ...(s.withdrawalId !== undefined
831
+ ? { withdrawalId: s.withdrawalId }
832
+ : {}),
833
+ })),
834
+ gatewayPerSource,
835
+ residueDelegationIndexes,
836
+ hasBalanceSource: hasBalance,
837
+ };
838
+ }
839
+ // No explicit sources: discover + plan.
840
+ const arnsConfig = await this.getArnsConfig();
841
+ const { discoverFundingSources } = await import('./funding-plan.js');
842
+ const sources = await discoverFundingSources(this.rpc, this.signer.address, {
843
+ arioMint: arnsConfig.mint,
844
+ garProgram: this.garProgram,
845
+ });
846
+ const plan = buildFundingPlanCore(sources, amountNeeded, {
847
+ fundFrom: params.fundFrom,
848
+ preferGateway: params.gatewayAddress
849
+ ? address(params.gatewayAddress)
850
+ : undefined,
851
+ fundAsOperator: params.fundAsOperator,
852
+ });
853
+ if ('kind' in plan) {
854
+ const err = new Error(plan.message);
855
+ err.cause = plan;
856
+ throw err;
857
+ }
858
+ return plan;
859
+ }
860
+ /**
861
+ * Build a `buy_name_from_funding_plan` ix using the funding-plan module.
862
+ * Resolves per-source PDAs (Delegation, Withdrawal) and the residue-vault
863
+ * PDA prediction in one shot.
864
+ */
865
+ async _buildBuyNameFromFundingPlanIx(args) {
866
+ const garConfig = await this.getGarConfig();
867
+ const [garSettings] = await getGarSettingsPDA(this.garProgram);
868
+ const buyerATA = await getAssociatedTokenAddressKit(args.arnsConfig.mint, this.signer.address);
869
+ const cost = await this._estimateBuyNameCost(args.buyNameParams);
870
+ const plan = await this._resolveFundingPlan(args.params, cost);
871
+ const { remainingAccounts, withdrawalCounter, residueVaultCount } = await this._materializeFundingPlan(args.params, plan);
872
+ return await getBuyNameFromFundingPlanInstructionAsync({
873
+ config: await this.arnsConfigPda(),
874
+ demandFactor: await this.demandFactorPda(),
875
+ arnsRecord: args.arnsRecord,
876
+ nameRegistry: await this.nameRegistryPda(),
877
+ reservedNameCheck: args.reservedNameCheck,
878
+ returnedNameCheck: args.returnedNameCheck,
879
+ garSettings,
880
+ stakeTokenAccount: garConfig.stakeTokenAccount,
881
+ protocolTokenAccount: args.arnsConfig.treasury,
882
+ payerTokenAccount: plan.hasBalanceSource ? buyerATA : undefined,
883
+ buyer: this.signer,
884
+ withdrawalCounter,
885
+ garProgram: this.garProgram,
886
+ params: args.buyNameParams,
887
+ sources: plan.sources.map(toGeneratedFundingSourceSpec),
888
+ discountAccountCount: 0,
889
+ residueVaultCount,
890
+ }, {
891
+ programAddress: this.arnsProgram,
892
+ }).then((ix) => remainingAccounts.length > 0
893
+ ? withRemainingAccounts(ix, remainingAccounts)
894
+ : ix);
895
+ }
896
+ /**
897
+ * For an explicit caller-supplied plan, detect which Delegation sources
898
+ * will trigger an on-chain residue auto-vault. Reads each (Delegation,
899
+ * Gateway) pair in parallel; computes post-drain; flags `(0, min)`.
900
+ *
901
+ * Hard-fails on RPC error or missing PDA — silently skipping would let
902
+ * the on-chain handler reject the tx with `MissingResidueVault` and
903
+ * burn fees. The error message points at remediation.
904
+ */
905
+ async _detectResidueIndexes(sources, gatewayPerSource) {
906
+ const delegationIndexes = sources
907
+ .map((s, i) => ({ s, i }))
908
+ .filter(({ s }) => s.kind === 'delegation');
909
+ if (delegationIndexes.length === 0)
910
+ return [];
911
+ const owner = this.signer.address;
912
+ const reads = await Promise.all(delegationIndexes.map(async ({ i }) => {
913
+ const gateway = gatewayPerSource[i];
914
+ if (!gateway) {
915
+ throw new Error(`funding plan source #${i} is a Delegation but gatewayPerSource[${i}] is undefined; set source.gateway or params.gatewayAddress`);
916
+ }
917
+ const [delegationPda] = await getDelegationPDA(gateway, owner, this.garProgram);
918
+ const [gatewayPda] = await getGatewayPDA(gateway, this.garProgram);
919
+ const [delAcct, gwAcct] = await Promise.all([
920
+ fetchEncodedAccount(this.rpc, delegationPda, {
921
+ commitment: this.commitment,
922
+ }),
923
+ fetchEncodedAccount(this.rpc, gatewayPda, {
924
+ commitment: this.commitment,
925
+ }),
926
+ ]);
927
+ if (!delAcct.exists) {
928
+ throw new Error(`residue auto-detect failed: Delegation PDA ${delegationPda} not found for source #${i} (gateway ${gateway}); ensure the delegation exists or pass an explicit funding plan with residue hints`);
929
+ }
930
+ if (!gwAcct.exists) {
931
+ throw new Error(`residue auto-detect failed: Gateway PDA ${gatewayPda} not found for source #${i}`);
932
+ }
933
+ return { i, delAcct, gwAcct };
934
+ }));
935
+ const delegationDecoder = getDelegationDecoder();
936
+ const gatewayDecoder = getGatewayDecoder();
937
+ const states = new Array(sources.length).fill(undefined);
938
+ for (const { i, delAcct, gwAcct } of reads) {
939
+ const delegation = delegationDecoder.decode(delAcct.data);
940
+ const gateway = gatewayDecoder.decode(gwAcct.data);
941
+ states[i] = {
942
+ delegationAmount: delegation.amount,
943
+ minDelegationAmount: gateway.settings.minDelegationAmount,
944
+ };
945
+ }
946
+ return computeResidueIndexes(sources, states);
947
+ }
948
+ /**
949
+ * Materialize a `FundingPlan` into the on-chain ix's per-source remaining
950
+ * accounts, residue-vault PDAs, and the withdrawal_counter slot. Shared
951
+ * across all 5 ArNS funding-plan ix dispatches and the 2 ario-core
952
+ * primary-name funding-plan dispatches.
953
+ *
954
+ * Throws when the plan has Withdrawal sources whose ids cannot be
955
+ * resolved from either `spec.withdrawalId` (preferred) or
956
+ * `params.withdrawalId` (single-withdrawal back-compat).
957
+ */
958
+ async _materializeFundingPlan(params, plan) {
959
+ // Resolve withdrawalIds: prefer per-source `spec.withdrawalId` (the
960
+ // multi-withdrawal canonical path — discoverFundingSources sets it
961
+ // and explicit caller plans can too); fall back to params.withdrawalId
962
+ // for single-withdrawal CLI back-compat.
963
+ const withdrawalSpecs = (params.sources ?? plan.sources).filter((s) => s.kind === 'withdrawal');
964
+ const withdrawalIds = withdrawalSpecs.map((s, idx) => {
965
+ const specId = s.withdrawalId;
966
+ if (specId !== undefined)
967
+ return BigInt(specId);
968
+ if (params.withdrawalId !== undefined && idx === 0) {
969
+ return BigInt(params.withdrawalId);
970
+ }
971
+ throw new Error(`funding plan Withdrawal source #${idx} has no withdrawalId; set it on the source spec or pass params.withdrawalId for single-withdrawal plans`);
972
+ });
973
+ const { residueVaults, withdrawalCounter } = await predictResidueVaults(this.rpc, this.signer.address, plan, { garProgram: this.garProgram });
974
+ const remainingAccounts = await buildFundingPlanRemainingAccounts(plan, this.signer.address, { withdrawalIds, residueVaults, garProgram: this.garProgram });
975
+ return {
976
+ remainingAccounts: remainingAccounts,
977
+ withdrawalCounter,
978
+ residueVaultCount: residueVaults.length,
979
+ };
980
+ }
981
+ /**
982
+ * Best-effort cost estimation for `buy_name`. Reads the live DemandFactor
983
+ * + ArnsConfig and applies the on-chain pricing math. Used by the funding-
984
+ * plan path so callers don't have to compute cost client-side.
985
+ *
986
+ * The estimate may be 1-2 mARIO higher than the actual on-chain cost when a
987
+ * demand-factor period rolls during the tx; the on-chain handler reads the
988
+ * live demand-factor and verifies sum(sources) == cost, so an overestimate
989
+ * fails fast with `FundingPlanAmountMismatch`. Callers should retry with a
990
+ * fresh estimate on that error.
991
+ */
992
+ async _estimateBuyNameCost(buyNameParams) {
993
+ // Importing the pricing helpers from generated/ would couple the SDK to
994
+ // codegen layout; instead we re-implement the same math (see
995
+ // programs/ario-arns/src/pricing.rs::calculate_registration_fee).
996
+ const [demandFactorPda] = await getDemandFactorPDA(this.arnsProgram);
997
+ const dfAccount = await fetchEncodedAccount(this.rpc, demandFactorPda, {
998
+ commitment: this.commitment,
999
+ });
1000
+ if (!dfAccount.exists)
1001
+ throw new Error('DemandFactor not found');
1002
+ const data = Buffer.from(dfAccount.data);
1003
+ const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
1004
+ const demandFactor = dv.getBigUint64(8, true);
1005
+ // DemandFactor layout (Borsh, packed; ario-arns/src/state/mod.rs):
1006
+ // disc(8) + current_demand_factor(u64) + current_period(u64) +
1007
+ // purchases_this_period(u64) + revenue_this_period(u64) +
1008
+ // consecutive_periods_with_min_demand_factor(u32) +
1009
+ // trailing_period_purchases([u64; 7]) +
1010
+ // trailing_period_revenues([u64; 7]) + fees([u64; 51]) + ...
1011
+ // -> fees starts at 8 + 8 + 8 + 8 + 8 + 4 + 56 + 56 = 156.
1012
+ const FEES_OFFSET = 156;
1013
+ if (data.length < FEES_OFFSET + 51 * 8) {
1014
+ throw new Error('DemandFactor account data too short for fees array');
1015
+ }
1016
+ const nameLen = buyNameParams.name.length;
1017
+ const idx = Math.min(Math.max(nameLen, 1), 51) - 1;
1018
+ const baseFee = dv.getBigUint64(FEES_OFFSET + idx * 8, true);
1019
+ const SCALE = 1000000n; // DEMAND_FACTOR_SCALE
1020
+ if (buyNameParams.purchaseType === PurchaseType.Permabuy) {
1021
+ // Permabuy = base_fee * 20% * 20 (annual share × 20 years cap)
1022
+ const permabuy = (baseFee * 200000n) / SCALE; // 20% annual
1023
+ return (permabuy * 20n * demandFactor) / SCALE;
1024
+ }
1025
+ // Lease: base_fee * (1 + 0.20 * years) * demand_factor
1026
+ const leasePct = SCALE + 200000n * BigInt(buyNameParams.years);
1027
+ return (((baseFee * leasePct) / SCALE) * demandFactor) / SCALE;
1028
+ }
1029
+ async arnsConfigPda() {
1030
+ // The ArNS config (`Settings`) PDA is seeded with `arns_config` — NOT
1031
+ // the `ario_config` seed used by the ario-core `Config` PDA. Earlier
1032
+ // revisions of this helper called `getArioConfigPDA(this.arnsProgram)`
1033
+ // which composes the wrong seed against the right program; the
1034
+ // resulting PDA points at an account that never exists, and every
1035
+ // fund-from-stakes / withdrawal / funding-plan path simulated as
1036
+ // AccountNotInitialized (#3012) on the `config` slot.
1037
+ const [pda] = await getArnsSettingsPDA(this.arnsProgram);
1038
+ return pda;
1039
+ }
1040
+ async demandFactorPda() {
1041
+ const [pda] = await getDemandFactorPDA(this.arnsProgram);
1042
+ return pda;
1043
+ }
1044
+ async nameRegistryPda() {
1045
+ const [pda] = await getArnsRegistryPDA(this.arnsProgram);
1046
+ return pda;
1047
+ }
1048
+ async upgradeRecord(params, _options) {
1049
+ const ix = await this._buildManageStakeIx({
1050
+ params,
1051
+ operation: 'upgrade',
1052
+ });
1053
+ const syncIx = await this._buildSyncAttributesIxIfOwner(params.name);
1054
+ const sig = await this.sendTransaction(syncIx ? [ix, syncIx] : [ix]);
1055
+ return { id: sig };
1056
+ }
1057
+ async syncAttributes(params, _options) {
1058
+ // Public method — caller is asking explicitly to sync. Build the ix
1059
+ // unconditionally; if they don't actually own the ANT, the on-chain
1060
+ // handler returns NotNftHolder. (The bundle path uses
1061
+ // `_buildSyncAttributesIxIfOwner`, which skips when not the owner so
1062
+ // the wrapping arns ix can still succeed for non-holder management
1063
+ // — see BD-095.)
1064
+ const ix = await this._buildSyncAttributesIxUnconditional(params.name);
1065
+ const sig = await this.sendTransaction([ix]);
1066
+ return { id: sig };
1067
+ }
1068
+ /**
1069
+ * Build a `sync_attributes` instruction for `name` IFF the signer is
1070
+ * the current MPL Core asset owner. Returns `null` otherwise.
1071
+ *
1072
+ * Sprint 4 / ADR-016: bundle helper for `buyRecord`, `upgradeRecord`,
1073
+ * `increaseUndernameLimit`, `reassignName`, and `buyReturnedName`.
1074
+ * Returning `null` lets the caller send the arns ix alone — preserves
1075
+ * BD-095 (non-holder ArNS lease management) and BD-096 (deferred
1076
+ * trait sync for non-holder buyers). The actual ANT owner reconciles
1077
+ * state later via the public `syncAttributes()`.
1078
+ *
1079
+ * `extendLease` is NOT a caller of this helper — extend_lease changes
1080
+ * only `end_timestamp`, which isn't mirrored in any Attributes-plugin
1081
+ * trait (BD-095 last row). `releaseName` is also excluded — release_name
1082
+ * closes the ArnsRecord PDA, so a follow-up `sync_attributes` would
1083
+ * fail the PDA-existence check.
1084
+ *
1085
+ * `assetOverride` MUST be set when the bundling ix mutates
1086
+ * `record.ant` mid-tx (i.e. `reassign_name`). The on-chain record
1087
+ * still points at the OLD asset at SDK build time, so without the
1088
+ * override the bundled sync would target the wrong asset and fail
1089
+ * the post-reassign `record.ant == asset.key()` check. The owner
1090
+ * check runs against the supplied asset (= new ANT for reassign),
1091
+ * matching the pre-reshape "new owner reconciles later" semantic.
1092
+ */
1093
+ async _buildSyncAttributesIxIfOwner(name, assetOverride) {
1094
+ let asset;
1095
+ if (assetOverride !== undefined) {
1096
+ asset = assetOverride;
1097
+ }
1098
+ else {
1099
+ const record = await this.getArNSRecord({ name });
1100
+ asset = address(record.processId);
1101
+ }
1102
+ const { fetchMplCoreOwner } = await import('./mpl-core.js');
1103
+ const owner = await fetchMplCoreOwner(this.rpc, asset, {
1104
+ commitment: this.commitment,
1105
+ });
1106
+ if (owner === null || owner !== this.signer.address) {
1107
+ return null;
1108
+ }
1109
+ return this._buildSyncAttributesIxFor(name, asset);
1110
+ }
1111
+ /**
1112
+ * Build a `sync_attributes` instruction unconditionally (no owner
1113
+ * check). Used by the public `syncAttributes()` method, where the
1114
+ * caller is asking explicitly — if they aren't the owner the chain
1115
+ * returns NotNftHolder.
1116
+ */
1117
+ async _buildSyncAttributesIxUnconditional(name) {
1118
+ const record = await this.getArNSRecord({ name });
1119
+ return this._buildSyncAttributesIxFor(name, address(record.processId));
1120
+ }
1121
+ /** Pure builder; no RPC. Used by both gated + unconditional helpers. */
1122
+ async _buildSyncAttributesIxFor(name, asset) {
1123
+ const [arnsRecord] = await getArnsRecordPDA(name, this.arnsProgram);
1124
+ return getSyncAttributesInstruction({
1125
+ asset,
1126
+ payer: this.signer,
1127
+ authority: this.signer,
1128
+ arnsRecord,
1129
+ name,
1130
+ }, { programAddress: this.antProgram });
1131
+ }
1132
+ async extendLease(params, _options) {
1133
+ const ix = await this._buildManageStakeIx({
1134
+ params,
1135
+ operation: 'extend',
1136
+ years: params.years,
1137
+ });
1138
+ // BD-095: extend_lease changes only `end_timestamp`, which isn't
1139
+ // mirrored in any Metaplex Attributes plugin trait. No bundle.
1140
+ const sig = await this.sendTransaction([ix]);
1141
+ return { id: sig };
1142
+ }
1143
+ async increaseUndernameLimit(params, _options) {
1144
+ const ix = await this._buildManageStakeIx({
1145
+ params,
1146
+ operation: 'increaseUndername',
1147
+ quantity: params.increaseCount,
1148
+ });
1149
+ const syncIx = await this._buildSyncAttributesIxIfOwner(params.name);
1150
+ const sig = await this.sendTransaction(syncIx ? [ix, syncIx] : [ix]);
1151
+ return { id: sig };
1152
+ }
1153
+ /**
1154
+ * Shared dispatch helper for the 3 manage variants (upgrade / extend /
1155
+ * increaseUndername). They share the same account shape per the
1156
+ * `manage_from_delegation_accounts!` / `manage_from_operator_stake_accounts!`
1157
+ * macros in `programs/ario-arns/src/instructions/manage_from_stake.rs`.
1158
+ * Only the operation-specific extra args differ (years for extend,
1159
+ * quantity for increaseUndername).
1160
+ */
1161
+ async _buildManageStakeIx(args) {
1162
+ const arnsConfig = await this.getArnsConfig();
1163
+ const callerATA = await getAssociatedTokenAddressKit(arnsConfig.mint, this.signer.address);
1164
+ const [arnsRecord] = await getArnsRecordPDA(args.params.name, this.arnsProgram);
1165
+ // Balance / undefined → original direct-transfer ix (matches pre-Phase-4).
1166
+ if (!args.params.fundFrom ||
1167
+ args.params.fundFrom === 'balance' ||
1168
+ args.params.fundFrom === 'turbo') {
1169
+ const baseAccounts = await this.withArnsDefaults({
1170
+ arnsRecord,
1171
+ callerTokenAccount: callerATA,
1172
+ protocolTokenAccount: arnsConfig.treasury,
1173
+ caller: this.signer,
1174
+ });
1175
+ if (args.operation === 'upgrade') {
1176
+ return getUpgradeNameInstructionAsync(baseAccounts, {
1177
+ programAddress: this.arnsProgram,
1178
+ });
1179
+ }
1180
+ if (args.operation === 'extend') {
1181
+ return getExtendLeaseInstructionAsync({ ...baseAccounts, years: args.years }, { programAddress: this.arnsProgram });
1182
+ }
1183
+ return getIncreaseUndernameLimitInstructionAsync({ ...baseAccounts, quantity: args.quantity }, { programAddress: this.arnsProgram });
1184
+ }
1185
+ // Stake / withdrawal / funding-plan paths share an account skeleton.
1186
+ const garConfig = await this.getGarConfig();
1187
+ const [garSettings] = await getGarSettingsPDA(this.garProgram);
1188
+ const sharedManageBase = {
1189
+ config: await this.arnsConfigPda(),
1190
+ demandFactor: await this.demandFactorPda(),
1191
+ arnsRecord,
1192
+ garSettings,
1193
+ stakeTokenAccount: garConfig.stakeTokenAccount,
1194
+ protocolTokenAccount: arnsConfig.treasury,
1195
+ caller: this.signer,
1196
+ garProgram: this.garProgram,
1197
+ };
1198
+ if (args.params.fundFrom === 'stakes' && args.params.gatewayAddress) {
1199
+ const gatewayAddr = address(args.params.gatewayAddress);
1200
+ const [gatewayPda] = await getGatewayPDA(gatewayAddr, this.garProgram);
1201
+ const stakeBase = { ...sharedManageBase, gateway: gatewayPda };
1202
+ if (args.params.fundAsOperator) {
1203
+ if (args.operation === 'upgrade')
1204
+ return getUpgradeNameFromOperatorStakeInstructionAsync(stakeBase, {
1205
+ programAddress: this.arnsProgram,
1206
+ });
1207
+ if (args.operation === 'extend')
1208
+ return getExtendLeaseFromOperatorStakeInstructionAsync({ ...stakeBase, years: args.years }, { programAddress: this.arnsProgram });
1209
+ return getIncreaseUndernameLimitFromOperatorStakeInstructionAsync({ ...stakeBase, quantity: args.quantity }, { programAddress: this.arnsProgram });
1210
+ }
1211
+ const [delegationPda] = await getDelegationPDA(gatewayAddr, this.signer.address, this.garProgram);
1212
+ const delBase = { ...stakeBase, delegation: delegationPda };
1213
+ if (args.operation === 'upgrade')
1214
+ return getUpgradeNameFromDelegationInstructionAsync(delBase, {
1215
+ programAddress: this.arnsProgram,
1216
+ });
1217
+ if (args.operation === 'extend')
1218
+ return getExtendLeaseFromDelegationInstructionAsync({ ...delBase, years: args.years }, { programAddress: this.arnsProgram });
1219
+ return getIncreaseUndernameLimitFromDelegationInstructionAsync({ ...delBase, quantity: args.quantity }, { programAddress: this.arnsProgram });
1220
+ }
1221
+ if (args.params.fundFrom === 'withdrawal' &&
1222
+ args.params.withdrawalId !== undefined) {
1223
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, args.params.withdrawalId, this.garProgram);
1224
+ const wBase = { ...sharedManageBase, withdrawal: withdrawalPda };
1225
+ if (args.operation === 'upgrade')
1226
+ return getUpgradeNameFromWithdrawalInstructionAsync(wBase, {
1227
+ programAddress: this.arnsProgram,
1228
+ });
1229
+ if (args.operation === 'extend')
1230
+ return getExtendLeaseFromWithdrawalInstructionAsync({ ...wBase, years: args.years }, { programAddress: this.arnsProgram });
1231
+ return getIncreaseUndernameLimitFromWithdrawalInstructionAsync({ ...wBase, quantity: args.quantity }, { programAddress: this.arnsProgram });
1232
+ }
1233
+ if (args.params.fundFrom === 'plan' || args.params.fundFrom === 'any') {
1234
+ // Cost estimation for manage variants: each operation has its own
1235
+ // pricing path. Keep it pragmatic — let the planner build the plan
1236
+ // around the user's desired total (caller can pass explicit sources
1237
+ // to bypass cost estimation entirely).
1238
+ const cost = await this._estimateManageStakeCost({
1239
+ operation: args.operation,
1240
+ name: args.params.name,
1241
+ years: args.years,
1242
+ quantity: args.quantity,
1243
+ });
1244
+ const plan = await this._resolveFundingPlan(args.params, cost);
1245
+ const buyerATA = await getAssociatedTokenAddressKit(arnsConfig.mint, this.signer.address);
1246
+ const { remainingAccounts, withdrawalCounter, residueVaultCount } = await this._materializeFundingPlan(args.params, plan);
1247
+ const fpBase = {
1248
+ config: await this.arnsConfigPda(),
1249
+ demandFactor: await this.demandFactorPda(),
1250
+ arnsRecord,
1251
+ garSettings,
1252
+ stakeTokenAccount: garConfig.stakeTokenAccount,
1253
+ protocolTokenAccount: arnsConfig.treasury,
1254
+ payerTokenAccount: plan.hasBalanceSource ? buyerATA : undefined,
1255
+ caller: this.signer,
1256
+ withdrawalCounter,
1257
+ garProgram: this.garProgram,
1258
+ sources: plan.sources.map(toGeneratedFundingSourceSpec),
1259
+ discountAccountCount: 0,
1260
+ residueVaultCount,
1261
+ };
1262
+ let ix;
1263
+ if (args.operation === 'upgrade')
1264
+ ix = await getUpgradeNameFromFundingPlanInstructionAsync(fpBase, {
1265
+ programAddress: this.arnsProgram,
1266
+ });
1267
+ else if (args.operation === 'extend')
1268
+ ix = await getExtendLeaseFromFundingPlanInstructionAsync({ ...fpBase, years: args.years }, { programAddress: this.arnsProgram });
1269
+ else
1270
+ ix = await getIncreaseUndernameLimitFromFundingPlanInstructionAsync({ ...fpBase, quantity: args.quantity }, { programAddress: this.arnsProgram });
1271
+ return remainingAccounts.length > 0
1272
+ ? withRemainingAccounts(ix, remainingAccounts)
1273
+ : ix;
1274
+ }
1275
+ throw new Error(`unsupported fundFrom mode '${args.params.fundFrom}' for ${args.operation}`);
1276
+ }
1277
+ /**
1278
+ * Cost estimate for manage operations (upgrade / extend / increaseUndername).
1279
+ * Reads the live DemandFactor account + applies the on-chain pricing math.
1280
+ */
1281
+ async _estimateManageStakeCost(args) {
1282
+ const [demandFactorPda] = await getDemandFactorPDA(this.arnsProgram);
1283
+ const dfAccount = await fetchEncodedAccount(this.rpc, demandFactorPda, {
1284
+ commitment: this.commitment,
1285
+ });
1286
+ if (!dfAccount.exists)
1287
+ throw new Error('DemandFactor not found');
1288
+ const data = Buffer.from(dfAccount.data);
1289
+ const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
1290
+ const demandFactor = dv.getBigUint64(8, true);
1291
+ const FEES_OFFSET = 156; // see DemandFactor layout note above
1292
+ const idx = Math.min(Math.max(args.name.length, 1), 51) - 1;
1293
+ const baseFee = dv.getBigUint64(FEES_OFFSET + idx * 8, true);
1294
+ const SCALE = 1000000n;
1295
+ if (args.operation === 'upgrade') {
1296
+ // Permabuy upgrade: 20% × 20 × demand_factor
1297
+ const permabuy = (baseFee * 200000n) / SCALE;
1298
+ return (permabuy * 20n * demandFactor) / SCALE;
1299
+ }
1300
+ if (args.operation === 'extend') {
1301
+ // Lease extension fee: base_fee * 0.20 * years * demand_factor
1302
+ return ((baseFee * 200000n * BigInt(args.years) * demandFactor) /
1303
+ SCALE /
1304
+ SCALE);
1305
+ }
1306
+ // increaseUndername: base_fee * UNDERNAME_LEASE_FEE_PCT * quantity * demand_factor
1307
+ // UNDERNAME_LEASE_FEE_PCT = 1% = 10_000 in RATE_SCALE = 1_000_000.
1308
+ return ((baseFee * 10000n * BigInt(args.quantity) * demandFactor) /
1309
+ SCALE /
1310
+ SCALE);
1311
+ }
1312
+ // =========================================
1313
+ // Primary name operations (ario-core)
1314
+ // =========================================
1315
+ /**
1316
+ * Build the `remaining_accounts` slice + the `antProgramId` arg the
1317
+ * four ario-core primary-name instructions consume. Sprint 2/5
1318
+ * reshape (ADR-016): ario-core no longer reads MPL Core asset bytes.
1319
+ * Authorization is "caller is the AntRecord.owner for this name" via
1320
+ * PDA-seed-pinned lookup.
1321
+ *
1322
+ * Layouts the on-chain handlers expect:
1323
+ * request_primary_name: [arnsRecord, demandFactor]
1324
+ * request_and_set_primary_name: [arnsRecord, demandFactor, antRecord]
1325
+ * approve_primary_name: [arnsRecord, antRecord]
1326
+ * remove_primary_name_for_base_name: [arnsRecord, antRecord(@)]
1327
+ *
1328
+ * `antRecord` keys off the undername part for undernames (e.g.
1329
+ * "blog_arweave" → AntRecord at "blog") or the canonical "@" sentinel
1330
+ * for base names. `removeForBaseName` is special — it always uses "@"
1331
+ * regardless of whether the primary name being removed is an undername,
1332
+ * since the *base* name owner is the one revoking it.
1333
+ *
1334
+ * `antProgram` honors ADR-016 / BD-100 pluggability: the asset's
1335
+ * `ANT Program` Attributes-plugin trait selects which program owns the
1336
+ * AntRecord PDA. Absent / unparseable → canonical fallback. Both the
1337
+ * PDA derivation here and the `ant_program_id` arg the caller passes
1338
+ * to the on-chain ix MUST agree (the handler re-derives and rejects
1339
+ * mismatches).
1340
+ */
1341
+ async _buildPrimaryNameValidationAccounts(name, variant) {
1342
+ const { isUndername, baseName, undername } = splitPrimaryName(name);
1343
+ const [arnsRecordPda] = await getArnsRecordPDA(baseName, this.arnsProgram);
1344
+ const remaining = [
1345
+ { address: arnsRecordPda, role: AccountRole.READONLY },
1346
+ ];
1347
+ // Fee-charging variants need the demand factor for fee scaling.
1348
+ if (variant === 'request' || variant === 'requestAndSet') {
1349
+ const [demandFactorPda] = await getDemandFactorPDA(this.arnsProgram);
1350
+ remaining.push({ address: demandFactorPda, role: AccountRole.READONLY });
1351
+ }
1352
+ // ANT-auth variants need the AntRecord PDA. We have to read the
1353
+ // ArnsRecord first to recover the ANT mint, then read the asset's
1354
+ // `ANT Program` trait (ADR-016 / BD-100) to pick the right program
1355
+ // for the AntRecord PDA derivation.
1356
+ let antProgram = this.antProgram;
1357
+ if (variant !== 'request') {
1358
+ const arnsAccount = await fetchEncodedAccount(this.rpc, arnsRecordPda, {
1359
+ commitment: this.commitment,
1360
+ });
1361
+ if (!arnsAccount.exists) {
1362
+ throw new Error(`ArNS record not found for base name: ${baseName}`);
1363
+ }
1364
+ const arnsRecord = deserializeArnsRecord(Buffer.from(arnsAccount.data));
1365
+ const antMint = address(arnsRecord.processId);
1366
+ const { fetchAntProgramFromAsset } = await import('./mpl-core.js');
1367
+ antProgram =
1368
+ (await fetchAntProgramFromAsset(this.rpc, antMint, {
1369
+ commitment: this.commitment,
1370
+ })) ?? this.antProgram;
1371
+ // removeForBaseName always uses the "@" undername (the base-name
1372
+ // owner's record). The other ANT-auth variants use the undername
1373
+ // part if the primary name is an undername.
1374
+ const antUndername = variant === 'removeForBaseName' || !isUndername || undername === null
1375
+ ? '@'
1376
+ : undername;
1377
+ const [antRecordPda] = await getAntRecordPDA(antMint, antUndername, antProgram);
1378
+ remaining.push({ address: antRecordPda, role: AccountRole.READONLY });
1379
+ }
1380
+ return { remaining, antProgram };
1381
+ }
1382
+ async requestPrimaryName(params, _options) {
1383
+ const coreConfig = await this.getCoreConfig();
1384
+ const signerATA = await getAssociatedTokenAddressKit(coreConfig.mint, this.signer.address);
1385
+ const { remaining } = await this._buildPrimaryNameValidationAccounts(params.name, 'request');
1386
+ // Phase 4 of FUND_FROM_PLAN.md: dispatch primary-name funding via the
1387
+ // funding-plan ix when caller asks for stakes/withdrawal/plan/any. The
1388
+ // direct-transfer ix stays the path for fundFrom='balance' / undefined.
1389
+ let ix;
1390
+ if (!params.fundFrom ||
1391
+ params.fundFrom === 'balance' ||
1392
+ params.fundFrom === 'turbo') {
1393
+ ix = withRemainingAccounts(await getRequestPrimaryNameInstructionAsync(await this.withCoreDefaults({
1394
+ initiatorTokenAccount: signerATA,
1395
+ protocolTokenAccount: coreConfig.treasury,
1396
+ initiator: this.signer,
1397
+ name: params.name,
1398
+ }), { programAddress: this.coreProgram }), remaining);
1399
+ }
1400
+ else {
1401
+ ix = await this._buildPrimaryNameFromFundingPlanIx({
1402
+ params,
1403
+ coreConfig,
1404
+ validationAccounts: remaining,
1405
+ operation: 'request',
1406
+ });
1407
+ }
1408
+ const sig = await this.sendTransaction([ix]);
1409
+ return { id: sig };
1410
+ }
1411
+ async setPrimaryName(params, _options) {
1412
+ // setPrimaryName routes to the on-chain `request_and_set_primary_name`
1413
+ // path — the auto-approve flow when the caller owns the AntRecord
1414
+ // for the matching name (undername part, or "@" for base names).
1415
+ const coreConfig = await this.getCoreConfig();
1416
+ const signerATA = await getAssociatedTokenAddressKit(coreConfig.mint, this.signer.address);
1417
+ const { remaining, antProgram } = await this._buildPrimaryNameValidationAccounts(params.name, 'requestAndSet');
1418
+ let ix;
1419
+ if (!params.fundFrom ||
1420
+ params.fundFrom === 'balance' ||
1421
+ params.fundFrom === 'turbo') {
1422
+ ix = withRemainingAccounts(await getRequestAndSetPrimaryNameInstructionAsync(await this.withCoreDefaults({
1423
+ initiatorTokenAccount: signerATA,
1424
+ protocolTokenAccount: coreConfig.treasury,
1425
+ initiator: this.signer,
1426
+ name: params.name,
1427
+ reverseLookupHash: hashName(params.name),
1428
+ antProgramId: antProgram,
1429
+ }), { programAddress: this.coreProgram }), remaining);
1430
+ }
1431
+ else {
1432
+ ix = await this._buildPrimaryNameFromFundingPlanIx({
1433
+ params,
1434
+ coreConfig,
1435
+ validationAccounts: remaining,
1436
+ operation: 'requestAndSet',
1437
+ antProgramId: antProgram,
1438
+ });
1439
+ }
1440
+ const sig = await this.sendTransaction([ix]);
1441
+ return { id: sig };
1442
+ }
1443
+ /**
1444
+ * Build a `request_primary_name_from_funding_plan` or
1445
+ * `request_and_set_primary_name_from_funding_plan` ix. Forwards both:
1446
+ * - validation accounts (ArnsRecord + DemandFactor [+ ant_asset
1447
+ * [+ AntRecord]]) — passed via remaining_accounts at indices
1448
+ * [0..validation_account_count)
1449
+ * - per-source PDAs from the funding plan — passed at indices
1450
+ * [validation_account_count..)
1451
+ *
1452
+ * The on-chain handler (programs/ario-core/src/instructions/primary_name.rs)
1453
+ * splits remaining_accounts at `validation_account_count` and forwards the
1454
+ * funding-source slice to ario-gar's pay_from_funding_plan via CPI.
1455
+ */
1456
+ async _buildPrimaryNameFromFundingPlanIx(args) {
1457
+ // Estimate the fee — primary-name fee = PRIMARY_NAME_REQUEST_BASE_FEE *
1458
+ // demand_factor / DEMAND_FACTOR_SCALE. Read demand_factor from chain.
1459
+ const [demandFactorPda] = await getDemandFactorPDA(this.arnsProgram);
1460
+ const dfAccount = await fetchEncodedAccount(this.rpc, demandFactorPda, {
1461
+ commitment: this.commitment,
1462
+ });
1463
+ if (!dfAccount.exists)
1464
+ throw new Error('DemandFactor not found');
1465
+ const dv = new DataView(dfAccount.data.buffer, dfAccount.data.byteOffset, dfAccount.data.byteLength);
1466
+ const demandFactor = dv.getBigUint64(8, true);
1467
+ const PRIMARY_NAME_REQUEST_BASE_FEE = 200000n; // 0.2 ARIO in mARIO
1468
+ const SCALE = 1000000n;
1469
+ const fee = (PRIMARY_NAME_REQUEST_BASE_FEE * demandFactor) / SCALE;
1470
+ const plan = await this._resolveFundingPlan(args.params, fee);
1471
+ const garConfig = await this.getGarConfig();
1472
+ const [garSettings] = await getGarSettingsPDA(this.garProgram);
1473
+ const initiatorATA = await getAssociatedTokenAddressKit(args.coreConfig.mint, this.signer.address);
1474
+ const { remainingAccounts: fundingRemaining, withdrawalCounter, residueVaultCount, } = await this._materializeFundingPlan(args.params, plan);
1475
+ const allRemaining = [
1476
+ ...args.validationAccounts,
1477
+ ...fundingRemaining,
1478
+ ];
1479
+ const validationAccountCount = args.validationAccounts.length;
1480
+ const baseFp = {
1481
+ config: await this._coreConfigPda(),
1482
+ garSettings,
1483
+ stakeTokenAccount: garConfig.stakeTokenAccount,
1484
+ protocolTokenAccount: args.coreConfig.treasury,
1485
+ payerTokenAccount: plan.hasBalanceSource ? initiatorATA : undefined,
1486
+ initiator: this.signer,
1487
+ withdrawalCounter,
1488
+ garProgram: this.garProgram,
1489
+ sources: plan.sources.map(toGeneratedFundingSourceSpec),
1490
+ validationAccountCount,
1491
+ residueVaultCount,
1492
+ };
1493
+ let ix;
1494
+ if (args.operation === 'request') {
1495
+ const [requestPda] = await getPrimaryNameRequestPDA(this.signer.address, this.coreProgram);
1496
+ ix = await getRequestPrimaryNameFromFundingPlanInstructionAsync({ ...baseFp, request: requestPda, name: args.params.name }, { programAddress: this.coreProgram });
1497
+ }
1498
+ else {
1499
+ const [primaryNamePda] = await getPrimaryNamePDA(this.signer.address, this.coreProgram);
1500
+ const [primaryNameReversePda] = await getPrimaryNameReversePDA(args.params.name, this.coreProgram);
1501
+ ix = await getRequestAndSetPrimaryNameFromFundingPlanInstructionAsync({
1502
+ ...baseFp,
1503
+ primaryName: primaryNamePda,
1504
+ primaryNameReverse: primaryNameReversePda,
1505
+ name: args.params.name,
1506
+ reverseLookupHash: hashName(args.params.name),
1507
+ antProgramId: args.antProgramId ?? this.antProgram,
1508
+ }, { programAddress: this.coreProgram });
1509
+ }
1510
+ return allRemaining.length > 0
1511
+ ? withRemainingAccounts(ix, allRemaining)
1512
+ : ix;
1513
+ }
1514
+ async _coreConfigPda() {
1515
+ const [pda] = await getArioConfigPDA(this.coreProgram);
1516
+ return pda;
1517
+ }
1518
+ /**
1519
+ * Approve a previously-created primary name request. The signer must be
1520
+ * the AntRecord.owner for the requested name (undername part for
1521
+ * undernames, "@" for base names) — Sprint 2 / ADR-016 reshape.
1522
+ *
1523
+ * Mirrors the on-chain `approve_primary_name` instruction
1524
+ * (`programs/ario-core/src/instructions/primary_name.rs`).
1525
+ * remaining_accounts: [arns_record(base), ant_record(undername | @)].
1526
+ */
1527
+ async approvePrimaryName(params, _options) {
1528
+ const [requestPda] = await getPrimaryNameRequestPDA(params.initiator, this.coreProgram);
1529
+ const [primaryNamePda] = await getPrimaryNamePDA(params.initiator, this.coreProgram);
1530
+ const [primaryNameReversePda] = await getPrimaryNameReversePDA(params.name, this.coreProgram);
1531
+ const { remaining, antProgram } = await this._buildPrimaryNameValidationAccounts(params.name, 'approve');
1532
+ // withCoreDefaults injects `config` as the ArioConfig PDA derived against
1533
+ // *this.coreProgram*. Without it, Codama's `findConfigPda()` fallback
1534
+ // resolves to the source-pinned `ARioCoreProgramXXXX...` placeholder
1535
+ // program id (declare_id! literal pre-anchor-keys-sync), which on any
1536
+ // non-mainnet deployment produces an unallocated PDA → Anchor #3012
1537
+ // AccountNotInitialized on `config`. requestPrimaryName /
1538
+ // requestAndSetPrimaryName already use withCoreDefaults; this was the
1539
+ // last setPrimaryName-family entrypoint missing it.
1540
+ const ix = withRemainingAccounts(await getApprovePrimaryNameInstructionAsync(await this.withCoreDefaults({
1541
+ request: requestPda,
1542
+ initiator: params.initiator,
1543
+ primaryName: primaryNamePda,
1544
+ primaryNameReverse: primaryNameReversePda,
1545
+ nameOwner: this.signer,
1546
+ reverseLookupHash: hashName(params.name),
1547
+ antProgramId: antProgram,
1548
+ }), { programAddress: this.coreProgram }), remaining);
1549
+ const sig = await this.sendTransaction([ix]);
1550
+ return { id: sig };
1551
+ }
1552
+ // =========================================
1553
+ // Vault release (ario-core)
1554
+ // =========================================
1555
+ /** Release tokens from an unlocked vault back to the owner. */
1556
+ async releaseVault(params, _options) {
1557
+ const mint = await this.getMint();
1558
+ const [vaultPda] = await getVaultPDA(this.signer.address, BigInt(params.vaultId), this.coreProgram);
1559
+ const vaultATA = await getAssociatedTokenAddressKit(mint, vaultPda, true);
1560
+ const ownerATA = await getAssociatedTokenAddressKit(mint, this.signer.address);
1561
+ const ix = await getReleaseVaultInstructionAsync(await this.withCoreDefaults({
1562
+ vault: vaultPda,
1563
+ vaultTokenAccount: vaultATA,
1564
+ ownerTokenAccount: ownerATA,
1565
+ owner: this.signer,
1566
+ }), { programAddress: this.coreProgram });
1567
+ const sig = await this.sendTransaction([ix]);
1568
+ return { id: sig };
1569
+ }
1570
+ // =========================================
1571
+ // Close expired primary name request (ario-core)
1572
+ // =========================================
1573
+ /** Close an expired primary name request (permissionless — anyone can call). */
1574
+ async closeExpiredRequest(params, _options) {
1575
+ const initiatorPubkey = address(params.initiator);
1576
+ const [requestPda] = await getPrimaryNameRequestPDA(initiatorPubkey, this.coreProgram);
1577
+ const ix = getCloseExpiredRequestInstruction({
1578
+ request: requestPda,
1579
+ initiator: initiatorPubkey,
1580
+ payer: this.signer,
1581
+ }, { programAddress: this.coreProgram });
1582
+ const sig = await this.sendTransaction([ix]);
1583
+ return { id: sig };
1584
+ }
1585
+ // =========================================
1586
+ // Withdrawal claim (ario-gar)
1587
+ // =========================================
1588
+ /** Claim tokens from a completed withdrawal (after lock period). */
1589
+ async claimWithdrawal(params, _options) {
1590
+ const garConfig = await this.getGarConfig();
1591
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, BigInt(params.withdrawalId), this.garProgram);
1592
+ const ownerATA = await getAssociatedTokenAddressKit(garConfig.mint, this.signer.address);
1593
+ const ix = await getClaimWithdrawalInstructionAsync(await this.withGarDefaults({
1594
+ withdrawal: withdrawalPda,
1595
+ stakeTokenAccount: garConfig.stakeTokenAccount,
1596
+ ownerTokenAccount: ownerATA,
1597
+ owner: this.signer,
1598
+ }), { programAddress: this.garProgram });
1599
+ const sig = await this.sendTransaction([ix], 1_000_000);
1600
+ return { id: sig };
1601
+ }
1602
+ // =========================================
1603
+ // Claim delegation from leaving gateway (ario-gar)
1604
+ // =========================================
1605
+ /** Claim delegated stake from a gateway that is leaving the network. */
1606
+ async claimDelegateFromLeavingGateway(params, _options) {
1607
+ const gateway = address(params.gatewayAddress);
1608
+ const [gatewayPda] = await getGatewayPDA(gateway, this.garProgram);
1609
+ const [delegationPda] = await getDelegationPDA(gateway, this.signer.address, this.garProgram);
1610
+ const nextId = await this.getNextWithdrawalId(this.signer.address);
1611
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, nextId, this.garProgram);
1612
+ // The on-chain handler is permissionless since `af38a40` (delegator +
1613
+ // payer split — anyone can crank). The IDL exposes both fields:
1614
+ // `delegator: Address` (no signature, just the seeds-derivation key)
1615
+ // and `payer: Signer` (covers rent on the init_if_needed withdrawal
1616
+ // counter + the new withdrawal account). The SDK's primary self-
1617
+ // claim path passes the signer for both roles; cranker callers can
1618
+ // pass distinct addresses by adding a `payer?` param to this method
1619
+ // (out of scope here — feature gap; tracked in
1620
+ // docs/E2E_TEST_COVERAGE_PLAN.md Phase 3.3).
1621
+ const ix = await getClaimDelegateFromLeavingGatewayInstructionAsync({
1622
+ gateway: gatewayPda,
1623
+ delegation: delegationPda,
1624
+ withdrawal: withdrawalPda,
1625
+ delegator: this.signer.address,
1626
+ payer: this.signer,
1627
+ }, { programAddress: this.garProgram });
1628
+ const sig = await this.sendTransaction([ix], 1_000_000);
1629
+ return { id: sig };
1630
+ }
1631
+ // =========================================
1632
+ // Delegation allowlist (ario-gar)
1633
+ // =========================================
1634
+ /** Add an address to the gateway's delegation allowlist. */
1635
+ async allowDelegate(params, _options) {
1636
+ const ix = await getAllowDelegateInstructionAsync({
1637
+ delegate: address(params.delegate),
1638
+ operator: this.signer,
1639
+ }, { programAddress: this.garProgram });
1640
+ const sig = await this.sendTransaction([ix], 1_000_000);
1641
+ return { id: sig };
1642
+ }
1643
+ /** Remove an address from the gateway's delegation allowlist. */
1644
+ async disallowDelegate(params, _options) {
1645
+ const ix = await getDisallowDelegateInstructionAsync({
1646
+ delegate: address(params.delegate),
1647
+ operator: this.signer,
1648
+ }, { programAddress: this.garProgram });
1649
+ const sig = await this.sendTransaction([ix], 1_000_000);
1650
+ return { id: sig };
1651
+ }
1652
+ /** Enable or disable the delegation allowlist for the gateway. */
1653
+ async setAllowlistEnabled(params, _options) {
1654
+ const ix = await getSetAllowlistEnabledInstructionAsync(await this.withGarDefaults({
1655
+ operator: this.signer,
1656
+ enabled: params.enabled,
1657
+ }), { programAddress: this.garProgram });
1658
+ const sig = await this.sendTransaction([ix], 1_000_000);
1659
+ return { id: sig };
1660
+ }
1661
+ // =========================================
1662
+ // Buy returned name (ario-arns)
1663
+ // =========================================
1664
+ /**
1665
+ * Buy a name from the returned name auction (Dutch auction with premium).
1666
+ *
1667
+ * Phase 4: now dispatches on `params.fundFrom`. Note that for
1668
+ * `buyReturnedName`, only the protocol share funds from the chosen source;
1669
+ * the initiator share is always a direct buyer-ATA → initiator-ATA SPL
1670
+ * transfer (matches the on-chain `_from_*` variant behavior).
1671
+ */
1672
+ async buyReturnedName(params, _options) {
1673
+ const arnsConfig = await this.getArnsConfig();
1674
+ const buyerATA = await getAssociatedTokenAddressKit(arnsConfig.mint, this.signer.address);
1675
+ const antPubkey = address(params.processId);
1676
+ // Read the ReturnedName to find the original initiator (gets the premium).
1677
+ const [returnedNamePda] = await getReturnedNamePDA(params.name, this.arnsProgram);
1678
+ const returnedNameAccount = await fetchEncodedAccount(this.rpc, returnedNamePda, { commitment: this.commitment });
1679
+ if (!returnedNameAccount.exists) {
1680
+ throw new Error(`Returned name not found: ${params.name}`);
1681
+ }
1682
+ const returnedNameData = Buffer.from(returnedNameAccount.data);
1683
+ const nameLen = returnedNameData.readUInt32LE(8);
1684
+ const initiatorOffset = 8 + 4 + nameLen + 32;
1685
+ const initiator = addressDecoder.decode(returnedNameData.subarray(initiatorOffset, initiatorOffset + 32));
1686
+ const initiatorATA = await getAssociatedTokenAddressKit(arnsConfig.mint, initiator);
1687
+ const [arnsRecord] = await getArnsRecordPDA(params.name, this.arnsProgram);
1688
+ const buyParams = {
1689
+ name: params.name,
1690
+ purchaseType: params.type === 'permabuy' ? PurchaseType.Permabuy : PurchaseType.Lease,
1691
+ years: params.years ?? 1,
1692
+ ant: antPubkey,
1693
+ };
1694
+ let ix;
1695
+ if (!params.fundFrom ||
1696
+ params.fundFrom === 'balance' ||
1697
+ params.fundFrom === 'turbo') {
1698
+ ix = await getBuyReturnedNameInstructionAsync(await this.withArnsDefaults({
1699
+ arnsRecord,
1700
+ returnedName: returnedNamePda,
1701
+ buyerTokenAccount: buyerATA,
1702
+ protocolTokenAccount: arnsConfig.treasury,
1703
+ initiatorTokenAccount: initiatorATA,
1704
+ buyer: this.signer,
1705
+ params: buyParams,
1706
+ }), { programAddress: this.arnsProgram });
1707
+ }
1708
+ else {
1709
+ const garConfig = await this.getGarConfig();
1710
+ const [garSettings] = await getGarSettingsPDA(this.garProgram);
1711
+ const sharedReturnedBase = {
1712
+ config: await this.arnsConfigPda(),
1713
+ demandFactor: await this.demandFactorPda(),
1714
+ returnedName: returnedNamePda,
1715
+ arnsRecord,
1716
+ nameRegistry: await this.nameRegistryPda(),
1717
+ buyerTokenAccount: buyerATA,
1718
+ initiatorTokenAccount: initiatorATA,
1719
+ garSettings,
1720
+ stakeTokenAccount: garConfig.stakeTokenAccount,
1721
+ protocolTokenAccount: arnsConfig.treasury,
1722
+ buyer: this.signer,
1723
+ garProgram: this.garProgram,
1724
+ params: buyParams,
1725
+ };
1726
+ if (params.fundFrom === 'stakes' && params.gatewayAddress) {
1727
+ const gatewayAddr = address(params.gatewayAddress);
1728
+ const [gatewayPda] = await getGatewayPDA(gatewayAddr, this.garProgram);
1729
+ if (params.fundAsOperator) {
1730
+ ix = await getBuyReturnedNameFromOperatorStakeInstructionAsync({ ...sharedReturnedBase, gateway: gatewayPda }, { programAddress: this.arnsProgram });
1731
+ }
1732
+ else {
1733
+ const [delegationPda] = await getDelegationPDA(gatewayAddr, this.signer.address, this.garProgram);
1734
+ ix = await getBuyReturnedNameFromDelegationInstructionAsync({
1735
+ ...sharedReturnedBase,
1736
+ gateway: gatewayPda,
1737
+ delegation: delegationPda,
1738
+ }, { programAddress: this.arnsProgram });
1739
+ }
1740
+ }
1741
+ else if (params.fundFrom === 'withdrawal' &&
1742
+ params.withdrawalId !== undefined) {
1743
+ const [withdrawalPda] = await getWithdrawalPDA(this.signer.address, params.withdrawalId, this.garProgram);
1744
+ ix = await getBuyReturnedNameFromWithdrawalInstructionAsync({ ...sharedReturnedBase, withdrawal: withdrawalPda }, { programAddress: this.arnsProgram });
1745
+ }
1746
+ else if (params.fundFrom === 'plan' || params.fundFrom === 'any') {
1747
+ // Returned-name pricing is dynamic (Dutch auction premium); we trust
1748
+ // explicit caller-supplied sources here and skip auto-discovery if
1749
+ // sources is provided. For 'any' without sources, we fall back to a
1750
+ // best-effort estimate using the plain registration fee — caller can
1751
+ // always retry with explicit sources on FundingPlanAmountMismatch.
1752
+ const cost = await this._estimateBuyNameCost({
1753
+ name: params.name,
1754
+ purchaseType: buyParams.purchaseType,
1755
+ years: buyParams.years,
1756
+ });
1757
+ const plan = await this._resolveFundingPlan(params, cost);
1758
+ const { remainingAccounts, withdrawalCounter, residueVaultCount } = await this._materializeFundingPlan(params, plan);
1759
+ ix = await getBuyReturnedNameFromFundingPlanInstructionAsync({
1760
+ ...sharedReturnedBase,
1761
+ payerTokenAccount: plan.hasBalanceSource ? buyerATA : undefined,
1762
+ withdrawalCounter,
1763
+ sources: plan.sources.map(toGeneratedFundingSourceSpec),
1764
+ discountAccountCount: 0,
1765
+ residueVaultCount,
1766
+ }, { programAddress: this.arnsProgram });
1767
+ if (remainingAccounts.length > 0)
1768
+ ix = withRemainingAccounts(ix, remainingAccounts);
1769
+ }
1770
+ else {
1771
+ throw new Error(`unsupported fundFrom mode '${params.fundFrom}' for buyReturnedName`);
1772
+ }
1773
+ }
1774
+ // Sprint 4 / ADR-016: bundle ant.sync_attributes after the buy so the
1775
+ // Attributes plugin reflects the new record holder. assetOverride =
1776
+ // antPubkey because the ArnsRecord PDA is created by buy_returned_name
1777
+ // and doesn't exist on-chain at SDK build time.
1778
+ const syncIx = await this._buildSyncAttributesIxIfOwner(params.name, antPubkey);
1779
+ const sig = await this.sendTransaction(syncIx ? [ix, syncIx] : [ix]);
1780
+ return { id: sig };
1781
+ }
1782
+ // =========================================
1783
+ // Name management (ario-arns)
1784
+ // =========================================
1785
+ /** Reassign an ArNS name to a different ANT. */
1786
+ async reassignName(params, _options) {
1787
+ const newAnt = address(params.processId);
1788
+ const [arnsRecord] = await getArnsRecordPDA(params.name, this.arnsProgram);
1789
+ const ix = await getReassignNameInstructionAsync(await this.withArnsDefaults({
1790
+ arnsRecord,
1791
+ caller: this.signer,
1792
+ newAnt,
1793
+ }), { programAddress: this.arnsProgram });
1794
+ // The on-chain handler validates the new ANT via `remaining_accounts[0]`
1795
+ // (must be MPL-Core-owned + key matches `newAnt`). The codama builder
1796
+ // for reassign_name only encodes the typed accounts above, so we tag
1797
+ // the new ANT asset on as a readonly remaining account.
1798
+ //
1799
+ // Sprint 4 / ADR-016: post-reassign the record points at `newAnt`. The
1800
+ // bundled `sync_attributes` MUST target `newAnt` — without the
1801
+ // override, the helper would read the on-chain record at SDK build
1802
+ // time (still pointing at the OLD asset), build a sync ix for the
1803
+ // OLD asset, and fail the post-reassign `record.ant == asset.key()`
1804
+ // check. The owner-check inside _buildSyncAttributesIxIfOwner runs
1805
+ // against `newAnt`, so the bundle fires only when the reassign
1806
+ // caller is also the new ANT's holder; otherwise the ix is sent
1807
+ // alone and the new owner runs `syncAttributes()` later (BD-095/096).
1808
+ const syncIx = await this._buildSyncAttributesIxIfOwner(params.name, newAnt);
1809
+ const reassignWithMetas = withRemainingAccounts(ix, [
1810
+ { address: newAnt, role: AccountRole.READONLY },
1811
+ ]);
1812
+ const sig = await this.sendTransaction(syncIx ? [reassignWithMetas, syncIx] : [reassignWithMetas]);
1813
+ return { id: sig };
1814
+ }
1815
+ /** Release a permabuy name back to the registry (creates a returned name auction). */
1816
+ async releaseName(params, _options) {
1817
+ const [returnedNamePda] = await getReturnedNamePDA(params.name, this.arnsProgram);
1818
+ const [arnsRecord] = await getArnsRecordPDA(params.name, this.arnsProgram);
1819
+ const ix = await getReleaseNameInstructionAsync(await this.withArnsDefaults({
1820
+ arnsRecord,
1821
+ returnedName: returnedNamePda,
1822
+ caller: this.signer,
1823
+ }), { programAddress: this.arnsProgram });
1824
+ // Note: no sync_attributes bundle here — release_name closes the
1825
+ // ArnsRecord PDA, so a follow-up sync would fail PDA validation. The
1826
+ // asset's stale traits remain pointing at the released name; off-chain
1827
+ // resolvers should treat ArnsRecord as the source of truth and ignore
1828
+ // a "ArNS Name" trait that no longer resolves.
1829
+ const sig = await this.sendTransaction([ix]);
1830
+ return { id: sig };
1831
+ }
1832
+ // =========================================
1833
+ // Epoch cranking (ario-gar) — permissionless
1834
+ // =========================================
1835
+ /**
1836
+ * Create a new epoch. Permissionless — anyone can call when the next
1837
+ * epoch's start time has arrived.
1838
+ */
1839
+ async createEpoch(_options) {
1840
+ const garConfig = await this.getGarConfig();
1841
+ const [epochSettingsPda] = await getEpochSettingsPDA(this.garProgram);
1842
+ const settingsAccount = await fetchEncodedAccount(this.rpc, epochSettingsPda, { commitment: this.commitment });
1843
+ if (!settingsAccount.exists)
1844
+ throw new Error('EpochSettings not found');
1845
+ const settings = deserializeEpochSettingsFull(Buffer.from(settingsAccount.data));
1846
+ const epochIndex = settings.currentEpochIndex;
1847
+ const [epochPda] = await getEpochPDA(epochIndex, this.garProgram);
1848
+ const ix = await getCreateEpochInstructionAsync(await this.withGarDefaults({
1849
+ epoch: epochPda,
1850
+ protocolTokenAccount: garConfig.protocolTokenAccount,
1851
+ payer: this.signer,
1852
+ }), { programAddress: this.garProgram });
1853
+ const sig = await this.sendTransaction([ix], 1_000_000);
1854
+ return { id: sig };
1855
+ }
1856
+ /**
1857
+ * Tally weights for a batch of gateways. Permissionless — call repeatedly
1858
+ * until all gateways are processed. Pass gateway PDAs as
1859
+ * `gatewayAccounts`; they're appended as `remaining_accounts`.
1860
+ */
1861
+ async tallyWeights(params, _options) {
1862
+ const ix = await getTallyWeightsInstructionAsync(await this.withGarDefaults({
1863
+ payer: this.signer,
1864
+ epochIndex: BigInt(params.epochIndex),
1865
+ }), { programAddress: this.garProgram });
1866
+ const remaining = params.gatewayAccounts.map((address) => ({
1867
+ address,
1868
+ role: AccountRole.WRITABLE,
1869
+ }));
1870
+ const sig = await this.sendTransaction([withRemainingAccounts(ix, remaining)], 1_000_000);
1871
+ return { id: sig };
1872
+ }
1873
+ /**
1874
+ * Prescribe observers and names for an epoch. Permissionless — call after
1875
+ * weights are tallied. Gateway PDAs are appended as `remaining_accounts`,
1876
+ * and the optional `nameRegistryAccount` (must be last) enables the name
1877
+ * prescription leg.
1878
+ */
1879
+ async prescribeEpoch(params, _options) {
1880
+ const ix = await getPrescribeEpochInstructionAsync(await this.withGarDefaults({
1881
+ payer: this.signer,
1882
+ epochIndex: BigInt(params.epochIndex),
1883
+ }), { programAddress: this.garProgram });
1884
+ const remaining = params.gatewayAccounts.map((address) => ({
1885
+ address,
1886
+ role: AccountRole.READONLY,
1887
+ }));
1888
+ if (params.nameRegistryAccount) {
1889
+ remaining.push({
1890
+ address: params.nameRegistryAccount,
1891
+ role: AccountRole.READONLY,
1892
+ });
1893
+ }
1894
+ const sig = await this.sendTransaction([withRemainingAccounts(ix, remaining)], 1_000_000);
1895
+ return { id: sig };
1896
+ }
1897
+ /**
1898
+ * Distribute rewards for a completed epoch in batches. Permissionless —
1899
+ * call after epoch ends. Gateway PDAs appended as `remaining_accounts`.
1900
+ */
1901
+ async distributeEpoch(params, _options) {
1902
+ const garConfig = await this.getGarConfig();
1903
+ // ario_gar::distribute_epoch CPIs into ario_core::release_treasury_to_recipient
1904
+ // (signed by the ArioConfig PDA — the canonical treasury authority). The
1905
+ // generated builder expects `arioConfig` + `arioCoreProgram` accounts at
1906
+ // positions 6+7 (post-PR-19 in ar-io-solana-contracts). Pin both to the
1907
+ // configured core program so devnet/testnet deployments don't fall back
1908
+ // to the bundled mainnet default.
1909
+ const [arioConfig] = await getArioConfigPDA(this.coreProgram);
1910
+ const ix = await getDistributeEpochInstructionAsync(await this.withGarDefaults({
1911
+ protocolTokenAccount: garConfig.protocolTokenAccount,
1912
+ stakeTokenAccount: garConfig.stakeTokenAccount,
1913
+ arioConfig,
1914
+ arioCoreProgram: this.coreProgram,
1915
+ payer: this.signer,
1916
+ epochIndex: BigInt(params.epochIndex),
1917
+ }), { programAddress: this.garProgram });
1918
+ const remaining = params.gatewayAccounts.map((address) => ({
1919
+ address,
1920
+ role: AccountRole.WRITABLE,
1921
+ }));
1922
+ const sig = await this.sendTransaction([withRemainingAccounts(ix, remaining)], 1_000_000);
1923
+ return { id: sig };
1924
+ }
1925
+ /**
1926
+ * Close an old epoch account and reclaim rent. Permissionless — call after
1927
+ * the epoch is distributed and at least 7 epochs have passed.
1928
+ */
1929
+ async closeEpoch(params, _options) {
1930
+ const ix = await getCloseEpochInstructionAsync(await this.withGarDefaults({
1931
+ payer: this.signer,
1932
+ epochIndex: BigInt(params.epochIndex),
1933
+ }), { programAddress: this.garProgram });
1934
+ const sig = await this.sendTransaction([ix]);
1935
+ return { id: sig };
1936
+ }
1937
+ // =========================================
1938
+ // Cranker helpers
1939
+ // =========================================
1940
+ /**
1941
+ * Get gateway PDAs for a batch starting at registryIndex.
1942
+ * Reads the GatewayRegistry and derives PDAs for the next `batchSize`
1943
+ * active gateways.
1944
+ */
1945
+ async getRegistryGatewayPDAs(startIndex, batchSize) {
1946
+ const [registryPda] = await getGatewayRegistryPDA(this.garProgram);
1947
+ const registryAccount = await fetchEncodedAccount(this.rpc, registryPda, {
1948
+ commitment: this.commitment,
1949
+ });
1950
+ if (!registryAccount.exists)
1951
+ return [];
1952
+ const registryData = Buffer.from(registryAccount.data);
1953
+ const count = registryData.readUInt32LE(40); // 8 disc + 32 authority
1954
+ const slotsOffset = 48; // 8 + 32 + 4 + 4
1955
+ // GatewaySlot: address(32) + composite_weight(8) + start_timestamp(8)
1956
+ // + status(1) + _padding(7) = 56 bytes.
1957
+ const SLOT_STRIDE = 56;
1958
+ const pdas = [];
1959
+ const end = Math.min(startIndex + batchSize, count);
1960
+ const zero = '11111111111111111111111111111111';
1961
+ for (let i = startIndex; i < end && i < 3000; i++) {
1962
+ const slotOffset = slotsOffset + i * SLOT_STRIDE;
1963
+ const addr = addressDecoder.decode(registryData.subarray(slotOffset, slotOffset + 32));
1964
+ if (addr === zero)
1965
+ continue;
1966
+ const [gatewayPda] = await getGatewayPDA(addr, this.garProgram);
1967
+ pdas.push(gatewayPda);
1968
+ }
1969
+ return pdas;
1970
+ }
1971
+ /** Get ALL active gateway PDAs from the registry. */
1972
+ async getAllRegistryGatewayPDAs() {
1973
+ const [registryPda] = await getGatewayRegistryPDA(this.garProgram);
1974
+ const registryAccount = await fetchEncodedAccount(this.rpc, registryPda, {
1975
+ commitment: this.commitment,
1976
+ });
1977
+ if (!registryAccount.exists)
1978
+ return [];
1979
+ const registryData = Buffer.from(registryAccount.data);
1980
+ const count = registryData.readUInt32LE(40);
1981
+ const slotsOffset = 48;
1982
+ const SLOT_STRIDE = 56;
1983
+ const pdas = [];
1984
+ const zero = '11111111111111111111111111111111';
1985
+ for (let i = 0; i < count && i < 3000; i++) {
1986
+ const slotOffset = slotsOffset + i * SLOT_STRIDE;
1987
+ const addr = addressDecoder.decode(registryData.subarray(slotOffset, slotOffset + 32));
1988
+ if (addr === zero)
1989
+ continue;
1990
+ const [gatewayPda] = await getGatewayPDA(addr, this.garProgram);
1991
+ pdas.push(gatewayPda);
1992
+ }
1993
+ return pdas;
1994
+ }
1995
+ /**
1996
+ * Read the raw epoch account data for cranker state inspection.
1997
+ * Returns null if the epoch account doesn't exist yet.
1998
+ */
1999
+ async getEpochRaw(epochIndex) {
2000
+ const [epochPda] = await getEpochPDA(epochIndex, this.garProgram);
2001
+ const account = await fetchEncodedAccount(this.rpc, epochPda, {
2002
+ commitment: this.commitment,
2003
+ });
2004
+ if (!account.exists)
2005
+ return null;
2006
+ try {
2007
+ return this.fetchEpochRawFields(Buffer.from(account.data));
2008
+ }
2009
+ catch {
2010
+ return null;
2011
+ }
2012
+ }
2013
+ /**
2014
+ * Parse raw epoch account data for cranker-relevant fields.
2015
+ * Offsets match the Rust Epoch zero-copy struct (repr(C)).
2016
+ *
2017
+ * Layout after 8-byte discriminator:
2018
+ * [8 epoch_index][8 start_ts][8 end_ts][8 total_eligible][8 per_gw]
2019
+ * [8 per_obs][8 reward_rate][8 weight_lo][8 weight_hi][32 hashchain]
2020
+ * [4 active_gw_count][4 dist_idx][4 tally_idx]
2021
+ * [1 observer_count][1 name_count][1 obs_submitted][1 rewards_dist]
2022
+ * [1 weights_tallied][1 prescriptions_done][1 bump][1 _pad1]
2023
+ * [6000 failure_counts][1600 prescribed_observers]
2024
+ * [1600 prescribed_observer_gateways][64 prescribed_names]
2025
+ * [7 has_observed][5 _pad2]
2026
+ */
2027
+ fetchEpochRawFields(data) {
2028
+ const base = 8;
2029
+ const endTimestamp = Number(data.readBigInt64LE(base + 16));
2030
+ const activeGatewayCount = data.readUInt32LE(base + 104);
2031
+ const distributionIndex = data.readUInt32LE(base + 108);
2032
+ const tallyIndex = data.readUInt32LE(base + 112);
2033
+ const rewardsDistributed = data.readUInt8(base + 119);
2034
+ const weightsTallied = data.readUInt8(base + 120);
2035
+ const prescriptionsDone = data.readUInt8(base + 121);
2036
+ return {
2037
+ tallyIndex,
2038
+ distributionIndex,
2039
+ weightsTallied,
2040
+ prescriptionsDone,
2041
+ rewardsDistributed,
2042
+ activeGatewayCount,
2043
+ endTimestamp,
2044
+ };
2045
+ }
2046
+ // =========================================
2047
+ // Prune / cleanup (permissionless crank)
2048
+ // =========================================
2049
+ //
2050
+ // These mirror `tick()`-driven lazy pruning in the Lua source — on Solana
2051
+ // each is a discrete instruction someone has to call. All are
2052
+ // permissionless except `releaseVault`, which the on-chain handler still
2053
+ // gates on `owner: Signer` (ADR / vault.rs::ReleaseVault). See
2054
+ // docs/CRANKER_PRUNING_PLAN.md for the full design.
2055
+ /**
2056
+ * Batch-prune expired ArnsRecord PDAs from the NameRegistry. The caller
2057
+ * supplies the eligible records as `arnsRecords` — they're appended as
2058
+ * `remaining_accounts` and the on-chain handler verifies each is past
2059
+ * `end_timestamp + grace_period + return_auction_duration` before closing.
2060
+ * `maxNames` caps the per-tx work (u8). Submit in batches of ~10-15.
2061
+ */
2062
+ async pruneExpiredNames(params, _options) {
2063
+ const ix = await getPruneExpiredNamesInstructionAsync(await this.withArnsDefaults({
2064
+ payer: this.signer,
2065
+ maxNames: params.maxNames,
2066
+ }), { programAddress: this.arnsProgram });
2067
+ const remaining = params.arnsRecords.map((a) => ({
2068
+ address: address(a),
2069
+ role: AccountRole.WRITABLE,
2070
+ }));
2071
+ const sig = await this.sendTransaction([withRemainingAccounts(ix, remaining)], 1_000_000);
2072
+ return { id: sig };
2073
+ }
2074
+ /**
2075
+ * Convert a single expired-but-not-yet-returned lease into a `ReturnedName`
2076
+ * (kicks off the Dutch auction). Permissionless.
2077
+ */
2078
+ async pruneNameToReturned(params, _options) {
2079
+ const [arnsRecord] = await getArnsRecordPDA(params.name, this.arnsProgram);
2080
+ const [returnedName] = await getReturnedNamePDA(params.name, this.arnsProgram);
2081
+ const ix = await getPruneNameToReturnedInstructionAsync(await this.withArnsDefaults({
2082
+ arnsRecord,
2083
+ returnedName,
2084
+ payer: this.signer,
2085
+ }), { programAddress: this.arnsProgram });
2086
+ const sig = await this.sendTransaction([ix]);
2087
+ return { id: sig };
2088
+ }
2089
+ /**
2090
+ * Batch-prune expired ReturnedName PDAs (auction window elapsed). Caller
2091
+ * supplies the eligible PDAs as `returnedNames`; they're appended as
2092
+ * `remaining_accounts`. `maxNames` caps per-tx work (u8).
2093
+ */
2094
+ async pruneReturnedNames(params, _options) {
2095
+ const ix = await getPruneReturnedNamesInstructionAsync(await this.withArnsDefaults({
2096
+ payer: this.signer,
2097
+ maxNames: params.maxNames,
2098
+ }), { programAddress: this.arnsProgram });
2099
+ const remaining = params.returnedNames.map((a) => ({
2100
+ address: address(a),
2101
+ role: AccountRole.WRITABLE,
2102
+ }));
2103
+ // Match `pruneExpiredNames` (1M CU) — both dispatch the same batched
2104
+ // shape over `remaining_accounts`, and the default 400K is too tight
2105
+ // when the cranker batches near `maxNames` (≈15) on a busy registry.
2106
+ const sig = await this.sendTransaction([withRemainingAccounts(ix, remaining)], 1_000_000);
2107
+ return { id: sig };
2108
+ }
2109
+ /**
2110
+ * Close a single expired ReservedName PDA. Permissionless after
2111
+ * `expires_at`.
2112
+ */
2113
+ async pruneExpiredReservation(params, _options) {
2114
+ const [reservedName] = await getReservedNamePDA(params.name, this.arnsProgram);
2115
+ const ix = getPruneExpiredReservationInstruction({
2116
+ reservedName,
2117
+ payer: this.signer,
2118
+ }, { programAddress: this.arnsProgram });
2119
+ const sig = await this.sendTransaction([ix]);
2120
+ return { id: sig };
2121
+ }
2122
+ /**
2123
+ * Slash and remove a deficient gateway (`stats.failed_consecutive >=
2124
+ * max_consecutive_failures`). Builds the protected exit vault for the
2125
+ * post-slash min portion plus the optional excess vault for any surplus.
2126
+ * The contract's `excess_withdrawal: Option<UncheckedAccount>` slot is
2127
+ * always passed (PDA derived from `next_id + 1`); the handler consumes
2128
+ * it only when the post-slash stake exceeds `min_operator_stake`.
2129
+ * Permissionless.
2130
+ */
2131
+ async pruneGateway(params, _options) {
2132
+ const gatewayAddr = address(params.gateway);
2133
+ const garConfig = await this.getGarConfig();
2134
+ const [gatewayPda] = await getGatewayPDA(gatewayAddr, this.garProgram);
2135
+ const [withdrawalCounterPda] = await getWithdrawalCounterPDA(gatewayAddr, this.garProgram);
2136
+ const nextId = await this.getNextWithdrawalId(gatewayAddr);
2137
+ const [withdrawalPda] = await getWithdrawalPDA(gatewayAddr, nextId, this.garProgram);
2138
+ const [excessWithdrawalPda] = await getWithdrawalPDA(gatewayAddr, nextId + 1n, this.garProgram);
2139
+ const ix = await getPruneGatewayInstructionAsync(await this.withGarDefaults({
2140
+ gateway: gatewayPda,
2141
+ withdrawalCounter: withdrawalCounterPda,
2142
+ withdrawal: withdrawalPda,
2143
+ excessWithdrawal: excessWithdrawalPda,
2144
+ stakeTokenAccount: garConfig.stakeTokenAccount,
2145
+ protocolTokenAccount: garConfig.protocolTokenAccount,
2146
+ payer: this.signer,
2147
+ }), { programAddress: this.garProgram });
2148
+ const sig = await this.sendTransaction([ix], 1_000_000);
2149
+ return { id: sig };
2150
+ }
2151
+ /**
2152
+ * GC a `Leaving`/`Gone` gateway whose leave window has fully elapsed.
2153
+ * Closes the Gateway PDA and refunds rent to the caller. Permissionless.
2154
+ */
2155
+ async finalizeGone(params, _options) {
2156
+ const gatewayAddr = address(params.gateway);
2157
+ const [gatewayPda] = await getGatewayPDA(gatewayAddr, this.garProgram);
2158
+ const ix = await getFinalizeGoneInstructionAsync(await this.withGarDefaults({
2159
+ gateway: gatewayPda,
2160
+ caller: this.signer,
2161
+ }), { programAddress: this.garProgram });
2162
+ const sig = await this.sendTransaction([ix]);
2163
+ return { id: sig };
2164
+ }
2165
+ /**
2166
+ * Reclaim rent from an Observation PDA whose epoch has been distributed.
2167
+ * Permissionless. Pass `epochIndex` and the `observer` address used as
2168
+ * the Observation seed.
2169
+ */
2170
+ async closeObservation(params, _options) {
2171
+ const observerAddr = address(params.observer);
2172
+ const [observationPda] = await getObservationPDA(params.epochIndex, observerAddr, this.garProgram);
2173
+ const ix = await getCloseObservationInstructionAsync({
2174
+ observation: observationPda,
2175
+ payer: this.signer,
2176
+ epochIndex: BigInt(params.epochIndex),
2177
+ }, { programAddress: this.garProgram });
2178
+ const sig = await this.sendTransaction([ix]);
2179
+ return { id: sig };
2180
+ }
2181
+ /**
2182
+ * Close an empty Delegation PDA (`amount == 0`) and refund rent to the
2183
+ * original delegator (NOT the caller — see GAR-016, prevents griefing).
2184
+ * Permissionless.
2185
+ */
2186
+ async closeEmptyDelegation(params, _options) {
2187
+ const gatewayAddr = address(params.gateway);
2188
+ const delegatorAddr = address(params.delegator);
2189
+ const [gatewayPda] = await getGatewayPDA(gatewayAddr, this.garProgram);
2190
+ const [delegationPda] = await getDelegationPDA(gatewayAddr, delegatorAddr, this.garProgram);
2191
+ const ix = getCloseEmptyDelegationInstruction({
2192
+ gateway: gatewayPda,
2193
+ delegation: delegationPda,
2194
+ delegator: delegatorAddr,
2195
+ payer: this.signer,
2196
+ }, { programAddress: this.garProgram });
2197
+ const sig = await this.sendTransaction([ix]);
2198
+ return { id: sig };
2199
+ }
2200
+ /**
2201
+ * Close a drained Withdrawal PDA (`amount == 0`) and refund rent to the
2202
+ * original owner (NOT the caller). Permissionless.
2203
+ */
2204
+ async closeDrainedWithdrawal(params, _options) {
2205
+ const ownerAddr = address(params.owner);
2206
+ const [withdrawalPda] = await getWithdrawalPDA(ownerAddr, BigInt(params.withdrawalId), this.garProgram);
2207
+ const ix = getCloseDrainedWithdrawalInstruction({
2208
+ withdrawal: withdrawalPda,
2209
+ owner: ownerAddr,
2210
+ closer: this.signer,
2211
+ }, { programAddress: this.garProgram });
2212
+ const sig = await this.sendTransaction([ix]);
2213
+ return { id: sig };
2214
+ }
2215
+ }