@ar.io/sdk

中文文档
4.5.2发布于 2026/10/10Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 9165

codecov

原始使用文档
文档目录16 节
  1. Table of Contents
  2. Installation
  3. Quick Start
  4. Usage
  5. Subpath exports
  6. Web
  7. Browser bundle
  8. TypeScript
  9. ARIO Contract
  10. General
  11. Networks
  12. Vaults
  13. Gateways
  14. ar.io Name System (ArNS)
  15. Epochs
  16. Primary Names

@ar.io/sdk

codecov

The Solana-native SDK for the AR.IO network. Provides typed client classes (ARIO, ANT, ANTRegistry), PDA helpers, deserializers, and escrow primitives for the AR.IO protocol on Solana. Codama-generated instruction builders and account decoders are supplied by @ar.io/solana-contracts.

Table of Contents

Installation

Requires node>=v18.0.0.

npm install @ar.io/sdk

or

yarn add @ar.io/sdk

Quick Start

import { ARIO } from '@ar.io/sdk';
import { createSolanaRpc } from '@solana/kit';

const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const ario = ARIO.init({ rpc });
const gateways = await ario.getGateways();

Write operations need a @solana/kit signer plus an rpcSubscriptions client (used by kit's sendAndConfirmTransaction):

import { ARIO } from '@ar.io/sdk';
import {
  createSolanaRpc,
  createSolanaRpcSubscriptions,
  createKeyPairSignerFromBytes,
} from '@solana/kit';
import { readFileSync } from 'node:fs';

const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const rpcSubscriptions = createSolanaRpcSubscriptions(
  'wss://api.mainnet-beta.solana.com',
);
const signer = await createKeyPairSignerFromBytes(
  new Uint8Array(JSON.parse(readFileSync('keypair.json', 'utf8'))),
);

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
await ario.buyRecord({
  name: 'foo',
  type: 'lease',
  years: 1,
  processId: '<ANT mint pubkey>',
});
Output
{
  "items": [
    {
      "gatewayAddress": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
      "observerAddress": "IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs",
      "operatorStake": 250000000000,
      "totalDelegatedStake": 0,
      "settings": {
        "allowDelegatedStaking": true,
        "allowedDelegates": [],
        "autoStake": false,
        "delegateRewardShareRatio": 10,
        "minDelegatedStake": 100000000,
        "fqdn": "ar-io.dev",
        "label": "ar.io Test",
        "note": "Test Gateway operated by PDS for the ar.io ecosystem.",
        "port": 443,
        "properties": "raJgvbFU-YAnku-WsupIdbTsqqGLQiYpGzoqk9SCVgY",
        "protocol": "https"
      },
      "startTimestamp": 1720720621424,
      "endTimestamp": 0,
      "stats": {
        "passedConsecutiveEpochs": 30,
        "failedConsecutiveEpochs": 0,
        "totalEpochCount": 31,
        "passedEpochCount": 30,
        "failedEpochCount": 1,
        "observedEpochCount": 30,
        "prescribedEpochCount": 31
      },
      "status": "joined",
      "weights": {
        "stakeWeight": 5.02400000024,
        "tenureWeight": 0.19444444444444,
        "gatewayPerformanceRatio": 1,
        "observerPerformanceRatio": 1,
        "gatewayRewardRatioWeight": 1,
        "observerRewardRatioWeight": 1,
        "compositeWeight": 0.97688888893556,
        "normalizedCompositeWeight": 0.19247316211083
      }
    }
  ],
  "hasMore": true,
  "nextCursor": "-4xgjroXENKYhTWqrBo57HQwvDL51mMdfsdsxJy6Y2Z_sA",
  "totalItems": 316,
  "limit": 100,
  "sortBy": "startTimestamp",
  "sortOrder": "desc"
}

Usage

The SDK is published as an ES module ("type": "module") and is compatible with modern bundlers such as Webpack, Rollup, ESbuild, and Vite. CommonJS consumers should migrate to ESM (Node 18+ supports ESM natively). Refer to the [examples] directory to see how to use the SDK in various environments.

Subpath exports

  • @ar.io/sdk — main entry. ARIO, ANT, ANTRegistry, Solana client classes, PDA helpers, deserializers, escrow primitives.
  • @ar.io/sdk/solana — alias of the main entry (kept for one release while consumers migrate from the previous subpath layout).

Web

[!WARNING] Polyfills are not provided by default for bundled web projects (Vite, ESBuild, Webpack, Rollup, etc.). Depending on your bundler config, you will need polyfills for crypto, process and buffer. Refer to [examples/webpack] and [examples/vite] for examples.

import { ARIO } from '@ar.io/sdk';
import { createSolanaRpc } from '@solana/kit';

const ario = ARIO.init({
  rpc: createSolanaRpc('https://api.mainnet-beta.solana.com'),
});
const gateways = await ario.getGateways();

Browser bundle

<script type="module">
  // replace <version> with a release version
  import { ARIO } from 'https://github.com/ar-io/ar-io-sdk/releases/download/v<version>/web.bundle.min.js';
  import { createSolanaRpc } from 'https://esm.sh/@solana/kit@6';

  const ario = ARIO.init({
    rpc: createSolanaRpc('https://api.mainnet-beta.solana.com'),
  });
  const gateways = await ario.getGateways();
</script>

TypeScript

The SDK ships TypeScript types alongside the JS output. Types are exported from ./lib/types/solana/index.d.ts and resolve automatically for ESM consumers.

[!NOTE] TypeScript 5.3+ is recommended (the SDK uses nodenext module resolution with .js extensions in relative imports).

ARIO Contract

General

init({ rpc, rpcSubscriptions?, signer? })

Factory function that creates a read-only or writeable ARIO client. Providing signer plus rpcSubscriptions enables write methods (joinNetwork, delegateStake, buyRecord, etc.). Without a signer, the client is read-only.

import { ARIO } from '@ar.io/sdk';
import {
  createSolanaRpc,
  createSolanaRpcSubscriptions,
  createKeyPairSignerFromBytes,
} from '@solana/kit';

const rpc = createSolanaRpc('https://api.mainnet-beta.solana.com');

// read-only client
const ario = ARIO.init({ rpc });

// read-write client (needs rpcSubscriptions for sendAndConfirm)
const rpcSubscriptions = createSolanaRpcSubscriptions(
  'wss://api.mainnet-beta.solana.com',
);
const signer = await createKeyPairSignerFromBytes(/* 64-byte secret key */);
const arioWrite = ARIO.init({ rpc, rpcSubscriptions, signer });

getInfo()

Retrieves the information of the ARIO process.

const ario = ARIO.init({ rpc });
const info = await ario.getInfo();
Output
{
  "Name": "AR.IO",
  "Ticker": "ARIO",
  "Logo": "",
  "Denomination": 6,
  "Handlers": [],
  "LastCreatedEpochIndex": 0,
  "LastDistributedEpochIndex": 0,
  "totalSupply": 1000000000000000,
  "protocolBalance": 0,
  "epochSettings": {
    "durationMs": 86400000,
    "prescribedNameCount": 25,
    "maxObservers": 50
  }
}

Note: Handlers, LastCreatedEpochIndex, and LastDistributedEpochIndex are placeholders on Solana (returned for backwards-compatible field shape with consumer code). totalSupply / protocolBalance are live reads from the ArioConfig PDA; epochSettings is live from the EpochSettings PDA. See src/solana/io-readable.ts for the exact projection.

getTokenSupply()

Retrieves the total supply of tokens, returned in mARIO. The total supply includes the following:

  • total - the total supply of all tokens
  • circulating - the total supply minus locked, withdrawn, delegated, and staked
  • locked - tokens that are locked in the protocol (a.k.a. vaulted)
  • withdrawn - tokens that have been withdrawn from the protocol by operators and delegators
  • delegated - tokens that have been delegated to gateways
  • staked - tokens that are staked in the protocol by gateway operators
  • protocolBalance - tokens that are held in the protocol's treasury. This is included in the circulating supply.
const ario = ARIO.init({ rpc });
const supply = await ario.getTokenSupply();
Output
{
  "total": 1000000000000000000,
  "circulating": 998094653842520,
  "locked": 0,
  "withdrawn": 560563387278,
  "delegated": 1750000000,
  "staked": 1343032770199,
  "protocolBalance": 46317263683761
}

getBalance({ address })

Retrieves the balance of the specified wallet address.

const ario = ARIO.init({ rpc });
// the balance will be returned in mARIO as a value
const balance = await ario
  .getBalance({
    address: "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
  })
  .then((balance: number) => new mARIOToken(balance).toARIO()); // convert it to ARIO for readability
Output
100000

getBalances({ cursor, limit, sortBy, sortOrder })

Retrieves the balances of the ARIO process in mARIO, paginated and sorted by the specified criteria. The cursor used for pagination is the last wallet address from the previous request.

const ario = ARIO.init({ rpc });
const balances = await ario.getBalances({
  cursor: "-4xgjroXENKYhTWqrBo57HQwvDL51mMdfsdsxJy6Y2Z_sA",
  limit: 100,
  sortBy: "balance",
  sortOrder: "desc",
});
Output
{
  "items": [
    {
      "address": "-4xgjroXENKYhTWqrBo57HQwvDL51mMvSxJy6Y2Z_sA",
      "balance": 1000000
    },
    {
      "address": "-7vXsQZQDk8TMDlpiSLy3CnLi5PDPlAaN2DaynORpck",
      "balance": 1000000
    }
    // ...98 other balances
  ],
  "hasMore": true,
  "nextCursor": "-7vXsQZQDk8TMDlpiSLy3CnLi5PDPlAaN2DaynORpck",
  "totalItems": 1789,
  "sortBy": "balance",
  "sortOrder": "desc"
}

transfer({ target, qty })

Transfers mARIO to the designated target recipient address. Requires signer to be provided on ARIO.init to sign the transaction.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.transfer({
  target: 'RecipientSolanaPubkeyBase58',
  qty: new ARIOToken(1000).toMARIO(),
});

Networks

The SDK talks to whatever cluster your @solana/kit RPC client points at — mainnet-beta by default. For devnet or a local validator, override the RPC URL and (on any non-mainnet cluster) the per-program addresses:

import { ARIO } from '@ar.io/sdk';
import { createSolanaRpc, address } from '@solana/kit';

const ario = ARIO.init({
  rpc: createSolanaRpc('https://api.devnet.solana.com'),
  coreProgramId: address('<ARIO_CORE_PROGRAM_ID>'),
  garProgramId: address('<ARIO_GAR_PROGRAM_ID>'),
  arnsProgramId: address('<ARIO_ARNS_PROGRAM_ID>'),
  antProgramId: address('<ARIO_ANT_PROGRAM_ID>'),
});

On localnet (Surfpool) source program IDs from migration/localnet/out/localnet.env in the solana-ar-io monorepo.

Vaults

getVault({ address, vaultId })

Retrieves the locked-balance user vault of the ARIO process by the specified wallet address and vault ID.

const ario = ARIO.init({ rpc });
const vault = await ario.getVault({
  address: "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
  vaultId: "vaultIdOne",
});
Output
{
  "balance": 1000000,
  "startTimestamp": 123,
  "endTimestamp": 4567
}

getVaults({ cursor, limit, sortBy, sortOrder })

Retrieves all locked-balance user vaults of the ARIO process, paginated and sorted by the specified criteria. The cursor used for pagination is the last wallet address from the previous request.

const ario = ARIO.init({ rpc });
const vaults = await ario.getVaults({
  cursor: "0",
  limit: 100,
  sortBy: "balance",
  sortOrder: "desc",
});
Output
{
  "items": [
    {
      "address": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
      "vaultId": "vaultIdOne",
      "balance": 1000000,
      "startTimestamp": 123,
      "endTimestamp": 4567
    },
    {
      "address": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
      "vaultId": "vaultIdTwo",
      "balance": 1000000,
      "startTimestamp": 123,
      "endTimestamp": 4567
    }
    // ...98 other addresses with vaults
  ],
  "hasMore": true,
  "nextCursor": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
  "totalItems": 1789,
  "sortBy": "balance",
  "sortOrder": "desc"
}

vaultedTransfer({ recipient, quantity, lockLengthMs, revokable })

Transfers mARIO to the designated recipient address and locks the balance for the specified lockLengthMs milliseconds. The revokable flag determines if the vaulted transfer can be revoked by the sender.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.vaultedTransfer(
  {
    recipient: "-5dV7nk7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5",
    quantity: new ARIOToken(1000).toMARIO(),
    lockLengthMs: 1000 * 60 * 60 * 24 * 365, // 1 year
    revokable: true,
  },
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);

revokeVault({ recipient, vaultId })

Revokes a vaulted transfer by the recipient address and vault ID. Only the sender of the vaulted transfer can revoke it.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.revokeVault({
  recipient: "-5dV7nk7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5",
  vaultId: "IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs",
});

createVault({ lockLengthMs, quantity })

Creates a vault for the specified quantity of mARIO from the signer's balance and locks it for the specified lockLengthMs milliseconds.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });

const { id: txId } = await ario.createVault({
  lockLengthMs: 1000 * 60 * 60 * 24 * 365, // 1 year
  quantity: new ARIOToken(1000).toMARIO(),
});

extendVault({ vaultId, extendLengthMs })

Extends the lock length of a signer's vault by the specified extendLengthMs milliseconds.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });

const { id: txId } = await ario.extendVault({
  vaultId: "vaultIdOne",
  extendLengthMs: 1000 * 60 * 60 * 24 * 365, // 1 year
});

increaseVault({ vaultId, quantity })

Increases the balance of a signer's vault by the specified quantity of mARIO.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.increaseVault({
  vaultId: "vaultIdOne",
  quantity: new ARIOToken(1000).toMARIO(),
});

Gateways

getGateway({ address })

Retrieves a gateway's info by its staking wallet address.

const ario = ARIO.init({ rpc });
const gateway = await ario.getGateway({
  address: "-7vXsQZQDk8TMDlpiSLy3CnLi5PDPlAaN2DaynORpck",
});
Output
{
  "observerAddress": "IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs",
  "operatorStake": 250000000000,
  "totalDelegatedStake": 0,
  "settings": {
    "allowDelegatedStaking": true,
    "allowedDelegates": [],
    "autoStake": false,
    "delegateRewardShareRatio": 10,
    "minDelegatedStake": 100000000,
    "fqdn": "ar-io.dev",
    "label": "ar.io Test",
    "note": "Test Gateway operated by PDS for the ar.io ecosystem.",
    "port": 443,
    "properties": "raJgvbFU-YAnku-WsupIdbTsqqGLQiYpGzoqk9SCVgY",
    "protocol": "https"
  },
  "startTimestamp": 1720720620813,
  "endTimestamp": 0,
  "stats": {
    "passedConsecutiveEpochs": 30,
    "failedConsecutiveEpochs": 0,
    "totalEpochCount": 31,
    "passedEpochCount": 30,
    "failedEpochCount": 1,
    "observedEpochCount": 30,
    "prescribedEpochCount": 31
  },
  "status": "joined",
  "weights": {
    "stakeWeight": 5.02400000024,
    "tenureWeight": 0.19444444444444,
    "gatewayPerformanceRatio": 1,
    "observerPerformanceRatio": 1,
    "gatewayRewardRatioWeight": 1,
    "observerRewardRatioWeight": 1,
    "compositeWeight": 0.97688888893556,
    "normalizedCompositeWeight": 0.19247316211083
  }
}

getGateways({ cursor, limit, sortBy, sortOrder })

Retrieves registered gateways of the ARIO process, using pagination and sorting by the specified criteria. The cursor used for pagination is the last gateway address from the previous request.

const ario = ARIO.init({ rpc });
const gateways = await ario.getGateways({
  limit: 100,
  sortOrder: "desc",
  sortBy: "operatorStake",
});

Available sortBy options are any of the keys on the gateway object, e.g. operatorStake, start, status, settings.fqdn, settings.label, settings.note, settings.port, settings.protocol, stats.failedConsecutiveEpochs, stats.passedConsecutiveEpochs, etc.

Output
{
  "items": [
    {
      "gatewayAddress": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
      "observerAddress": "IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs",
      "operatorStake": 250000000000,
      "totalDelegatedStake": 0,
      "settings": {
        "allowDelegatedStaking": true,
        "allowedDelegates": [],
        "autoStake": false,
        "delegateRewardShareRatio": 10,
        "minDelegatedStake": 100000000,
        "fqdn": "ar-io.dev",
        "label": "ar.io Test",
        "note": "Test Gateway operated by PDS for the ar.io ecosystem.",
        "port": 443,
        "properties": "raJgvbFU-YAnku-WsupIdbTsqqGLQiYpGzoqk9SCVgY",
        "protocol": "https"
      },
      "startTimestamp": 1720720620813,
      "endTimestamp": 0,
      "stats": {
        "passedConsecutiveEpochs": 30,
        "failedConsecutiveEpochs": 0,
        "totalEpochCount": 31,
        "passedEpochCount": 30,
        "failedEpochCount": 1,
        "observedEpochCount": 30,
        "prescribedEpochCount": 31
      },
      "status": "joined",
      "weights": {
        "stakeWeight": 5.02400000024,
        "tenureWeight": 0.19444444444444,
        "gatewayPerformanceRatio": 1,
        "observerPerformanceRatio": 1,
        "gatewayRewardRatioWeight": 1,
        "observerRewardRatioWeight": 1,
        "compositeWeight": 0.97688888893556,
        "normalizedCompositeWeight": 0.19247316211083
      }
    }
  ],
  "hasMore": true,
  "nextCursor": "-4xgjroXENKYhTWqrBo57HQwvDL51mMdfsdsxJy6Y2Z_sA",
  "totalItems": 316,
  "limit": 100,
  "sortBy": "operatorStake",
  "sortOrder": "desc"
}

getGatewayDelegates({ address, cursor, limit, sortBy, sortOrder })

Retrieves all delegates for a specific gateway, paginated and sorted by the specified criteria. The cursor used for pagination is the last delegate address from the previous request.

const ario = ARIO.init({ rpc });
const delegates = await ario.getGatewayDelegates({
  address: "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
  limit: 3,
  sortBy: "startTimestamp",
  sortOrder: "desc",
});
Output
{
  "nextCursor": "ScEtph9-vfY7lgqlUWwUwOmm99ySeZGQhOX0MFAyFEs",
  "limit": 3,
  "sortBy": "startTimestamp",
  "totalItems": 32,
  "sortOrder": "desc",
  "hasMore": true,
  "items": [
    {
      "delegatedStake": 600000000,
      "address": "qD5VLaMYyIHlT6vH59TgYIs6g3EFlVjlPqljo6kqVxk",
      "startTimestamp": 1732716956301
    },
    {
      "delegatedStake": 508999038,
      "address": "KG8TlcWk-8pvroCjiLD2J5zkG9rqC6yYaBuZNqHEyY4",
      "startTimestamp": 1731828123742
    },
    {
      "delegatedStake": 510926479,
      "address": "ScEtph9-vfY7lgqlUWwUwOmm99ySeZGQhOX0MFAyFEs",
      "startTimestamp": 1731689356040
    }
  ]
}

joinNetwork(params)

Joins a gateway to the ar.io network via its associated wallet.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.joinNetwork(
  {
    qty: new ARIOToken(10_000).toMARIO(), // minimum operator stake allowed
    allowDelegatedStaking: true, // allows delegated staking
    minDelegatedStake: new ARIOToken(100).toMARIO(), // minimum delegated stake allowed
    delegateRewardShareRatio: 10, // percentage of rewards to share with delegates (e.g. 10%)
    label: "john smith", // min 1, max 64 characters
    note: "The example gateway", // max 256 characters
    properties: "FH1aVetOoulPGqgYukj0VE0wIhDy90WiQoV3U2PeY44", // Arweave transaction ID containing additional properties of the Gateway
    observerWallet: "0VE0wIhDy90WiQoV3U2PeY44FH1aVetOoulPGqgYukj", // wallet address of the observer, must match OBSERVER_WALLET on the observer
    fqdn: "example.com", // fully qualified domain name - note: you must own the domain and set the OBSERVER_WALLET on your gateway to match `observerWallet`
    port: 443, // port number
    protocol: "https", // only 'https' is supported
  },
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);

leaveNetwork()

Sets the gateway as leaving on the ar.io network. Requires signer to be provided on ARIO.init to sign the transaction. The gateways operator and delegate stakes are vaulted and will be returned after leave periods. The gateway will be removed from the network after the leave period.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });

const { id: txId } = await ario.leaveNetwork(
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);

updateGatewaySettings({ ...settings })

Writes new gateway settings to the callers gateway configuration.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.updateGatewaySettings(
  {
    // any other settings you want to update
    minDelegatedStake: new ARIOToken(100).toMARIO(),
  },
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);

updateOperationsAddress({ operationsAddress })

Authorises a second address to update the caller's gateway metadata (see updateGatewayMetadata) and to spend the gateway's ArNS discount. Staking, delegation settings and the operations address itself stay operator-only. Pass the operator's own address to revoke a delegation.

A gateway that has not yet been migrated to schema 1.2.0 cannot hold an operations address; in that case migrate_gateway is added to the same transaction automatically.

Note: Solana-only, so it is on SolanaARIOWriteable rather than the cross-backend ARIOWrite type. Must be signed by the gateway operator.

import { SolanaARIOWriteable } from "@ar.io/sdk";

const ario = new SolanaARIOWriteable({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.updateOperationsAddress({
  operationsAddress: "DeLegateAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
});

updateGatewayMetadata({ gatewayAddress?, ...metadata })

Updates a gateway's label, fqdn, port, protocol, properties and/or note. Can be signed by the gateway operator, or by its operations address — in which case pass the operator as gatewayAddress. An operations address is only honoured once the gateway is at schema 1.2.0.

Note: Solana-only (SolanaARIOWriteable).

// signed by the gateway's operations address
const ario = new SolanaARIOWriteable({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.updateGatewayMetadata({
  gatewayAddress: "GatewayAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
  fqdn: "gateway.example.com",
  port: 443,
});

When reading gateways, operationsAddress is only present for gateways at schema 1.2.0 or later; below that the program ignores the field and only the operator can act.

migrateGateway({ gatewayAddress }) / migrateGateways({ gatewayAddresses?, batchSize? })

Migrates Gateway accounts to schema 1.2.0 (ADR-0030). Permissionless — the signer pays a small rent top-up (32 bytes per gateway). migrateGateways with no gatewayAddresses migrates every gateway still below 1.2.0 (see getUnmigratedGatewayAddresses()), 8 per transaction by default, and stops at the first failed batch.

Note: Solana-only (SolanaARIOWriteable).

const ario = new SolanaARIOWriteable({ rpc, rpcSubscriptions, signer });
const pending = await ario.getUnmigratedGatewayAddresses();
const { migrated, signatures } = await ario.migrateGateways();

transferEpochSettingsAuthority({ newAuthority })

Hands EpochSettings.authority — the key for epoch admin instructions — to a new address, such as a multisig (ADR-0031). Must be signed by the current authority.

Note: Solana-only (SolanaARIOWriteable).

const ario = new SolanaARIOWriteable({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.transferEpochSettingsAuthority({
  newAuthority: "MuLtisigAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
});

increaseDelegateStake({ target, qty })

Increases the callers stake on the target gateway.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.increaseDelegateStake(
  {
    target: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
    qty: new ARIOToken(100).toMARIO(),
  },
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);

decreaseDelegateStake({ target, qty, instant })

Decreases the callers stake on the target gateway. Can instantly decrease stake by setting instant to true.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.decreaseDelegateStake(
  {
    target: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
    qty: new ARIOToken(100).toMARIO(),
  },
  {
    tags: [{ name: "App-Name", value: "My-Awesome-App" }],
  },
);

Pay the early withdrawal fee and withdraw instantly.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.decreaseDelegateStake({
  target: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
  qty: new ARIOToken(100).toMARIO(),
  instant: true, // Immediately withdraw this stake and pay the instant withdrawal fee
});

getDelegations({ address, cursor, limit, sortBy, sortOrder })

Retrieves all active and vaulted stakes across all gateways for a specific address, paginated and sorted by the specified criteria. The cursor used for pagination is the last delegationId (concatenated gateway and startTimestamp of the delgation) from the previous request.

const ario = ARIO.init({ rpc });
const vaults = await ario.getDelegations({
  address: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
  cursor: "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ_123456789",
  limit: 2,
  sortBy: "startTimestamp",
  sortOrder: "asc",
});
Output
{
  "sortOrder": "asc",
  "hasMore": true,
  "totalItems": 95,
  "limit": 2,
  "sortBy": "startTimestamp",
  "items": [
    {
      "type": "stake",
      "startTimestamp": 1727815440632,
      "gatewayAddress": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
      "delegationId": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ_1727815440632",
      "balance": 1383212512
    },
    {
      "type": "vault",
      "startTimestamp": 1730996691117,
      "gatewayAddress": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
      "delegationId": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ_1730996691117",
      "vaultId": "_sGDS7X1hyLCVpfe40GWioH9BSOb7f0XWbhHBa1q4-g",
      "balance": 50000000,
      "endTimestamp": 1733588691117
    }
  ],
  "nextCursor": "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ_1730996691117"
}

instantWithdrawal({ gatewayAddress, vaultId })

Instantly withdraws an existing vault on a gateway. If no gatewayAddress is provided, the signer's address will be used.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
// removes a delegated vault from a gateway
const { id: txId } = await ario.instantWithdrawal(
  {
    // gateway address where delegate vault exists
    gatewayAddress: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
    // delegated vault id to cancel
    vaultId: "fDrr0_J4Iurt7caNST02cMotaz2FIbWQ4Kcj616RHl3",
  },
  // optional additional tags
  {
    tags: [{ name: "App-Name", value: "My-Awesome-App" }],
  },
);
// removes an operator vault from a gateway
const { id: txId } = await ario.instantWithdrawal({
  vaultId: "fDrr0_J4Iurt7caNST02cMotaz2FIbWQ4Kcj616RHl3",
});

cancelWithdrawal({ gatewayAddress, vaultId })

Cancels an existing vault on a gateway. The vaulted stake will be returned to the callers stake. If no gatewayAddress is provided, the signer's address will be used.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
// cancels a delegated vault from a gateway
const { id: txId } = await ario.cancelWithdrawal(
  {
    // gateway address where vault exists
    gatewayAddress: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
    // vault id to cancel
    vaultId: "fDrr0_J4Iurt7caNST02cMotaz2FIbWQ4Kcj616RHl3",
  },
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);
// cancels an operator vault from a gateway
const { id: txId } = await ario.cancelWithdrawal({
  // operator vault id to cancel
  vaultId: "fDrr0_J4Iurt7caNST02cMotaz2FIbWQ4Kcj616RHl3",
});

getAllowedDelegates({ address, cursor, limit, sortBy, sortOrder })

Retrieves all allowed delegates for a specific address. The cursor used for pagination is the last address from the previous request.

const ario = ARIO.init({ rpc });
const allowedDelegates = await ario.getAllowedDelegates({
  address: "QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ",
});
Output
{
  "sortOrder": "desc",
  "hasMore": false,
  "totalItems": 4,
  "limit": 100,
  "items": [
    "PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM",
    "N4h8M9A9hasa3tF47qQyNvcKjm4APBKuFs7vqUVm-SI",
    "JcC4ZLUY76vmWha5y6RwKsFqYTrMZhbockl8iM9p5lQ",
    "31LPFYoow2G7j-eSSsrIh8OlNaARZ84-80J-8ba68d8"
  ]
}

getGatewayVaults({ address, cursor, limit, sortBy, sortOrder })

Retrieves all vaults across all gateways for a specific address, paginated and sorted by the specified criteria. The cursor used for pagination is the last vaultId from the previous request.

const ario = ARIO.init({ rpc });
const vaults = await ario.getGatewayVaults({
  address: '"PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM',
});
Output
{
  "sortOrder": "desc",
  "hasMore": false,
  "totalItems": 1,
  "limit": 100,
  "sortBy": "endTimestamp",
  "items": [
    {
      "cursorId": "PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM_1728067635857",
      "startTimestamp": 1728067635857,
      "balance": 50000000000,
      "vaultId": "PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM",
      "endTimestamp": 1735843635857
    }
  ]
}

getAllGatewayVaults({ cursor, limit, sortBy, sortOrder })

Retrieves all vaults across all gateways, paginated and sorted by the specified criteria. The cursor used for pagination is the last vaultId from the previous request.

const ario = ARIO.init({ rpc });
const vaults = await ario.getAllGatewayVaults({
  limit: 1,
  sortBy: "endTimestamp",
  sortOrder: "desc",
});
Output
{
  "sortOrder": "desc",
  "hasMore": true,
  "totalItems": 95,
  "limit": 1,
  "sortBy": "endTimestamp",
  "items": [
    {
      "cursorId": "PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM_E-QVU3dta36Wia2uQw6tQLjQk7Qw5uN0Z6fUzsoqzUc",
      "gatewayAddress": "PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM",
      "startTimestamp": 1728067635857,
      "balance": 50000000000,
      "vaultId": "E-QVU3dta36Wia2uQw6tQLjQk7Qw5uN0Z6fUzsoqzUc",
      "endTimestamp": 1735843635857
    }
  ],
  "nextCursor": "PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM_E-QVU3dta36Wia2uQw6tQLjQk7Qw5uN0Z6fUzsoqzUc"
}

getWithdrawals({ address, cursor, limit, sortBy, sortOrder })

Returns every pending stake withdrawal owned by address — covering both operator-stake decreases (isDelegate: false) and delegate-stake decreases (isDelegate: true). A withdrawal is claimable when Date.now() >= endTimestamp; call claimWithdrawal({ withdrawalId: item.vaultId }) to release the tokens.

This is the per-owner read needed to drive "you have X claimable withdrawals" UIs without fanning out across every gateway the wallet has interacted with.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });

const withdrawals = await ario.getWithdrawals({
  address: "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
});

const claimable = withdrawals.items.filter(
  (w) => Date.now() >= w.endTimestamp,
);
Output
{
  "hasMore": false,
  "totalItems": 2,
  "limit": 100,
  "items": [
    {
      "cursorId": "8CSdSjf7gXqQ5p1U2qfdwHzVw9sZRYHJpDpV87dnvb4d",
      "vaultId": "0",
      "gatewayAddress": "Bxz7Q2tWfqr9Q5T6cZjUnVxRk9CnHwShfgUaW5fY1Mvr",
      "balance": 50000000000,
      "startTimestamp": 1735843635857,
      "endTimestamp": 1738435635857,
      "isDelegate": true
    },
    {
      "cursorId": "FmWUz4w7vSdLcz1nN8H1n2KkjJgrQQXR1n4kV3WqJ7Hf",
      "vaultId": "1",
      "gatewayAddress": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
      "balance": 10000000000,
      "startTimestamp": 1735843835857,
      "endTimestamp": 1738435835857,
      "isDelegate": false
    }
  ]
}

increaseOperatorStake({ qty })

Increases the callers operator stake. Must be executed with a wallet registered as a gateway operator.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.increaseOperatorStake(
  {
    qty: new ARIOToken(100).toMARIO(),
  },
  {
    tags: [{ name: "App-Name", value: "My-Awesome-App" }],
  },
);

decreaseOperatorStake({ qty })

Decreases the callers operator stake. Must be executed with a wallet registered as a gateway operator. Requires signer to be provided on ARIO.init to sign the transaction.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.decreaseOperatorStake(
  {
    qty: new ARIOToken(100).toMARIO(),
  },
  {
    tags: [{ name: "App-Name", value: "My-Awesome-App" }],
  },
);

redelegateStake({ target, source, stakeQty, vaultId })

Redelegates the stake of a specific address to a new gateway. Vault ID may be optionally included in order to redelegate from an existing withdrawal vault. The redelegation fee is calculated based on the fee rate and the stake amount. Users are allowed one free redelegation every seven epochs. Each additional redelegation beyond the free redelegation will increase the fee by 10%, capping at a 60% redelegation fee.

e.g: If 1000 mARIO is redelegated and the fee rate is 10%, the fee will be 100 mARIO. Resulting in 900 mARIO being redelegated to the new gateway and 100 mARIO being deducted back to the protocol balance.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });

const { id: txId } = await ario.redelegateStake({
  target: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
  source: "HwFceQaMQnOBgKDpnFqCqgwKwEU5LBme1oXRuQOWSRA",
  stakeQty: new ARIOToken(1000).toMARIO(),
  vaultId: "fDrr0_J4Iurt7caNST02cMotaz2FIbWQ4Kcj616RHl3",
});

getRedelegationFee({ address })

Retrieves the fee rate as percentage required to redelegate the stake of a specific address. Fee rate ranges from 0% to 60% based on the number of redelegations since the last fee reset.

const ario = ARIO.init({ rpc });

const fee = await ario.getRedelegationFee({
  address: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
});
Output
{
  "redelegationFeeRate": 10,
  "feeResetTimestamp": 1730996691117
}

getAllDelegates({ cursor, limit, sortBy, sortOrder })

Retrieves all delegates across all gateways, paginated and sorted by the specified criteria. The cursor used for pagination is a cursorId derived from delegate address and the gatewayAddress from the previous request. e.g address_gatewayAddress.

const ario = ARIO.init({ rpc });
const delegates = await ario.getAllDelegates({
  limit: 2,
  sortBy: "startTimestamp",
  sortOrder: "desc",
});
Output
{
  "sortOrder": "desc",
  "hasMore": true,
  "totalItems": 95,
  "limit": 2,
  "sortBy": "startTimestamp",
  "items": [
    {
      "startTimestamp": 1734709397622,
      "cursorId": "9jfM0uzGNc9Mkhjo1ixGoqM7ygSem9wx_EokiVgi0Bs_E-QVU3dta36Wia2uQw6tQLjQk7Qw5uN0Z6fUzsoqzUc",
      "gatewayAddress": "E-QVU3dta36Wia2uQw6tQLjQk7Qw5uN0Z6fUzsoqzUc",
      "address": "9jfM0uzGNc9Mkhjo1ixGoqM7ygSem9wx_EokiVgi0Bs",
      "delegatedStake": 2521349108,
      "vaultedStake": 0
    },
    {
      "startTimestamp": 1734593229454,
      "cursorId": "LtV0aSqgK3YI7c5FmfvZd-wG95TJ9sezj_a4syaLMS8_M0WP8KSzCvKpzC-HPF1WcddLgGaL9J4DGi76iMnhrN4",
      "gatewayAddress": "M0WP8KSzCvKpzC-HPF1WcddLgGaL9J4DGi76iMnhrN4",
      "address": "LtV0aSqgK3YI7c5FmfvZd-wG95TJ9sezj_a4syaLMS8",
      "delegatedStake": 1685148110,
      "vaultedStake": 10000000
    }
  ],
  "nextCursor": "PZ5vIhHf8VY969TxBPQN-rYY9CNFP9ggNsMBqlWUzWM_QGWqtJdLLgm2ehFWiiPzMaoFLD50CnGuzZIPEdoDRGQ"
}

ar.io Name System (ArNS)

resolveArNSName({ name })

Resolves an ArNS name to the underlying data id stored on the names corresponding ANT id.

Resolving a base name
const ario = ARIO.init({ rpc });
const record = await ario.resolveArNSName({ name: "ardrive" });
Output
{
  "name": "ardrive",
  "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
  "txId": "kvhEUsIY5bXe0Wu2-YUFz20O078uYFzmQIO-7brv8qw",
  "type": "lease",
  "ttlSeconds": 3600,
  "undernameLimit": 100
}
Resolving an undername
const ario = ARIO.init({ rpc });
const record = await ario.resolveArNSName({ name: "logo_ardrive" });
Output
{
  "name": "ardrive",
  "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
  "txId": "kvhEUsIY5bXe0Wu2-YUFz20O078uYFzmQIO-7brv8qw",
  "type": "lease",
  "ttlSeconds": 3600,
  "undernameLimit": 100
}

buyRecord({ name, type, years, processId, antState })

Purchases a new ArNS record with the specified name, type, processId, and duration.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

Arguments:

  • name - required: the name of the ArNS record to purchase
  • type - required: the type of ArNS record to purchase
  • processId - optional: the process id of an existing ANT process. If not provided, a new ANT process using the provided signer will be spawned, and the ArNS record will be assigned to that process.
  • years - optional: the duration of the ArNS record in years. If not provided and type is lease, the record will be leased for 1 year. If not provided and type is permabuy, the record will be permanently registered.
  • referrer - optional: track purchase referrals for analytics (e.g. my-app.com)
  • antState - optional (Solana atomic buy only): initial ANT metadata + base @ target to bake into the newly minted ANT in the same transaction, so the name resolves to your content immediately instead of the default AR.IO logo. Fields: transactionId (the @ target — Arweave TX id, or IPFS CID when targetProtocol is 1), targetProtocol (0 = Arweave (default), 1 = IPFS), ticker, logo (43-char Arweave TX id), description (≤ 512 chars), keywords (≤ 16). Ignored (with a warning) when processId is provided — set metadata on an existing ANT via the ANT writeable instead. Note: TTL cannot be set at mint (initialize has no TTL field), so a non-default TTL still needs a post-buy setBaseNameRecord; and a very long description/keywords set may exceed the transaction size limit — keep those on the post-buy path.
// Atomic buy that also points the name at your content in one transaction:
const record = await ario.buyRecord({
  name: "ardrive",
  type: "lease",
  years: 1,
  antState: {
    transactionId: "432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM", // base @ target
    ticker: "ARDRIVE",
    description: "Permanent, decentralized data storage.",
    keywords: ["storage", "permaweb"],
  },
});
const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const record = await ario.buyRecord(
  {
    name: "ardrive",
    type: "lease",
    years: 1,
    processId: "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM", // optional: assign to existing ANT process
    referrer: "my-app.com", // optional: track purchase referrals for analytics
  },
  {
    // optional tags
    tags: [{ name: "App-Name", value: "ArNS-App" }],
    onSigningProgress: (step, event) => {
      console.log(`Signing progress: ${step}`);
      if (step === "spawning-ant") {
        console.log("Spawning ant:", event);
      }
      if (step === "registering-ant") {
        console.log("Registering ant:", event);
      }
      if (step === "verifying-state") {
        console.log("Verifying state:", event);
      }
      if (step === "buying-name") {
        console.log("Buying name:", event);
      }
    },
  },
);

upgradeRecord({ name })

Upgrades an existing leased ArNS record to a permanent ownership. The record must be currently owned by the caller and be of type "lease".

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const record = await ario.upgradeRecord(
  {
    name: "ardrive",
    referrer: "my-app.com", // optional: track purchase referrals for analytics
  },
  {
    // optional tags
    tags: [{ name: "App-Name", value: "ArNS-App" }],
  },
);

getArNSRecord({ name })

Retrieves the record info of the specified ArNS name.

const ario = ARIO.init({ rpc });
const record = await ario.getArNSRecord({ name: "ardrive" });
Output
{
  "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
  "startTimestamp": 1720720819969,
  "endTimestamp": 1752256702026,
  "type": "lease",
  "undernameLimit": 100,
  "purchasePrice": 75541282285
}

getArNSRecords({ cursor, limit, sortBy, sortOrder })

Retrieves all registered ArNS records of the ARIO process, paginated and sorted by the specified criteria. The cursor used for pagination is the last ArNS name from the previous request.

const ario = ARIO.init({ rpc });
// get the newest 100 names
const records = await ario.getArNSRecords({
  limit: 100,
  sortBy: "startTimestamp",
  sortOrder: "desc",
});

Available sortBy options are any of the keys on the record object, e.g. name, processId, endTimestamp, startTimestamp, type, undernames.

Output
{
  "items": [
    {
      "name": "ao",
      "processId": "eNey-H9RB9uCdoJUvPULb35qhZVXZcEXv8xds4aHhkQ",
      "purchasePrice": 75541282285,
      "startTimestamp": 1720720621424,
      "endTimestamp": 1752256702026,
      "type": "permabuy",
      "undernameLimit": 10
    },
    {
      "name": "ardrive",
      "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
      "endTimestamp": 1720720819969,
      "startTimestamp": 1720720620813,
      "purchasePrice": 75541282285,
      "type": "lease",
      "undernameLimit": 100
    },
    {
      "name": "arweave",
      "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
      "endTimestamp": 1720720819969,
      "startTimestamp": 1720720620800,
      "purchasePrice": 75541282285,
      "type": "lease",
      "undernameLimit": 100
    },
    {
      "name": "ar-io",
      "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
      "endTimestamp": 1720720819969,
      "startTimestamp": 1720720619000,
      "purchasePrice": 75541282285,
      "type": "lease",
      "undernameLimit": 100
    },
    {
      "name": "fwd",
      "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
      "endTimestamp": 1720720819969,
      "startTimestamp": 1720720220811,
      "purchasePrice": 75541282285,
      "type": "lease",
      "undernameLimit": 100
    }
    // ...95 other records
  ],
  "hasMore": true,
  "nextCursor": "fwdresearch",
  "totalItems": 21740,
  "sortBy": "startTimestamp",
  "sortOrder": "desc"
}

getArNSRecordsForAddress({ address, cursor, limit, sortBy, sortOrder })

Retrieves all registered ArNS records of the specified address according to the ANTRegistry access control list, paginated and sorted by the specified criteria. The cursor used for pagination is the last ArNS name from the previous request.

const ario = ARIO.init({ rpc });
const records = await ario.getArNSRecordsForAddress({
  address: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
  limit: 100,
  sortBy: "startTimestamp",
  sortOrder: "desc",
});

Available sortBy options are any of the keys on the record object, e.g. name, processId, endTimestamp, startTimestamp, type, undernames.

Output
{
  "limit": 1,
  "totalItems": 31,
  "hasMore": true,
  "nextCursor": "ardrive",
  "items": [
    {
      "startTimestamp": 1740009600000,
      "name": "ardrive",
      "endTimestamp": 1777328018367,
      "type": "permabuy",
      "purchasePrice": 0,
      "undernameLimit": 100,
      "processId": "hpF0HdijWlBLFePjWX6u_-Lg3Z2E_PrP_AoaXDVs0bA"
    }
  ],
  "sortOrder": "desc",
  "sortBy": "startTimestamp"
}

increaseUndernameLimit({ name, qty })

Increases the undername support of a domain up to a maximum of 10k. Domains, by default, support up to 10 undernames.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.increaseUndernameLimit(
  {
    name: "ar-io",
    qty: 420,
    referrer: "my-app.com", // optional: track purchase referrals for analytics
  },
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);

extendLease({ name, years })

Extends the lease of a registered ArNS domain, with an extension of 1-5 years depending on grace period status. Permanently registered domains cannot be extended.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.extendLease(
  {
    name: "ar-io",
    years: 1,
    referrer: "my-app.com", // optional: track purchase referrals for analytics
  },
  // optional additional tags
  { tags: [{ name: "App-Name", value: "My-Awesome-App" }] },
);

getTokenCost({ intent, ...args })

Calculates the price in mARIO to perform the interaction in question, eg a 'Buy-Name' interaction, where args are the specific params for that interaction.

const price = await ario
  .getTokenCost({
    intent: "Buy-Name",
    name: "ar-io",
    type: "permabuy",
  })
  .then((p) => new mARIOToken(p).toARIO()); // convert to ARIO for readability
Output
1642.34

getCostDetails({ intent, fromAddress, fundFrom, ...args})

Calculates the expanded cost details for the interaction in question, e.g a 'Buy-Name' interaction, where args are the specific params for that interaction. The fromAddress is the address that would be charged for the interaction, and fundFrom is where the funds would be taken from, either balance, stakes, or any.

On Solana, the result also includes a gasEstimate — the total SOL (in lamports) the wallet needs to execute the intent: transaction fees (quoted from recent on-chain prioritization fees) plus rent-exempt deposits for the accounts the flow creates. For Buy-Name that covers both transactions (ANT spawn + buy) and the rent for the spawned asset/PDAs and the ArNS record; first-time buyers with no ACL accounts yet are quoted the ACL bootstrap rent as well (pass fromAddress so that check can be made). The fee side is a conservative upper bound: the write path tightens the compute-unit limit from a pre-send simulation, so the landed fee is usually lower.

Gateway operator discount (Solana). ArNS purchases (Buy-Name, Extend-Lease, Increase-Undername-Limit, Upgrade-Name) are 20% cheaper when the payer is a gateway's operator — or, once the gateway is migrated, its operations address — and that gateway is joined, has run for at least 180 days, and passes at least 90% of epochs. Primary-name fees are never discounted. The quote and the purchase methods (buyRecord, buyReturnedName, extendLease, increaseUndernameLimit, upgradeRecord) apply the same rule: by default they use the payer's own gateway and add the discount only when it qualifies (the program rejects a purchase whose discount gateway does not qualify). An operations address names the gateway with discountGatewayAddress (its operator address); naming a gateway that does not qualify is an error. CLI: --discount-gateway-address.

const costDetails = await ario.getCostDetails({
  intent: "Buy-Name",
  fromAddress: "t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3",
  fundFrom: "stakes",
  name: "ar-io",
  type: "permabuy",
});
Output
{
  "tokenCost": 1907401818,
  "discounts": [
    {
      "name": "Gateway Operator",
      "discountTotal": 476850455,
      "multiplier": 0.8
    }
  ],
  "gasEstimate": {
    "totalLamports": 14679680,
    "feeLamports": 23000,
    "baseFeeLamports": 15000,
    "priorityFeeLamports": 8000,
    "rentLamports": 14656680,
    "rentReclaimedLamports": 0,
    "priorityFeeMicroLamports": 10000,
    "computeUnitLimit": 400000,
    "signatureCount": 3,
    "transactionCount": 2
  }
}

getDemandFactor()

Retrieves the current demand factor of the network. The demand factor is a multiplier applied to the cost of ArNS interactions based on the current network demand.

const ario = ARIO.init({ rpc });
const demandFactor = await ario.getDemandFactor();
Output
1.05256

getArNSReturnedNames({ cursor, limit, sortBy, sortOrder })

Retrieves all active returned names of the ARIO process, paginated and sorted by the specified criteria. The cursor used for pagination is the last returned name from the previous request.

const ario = ARIO.init({ rpc });
const returnedNames = await ario.getArNSReturnedNames({
  limit: 100,
  sortBy: "endTimestamp",
  sortOrder: "asc", // return the returned names ending soonest first
});
Output
{
  "items": [
    {
      "name": "permalink",
      "startTimestamp": 1729775641349,
      "endTimestamp": 1730985241349,
      "initiator": "GaQrvEMKBpkjofgnBi_B3IgIDmY_XYelVLB6GcRGrHc",
      "premiumMultiplier": 50
    }
  ],
  "hasMore": false,
  "totalItems": 1,
  "limit": 100,
  "sortBy": "endTimestamp",
  "sortOrder": "asc"
}

getArNSReturnedName({ name })

Retrieves the returned name data for the specified returned name.

const ario = ARIO.init({ rpc });
const returnedName = await ario.getArNSReturnedName({ name: "permalink" });
Output
{
  "name": "permalink",
  "startTimestamp": 1729775641349,
  "endTimestamp": 1730985241349,
  "initiator": "GaQrvEMKBpkjofgnBi_B3IgIDmY_XYelVLB6GcRGrHc",
  "premiumMultiplier": 50
}

Epochs

getCurrentEpoch()

Returns the current epoch data.

const ario = ARIO.init({ rpc });
const epoch = await ario.getCurrentEpoch();
Output
{
  "epochIndex": 0,
  "startHeight": 0,
  "startTimestamp": 1720720621424,
  "endTimestamp": 1752256702026,
  "distributionTimestamp": 1752256702026,
  "observations": {
    "failureSummaries": {
      "-Tk2DDk8k4zkwtppp_XFKKI5oUgh6IEHygAoN7mD-w8": [
        "Ie2wEEUDKoU26c7IuckHNn3vMFdNQnMvfPBrFzAb3NA"
      ]
    },
    "reports": {
      "IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs": "B6UUjKWjjEWDBvDSMXWNmymfwvgR9EN27z5FTkEVlX4"
    }
  },
  "prescribedNames": ["ardrive", "ar-io", "arweave", "fwd", "ao"],
  "prescribedObservers": [
    {
      "gatewayAddress": "2Fk8lCmDegPg6jjprl57-UCpKmNgYiKwyhkU4vMNDnE",
      "observerAddress": "2Fk8lCmDegPg6jjprl57-UCpKmNgYiKwyhkU4vMNDnE",
      "stake": 10000000000,
      "startTimestamp": 1720720621424,
      "stakeWeight": 1,
      "tenureWeight": 0.4494598765432099,
      "gatewayPerformanceRatio": 1,
      "observerPerformanceRatio": 1,
      "gatewayRewardRatioWeight": 1,
      "observerRewardRatioWeight": 1,
      "compositeWeight": 0.4494598765432099,
      "normalizedCompositeWeight": 0.002057032496835938
    }
  ],
  "distributions": {
    "totalEligibleGateways": 1,
    "totalEligibleRewards": 100000000,
    "totalEligibleObserverReward": 100000000,
    "totalEligibleGatewayReward": 100000000
  },
  "arnsStats": {
    "totalReturnedNames": 0,
    "totalActiveNames": 0,
    "totalGracePeriodNames": 0,
    "totalReservedNames": 0
  }
}

getEpoch({ epochIndex })

Returns the epoch data for the specified block height. If no epoch index is provided, the current epoch is used.

const ario = ARIO.init({ rpc });
const epoch = await ario.getEpoch({ epochIndex: 0 });
Output
{
  "epochIndex": 0,
  "startHeight": 0,
  "startTimestamp": 1720720620813,
  "endTimestamp": 1752256702026,
  "distributionTimestamp": 1752256702026,
  "observations": {
    "failureSummaries": {
      "-Tk2DDk8k4zkwtppp_XFKKI5oUgh6IEHygAoN7mD-w8": [
        "Ie2wEEUDKoU26c7IuckHNn3vMFdNQnMvfPBrFzAb3NA"
      ]
    },
    "reports": {
      "IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs": "B6UUjKWjjEWDBvDSMXWNmymfwvgR9EN27z5FTkEVlX4"
    }
  },
  "prescribedNames": ["ardrive", "ar-io", "arweave", "fwd", "ao"],
  "prescribedObservers": [
    {
      "gatewayAddress": "2Fk8lCmDegPg6jjprl57-UCpKmNgYiKwyhkU4vMNDnE",
      "observerAddress": "2Fk8lCmDegPg6jjprl57-UCpKmNgYiKwyhkU4vMNDnE",
      "stake": 10000000000,
      "startTimestamp": 1720720620813,
      "stakeWeight": 1,
      "tenureWeight": 0.4494598765432099,
      "gatewayPerformanceRatio": 1,
      "observerPerformanceRatio": 1,
      "gatewayRewardRatioWeight": 1,
      "observerRewardRatioWeight": 1,
      "compositeWeight": 0.4494598765432099,
      "normalizedCompositeWeight": 0.002057032496835938
    }
  ],
  "distributions": {
    "totalEligibleGateways": 1,
    "totalEligibleRewards": 100000000,
    "totalEligibleObserverReward": 100000000,
    "totalEligibleGatewayReward": 100000000
  },
  "arnsStats": {
    "totalReturnedNames": 0,
    "totalActiveNames": 0,
    "totalGracePeriodNames": 0,
    "totalReservedNames": 0
  }
}

`getEligibleEpochRewards({ epochIndex }, { cursor, limit, sortBy, sortOrder })

Returns the eligible epoch rewards for the specified block height. If no epoch index is provided, the current epoch is used.

const ario = ARIO.init({ rpc });
const rewards = await ario.getEligibleEpochRewards({ epochIndex: 0 });
Output
{
  "sortOrder": "desc",
  "hasMore": true,
  "totalItems": 37,
  "limit": 1,
  "sortBy": "cursorId",
  "items": [
    {
      "cursorId": "xN_aVln30LmoCffwmk5_kRkcyQZyZWy1o_TNtM_CTm0_xN_aVln30LmoCffwmk5_kRkcyQZyZWy1o_TNtM_CTm0",
      "recipient": "xN_aVln30LmoCffwmk5_kRkcyQZyZWy1o_TNtM_CTm0",
      "gatewayAddress": "xN_aVln30LmoCffwmk5_kRkcyQZyZWy1o_TNtM_CTm0",
      "eligibleReward": 2627618704,
      "type": "operatorReward"
    }
  ],
  "nextCursor": "xN_aVln30LmoCffwmk5_kRkcyQZyZWy1o_TNtM_CTm0_xN_aVln30LmoCffwmk5_kRkcyQZyZWy1o_TNtM_CTm0"
}

getObservations({ epochIndex })

Returns the epoch-indexed observation list. If no epoch index is provided, the current epoch is used.

const ario = ARIO.init({ rpc });
const observations = await ario.getObservations();
Output
{
  "failureSummaries": {
    "-Tk2DDk8k4zkwtppp_XFKKI5oUgh6IEHygAoN7mD-w8": [
      "Ie2wEEUDKoU26c7IuckHNn3vMFdNQnMvfPBrFzAb3NA"
    ]
  },
  "reports": {
    "IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs": "B6UUjKWjjEWDBvDSMXWNmymfwvgR9EN27z5FTkEVlX4",
    "Ie2wEEUDKoU26c7IuckHNn3vMFdNQnMvfPBrFzAb3NA": "7tKsiQ2fxv0D8ZVN_QEv29fZ8hwFIgHoEDrpeEG0DIs",
    "osZP4D9cqeDvbVFBaEfjIxwc1QLIvRxUBRAxDIX9je8": "aatgznEvC_UPcxp1v0uw_RqydhIfKm4wtt1KCpONBB0",
    "qZ90I67XG68BYIAFVNfm9PUdM7v1XtFTn7u-EOZFAtk": "Bd8SmFK9-ktJRmwIungS8ur6JM-JtpxrvMtjt5JkB1M"
  }
}

getDistributions({ epochIndex })

Returns the current rewards distribution information. If no epoch index is provided, the current epoch is used.

const ario = ARIO.init({ rpc });
const distributions = await ario.getDistributions({ epochIndex: 0 });
Output
{
  "totalEligibleGateways": 1,
  "totalEligibleRewards": 100000000,
  "totalEligibleObserverReward": 100000000,
  "totalEligibleGatewayReward": 100000000
}

saveObservations({ reportTxId, failedGateways })

Saves the observations of the current epoch. Requires signer to be provided on ARIO.init to sign the transaction.

Note: Requires signer to be provided on ARIO.init to sign the transaction.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });
const { id: txId } = await ario.saveObservations(
  {
    reportTxId: "fDrr0_J4Iurt7caNST02cMotaz2FIbWQ4Kcj616RHl3",
    failedGateways: ["t4Xr0_J4Iurt7caNST02cMotaz2FIbWQ4Kbj616RHl3"],
  },
  {
    tags: [{ name: "App-Name", value: "My-Awesome-App" }],
  },
);

getPrescribedObservers({ epochIndex })

Retrieves the prescribed observers of the ARIO process. To fetch prescribed observers for a previous epoch set the epochIndex to the desired epoch index.

const ario = ARIO.init({ rpc });
const observers = await ario.getPrescribedObservers({ epochIndex: 0 });
Output
[
  {
    "gatewayAddress": "BpQlyhREz4lNGS-y3rSS1WxADfxPpAuing9Lgfdrj2U",
    "observerAddress": "2Fk8lCmDegPg6jjprl57-UCpKmNgYiKwyhkU4vMNDnE",
    "stake": 10000000000,
    "startTimestamp": 1720720620813,
    "stakeWeight": 1,
    "tenureWeight": 0.41453703703703704,
    "gatewayPerformanceRatio": 1,
    "observerPerformanceRatio": 1,
    "gatewayRewardRatioWeight": 1,
    "observerRewardRatioWeight": 1,
    "compositeWeight": 0.41453703703703704,
    "normalizedCompositeWeight": 0.0018972019546783507
  }
]

crankEpochStep(options?)

High-level, permissionless epoch crank. Advances the epoch lifecycle by one step per call and returns the action it took — run it on a loop (this is what the standalone cranker and the observer-embedded cranker do). It owns the whole sequence so you don't orchestrate the individual instructions yourself:

create → tally → prescribe → distribute → close — closing an epoch's observation PDAs first (close_observation) so close_epoch doesn't revert — plus an idle-tail of permissionless maintenance: compound delegate rewards, update_demand_factor, and prune_returned_names. The close path is non-wedging: a cleanup failure never blocks creation of the next epoch.

const ario = ARIO.init({ rpc, rpcSubscriptions, signer });

// one step
const result = await ario.crankEpochStep();
// → { action, epochIndex?, txId?, progress? }
//   action ∈ create | tally | prescribe | distribute | close
//          | close_observation | compound | update_demand_factor
//          | prune_returned_names | idle

// or drive it on an interval
setInterval(async () => {
  const r = await ario.crankEpochStep();
  if (r.action !== 'idle') console.log(r.action, r.epochIndex, r.txId);
}, 60_000);

All options are optional: batchSize, enableClose, epochRetention, enableCompound, compoundMinPendingRewards, enableDemandFactorRoll, enablePrune, pruneBatchSize, nameRegistryAccount.

Primary Names

getPrimaryNames({ cursor, limit, sortBy, sortOrder })

Retrieves all primary names paginated and sorted by the specified criteria. The cursor used for pagination is the last name from the previous request.

const ario = ARIO.init({ rpc });
const names = await ario.getPrimaryNames({
  cursor: "ao", // this is the last name from the previous request
  limit: 1,
  sortBy: "startTimestamp",
  sortOrder: "desc",
});
Output
{
  "sortOrder": "desc",
  "hasMore": true,
  "totalItems": 100,
  "limit": 1,
  "sortBy": "startTimestamp",
  "nextCursor": "arns",
  "items": [
    {
      "name": "arns",
      "owner": "HwFceQaMQnOBgKDpnFqCqgwKwEU5LBme1oXRuQOWSRA",
      "processId": "bh9l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM",
      "startTimestamp": 1719356032297
    }
  ]
}

getPrimaryName({ name, address })

Retrieves the primary name for a given name or address.

const ario = ARIO.init({ rpc });
const name = await ario.g

版本与发布记录

@ar.io/sdk 共发布 539 个版本,首次发布于 2024/03/13;过去 12 个月发布了 129 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.5.2latest2026/10/1028 天前
4.5.2-alpha.1alpha2026/10/0929 天前
4.5.12026/10/0929 天前
4.5.1-alpha.52026/10/0929 天前
4.5.1-alpha.42026/10/0929 天前
4.5.1-alpha.32026/09/301 个月前

其他发布通道:beta → 3.13.0-beta.1,solana → 4.0.0-solana.40,alpha → 4.5.2-alpha.1。

关于 @ar.io/sdk 的常见问题

如何安装 @ar.io/sdk?

在项目目录运行 npm install @ar.io/sdk,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 ar.io,可以用 npx ar.io 直接运行。

@ar.io/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@ar.io/sdk 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@ar.io/sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@ar.io/sdk 可以商用吗?

@ar.io/sdk 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@ar.io/sdk 的下载量有多少?

根据 npm 官方下载统计,@ar.io/sdk 在 2026/10/07 – 2026/11/05 这 30 天内被下载 9,165 次,日均约 306 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ar.io/sdk 还在维护吗?

最新版本 4.5.2 发布于 2026/10/10(28 天前);至今共发布 539 个版本,其中过去 12 个月发布了 129 个;首次发布于 2024/03/13。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。