@acala-network/chopsticks-testing 0.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ import { ApiPromise, WsProvider } from '@polkadot/api';
2
+ import { Codec } from '@polkadot/types/types';
3
+ import { HexString } from '@polkadot/util/types';
4
+ import { Keyring } from '@polkadot/keyring';
5
+ import { StorageValues } from '@acala-network/chopsticks/utils/set-storage';
6
+ import { SubmittableExtrinsic } from '@polkadot/api-base/types';
7
+ export type SetupOption = {
8
+ endpoint: string;
9
+ blockNumber?: number;
10
+ blockHash?: HexString;
11
+ wasmOverride?: string;
12
+ db?: string;
13
+ };
14
+ export declare const setupContext: ({ endpoint, blockNumber, blockHash, wasmOverride, db }: SetupOption) => Promise<{
15
+ chain: import("@acala-network/chopsticks").Blockchain;
16
+ ws: WsProvider;
17
+ api: ApiPromise;
18
+ dev: {
19
+ newBlock: (param?: {
20
+ count?: number;
21
+ to?: number;
22
+ }) => Promise<string>;
23
+ setStorage: (values: StorageValues, blockHash?: string) => Promise<any>;
24
+ timeTravel: (date: string | number) => Promise<number>;
25
+ setHead: (hashOrNumber: string | number) => Promise<any>;
26
+ };
27
+ teardown(): Promise<void>;
28
+ }>;
29
+ type CodecOrArray = Codec | Codec[];
30
+ export declare const expectEvent: (codec: CodecOrArray, event: any) => void;
31
+ export declare const expectHuman: (codec: CodecOrArray) => Vi.Assertion<any>;
32
+ export declare const expectJson: (codec: CodecOrArray) => Vi.Assertion<any>;
33
+ export declare const expectHex: (codec: CodecOrArray) => Vi.Assertion<any>;
34
+ export declare const matchJson: (codec: CodecOrArray) => void;
35
+ export declare const matchHuman: (codec: CodecOrArray) => void;
36
+ type EventFilter = string | {
37
+ method: string;
38
+ section: string;
39
+ };
40
+ export declare const matchEvents: (events: Promise<Codec[] | Codec>, ...filters: EventFilter[]) => Promise<void>;
41
+ export declare const matchSystemEvents: ({ api }: {
42
+ api: ApiPromise;
43
+ }, ...filters: EventFilter[]) => Promise<void>;
44
+ export declare const matchUmp: ({ api }: {
45
+ api: ApiPromise;
46
+ }) => Promise<void>;
47
+ export declare const matchHrmp: ({ api }: {
48
+ api: ApiPromise;
49
+ }) => Promise<void>;
50
+ export declare const redact: (data: any | Promise<any>) => Promise<any>;
51
+ export declare function defer<T>(): {
52
+ resolve: (value: any) => void;
53
+ reject: (reason: any) => void;
54
+ promise: Promise<T>;
55
+ };
56
+ export declare const sendTransaction: (tx: Promise<SubmittableExtrinsic<'promise'>>) => Promise<{
57
+ events: Promise<Codec[]>;
58
+ }>;
59
+ export declare const balance: (api: ApiPromise, address: string) => Promise<Record<string, import("@polkadot/types/types").AnyJson>>;
60
+ export declare const testingPairs: (ss58Format?: number) => {
61
+ alice: import("@polkadot/keyring/types").KeyringPair;
62
+ bob: import("@polkadot/keyring/types").KeyringPair;
63
+ charlie: import("@polkadot/keyring/types").KeyringPair;
64
+ dave: import("@polkadot/keyring/types").KeyringPair;
65
+ eve: import("@polkadot/keyring/types").KeyringPair;
66
+ test1: import("@polkadot/keyring/types").KeyringPair;
67
+ test2: import("@polkadot/keyring/types").KeyringPair;
68
+ keyring: Keyring;
69
+ };
70
+ export {};
package/lib/index.js ADDED
@@ -0,0 +1,193 @@
1
+ import { ApiPromise, WsProvider } from '@polkadot/api';
2
+ import { BuildBlockMode, setupWithServer } from '@acala-network/chopsticks';
3
+ import { Keyring } from '@polkadot/keyring';
4
+ import { expect } from 'vitest';
5
+ export const setupContext = async ({ endpoint, blockNumber, blockHash, wasmOverride, db }) => {
6
+ // random port
7
+ const port = Math.floor(Math.random() * 10000) + 10000;
8
+ const config = {
9
+ endpoint,
10
+ port,
11
+ block: blockNumber || blockHash,
12
+ mockSignatureHost: true,
13
+ 'build-block-mode': BuildBlockMode.Manual,
14
+ db,
15
+ 'wasm-override': wasmOverride,
16
+ };
17
+ const { chain, listenPort, close } = await setupWithServer(config);
18
+ const ws = new WsProvider(`ws://localhost:${listenPort}`);
19
+ const api = await ApiPromise.create({
20
+ provider: ws,
21
+ signedExtensions: {
22
+ SetEvmOrigin: {
23
+ extrinsic: {},
24
+ payload: {},
25
+ },
26
+ },
27
+ });
28
+ await api.isReady;
29
+ return {
30
+ chain,
31
+ ws,
32
+ api,
33
+ dev: {
34
+ newBlock: (param) => {
35
+ return ws.send('dev_newBlock', [param]);
36
+ },
37
+ setStorage: (values, blockHash) => {
38
+ return ws.send('dev_setStorage', [values, blockHash]);
39
+ },
40
+ timeTravel: (date) => {
41
+ return ws.send('dev_timeTravel', [date]);
42
+ },
43
+ setHead: (hashOrNumber) => {
44
+ return ws.send('dev_setHead', [hashOrNumber]);
45
+ },
46
+ },
47
+ async teardown() {
48
+ await api.disconnect();
49
+ await close();
50
+ },
51
+ };
52
+ };
53
+ const processCodecOrArray = (codec, fn) => Array.isArray(codec) ? codec.map(fn) : fn(codec);
54
+ const toHuman = (codec) => processCodecOrArray(codec, (c) => c?.toHuman?.() ?? c);
55
+ const toJson = (codec) => processCodecOrArray(codec, (c) => c?.toJSON?.() ?? c);
56
+ const toHex = (codec) => processCodecOrArray(codec, (c) => c?.toHex?.() ?? c);
57
+ export const expectEvent = (codec, event) => {
58
+ return expect(toHuman(codec)).toEqual(expect.arrayContaining([expect.objectContaining(event)]));
59
+ };
60
+ export const expectHuman = (codec) => {
61
+ return expect(toHuman(codec));
62
+ };
63
+ export const expectJson = (codec) => {
64
+ return expect(toJson(codec));
65
+ };
66
+ export const expectHex = (codec) => {
67
+ return expect(toHex(codec));
68
+ };
69
+ export const matchJson = (codec) => {
70
+ return expect(toJson(codec)).toMatchSnapshot();
71
+ };
72
+ export const matchHuman = (codec) => {
73
+ return expect(toHuman(codec)).toMatchSnapshot();
74
+ };
75
+ const _matchEvents = async (msg, events, ...filters) => {
76
+ let data = toHuman(await events).map(({ event: { index: _, ...event } }) => event);
77
+ if (filters.length > 0) {
78
+ const filtersArr = Array.isArray(filters) ? filters : [filters];
79
+ data = data.filter((evt) => {
80
+ return filtersArr.some((filter) => {
81
+ if (typeof filter === 'string') {
82
+ return evt.section === filter;
83
+ }
84
+ const { section, method } = filter;
85
+ return evt.section === section && evt.method === method;
86
+ });
87
+ });
88
+ }
89
+ return expect(data).toMatchSnapshot(msg);
90
+ };
91
+ export const matchEvents = async (events, ...filters) => {
92
+ return _matchEvents('events', redact(events), ...filters);
93
+ };
94
+ export const matchSystemEvents = async ({ api }, ...filters) => {
95
+ await _matchEvents('system events', redact(api.query.system.events()), ...filters);
96
+ };
97
+ export const matchUmp = async ({ api }) => {
98
+ const ump = await api.query.parachainSystem.upwardMessages();
99
+ const decoded = ump.toJSON().map((msg) => api.createType('XcmVersionedXcm', msg));
100
+ expect(decoded).toMatchSnapshot('ump');
101
+ };
102
+ export const matchHrmp = async ({ api }) => {
103
+ const hrmp = await api.query.parachainSystem.hrmpOutboundMessages();
104
+ const decoded = hrmp.toJSON().map(({ recipient, data }) => ({
105
+ data: api.createType('(XcmpMessageFormat, XcmVersionedXcm)', data),
106
+ recipient,
107
+ }));
108
+ expect(decoded).toMatchSnapshot('hrmp');
109
+ };
110
+ export const redact = async (data) => {
111
+ const json = toHuman(await data);
112
+ const process = (obj) => {
113
+ if (obj == null) {
114
+ return obj;
115
+ }
116
+ if (Array.isArray(obj)) {
117
+ return obj.map(process);
118
+ }
119
+ if (typeof obj === 'number') {
120
+ const rounded = parseFloat(obj.toPrecision(2));
121
+ if (rounded === obj) {
122
+ return rounded;
123
+ }
124
+ return `(rounded ${rounded})`;
125
+ }
126
+ if (typeof obj === 'string') {
127
+ if (obj.match(/0x[0-9a-f]{64}/)) {
128
+ return '(hash)';
129
+ }
130
+ if (obj.match(/^[\d,]+$/)) {
131
+ const num = parseInt(obj.replace(/,/g, ''));
132
+ const rounded = parseFloat(num.toPrecision(2));
133
+ if (rounded === num) {
134
+ return rounded;
135
+ }
136
+ return `(rounded ${rounded})`;
137
+ }
138
+ return obj;
139
+ }
140
+ if (typeof obj === 'object') {
141
+ return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, process(v)]));
142
+ }
143
+ return obj;
144
+ };
145
+ return process(json);
146
+ };
147
+ export function defer() {
148
+ const deferred = {};
149
+ deferred.promise = new Promise((resolve, reject) => {
150
+ deferred.resolve = resolve;
151
+ deferred.reject = reject;
152
+ });
153
+ return deferred;
154
+ }
155
+ export const sendTransaction = async (tx) => {
156
+ const signed = await tx;
157
+ const deferred = defer();
158
+ await signed.send((status) => {
159
+ if (status.isCompleted) {
160
+ deferred.resolve(status.events);
161
+ }
162
+ if (status.isError) {
163
+ deferred.reject(status.status);
164
+ }
165
+ });
166
+ return {
167
+ events: deferred.promise,
168
+ };
169
+ };
170
+ export const balance = async (api, address) => {
171
+ const account = await api.query.system.account(address);
172
+ return account.data.toJSON();
173
+ };
174
+ export const testingPairs = (ss58Format) => {
175
+ const keyring = new Keyring({ type: 'ed25519', ss58Format }); // cannot use sr25519 as it is non determinstic
176
+ const alice = keyring.addFromUri('//Alice');
177
+ const bob = keyring.addFromUri('//Bob');
178
+ const charlie = keyring.addFromUri('//Charlie');
179
+ const dave = keyring.addFromUri('//Dave');
180
+ const eve = keyring.addFromUri('//Eve');
181
+ const test1 = keyring.addFromUri('//test1');
182
+ const test2 = keyring.addFromUri('//test2');
183
+ return {
184
+ alice,
185
+ bob,
186
+ charlie,
187
+ dave,
188
+ eve,
189
+ test1,
190
+ test2,
191
+ keyring,
192
+ };
193
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@acala-network/chopsticks-testing",
3
+ "version": "0.5.10",
4
+ "author": "Bryan Chen <xlchen1291@gmail.com>",
5
+ "license": "Apache-2.0",
6
+ "scripts": {
7
+ "clean": "rm -rf lib tsconfig.tsbuildinfo",
8
+ "build": "tsc -p ./tsconfig.json"
9
+ },
10
+ "dependencies": {
11
+ "@acala-network/chopsticks": "^0.5.10"
12
+ },
13
+ "peerDependencies": {
14
+ "vitest": "^0.29.2"
15
+ },
16
+ "devDependencies": {
17
+ "@types/chai": "^4",
18
+ "typescript": "^4.9.5"
19
+ },
20
+ "files": [
21
+ "lib"
22
+ ],
23
+ "main": "./lib/index.js",
24
+ "types": "./lib/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./lib/index.d.ts",
28
+ "default": "./lib/index.js"
29
+ },
30
+ "./*": {
31
+ "types": "./lib/*.d.ts",
32
+ "default": "./lib/*.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ }
36
+ }