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.
Requires node>=v18.0.0.
npm install @ar.io/sdk
or
yarn add @ar.io/sdk
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"
}
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.
@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).[!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,processandbuffer. 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();
<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>
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
nodenextmodule resolution with.jsextensions in relative imports).
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, andLastDistributedEpochIndexare placeholders on Solana (returned for backwards-compatible field shape with consumer code).totalSupply/protocolBalanceare live reads from theArioConfigPDA;epochSettingsis live from theEpochSettingsPDA. Seesrc/solana/io-readable.tsfor 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 tokenscirculating - the total supply minus locked, withdrawn, delegated, and stakedlocked - tokens that are locked in the protocol (a.k.a. vaulted)withdrawn - tokens that have been withdrawn from the protocol by operators and delegatorsdelegated - tokens that have been delegated to gatewaysstaked - tokens that are staked in the protocol by gateway operatorsprotocolBalance - 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(),
});
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.
getVault({ address, vaultId })Retrieves the locked-balance user vault of the ARIO process by the specified wallet address and vault ID.
```typescript const ario = ARIO.init({ rpc }); const
$ claude mcp add ar-io-sdk \
-- python -m otcore.mcp_server <graph>