@moonsong-labs/moonwall-cli
Version:
Testing framework for the Moon family of projects
118 lines (115 loc) • 3.97 kB
JavaScript
import {
MoonwallContext
} from "./chunk-WICDGWJQ.js";
// src/lib/contextHelpers.ts
import "@moonbeam-network/api-augment";
import {
customWeb3Request,
alith,
createAndFinalizeBlock
} from "@moonsong-labs/moonwall-util";
import { assert } from "vitest";
import Debug from "debug";
var debug = Debug("context");
async function createBlock(w3Api, pjsApi, transactions, options = {}) {
assert(
MoonwallContext.getContext().foundation == "dev",
"createBlock should only be used on DevMode foundations"
);
const results = [];
const txs = transactions == void 0 ? [] : Array.isArray(transactions) ? transactions : [transactions];
for await (const call of txs) {
if (typeof call == "string") {
results.push({
type: "eth",
hash: (await customWeb3Request(w3Api, "eth_sendRawTransaction", [call])).result
});
} else if (call.isSigned) {
const tx = pjsApi.tx(call);
debug(
`- Signed: ${tx.method.section}.${tx.method.method}(${tx.args.map((d) => d.toHuman()).join("; ")}) [ nonce: ${tx.nonce}]`
);
results.push({
type: "sub",
hash: (await call.send()).toString()
});
} else {
const tx = pjsApi.tx(call);
debug(
`- Unsigned: ${tx.method.section}.${tx.method.method}(${tx.args.map((d) => d.toHuman()).join("; ")}) [ nonce: ${tx.nonce}]`
);
results.push({
type: "sub",
hash: (await call.signAndSend(alith)).toString()
});
}
}
const { parentHash, finalize } = options;
const blockResult = await createAndFinalizeBlock(pjsApi, parentHash, finalize);
if (results.length == 0) {
return {
block: blockResult,
result: null
};
}
const allRecords = await (await pjsApi.at(blockResult.hash)).query.system.events();
const blockData = await pjsApi.rpc.chain.getBlock(blockResult.hash);
const result = results.map((result2) => {
const extrinsicIndex = result2.type == "eth" ? allRecords.find(
({ phase, event: { section, method, data } }) => phase.isApplyExtrinsic && section == "ethereum" && method == "Executed" && data[2].toString() == result2.hash
)?.phase?.asApplyExtrinsic?.toNumber() : blockData.block.extrinsics.findIndex((ext) => ext.hash.toHex() == result2.hash);
const events = allRecords.filter(
({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.toNumber() === extrinsicIndex
);
const failure = extractError(events);
return {
extrinsic: extrinsicIndex >= 0 ? blockData.block.extrinsics[extrinsicIndex] : null,
events,
error: failure && (failure.isModule && pjsApi.registry.findMetaError(failure.asModule) || { name: failure.toString() }),
successful: extrinsicIndex !== void 0 && !failure,
hash: result2.hash
};
});
if (results.find((r) => r.type == "eth")) {
await new Promise((resolve) => setTimeout(resolve, 2));
}
return {
block: blockResult,
result: Array.isArray(transactions) ? result : result[0]
};
}
function filterAndApply(events, section, methods, onFound) {
return events.filter(({ event }) => section === event.section && methods.includes(event.method)).map((record) => onFound(record));
}
function getDispatchError({
event: {
data: [dispatchError]
}
}) {
return dispatchError;
}
function getDispatchInfo({ event: { data, method } }) {
return method === "ExtrinsicSuccess" ? data[0] : data[1];
}
function extractError(events = []) {
return filterAndApply(events, "system", ["ExtrinsicFailed"], getDispatchError)[0];
}
function isExtrinsicSuccessful(events = []) {
return filterAndApply(events, "system", ["ExtrinsicSuccess"], () => true).length > 0;
}
function extractInfo(events = []) {
return filterAndApply(
events,
"system",
["ExtrinsicFailed", "ExtrinsicSuccess"],
getDispatchInfo
)[0];
}
export {
createBlock,
filterAndApply,
getDispatchError,
extractError,
isExtrinsicSuccessful,
extractInfo
};