git.delta.rocks / unique-network / refs/commits / d73f42eb761b

difftreelog

source

js-packages/scripts/hrmpchannel.ts6.8 KiBsourcehistory
1import {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) => {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(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) => {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(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  const relayUrl = process.argv[2]63  const uniqueParachainUrl = process.argv[3];64  const otherParachainUrl = process.argv[4];65  const op = process.argv[5];6667  const relayWsProvider = new WsProvider(relayUrl);68  const relayApi = await ApiPromise.create({provider: relayWsProvider});6970  const uniqueWsProvider = new WsProvider(uniqueParachainUrl);71  const uniqueApi = await ApiPromise.create({provider: uniqueWsProvider});7273  const otherWsProvider = new WsProvider(otherParachainUrl);74  const otherApi = await ApiPromise.create({provider: otherWsProvider});7576  const uniqueParaId = await uniqueApi.query.parachainInfo.parachainId()77    .then(data => data.toJSON() as number);7879  const otherParaId = await otherApi.query.parachainInfo.parachainId()80    .then(data => data.toJSON() as number);8182  const relayDecimals = await relayApi.rpc.system.properties()83    .then(data => data.tokenDecimals.unwrap()[0].toNumber());8485  const relayFee = 2n * BigInt(10 ** relayDecimals);8687  let encodedRelayCall: string;88  if(op == 'open') {89    encodedRelayCall = await proposeOpenChannel(relayApi, relayFee, uniqueParaId, otherParaId);90  } else if(op == 'accept') {91    encodedRelayCall = await proposeAcceptChannel(relayApi, relayFee, otherParaId, uniqueParaId);92  } else {93    throw Error(`Unknown hrmp channel operation: ${op}`);94  }9596  const proposal = uniqueApi.tx.polkadotXcm.send(97    {98        V3: {99            parents: 1,100            interior: 'Here',101        }102    },103    {104        V3: [105            {106                WithdrawAsset: [107                    {108                        id: {109                            Concrete: {110                                parents: 0,111                                interior: 'Here',112                            },113                        },114                        fun: {115                            Fungible: relayFee,116                        },117                    },118                ],119            },120            {121                BuyExecution: {122                    fees: {123                        id: {124                            Concrete: {125                                parents: 0,126                                interior: 'Here',127                            },128                        },129                        fun: {130                            Fungible: relayFee,131                        },132                    },133                    weightLimit: 'Unlimited',134                },135            },136            {137                Transact: {138                    originKind: 'Native',139                    requireWeightAtMost: {140                        refTime: 1000000000,141                        proofSize: 65536,142                    },143                    call: {144                        encoded: encodedRelayCall,145                    },146                },147            },148            'RefundSurplus',149            {150                DepositAsset: {151                    assets: {152                        Wild: {153                            AllCounted: 1,154                        },155                    },156                    beneficiary: {157                        parents: 0,158                        interior: {159                            X1: {160                                Parachain: uniqueParaId,161                            },162                        },163                    },164                },165            },166        ],167    },168  ).method.toHex();169170  const councilMembers = (await uniqueApi.query.council.members()).toJSON() as any[];171  const councilProposalThreshold = Math.floor(councilMembers.length / 2) + 1;172173  const democracyProposalHash = blake2AsHex(proposal, 256);174  const democracyProposalPreimage = uniqueApi.tx.preimage.notePreimage(proposal).method.toHex();175176  const democracyProposal = uniqueApi.tx.democracy.externalProposeDefault({177    Legacy: democracyProposalHash,178  });179180  const councilProposal = uniqueApi.tx.council.propose(181    councilProposalThreshold,182    democracyProposal,183    democracyProposal.method.encodedLength,184  ).method.toHex();185186  const proposeBatch = uniqueApi.tx.utility.batchAll([187    democracyProposalPreimage,188    councilProposal,189  ]);190191  const encodedCall = proposeBatch.method.toHex();192193  console.log('-----------------');194  console.log('Council Proposal: ', `https://polkadot.js.org/apps/?rpc=${uniqueParachainUrl}#/extrinsics/decode/${encodedCall}`);195  console.log('-----------------');196197  await relayApi.disconnect();198  await uniqueApi.disconnect();199  await otherApi.disconnect();200}201202await main();