Skip to main content

Updated Sponsor Wallet Derivation

· 2 min read
Nodary

The way the sponsor wallets are derived is changed to provide users more control over beacons and many more upcoming features. Due to this change, all sponsor wallet and beacon ids are changed. This is a one-time-only breaking change. Previously deployed beacon ids will be active until March 1, 2023.

Previous sponsor wallet derivation

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 sponsorAddress = beaconId.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);

New sponsor wallet derivation

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