diff --git a/src/helpers/constants.ts b/src/helpers/constants.ts index a3657ac0..1648bcd4 100644 --- a/src/helpers/constants.ts +++ b/src/helpers/constants.ts @@ -76,6 +76,11 @@ export const CONTRACTS = { MARKETMAP: 'marketmap.wasm', ORACLE: 'oracle.wasm', IBC_RATE_LIMITER: 'rate_limiter.wasm', + + // docs related contracts + HOWTO_REGISTER_KV_ICQ: 'howto_register_kv_icq.wasm', + HOWTO_REGISTER_CUSTOM_KV_ICQ: 'howto_register_custom_kv_icq.wasm', + HOWTO_REGISTER_TX_ICQ: 'howto_register_tx_icq.wasm', }; export const NEUTRON_PREFIX = process.env.NEUTRON_ADDRESS_PREFIX || 'neutron'; diff --git a/src/testcases/parallel/icq_howto_register_custom_kv_icq.test.ts b/src/testcases/parallel/icq_howto_register_custom_kv_icq.test.ts new file mode 100644 index 00000000..b5e60901 --- /dev/null +++ b/src/testcases/parallel/icq_howto_register_custom_kv_icq.test.ts @@ -0,0 +1,129 @@ +import config from '../../config.json'; +import { inject, RunnerTestSuite } from 'vitest'; +import { LocalState } from '../../helpers/local_state'; +import { Registry } from '@cosmjs/proto-signing'; +import { Wallet } from '../../helpers/wallet'; +import { defaultRegistryTypes, SigningStargateClient } from '@cosmjs/stargate'; +import { + COSMOS_DENOM, + CONTRACTS, + NEUTRON_DENOM, +} from '../../helpers/constants'; +import { GasPrice } from '@cosmjs/stargate/build/fee'; +import { SigningNeutronClient } from '../../helpers/signing_neutron_client'; +import { waitBlocks } from '@neutron-org/neutronjsplus/dist/wait'; + +// just a fresh test-specific address. don't use it in other parallel test cases to avoid races +const WATCHED_GAIA_ADDR = 'cosmos1yfhvt7uje9ztwr9mk6xnkg0thf83r2d53w38ja'; + +const CONNECTION_ID = 'connection-0'; +const ICQ_UPDATE_PERIOD = 5; + +describe( + 'Neutron / docs / interchainqueries / howto / register KV ICQ', + {}, + () => { + let testState: LocalState; + let gaiaClient: SigningStargateClient; + let gaiaAddress: string; + let neutronWallet: Wallet; + let neutronClient: SigningNeutronClient; + + beforeAll(async (suite: RunnerTestSuite) => { + testState = await LocalState.create(config, inject('mnemonics'), suite); + neutronWallet = await testState.nextWallet('neutron'); + + const galaWallet = await testState.nextWallet('cosmos'); + gaiaClient = await SigningStargateClient.connectWithSigner( + testState.rpcGaia, + galaWallet.directwallet, + { + registry: new Registry(defaultRegistryTypes), + gasPrice: GasPrice.fromString('0.05uatom'), + }, + ); + gaiaAddress = ( + await galaWallet.directwallet.getAccounts() + )[0].address.toString(); + + neutronClient = await SigningNeutronClient.connectWithSigner( + testState.rpcNeutron, + neutronWallet.directwallet, + neutronWallet.address, + ); + + await gaiaClient.sendTokens( + gaiaAddress, + WATCHED_GAIA_ADDR, + [ + { + amount: '1000000', + denom: COSMOS_DENOM, + }, + ], + 300000, + ); + }); + + let contractAddress: string; + describe('instantiate contract', () => { + let codeId: number; + test('store contract', async () => { + codeId = await neutronClient.upload( + CONTRACTS.HOWTO_REGISTER_CUSTOM_KV_ICQ, + ); + expect(codeId).toBeGreaterThan(0); + }); + test('instantiate contract', async () => { + contractAddress = await neutronClient.instantiate( + codeId, + {}, + 'howto_register_custom_kv_icq', + ); + }); + }); + + describe('register and execute KV ICQ', () => { + test('top up contract', async () => { + await neutronClient.sendTokens( + contractAddress, + [{ denom: NEUTRON_DENOM, amount: '1000000' }], + { + gas: '200000', + amount: [{ denom: NEUTRON_DENOM, amount: '1000' }], + }, + ); + }); + + test('register KV ICQ', async () => { + await neutronClient.execute( + contractAddress, + { + register_account_query: { + connection_id: CONNECTION_ID, + addr: WATCHED_GAIA_ADDR, + update_period: ICQ_UPDATE_PERIOD, + }, + }, + [], + { + amount: [{ denom: NEUTRON_DENOM, amount: '1000000' }], + gas: '2000000', + }, + ); + }); + + test('check ICQ submitted value result', async () => { + await waitBlocks(ICQ_UPDATE_PERIOD, neutronClient); + + const queryResult = await neutronClient.queryContractSmart( + contractAddress, + { account: { address: WATCHED_GAIA_ADDR } }, + ); + expect(queryResult.address).toEqual(WATCHED_GAIA_ADDR); + expect(+queryResult.sequence).toEqual(0); + expect(+queryResult.account_number).not.toEqual(0); + }); + }); + }, +); diff --git a/src/testcases/parallel/icq_howto_register_kv_icq.test.ts b/src/testcases/parallel/icq_howto_register_kv_icq.test.ts new file mode 100644 index 00000000..9f5e2247 --- /dev/null +++ b/src/testcases/parallel/icq_howto_register_kv_icq.test.ts @@ -0,0 +1,134 @@ +import config from '../../config.json'; +import { inject, RunnerTestSuite } from 'vitest'; +import { LocalState } from '../../helpers/local_state'; +import { Registry } from '@cosmjs/proto-signing'; +import { Wallet } from '../../helpers/wallet'; +import { defaultRegistryTypes, SigningStargateClient } from '@cosmjs/stargate'; +import { + COSMOS_DENOM, + CONTRACTS, + NEUTRON_DENOM, +} from '../../helpers/constants'; +import { GasPrice } from '@cosmjs/stargate/build/fee'; +import { SigningNeutronClient } from '../../helpers/signing_neutron_client'; +import { waitBlocks } from '@neutron-org/neutronjsplus/dist/wait'; + +// just a fresh test-specific address. don't use it in other parallel test cases to avoid races +const WATCHED_GAIA_ADDR = 'cosmos1gdzru2fzdn7czxn89phu9ergn7v8c7zpladz6f'; + +const WATCHED_GAIA_ADDR_BALANCE_UATOM = 100000; +const CONNECTION_ID = 'connection-0'; +const ICQ_UPDATE_PERIOD = 5; + +describe( + 'Neutron / docs / interchainqueries / howto / register KV ICQ', + {}, + () => { + let testState: LocalState; + let gaiaClient: SigningStargateClient; + let gaiaAddress: string; + let neutronWallet: Wallet; + let neutronClient: SigningNeutronClient; + + beforeAll(async (suite: RunnerTestSuite) => { + testState = await LocalState.create(config, inject('mnemonics'), suite); + neutronWallet = await testState.nextWallet('neutron'); + + const galaWallet = await testState.nextWallet('cosmos'); + gaiaClient = await SigningStargateClient.connectWithSigner( + testState.rpcGaia, + galaWallet.directwallet, + { + registry: new Registry(defaultRegistryTypes), + gasPrice: GasPrice.fromString('0.05uatom'), + }, + ); + gaiaAddress = ( + await galaWallet.directwallet.getAccounts() + )[0].address.toString(); + + neutronClient = await SigningNeutronClient.connectWithSigner( + testState.rpcNeutron, + neutronWallet.directwallet, + neutronWallet.address, + ); + + await gaiaClient.sendTokens( + gaiaAddress, + WATCHED_GAIA_ADDR, + [ + { + amount: WATCHED_GAIA_ADDR_BALANCE_UATOM.toString(), + denom: COSMOS_DENOM, + }, + ], + 300000, + ); + }); + + let contractAddress: string; + describe('instantiate contract', () => { + let codeId: number; + test('store contract', async () => { + codeId = await neutronClient.upload(CONTRACTS.HOWTO_REGISTER_KV_ICQ); + expect(codeId).toBeGreaterThan(0); + }); + test('instantiate contract', async () => { + contractAddress = await neutronClient.instantiate( + codeId, + {}, + 'howto_register_kv_icq', + ); + }); + }); + + describe('register and execute KV ICQ', () => { + test('top up contract', async () => { + await neutronClient.sendTokens( + contractAddress, + [{ denom: NEUTRON_DENOM, amount: '1000000' }], + { + gas: '200000', + amount: [{ denom: NEUTRON_DENOM, amount: '1000' }], + }, + ); + }); + + test('register KV ICQ', async () => { + await neutronClient.execute( + contractAddress, + { + register_balances_query: { + connection_id: CONNECTION_ID, + denoms: [COSMOS_DENOM], + addr: WATCHED_GAIA_ADDR, + update_period: ICQ_UPDATE_PERIOD, + }, + }, + [], + { + amount: [{ denom: NEUTRON_DENOM, amount: '1000000' }], + gas: '2000000', + }, + ); + }); + + test('check ICQ submitted value result', async () => { + await waitBlocks(ICQ_UPDATE_PERIOD, neutronClient); + + const queryResult = await neutronClient.queryContractSmart( + contractAddress, + { balances: { address: WATCHED_GAIA_ADDR } }, + ); + expect(queryResult).toEqual({ + coins: [ + { + denom: COSMOS_DENOM, + amount: WATCHED_GAIA_ADDR_BALANCE_UATOM.toString(), + }, + ], + }); + }); + }); + }, +); diff --git a/src/testcases/parallel/icq_howto_register_tx_icq.test.ts b/src/testcases/parallel/icq_howto_register_tx_icq.test.ts new file mode 100644 index 00000000..579abed8 --- /dev/null +++ b/src/testcases/parallel/icq_howto_register_tx_icq.test.ts @@ -0,0 +1,162 @@ +import config from '../../config.json'; +import { inject, RunnerTestSuite } from 'vitest'; +import { LocalState } from '../../helpers/local_state'; +import { Coin, Registry } from '@cosmjs/proto-signing'; +import { Wallet } from '../../helpers/wallet'; +import { defaultRegistryTypes, SigningStargateClient } from '@cosmjs/stargate'; +import { + COSMOS_DENOM, + CONTRACTS, + NEUTRON_DENOM, +} from '../../helpers/constants'; +import { GasPrice } from '@cosmjs/stargate/build/fee'; +import { SigningNeutronClient } from '../../helpers/signing_neutron_client'; +import { getWithAttempts } from '@neutron-org/neutronjsplus/dist/wait'; + +const CONNECTION_ID = 'connection-0'; +const ICQ_UPDATE_PERIOD = 5; +const GAIA_VAL_ADDR = 'cosmosvaloper18hl5c9xn5dze2g50uaw0l2mr02ew57zk0auktn'; +const DELEGATION_AMOUNT = 1000000; + +describe( + 'Neutron / docs / interchainqueries / howto / register TX ICQ', + {}, + () => { + let testState: LocalState; + let gaiaClient: SigningStargateClient; + let gaiaWallet: Wallet; + let neutronWallet: Wallet; + let neutronClient: SigningNeutronClient; + + beforeAll(async (suite: RunnerTestSuite) => { + testState = await LocalState.create(config, inject('mnemonics'), suite); + + neutronWallet = await testState.nextWallet('neutron'); + neutronClient = await SigningNeutronClient.connectWithSigner( + testState.rpcNeutron, + neutronWallet.directwallet, + neutronWallet.address, + ); + + gaiaWallet = await testState.nextWallet('cosmos'); + gaiaClient = await SigningStargateClient.connectWithSigner( + testState.rpcGaia, + gaiaWallet.directwallet, + { + registry: new Registry(defaultRegistryTypes), + gasPrice: GasPrice.fromString('0.05uatom'), + }, + ); + + let resp = await gaiaClient.delegateTokens( + gaiaWallet.address.toString(), + GAIA_VAL_ADDR, + { amount: DELEGATION_AMOUNT.toString(), denom: COSMOS_DENOM }, + 'auto', + ); + expect(resp.code).toBe(0); + await getWithAttempts( + gaiaClient, + async () => + await gaiaClient.getDelegation( + gaiaWallet.address.toString(), + GAIA_VAL_ADDR, + ), + async (response) => response.amount == DELEGATION_AMOUNT.toString(), + ); + + resp = await gaiaClient.undelegateTokens( + gaiaWallet.address.toString(), + GAIA_VAL_ADDR, + { amount: (DELEGATION_AMOUNT / 2).toString(), denom: COSMOS_DENOM }, + 'auto', + ); + expect(resp.code).toBe(0); + }); + + let contractAddress: string; + describe('instantiate contract', () => { + let codeId: number; + test('store contract', async () => { + codeId = await neutronClient.upload(CONTRACTS.HOWTO_REGISTER_TX_ICQ); + expect(codeId).toBeGreaterThan(0); + }); + test('instantiate contract', async () => { + contractAddress = await neutronClient.instantiate( + codeId, + {}, + 'howto_register_custom_tx_icq', + ); + }); + }); + + describe('register and execute TX ICQ', () => { + test('top up contract', async () => { + await neutronClient.sendTokens( + contractAddress, + [{ denom: NEUTRON_DENOM, amount: '1000000' }], + { + gas: '200000', + amount: [{ denom: NEUTRON_DENOM, amount: '1000' }], + }, + ); + }); + + test('register TX ICQ', async () => { + await neutronClient.execute( + contractAddress, + { + register_undelegations_query: { + connection_id: CONNECTION_ID, + addr: gaiaWallet.address.toString(), + update_period: ICQ_UPDATE_PERIOD, + }, + }, + [], + { + amount: [{ denom: NEUTRON_DENOM, amount: '1000000' }], + gas: '2000000', + }, + ); + }); + + describe('check ICQ submitted value result', () => { + test('beforeAll undelegation result submission', async () => { + await getWithAttempts( + neutronClient, + async (): Promise => + await neutronClient.queryContractSmart(contractAddress, { + undelegated_amount: { address: gaiaWallet.address.toString() }, + }), + async (response) => + response.length == 1 && + response[0].amount == (DELEGATION_AMOUNT / 2).toString(), + ); + }); + + test('undelegate once more', async () => { + const resp = await gaiaClient.undelegateTokens( + gaiaWallet.address.toString(), + GAIA_VAL_ADDR, + { amount: (DELEGATION_AMOUNT / 4).toString(), denom: COSMOS_DENOM }, + 'auto', + ); + expect(resp.code).toBe(0); + }); + + test('one more undelegation result submission', async () => { + await getWithAttempts( + neutronClient, + async (): Promise => + await neutronClient.queryContractSmart(contractAddress, { + undelegated_amount: { address: gaiaWallet.address.toString() }, + }), + async (response) => + response.length == 2 && + response[1].amount == (DELEGATION_AMOUNT / 4).toString(), + ); + }); + }); + }); + }, +);