difftreelog
feat skip-balance-check option
in: master
1 file changed
js-packages/scripts/hrmpchannel.tsdiffbeforeafterboth1import {ApiPromise, WsProvider} from '@polkadot/api';2import {blake2AsHex, encodeAddress} from '@polkadot/util-crypto';34export const paraChildSovereignAccount = (relayApi: ApiPromise, paraid: number) => {5 // We are getting a *child* parachain sovereign account,6 // so we need a child prefix: encoded(b"para") == 0x706172617 const childPrefix = '70617261';89 const encodedParaId = relayApi10 .createType('u32', paraid)11 .toHex(true)12 .substring(2 /* skip 0x */);1314 const addrBytesLen = 32;15 const byteLenInHex = 2;16 return '0x' + (childPrefix + encodedParaId).padEnd(addrBytesLen * byteLenInHex, '0');17};1819const proposeOpenChannel = async (relayApi: ApiPromise, relayFee: bigint, senderParaId: number, receiverParaId: number, skipBalanceCheck: boolean) => {20 const conf: any = await relayApi.query.configuration.activeConfig()21 .then(data => data.toJSON());22 const maxCapacity = conf.hrmpChannelMaxCapacity;23 const maxSize = conf.hrmpChannelMaxMessageSize;2425 const senderDeposit = BigInt(conf.hrmpSenderDeposit);2627 const requiredBalance = relayFee + senderDeposit;28 const sovereignAccount = paraChildSovereignAccount(relayApi, senderParaId);29 const balance = await relayApi.query.system.account(sovereignAccount)30 .then(accountInfo => (accountInfo.toJSON() as any).data.free as bigint);3132 if(!skipBalanceCheck && balance < requiredBalance) {33 throw Error(`Not enough balance on the sender's sovereign account: balance(${balance}) < requiredBalance(${requiredBalance})`);34 }3536 return relayApi.tx.hrmp.hrmpInitOpenChannel(37 receiverParaId,38 maxCapacity,39 maxSize,40 ).method.toHex();41};4243const proposeAcceptChannel = async (relayApi: ApiPromise, relayFee: bigint, senderParaId: number, recipientParaId: number, skipBalanceCheck: boolean) => {44 const conf: any = await relayApi.query.configuration.activeConfig()45 .then(data => data.toJSON());46 const recipientDeposit = BigInt(conf.hrmpRecipientDeposit);4748 const requiredBalance = relayFee + recipientDeposit;4950 const sovereignAccount = paraChildSovereignAccount(relayApi, recipientParaId);51 const balance = await relayApi.query.system.account(sovereignAccount)52 .then(accountInfo => (accountInfo.toJSON() as any).data.free as bigint);5354 if(!skipBalanceCheck && balance < requiredBalance) {55 throw Error(`Not enough balance on the recipient's sovereign account: balance(${balance}) < requiredBalance(${requiredBalance})`);56 }5758 return relayApi.tx.hrmp.hrmpAcceptOpenChannel(senderParaId).method.toHex();59};6061async function main() {62 let skipBalanceCheck;63 if(process.argv.length == 6) {64 skipBalanceCheck = false;65 }66 else if(process.argv.length == 7 && process.argv[6] == 'skip-balance-check') {67 skipBalanceCheck = true;68 } else {69 console.log('Usage: yarn hrmpChannel <RELAY_URL> <OUR_CHAIN_URL> <OTHER_CHAIN_URL> <open | accept> [skip-balance-check]');70 process.exit(1);71 }7273 const relayUrl = process.argv[2];74 const uniqueParachainUrl = process.argv[3];75 const otherParachainUrl = process.argv[4];76 const op = process.argv[5];7778 const relayWsProvider = new WsProvider(relayUrl);79 const relayApi = await ApiPromise.create({provider: relayWsProvider});8081 const uniqueWsProvider = new WsProvider(uniqueParachainUrl);82 const uniqueApi = await ApiPromise.create({provider: uniqueWsProvider});8384 const otherWsProvider = new WsProvider(otherParachainUrl);85 const otherApi = await ApiPromise.create({provider: otherWsProvider});8687 const uniqueParaId = await uniqueApi.query.parachainInfo.parachainId()88 .then(data => data.toJSON() as number);8990 const otherParaId = await otherApi.query.parachainInfo.parachainId()91 .then(data => data.toJSON() as number);9293 const relayDecimals = await relayApi.rpc.system.properties()94 .then(data => data.tokenDecimals.unwrap()[0].toNumber());9596 const relayFee = 2n * BigInt(10 ** relayDecimals);9798 let encodedRelayCall: string;99100 if(op == 'open') {101 encodedRelayCall = await proposeOpenChannel(relayApi, relayFee, uniqueParaId, otherParaId, skipBalanceCheck);102 } else if(op == 'accept') {103 encodedRelayCall = await proposeAcceptChannel(relayApi, relayFee, otherParaId, uniqueParaId, skipBalanceCheck);104 } else {105 throw Error(`Unknown hrmp channel operation: ${op}`);106 }107108 const proposal = uniqueApi.tx.polkadotXcm.send(109 {110 V3: {111 parents: 1,112 interior: 'Here',113 },114 },115 {116 V3: [117 {118 WithdrawAsset: [119 {120 id: {121 Concrete: {122 parents: 0,123 interior: 'Here',124 },125 },126 fun: {127 Fungible: relayFee,128 },129 },130 ],131 },132 {133 BuyExecution: {134 fees: {135 id: {136 Concrete: {137 parents: 0,138 interior: 'Here',139 },140 },141 fun: {142 Fungible: relayFee,143 },144 },145 weightLimit: 'Unlimited',146 },147 },148 {149 Transact: {150 originKind: 'Native',151 requireWeightAtMost: {152 refTime: 1000000000,153 proofSize: 65536,154 },155 call: {156 encoded: encodedRelayCall,157 },158 },159 },160 'RefundSurplus',161 {162 DepositAsset: {163 assets: {164 Wild: {165 AllCounted: 1,166 },167 },168 beneficiary: {169 parents: 0,170 interior: {171 X1: {172 Parachain: uniqueParaId,173 },174 },175 },176 },177 },178 ],179 },180 ).method.toHex();181182 const councilMembers = (await uniqueApi.query.council.members()).toJSON() as any[];183 const councilProposalThreshold = Math.floor(councilMembers.length / 2) + 1;184185 const democracyProposalHash = blake2AsHex(proposal, 256);186 const democracyProposalPreimage = uniqueApi.tx.preimage.notePreimage(proposal).method.toHex();187188 const democracyProposal = uniqueApi.tx.democracy.externalProposeDefault({189 Legacy: democracyProposalHash,190 });191192 const councilProposal = uniqueApi.tx.council.propose(193 councilProposalThreshold,194 democracyProposal,195 democracyProposal.method.encodedLength,196 ).method.toHex();197198 const proposeBatch = uniqueApi.tx.utility.batchAll([199 democracyProposalPreimage,200 councilProposal,201 ]);202203 const encodedCall = proposeBatch.method.toHex();204205 console.log('-----------------');206 console.log('Council Proposal: ', `https://polkadot.js.org/apps/?rpc=${uniqueParachainUrl}#/extrinsics/decode/${encodedCall}`);207 console.log('-----------------');208209 await relayApi.disconnect();210 await uniqueApi.disconnect();211 await otherApi.disconnect();212}213214await main();