ar.io Logoar.io Documentation
ar.io SDKARIO Contract

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()

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()

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()

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()

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()

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()

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()

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:

createtallyprescribedistributeclose — 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.

How is this guide?