Files
pwap/web/scripts/create-staking-pools.mjs
T

131 lines
4.2 KiB
JavaScript

/**
* Script to create LP staking reward pools
* Run with: node scripts/create-staking-pools.mjs
*
* Requires MNEMONIC environment variable with admin wallet seed
*/
import { ApiPromise, WsProvider } from '@pezkuwi/api';
import { Keyring } from '@pezkuwi/api';
const ASSET_HUB_RPC = 'wss://asset-hub-rpc.pezkuwichain.io';
// LP Token IDs (from assetConversion pools)
const LP_TOKENS = {
'HEZ-PEZ': 0,
'HEZ-USDT': 1,
'HEZ-DOT': 2,
};
// Reward token: PEZ (asset ID 1)
const REWARD_ASSET_ID = 1;
// Reward rate per block (in smallest units - 12 decimals)
// 0.01 PEZ per block = 10_000_000_000 (10^10)
const REWARD_RATE_PER_BLOCK = '10000000000';
// 100 years in blocks (6 second blocks)
const BLOCKS_100_YEARS = 525600000;
async function main() {
const mnemonic = process.env.MNEMONIC;
if (!mnemonic) {
console.error('ERROR: Set MNEMONIC environment variable');
console.log('Usage: MNEMONIC="foam hope topic phone year fold lyrics biology erosion feed false island" node scripts/create-staking-pools.mjs');
process.exit(1);
}
const provider = new WsProvider(ASSET_HUB_RPC);
const api = await ApiPromise.create({ provider });
const keyring = new Keyring({ type: 'sr25519' });
const admin = keyring.addFromMnemonic(mnemonic);
console.log('Admin address:', admin.address);
// Get current block for expiry calculation
const header = await api.rpc.chain.getHeader();
const currentBlock = header.number.toNumber();
const expiryBlock = currentBlock + BLOCKS_100_YEARS;
console.log('Current block:', currentBlock);
console.log('Expiry block (100 years):', expiryBlock);
// Format asset location for LP tokens (poolAssets pallet, instance 55)
const formatLpTokenLocation = (lpTokenId) => ({
parents: 0,
interior: { X2: [{ PalletInstance: 55 }, { GeneralIndex: lpTokenId }] }
});
// Format asset location for reward token (assets pallet, instance 50)
const formatRewardTokenLocation = (assetId) => ({
parents: 0,
interior: { X2: [{ PalletInstance: 50 }, { GeneralIndex: assetId }] }
});
// Expiry format: { At: blockNumber }
const expiry = { At: expiryBlock };
console.log('\n=== Creating Staking Pools ===\n');
for (const [poolName, lpTokenId] of Object.entries(LP_TOKENS)) {
console.log(`Creating pool for ${poolName} (LP Token #${lpTokenId})...`);
const stakedAssetLocation = formatLpTokenLocation(lpTokenId);
const rewardAssetLocation = formatRewardTokenLocation(REWARD_ASSET_ID);
try {
const tx = api.tx.assetRewards.createPool(
stakedAssetLocation,
rewardAssetLocation,
REWARD_RATE_PER_BLOCK,
expiry,
admin.address // admin
);
await new Promise((resolve, reject) => {
tx.signAndSend(admin, ({ status, events, dispatchError }) => {
if (status.isInBlock) {
console.log(` In block: ${status.asInBlock.toHex()}`);
} else if (status.isFinalized) {
console.log(` Finalized: ${status.asFinalized.toHex()}`);
if (dispatchError) {
if (dispatchError.isModule) {
const decoded = api.registry.findMetaError(dispatchError.asModule);
reject(new Error(`${decoded.section}.${decoded.name}: ${decoded.docs.join(' ')}`));
} else {
reject(new Error(dispatchError.toString()));
}
} else {
// Find pool created event
const poolCreated = events.find(({ event }) =>
event.section === 'assetRewards' && event.method === 'PoolCreated'
);
if (poolCreated) {
console.log(` ✅ Pool created:`, poolCreated.event.data.toHuman());
}
resolve();
}
}
});
});
console.log(`${poolName} staking pool created!\n`);
} catch (err) {
console.error(` ❌ Failed to create ${poolName} pool:`, err.message);
}
}
// List created pools
console.log('\n=== Created Pools ===');
const pools = await api.query.assetRewards.pools.entries();
for (const [key, value] of pools) {
console.log('Pool ID:', key.args[0].toString());
console.log(' Config:', value.toHuman());
}
await api.disconnect();
console.log('\nDone!');
}
main().catch(console.error);