import { run_task, get_runtime_version } from '@acala-network/chopsticks-executor';
import { Binary } from 'polkadot-api';

let nextTaskId = 0;
const runRuntimeCall = async ({
  chain,
  hash,
  call,
  params,
  storageOverrides = {},
  mockSignatureHost = false
}) => {
  const code = chain.getBlock(hash)?.code;
  if (!code) {
    throw new Error(`No runtime code found at block ${hash}`);
  }
  const codeHex = Binary.toHex(code);
  const jsCallback = createJsCallback(chain, hash, storageOverrides);
  const task = {
    id: nextTaskId++,
    wasm: codeHex,
    calls: [[call, [params]]],
    // 0: no mock, 1: require magic signature, 2: always valid
    mockSignatureHost: mockSignatureHost ? 2 : 0,
    allowUnresolvedImports: true,
    runtimeLogLevel: 0,
    storageProofSize: 1e3
  };
  const response = await run_task(task, jsCallback);
  if (response.Error) {
    throw new Error(`Runtime call failed: ${response.Error}`);
  }
  if (!response.Call) {
    throw new Error("Unexpected response format from runtime");
  }
  return response.Call;
};
const getRuntimeVersion = async (code) => {
  const codeHex = Binary.toHex(code);
  const version = await get_runtime_version(codeHex);
  return version;
};
const MIN_PREFIX_LEN = 32 * 2 + 2;
const createJsCallback = (chain, hash, overlay) => {
  return {
    async getStorage(key) {
      if (key in overlay) {
        return overlay[key] ?? void 0;
      }
      const node = await chain.getStorage(hash, key);
      return node.value ? Binary.toHex(node.value) : void 0;
    },
    async getNextKey(prefix, key) {
      prefix = prefix.length < MIN_PREFIX_LEN ? key.slice(0, MIN_PREFIX_LEN) : prefix;
      const descendants = await chain.getStorageDescendants(hash, prefix);
      const allKeys = /* @__PURE__ */ new Set([
        ...Object.keys(descendants),
        ...Object.keys(overlay).filter(
          (k) => k.startsWith(prefix) && overlay[k] !== null
        )
      ]);
      for (const k of Object.keys(overlay)) {
        if (overlay[k] === null) allKeys.delete(k);
      }
      const keys = [...allKeys].sort();
      const idx = keys.findIndex((k) => k > key);
      return idx >= 0 ? keys[idx] : void 0;
    },
    async offchainGetStorage(_key) {
      return void 0;
    },
    async offchainTimestamp() {
      return Date.now();
    },
    async offchainRandomSeed() {
      const bytes = new Uint8Array(32);
      crypto.getRandomValues(bytes);
      return Binary.toHex(bytes);
    },
    async offchainSubmitTransaction(_tx) {
      return false;
    }
  };
};

export { getRuntimeVersion, runRuntimeCall };
//# sourceMappingURL=executor.js.map
