git.delta.rocks / unique-network / refs/commits / d339ca36aeb2

difftreelog

source

tests/src/contracts.test.ts6.3 KiBsourcehistory
1import { expect } from "chai";2import usingApi from "./substrate/substrate-api";3import promisifySubstrate from "./substrate/promisify-substrate";4import fs from "fs";5import privateKey from "./substrate/privateKey";6import { compactAddLength, u8aToU8a } from '@polkadot/util';7import { Hash, AccountId } from "@polkadot/types/interfaces";8import { Abi, PromiseContract } from "@polkadot/api-contract";9import { ISubmittableResult, IKeyringPair } from "@polkadot/types/types";10import BN from "bn.js";11import { alicesPublicKey, bobsPublicKey } from "./accounts";12import { ApiPromise } from "@polkadot/api";13import { GenericAccountId, u128 } from "@polkadot/types";14import getBalance from "./substrate/get-balance";151617function deployContract(api: ApiPromise, contract: Uint8Array, privateKey: IKeyringPair): Promise<Hash> {18  return promisifySubstrate(api, () => {19    return new Promise<Hash>(async (resolve, reject) => {20      const unsubscribe = api.tx.contracts.putCode(contract).signAndSend(privateKey, async result => {21        if(!result.isInBlock){22          return;23        }2425        const record = result.findRecord('contracts', 'CodeStored');2627        if(record) {28          (await unsubscribe)();29          resolve(record.event.data[0] as unknown as Hash);30        } else {31          reject('Failed to find contract hash in putCode transaction result.');32        }33      });34    })35  })();36}3738function instantiateContract(api: ApiPromise, contractHash: Hash, args: Uint8Array, privateKey: IKeyringPair): Promise<AccountId> {39  return promisifySubstrate(api, () => {40    return new Promise<AccountId>((resolve, reject) => {41      const unsubscribe = api.tx.contracts.instantiate(1000000000000000n, 1000000000000n, contractHash, args)42        .signAndSend(privateKey, async (result:ISubmittableResult) => {43          if(!result.isInBlock) {44            return;45          }46          const record = result.findRecord('contracts', 'Instantiated');47          if(record) {48            (await unsubscribe)();49            expect(alicesPublicKey).to.be.equal(record.event.data[0].toString());50            resolve(record.event.data[1] as AccountId);51          } else {52            reject('Failed to find instantiated event.');53          }54        });55    });56  })();57}5859function txContractCall(api: ApiPromise, privateKey: IKeyringPair, address: string, call: Uint8Array): Promise<void> {60  return promisifySubstrate(api, async () => {61    return new Promise<void>(async (resolve, reject) => {62      api.tx.contracts.call(address, 0, 1000000000000n, call)63        .signAndSend(privateKey, async result => {64          if(!result.isInBlock) {65            return;66          }6768          if(result.findRecord('system', 'ExtrinsicSuccess')) {69            resolve();70          }71          else {72            reject('Failed to execute tx call.');73          }74        })75    });76  })();77}7879describe('Contracts', () => {80  it(`Can deploy smart contract Flipper, instantiate it and call it's get and flip messages.`, async () => {81    await usingApi(async api => {82      const wasm = fs.readFileSync('./src/flipper/flipper.wasm');83      const contract = compactAddLength(u8aToU8a(wasm));8485      const metadata = JSON.parse(fs.readFileSync('./src/flipper/metadata.json').toString('utf-8'));86      const abi = new Abi(api.registry as any, metadata);8788      const alicesPrivateKey = privateKey('//Alice');8990      const contractHash = await deployContract(api, contract, alicesPrivateKey);9192      const args = abi.constructors[0](true);93      const instanceAccountId = await instantiateContract(api, contractHash, args, alicesPrivateKey);9495      const contractInstance = new PromiseContract(api, abi, instanceAccountId);96      const getFlipValue = async () => {97        return await promisifySubstrate(api, async () => {98          const result = await contractInstance.call('rpc', 'get', 0, new BN('1000000000000'))99            .send(alicesPublicKey);100          if(!result.isSuccess) {101            throw 'Failed to get flipper value';102          }103          return result.output && result.output.valueOf && result.output.valueOf();104        })();105      }106107      const initialGetResponse = await getFlipValue();108      expect(initialGetResponse).to.be.true;109110      await promisifySubstrate(api, async () => {111        return new Promise<void>(async (resolve, reject) => {112          api.tx.contracts.call(contractInstance.address.toString(), 0, 1000000000000n, contractInstance.getMessage('flip').fn())113            .signAndSend(alicesPrivateKey, async result => {114              if(!result.isInBlock) {115                return;116              }117118              if(result.findRecord('system', 'ExtrinsicSuccess')) {119                resolve();120              }121              else {122                reject('Failed to flip value.');123              }124            })125        });126      })();127128      const afterFlipGetResponse = await getFlipValue();129130      expect(afterFlipGetResponse).to.be.false;131    });132  });133134  it('Can transfer balance using smart contract.', async () => {135    await usingApi(async api => {136      const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);137      const wasm = fs.readFileSync('./src/balance-transfer-contract/calls.wasm');138      const contract = compactAddLength(u8aToU8a(wasm));139140      const metadata = JSON.parse(fs.readFileSync('./src/balance-transfer-contract/metadata.json').toString('utf-8'));141      const abi = new Abi(api.registry as any, metadata);142143      const alicesPrivateKey = privateKey('//Alice');144145      const contractHash = await deployContract(api, contract, alicesPrivateKey);146147      const args = abi.constructors[0]();148      const instanceAccountId = await instantiateContract(api, contractHash, args, alicesPrivateKey);149      const contractInstance = new PromiseContract(api, abi, instanceAccountId);150      const bob = new GenericAccountId(api.registry, bobsPublicKey);151      const call = contractInstance.getMessage('balance_transfer').fn(bob, new u128(api.registry, 1000000));152      await txContractCall(api, alicesPrivateKey, contractInstance.address.toString(), call);153154      const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);155156      expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;157      expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;158    });159  })160});