From d9584873e5ddee8ed20c36e8365be8064a3e0aee Mon Sep 17 00:00:00 2001 From: cuteolaf Date: Sun, 12 May 2024 23:55:52 -0700 Subject: [PATCH] test tx fee handler (#124) * test tx fee handler * fix test --- e2e_tests/common.ts | 42 ++++++++++++++++++----- e2e_tests/fee-payment/native.ts | 61 +++++++++++++++++++++++++++++---- package.json | 8 +++-- 3 files changed, 93 insertions(+), 18 deletions(-) diff --git a/e2e_tests/common.ts b/e2e_tests/common.ts index f6d7991b..20c8fe35 100644 --- a/e2e_tests/common.ts +++ b/e2e_tests/common.ts @@ -1,6 +1,8 @@ import { ApiPromise, Keyring } from '@polkadot/api'; import { SignerOptions, SubmittableExtrinsic } from '@polkadot/api/types'; import { KeyringPair } from '@polkadot/keyring/types'; +import { stringToU8a } from '@polkadot/util'; +import { encodeAddress } from '@polkadot/util-crypto'; const RELAY_ASSET_ID = 1; @@ -10,15 +12,15 @@ async function submitExtrinsic( options: Partial ): Promise { return new Promise((resolve, reject) => { - const unsub = call.signAndSend(signer, options, (result) => { - console.log(`Current status is ${result.status}`); - if (result.status.isInBlock) { - console.log(`Transaction included at blockHash ${result.status.asInBlock}`); - } else if (result.status.isFinalized) { - console.log(`Transaction finalized at blockHash ${result.status.asFinalized}`); + const unsub = call.signAndSend(signer, options, ({ status, isError }) => { + console.log(`Current status is ${status}`); + if (status.isInBlock) { + console.log(`Transaction included at blockHash ${status.asInBlock}`); + } else if (status.isFinalized) { + console.log(`Transaction finalized at blockHash ${status.asFinalized}`); unsub.then(); return resolve(); - } else if (result.isError) { + } else if (isError) { console.log('Transaction error'); unsub.then(); return reject(); @@ -107,4 +109,28 @@ async function sleep(milliseconds: number) { return new Promise((resolve) => setTimeout(resolve, milliseconds)); } -export { RELAY_ASSET_ID, setupRelayAsset, sleep, submitExtrinsic, transferRelayAssetToPara }; +const getAddressFromModuleId = (moduleId: string): string => { + if (moduleId.length !== 8) { + console.log('Module Id must be 8 characters (i.e. `py/trsry`)'); + return ''; + } + const address = stringToU8a(('modl' + moduleId).padEnd(32, '\0')); + return encodeAddress(address); +}; + +const getFreeBalance = async (api: ApiPromise, address: string): Promise => { + const { + data: { free }, + } = (await api.query.system.account(address)).toJSON() as any; + return BigInt(free); +}; + +export { + RELAY_ASSET_ID, + setupRelayAsset, + sleep, + submitExtrinsic, + transferRelayAssetToPara, + getAddressFromModuleId, + getFreeBalance +}; diff --git a/e2e_tests/fee-payment/native.ts b/e2e_tests/fee-payment/native.ts index 13a3d4e1..4eef9922 100644 --- a/e2e_tests/fee-payment/native.ts +++ b/e2e_tests/fee-payment/native.ts @@ -1,18 +1,65 @@ import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; -import { submitExtrinsic } from '../common'; +import assert from 'node:assert'; +import { getAddressFromModuleId, getFreeBalance } from '../common'; async function run(nodeName: string, networkInfo: any, _jsArgs: any) { - const { wsUri } = networkInfo.nodesByName[nodeName]; - const api = await ApiPromise.create({ provider: new WsProvider(wsUri) }); + const { wsUri: regionXUri } = networkInfo.nodesByName[nodeName]; + const regionXApi = await ApiPromise.create({ provider: new WsProvider(regionXUri) }); // account to submit tx const keyring = new Keyring({ type: 'sr25519' }); const alice = keyring.addFromUri('//Alice'); - const bob = keyring.addFromUri('//Bob'); - const call = api.tx.balances.transferKeepAlive(bob.address, 10n ** 6n); - const sudo = api.tx.sudo.sudo(call); - await submitExtrinsic(alice, sudo, {}); + const treasuryId = regionXApi.consts.treasury.palletId.toHuman() as string; + const treasuryAccount = getAddressFromModuleId(treasuryId); + + const podId = 'PotStake'; // FIXME: remove this hard-coded constant and fetch the on-chain value. + const potAccount = getAddressFromModuleId(podId); + + const treasuryBalanceOld = await getFreeBalance(regionXApi, treasuryAccount); + const potBalanceOld = await getFreeBalance(regionXApi, potAccount); + + const call = regionXApi.tx.system.remark('0x44'); + + let fee = BigInt(0), + tips = BigInt(0); + + const promise: Promise = new Promise((resolve, reject) => { + const unsub = call.signAndSend(alice, { tip: 1_000_000_000 }, ({ status, isError, events }) => { + console.log(`Current status is ${status}`); + if (status.isInBlock) { + console.log(`Transaction included at blockHash ${status.asInBlock}`); + } else if (status.isFinalized) { + console.log(`Transaction finalized at blockHash ${status.asFinalized}`); + for (const event of events) { + const { + event: { data, method, section }, + } = event; + if (section === 'transactionPayment' && method === 'TransactionFeePaid') { + const args = data.toJSON() as [string, number, number]; + tips = BigInt(args[2]); + fee = BigInt(args[1]) - tips; + } + } + + unsub.then(); + return resolve(); + } else if (isError) { + console.log('Transaction error'); + unsub.then(); + return reject(); + } + }); + }); + await promise; + const treasuryBalanceNew = await getFreeBalance(regionXApi, treasuryAccount); + const potBalanceNew = await getFreeBalance(regionXApi, potAccount); + + const fee2Treasury = (fee * 60n) / 100n; + const fee2Collators = fee - fee2Treasury + tips; + + assert.equal(treasuryBalanceNew - treasuryBalanceOld, fee2Treasury); + assert.equal(potBalanceNew - potBalanceOld, fee2Collators); } export { run }; diff --git a/package.json b/package.json index 8e89e0a5..500c81b0 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,14 @@ "dependencies": { "@polkadot/api": "^11.0.2", "@polkadot/keyring": "^12.6.2", + "@polkadot/util": "^12.6.2", + "@polkadot/util-crypto": "^12.6.2", "coretime-utils": "^0.3.2", "typescript": "^4.1.6" }, "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.48.1", + "@typescript-eslint/parser": "^5.48.1", "eslint": "8.31.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", @@ -26,8 +30,6 @@ "eslint-plugin-import": "^2.27.4", "eslint-plugin-prettier": "^4.0.0", "prettier": "^2.8.1", - "prettier-plugin-organize-imports": "^3.2.0", - "@typescript-eslint/eslint-plugin": "^5.48.1", - "@typescript-eslint/parser": "^5.48.1" + "prettier-plugin-organize-imports": "^3.2.0" } }