Skip to main content

Funding Beacons

Each Beacon has an associated sponsor wallet. For the respective Beacon to stay active, the sponsor wallet must be funded.

Sponsor wallet is where you fund. The Beacons are updated by their sponsor wallets, which means the gas cost of the update is paid by the sponsor wallet. You can see available wallets for corresponding chains and beacons in here.

What happens if a sponsor wallet runs out of currency?

It will stop updating. If you want the feed to start operating again, just fund the sponsor wallet and wait up to 15 minutes for it to go back online.

How to derive sponsor wallet addresses?

This section is for advanced users only, you don't need to know this to use Nodary feeds.

While deriving a sponsor wallet address, the deviation threshold is mapped to where 100% is 1e8. Then mapped deviation threshold, deviation reference, and heartbeat interval are encoded to one value, encodedConditions. Sponsor address is taken as the first 40 hexadecimal digits of the hash of beaconId and encodedConditions. Finally, using Nodary's Airnode extended public key with the sponsor address, the sponsor wallet address is derived.

Here's a snippet that demonstrates how we do this

import ethers from "ethers";

function deriveWalletPathFromSponsorAddress(sponsorAddress, protocolId) {
const sponsorAddressBN = ethers.BigNumber.from(sponsorAddress);
const paths = [];
for (let i = 0; i < 6; i++) {
const shiftedSponsorAddressBN = sponsorAddressBN.shr(31 * i);
paths.push(shiftedSponsorAddressBN.mask(31).toString());
}
return `${protocolId}/${paths.join("/")}`;
}
const PROTOCOL_ID_AIRSEEKER = "5";
const beaconId =
"0x7713f1e0aa944ed993b2de888d9c01c9088c0eacdddf580b92cff831525a2793";
const deviationReference = 0;
const heartbeatInterval = 86400;
const updateInterval = 60;
const deviationThreshold = 1.0;

// Map the threshold where 100% is equal to 1e8
const deviationThresholdMapped = ethers.BigNumber.from(
Math.trunc(deviationThreshold * HUNDRED_PERCENT),
).div(ethers.BigNumber.from(100));
const encodedConditions = ethers.utils.defaultAbiCoder.encode(
["uint256", "int224", "uint256"],
[deviationThresholdMapped, deviationReference, heartbeatInterval],
);
const sponsorAddress = ethers.utils
.keccak256(
ethers.utils.solidityPack(
["bytes32", "bytes"],
[beaconId, encodedConditions],
),
)
.substring(0, 42);
const airnodeXPub =
"xpub6BuqcSvAqaZTNo47kddwx8HYbxviHE86NDfQANnEK9z3gnkkN9LisNhYc5kCtheJ1jQxpby28PiMYX595yRnkp11rDFPvvUrpg2Siyn6vGk";
const airnodeHdNode = ethers.utils.HDNode.fromExtendedKey(airnodeXPub);
const sponsorWallet = airnodeHdNode.derivePath(
deriveWalletPathFromSponsorAddress(sponsorAddress, PROTOCOL_ID_AIRSEEKER),
).address;
console.log(sponsorWallet.address);