Skip to content

Commit 00536d2

Browse files
Implement sendAndWait to substrate lib at ts e2e-tests
1 parent f6d145d commit 00536d2

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

utils/e2e-tests/ts/lib/substrate.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { ApiPromise, HttpProvider, WsProvider } from "@polkadot/api";
22
import { RunNodeState } from "./node";
33
import { AddCleanup } from "./cleanup";
4+
import { SubmittableExtrinsic } from "@polkadot/api/types/submittable";
5+
import { KeyringPair } from "@polkadot/keyring/types";
6+
import { Callback, ISubmittableResult } from "@polkadot/types/types";
47

58
export type Provider = HttpProvider | WsProvider;
69
export type Api = ApiPromise;
@@ -50,3 +53,95 @@ export const apiFromNodeWebSocket = (
5053
node: RunNodeState,
5154
addCleanup: AddCleanup,
5255
): Promise<Api> => apiWebSocket(node.meta.rpcUrlWs, addCleanup);
56+
57+
class TxFailedError extends Error {
58+
constructor(
59+
readonly extrinsic: SubmittableExtrinsic<"promise">,
60+
readonly result: ISubmittableResult,
61+
) {
62+
let message = `Extrinsic ${extrinsic.method.section}.${extrinsic.method.method} failed`;
63+
64+
if (result.dispatchError) {
65+
message = `${message}: ${JSON.stringify(result.dispatchError.asModule.toHuman())}`;
66+
}
67+
68+
super(message);
69+
70+
// Hide the uselessly long properties from the error inspect printing.
71+
Object.defineProperty(this, "extrinsic", { enumerable: false });
72+
Object.defineProperty(this, "result", { enumerable: false });
73+
}
74+
}
75+
76+
type ExecuteFn<E, R> = (extrinsic: E, cb: Callback<R>) => Promise<() => void>;
77+
78+
const execute = <
79+
E extends SubmittableExtrinsic<"promise">,
80+
R extends ISubmittableResult,
81+
>(
82+
extrinsic: E,
83+
f: ExecuteFn<E, R>,
84+
) =>
85+
new Promise<ISubmittableResult>((resolve, reject) => {
86+
console.log(
87+
`==> ${extrinsic.method.section}.${extrinsic.method.method} / ${extrinsic.hash.toHex()}`,
88+
);
89+
let fired = false;
90+
f(extrinsic, (result) => {
91+
if (fired) return;
92+
93+
const { isCompleted, internalError, events, status, dispatchError } =
94+
result;
95+
96+
if (internalError) {
97+
reject(internalError);
98+
fired = true;
99+
return;
100+
}
101+
102+
if (isCompleted) {
103+
console.log(` Complete!`);
104+
console.log(` Status: ${status.type}`);
105+
console.log(` Error: ${dispatchError ? "yes" : "no"}`);
106+
console.log(` Events:`);
107+
108+
for (const item of events) {
109+
console.log(` ${item.event.section} / ${item.event.method}:`);
110+
console.log(
111+
` ${JSON.stringify(item.event.data.toHuman(), null, 2).replaceAll("\n", "\n ")}\n`,
112+
);
113+
}
114+
115+
console.log(" ... events end\n");
116+
117+
fired = true;
118+
119+
if (dispatchError) {
120+
const error = new TxFailedError(extrinsic, result);
121+
reject(error);
122+
return;
123+
}
124+
125+
resolve(result);
126+
}
127+
}).catch((err: unknown) => {
128+
reject(err as Error);
129+
});
130+
});
131+
132+
export type Params = {
133+
signWith?: KeyringPair;
134+
};
135+
136+
export const sendAndWait = (
137+
extrinsic: SubmittableExtrinsic<"promise">,
138+
params: Params = {},
139+
) => {
140+
const { signWith } = params;
141+
142+
return signWith === undefined
143+
? execute(extrinsic, (extrinsic, cb) => extrinsic.send(cb))
144+
: execute(extrinsic, (extrinsic, cb) =>
145+
extrinsic.signAndSend(signWith, cb),
146+
);
147+
};

0 commit comments

Comments
 (0)