Browse Source

Substrate: Support contracts node v0.22 (#1080)

Change the linker to use stabilized APIs for any remaining __unstable__
Update integration tests:
-    Introduce a helper for the (currently) broken contracts query API
-    Use WeightV2 for gas limits
-    Use estimated gas from dry run instead of hardcoded value
-    Compile test contracts in parallel
Updates to the latest contracts CI image for pallet contracts v0.22.1. I'm aware that this is not ideal but it's what's available right now. There shouldn't be a breaking release soon, we can switch to production as soon as its here.
Cyrill Leutwiler 3 years ago
parent
commit
46c282207f

+ 1 - 1
.github/workflows/test.yml

@@ -309,7 +309,7 @@ jobs:
       # We can't run substrate as a github actions service, since it requires
       # We can't run substrate as a github actions service, since it requires
       # command line arguments. See https://github.com/actions/runner/pull/1152
       # command line arguments. See https://github.com/actions/runner/pull/1152
     - name: Start substrate
     - name: Start substrate
-      run: docker run -d -p 9944:9944 paritytech/contracts-ci-linux:production substrate-contracts-node --dev --ws-external
+      run: docker run -d -p 9944:9944 paritytech/contracts-ci-linux:latest substrate-contracts-node --dev --ws-external
     - uses: actions/setup-node@v3
     - uses: actions/setup-node@v3
       with:
       with:
         node-version: '14'
         node-version: '14'

+ 21 - 17
integration/substrate/UniswapV2ERC20.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, daveKeypair } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
@@ -31,19 +31,19 @@ describe('Deploy UniswapV2ERC20 contract and test', () => {
     });
     });
 
 
     it('name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH', async () => {
     it('name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH', async () => {
-        const { output: name } = await token.query.name(alice.address, {});
+        const { output: name } = await query(conn, alice, token, "name");
         expect(name?.toJSON()).toEqual('Uniswap V2')
         expect(name?.toJSON()).toEqual('Uniswap V2')
-        const { output: symbol } = await token.query.symbol(alice.address, {});
+        const { output: symbol } = await query(conn, alice, token, "symbol");
         expect(symbol?.toJSON()).toEqual('UNI-V2')
         expect(symbol?.toJSON()).toEqual('UNI-V2')
-        const { output: decimals } = await token.query.decimals(alice.address, {});
+        const { output: decimals } = await query(conn, alice, token, "decimals");
         expect(decimals?.toJSON()).toEqual(18)
         expect(decimals?.toJSON()).toEqual(18)
-        const { output: totalSupply } = await token.query.totalSupply(alice.address, {});
+        const { output: totalSupply } = await query(conn, alice, token, "totalSupply");
         //console.log(`total supply: ${totalSupply?.toHuman()}`);
         //console.log(`total supply: ${totalSupply?.toHuman()}`);
         expect(totalSupply?.eq(TOTAL_SUPPLY)).toBeTruthy();
         expect(totalSupply?.eq(TOTAL_SUPPLY)).toBeTruthy();
-        const { output: bal } = await token.query.balanceOf(alice.address, {}, alice.address);
+        const { output: bal } = await query(conn, alice, token, "balanceOf", [alice.address]);
         expect(bal?.eq(TOTAL_SUPPLY)).toBeTruthy();
         expect(bal?.eq(TOTAL_SUPPLY)).toBeTruthy();
 
 
-        const { output: domain_seperator } = await token.query.domainSeparator(alice.address, {});
+        const { output: domain_seperator } = await query(conn, alice, token, "domainSeparator");
 
 
         let expected = keccakAsHex(Buffer.concat([
         let expected = keccakAsHex(Buffer.concat([
             keccakAsU8a('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
             keccakAsU8a('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
@@ -56,25 +56,27 @@ describe('Deploy UniswapV2ERC20 contract and test', () => {
         //console.log(`domain_separator: ${domain_seperator} ${expected}`);
         //console.log(`domain_separator: ${domain_seperator} ${expected}`);
         expect(domain_seperator?.eq(expected)).toBeTruthy();
         expect(domain_seperator?.eq(expected)).toBeTruthy();
 
 
-        const { output: permit_typehash } = await token.query.permitTypehash(alice.address, {});
+        const { output: permit_typehash } = await query(conn, alice, token, "permitTypehash");
         expect(permit_typehash?.eq('0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9')).toBeTruthy();
         expect(permit_typehash?.eq('0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9')).toBeTruthy();
     })
     })
 
 
     it('approve', async () => {
     it('approve', async () => {
+        let gasLimit = await weight(conn, token, "approve", [dave.address, TEST_AMOUNT]);
         let tx = token.tx.approve({ gasLimit }, dave.address, TEST_AMOUNT);
         let tx = token.tx.approve({ gasLimit }, dave.address, TEST_AMOUNT);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        let { output } = await token.query.allowance(alice.address, {}, alice.address, dave.address);
+        let { output } = await query(conn, alice, token, "allowance", [alice.address, dave.address]);
         expect(output?.eq(TEST_AMOUNT)).toBeTruthy();
         expect(output?.eq(TEST_AMOUNT)).toBeTruthy();
     })
     })
 
 
     it('transfer', async () => {
     it('transfer', async () => {
+        let gasLimit = await weight(conn, token, "approve", [dave.address, TEST_AMOUNT]);
         let tx = token.tx.transfer({ gasLimit }, dave.address, TEST_AMOUNT);
         let tx = token.tx.transfer({ gasLimit }, dave.address, TEST_AMOUNT);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        const { output: aliceBal } = await token.query.balanceOf(alice.address, {}, alice.address);
+        const { output: aliceBal } = await query(conn, alice, token, "balanceOf", [alice.address]);
         expect(aliceBal?.eq(TOTAL_SUPPLY - TEST_AMOUNT)).toBeTruthy();
         expect(aliceBal?.eq(TOTAL_SUPPLY - TEST_AMOUNT)).toBeTruthy();
-        const { output: daveBal } = await token.query.balanceOf(alice.address, {}, dave.address);
+        const { output: daveBal } = await query(conn, alice, token, "balanceOf", [dave.address]);
         expect(daveBal?.eq(TEST_AMOUNT)).toBeTruthy();
         expect(daveBal?.eq(TEST_AMOUNT)).toBeTruthy();
     })
     })
 
 
@@ -84,32 +86,34 @@ describe('Deploy UniswapV2ERC20 contract and test', () => {
     // })
     // })
 
 
     it('transferFrom', async () => {
     it('transferFrom', async () => {
+        let gasLimit = await weight(conn, token, "approve", [dave.address, TEST_AMOUNT]);
         let tx = token.tx.approve({ gasLimit }, dave.address, TEST_AMOUNT);
         let tx = token.tx.approve({ gasLimit }, dave.address, TEST_AMOUNT);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
         tx = token.tx.transferFrom({ gasLimit }, alice.address, dave.address, TEST_AMOUNT);
         tx = token.tx.transferFrom({ gasLimit }, alice.address, dave.address, TEST_AMOUNT);
         await transaction(tx, dave);
         await transaction(tx, dave);
 
 
-        const { output: allowance } = await token.query.allowance(alice.address, {}, alice.address, dave.address);
+        const { output: allowance } = await query(conn, alice, token, "allowance", [alice.address, dave.address]);
         expect(allowance?.eq(0)).toBeTruthy();
         expect(allowance?.eq(0)).toBeTruthy();
-        const { output: aliceBal } = await token.query.balanceOf(alice.address, {}, alice.address);
+        const { output: aliceBal } = await query(conn, alice, token, "balanceOf", [alice.address]);
         expect(aliceBal?.eq(TOTAL_SUPPLY - TEST_AMOUNT)).toBeTruthy();
         expect(aliceBal?.eq(TOTAL_SUPPLY - TEST_AMOUNT)).toBeTruthy();
-        const { output: daveBal } = await token.query.balanceOf(alice.address, {}, dave.address);
+        const { output: daveBal } = await query(conn, alice, token, "balanceOf", [dave.address]);
         expect(daveBal?.eq(TEST_AMOUNT)).toBeTruthy();
         expect(daveBal?.eq(TEST_AMOUNT)).toBeTruthy();
     })
     })
 
 
     it('transferFrom:max', async () => {
     it('transferFrom:max', async () => {
+        let gasLimit = await weight(conn, token, "approve", [dave.address, MAX_UINT256]);
         let tx = token.tx.approve({ gasLimit }, dave.address, MAX_UINT256);
         let tx = token.tx.approve({ gasLimit }, dave.address, MAX_UINT256);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
         tx = token.tx.transferFrom({ gasLimit }, alice.address, dave.address, TEST_AMOUNT);
         tx = token.tx.transferFrom({ gasLimit }, alice.address, dave.address, TEST_AMOUNT);
         await transaction(tx, dave);
         await transaction(tx, dave);
 
 
-        const { output: allowance } = await token.query.allowance(alice.address, {}, alice.address, dave.address);
+        const { output: allowance } = await query(conn, alice, token, "allowance", [alice.address, dave.address]);
         expect(allowance?.eq(MAX_UINT256 - TEST_AMOUNT)).toBeTruthy();
         expect(allowance?.eq(MAX_UINT256 - TEST_AMOUNT)).toBeTruthy();
-        const { output: aliceBal } = await token.query.balanceOf(alice.address, {}, alice.address);
+        const { output: aliceBal } = await query(conn, alice, token, "balanceOf", [alice.address]);
         expect(aliceBal?.eq(TOTAL_SUPPLY - TEST_AMOUNT)).toBeTruthy();
         expect(aliceBal?.eq(TOTAL_SUPPLY - TEST_AMOUNT)).toBeTruthy();
-        const { output: daveBal } = await token.query.balanceOf(alice.address, {}, dave.address);
+        const { output: daveBal } = await query(conn, alice, token, "balanceOf", [dave.address]);
         expect(daveBal?.eq(TEST_AMOUNT)).toBeTruthy();
         expect(daveBal?.eq(TEST_AMOUNT)).toBeTruthy();
     })
     })
 });
 });

+ 16 - 13
integration/substrate/UniswapV2Factory.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, daveKeypair } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
@@ -39,18 +39,19 @@ describe('UniswapV2Factory', () => {
   });
   });
 
 
   it('feeTo, feeToSetter, allPairsLength', async () => {
   it('feeTo, feeToSetter, allPairsLength', async () => {
-    const { output: feeTo } = await factory.query.feeTo(alice.address, {});
+    const { output: feeTo } = await query(conn, alice, factory, "feeTo");
     // This is the 32-byte 0-address in ss58 format
     // This is the 32-byte 0-address in ss58 format
     expect(feeTo?.eq('5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM')).toBeTruthy();
     expect(feeTo?.eq('5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM')).toBeTruthy();
 
 
-    const { output: feeToSetter } = await factory.query.feeToSetter(alice.address, {});
+    const { output: feeToSetter } = await query(conn, alice, factory, "feeToSetter");
     expect(feeToSetter?.eq(alice.address)).toBeTruthy();
     expect(feeToSetter?.eq(alice.address)).toBeTruthy();
 
 
-    const { output: allPairsLength } = await factory.query.allPairsLength(alice.address, {});
+    const { output: allPairsLength } = await query(conn, alice, factory, "allPairsLength");
     expect(allPairsLength?.eq(0)).toBeTruthy();
     expect(allPairsLength?.eq(0)).toBeTruthy();
   })
   })
 
 
   async function createPair(tokens: [string, string]) {
   async function createPair(tokens: [string, string]) {
+    let gasLimit = await weight(conn, factory, "createPair", [tokens[0], tokens[1]]);
     let tx = factory.tx.createPair({ gasLimit }, ...tokens);
     let tx = factory.tx.createPair({ gasLimit }, ...tokens);
 
 
     let res0: any = await transaction(tx, alice);
     let res0: any = await transaction(tx, alice);
@@ -64,27 +65,27 @@ describe('UniswapV2Factory', () => {
 
 
     let pair_address = events[0].args[2].toString();
     let pair_address = events[0].args[2].toString();
 
 
-    const { output: get_pair } = await factory.query.getPair(alice.address, {}, ...tokens);
+    const { output: get_pair } = await query(conn, alice, factory, "getPair", [tokens[0], tokens[1]]);
     expect(get_pair?.eq(pair_address)).toBeTruthy();
     expect(get_pair?.eq(pair_address)).toBeTruthy();
 
 
-    const { output: pairRev } = await factory.query.getPair(alice.address, {}, ...tokens.slice().reverse());
+    const { output: pairRev } = await query(conn, alice, factory, "getPair", [tokens[1], tokens[0]]);
     expect(pairRev?.eq(pair_address)).toBeTruthy();
     expect(pairRev?.eq(pair_address)).toBeTruthy();
 
 
-    const { output: pair0 } = await factory.query.allPairs(alice.address, {}, 0);
+    const { output: pair0 } = await query(conn, alice, factory, "allPairs", [0]);
     expect(pair0?.eq(pair_address)).toBeTruthy();
     expect(pair0?.eq(pair_address)).toBeTruthy();
 
 
-    const { output: pairLength } = await factory.query.allPairsLength(alice.address, {});
+    const { output: pairLength } = await query(conn, alice, factory, "allPairsLength");
     expect(pairLength?.eq(1)).toBeTruthy();
     expect(pairLength?.eq(1)).toBeTruthy();
 
 
     const pair = new ContractPromise(conn, pairAbi, pair_address);
     const pair = new ContractPromise(conn, pairAbi, pair_address);
 
 
-    const { output: pair_factory } = await pair.query.factory(alice.address, {});
+    const { output: pair_factory } = await query(conn, alice, pair, "factory");
     expect(pair_factory?.eq(factory.address)).toBeTruthy();
     expect(pair_factory?.eq(factory.address)).toBeTruthy();
 
 
-    const { output: token0 } = await pair.query.token0(alice.address, {});
+    const { output: token0 } = await query(conn, alice, pair, "token0");
     expect(token0?.eq(TEST_ADDRESSES[0])).toBeTruthy();
     expect(token0?.eq(TEST_ADDRESSES[0])).toBeTruthy();
 
 
-    const { output: token1 } = await pair.query.token1(alice.address, {});
+    const { output: token1 } = await query(conn, alice, pair, "token1");
     expect(token1?.eq(TEST_ADDRESSES[1])).toBeTruthy();
     expect(token1?.eq(TEST_ADDRESSES[1])).toBeTruthy();
   }
   }
 
 
@@ -97,18 +98,20 @@ describe('UniswapV2Factory', () => {
   })
   })
 
 
   it('setFeeTo', async () => {
   it('setFeeTo', async () => {
+    let gasLimit = await weight(conn, factory, "setFeeTo", [dave.address]);
     let tx = factory.tx.setFeeTo({ gasLimit }, dave.address);
     let tx = factory.tx.setFeeTo({ gasLimit }, dave.address);
     await transaction(tx, alice);
     await transaction(tx, alice);
 
 
-    const { output: feeTo } = await factory.query.feeTo(alice.address, {});
+    const { output: feeTo } = await query(conn, alice, factory, "feeTo");
     expect(feeTo?.eq(dave.address)).toBeTruthy();
     expect(feeTo?.eq(dave.address)).toBeTruthy();
   })
   })
 
 
   it('setFeeToSetter', async () => {
   it('setFeeToSetter', async () => {
+    let gasLimit = await weight(conn, factory, "setFeeToSetter", [dave.address]);
     let tx = factory.tx.setFeeToSetter({ gasLimit }, dave.address);
     let tx = factory.tx.setFeeToSetter({ gasLimit }, dave.address);
     await transaction(tx, alice);
     await transaction(tx, alice);
 
 
-    const { output: feeTo } = await factory.query.feeToSetter(alice.address, {});
+    const { output: feeTo } = await query(conn, alice, factory, "feeToSetter");
     expect(feeTo?.eq(dave.address)).toBeTruthy();
     expect(feeTo?.eq(dave.address)).toBeTruthy();
   })
   })
 })
 })

+ 43 - 32
integration/substrate/UniswapV2Pair.spec.ts

@@ -1,9 +1,8 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, daveKeypair } from './index';
+import { weight, query, createConnection, deploy, transaction, aliceKeypair, daveKeypair } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import type { Codec } from '@polkadot/types/types';
 
 
 const MINIMUM_LIQUIDITY = BigInt(1000);
 const MINIMUM_LIQUIDITY = BigInt(1000);
 const TOTAL_SUPPLY = BigInt(10000e18);
 const TOTAL_SUPPLY = BigInt(10000e18);
@@ -41,15 +40,16 @@ describe('UniswapV2Pair', () => {
 
 
         const tokenB = new ContractPromise(conn, tokenB_contract.abi, tokenB_contract.address);
         const tokenB = new ContractPromise(conn, tokenB_contract.abi, tokenB_contract.address);
 
 
+        let gasLimit = await weight(conn, factory, "createPair", [tokenA.address, tokenB.address]);
         let tx = factory.tx.createPair({ gasLimit }, tokenA.address, tokenB.address);
         let tx = factory.tx.createPair({ gasLimit }, tokenA.address, tokenB.address);
 
 
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        const { output: get_pair } = await factory.query.getPair(alice.address, {}, tokenA.address, tokenB.address);
+        const { output: get_pair } = await query(conn, alice, factory, "getPair", [tokenA.address, tokenB.address]);
 
 
         pair = new ContractPromise(conn, pairAbi, get_pair!.toString());
         pair = new ContractPromise(conn, pairAbi, get_pair!.toString());
 
 
-        const { output: token0_address } = await pair.query.token0(alice.address, {});
+        const { output: token0_address } = await query(conn, alice, pair, "token0");
 
 
         if (tokenA.address.toString() == token0_address!.toString()) {
         if (tokenA.address.toString() == token0_address!.toString()) {
             token0 = tokenA;
             token0 = tokenA;
@@ -69,24 +69,27 @@ describe('UniswapV2Pair', () => {
         const token0Amount = BigInt(1e18)
         const token0Amount = BigInt(1e18)
         const token1Amount = BigInt(4e18)
         const token1Amount = BigInt(4e18)
 
 
+        let gasLimit = await weight(conn, token0, "transfer", [pair.address, token0Amount]);
         let tx = token0.tx.transfer({ gasLimit }, pair.address, token0Amount);
         let tx = token0.tx.transfer({ gasLimit }, pair.address, token0Amount);
         await transaction(tx, alice);
         await transaction(tx, alice);
+        gasLimit = await weight(conn, token1, "transfer", [pair.address, token1Amount]);
         tx = token1.tx.transfer({ gasLimit }, pair.address, token1Amount);
         tx = token1.tx.transfer({ gasLimit }, pair.address, token1Amount);
         await transaction(tx, alice);
         await transaction(tx, alice);
         const expectedLiquidity = BigInt(2e18)
         const expectedLiquidity = BigInt(2e18)
 
 
+        gasLimit = await weight(conn, pair, "mint", [alice.address]);
         tx = pair.tx.mint({ gasLimit }, alice.address);
         tx = pair.tx.mint({ gasLimit }, alice.address);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        const { output: totalSupply } = await pair.query.totalSupply(alice.address, {});
+        const { output: totalSupply } = await query(conn, alice, pair, "totalSupply");
         expect(totalSupply?.eq(expectedLiquidity)).toBeTruthy();
         expect(totalSupply?.eq(expectedLiquidity)).toBeTruthy();
-        const { output: bal } = await pair.query.balanceOfAddress(alice.address, {}, alice.address);
+        const { output: bal } = await query(conn, alice, pair, "balanceOfAddress", [alice.address]);
         expect(bal?.eq(expectedLiquidity - MINIMUM_LIQUIDITY)).toBeTruthy();
         expect(bal?.eq(expectedLiquidity - MINIMUM_LIQUIDITY)).toBeTruthy();
-        const { output: bal0 } = await token0.query.balanceOf(alice.address, {}, pair.address);
+        const { output: bal0 } = await query(conn, alice, token0, "balanceOf", [pair.address]);
         expect(bal0?.eq(token0Amount)).toBeTruthy();
         expect(bal0?.eq(token0Amount)).toBeTruthy();
-        const { output: bal1 } = await token1.query.balanceOf(alice.address, {}, pair.address);
+        const { output: bal1 } = await query(conn, alice, token1, "balanceOf", [pair.address]);
         expect(bal1?.eq(token1Amount)).toBeTruthy();
         expect(bal1?.eq(token1Amount)).toBeTruthy();
-        const { output: reserves } = await pair.query.getReserves(alice.address, {});
+        const { output: reserves } = await query(conn, alice, pair, "getReserves");
         // surely there must be a better way.
         // surely there must be a better way.
         let v: any = reserves;
         let v: any = reserves;
         expect(v[0].eq(token0Amount)).toBeTruthy();
         expect(v[0].eq(token0Amount)).toBeTruthy();
@@ -94,11 +97,13 @@ describe('UniswapV2Pair', () => {
     })
     })
 
 
     async function addLiquidity(token0Amount: BigInt, token1Amount: BigInt) {
     async function addLiquidity(token0Amount: BigInt, token1Amount: BigInt) {
+        let gasLimit = await weight(conn, token0, "transfer", [pair.address, token0Amount]);
         let tx = token0.tx.transfer({ gasLimit }, pair.address, token0Amount);
         let tx = token0.tx.transfer({ gasLimit }, pair.address, token0Amount);
         await transaction(tx, alice);
         await transaction(tx, alice);
+        gasLimit = await weight(conn, token1, "transfer", [pair.address, token1Amount]);
         tx = token1.tx.transfer({ gasLimit }, pair.address, token1Amount);
         tx = token1.tx.transfer({ gasLimit }, pair.address, token1Amount);
         await transaction(tx, alice);
         await transaction(tx, alice);
-
+        gasLimit = await weight(conn, pair, "mint", [alice.address]);
         tx = pair.tx.mint({ gasLimit }, alice.address);
         tx = pair.tx.mint({ gasLimit }, alice.address);
         await transaction(tx, alice);
         await transaction(tx, alice);
     }
     }
@@ -111,27 +116,29 @@ describe('UniswapV2Pair', () => {
         const swapAmount = BigInt(1e18)
         const swapAmount = BigInt(1e18)
         const expectedOutputAmount = BigInt(1662497915624478906)
         const expectedOutputAmount = BigInt(1662497915624478906)
 
 
+        let gasLimit = await weight(conn, token0, "transfer", [pair.address, swapAmount]);
         let tx = token0.tx.transfer({ gasLimit }, pair.address, swapAmount);
         let tx = token0.tx.transfer({ gasLimit }, pair.address, swapAmount);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
+        gasLimit = await weight(conn, pair, "swap", [0, expectedOutputAmount, alice.address, '']);
         tx = pair.tx.swap({ gasLimit }, 0, expectedOutputAmount, alice.address, '');
         tx = pair.tx.swap({ gasLimit }, 0, expectedOutputAmount, alice.address, '');
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        const { output: reserves } = await pair.query.getReserves(alice.address, {});
+        const { output: reserves } = await query(conn, alice, pair, "getReserves");
         // surely there must be a better way.
         // surely there must be a better way.
         let v: any = reserves;
         let v: any = reserves;
         expect(v[0].eq(token0Amount + swapAmount)).toBeTruthy();
         expect(v[0].eq(token0Amount + swapAmount)).toBeTruthy();
         expect(v[1].eq(token1Amount - expectedOutputAmount)).toBeTruthy();
         expect(v[1].eq(token1Amount - expectedOutputAmount)).toBeTruthy();
 
 
-        const { output: bal0 } = await token0.query.balanceOf(alice.address, {}, pair.address);
+        const { output: bal0 } = await query(conn, alice, token0, "balanceOf", [pair.address]);
         expect(bal0?.eq(token0Amount + swapAmount)).toBeTruthy();
         expect(bal0?.eq(token0Amount + swapAmount)).toBeTruthy();
-        const { output: bal1 } = await token1.query.balanceOf(alice.address, {}, pair.address);
+        const { output: bal1 } = await query(conn, alice, token1, "balanceOf", [pair.address]);
         expect(bal1?.eq(token1Amount - expectedOutputAmount)).toBeTruthy();
         expect(bal1?.eq(token1Amount - expectedOutputAmount)).toBeTruthy();
 
 
-        const { output: returnTotalSupplyToken0 } = await token0.query.totalSupply(alice.address, {});
-        const { output: returnTotalSupplyToken1 } = await token1.query.totalSupply(alice.address, {});
-        const { output: walletBal0 } = await token0.query.balanceOf(alice.address, {}, alice.address);
-        const { output: walletBal1 } = await token1.query.balanceOf(alice.address, {}, alice.address);
+        const { output: returnTotalSupplyToken0 } = await query(conn, alice, token0, "totalSupply");
+        const { output: returnTotalSupplyToken1 } = await query(conn, alice, token1, "totalSupply");
+        const { output: walletBal0 } = await query(conn, alice, token0, "balanceOf", [alice.address]);
+        const { output: walletBal1 } = await query(conn, alice, token1, "balanceOf", [alice.address]);
 
 
         const totalSupplyToken0 = BigInt(returnTotalSupplyToken0!.toString());
         const totalSupplyToken0 = BigInt(returnTotalSupplyToken0!.toString());
         const totalSupplyToken1 = BigInt(returnTotalSupplyToken1!.toString());
         const totalSupplyToken1 = BigInt(returnTotalSupplyToken1!.toString());
@@ -148,27 +155,29 @@ describe('UniswapV2Pair', () => {
         const swapAmount = BigInt(1e18)
         const swapAmount = BigInt(1e18)
         const expectedOutputAmount = BigInt(453305446940074565)
         const expectedOutputAmount = BigInt(453305446940074565)
 
 
+        let gasLimit = await weight(conn, token1, "transfer", [pair.address, swapAmount]);
         let tx = token1.tx.transfer({ gasLimit }, pair.address, swapAmount);
         let tx = token1.tx.transfer({ gasLimit }, pair.address, swapAmount);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
+        gasLimit = await weight(conn, pair, "swap", [expectedOutputAmount, 0, alice.address, '']);
         tx = pair.tx.swap({ gasLimit }, expectedOutputAmount, 0, alice.address, '');
         tx = pair.tx.swap({ gasLimit }, expectedOutputAmount, 0, alice.address, '');
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        const { output: reserves } = await pair.query.getReserves(alice.address, {});
+        const { output: reserves } = await query(conn, alice, pair, "getReserves");
         // surely there must be a better way.
         // surely there must be a better way.
         let v: any = reserves;
         let v: any = reserves;
         expect(v[0].eq(token0Amount - expectedOutputAmount)).toBeTruthy();
         expect(v[0].eq(token0Amount - expectedOutputAmount)).toBeTruthy();
         expect(v[1].eq(token1Amount + swapAmount)).toBeTruthy();
         expect(v[1].eq(token1Amount + swapAmount)).toBeTruthy();
 
 
-        const { output: bal0 } = await token0.query.balanceOf(alice.address, {}, pair.address);
+        const { output: bal0 } = await query(conn, alice, token0, "balanceOf", [pair.address]);
         expect(bal0?.eq(token0Amount - expectedOutputAmount)).toBeTruthy();
         expect(bal0?.eq(token0Amount - expectedOutputAmount)).toBeTruthy();
-        const { output: bal1 } = await token1.query.balanceOf(alice.address, {}, pair.address);
+        const { output: bal1 } = await query(conn, alice, token1, "balanceOf", [pair.address]);
         expect(bal1?.eq(token1Amount + swapAmount)).toBeTruthy();
         expect(bal1?.eq(token1Amount + swapAmount)).toBeTruthy();
 
 
-        const { output: returnTotalSupplyToken0 } = await token0.query.totalSupply(alice.address, {});
-        const { output: returnTotalSupplyToken1 } = await token1.query.totalSupply(alice.address, {});
-        const { output: walletBal0 } = await token0.query.balanceOf(alice.address, {}, alice.address);
-        const { output: walletBal1 } = await token1.query.balanceOf(alice.address, {}, alice.address);
+        const { output: returnTotalSupplyToken0 } = await query(conn, alice, token0, "totalSupply");
+        const { output: returnTotalSupplyToken1 } = await query(conn, alice, token1, "totalSupply");
+        const { output: walletBal0 } = await query(conn, alice, token0, "balanceOf", [alice.address]);
+        const { output: walletBal1 } = await query(conn, alice, token1, "balanceOf", [alice.address]);
 
 
         const totalSupplyToken0 = BigInt(returnTotalSupplyToken0!.toString());
         const totalSupplyToken0 = BigInt(returnTotalSupplyToken0!.toString());
         const totalSupplyToken1 = BigInt(returnTotalSupplyToken1!.toString());
         const totalSupplyToken1 = BigInt(returnTotalSupplyToken1!.toString());
@@ -184,32 +193,34 @@ describe('UniswapV2Pair', () => {
 
 
         const expectedLiquidity = BigInt(3e18)
         const expectedLiquidity = BigInt(3e18)
 
 
+        let gasLimit = await weight(conn, pair, "transferAddressUint256", [pair.address, expectedLiquidity - MINIMUM_LIQUIDITY]);
         let tx = pair.tx.transferAddressUint256({ gasLimit }, pair.address, expectedLiquidity - MINIMUM_LIQUIDITY);
         let tx = pair.tx.transferAddressUint256({ gasLimit }, pair.address, expectedLiquidity - MINIMUM_LIQUIDITY);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
+        gasLimit = await weight(conn, pair, "burn", [alice.address]);
         tx = pair.tx.burn({ gasLimit }, alice.address);
         tx = pair.tx.burn({ gasLimit }, alice.address);
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        const { output: walletBal0 } = await pair.query.balanceOfAddress(alice.address, {}, alice.address);
+        const { output: walletBal0 } = await query(conn, alice, pair, "balanceOfAddress", [alice.address]);
         expect(walletBal0?.eq(0)).toBeTruthy();
         expect(walletBal0?.eq(0)).toBeTruthy();
 
 
-        const { output: pairTotalSupply } = await pair.query.totalSupply(alice.address, {});
+        const { output: pairTotalSupply } = await query(conn, alice, pair, "totalSupply");
         expect(pairTotalSupply?.eq(MINIMUM_LIQUIDITY)).toBeTruthy();
         expect(pairTotalSupply?.eq(MINIMUM_LIQUIDITY)).toBeTruthy();
 
 
-        const { output: token0pairBal } = await token0.query.balanceOf(alice.address, {}, pair.address);
+        const { output: token0pairBal } = await query(conn, alice, token0, "balanceOf", [pair.address]);
         expect(token0pairBal?.eq(1000)).toBeTruthy();
         expect(token0pairBal?.eq(1000)).toBeTruthy();
-        const { output: token1pairBal } = await token1.query.balanceOf(alice.address, {}, pair.address);
+        const { output: token1pairBal } = await query(conn, alice, token1, "balanceOf", [pair.address]);
         expect(token1pairBal?.eq(1000)).toBeTruthy();
         expect(token1pairBal?.eq(1000)).toBeTruthy();
 
 
-        const { output: retToken0TotalSupply } = await token0.query.totalSupply(alice.address, {});
-        const { output: retToken1TotalSupply } = await token1.query.totalSupply(alice.address, {});
+        const { output: retToken0TotalSupply } = await query(conn, alice, token0, "totalSupply");
+        const { output: retToken1TotalSupply } = await query(conn, alice, token1, "totalSupply");
 
 
         const totalSupplyToken0 = BigInt(retToken0TotalSupply!.toString());
         const totalSupplyToken0 = BigInt(retToken0TotalSupply!.toString());
         const totalSupplyToken1 = BigInt(retToken1TotalSupply!.toString());
         const totalSupplyToken1 = BigInt(retToken1TotalSupply!.toString());
 
 
-        const { output: bal0 } = await token0.query.balanceOf(alice.address, {}, alice.address);
+        const { output: bal0 } = await query(conn, alice, token0, "balanceOf", [alice.address]);
         expect(bal0?.eq(totalSupplyToken0 - 1000n)).toBeTruthy();
         expect(bal0?.eq(totalSupplyToken0 - 1000n)).toBeTruthy();
-        const { output: bal1 } = await token1.query.balanceOf(alice.address, {}, alice.address);
+        const { output: bal1 } = await query(conn, alice, token1, "balanceOf", [alice.address]);
         expect(bal1?.eq(totalSupplyToken1 - 1000n)).toBeTruthy();
         expect(bal1?.eq(totalSupplyToken1 - 1000n)).toBeTruthy();
     })
     })
 });
 });

+ 5 - 4
integration/substrate/array_struct_mapping_storage.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, aliceKeypair, transaction } from './index';
+import { weight, createConnection, deploy, aliceKeypair, transaction, query } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 
 
 describe('Deploy array_struct_mapping_storage contract and test', () => {
 describe('Deploy array_struct_mapping_storage contract and test', () => {
@@ -14,6 +14,7 @@ describe('Deploy array_struct_mapping_storage contract and test', () => {
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
 
 
         // first set a canary
         // first set a canary
+        let gasLimit = await weight(conn, contract, "setNumber", [2147483647]);
         let tx = contract.tx.setNumber({ gasLimit }, 2147483647);
         let tx = contract.tx.setNumber({ gasLimit }, 2147483647);
 
 
         await transaction(tx, alice);
         await transaction(tx, alice);
@@ -39,7 +40,7 @@ describe('Deploy array_struct_mapping_storage contract and test', () => {
         // test our values
         // test our values
         for (let array_no = 0; array_no < 2; array_no += 1) {
         for (let array_no = 0; array_no < 2; array_no += 1) {
             for (let i = 0; i < 10; i += 1) {
             for (let i = 0; i < 10; i += 1) {
-                let { output } = await contract.query.get(alice.address, {}, array_no, 102 + i + array_no * 500);
+                let { output } = await query(conn, alice, contract, "get", [array_no, 102 + i + array_no * 500]);
 
 
                 let number = Number.parseInt(output!.toString());
                 let number = Number.parseInt(output!.toString());
 
 
@@ -53,7 +54,7 @@ describe('Deploy array_struct_mapping_storage contract and test', () => {
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
         for (let i = 0; i < 10; i += 1) {
         for (let i = 0; i < 10; i += 1) {
-            let { output } = await contract.query.get(alice.address, {}, 0, 102 + i);
+            let { output } = await query(conn, alice, contract, "get", [0, 102 + i]);
 
 
             let number = Number.parseInt(output!.toString());
             let number = Number.parseInt(output!.toString());
 
 
@@ -65,7 +66,7 @@ describe('Deploy array_struct_mapping_storage contract and test', () => {
         }
         }
 
 
         // test our canary
         // test our canary
-        let { output } = await contract.query.number(alice.address, {});
+        let { output } = await query(conn, alice, contract, "number");
 
 
         let number = Number.parseInt(output!.toString());
         let number = Number.parseInt(output!.toString());
 
 

+ 7 - 5
integration/substrate/arrays.spec.ts

@@ -1,6 +1,6 @@
 import expect from 'expect';
 import expect from 'expect';
 import crypto from 'crypto';
 import crypto from 'crypto';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { createConnection, deploy, transaction, aliceKeypair, weight, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -38,6 +38,7 @@ describe('Deploy arrays contract and test', () => {
                 perms.push(`Perm${p + 1}`);
                 perms.push(`Perm${p + 1}`);
             }
             }
 
 
+            let gasLimit = await weight(conn, contract, "addUser", [id, addr, name, perms]);
             const tx1 = contract.tx.addUser({ gasLimit }, id, addr, name, perms);
             const tx1 = contract.tx.addUser({ gasLimit }, id, addr, name, perms);
 
 
             await transaction(tx1, alice);
             await transaction(tx1, alice);
@@ -47,7 +48,7 @@ describe('Deploy arrays contract and test', () => {
 
 
         let user = users[Math.floor(Math.random() * users.length)];
         let user = users[Math.floor(Math.random() * users.length)];
 
 
-        let res1 = await contract.query.getUserById(alice.address, {}, user.id);
+        let res1 = await query(conn, alice, contract, "getUserById", [user.id]);
 
 
         expect(res1.output?.toJSON()).toStrictEqual(user);
         expect(res1.output?.toJSON()).toStrictEqual(user);
 
 
@@ -56,22 +57,23 @@ describe('Deploy arrays contract and test', () => {
 
 
             let p = perms[Math.floor(Math.random() * perms.length)];
             let p = perms[Math.floor(Math.random() * perms.length)];
 
 
-            let res2 = await contract.query.hasPermission(alice.address, {}, user.id, p);
+            let res2 = await query(conn, alice, contract, "hasPermission", [user.id, p]);
 
 
             expect(res2.output?.toJSON()).toBe(true);
             expect(res2.output?.toJSON()).toBe(true);
         }
         }
 
 
         user = users[Math.floor(Math.random() * users.length)];
         user = users[Math.floor(Math.random() * users.length)];
 
 
-        let res3 = await contract.query.getUserByAddress(alice.address, {}, user.addr);
+        let res3 = await query(conn, alice, contract, "getUserByAddress", [user.addr]);
 
 
         expect(res3.output?.toJSON()).toStrictEqual(user);
         expect(res3.output?.toJSON()).toStrictEqual(user);
 
 
+        let gasLimit = await weight(conn, contract, "removeUser", [user.id]);
         const tx2 = contract.tx.removeUser({ gasLimit }, user.id);
         const tx2 = contract.tx.removeUser({ gasLimit }, user.id);
 
 
         await transaction(tx2, alice);
         await transaction(tx2, alice);
 
 
-        let res4 = await contract.query.userExists(alice.address, {}, user.id);
+        let res4 = await query(conn, alice, contract, "userExists", [user.id]);
 
 
         expect(res4.output?.toJSON()).toBe(false);
         expect(res4.output?.toJSON()).toBe(false);
     });
     });

+ 5 - 4
integration/substrate/asserts.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -24,13 +24,14 @@ describe('Deploy asserts contract and test', () => {
 
 
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
 
 
-        let res0 = await contract.query.var(alice.address, {});
+        let res0 = await query(conn, alice, contract, "var");
 
 
         expect(res0.output?.toJSON()).toEqual(1);
         expect(res0.output?.toJSON()).toEqual(1);
 
 
-        let res1 = await contract.query.testAssertRpc(alice.address, {});
+        let res1 = await query(conn, alice, contract, "testAssertRpc");
         expect(res1.result.toHuman()).toEqual({ "Err": { "Module": { "error": "0x0b000000", "index": "7" } } });
         expect(res1.result.toHuman()).toEqual({ "Err": { "Module": { "error": "0x0b000000", "index": "7" } } });
 
 
+        let gasLimit = await weight(conn, contract, "testAssert");
         let tx = contract.tx.testAssert({ gasLimit });
         let tx = contract.tx.testAssert({ gasLimit });
 
 
         let res2 = await transaction(tx, alice).then(() => {
         let res2 = await transaction(tx, alice).then(() => {
@@ -39,7 +40,7 @@ describe('Deploy asserts contract and test', () => {
 
 
         expect(res2.dispatchError.toHuman()).toEqual({ "Module": { "error": "0x0b000000", "index": "7" } });
         expect(res2.dispatchError.toHuman()).toEqual({ "Module": { "error": "0x0b000000", "index": "7" } });
 
 
-        let res3 = await contract.query.var(alice.address, {});
+        let res3 = await query(conn, alice, contract, "var");
 
 
         expect(res3.output?.toJSON()).toEqual(1);
         expect(res3.output?.toJSON()).toEqual(1);
     });
     });

+ 3 - 2
integration/substrate/balances.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, daveKeypair } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -25,11 +25,12 @@ describe('Deploy balances contract and test', () => {
 
 
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
 
 
-        let { output: contractRpcBal } = await contract.query.getBalance(alice.address, {});
+        let { output: contractRpcBal } = await query(conn, alice, contract, "getBalance");
         let { data: { free: contractQueryBalBefore } } = await conn.query.system.account(String(deploy_contract.address));
         let { data: { free: contractQueryBalBefore } } = await conn.query.system.account(String(deploy_contract.address));
 
 
         expect(contractRpcBal?.toString()).toBe(contractQueryBalBefore.toString());
         expect(contractRpcBal?.toString()).toBe(contractQueryBalBefore.toString());
 
 
+        let gasLimit = await weight(conn, contract, "payMe");
         let tx = contract.tx.payMe({ gasLimit, value: 1000000n });
         let tx = contract.tx.payMe({ gasLimit, value: 1000000n });
 
 
         await transaction(tx, alice);
         await transaction(tx, alice);

+ 5 - 5
integration/substrate/builtins.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { createConnection, deploy, transaction, aliceKeypair, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 
 
 describe('Deploy builtin contract and test', () => {
 describe('Deploy builtin contract and test', () => {
@@ -14,19 +14,19 @@ describe('Deploy builtin contract and test', () => {
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
 
 
         // call the constructor
         // call the constructor
-        let ripemd160_res = await contract.query.hashRipemd160(alice.address, {}, '0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex'));
+        let ripemd160_res = await query(conn, alice, contract, "hashRipemd160", ['0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex')]);
 
 
         expect(ripemd160_res.output?.toJSON()).toBe("0x0c8b641c461e3c7abbdabd7f12a8905ee480dadf");
         expect(ripemd160_res.output?.toJSON()).toBe("0x0c8b641c461e3c7abbdabd7f12a8905ee480dadf");
 
 
-        let sha256_res = await contract.query.hashSha256(alice.address, {}, '0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex'));
+        let sha256_res = await query(conn, alice, contract, "hashSha256", ['0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex')]);
 
 
         expect(sha256_res.output?.toJSON()).toBe("0x458f3ceeeec730139693560ecf66c9c22d9c7bc7dcb0599e8e10b667dfeac043");
         expect(sha256_res.output?.toJSON()).toBe("0x458f3ceeeec730139693560ecf66c9c22d9c7bc7dcb0599e8e10b667dfeac043");
 
 
-        let keccak256_res = await contract.query.hashKecccak256(alice.address, {}, '0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex'));
+        let keccak256_res = await query(conn, alice, contract, "hashKecccak256", ['0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex')]);
 
 
         expect(keccak256_res.output?.toJSON()).toBe("0x823ad8e1757b879aac338f9a18542928c668e479b37e4a56f024016215c5928c");
         expect(keccak256_res.output?.toJSON()).toBe("0x823ad8e1757b879aac338f9a18542928c668e479b37e4a56f024016215c5928c");
 
 
-        let timestamps_res = await contract.query.mrNow(alice.address, {});
+        let timestamps_res = await query(conn, alice, contract, "mrNow");
 
 
         let now = Math.floor(+new Date() / 1000);
         let now = Math.floor(+new Date() / 1000);
 
 

+ 13 - 10
integration/substrate/builtins2.spec.ts

@@ -1,6 +1,7 @@
 import expect from 'expect';
 import expect from 'expect';
-import { createConnection, deploy, aliceKeypair, gasLimit } from './index';
+import { createConnection, deploy, aliceKeypair, weight, query } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
+import { convertWeight } from '@polkadot/api-contract/base/util';
 
 
 describe('Deploy builtins2 contract and test', () => {
 describe('Deploy builtins2 contract and test', () => {
     it('builtins2', async function () {
     it('builtins2', async function () {
@@ -13,15 +14,17 @@ describe('Deploy builtins2 contract and test', () => {
 
 
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
 
 
-        let { output: blake2_128 } = await contract.query.hashBlake2128(alice.address, {}, '0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex'));
+        let gasLimit = await weight(conn, contract, "burnGas", [0]);
+
+        let { output: blake2_128 } = await query(conn, alice, contract, "hashBlake2128", ['0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex')]);
 
 
         expect(blake2_128?.toJSON()).toBe("0x56691483d63cac66c38c168c703c6f13");
         expect(blake2_128?.toJSON()).toBe("0x56691483d63cac66c38c168c703c6f13");
 
 
-        let { output: blake2_256 } = await contract.query.hashBlake2256(alice.address, {}, '0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex'));
+        let { output: blake2_256 } = await query(conn, alice, contract, "hashBlake2256", ['0x' + Buffer.from('Call me Ishmael.', 'utf8').toString('hex')]);
 
 
         expect(blake2_256?.toJSON()).toBe("0x1abd7330c92d835b5084219aedba821c3a599d039d5b66fb5a22ee8e813951a8");
         expect(blake2_256?.toJSON()).toBe("0x1abd7330c92d835b5084219aedba821c3a599d039d5b66fb5a22ee8e813951a8");
 
 
-        let { output: _contract_block_number } = await contract.query.blockHeight(alice.address, {});
+        let { output: _contract_block_number } = await query(conn, alice, contract, "blockHeight", []);
 
 
         let contract_block_number = Number.parseInt(_contract_block_number!.toString());
         let contract_block_number = Number.parseInt(_contract_block_number!.toString());
 
 
@@ -29,19 +32,19 @@ describe('Deploy builtins2 contract and test', () => {
 
 
         expect(Math.abs(contract_block_number - rpc_block_number)).toBeLessThanOrEqual(3);
         expect(Math.abs(contract_block_number - rpc_block_number)).toBeLessThanOrEqual(3);
 
 
-        let { output: gas_left } = await contract.query.burnGas(alice.address, { gasLimit }, 0);
+        let { output: gas_left } = await query(conn, alice, contract, "burnGas", [0], undefined, convertWeight(gasLimit).v2Weight);
         let gas = BigInt(gas_left!.toString());
         let gas = BigInt(gas_left!.toString());
-        expect(gasLimit).toBeGreaterThan(gas);
-        let previous_diff = gasLimit - gas;
+        expect(gasLimit.toJSON().refTime).toBeGreaterThan(gas);
+        let previous_diff = BigInt(gasLimit.toJSON().refTime) - gas;
 
 
         // Gas metering is based on execution time:
         // Gas metering is based on execution time:
         // Expect each call to burn between 10000..1000000 more gas than the previous iteration.
         // Expect each call to burn between 10000..1000000 more gas than the previous iteration.
         for (let i = 1; i < 100; i++) {
         for (let i = 1; i < 100; i++) {
-            let { output: gas_left } = await contract.query.burnGas(alice.address, { gasLimit }, i);
+            let { output: gas_left } = await query(conn, alice, contract, "burnGas", [i], undefined, convertWeight(gasLimit).v2Weight);
             let gas = BigInt(gas_left!.toString());
             let gas = BigInt(gas_left!.toString());
-            expect(gasLimit).toBeGreaterThan(gas);
+            expect(gasLimit.toJSON().refTime).toBeGreaterThan(gas);
 
 
-            let diff = gasLimit - gas;
+            let diff = BigInt(gasLimit.toJSON().refTime) - gas;
             expect(diff).toBeGreaterThan(previous_diff);
             expect(diff).toBeGreaterThan(previous_diff);
             expect(diff - previous_diff).toBeLessThan(1e6);
             expect(diff - previous_diff).toBeLessThan(1e6);
             expect(diff - previous_diff).toBeGreaterThan(1e4);
             expect(diff - previous_diff).toBeGreaterThan(1e4);

+ 4 - 3
integration/substrate/create_contract.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -27,16 +27,17 @@ describe('Deploy create_contract contract and test', () => {
 
 
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
 
 
+        let gasLimit = await weight(conn, contract, "createChild");
         let tx = contract.tx.createChild({ gasLimit });
         let tx = contract.tx.createChild({ gasLimit });
 
 
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        let res2 = await contract.query.callChild(alice.address, {});
+        let res2 = await query(conn, alice, contract, "callChild");
 
 
         expect(res2.output?.toJSON()).toStrictEqual("child");
         expect(res2.output?.toJSON()).toStrictEqual("child");
 
 
         // child was created with a balance of 1e15, verify
         // child was created with a balance of 1e15, verify
-        res2 = await contract.query.c(alice.address, {});
+        res2 = await query(conn, alice, contract, "c");
 
 
         let child = res2.output!.toString();
         let child = res2.output!.toString();
 
 

+ 3 - 2
integration/substrate/destruct.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, daveKeypair } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -25,13 +25,14 @@ describe('Deploy destruct contract and test', () => {
 
 
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
 
 
-        let hello = await contract.query.hello(alice.address, {});
+        let hello = await query(conn, alice, contract, "hello");
 
 
         expect(hello.output?.toJSON()).toBe('Hello');
         expect(hello.output?.toJSON()).toBe('Hello');
 
 
         let { data: { free: daveBalBefore } } = await conn.query.system.account(dave.address);
         let { data: { free: daveBalBefore } } = await conn.query.system.account(dave.address);
         let { data: { free: contractBalBefore } } = await conn.query.system.account(String(deploy_contract.address));
         let { data: { free: contractBalBefore } } = await conn.query.system.account(String(deploy_contract.address));
 
 
+        let gasLimit = await weight(conn, contract, "selfterminate", [dave.address]);
         let tx = contract.tx.selfterminate({ gasLimit }, dave.address);
         let tx = contract.tx.selfterminate({ gasLimit }, dave.address);
 
 
         await transaction(tx, alice);
         await transaction(tx, alice);

+ 2 - 1
integration/substrate/events.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 import { DecodedEvent } from '@polkadot/api-contract/types';
 import { DecodedEvent } from '@polkadot/api-contract/types';
@@ -22,6 +22,7 @@ describe('Deploy events contract and test event data, docs and topics', () => {
 
 
         let deploy_contract = await deploy(conn, alice, 'Events.contract', BigInt(0));
         let deploy_contract = await deploy(conn, alice, 'Events.contract', BigInt(0));
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
+        let gasLimit = await weight(conn, contract, "emitEvent");
         let tx = contract.tx.emitEvent({ gasLimit });
         let tx = contract.tx.emitEvent({ gasLimit });
         let res0: any = await transaction(tx, alice);
         let res0: any = await transaction(tx, alice);
         let events: DecodedEvent[] = res0.contractEvents;
         let events: DecodedEvent[] = res0.contractEvents;

+ 9 - 7
integration/substrate/external_call.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -32,35 +32,37 @@ describe('Deploy external_call contract and test', () => {
 
 
         let callee2_contract = new ContractPromise(conn, callee2_res.abi, callee2_res.address);
         let callee2_contract = new ContractPromise(conn, callee2_res.abi, callee2_res.address);
 
 
+        let gasLimit = await weight(conn, callee_contract, "setX", [102]);
         let tx1 = callee_contract.tx.setX({ gasLimit }, 102);
         let tx1 = callee_contract.tx.setX({ gasLimit }, 102);
 
 
         await transaction(tx1, alice);
         await transaction(tx1, alice);
 
 
-        let res1 = await callee_contract.query.getX(alice.address, {});
+        let res1 = await query(conn, alice, callee_contract, "getX");
 
 
         expect(res1.output?.toJSON()).toStrictEqual(102);
         expect(res1.output?.toJSON()).toStrictEqual(102);
 
 
-        let res2 = await caller_contract.query.whoAmI(alice.address, {});
+        let res2 = await query(conn, alice, caller_contract, "whoAmI");
 
 
         expect(res2.output?.toString()).toEqual(caller_res.address.toString());
         expect(res2.output?.toString()).toEqual(caller_res.address.toString());
 
 
+        gasLimit = await weight(conn, caller_contract, "doCall", [callee_contract.address, 13123]);
         let tx2 = caller_contract.tx.doCall({ gasLimit }, callee_contract.address, 13123);
         let tx2 = caller_contract.tx.doCall({ gasLimit }, callee_contract.address, 13123);
 
 
         await transaction(tx2, alice);
         await transaction(tx2, alice);
 
 
-        let res3 = await callee_contract.query.getX(alice.address, {});
+        let res3 = await query(conn, alice, callee_contract, "getX");
 
 
         expect(res3.output?.toJSON()).toStrictEqual(13123);
         expect(res3.output?.toJSON()).toStrictEqual(13123);
 
 
-        let res4 = await caller_contract.query.doCall2(alice.address, {}, callee_contract.address, 20000);
+        let res4 = await query(conn, alice, caller_contract, "doCall2", [callee_contract.address, 20000]);
 
 
         expect(res4.output?.toJSON()).toStrictEqual(33123);
         expect(res4.output?.toJSON()).toStrictEqual(33123);
 
 
-        let res5 = await caller_contract.query.doCall3(alice.address, {}, callee_contract.address, callee2_contract.address, [3, 5, 7, 9], "yo");
+        let res5 = await query(conn, alice, caller_contract, "doCall3", [callee_contract.address, callee2_contract.address, [3, 5, 7, 9], "yo"]);
 
 
         expect(res5.output?.toJSON()).toEqual([24, "my name is callee"]);
         expect(res5.output?.toJSON()).toEqual([24, "my name is callee"]);
 
 
-        let res6 = await caller_contract.query.doCall4(alice.address, {}, callee_contract.address, callee2_contract.address, [1, 2, 3, 4], "asda");
+        let res6 = await query(conn, alice, caller_contract, "doCall4", [callee_contract.address, callee2_contract.address, [1, 2, 3, 4], "asda"]);
 
 
         expect(res6.output?.toJSON()).toEqual([10, "x:asda"]);
         expect(res6.output?.toJSON()).toEqual([10, "x:asda"]);
     });
     });

+ 4 - 3
integration/substrate/flipper.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 
 
 describe('Deploy flipper contract and test', () => {
 describe('Deploy flipper contract and test', () => {
@@ -13,15 +13,16 @@ describe('Deploy flipper contract and test', () => {
 
 
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
 
 
-        let init_value = await contract.query.get(alice.address, {});
+        let init_value = await query(conn, alice, contract, "get");
 
 
         expect(init_value.output?.toJSON()).toBe(true);
         expect(init_value.output?.toJSON()).toBe(true);
 
 
+        let gasLimit = await weight(conn, contract, "flip");
         const tx = contract.tx.flip({ gasLimit });
         const tx = contract.tx.flip({ gasLimit });
 
 
         await transaction(tx, alice);
         await transaction(tx, alice);
 
 
-        let flipped_value = await contract.query.get(alice.address, {});
+        let flipped_value = await query(conn, alice, contract, "get");
 
 
         expect(flipped_value.output?.toJSON()).toBe(false);
         expect(flipped_value.output?.toJSON()).toBe(false);
 
 

+ 44 - 8
integration/substrate/index.ts

@@ -1,13 +1,15 @@
 import '@polkadot/api-augment';
 import '@polkadot/api-augment';
 import fs, { PathLike } from 'fs';
 import fs, { PathLike } from 'fs';
 import { ApiPromise, WsProvider, Keyring } from '@polkadot/api';
 import { ApiPromise, WsProvider, Keyring } from '@polkadot/api';
-import { CodePromise } from '@polkadot/api-contract';
+import { convertWeight } from '@polkadot/api-contract/base/util';
+import { CodePromise, ContractPromise } from '@polkadot/api-contract';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
-import { ISubmittableResult } from '@polkadot/types/types';
+import { Codec, ISubmittableResult } from '@polkadot/types/types';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
+import expect from 'expect';
+import { ContractExecResultResult, WeightV2 } from '@polkadot/types/interfaces';
 
 
-const default_url: string = "ws://localhost:9944";
-export const gasLimit: bigint = 200000n * 1000000n;
+const default_url = "ws://127.0.0.1:9944";
 
 
 export function aliceKeypair(): KeyringPair {
 export function aliceKeypair(): KeyringPair {
   const keyring = new Keyring({ type: 'sr25519' });
   const keyring = new Keyring({ type: 'sr25519' });
@@ -19,17 +21,18 @@ export function daveKeypair(): KeyringPair {
   return keyring.addFromUri('//Dave');
   return keyring.addFromUri('//Dave');
 }
 }
 
 
-export async function createConnection(): Promise<ApiPromise> {
-  let url = process.env.RPC_URL || default_url;
+export function createConnection(): Promise<ApiPromise> {
+  const url = process.env.RPC_URL || default_url;
 
 
   return ApiPromise.create({ provider: new WsProvider(url) });
   return ApiPromise.create({ provider: new WsProvider(url) });
 }
 }
 
 
-export async function deploy(api: ApiPromise, pair: KeyringPair, file: PathLike, value: bigint, ...params: unknown[]): Promise<any> {
+export function deploy(api: ApiPromise, pair: KeyringPair, file: PathLike, value: bigint, ...params: unknown[]): Promise<any> {
   const contractJson = fs.readFileSync(file, { encoding: 'utf-8' });
   const contractJson = fs.readFileSync(file, { encoding: 'utf-8' });
 
 
   const code = new CodePromise(api, contractJson, null);
   const code = new CodePromise(api, contractJson, null);
 
 
+  const gasLimit = api.registry.createType('WeightV2', convertWeight(200000n * 1000000n).v2Weight);
   const tx = code.tx.new({ gasLimit, value }, ...params);
   const tx = code.tx.new({ gasLimit, value }, ...params);
 
 
   return new Promise(async (resolve, reject) => {
   return new Promise(async (resolve, reject) => {
@@ -53,7 +56,7 @@ export async function deploy(api: ApiPromise, pair: KeyringPair, file: PathLike,
   });
   });
 }
 }
 
 
-export async function transaction(tx: SubmittableExtrinsic<"promise", ISubmittableResult>, pair: KeyringPair): Promise<ISubmittableResult> {
+export function transaction(tx: SubmittableExtrinsic<"promise", ISubmittableResult>, pair: KeyringPair): Promise<ISubmittableResult> {
   return new Promise(async (resolve, reject) => {
   return new Promise(async (resolve, reject) => {
     const unsub = await tx.signAndSend(pair, (result: any) => {
     const unsub = await tx.signAndSend(pair, (result: any) => {
       if (result.dispatchError) {
       if (result.dispatchError) {
@@ -75,3 +78,36 @@ export async function transaction(tx: SubmittableExtrinsic<"promise", ISubmittab
     });
     });
   });
   });
 }
 }
+
+// Returns the required gas estimated from a dry run
+export async function weight(api: ApiPromise, contract: ContractPromise, message: string, args?: unknown[], value?: number) {
+  const ALICE = new Keyring({ type: 'sr25519' }).addFromUri('//Alice').address;
+  const msg = contract.abi.findMessage(message);
+  const dry = await api.call.contractsApi.call(ALICE, contract.address, value ? value : 0, null, null, msg.toU8a(args ? args : []));
+  return dry.gasRequired;
+}
+
+// FIXME: The old contract.query API does not support WeightV2 yet
+export async function query(
+  api: ApiPromise,
+  account: KeyringPair,
+  contract: ContractPromise,
+  message: string,
+  args?: unknown[],
+  value?: number,
+  gasLimit?: WeightV2 | { refTime?: any; proofSize?: any; }
+): Promise<{ output: Codec | null, result: ContractExecResultResult }> {
+  const msg = contract.abi.findMessage(message);
+  const callResult = await api.call.contractsApi.call(account.address, contract.address, value ? value : 0, gasLimit ? gasLimit : null, null, msg.toU8a(args ? args : []));
+  // Same logic as contracts UI, so should be fine.
+  // Refernce implementation: https://github.com/paritytech/contracts-ui/blob/e343221a0d5c1ae67122fe99028246e5bdf38c46/src/ui/hooks/useDecodedOutput.ts
+  const output = callResult.result.isOk && msg.returnType
+    ? contract.abi.registry.createTypeUnsafe(
+      msg.returnType.lookupName || msg.returnType.type,
+      [callResult.result.asOk.data.toU8a(true)],
+      { isPedantic: true }
+    )
+    : null;
+  expect(output !== null && typeof output === 'object' && 'Err' in output).toBeFalsy();
+  return { output, result: callResult.result };
+}

+ 2 - 1
integration/substrate/issue666.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -28,6 +28,7 @@ describe('issue666 flip and inc', () => {
 
 
         let contract = new ContractPromise(conn, inc_contract.abi, inc_contract.address);
         let contract = new ContractPromise(conn, inc_contract.abi, inc_contract.address);
 
 
+        let gasLimit = await weight(conn, contract, "superFlip");
         contract.tx.superFlip({ gasLimit });
         contract.tx.superFlip({ gasLimit });
     });
     });
 });
 });

+ 4 - 3
integration/substrate/msg_sender.spec.ts

@@ -1,5 +1,5 @@
 import expect from "expect";
 import expect from "expect";
-import { aliceKeypair, createConnection, deploy, gasLimit, transaction } from "./index";
+import { aliceKeypair, createConnection, deploy, weight, transaction, query } from "./index";
 import { ContractPromise } from "@polkadot/api-contract";
 import { ContractPromise } from "@polkadot/api-contract";
 import { DecodedEvent } from "@polkadot/api-contract/types";
 import { DecodedEvent } from "@polkadot/api-contract/types";
 import { ApiPromise } from "@polkadot/api";
 import { ApiPromise } from "@polkadot/api";
@@ -23,10 +23,10 @@ describe('Deploy mytoken contract and test', () => {
         let deployed_contract = await deploy(conn, alice, 'mytoken.contract', BigInt(0));
         let deployed_contract = await deploy(conn, alice, 'mytoken.contract', BigInt(0));
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
 
 
-        let res = await contract.query.test(alice.address, {}, alice.address, true);
+        let res = await query(conn, alice, contract, "test", [alice.address, true]);
         expect(res.output?.toJSON()).toEqual(alice.address);
         expect(res.output?.toJSON()).toEqual(alice.address);
 
 
-        res = await contract.query.test(alice.address, {}, alice.address, false);
+        res = await query(conn, alice, contract, "test", [alice.address, false]);
         expect(res.output?.toJSON()).toEqual(alice.address);
         expect(res.output?.toJSON()).toEqual(alice.address);
     });
     });
 
 
@@ -37,6 +37,7 @@ describe('Deploy mytoken contract and test', () => {
 
 
         let deployed_contract = await deploy(conn, alice, 'mytokenEvent.contract', BigInt(0));
         let deployed_contract = await deploy(conn, alice, 'mytokenEvent.contract', BigInt(0));
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
+        let gasLimit = await weight(conn, contract, "test");
         let tx = contract.tx.test({ gasLimit });
         let tx = contract.tx.test({ gasLimit });
         let res0: any = await transaction(tx, alice);
         let res0: any = await transaction(tx, alice);
 
 

+ 4 - 4
integration/substrate/overloading.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { createConnection, deploy, transaction, aliceKeypair, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -21,14 +21,14 @@ describe('Deploy contract with overloaded functions using mangled names', () =>
         let deploy_contract = await deploy(conn, alice, 'Overloading.contract', BigInt(0));
         let deploy_contract = await deploy(conn, alice, 'Overloading.contract', BigInt(0));
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
         let contract = new ContractPromise(conn, deploy_contract.abi, deploy_contract.address);
 
 
-        let res0 = await contract.query.echo(alice.address, {});
+        let res0 = await query(conn, alice, contract, "echo");
         expect(res0.output?.toJSON()).toEqual(42);
         expect(res0.output?.toJSON()).toEqual(42);
 
 
-        let res1 = await contract.query.echoUint32(alice.address, {}, 1234);
+        let res1 = await query(conn, alice, contract, "echoUint32", [1234]);
         expect(res1.output?.toJSON()).toEqual(1234);
         expect(res1.output?.toJSON()).toEqual(1234);
 
 
         let someStruct = { s: "foo", e: [["v1", "v2"], ["v3", "v4"]] };
         let someStruct = { s: "foo", e: [["v1", "v2"], ["v3", "v4"]] };
-        let res2 = await contract.query.echoBoolStringUint8Array2Array(alice.address, {}, true, someStruct);
+        let res2 = await query(conn, alice, contract, "echoBoolStringUint8Array2Array", [true, someStruct]);
         expect(res2.output?.toJSON()).toEqual(someStruct);
         expect(res2.output?.toJSON()).toEqual(someStruct);
     });
     });
 });
 });

+ 11 - 2
integration/substrate/package.json

@@ -5,9 +5,18 @@
   "main": "index.js",
   "main": "index.js",
   "scripts": {
   "scripts": {
     "test": "tsc; ts-mocha -t 20000 *.spec.ts",
     "test": "tsc; ts-mocha -t 20000 *.spec.ts",
-    "build": "solang compile *.sol test/*.sol --target substrate -v"
+    "build": "parallel solang compile -v --target substrate ::: *.sol test/*.sol"
   },
   },
-  "author": "Sean Young <sean@mess.org>",
+  "contributors": [
+    {
+      "name": "Sean Young",
+      "email": "sean@mess.org"
+    },
+    {
+      "name": "Cyrill Leutwiler",
+      "email": "me@09f9.org"
+    }
+  ],
   "license": "Apache-2.0",
   "license": "Apache-2.0",
   "devDependencies": {
   "devDependencies": {
     "@types/mocha": "^9.1.0",
     "@types/mocha": "^9.1.0",

+ 47 - 47
integration/substrate/primitives.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { createConnection, deploy, aliceKeypair, daveKeypair, } from './index';
+import { createConnection, deploy, aliceKeypair, daveKeypair, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -27,117 +27,117 @@ describe('Deploy primitives contract and test', () => {
         // TEST Basic enums
         // TEST Basic enums
         // in ethereum, an enum is described as an uint8 so can't use the enum
         // in ethereum, an enum is described as an uint8 so can't use the enum
         // names programmatically. 0 = add, 1 = sub, 2 = mul, 3 = div, 4 = mod, 5 = pow, 6 = shl, 7 = shr
         // names programmatically. 0 = add, 1 = sub, 2 = mul, 3 = div, 4 = mod, 5 = pow, 6 = shl, 7 = shr
-        let res = await contract.query.isMul(alice.address, {}, 2);
+        let res = await query(conn, alice, contract, "isMul", [2]);
         expect(res.output?.toJSON()).toEqual(true);
         expect(res.output?.toJSON()).toEqual(true);
 
 
-        res = await contract.query.returnDiv(alice.address, {});
+        res = await query(conn, alice, contract, "returnDiv");
         expect(res.output?.toJSON()).toEqual("div");
         expect(res.output?.toJSON()).toEqual("div");
 
 
         // TEST uint and int types, and arithmetic/bitwise ops
         // TEST uint and int types, and arithmetic/bitwise ops
-        res = await contract.query.opI64(alice.address, {}, 0, 1000, 4100);
+        res = await query(conn, alice, contract, "opI64", [0, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(5100);
         expect(res.output?.toJSON()).toEqual(5100);
-        res = await contract.query.opI64(alice.address, {}, 1, 1000, 4100);
+        res = await query(conn, alice, contract, "opI64", [1, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(-3100);
         expect(res.output?.toJSON()).toEqual(-3100);
-        res = await contract.query.opI64(alice.address, {}, 2, 1000, 4100);
+        res = await query(conn, alice, contract, "opI64", [2, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(4100000);
         expect(res.output?.toJSON()).toEqual(4100000);
-        res = await contract.query.opI64(alice.address, {}, 3, 1000, 10);
+        res = await query(conn, alice, contract, "opI64", [3, 1000, 10]);
         expect(res.output?.toJSON()).toEqual(100);
         expect(res.output?.toJSON()).toEqual(100);
-        res = await contract.query.opI64(alice.address, {}, 4, 1000, 99);
+        res = await query(conn, alice, contract, "opI64", [4, 1000, 99]);
         expect(res.output?.toJSON()).toEqual(10);
         expect(res.output?.toJSON()).toEqual(10);
-        res = await contract.query.opI64(alice.address, {}, 6, - 1000, 8);
+        res = await query(conn, alice, contract, "opI64", [6, - 1000, 8]);
         expect(res.output?.toJSON()).toEqual(-256000);
         expect(res.output?.toJSON()).toEqual(-256000);
-        res = await contract.query.opI64(alice.address, {}, 7, - 1000, 8);
+        res = await query(conn, alice, contract, "opI64", [7, - 1000, 8]);
         expect(res.output?.toJSON()).toEqual(-4);
         expect(res.output?.toJSON()).toEqual(-4);
 
 
 
 
-        res = await contract.query.opU64(alice.address, {}, 0, 1000, 4100);
+        res = await query(conn, alice, contract, "opU64", [0, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(5100);
         expect(res.output?.toJSON()).toEqual(5100);
-        res = await contract.query.opU64(alice.address, {}, 1, 1000, 4100);
+        res = await query(conn, alice, contract, "opU64", [1, 1000, 4100]);
         expect(res.output?.toString()).toEqual("18446744073709548516"); // (2^64)-18446744073709548516 = 3100
         expect(res.output?.toString()).toEqual("18446744073709548516"); // (2^64)-18446744073709548516 = 3100
-        res = await contract.query.opU64(alice.address, {}, 2, 123456789, 123456789);
+        res = await query(conn, alice, contract, "opU64", [2, 123456789, 123456789]);
         expect(res.output?.toString()).toEqual("15241578750190521");
         expect(res.output?.toString()).toEqual("15241578750190521");
-        res = await contract.query.opU64(alice.address, {}, 3, 123456789, 100);
+        res = await query(conn, alice, contract, "opU64", [3, 123456789, 100]);
         expect(res.output?.toJSON()).toEqual(1234567);
         expect(res.output?.toJSON()).toEqual(1234567);
-        res = await contract.query.opU64(alice.address, {}, 4, 123456789, 100);
+        res = await query(conn, alice, contract, "opU64", [4, 123456789, 100]);
         expect(res.output?.toJSON()).toEqual(89);
         expect(res.output?.toJSON()).toEqual(89);
-        res = await contract.query.opU64(alice.address, {}, 5, 3, 7);
+        res = await query(conn, alice, contract, "opU64", [5, 3, 7]);
         expect(res.output?.toJSON()).toEqual(2187);
         expect(res.output?.toJSON()).toEqual(2187);
-        res = await contract.query.opI64(alice.address, {}, 6, 1000, 8);
+        res = await query(conn, alice, contract, "opI64", [6, 1000, 8]);
         expect(res.output?.toJSON()).toEqual(256000);
         expect(res.output?.toJSON()).toEqual(256000);
-        res = await contract.query.opI64(alice.address, {}, 7, 1000, 8);
+        res = await query(conn, alice, contract, "opI64", [7, 1000, 8]);
         expect(res.output?.toJSON()).toEqual(3);
         expect(res.output?.toJSON()).toEqual(3);
 
 
         // // now for 256 bit operations
         // // now for 256 bit operations
-        res = await contract.query.opI256(alice.address, {}, 0, 1000, 4100);
+        res = await query(conn, alice, contract, "opI256", [0, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(5100);
         expect(res.output?.toJSON()).toEqual(5100);
-        res = await contract.query.opI256(alice.address, {}, 1, 1000, 4100);
+        res = await query(conn, alice, contract, "opI256", [1, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(-3100);
         expect(res.output?.toJSON()).toEqual(-3100);
-        res = await contract.query.opI256(alice.address, {}, 2, 1000, 4100);
+        res = await query(conn, alice, contract, "opI256", [2, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(4100000);
         expect(res.output?.toJSON()).toEqual(4100000);
-        res = await contract.query.opI256(alice.address, {}, 3, 1000, 10);
+        res = await query(conn, alice, contract, "opI256", [3, 1000, 10]);
         expect(res.output?.toJSON()).toEqual(100);
         expect(res.output?.toJSON()).toEqual(100);
-        res = await contract.query.opI256(alice.address, {}, 4, 1000, 99);
+        res = await query(conn, alice, contract, "opI256", [4, 1000, 99]);
         expect(res.output?.toJSON()).toEqual(10);
         expect(res.output?.toJSON()).toEqual(10);
-        res = await contract.query.opI256(alice.address, {}, 6, - 10000000000000, 8);
+        res = await query(conn, alice, contract, "opI256", [6, - 10000000000000, 8]);
         expect(res.output?.toJSON()).toEqual(-2560000000000000);
         expect(res.output?.toJSON()).toEqual(-2560000000000000);
-        res = await contract.query.opI256(alice.address, {}, 7, - 10000000000000, 8);
+        res = await query(conn, alice, contract, "opI256", [7, - 10000000000000, 8]);
         expect(res.output?.toJSON()).toEqual(-39062500000);
         expect(res.output?.toJSON()).toEqual(-39062500000);
 
 
-        res = await contract.query.opU256(alice.address, {}, 0, 1000, 4100);
+        res = await query(conn, alice, contract, "opU256", [0, 1000, 4100]);
         expect(res.output?.toJSON()).toEqual(5100);
         expect(res.output?.toJSON()).toEqual(5100);
-        res = await contract.query.opU256(alice.address, {}, 1, 1000, 4100);
+        res = await query(conn, alice, contract, "opU256", [1, 1000, 4100]);
         expect(res.output?.toString()).toEqual('115792089237316195423570985008687907853269984665640564039457584007913129636836'); // (2^64)-18446744073709548516 = 3100
         expect(res.output?.toString()).toEqual('115792089237316195423570985008687907853269984665640564039457584007913129636836'); // (2^64)-18446744073709548516 = 3100
-        res = await contract.query.opU256(alice.address, {}, 2, 123456789, 123456789);
+        res = await query(conn, alice, contract, "opU256", [2, 123456789, 123456789]);
         expect(res.output?.toString()).toEqual('15241578750190521');
         expect(res.output?.toString()).toEqual('15241578750190521');
-        res = await contract.query.opU256(alice.address, {}, 3, 123456789, 100);
+        res = await query(conn, alice, contract, "opU256", [3, 123456789, 100]);
         expect(res.output?.toJSON()).toEqual(1234567);
         expect(res.output?.toJSON()).toEqual(1234567);
-        res = await contract.query.opU256(alice.address, {}, 4, 123456789, 100);
+        res = await query(conn, alice, contract, "opU256", [4, 123456789, 100]);
         expect(res.output?.toJSON()).toEqual(89);
         expect(res.output?.toJSON()).toEqual(89);
-        res = await contract.query.opU256(alice.address, {}, 5, 123456789, 9);
+        res = await query(conn, alice, contract, "opU256", [5, 123456789, 9]);
         expect(res.output?.toString()).toEqual('6662462759719942007440037531362779472290810125440036903063319585255179509');
         expect(res.output?.toString()).toEqual('6662462759719942007440037531362779472290810125440036903063319585255179509');
-        res = await contract.query.opI256(alice.address, {}, 6, 10000000000000, 8);
+        res = await query(conn, alice, contract, "opI256", [6, 10000000000000, 8]);
         expect(res.output?.toJSON()).toEqual(2560000000000000);
         expect(res.output?.toJSON()).toEqual(2560000000000000);
-        res = await contract.query.opI256(alice.address, {}, 7, 10000000000000, 8);
+        res = await query(conn, alice, contract, "opI256", [7, 10000000000000, 8]);
         expect(res.output?.toJSON()).toEqual(39062500000);
         expect(res.output?.toJSON()).toEqual(39062500000);
 
 
         // TEST bytesN
         // TEST bytesN
-        res = await contract.query.returnU86(alice.address, {},);
+        res = await query(conn, alice, contract, "returnU86");
         expect(res.output?.toJSON()).toEqual('0x414243444546');
         expect(res.output?.toJSON()).toEqual('0x414243444546');
 
 
         // TEST bytes5
         // TEST bytes5
-        res = await contract.query.opU85Shift(alice.address, {}, 6, '0xdeadcafe59', 8);
+        res = await query(conn, alice, contract, "opU85Shift", [6, '0xdeadcafe59', 8]);
         expect(res.output?.toJSON()).toEqual('0xadcafe5900');
         expect(res.output?.toJSON()).toEqual('0xadcafe5900');
-        res = await contract.query.opU85Shift(alice.address, {}, 7, '0xdeadcafe59', 8);
+        res = await query(conn, alice, contract, "opU85Shift", [7, '0xdeadcafe59', 8]);
         expect(res.output?.toJSON()).toEqual('0x00deadcafe');
         expect(res.output?.toJSON()).toEqual('0x00deadcafe');
-        res = await contract.query.opU85(alice.address, {}, 8, '0xdeadcafe59', '0x0000000006');
+        res = await query(conn, alice, contract, "opU85", [8, '0xdeadcafe59', '0x0000000006']);
         expect(res.output?.toJSON()).toEqual('0xdeadcafe5f');
         expect(res.output?.toJSON()).toEqual('0xdeadcafe5f');
-        res = await contract.query.opU85(alice.address, {}, 9, '0xdeadcafe59', '0x00000000ff');
+        res = await query(conn, alice, contract, "opU85", [9, '0xdeadcafe59', '0x00000000ff']);
         expect(res.output?.toJSON()).toEqual('0x0000000059');
         expect(res.output?.toJSON()).toEqual('0x0000000059');
-        res = await contract.query.opU85(alice.address, {}, 10, '0xdeadcafe59', '0x00000000ff');
+        res = await query(conn, alice, contract, "opU85", [10, '0xdeadcafe59', '0x00000000ff']);
         expect(res.output?.toJSON()).toEqual('0xdeadcafea6');
         expect(res.output?.toJSON()).toEqual('0xdeadcafea6');
 
 
         // TEST bytes14
         // TEST bytes14
-        res = await contract.query.opU814Shift(alice.address, {}, 6, '0xdeadcafe123456789abcdefbeef7', 9);
+        res = await query(conn, alice, contract, "opU814Shift", [6, '0xdeadcafe123456789abcdefbeef7', 9]);
         expect(res.output?.toJSON()).toEqual('0x5b95fc2468acf13579bdf7ddee00');
         expect(res.output?.toJSON()).toEqual('0x5b95fc2468acf13579bdf7ddee00');
-        res = await contract.query.opU814Shift(alice.address, {}, 7, '0xdeadcafe123456789abcdefbeef7', 9);
+        res = await query(conn, alice, contract, "opU814Shift", [7, '0xdeadcafe123456789abcdefbeef7', 9]);
         expect(res.output?.toJSON()).toEqual('0x006f56e57f091a2b3c4d5e6f7df7');
         expect(res.output?.toJSON()).toEqual('0x006f56e57f091a2b3c4d5e6f7df7');
-        res = await contract.query.opU814(alice.address, {}, 8, '0xdeadcafe123456789abcdefbeef7', '0x0000060000000000000000000000');
+        res = await query(conn, alice, contract, "opU814", [8, '0xdeadcafe123456789abcdefbeef7', '0x0000060000000000000000000000']);
         expect(res.output?.toJSON()).toEqual('0xdeadcefe123456789abcdefbeef7');
         expect(res.output?.toJSON()).toEqual('0xdeadcefe123456789abcdefbeef7');
-        res = await contract.query.opU814(alice.address, {}, 9, '0xdeadcafe123456789abcdefbeef7', '0x000000000000000000ff00000000');
+        res = await query(conn, alice, contract, "opU814", [9, '0xdeadcafe123456789abcdefbeef7', '0x000000000000000000ff00000000']);
         expect(res.output?.toJSON()).toEqual('0x000000000000000000bc00000000');
         expect(res.output?.toJSON()).toEqual('0x000000000000000000bc00000000');
-        res = await contract.query.opU814(alice.address, {}, 10, '0xdeadcafe123456789abcdefbeef7', '0xff00000000000000000000000000');
+        res = await query(conn, alice, contract, "opU814", [10, '0xdeadcafe123456789abcdefbeef7', '0xff00000000000000000000000000']);
         expect(res.output?.toJSON()).toEqual('0x21adcafe123456789abcdefbeef7');
         expect(res.output?.toJSON()).toEqual('0x21adcafe123456789abcdefbeef7');
 
 
         // TEST address type.
         // TEST address type.
         const default_account = '5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sjeZ';
         const default_account = '5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sjeZ';
 
 
-        res = await contract.query.addressPassthrough(alice.address, {}, default_account);
+        res = await query(conn, alice, contract, "addressPassthrough", [default_account]);
         expect(res.output?.toJSON()).toEqual(default_account);
         expect(res.output?.toJSON()).toEqual(default_account);
 
 
-        res = await contract.query.addressPassthrough(alice.address, {}, dave.address);
+        res = await query(conn, alice, contract, "addressPassthrough", [dave.address]);
         expect(res.output?.toJSON()).toEqual(dave.address);
         expect(res.output?.toJSON()).toEqual(dave.address);
 
 
-        res = await contract.query.addressPassthrough(alice.address, {}, alice.address);
+        res = await query(conn, alice, contract, "addressPassthrough", [alice.address]);
         expect(res.output?.toJSON()).toEqual(alice.address);
         expect(res.output?.toJSON()).toEqual(alice.address);
     });
     });
 });
 });

+ 5 - 1
integration/substrate/store.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { weight, createConnection, deploy, transaction, aliceKeypair, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -33,6 +33,7 @@ describe.skip('Deploy store contract and test', () => {
 
 
         expect(res2.output?.toJSON()).toStrictEqual([0, "", "0xb00b1e", "0x00000000", "bar1"]);
         expect(res2.output?.toJSON()).toStrictEqual([0, "", "0xb00b1e", "0x00000000", "bar1"]);
 
 
+        let gasLimit = await weight(conn, contract, "setValues");
         const tx1 = contract.tx.setValues({ gasLimit });
         const tx1 = contract.tx.setValues({ gasLimit });
 
 
         await transaction(tx1, alice);
         await transaction(tx1, alice);
@@ -55,6 +56,7 @@ describe.skip('Deploy store contract and test', () => {
             "bar2",
             "bar2",
         ]);
         ]);
 
 
+        gasLimit = await weight(conn, contract, "doOps");
         const tx2 = contract.tx.doOps({ gasLimit });
         const tx2 = contract.tx.doOps({ gasLimit });
 
 
         await transaction(tx2, alice);
         await transaction(tx2, alice);
@@ -78,6 +80,7 @@ describe.skip('Deploy store contract and test', () => {
             "bar4",
             "bar4",
         ]);
         ]);
 
 
+        gasLimit = await weight(conn, contract, "pushZero");
         const tx3 = contract.tx.pushZero({ gasLimit });
         const tx3 = contract.tx.pushZero({ gasLimit });
 
 
         await transaction(tx3, alice);
         await transaction(tx3, alice);
@@ -94,6 +97,7 @@ describe.skip('Deploy store contract and test', () => {
 
 
                 val = val.length == 1 ? "0" + val : val;
                 val = val.length == 1 ? "0" + val : val;
 
 
+                gasLimit = await weight(conn, contract, "push", ["0x" + val]);
                 const tx = contract.tx.push({ gasLimit }, ["0x" + val]);
                 const tx = contract.tx.push({ gasLimit }, ["0x" + val]);
 
 
                 await transaction(tx, alice);
                 await transaction(tx, alice);

+ 21 - 19
integration/substrate/structs.spec.ts

@@ -1,5 +1,5 @@
 import expect from 'expect';
 import expect from 'expect';
-import { gasLimit, createConnection, deploy, transaction, aliceKeypair, } from './index';
+import { createConnection, deploy, transaction, aliceKeypair, weight, query, } from './index';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ContractPromise } from '@polkadot/api-contract';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 
 
@@ -23,11 +23,12 @@ describe('Deploy struct contract and test', () => {
 
 
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
         let contract = new ContractPromise(conn, deployed_contract.abi, deployed_contract.address);
 
 
+        let gasLimit = await weight(conn, contract, "setFoo1");
         const tx1 = contract.tx.setFoo1({ gasLimit });
         const tx1 = contract.tx.setFoo1({ gasLimit });
 
 
         await transaction(tx1, alice);
         await transaction(tx1, alice);
 
 
-        let res1 = await contract.query.getBothFoos(alice.address, {});
+        let res1 = await query(conn, alice, contract, "getBothFoos");
 
 
         expect(res1.output?.toJSON()).toStrictEqual([
         expect(res1.output?.toJSON()).toStrictEqual([
             {
             {
@@ -48,24 +49,23 @@ describe('Deploy struct contract and test', () => {
             }
             }
         ]);
         ]);
 
 
-        const tx2 = contract.tx.setFoo2({ gasLimit },
-            {
-                "f1": "bar2",
-                "f2": "0xb52b073595ccb35eaebb87178227b779",
-                "f3": -123112321,
-                "f4": "0x123456",
-                "f5": "Barking up the wrong tree",
-                "f6": {
-                    "in1": true, "in2": "Drive someone up the wall"
-                }
-            },
-            "nah"
-        );
+        const arg1 = {
+            "f1": "bar2",
+            "f2": "0xb52b073595ccb35eaebb87178227b779",
+            "f3": -123112321,
+            "f4": "0x123456",
+            "f5": "Barking up the wrong tree",
+            "f6": {
+                "in1": true, "in2": "Drive someone up the wall"
+            }
+        };
+        gasLimit = await weight(conn, contract, "setFoo2", [arg1, "nah"]);
+        const tx2 = contract.tx.setFoo2({ gasLimit }, arg1, "nah");
 
 
         await transaction(tx2, alice);
         await transaction(tx2, alice);
 
 
         if (1) {
         if (1) {
-            let res3 = await contract.query.getFoo(alice.address, {}, false);
+            let res3 = await query(conn, alice, contract, "getFoo", [false]);
 
 
             expect(res3.output?.toJSON()).toStrictEqual(
             expect(res3.output?.toJSON()).toStrictEqual(
                 {
                 {
@@ -79,7 +79,7 @@ describe('Deploy struct contract and test', () => {
             );
             );
         }
         }
 
 
-        let res2 = await contract.query.getBothFoos(alice.address, {});
+        let res2 = await query(conn, alice, contract, "getBothFoos");
 
 
         expect(res2.output?.toJSON()).toStrictEqual([
         expect(res2.output?.toJSON()).toStrictEqual([
             {
             {
@@ -100,11 +100,12 @@ describe('Deploy struct contract and test', () => {
             }
             }
         ]);
         ]);
 
 
+        gasLimit = await weight(conn, contract, "deleteFoo", [true]);
         const tx3 = contract.tx.deleteFoo({ gasLimit }, true);
         const tx3 = contract.tx.deleteFoo({ gasLimit }, true);
 
 
         await transaction(tx3, alice);
         await transaction(tx3, alice);
 
 
-        let res3 = await contract.query.getFoo(alice.address, {}, false);
+        let res3 = await query(conn, alice, contract, "getFoo", [false]);
 
 
         expect(res3.output?.toJSON()).toStrictEqual(
         expect(res3.output?.toJSON()).toStrictEqual(
             {
             {
@@ -117,11 +118,12 @@ describe('Deploy struct contract and test', () => {
             },
             },
         );
         );
 
 
+        gasLimit = await weight(conn, contract, "structLiteral");
         const tx4 = contract.tx.structLiteral({ gasLimit });
         const tx4 = contract.tx.structLiteral({ gasLimit });
 
 
         await transaction(tx4, alice);
         await transaction(tx4, alice);
 
 
-        let res4 = await contract.query.getFoo(alice.address, {}, true);
+        let res4 = await query(conn, alice, contract, "getFoo", [true]);
 
 
         expect(res4.output?.toJSON()).toStrictEqual(
         expect(res4.output?.toJSON()).toStrictEqual(
             {
             {

+ 7 - 4
src/linker/wasm.rs

@@ -70,11 +70,14 @@ pub fn link(input: &[u8], name: &str) -> Vec<u8> {
         while ind < imports.len() {
         while ind < imports.len() {
             if imports[ind].field().starts_with("seal") {
             if imports[ind].field().starts_with("seal") {
                 let module_name = match imports[ind].field() {
                 let module_name = match imports[ind].field() {
-                    "seal_instantiate" | "seal_terminate" | "seal_random" | "seal_call" => "seal1",
-                    "seal_set_storage"
-                    | "seal_clear_storage"
+                    "seal_set_storage" => "seal2",
+                    "seal_clear_storage"
                     | "seal_contains_storage"
                     | "seal_contains_storage"
-                    | "seal_get_storage" => "__unstable__",
+                    | "seal_get_storage"
+                    | "seal_instantiate"
+                    | "seal_terminate"
+                    | "seal_random"
+                    | "seal_call" => "seal1",
                     _ => "seal0",
                     _ => "seal0",
                 };
                 };
                 *imports[ind].module_mut() = module_name.to_owned();
                 *imports[ind].module_mut() = module_name.to_owned();

+ 1 - 1
tests/substrate.rs

@@ -948,7 +948,7 @@ impl MockSubstrate {
                 .with_resolver("env", self)
                 .with_resolver("env", self)
                 .with_resolver("seal0", self)
                 .with_resolver("seal0", self)
                 .with_resolver("seal1", self)
                 .with_resolver("seal1", self)
-                .with_resolver("__unstable__", self),
+                .with_resolver("seal2", self),
         )
         )
         .expect("Failed to instantiate module")
         .expect("Failed to instantiate module")
         .run_start(&mut NopExternals)
         .run_start(&mut NopExternals)