From e7fe7ed00460ebba52459aac6c04b6ba666eab39 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Fri, 15 Sep 2023 19:02:45 +0300 Subject: [PATCH 1/4] add voting registry test --- .../parallel/voting_registry.test.ts | 850 ++++++++++++++++++ 1 file changed, 850 insertions(+) create mode 100644 src/testcases/parallel/voting_registry.test.ts diff --git a/src/testcases/parallel/voting_registry.test.ts b/src/testcases/parallel/voting_registry.test.ts new file mode 100644 index 00000000..8fddf992 --- /dev/null +++ b/src/testcases/parallel/voting_registry.test.ts @@ -0,0 +1,850 @@ +import { + NEUTRON_DENOM, + WalletWrapper, + CosmosWrapper, +} from '../../helpers/cosmos'; +import { NeutronContract } from '../../helpers/types'; +import { getHeight } from '../../helpers/wait'; +import { TestStateLocalCosmosTestNet } from '../common_localcosmosnet'; + +// general contract keys used across the tests +const VOTING_REGISTRY_CONTRACT_KEY = 'VOTING_REGISTRY'; +const NEUTRON_VAULT_CONTRACT_KEY = 'NEUTRON_VAULT'; +// specific contract keys used across the tests +const NEUTRON_VAULT_1_CONTRACT_KEY = 'NEUTRON_VAULT_1'; +const NEUTRON_VAULT_2_CONTRACT_KEY = 'NEUTRON_VAULT_2'; +const NEUTRON_VAULT_3_CONTRACT_KEY = 'NEUTRON_VAULT_3'; + +describe('Neutron / Voting Registry', () => { + let testState: TestStateLocalCosmosTestNet; + let neutronChain: CosmosWrapper; + let cmInstantiator: WalletWrapper; + let cmDaoMember: WalletWrapper; + let contractAddresses: Record = {}; + let votingRegistryAddr: string; + let vault1Addr: string; + let vault2Addr: string; + let vault3Addr: string; + + let vpHistory: VotingPowerInfoHistory; + // initial bondings + const vault1Bonding = 1_000_000; + const vault2Bonding = 500_000; + // additional bonding amount + const vault1AddBonding = 10_000; + // partial unbonding amount + const vault1Unbonding = 100_000; + // bonding to an additional vault + const vault3Bonding = 5_000_000; + + beforeAll(async () => { + testState = new TestStateLocalCosmosTestNet(); + await testState.init(); + neutronChain = new CosmosWrapper( + testState.sdk1, + testState.blockWaiter1, + NEUTRON_DENOM, + ); + cmInstantiator = new WalletWrapper( + neutronChain, + testState.wallets.qaNeutronThree.genQaWal1, + ); + cmDaoMember = new WalletWrapper( + neutronChain, + testState.wallets.qaNeutron.genQaWal1, + ); + contractAddresses = await deployContracts(neutronChain, cmInstantiator); + votingRegistryAddr = contractAddresses[VOTING_REGISTRY_CONTRACT_KEY]; + vault1Addr = contractAddresses[NEUTRON_VAULT_1_CONTRACT_KEY]; + vault2Addr = contractAddresses[NEUTRON_VAULT_2_CONTRACT_KEY]; + vault3Addr = contractAddresses[NEUTRON_VAULT_3_CONTRACT_KEY]; + + vpHistory = initVotingPowerInfoHistory(); + }); + + describe('assert init state', () => { + test('check voting vaults', async () => { + const votingVaults = await getVotingVaults( + neutronChain, + votingRegistryAddr, + ); + // initially there are only vault1 and vault2 in the registry, vault3 is to be added later + expect(votingVaults.length).toBe(2); + expect(votingVaults).toContainEqual({ + address: vault1Addr, + description: NEUTRON_VAULT_1_CONTRACT_KEY, + name: NEUTRON_VAULT_1_CONTRACT_KEY, + state: 'Active', + }); + expect(votingVaults).toContainEqual({ + address: vault2Addr, + description: NEUTRON_VAULT_2_CONTRACT_KEY, + name: NEUTRON_VAULT_2_CONTRACT_KEY, + state: 'Active', + }); + }); + test('check voting power', async () => { + const vpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + ); + expect(vpInfo.vault1Power).toBe(0); + expect(vpInfo.vault1TotalPower).toBe(0); + expect(vpInfo.vault2Power).toBe(0); + expect(vpInfo.vault2TotalPower).toBe(0); + expect(vpInfo.vault3Power).toBe(0); + expect(vpInfo.vault3TotalPower).toBe(0); + expect(vpInfo.votingRegistryPower).toBe(0); + expect(vpInfo.votingRegistryTotalPower).toBe(0); + }); + }); + + describe('accrue init voting power', () => { + test('bond funds', async () => { + await bondFunds(cmDaoMember, vault1Addr, vault1Bonding.toString()); + await bondFunds(cmDaoMember, vault2Addr, vault2Bonding.toString()); + // we bond to vault3 in advance regardless of this is not in the registry yet + await bondFunds(cmDaoMember, vault3Addr, vault3Bonding.toString()); + await neutronChain.blockWaiter.waitBlocks(1); + }); + + test('check accrued voting power', async () => { + const vpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + ); + expect(vpInfo.vault1Power).toEqual(vault1Bonding); + expect(vpInfo.vault1TotalPower).toEqual(vault1Bonding); + expect(vpInfo.vault2Power).toEqual(vault2Bonding); + expect(vpInfo.vault2TotalPower).toEqual(vault2Bonding); + expect(vpInfo.vault3Power).toEqual(vault3Bonding); + expect(vpInfo.vault3TotalPower).toEqual(vault3Bonding); + // no vault3 in the registry yet + expect(vpInfo.votingRegistryPower).toEqual(vault1Bonding + vault2Bonding); + expect(vpInfo.votingRegistryTotalPower).toEqual( + vault1Bonding + vault2Bonding, + ); + vpHistory.init = vpInfo; + }); + }); + + describe('VP on bond and unbond', () => { + test('bond funds', async () => { + await bondFunds(cmDaoMember, vault1Addr, vault1AddBonding.toString()); + await neutronChain.blockWaiter.waitBlocks(1); + }); + test('check voting power after bonding', async () => { + const vpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + ); + + // compare the new values to the prev state ones + // expect the vault1 VP to increase by bonding amount + expect(vpInfo.vault1Power).toEqual( + vpHistory.init.vault1Power + vault1AddBonding, + ); + expect(vpInfo.vault1TotalPower).toEqual( + vpHistory.init.vault1TotalPower + vault1AddBonding, + ); + + // expect the vault2 VP to remain the same + expect(vpInfo.vault2Power).toEqual(vpHistory.init.vault2Power); + expect(vpInfo.vault2TotalPower).toEqual(vpHistory.init.vault2TotalPower); + + // expect the vault3 VP to remain the same + expect(vpInfo.vault3Power).toEqual(vpHistory.init.vault3Power); + expect(vpInfo.vault3TotalPower).toEqual(vpHistory.init.vault3TotalPower); + + // expect the registry VP to increase by bonding amount + expect(vpInfo.votingRegistryPower).toEqual( + vpHistory.init.vault1TotalPower + + vault1AddBonding + + vpHistory.init.vault2TotalPower, + ); + expect(vpInfo.votingRegistryTotalPower).toEqual( + vpHistory.init.vault1TotalPower + + vault1AddBonding + + vpHistory.init.vault2TotalPower, + ); + vpHistory.additionalBonding = vpInfo; + }); + + test('unbond funds', async () => { + await unbondFunds(cmDaoMember, vault1Addr, vault1Unbonding.toString()); + await neutronChain.blockWaiter.waitBlocks(1); + }); + test('check voting power after unbonding', async () => { + const vpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + ); + + // compare the new values to the prev state ones + // expect the vault1 VP to decrease by bonding amount + expect(vpInfo.vault1Power).toEqual( + vpHistory.additionalBonding.vault1Power - vault1Unbonding, + ); + expect(vpInfo.vault1TotalPower).toEqual( + vpHistory.additionalBonding.vault1TotalPower - vault1Unbonding, + ); + + // expect the vault2 VP to remain the same + expect(vpInfo.vault2Power).toEqual( + vpHistory.additionalBonding.vault2Power, + ); + expect(vpInfo.vault2TotalPower).toEqual( + vpHistory.additionalBonding.vault2TotalPower, + ); + + // expect the vault3 VP to remain the same + expect(vpInfo.vault3Power).toEqual( + vpHistory.additionalBonding.vault3Power, + ); + expect(vpInfo.vault3TotalPower).toEqual( + vpHistory.additionalBonding.vault3TotalPower, + ); + + // expect the registry VP to decrease by unbonding amount + expect(vpInfo.votingRegistryPower).toEqual( + vpHistory.additionalBonding.vault1TotalPower - + vault1Unbonding + + vpHistory.additionalBonding.vault2TotalPower, + ); + expect(vpInfo.votingRegistryTotalPower).toEqual( + vpHistory.additionalBonding.vault1TotalPower - + vault1Unbonding + + vpHistory.additionalBonding.vault2TotalPower, + ); + vpHistory.unbonding = vpInfo; + }); + + // expect VP infos taken from heights in the past to be the same as they were at that points + test('check historical voting power', async () => { + const initVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.init.height, + ); + expect(initVpInfo).toMatchObject(vpHistory.init); + + const atAdditionalBondingVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.additionalBonding.height, + ); + expect(atAdditionalBondingVpInfo).toMatchObject( + vpHistory.additionalBonding, + ); + + const atUnbondingVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.unbonding.height, + ); + expect(atUnbondingVpInfo).toMatchObject(vpHistory.unbonding); + }); + }); + + describe('VP on vaults list mutation', () => { + test('deactivate vault', async () => { + await deactivateVotingVault( + cmInstantiator, + votingRegistryAddr, + vault2Addr, + ); + await neutronChain.blockWaiter.waitBlocks(1); + + const votingVaults = await getVotingVaults( + neutronChain, + votingRegistryAddr, + ); + expect(votingVaults.length).toBe(2); + expect(votingVaults).toContainEqual({ + address: vault1Addr, + description: NEUTRON_VAULT_1_CONTRACT_KEY, + name: NEUTRON_VAULT_1_CONTRACT_KEY, + state: 'Active', + }); + expect(votingVaults).toContainEqual({ + address: vault2Addr, + description: NEUTRON_VAULT_2_CONTRACT_KEY, + name: NEUTRON_VAULT_2_CONTRACT_KEY, + state: 'Inactive', + }); + }); + test('check voting power after deactivation', async () => { + const vpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + ); + + // compare the new values to the prev state ones + // expect the vault1 VP to remain the same + expect(vpInfo.vault1Power).toEqual(vpHistory.unbonding.vault1Power); + expect(vpInfo.vault1TotalPower).toEqual( + vpHistory.unbonding.vault1TotalPower, + ); + + // expect the vault2 VP to remain the same + expect(vpInfo.vault2Power).toEqual(vpHistory.unbonding.vault2Power); + expect(vpInfo.vault2TotalPower).toEqual( + vpHistory.unbonding.vault2TotalPower, + ); + + // expect the vault3 VP to remain the same + expect(vpInfo.vault3Power).toEqual(vpHistory.unbonding.vault3Power); + expect(vpInfo.vault3TotalPower).toEqual( + vpHistory.unbonding.vault3TotalPower, + ); + + // expect the registry VP to decrease by deactivated vault's power + expect(vpInfo.votingRegistryPower).toEqual( + vpHistory.unbonding.votingRegistryPower - + vpHistory.unbonding.vault2Power, + ); + expect(vpInfo.votingRegistryTotalPower).toEqual( + vpHistory.unbonding.votingRegistryTotalPower - + vpHistory.unbonding.vault2TotalPower, + ); + vpHistory.vaultDeactivation = vpInfo; + }); + + test('add another vault', async () => { + await addVotingVault(cmInstantiator, votingRegistryAddr, vault3Addr); + await neutronChain.blockWaiter.waitBlocks(1); + + const votingVaults = await getVotingVaults( + neutronChain, + votingRegistryAddr, + ); + expect(votingVaults.length).toBe(3); + expect(votingVaults).toContainEqual({ + address: vault1Addr, + description: NEUTRON_VAULT_1_CONTRACT_KEY, + name: NEUTRON_VAULT_1_CONTRACT_KEY, + state: 'Active', + }); + expect(votingVaults).toContainEqual({ + address: vault2Addr, + description: NEUTRON_VAULT_2_CONTRACT_KEY, + name: NEUTRON_VAULT_2_CONTRACT_KEY, + state: 'Inactive', + }); + expect(votingVaults).toContainEqual({ + address: vault3Addr, + description: NEUTRON_VAULT_3_CONTRACT_KEY, + name: NEUTRON_VAULT_3_CONTRACT_KEY, + state: 'Active', + }); + }); + test('check voting power after vault addition', async () => { + const vpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + ); + + // compare the new values to the prev state ones + // expect the vault1 VP to remain the same + expect(vpInfo.vault1Power).toEqual( + vpHistory.vaultDeactivation.vault1Power, + ); + expect(vpInfo.vault1TotalPower).toEqual( + vpHistory.vaultDeactivation.vault1TotalPower, + ); + + // expect the vault2 VP to remain the same + expect(vpInfo.vault2Power).toEqual( + vpHistory.vaultDeactivation.vault2Power, + ); + expect(vpInfo.vault2TotalPower).toEqual( + vpHistory.vaultDeactivation.vault2TotalPower, + ); + + // expect the vault3 VP to remain the same + expect(vpInfo.vault3Power).toEqual( + vpHistory.vaultDeactivation.vault3Power, + ); + expect(vpInfo.vault3TotalPower).toEqual( + vpHistory.vaultDeactivation.vault3TotalPower, + ); + + // expect the registry VP to increase by added vault's power + expect(vpInfo.votingRegistryPower).toEqual( + vpHistory.vaultDeactivation.votingRegistryPower + + vpHistory.vaultDeactivation.vault3Power, + ); + expect(vpInfo.votingRegistryTotalPower).toEqual( + vpHistory.vaultDeactivation.votingRegistryTotalPower + + vpHistory.vaultDeactivation.vault3TotalPower, + ); + vpHistory.vaultAdded = vpInfo; + }); + + test('activate vault', async () => { + await activateVotingVault(cmInstantiator, votingRegistryAddr, vault2Addr); + await neutronChain.blockWaiter.waitBlocks(1); + + const votingVaults = await getVotingVaults( + neutronChain, + votingRegistryAddr, + ); + expect(votingVaults.length).toBe(3); + expect(votingVaults).toContainEqual({ + address: vault1Addr, + description: NEUTRON_VAULT_1_CONTRACT_KEY, + name: NEUTRON_VAULT_1_CONTRACT_KEY, + state: 'Active', + }); + expect(votingVaults).toContainEqual({ + address: vault2Addr, + description: NEUTRON_VAULT_2_CONTRACT_KEY, + name: NEUTRON_VAULT_2_CONTRACT_KEY, + state: 'Active', + }); + expect(votingVaults).toContainEqual({ + address: vault3Addr, + description: NEUTRON_VAULT_3_CONTRACT_KEY, + name: NEUTRON_VAULT_3_CONTRACT_KEY, + state: 'Active', + }); + }); + test('check voting power after activation', async () => { + const vpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + ); + + // compare the new values to the prev state ones + // expect the vault1 VP to remain the same + expect(vpInfo.vault1Power).toEqual(vpHistory.vaultAdded.vault1Power); + expect(vpInfo.vault1TotalPower).toEqual( + vpHistory.vaultAdded.vault1TotalPower, + ); + + // expect the vault2 VP to remain the same + expect(vpInfo.vault2Power).toEqual(vpHistory.vaultAdded.vault2Power); + expect(vpInfo.vault2TotalPower).toEqual( + vpHistory.vaultAdded.vault2TotalPower, + ); + + // expect the vault3 VP to remain the same + expect(vpInfo.vault3Power).toEqual(vpHistory.vaultAdded.vault3Power); + expect(vpInfo.vault3TotalPower).toEqual( + vpHistory.vaultAdded.vault3TotalPower, + ); + + // expect the registry VP to increase by activated vault's power + expect(vpInfo.votingRegistryPower).toEqual( + vpHistory.vaultAdded.votingRegistryPower + + vpHistory.vaultAdded.vault2Power, + ); + expect(vpInfo.votingRegistryTotalPower).toEqual( + vpHistory.vaultAdded.votingRegistryTotalPower + + vpHistory.vaultAdded.vault2TotalPower, + ); + vpHistory.vaultActivation = vpInfo; + }); + + // expect VP infos taken from heights in the past to be the same as they were at that points + test('check historical voting power', async () => { + const initVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.init.height, + ); + expect(initVpInfo).toMatchObject(vpHistory.init); + + const atAdditionalBondingVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.additionalBonding.height, + ); + expect(atAdditionalBondingVpInfo).toMatchObject( + vpHistory.additionalBonding, + ); + expect(atAdditionalBondingVpInfo.height).toBeGreaterThan( + initVpInfo.height, + ); + + const atUnbondingVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.unbonding.height, + ); + expect(atUnbondingVpInfo).toMatchObject(vpHistory.unbonding); + expect(atUnbondingVpInfo.height).toBeGreaterThan( + atAdditionalBondingVpInfo.height, + ); + + const atVaultDeactivationVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.vaultDeactivation.height, + ); + expect(atVaultDeactivationVpInfo).toMatchObject( + vpHistory.vaultDeactivation, + ); + expect(atVaultDeactivationVpInfo.height).toBeGreaterThan( + atUnbondingVpInfo.height, + ); + + const atVaultAddedVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.vaultAdded.height, + ); + expect(atVaultAddedVpInfo).toMatchObject(vpHistory.vaultAdded); + expect(atVaultAddedVpInfo.height).toBeGreaterThan( + atVaultDeactivationVpInfo.height, + ); + + const atVaultActivationVpInfo = await getVotingPowerInfo( + neutronChain, + cmDaoMember.wallet.address.toString(), + contractAddresses, + vpHistory.vaultActivation.height, + ); + expect(atVaultActivationVpInfo).toMatchObject(vpHistory.vaultActivation); + expect(atVaultActivationVpInfo.height).toBeGreaterThan( + atVaultAddedVpInfo.height, + ); + }); + }); +}); + +const deployContracts = async ( + chain: CosmosWrapper, + instantiator: WalletWrapper, +): Promise> => { + const codeIds: Record = {}; + for (const contract of [ + VOTING_REGISTRY_CONTRACT_KEY, + NEUTRON_VAULT_CONTRACT_KEY, + ]) { + const codeId = await instantiator.storeWasm(NeutronContract[contract]); + expect(codeId).toBeGreaterThan(0); + codeIds[contract] = codeId; + } + + const contractAddresses: Record = {}; + await deployNeutronVault( + instantiator, + NEUTRON_VAULT_1_CONTRACT_KEY, + codeIds, + contractAddresses, + ); + await deployNeutronVault( + instantiator, + NEUTRON_VAULT_2_CONTRACT_KEY, + codeIds, + contractAddresses, + ); + await deployVotingRegistry( + instantiator, + [ + contractAddresses[NEUTRON_VAULT_1_CONTRACT_KEY], + contractAddresses[NEUTRON_VAULT_2_CONTRACT_KEY], + ], + codeIds, + contractAddresses, + ); + + // just deploy for later use + await deployNeutronVault( + instantiator, + NEUTRON_VAULT_3_CONTRACT_KEY, + codeIds, + contractAddresses, + ); + return contractAddresses; +}; + +const deployVotingRegistry = async ( + instantiator: WalletWrapper, + vaults: string[], + codeIds: Record, + contractAddresses: Record, +) => { + const res = await instantiator.instantiateContract( + codeIds[VOTING_REGISTRY_CONTRACT_KEY], + JSON.stringify({ + owner: instantiator.wallet.address.toString(), + voting_vaults: vaults, + }), + 'voting_registry', + ); + expect(res).toBeTruthy(); + contractAddresses[VOTING_REGISTRY_CONTRACT_KEY] = res[0]._contract_address; +}; + +const deployNeutronVault = async ( + instantiator: WalletWrapper, + vaultKey: string, + codeIds: Record, + contractAddresses: Record, +) => { + const res = await instantiator.instantiateContract( + codeIds[NEUTRON_VAULT_CONTRACT_KEY], + JSON.stringify({ + owner: instantiator.wallet.address.toString(), + name: vaultKey, + description: vaultKey, + denom: NEUTRON_DENOM, + }), + 'neutron_vault', + ); + expect(res).toBeTruthy(); + contractAddresses[vaultKey] = res[0]._contract_address; +}; + +const bondFunds = async (cm: WalletWrapper, vault: string, amount: string) => + cm.executeContract( + vault, + JSON.stringify({ + bond: {}, + }), + [{ denom: NEUTRON_DENOM, amount: amount }], + ); + +const unbondFunds = async (cm: WalletWrapper, vault: string, amount: string) => + cm.executeContract( + vault, + JSON.stringify({ + unbond: { amount: amount }, + }), + [], + ); + +const activateVotingVault = async ( + cm: WalletWrapper, + registry: string, + vault: string, +) => + cm.executeContract( + registry, + JSON.stringify({ + activate_voting_vault: { + voting_vault_contract: vault, + }, + }), + [], + ); + +const deactivateVotingVault = async ( + cm: WalletWrapper, + registry: string, + vault: string, +) => + cm.executeContract( + registry, + JSON.stringify({ + deactivate_voting_vault: { + voting_vault_contract: vault, + }, + }), + [], + ); + +const addVotingVault = async ( + cm: WalletWrapper, + registry: string, + vault: string, +) => + cm.executeContract( + registry, + JSON.stringify({ + add_voting_vault: { + new_voting_vault_contract: vault, + }, + }), + [], + ); + +/** + * Retrieves voting power data for a given address from both vaults and voting registry. Also + * retrieves total voting powerdata from the same contracts. + */ +const getVotingPowerInfo = async ( + chain: CosmosWrapper, + address: string, + contractAddresses: Record, + height?: number, +): Promise => { + if (typeof height === 'undefined') { + height = await getHeight(chain.sdk); + } + const vault1Power = getVotingPowerAtHeight( + chain, + contractAddresses[NEUTRON_VAULT_1_CONTRACT_KEY], + address, + height, + ); + const vault1TotalPower = getTotalPowerAtHeight( + chain, + contractAddresses[NEUTRON_VAULT_1_CONTRACT_KEY], + height, + ); + const vault2Power = getVotingPowerAtHeight( + chain, + contractAddresses[NEUTRON_VAULT_2_CONTRACT_KEY], + address, + height, + ); + const vault2TotalPower = getTotalPowerAtHeight( + chain, + contractAddresses[NEUTRON_VAULT_2_CONTRACT_KEY], + height, + ); + const vault3Power = getVotingPowerAtHeight( + chain, + contractAddresses[NEUTRON_VAULT_3_CONTRACT_KEY], + address, + height, + ); + const vault3TotalPower = getTotalPowerAtHeight( + chain, + contractAddresses[NEUTRON_VAULT_3_CONTRACT_KEY], + height, + ); + const registryPower = getVotingPowerAtHeight( + chain, + contractAddresses[VOTING_REGISTRY_CONTRACT_KEY], + address, + height, + ); + const registryTotalPower = getTotalPowerAtHeight( + chain, + contractAddresses[VOTING_REGISTRY_CONTRACT_KEY], + height, + ); + + return { + height: height, + vault1Power: +(await vault1Power).power, + vault1TotalPower: +(await vault1TotalPower).power, + vault2Power: +(await vault2Power).power, + vault2TotalPower: +(await vault2TotalPower).power, + vault3Power: +(await vault3Power).power, + vault3TotalPower: +(await vault3TotalPower).power, + votingRegistryPower: +(await registryPower).power, + votingRegistryTotalPower: +(await registryTotalPower).power, + }; +}; + +const getTotalPowerAtHeight = async ( + chain: CosmosWrapper, + contract: string, + height?: number, +): Promise => + chain.queryContract(contract, { + total_power_at_height: + typeof height === 'undefined' ? {} : { height: height }, + }); + +const getVotingPowerAtHeight = async ( + chain: CosmosWrapper, + contract: string, + address: string, + height?: number, +): Promise => + chain.queryContract(contract, { + voting_power_at_height: + typeof height === 'undefined' + ? { + address: address, + } + : { + address: address, + height: height, + }, + }); + +const getVotingVaults = async ( + chain: CosmosWrapper, + registry: string, + height?: number, +): Promise => + chain.queryContract(registry, { + voting_vaults: typeof height === 'undefined' ? {} : { height: height }, + }); + +type VotingPowerResponse = { + power: string; + height: number; +}; + +type VotingPowerInfo = { + height: number; + vault1Power: number; + vault1TotalPower: number; + vault2Power: number; + vault2TotalPower: number; + vault3Power: number; + vault3TotalPower: number; + votingRegistryPower: number; + votingRegistryTotalPower: number; +}; + +/** + * Contains voting power info for each important point in the test history. Used to make sure + * historical voting power queries are correct. Fields are placed in order of their occurrence + * in the test. + */ +type VotingPowerInfoHistory = { + /** initial voting power info */ + init: VotingPowerInfo; + /** voting power info after making an additional bonding */ + additionalBonding: VotingPowerInfo; + /** voting power info after making a partial unbonding */ + unbonding: VotingPowerInfo; + /** voting power info after a vault deactivation */ + vaultDeactivation: VotingPowerInfo; + /** voting power info after vault addition */ + vaultAdded: VotingPowerInfo; + /** voting power info after the deactivated vault activation */ + vaultActivation: VotingPowerInfo; +}; + +const initVotingPowerInfoHistory = (): VotingPowerInfoHistory => ({ + init: initVotingPowerInfo(), + additionalBonding: initVotingPowerInfo(), + unbonding: initVotingPowerInfo(), + vaultDeactivation: initVotingPowerInfo(), + vaultAdded: initVotingPowerInfo(), + vaultActivation: initVotingPowerInfo(), +}); + +const initVotingPowerInfo = (): VotingPowerInfo => ({ + height: 0, + vault1Power: 0, + vault1TotalPower: 0, + vault2Power: 0, + vault2TotalPower: 0, + vault3Power: 0, + vault3TotalPower: 0, + votingRegistryPower: 0, + votingRegistryTotalPower: 0, +}); + +type VotingVault = { + address: string; + name: string; + description: string; + state: string; +}; From 522289faee5b191a5b7bc4e271b24be735cc7d7f Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Fri, 15 Sep 2023 19:06:56 +0300 Subject: [PATCH 2/4] add voting registry test to package.json --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9f6af9c6..4ab87129 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "test:tge:vesting_lp_vault": "jest -b src/testcases/parallel/tge.vesting_lp_vault", "test:tge:credits_vault": "jest -b src/testcases/parallel/tge.credits_vault", "test:tge:investors_vesting_vault": "jest -b src/testcases/parallel/tge.investors_vesting_vault", + "test:voting_registry": "jest -b src/testcases/parallel/voting_registry", "gen:proto": "bash ./gen-proto.sh", "lint": "eslint ./src", "fmt": "eslint ./src --fix" @@ -85,4 +86,4 @@ "engines": { "node": ">=11.0 <17" } -} +} \ No newline at end of file From 6a717404ad187ee94a04aeac0111c8ce3ce4adf9 Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Mon, 18 Sep 2023 14:59:57 +0300 Subject: [PATCH 3/4] replace local imports with neutronjsplus for voting registry test --- .../parallel/voting_registry.test.ts | 67 +++++++++++-------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/testcases/parallel/voting_registry.test.ts b/src/testcases/parallel/voting_registry.test.ts index 8fddf992..58807ffe 100644 --- a/src/testcases/parallel/voting_registry.test.ts +++ b/src/testcases/parallel/voting_registry.test.ts @@ -1,11 +1,12 @@ import { NEUTRON_DENOM, - WalletWrapper, - CosmosWrapper, -} from '../../helpers/cosmos'; -import { NeutronContract } from '../../helpers/types'; -import { getHeight } from '../../helpers/wait'; -import { TestStateLocalCosmosTestNet } from '../common_localcosmosnet'; + cosmosWrapper, + types, + env, + TestStateLocalCosmosTestNet, +} from '@neutron-org/neutronjsplus'; + +const config = require('../../config.json'); // general contract keys used across the tests const VOTING_REGISTRY_CONTRACT_KEY = 'VOTING_REGISTRY'; @@ -17,9 +18,9 @@ const NEUTRON_VAULT_3_CONTRACT_KEY = 'NEUTRON_VAULT_3'; describe('Neutron / Voting Registry', () => { let testState: TestStateLocalCosmosTestNet; - let neutronChain: CosmosWrapper; - let cmInstantiator: WalletWrapper; - let cmDaoMember: WalletWrapper; + let neutronChain: cosmosWrapper.CosmosWrapper; + let cmInstantiator: cosmosWrapper.WalletWrapper; + let cmDaoMember: cosmosWrapper.WalletWrapper; let contractAddresses: Record = {}; let votingRegistryAddr: string; let vault1Addr: string; @@ -38,18 +39,18 @@ describe('Neutron / Voting Registry', () => { const vault3Bonding = 5_000_000; beforeAll(async () => { - testState = new TestStateLocalCosmosTestNet(); + testState = new TestStateLocalCosmosTestNet(config); await testState.init(); - neutronChain = new CosmosWrapper( + neutronChain = new cosmosWrapper.CosmosWrapper( testState.sdk1, testState.blockWaiter1, NEUTRON_DENOM, ); - cmInstantiator = new WalletWrapper( + cmInstantiator = new cosmosWrapper.WalletWrapper( neutronChain, testState.wallets.qaNeutronThree.genQaWal1, ); - cmDaoMember = new WalletWrapper( + cmDaoMember = new cosmosWrapper.WalletWrapper( neutronChain, testState.wallets.qaNeutron.genQaWal1, ); @@ -529,15 +530,17 @@ describe('Neutron / Voting Registry', () => { }); const deployContracts = async ( - chain: CosmosWrapper, - instantiator: WalletWrapper, + chain: cosmosWrapper.CosmosWrapper, + instantiator: cosmosWrapper.WalletWrapper, ): Promise> => { const codeIds: Record = {}; for (const contract of [ VOTING_REGISTRY_CONTRACT_KEY, NEUTRON_VAULT_CONTRACT_KEY, ]) { - const codeId = await instantiator.storeWasm(NeutronContract[contract]); + const codeId = await instantiator.storeWasm( + types.NeutronContract[contract], + ); expect(codeId).toBeGreaterThan(0); codeIds[contract] = codeId; } @@ -576,7 +579,7 @@ const deployContracts = async ( }; const deployVotingRegistry = async ( - instantiator: WalletWrapper, + instantiator: cosmosWrapper.WalletWrapper, vaults: string[], codeIds: Record, contractAddresses: Record, @@ -594,7 +597,7 @@ const deployVotingRegistry = async ( }; const deployNeutronVault = async ( - instantiator: WalletWrapper, + instantiator: cosmosWrapper.WalletWrapper, vaultKey: string, codeIds: Record, contractAddresses: Record, @@ -613,7 +616,11 @@ const deployNeutronVault = async ( contractAddresses[vaultKey] = res[0]._contract_address; }; -const bondFunds = async (cm: WalletWrapper, vault: string, amount: string) => +const bondFunds = async ( + cm: cosmosWrapper.WalletWrapper, + vault: string, + amount: string, +) => cm.executeContract( vault, JSON.stringify({ @@ -622,7 +629,11 @@ const bondFunds = async (cm: WalletWrapper, vault: string, amount: string) => [{ denom: NEUTRON_DENOM, amount: amount }], ); -const unbondFunds = async (cm: WalletWrapper, vault: string, amount: string) => +const unbondFunds = async ( + cm: cosmosWrapper.WalletWrapper, + vault: string, + amount: string, +) => cm.executeContract( vault, JSON.stringify({ @@ -632,7 +643,7 @@ const unbondFunds = async (cm: WalletWrapper, vault: string, amount: string) => ); const activateVotingVault = async ( - cm: WalletWrapper, + cm: cosmosWrapper.WalletWrapper, registry: string, vault: string, ) => @@ -647,7 +658,7 @@ const activateVotingVault = async ( ); const deactivateVotingVault = async ( - cm: WalletWrapper, + cm: cosmosWrapper.WalletWrapper, registry: string, vault: string, ) => @@ -662,7 +673,7 @@ const deactivateVotingVault = async ( ); const addVotingVault = async ( - cm: WalletWrapper, + cm: cosmosWrapper.WalletWrapper, registry: string, vault: string, ) => @@ -681,13 +692,13 @@ const addVotingVault = async ( * retrieves total voting powerdata from the same contracts. */ const getVotingPowerInfo = async ( - chain: CosmosWrapper, + chain: cosmosWrapper.CosmosWrapper, address: string, contractAddresses: Record, height?: number, ): Promise => { if (typeof height === 'undefined') { - height = await getHeight(chain.sdk); + height = await env.getHeight(chain.sdk); } const vault1Power = getVotingPowerAtHeight( chain, @@ -748,7 +759,7 @@ const getVotingPowerInfo = async ( }; const getTotalPowerAtHeight = async ( - chain: CosmosWrapper, + chain: cosmosWrapper.CosmosWrapper, contract: string, height?: number, ): Promise => @@ -758,7 +769,7 @@ const getTotalPowerAtHeight = async ( }); const getVotingPowerAtHeight = async ( - chain: CosmosWrapper, + chain: cosmosWrapper.CosmosWrapper, contract: string, address: string, height?: number, @@ -776,7 +787,7 @@ const getVotingPowerAtHeight = async ( }); const getVotingVaults = async ( - chain: CosmosWrapper, + chain: cosmosWrapper.CosmosWrapper, registry: string, height?: number, ): Promise => From 889fca4d41a80f759be233dfafdf64eb1ab96f9e Mon Sep 17 00:00:00 2001 From: sotnikov-s Date: Tue, 19 Sep 2023 18:12:06 +0300 Subject: [PATCH 4/4] describe expected total voting power --- src/testcases/parallel/governance.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/testcases/parallel/governance.test.ts b/src/testcases/parallel/governance.test.ts index 057da3de..417a3a94 100644 --- a/src/testcases/parallel/governance.test.ts +++ b/src/testcases/parallel/governance.test.ts @@ -131,6 +131,7 @@ describe('Neutron / Governance', () => { await wait.getWithAttempts( neutronChain.blockWaiter, async () => await mainDao.queryTotalVotingPower(), + // 3x1000000000 + 100000000 from investors vault (see neutron/network/init-neutrond.sh) async (response) => response.power == 3100000000, 20, );