From 3fd1cbdba689c79b3f4a953087799d1d44f8a03f Mon Sep 17 00:00:00 2001 From: sotmorskiy Date: Fri, 11 Sep 2020 07:01:16 +0000 Subject: [PATCH] Connection test now detects disconnection and added transfer test. --- --- a/tests/.vscode/launch.json +++ b/tests/.vscode/launch.json @@ -1,23 +1,42 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Mocha Current File", - "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", - "args": [ - "--timeout", "999999", - "--colors", - "--recursive", - "--require", "ts-node/register", - "./**/*.test.ts" - ], - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen" - } - ] + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Mocha Current File", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "args": [ + "--timeout", + "9999999", + "--colors", + "--recursive", + "--require", + "ts-node/register", + "${file}" + ], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + }, + { + "type": "node", + "request": "launch", + "name": "Mocha All tests", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "args": [ + "--timeout", + "9999999", + "--colors", + "--recursive", + "--require", + "ts-node/register", + "./**/*.test.ts" + ], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + } + ] } \ No newline at end of file --- a/tests/package-lock.json +++ b/tests/package-lock.json @@ -3916,25 +3916,64 @@ } }, "@polkadot/api": { - "version": "1.32.1", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-1.32.1.tgz", - "integrity": "sha512-YwqvD7lmH18xPFggwqpXAQHH0DmwQcePVGLHb5c9JjX9QxYqPS5r+Ed6lFPqTBTTiYhb1ep8QZrY7TrgceP41g==", + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-1.31.2.tgz", + "integrity": "sha512-5nMraRQYFt+xeInQi5i7c00fwOiSeZgU3Y1LJWz+z+Vnxep7xzjVBMLgBi4fe7g2eWKUYB79ApFNV8r2thsQZg==", "requires": { "@babel/runtime": "^7.11.2", - "@polkadot/api-derive": "1.32.1", + "@polkadot/api-derive": "1.31.2", "@polkadot/keyring": "^3.4.1", - "@polkadot/metadata": "1.32.1", - "@polkadot/rpc-core": "1.32.1", - "@polkadot/rpc-provider": "1.32.1", - "@polkadot/types": "1.32.1", - "@polkadot/types-known": "1.32.1", + "@polkadot/metadata": "1.31.2", + "@polkadot/rpc-core": "1.31.2", + "@polkadot/rpc-provider": "1.31.2", + "@polkadot/types": "1.31.2", + "@polkadot/types-known": "1.31.2", "@polkadot/util": "^3.4.1", "@polkadot/util-crypto": "^3.4.1", "bn.js": "^5.1.3", - "eventemitter3": "^4.0.7", + "eventemitter3": "^4.0.6", "rxjs": "^6.6.2" }, "dependencies": { + "@polkadot/metadata": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/metadata/-/metadata-1.31.2.tgz", + "integrity": "sha512-UAcZLxh6QFwhF2Ccmax6LUYa99NntBZrAe8oUN92UJlHbtAutd5sq322P+liG2EHfyhUZs5T5v8jLD79pMTjdA==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/types-known": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "bn.js": "^5.1.3" + } + }, + "@polkadot/types": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-1.31.2.tgz", + "integrity": "sha512-eJsWdMzBlkYYrowR7tl9LYvGW3Za05esDQPxPxc1z2kkwzU2IoX2qijhUb6J9ViESY/h0jWFyEbV/1mBn4uupg==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/metadata": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "@types/bn.js": "^4.11.6", + "bn.js": "^5.1.3", + "memoizee": "^0.4.14", + "rxjs": "^6.6.2" + } + }, + "@polkadot/types-known": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-1.31.2.tgz", + "integrity": "sha512-sA9IEwYNCsN+Z4eZklxOluJA5OBN2eGNvLz0uUQ6TFvqbi9Z8Mba+h+RZU1iFO6+yq2U7ECvdWzET6RN7zv+oQ==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/util": "^3.4.1", + "bn.js": "^5.1.3" + } + }, "@polkadot/util": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-3.4.1.tgz", @@ -3951,15 +3990,15 @@ } }, "@polkadot/api-derive": { - "version": "1.32.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-1.32.1.tgz", - "integrity": "sha512-i7kz2v8tHRl9RHKzvwc8OwjRyZVCwiP40CEpq0ZIgSl4wl2MpWcSMLrhbZdvRtBiVIfaogNb6esAZ1AFrtSDMQ==", + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-1.31.2.tgz", + "integrity": "sha512-j33elEBZpY7/ucsBRYdUxeWHID8vlvPKm7k9dWgaH8txYuzms0SFfkMHyECgo15SL+RTNhu/VxzSRWryk6dvTA==", "requires": { "@babel/runtime": "^7.11.2", - "@polkadot/api": "1.32.1", - "@polkadot/rpc-core": "1.32.1", - "@polkadot/rpc-provider": "1.32.1", - "@polkadot/types": "1.32.1", + "@polkadot/api": "1.31.2", + "@polkadot/rpc-core": "1.31.2", + "@polkadot/rpc-provider": "1.31.2", + "@polkadot/types": "1.31.2", "@polkadot/util": "^3.4.1", "@polkadot/util-crypto": "^3.4.1", "bn.js": "^5.1.3", @@ -3967,6 +4006,45 @@ "rxjs": "^6.6.2" }, "dependencies": { + "@polkadot/metadata": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/metadata/-/metadata-1.31.2.tgz", + "integrity": "sha512-UAcZLxh6QFwhF2Ccmax6LUYa99NntBZrAe8oUN92UJlHbtAutd5sq322P+liG2EHfyhUZs5T5v8jLD79pMTjdA==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/types-known": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "bn.js": "^5.1.3" + } + }, + "@polkadot/types": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-1.31.2.tgz", + "integrity": "sha512-eJsWdMzBlkYYrowR7tl9LYvGW3Za05esDQPxPxc1z2kkwzU2IoX2qijhUb6J9ViESY/h0jWFyEbV/1mBn4uupg==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/metadata": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "@types/bn.js": "^4.11.6", + "bn.js": "^5.1.3", + "memoizee": "^0.4.14", + "rxjs": "^6.6.2" + } + }, + "@polkadot/types-known": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-1.31.2.tgz", + "integrity": "sha512-sA9IEwYNCsN+Z4eZklxOluJA5OBN2eGNvLz0uUQ6TFvqbi9Z8Mba+h+RZU1iFO6+yq2U7ECvdWzET6RN7zv+oQ==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/util": "^3.4.1", + "bn.js": "^5.1.3" + } + }, "@polkadot/util": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-3.4.1.tgz", @@ -4117,19 +4195,58 @@ } }, "@polkadot/rpc-core": { - "version": "1.32.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-1.32.1.tgz", - "integrity": "sha512-pre6aUVCQZqsoffGewyFzjM3MQ+kPn18n2L+B9EKqVBBd3+9v05X6aNmbm1aXb6laa0DzcuxO3EQmOT21CdbNQ==", + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-1.31.2.tgz", + "integrity": "sha512-amFN0UtxB94TnXVuL9oBSQDFheCrxUN6C/lmVlOBqnWj6ZA1RDAuPPJBNIjhSxNlGmJxS2yIexaCVKgF8kS8Cg==", "requires": { "@babel/runtime": "^7.11.2", - "@polkadot/metadata": "1.32.1", - "@polkadot/rpc-provider": "1.32.1", - "@polkadot/types": "1.32.1", + "@polkadot/metadata": "1.31.2", + "@polkadot/rpc-provider": "1.31.2", + "@polkadot/types": "1.31.2", "@polkadot/util": "^3.4.1", "memoizee": "^0.4.14", "rxjs": "^6.6.2" }, "dependencies": { + "@polkadot/metadata": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/metadata/-/metadata-1.31.2.tgz", + "integrity": "sha512-UAcZLxh6QFwhF2Ccmax6LUYa99NntBZrAe8oUN92UJlHbtAutd5sq322P+liG2EHfyhUZs5T5v8jLD79pMTjdA==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/types-known": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "bn.js": "^5.1.3" + } + }, + "@polkadot/types": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-1.31.2.tgz", + "integrity": "sha512-eJsWdMzBlkYYrowR7tl9LYvGW3Za05esDQPxPxc1z2kkwzU2IoX2qijhUb6J9ViESY/h0jWFyEbV/1mBn4uupg==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/metadata": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "@types/bn.js": "^4.11.6", + "bn.js": "^5.1.3", + "memoizee": "^0.4.14", + "rxjs": "^6.6.2" + } + }, + "@polkadot/types-known": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-1.31.2.tgz", + "integrity": "sha512-sA9IEwYNCsN+Z4eZklxOluJA5OBN2eGNvLz0uUQ6TFvqbi9Z8Mba+h+RZU1iFO6+yq2U7ECvdWzET6RN7zv+oQ==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/util": "^3.4.1", + "bn.js": "^5.1.3" + } + }, "@polkadot/util": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-3.4.1.tgz", @@ -4146,21 +4263,60 @@ } }, "@polkadot/rpc-provider": { - "version": "1.32.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-1.32.1.tgz", - "integrity": "sha512-m3Vk7somPLrAfNM/z24XFQUD7lYrOZxa647uaCSGqGUNsszrcotBDBU3bE6WL5qOaR3EpLXs0Lhq6RpgowOqJg==", + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-1.31.2.tgz", + "integrity": "sha512-vqS1lsk/BBGSuklGKJhJxduKXOyXjc/kZzPWmmH8B92Zh59LqlzoJ8a4gQIjDr0CFjeJZbaaL1yRhE6qwaEe2A==", "requires": { "@babel/runtime": "^7.11.2", - "@polkadot/metadata": "1.32.1", - "@polkadot/types": "1.32.1", + "@polkadot/metadata": "1.31.2", + "@polkadot/types": "1.31.2", "@polkadot/util": "^3.4.1", "@polkadot/util-crypto": "^3.4.1", "bn.js": "^5.1.3", - "eventemitter3": "^4.0.7", + "eventemitter3": "^4.0.6", "isomorphic-fetch": "^2.2.1", - "websocket": "^1.0.32" + "websocket": "^1.0.31" }, "dependencies": { + "@polkadot/metadata": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/metadata/-/metadata-1.31.2.tgz", + "integrity": "sha512-UAcZLxh6QFwhF2Ccmax6LUYa99NntBZrAe8oUN92UJlHbtAutd5sq322P+liG2EHfyhUZs5T5v8jLD79pMTjdA==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/types-known": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "bn.js": "^5.1.3" + } + }, + "@polkadot/types": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-1.31.2.tgz", + "integrity": "sha512-eJsWdMzBlkYYrowR7tl9LYvGW3Za05esDQPxPxc1z2kkwzU2IoX2qijhUb6J9ViESY/h0jWFyEbV/1mBn4uupg==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/metadata": "1.31.2", + "@polkadot/util": "^3.4.1", + "@polkadot/util-crypto": "^3.4.1", + "@types/bn.js": "^4.11.6", + "bn.js": "^5.1.3", + "memoizee": "^0.4.14", + "rxjs": "^6.6.2" + } + }, + "@polkadot/types-known": { + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-1.31.2.tgz", + "integrity": "sha512-sA9IEwYNCsN+Z4eZklxOluJA5OBN2eGNvLz0uUQ6TFvqbi9Z8Mba+h+RZU1iFO6+yq2U7ECvdWzET6RN7zv+oQ==", + "requires": { + "@babel/runtime": "^7.11.2", + "@polkadot/types": "1.31.2", + "@polkadot/util": "^3.4.1", + "bn.js": "^5.1.3" + } + }, "@polkadot/util": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-3.4.1.tgz", --- a/tests/package.json +++ b/tests/package.json @@ -16,7 +16,7 @@ "typescript": "^3.9.7" }, "scripts": { - "test": "mocha -r ts-node/register ./**/*.test.ts" + "test": "mocha --timeout 9999999 -r ts-node/register ./**/*.test.ts" }, "author": "", "license": "Apache 2.0", --- a/tests/src/config.ts +++ b/tests/src/config.ts @@ -1,7 +1,71 @@ import process from 'process'; const config = { - substrateUrl: process.env.substrateUrl || 'ws://127.0.0.1:9944' + substrateUrl: process.env.substrateUrl || 'ws://127.0.0.1:9944', + customTypes: process.env.customTypes || `{ + "Schedule": { + "version": "u32", + "put_code_per_byte_cost": "Gas", + "grow_mem_cost": "Gas", + "regular_op_cost": "Gas", + "return_data_per_byte_cost": "Gas", + "event_data_per_byte_cost": "Gas", + "event_per_topic_cost": "Gas", + "event_base_cost": "Gas", + "call_base_cost": "Gas", + "instantiate_base_cost": "Gas", + "dispatch_base_cost": "Gas", + "sandbox_data_read_cost": "Gas", + "sandbox_data_write_cost": "Gas", + "transfer_cost": "Gas", + "instantiate_cost": "Gas", + "max_event_topics": "u32", + "max_stack_height": "u32", + "max_memory_pages": "u32", + "max_table_size": "u32", + "enable_println": "bool", + "max_subject_len": "u32" + }, + "CollectionMode": { + "_enum": { + "Invalid": null, + "NFT": "u32", + "Fungible": "u32", + "ReFungible": "(u32, u32)" + } + }, + "NftItemType": { + "Collection": "u64", + "Owner": "AccountId", + "Data": "Vec" + }, + "Ownership": { + "owner": "AccountId", + "fraction": "u128" + }, + "ReFungibleItemType": { + "Collection": "u64", + "Owner": "Vec>", + "Data": "Vec" + }, + "CollectionType": { + "Owner": "AccountId", + "Mode": "CollectionMode", + "Access": "u8", + "DecimalPoints": "u32", + "Name": "Vec", + "Description": "Vec", + "TokenPrefix": "Vec", + "CustomDataSize": "u32", + "OffchainSchema": "Vec", + "Sponsor": "AccountId", + "UnconfirmedSponsor": "AccountId" + }, + "RawData": "Vec", + "Address": "AccountId", + "LookupSource": "AccountId", + "Weight": "u64" + }` } export default config; \ No newline at end of file --- a/tests/src/connection.test.ts +++ b/tests/src/connection.test.ts @@ -1,10 +1,11 @@ -import createSubstrateApi from "./substrate-api"; import {expect} from 'chai'; +import usingApi from "./substrate/substrate-api"; describe('Connection', () => { it('Connection can be established', async () => { - const api = await createSubstrateApi(); - const health = await api.rpc.system.health(); - expect(health).to.be.not.empty; + await usingApi(async api => { + const health = await api.rpc.system.health(); + expect(health).to.be.not.empty; + }); }); }); \ No newline at end of file --- a/tests/src/substrate-api.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { WsProvider, ApiPromise } from "@polkadot/api"; -import config from "./config"; - -const wsProvider = new WsProvider(config.substrateUrl); -const settings = { provider: wsProvider }; - - -export default function createSubstrateApi(): Promise { - return new ApiPromise(settings).isReady; -} \ No newline at end of file --- /dev/null +++ b/tests/src/substrate/promisify-substrate.ts @@ -0,0 +1,32 @@ +import ApiPromise from "@polkadot/api/promise/Api"; + +type PromiseType = T extends PromiseLike ? TInner : T; + +export default function promisifySubstrate any>(api: ApiPromise, action: T): (...args: Parameters) => Promise>> { + return (...args: Parameters) => { + const promise = new Promise>>((resolve, reject) => { + const cleanup = () => { + api.off('disconnected', fail); + api.off('error', fail); + }; + + const success = (r: any) => { + cleanup(); + resolve(r); + }; + const fail = (error: any) => { + cleanup(); + reject(error); + }; + + api.on('disconnected', fail); + api.on('error', fail); + + const result = action(...args); + Promise.resolve(result) + .then(success, fail); + + }); + return promise as any; + }; +} --- /dev/null +++ b/tests/src/substrate/substrate-api.ts @@ -0,0 +1,18 @@ +import { WsProvider, ApiPromise } from "@polkadot/api"; +import config from "../config"; +import promisifySubstrate from "./promisify-substrate"; +import { ApiOptions } from "@polkadot/api/types"; + +export default async function usingApi(action: (api: ApiPromise) => Promise): Promise { + const wsProvider = new WsProvider(config.substrateUrl); + const settings: ApiOptions = { provider: wsProvider, types: JSON.parse(config.customTypes) }; + let api: ApiPromise | undefined = undefined; + + try { + api = await ApiPromise.create(settings); + await promisifySubstrate(api, () => api && api.isReady)(); + await action(api); + } finally { + api && api.disconnect(); + } +} \ No newline at end of file --- /dev/null +++ b/tests/src/substrate/wait-new-blocks.ts @@ -0,0 +1,17 @@ +import { ApiPromise } from "@polkadot/api"; + +export default function waitNewBlocks(api: ApiPromise, blocksCount: number = 1): Promise { + const promise = new Promise(async (resolve, reject) => { + + const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => { + if(blocksCount > 0) { + blocksCount--; + }else { + unsubscribe(); + resolve(); + } + }); + }); + + return promise; +} \ No newline at end of file --- /dev/null +++ b/tests/src/transfer.test.ts @@ -0,0 +1,38 @@ +import createSubstrateApi from "./substrate/substrate-api"; +import { Keyring, ApiPromise } from "@polkadot/api"; +import {AccountInfo} from "@polkadot/types/interfaces/system"; +import { expect } from "chai"; +import usingApi from "./substrate/substrate-api"; +import promisifySubstrate from "./substrate/promisify-substrate"; +import waitNewBlocks from "./substrate/wait-new-blocks"; + +async function getBalance(api: ApiPromise, accounts: string[]): Promise { + const balance = promisifySubstrate(api, (accounts: string[]) => api.query.system.account.multi(accounts)); + const responce = await balance(accounts) as unknown as AccountInfo[]; + return responce.map(r => r.data.free.toBigInt().valueOf()); +} + +describe('Transfer', () => { + it('Balance transfers', async () => { + const bobsPublicKey = '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty'; + const alicesPublicKey = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; + await usingApi(async api => { + const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); + + const keyring = new Keyring({ type: 'sr25519' }); + + const alicePrivateKey = keyring.addFromUri('//Alice'); + + const transfer = api.tx.balances.transfer(bobsPublicKey, 1n); + + const hash = await transfer.signAndSend(alicePrivateKey); + + await waitNewBlocks(api); + + const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); + + expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true; + expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true; + }); + }); +}); --- a/tests/tsconfig.json +++ b/tests/tsconfig.json @@ -5,7 +5,7 @@ "**/node_modules/**/*" ], "compilerOptions": { - "target": "es6", + "target": "ES2020", "moduleResolution": "node", "esModuleInterop": true, "resolveJsonModule": true, @@ -18,5 +18,5 @@ "include": [ "src/**/*" ], - "lib": ["es2015"] + "lib": ["es2017"] } -- gitstuff