UNPKG

@mavrykdynamics/taquito-local-forging

Version:

Provide local forging functionality to be with taquito

1,667 lines 65 kB
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@mavrykdynamics/taquito-utils'), require('@mavrykdynamics/taquito-core'), require('bignumber.js')) :
  typeof define === 'function' && define.amd ? define(['exports', '@mavrykdynamics/taquito-utils', '@mavrykdynamics/taquito-core', 'bignumber.js'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.taquitoLocalForging = {}, global.taquitoUtils, global.taquitoCore, global.BigNumber));
})(this, (function (exports, taquitoUtils, taquitoCore, BigNumber) { 'use strict';

  const toHexString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
  const pad = (num, paddingLen = 8) => {
      return num.toString(16).padStart(paddingLen, '0');
  };

  /*
   * Some code in this file is originally from sotez
   * Copyright (c) 2018 Andrew Kishino
   */
  // See: https://protocol.mavryk.org/protocols/005_babylon.html#transactions-now-have-an-entrypoint
  const ENTRYPOINT_MAX_LENGTH = 31;
  exports.CODEC = void 0;
  (function (CODEC) {
      CODEC["SECRET"] = "secret";
      CODEC["RAW"] = "raw";
      CODEC["MV1"] = "mv1";
      CODEC["BRANCH"] = "branch";
      CODEC["ZARITH"] = "zarith";
      CODEC["PUBLIC_KEY"] = "public_key";
      CODEC["PKH"] = "pkh";
      CODEC["PKH_ARR"] = "pkhArr";
      CODEC["DELEGATE"] = "delegate";
      CODEC["SCRIPT"] = "script";
      CODEC["BALLOT_STATEMENT"] = "ballotStmt";
      CODEC["PROPOSAL"] = "proposal";
      CODEC["PROPOSAL_ARR"] = "proposalArr";
      CODEC["INT32"] = "int32";
      CODEC["INT16"] = "int16";
      CODEC["PARAMETERS"] = "parameters";
      CODEC["ADDRESS"] = "address";
      CODEC["SMART_CONTRACT_ADDRESS"] = "smart_contract_address";
      CODEC["SMART_ROLLUP_ADDRESS"] = "smart_rollup_address";
      CODEC["SMART_ROLLUP_COMMITMENT_HASH"] = "smart_rollup_commitment_hash";
      CODEC["VALUE"] = "value";
      CODEC["PADDED_BYTES"] = "padded_bytes";
      CODEC["SMART_ROLLUP_MESSAGE"] = "smart_rollup_message";
      CODEC["MANAGER"] = "manager";
      CODEC["BLOCK_PAYLOAD_HASH"] = "blockPayloadHash";
      CODEC["ENTRYPOINT"] = "entrypoint";
      CODEC["OPERATION"] = "operation";
      CODEC["OP_ACTIVATE_ACCOUNT"] = "activate_account";
      CODEC["OP_DELEGATION"] = "delegation";
      CODEC["OP_TRANSACTION"] = "transaction";
      CODEC["OP_ORIGINATION"] = "origination";
      CODEC["OP_BALLOT"] = "ballot";
      CODEC["OP_FAILING_NOOP"] = "failing_noop";
      CODEC["OP_ATTESTATION"] = "attestation";
      CODEC["OP_ATTESTATION_WITH_DAL"] = "attestation_with_dal";
      CODEC["OP_SEED_NONCE_REVELATION"] = "seed_nonce_revelation";
      CODEC["OP_REVEAL"] = "reveal";
      CODEC["OP_PROPOSALS"] = "proposals";
      CODEC["OP_REGISTER_GLOBAL_CONSTANT"] = "register_global_constant";
      CODEC["OP_TRANSFER_TICKET"] = "transfer_ticket";
      CODEC["BURN_LIMIT"] = "burn_limit";
      CODEC["OP_INCREASE_PAID_STORAGE"] = "increase_paid_storage";
      CODEC["OP_UPDATE_CONSENSUS_KEY"] = "update_consensus_key";
      CODEC["OP_DRAIN_DELEGATE"] = "drain_delegate";
      CODEC["DEPOSITS_LIMIT"] = "deposits_limit";
      CODEC["OP_SET_DEPOSITS_LIMIT"] = "set_deposits_limit";
      CODEC["OP_SMART_ROLLUP_ORIGINATE"] = "smart_rollup_originate";
      CODEC["PVM_KIND"] = "pvm_kind";
      CODEC["OP_SMART_ROLLUP_ADD_MESSAGES"] = "smart_rollup_add_messages";
      CODEC["OP_SMART_ROLLUP_EXECUTE_OUTBOX_MESSAGE"] = "smart_rollup_execute_outbox_message";
      CODEC["OP_DAL_PUBLISH_COMMITMENT"] = "dal_publish_commitment";
      CODEC["SLOT_HEADER"] = "slot_header";
  })(exports.CODEC || (exports.CODEC = {}));
  // See https://protocol.mavryk.org/shell/p2p_api.html#alpha-michelson-v1-primitives-enumeration-unsigned-8-bit-integer
  const opMapping = {
      '00': 'parameter',
      '01': 'storage',
      '02': 'code',
      '03': 'False',
      '04': 'Elt',
      '05': 'Left',
      '06': 'None',
      '07': 'Pair',
      '08': 'Right',
      '09': 'Some',
      '0a': 'True',
      '0b': 'Unit',
      '0c': 'PACK',
      '0d': 'UNPACK',
      '0e': 'BLAKE2B',
      '0f': 'SHA256',
      '10': 'SHA512',
      '11': 'ABS',
      '12': 'ADD',
      '13': 'AMOUNT',
      '14': 'AND',
      '15': 'BALANCE',
      '16': 'CAR',
      '17': 'CDR',
      '18': 'CHECK_SIGNATURE',
      '19': 'COMPARE',
      '1a': 'CONCAT',
      '1b': 'CONS',
      '1c': 'CREATE_ACCOUNT',
      '1d': 'CREATE_CONTRACT',
      '1e': 'IMPLICIT_ACCOUNT',
      '1f': 'DIP',
      '20': 'DROP',
      '21': 'DUP',
      '22': 'EDIV',
      '23': 'EMPTY_MAP',
      '24': 'EMPTY_SET',
      '25': 'EQ',
      '26': 'EXEC',
      '27': 'FAILWITH',
      '28': 'GE',
      '29': 'GET',
      '2a': 'GT',
      '2b': 'HASH_KEY',
      '2c': 'IF',
      '2d': 'IF_CONS',
      '2e': 'IF_LEFT',
      '2f': 'IF_NONE',
      '30': 'INT',
      '31': 'LAMBDA',
      '32': 'LE',
      '33': 'LEFT',
      '34': 'LOOP',
      '35': 'LSL',
      '36': 'LSR',
      '37': 'LT',
      '38': 'MAP',
      '39': 'MEM',
      '3a': 'MUL',
      '3b': 'NEG',
      '3c': 'NEQ',
      '3d': 'NIL',
      '3e': 'NONE',
      '3f': 'NOT',
      '40': 'NOW',
      '41': 'OR',
      '42': 'PAIR',
      '43': 'PUSH',
      '44': 'RIGHT',
      '45': 'SIZE',
      '46': 'SOME',
      '47': 'SOURCE',
      '48': 'SENDER',
      '49': 'SELF',
      '4a': 'STEPS_TO_QUOTA',
      '4b': 'SUB',
      '4c': 'SWAP',
      '4d': 'TRANSFER_TOKENS',
      '4e': 'SET_DELEGATE',
      '4f': 'UNIT',
      '50': 'UPDATE',
      '51': 'XOR',
      '52': 'ITER',
      '53': 'LOOP_LEFT',
      '54': 'ADDRESS',
      '55': 'CONTRACT',
      '56': 'ISNAT',
      '57': 'CAST',
      '58': 'RENAME',
      '59': 'bool',
      '5a': 'contract',
      '5b': 'int',
      '5c': 'key',
      '5d': 'key_hash',
      '5e': 'lambda',
      '5f': 'list',
      '60': 'map',
      '61': 'big_map',
      '62': 'nat',
      '63': 'option',
      '64': 'or',
      '65': 'pair',
      '66': 'set',
      '67': 'signature',
      '68': 'string',
      '69': 'bytes',
      '6a': 'mumav',
      '6b': 'timestamp',
      '6c': 'unit',
      '6d': 'operation',
      '6e': 'address',
      '6f': 'SLICE',
      '70': 'DIG',
      '71': 'DUG',
      '72': 'EMPTY_BIG_MAP',
      '73': 'APPLY',
      '74': 'chain_id',
      '75': 'CHAIN_ID',
      '76': 'LEVEL',
      '77': 'SELF_ADDRESS',
      '78': 'never',
      '79': 'NEVER',
      '7a': 'UNPAIR',
      '7b': 'VOTING_POWER',
      '7c': 'TOTAL_VOTING_POWER',
      '7d': 'KECCAK',
      '7e': 'SHA3',
      '7f': 'PAIRING_CHECK',
      '80': 'bls12_381_g1',
      '81': 'bls12_381_g2',
      '82': 'bls12_381_fr',
      '83': 'sapling_state',
      '84': 'sapling_transaction_deprecated',
      '85': 'SAPLING_EMPTY_STATE',
      '86': 'SAPLING_VERIFY_UPDATE',
      '87': 'ticket',
      '88': 'TICKET_DEPRECATED',
      '89': 'READ_TICKET',
      '8a': 'SPLIT_TICKET',
      '8b': 'JOIN_TICKETS',
      '8c': 'GET_AND_UPDATE',
      '8d': 'chest',
      '8e': 'chest_key',
      '8f': 'OPEN_CHEST',
      '90': 'VIEW',
      '91': 'view',
      '92': 'constant',
      '93': 'SUB_MUMAV',
      '94': 'tx_rollup_l2_address',
      '95': 'MIN_BLOCK_TIME',
      '96': 'sapling_transaction',
      '97': 'EMIT',
      '98': 'Lambda_rec',
      '99': 'LAMBDA_REC',
      '9a': 'TICKET',
      '9b': 'BYTES',
      '9c': 'NAT',
      '9d': 'Ticket',
  };
  const opMappingReverse = (() => {
      const result = {};
      Object.keys(opMapping).forEach((key) => {
          result[opMapping[key]] = key;
      });
      return result;
  })();
  // See https://protocol.mavryk.org/shell/p2p_api.html
  const kindMapping = {
      0x04: 'activate_account',
      0x6b: 'reveal',
      0x6e: 'delegation',
      0x6c: 'transaction',
      0x6d: 'origination',
      0x06: 'ballot',
      0x15: 'attestation',
      0x17: 'attestation_with_dal',
      0x01: 'seed_nonce_revelation',
      0x05: 'proposals',
      0x6f: 'register_global_constant',
      0x9e: 'transfer_ticket',
      0x70: 'set_deposits_limit',
      0x71: 'increase_paid_storage',
      0x72: 'update_consensus_key',
      0x09: 'drain_delegate',
      0xc8: 'smart_rollup_originate',
      0xc9: 'smart_rollup_add_messages',
      0xce: 'smart_rollup_execute_outbox_message',
      0xe6: 'dal_publish_commitment',
      0x11: 'failing_noop',
  };
  const kindMappingReverse = (() => {
      const result = {};
      Object.keys(kindMapping).forEach((key) => {
          const keyNum = typeof key === 'string' ? parseInt(key, 10) : key;
          result[kindMapping[keyNum]] = pad(keyNum, 2);
      });
      return result;
  })();
  // See https://protocol.mavryk.org/protocols/005_babylon.html#transactions-now-have-an-entrypoint
  const entrypointMapping = {
      '00': 'default',
      '01': 'root',
      '02': 'do',
      '03': 'set_delegate',
      '04': 'remove_delegate',
      '05': 'deposit',
      '06': 'stake',
      '07': 'unstake',
      '08': 'finalize_unstake',
      '09': 'set_delegate_parameters',
  };
  const entrypointMappingReverse = (() => {
      const result = {};
      Object.keys(entrypointMapping).forEach((key) => {
          result[entrypointMapping[key]] = key;
      });
      return result;
  })();

  /**
   *  @category Error
   *  @description Error that indicates an invalid operation content being passed or used
   */ class InvalidOperationSchemaError extends taquitoCore.ParameterValidationError {
      constructor(operation, errorDetail) {
          super();
          this.operation = operation;
          this.errorDetail = errorDetail;
          this.name = 'InvalidOperationSchemaError';
          this.message = `Invalid operation content recevied`;
          errorDetail ? (this.message += ` ${errorDetail}.`) : '';
      }
  }
  /**
   *  @category Error
   *  @description Error that indicates an entrypoint name exceeding maximum length
   */
  class OversizedEntryPointError extends taquitoCore.ParameterValidationError {
      constructor(entrypoint) {
          super();
          this.entrypoint = entrypoint;
          this.name = 'OversizedEntryPointError';
          this.message = `Invalid entrypoint length "${entrypoint.length}", maximum length is "${ENTRYPOINT_MAX_LENGTH}".`;
      }
  }
  /**
   *  @category Error
   *  @description Error that indicates an invalid ballot value being used
   */
  class InvalidBallotValueError extends taquitoCore.ParameterValidationError {
      constructor(ballotValue) {
          super();
          this.ballotValue = ballotValue;
          this.name = 'InvalidBallotValueError';
          this.message = `Invalid ballot value "${ballotValue}" expecting one of the following: "yay", "nay", "pass".`;
      }
  }
  /**
   *  @category Error
   *  @description Error that indicates a failure when trying to decode ballot value
   */
  class DecodeBallotValueError extends taquitoCore.ParameterValidationError {
      constructor(ballotValue) {
          super();
          this.ballotValue = ballotValue;
          this.name = 'DecodeBallotValueError';
          this.message = `Invalid ballot value "${ballotValue}", cannot be decoded.`;
      }
  }
  /**
   *  @category Error
   *  @description Error that indicates unexpected Michelson Value being passed or used
   */
  class UnexpectedMichelsonValueError extends taquitoCore.ParameterValidationError {
      constructor(value) {
          super();
          this.value = value;
          this.name = 'UnexpectedMichelsonValueError';
          this.message = `Invalid Michelson value "${value}", unalbe to encode.`;
      }
  }
  /**
   *  @category Error
   *  @description Error that indicates a failure when trying to decode an operation
   */
  class OperationDecodingError extends taquitoCore.ParameterValidationError {
      constructor(message) {
          super();
          this.message = message;
          this.name = 'OperationDecodingError';
      }
  }
  /**
   *  @category Error
   *  @description Error that indicates a failure when trying to encode an operation
   */
  class OperationEncodingError extends taquitoCore.ParameterValidationError {
      constructor(message) {
          super();
          this.message = message;
          this.name = 'OperationEncodingError';
      }
  }
  /**
   *  @category Error
   *  @description Error that indicates an unsupported operation being passed or used
   */
  class UnsupportedOperationError extends taquitoCore.ParameterValidationError {
      constructor(op) {
          super();
          this.op = op;
          this.name = 'UnsupportedOperationError';
          this.message = `Unsupported operation "${op}", can submit an issue on our github for feature request.`;
      }
  }
  /**
   * @cateogry Error
   * @description Error that indicates an unsupported pvm being passed or used
   */
  class UnsupportedPvmKindError extends taquitoCore.ParameterValidationError {
      constructor(pvm) {
          super();
          this.pvm = pvm;
          this.name = 'UnsupportedPvmKindError';
          this.message = `Invalid Pvm kind "${pvm}" expecting either "arith" or "wasm_2_0_0".`;
      }
  }
  /**
   * @category Error
   * @description Error that indicates an unsupported pvm to decode
   */
  class DecodePvmKindError extends taquitoCore.ParameterValidationError {
      constructor(pvm) {
          super();
          this.pvm = pvm;
          this.name = 'DecodePvmKindError';
          this.message = `Invalid Pvm kind "${pvm}", cannot be decoded.`;
      }
  }
  /**
   * @category Error
   * @description Error that indicates an invalid Smart Rollup Address (sr1)
   */
  class InvalidSmartRollupAddressError extends taquitoCore.ParameterValidationError {
      constructor(address, errorDetail) {
          super();
          this.address = address;
          this.errorDetail = errorDetail;
          this.name = 'InvalidSmartRollupAddress';
          this.message = `Invalid smart rollup address "${address}"`;
          errorDetail ? (this.message += ` ${errorDetail}.`) : '';
      }
  }
  /**
   * @category Error
   * @description Error that indicates an invalid Smart Rollup commitment hash (src1)
   */
  class InvalidSmartRollupCommitmentHashError extends taquitoCore.ParameterValidationError {
      constructor(hash, errorDetail) {
          super();
          this.hash = hash;
          this.errorDetail = errorDetail;
          this.name = 'InvalidSmartRollupCommitmentHashError';
          this.message = `Invalid smart rollup commitment hash "${hash}"`;
          errorDetail ? (this.message += ` ${errorDetail}.`) : '';
      }
  }
  /**
   * @category Error
   * @description Error that indicates an invalid dal commitment (sh)
   */
  class InvalidDalCommitmentError extends taquitoCore.ParameterValidationError {
      constructor(commitment, errorDetail) {
          super();
          this.commitment = commitment;
          this.errorDetail = errorDetail;
          this.name = 'InvalidDalCommitmentError';
          this.message = `Invalid dal commitment "${commitment}"`;
          errorDetail ? (this.message += ` ${errorDetail}.`) : '';
      }
  }

  class Uint8ArrayConsumer {
      static fromHexString(hex) {
          const lowHex = hex.toLowerCase();
          if (/^(([a-f]|\d){2})*$/.test(lowHex)) {
              const arr = new Uint8Array((lowHex.match(/([a-z]|\d){2}/g) || []).map((byte) => parseInt(byte, 16)));
              return new Uint8ArrayConsumer(arr);
          }
          else {
              throw new taquitoCore.InvalidHexStringError(lowHex);
          }
      }
      constructor(arr, offset = 0) {
          this.arr = arr;
          this.offset = offset;
      }
      consume(count) {
          const subArr = this.arr.subarray(this.offset, this.offset + count);
          this.offset += count;
          return subArr;
      }
      get(idx) {
          return this.arr[this.offset + idx];
      }
      length() {
          return this.arr.length - this.offset;
      }
      slice(start, end) {
          return new Uint8ArrayConsumer(this.arr.slice(start, end));
      }
  }

  const isPrim = (value) => {
      return 'prim' in value;
  };
  const isBytes = (value) => {
      return 'bytes' in value && typeof value.bytes === 'string';
  };
  const isString = (value) => {
      return 'string' in value && typeof value.string === 'string';
  };
  const isInt = (value) => {
      return 'int' in value && typeof value.int === 'string';
  };
  const scriptEncoder = (script) => {
      const code = valueEncoder(script.code);
      const storage = valueEncoder(script.storage);
      return `${pad(code.length / 2, 8)}${code}${pad(storage.length / 2, 8)}${storage}`;
  };
  const scriptDecoder = (value) => {
      const code = extractRequiredLen(value);
      const storage = extractRequiredLen(value);
      return {
          code: valueDecoder(new Uint8ArrayConsumer(code)),
          storage: valueDecoder(new Uint8ArrayConsumer(storage)),
      };
  };
  const valueEncoder = (value) => {
      if (Array.isArray(value)) {
          const encoded = value.map((x) => valueEncoder(x)).join('');
          const len = encoded.length / 2;
          return `02${pad(len)}${encoded}`;
      }
      else if (isPrim(value)) {
          return primEncoder(value);
      }
      else if (isBytes(value)) {
          return bytesEncoder(value);
      }
      else if (isString(value)) {
          return stringEncoder(value);
      }
      else if (isInt(value)) {
          return intEncoder(value);
      }
      throw new UnexpectedMichelsonValueError(JSON.stringify(value));
  };
  const valueDecoder = (value) => {
      const preamble = value.consume(1);
      switch (preamble[0]) {
          case 0x0a:
              return bytesDecoder(value);
          case 0x01:
              return stringDecoder(value);
          case 0x00:
              return intDecoder(value);
          case 0x02: {
              const val = new Uint8ArrayConsumer(extractRequiredLen(value));
              const results = [];
              while (val.length() > 0) {
                  results.push(valueDecoder(val));
              }
              return results;
          }
          default:
              return primDecoder(value, preamble);
      }
  };
  const extractRequiredLen = (value, bytesLength = 4) => {
      const len = value.consume(bytesLength);
      const valueLen = parseInt(Buffer.from(len).toString('hex'), 16);
      return value.consume(valueLen);
  };
  /**
   * @description parse bytes into multiple items of an array
   * @param value Uint8ArrayConsumer class of forged segment to parse
   * @param bytesLength default 4 bytes for length of variable bytes
   * @returns array of Uint8Array values for each array item
   */
  const stripLengthPrefixFromBytes = (value, bytesLength = 4) => {
      const ret = [];
      let values = value;
      while (values.length()) {
          const len = values.consume(bytesLength);
          const valueLen = parseInt(Buffer.from(len).toString('hex'), 16);
          ret.push(values.consume(valueLen));
          values = values.slice(valueLen + bytesLength);
      }
      return ret;
  };
  const bytesEncoder = (value) => {
      if (!/^([A-Fa-f0-9]{2})*$/.test(value.bytes)) {
          throw new taquitoCore.InvalidHexStringError(value.bytes);
      }
      const len = value.bytes.length / 2;
      return `0a${pad(len)}${value.bytes}`;
  };
  const bytesDecoder = (value) => {
      const bytes = extractRequiredLen(value);
      return {
          bytes: Buffer.from(bytes).toString('hex'),
      };
  };
  const stringEncoder = (value) => {
      const str = Buffer.from(value.string, 'utf8').toString('hex');
      const hexLength = str.length / 2;
      return `01${pad(hexLength)}${str}`;
  };
  const stringDecoder = (value) => {
      const str = extractRequiredLen(value);
      return {
          string: Buffer.from(str).toString('utf8'),
      };
  };
  const intEncoder = ({ int }) => {
      const num = new BigNumber.BigNumber(int, 10);
      const positiveMark = num.toString(2)[0] === '-' ? '1' : '0';
      const binary = num.toString(2).replace(/-/g, '');
      const pad = binary.length <= 6
          ? 6
          : (binary.length - 6) % 7
              ? binary.length + 7 - ((binary.length - 6) % 7)
              : binary.length;
      const splitted = binary.padStart(pad, '0').match(/\d{6,7}/g);
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      const reversed = splitted.reverse();
      reversed[0] = positiveMark + reversed[0];
      const numHex = reversed.map((x, i) => 
      // Add one to the last chunk
      parseInt((i === reversed.length - 1 ? '0' : '1') + x, 2)
          .toString(16)
          .padStart(2, '0'));
      return `00${numHex.join('')}`;
  };
  const intDecoder = (value) => {
      let c = value.consume(1)[0];
      const hexNumber = [];
      const isNotLastChunkMask = 1 << 7;
      while (c & isNotLastChunkMask) {
          hexNumber.push(c);
          c = value.consume(1)[0];
      }
      hexNumber.push(c);
      const isNegative = !!((1 << 6) & hexNumber[0]);
      hexNumber[0] = hexNumber[0] & 0b1111111;
      const numBin = hexNumber
          .map((x, i) => x
          .toString(2)
          .slice(i === 0 ? -6 : -7)
          .padStart(i === 0 ? 6 : 7, '0'))
          .reverse();
      let num = new BigNumber.BigNumber(numBin.join(''), 2);
      if (isNegative) {
          num = num.times(-1);
      }
      return {
          int: num.toFixed(),
      };
  };
  const primEncoder = (value) => {
      const hasAnnot = +Array.isArray(value.annots);
      const argsCount = Array.isArray(value.args) ? value.args.length : 0;
      // Specify the number of args max is 3 without annotation
      const preamble = pad(Math.min(2 * argsCount + hasAnnot + 0x03, 9), 2);
      const op = opMappingReverse[value.prim];
      let encodedArgs = (value.args || []).map((arg) => valueEncoder(arg)).join('');
      const encodedAnnots = Array.isArray(value.annots) ? encodeAnnots(value.annots) : '';
      if ((value.prim === 'LAMBDA' || value.prim === 'LAMBDA_REC') && argsCount) {
          encodedArgs = pad(encodedArgs.length / 2) + encodedArgs + pad(0);
      }
      if ((value.prim === 'pair' || value.prim === 'Pair') && argsCount > 2) {
          encodedArgs =
              encodedAnnots === ''
                  ? pad(encodedArgs.length / 2) + encodedArgs + pad(0)
                  : pad(encodedArgs.length / 2) + encodedArgs;
      }
      if (value.prim === 'view' && value.args) {
          encodedArgs = pad(encodedArgs.length / 2) + encodedArgs + pad(0);
      }
      return `${preamble}${op}${encodedArgs}${encodedAnnots}`;
  };
  const primDecoder = (value, preamble) => {
      const hasAnnot = (preamble[0] - 0x03) % 2 === 1;
      let argsCount = Math.floor((preamble[0] - 0x03) / 2);
      const op = value.consume(1)[0].toString(16).padStart(2, '0');
      const result = {
          prim: opMapping[op],
      };
      if (opMapping[op] === 'LAMBDA' || opMapping[op] === 'LAMBDA_REC') {
          value.consume(4);
      }
      if (opMapping[op] === 'view') {
          if (argsCount != 0) {
              return primViewDecoder(value, result);
          }
          else {
              return result;
          }
      }
      let combPairArgs;
      let combPairAnnots;
      if ((opMapping[op] === 'pair' || opMapping[op] === 'Pair') && argsCount > 2) {
          combPairArgs = decodeCombPair(value);
          argsCount = 0;
          combPairAnnots = decodeAnnots(value);
      }
      const args = new Array(argsCount).fill(0).map(() => valueDecoder(value));
      if (opMapping[op] === 'LAMBDA' || opMapping[op] === 'LAMBDA_REC') {
          value.consume(4);
      }
      if (combPairArgs) {
          result['args'] = combPairArgs;
      }
      else if (args.length) {
          result['args'] = args;
      }
      if (combPairAnnots && combPairAnnots[0] !== '') {
          result['annots'] = combPairAnnots;
      }
      else if (hasAnnot) {
          result['annots'] = decodeAnnots(value);
      }
      return result;
  };
  const primViewDecoder = (value, result) => {
      value.consume(4);
      result['args'] = new Array(4).fill(0).map(() => valueDecoder(value));
      value.consume(4);
      return result;
  };
  const decodeCombPair = (val) => {
      const array = new Uint8ArrayConsumer(extractRequiredLen(val));
      const args = [];
      while (array.length() > 0) {
          args.push(valueDecoder(array));
      }
      return args;
  };
  const encodeAnnots = (value) => {
      const mergedAnnot = value
          .map((x) => {
          return Buffer.from(x, 'utf8').toString('hex');
      })
          .join('20');
      const len = mergedAnnot.length / 2;
      return `${pad(len)}${mergedAnnot}`;
  };
  const decodeAnnots = (val) => {
      const len = val.consume(4);
      const annotLen = parseInt(Buffer.from(len).toString('hex'), 16);
      const restOfAnnot = val.consume(annotLen);
      const restOfAnnotHex = Buffer.from(restOfAnnot).toString('hex');
      return restOfAnnotHex.split('20').map((x) => Buffer.from(x, 'hex').toString('utf8'));
  };

  // https://protocol.mavryk.org/shell/p2p_api.html specifies data types and structure for forging
  const prefixEncoder = (prefix) => (str) => {
      return taquitoUtils.buf2hex(Buffer.from(taquitoUtils.b58cdecode(str, taquitoUtils.prefix[prefix])));
  };
  const prefixDecoder = (pre) => (str) => {
      const val = str.consume(taquitoUtils.prefixLength[pre]);
      return taquitoUtils.b58cencode(val, taquitoUtils.prefix[pre]);
  };
  const mv1Decoder = prefixDecoder(taquitoUtils.Prefix.MV1);
  const branchDecoder = prefixDecoder(taquitoUtils.Prefix.B);
  const publicKeyHashDecoder = (val) => {
      const prefix = val.consume(1);
      if (prefix[0] === 0x00) {
          return prefixDecoder(taquitoUtils.Prefix.MV1)(val);
      }
      else if (prefix[0] === 0x01) {
          return prefixDecoder(taquitoUtils.Prefix.MV2)(val);
      }
      else if (prefix[0] === 0x02) {
          return prefixDecoder(taquitoUtils.Prefix.MV3)(val);
      }
  };
  const publicKeyHashesDecoder = (val) => {
      if (!boolDecoder(val)) {
          return undefined;
      }
      const publicKeyHashes = [];
      val.consume(4);
      while (val.length() > 0) {
          publicKeyHashes.push(publicKeyHashDecoder(val));
      }
      return publicKeyHashes;
  };
  const branchEncoder = prefixEncoder(taquitoUtils.Prefix.B);
  const mv1Encoder = prefixEncoder(taquitoUtils.Prefix.MV1);
  const boolEncoder = (bool) => (bool ? 'ff' : '00');
  const proposalEncoder = (proposal) => {
      return prefixEncoder(taquitoUtils.Prefix.P)(proposal);
  };
  const proposalDecoder = (proposal) => {
      return prefixDecoder(taquitoUtils.Prefix.P)(proposal);
  };
  const proposalsDecoder = (proposal) => {
      const proposals = [];
      proposal.consume(4);
      while (proposal.length() > 0) {
          proposals.push(proposalDecoder(proposal));
      }
      return proposals;
  };
  const proposalsEncoder = (proposals) => {
      return pad(32 * proposals.length) + proposals.map((x) => proposalEncoder(x)).join('');
  };
  const ballotEncoder = (ballot) => {
      switch (ballot) {
          case 'yay':
              return '00';
          case 'nay':
              return '01';
          case 'pass':
              return '02';
          default:
              throw new InvalidBallotValueError(ballot);
      }
  };
  const ballotDecoder = (ballot) => {
      const value = ballot.consume(1);
      switch (value[0]) {
          case 0x00:
              return 'yay';
          case 0x01:
              return 'nay';
          case 0x02:
              return 'pass';
          default:
              throw new DecodeBallotValueError(value[0].toString());
      }
  };
  const pvmKindEncoder = (pvm) => {
      switch (pvm) {
          case 'arith':
              return '00';
          case 'wasm_2_0_0':
              return '01';
          case 'riscv':
              return '02';
          default:
              throw new UnsupportedPvmKindError(pvm);
      }
  };
  const pvmKindDecoder = (pvm) => {
      const value = pvm.consume(1);
      switch (value[0]) {
          case 0x00:
              return 'arith';
          case 0x01:
              return 'wasm_2_0_0';
          case 0x02:
              return 'riscv';
          default:
              throw new DecodePvmKindError(value[0].toString());
      }
  };
  const delegateEncoder = (val) => {
      if (val) {
          return boolEncoder(true) + publicKeyHashEncoder(val);
      }
      else {
          return boolEncoder(false);
      }
  };
  const int32Encoder = (val) => {
      const num = parseInt(String(val), 10);
      const byte = [];
      for (let i = 0; i < 4; i++) {
          const shiftBy = (4 - (i + 1)) * 8;
          byte.push((num & (0xff << shiftBy)) >> shiftBy);
      }
      return Buffer.from(byte).toString('hex');
  };
  const int32Decoder = (val) => {
      const num = val.consume(4);
      let finalNum = 0;
      for (let i = 0; i < num.length; i++) {
          finalNum = finalNum | (num[i] << ((num.length - (i + 1)) * 8));
      }
      return finalNum;
  };
  const int16Encoder = (val) => {
      const num = parseInt(String(val), 10);
      const byte = [];
      for (let i = 0; i < 2; i++) {
          const shiftBy = (2 - (i + 1)) * 8;
          byte.push((num & (0xff << shiftBy)) >> shiftBy);
      }
      return Buffer.from(byte).toString('hex');
  };
  const int16Decoder = (val) => {
      const num = val.consume(2);
      let finalNum = 0;
      for (let i = 0; i < num.length; i++) {
          finalNum = finalNum | (num[i] << ((num.length - (i + 1)) * 8));
      }
      return finalNum;
  };
  const boolDecoder = (val) => {
      const bool = val.consume(1);
      return bool[0] === 0xff;
  };
  const delegateDecoder = (val) => {
      const hasDelegate = boolDecoder(val);
      if (hasDelegate) {
          return publicKeyHashDecoder(val);
      }
  };
  const publicKeyHashEncoder = (val) => {
      const pubkeyPrefix = val.substring(0, 3);
      switch (pubkeyPrefix) {
          case taquitoUtils.Prefix.MV1:
              return '00' + prefixEncoder(taquitoUtils.Prefix.MV1)(val);
          case taquitoUtils.Prefix.MV2:
              return '01' + prefixEncoder(taquitoUtils.Prefix.MV2)(val);
          case taquitoUtils.Prefix.MV3:
              return '02' + prefixEncoder(taquitoUtils.Prefix.MV3)(val);
          case taquitoUtils.Prefix.MV4:
              return '03' + prefixEncoder(taquitoUtils.Prefix.MV4)(val);
          default:
              throw new taquitoUtils.InvalidKeyHashError(val, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) +
                  ` expecting one for the following "${taquitoUtils.Prefix.MV1}", "${taquitoUtils.Prefix.MV2}", "${taquitoUtils.Prefix.MV3}" or "${taquitoUtils.Prefix.MV4}".`);
      }
  };
  const publicKeyHashesEncoder = (val) => {
      if (!val) {
          return boolEncoder(false);
      }
      if (val.length === 0) {
          return boolEncoder(true) + pad(0);
      }
      const publicKeyHashes = val.reduce((prev, curr) => {
          return prev + publicKeyHashEncoder(curr);
      }, '');
      return boolEncoder(true) + pad(publicKeyHashes.length / 2) + publicKeyHashes;
  };
  const publicKeyEncoder = (val) => {
      const pubkeyPrefix = val.substring(0, 4);
      switch (pubkeyPrefix) {
          case taquitoUtils.Prefix.EDPK:
              return '00' + prefixEncoder(taquitoUtils.Prefix.EDPK)(val);
          case taquitoUtils.Prefix.SPPK:
              return '01' + prefixEncoder(taquitoUtils.Prefix.SPPK)(val);
          case taquitoUtils.Prefix.P2PK:
              return '02' + prefixEncoder(taquitoUtils.Prefix.P2PK)(val);
          default:
              throw new taquitoUtils.InvalidPublicKeyError(val, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) +
                  ` expecting one of the following '${taquitoUtils.Prefix.EDPK}', '${taquitoUtils.Prefix.SPPK}', '${taquitoUtils.Prefix.P2PK}' or '${taquitoUtils.Prefix.BLPK}'.`);
      }
  };
  const addressEncoder = (val) => {
      const pubkeyPrefix = val.substring(0, 3);
      switch (pubkeyPrefix) {
          case taquitoUtils.Prefix.MV1:
          case taquitoUtils.Prefix.MV2:
          case taquitoUtils.Prefix.MV3:
          case taquitoUtils.Prefix.MV4:
              return '00' + publicKeyHashEncoder(val);
          case taquitoUtils.Prefix.KT1:
              return '01' + prefixEncoder(taquitoUtils.Prefix.KT1)(val) + '00';
          default:
              throw new taquitoCore.InvalidAddressError(val, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) +
                  ` expecting one of the following prefix '${taquitoUtils.Prefix.MV1}', ${taquitoUtils.Prefix.MV2}', '${taquitoUtils.Prefix.MV3}', '${taquitoUtils.Prefix.MV4}' or '${taquitoUtils.Prefix.KT1}'.`);
      }
  };
  const smartRollupAddressEncoder = (val) => {
      if (val.substring(0, 3) !== taquitoUtils.Prefix.SR1) {
          throw new InvalidSmartRollupAddressError(val, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquitoUtils.Prefix.SR1}'.`);
      }
      return prefixEncoder(taquitoUtils.Prefix.SR1)(val);
  };
  const smartContractAddressEncoder = (val) => {
      const prefix = val.substring(0, 3);
      if (prefix === taquitoUtils.Prefix.KT1) {
          return '01' + prefixEncoder(taquitoUtils.Prefix.KT1)(val) + '00';
      }
      throw new taquitoCore.InvalidContractAddressError(val, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquitoUtils.Prefix.KT1}'.`);
  };
  const publicKeyDecoder = (val) => {
      const preamble = val.consume(1);
      switch (preamble[0]) {
          case 0x00:
              return prefixDecoder(taquitoUtils.Prefix.EDPK)(val);
          case 0x01:
              return prefixDecoder(taquitoUtils.Prefix.SPPK)(val);
          case 0x02:
              return prefixDecoder(taquitoUtils.Prefix.P2PK)(val);
          default:
              throw new taquitoUtils.InvalidPublicKeyError(val.toString(), taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED));
      }
  };
  const smartRollupCommitmentHashEncoder = (val) => {
      const prefix = val.substring(0, 4);
      if (prefix === taquitoUtils.Prefix.SRC1) {
          return prefixEncoder(taquitoUtils.Prefix.SRC1)(val);
      }
      throw new InvalidSmartRollupCommitmentHashError(val, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquitoUtils.Prefix.SRC1}'`);
  };
  const addressDecoder = (val) => {
      const preamble = val.consume(1);
      switch (preamble[0]) {
          case 0x00:
              return publicKeyHashDecoder(val);
          case 0x01: {
              const address = prefixDecoder(taquitoUtils.Prefix.KT1)(val);
              val.consume(1);
              return address;
          }
          default:
              throw new taquitoCore.InvalidAddressError(val.toString(), ': Unable to decode.');
      }
  };
  const smartRollupAddressDecoder = (val) => {
      const address = prefixDecoder(taquitoUtils.Prefix.SR1)(val);
      if (address.substring(0, 3) !== taquitoUtils.Prefix.SR1) {
          throw new InvalidSmartRollupAddressError(address, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquitoUtils.Prefix.SR1}'.`);
      }
      return address;
  };
  const smartContractAddressDecoder = (val) => {
      const preamble = val.consume(1);
      if (preamble[0] === 0x01) {
          const scAddress = prefixDecoder(taquitoUtils.Prefix.KT1)(val);
          val.consume(1);
          return scAddress;
      }
      throw new taquitoCore.InvalidContractAddressError(val.toString(), taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED));
  };
  const smartRollupCommitmentHashDecoder = (val) => {
      const address = prefixDecoder(taquitoUtils.Prefix.SRC1)(val);
      if (address.substring(0, 4) !== taquitoUtils.Prefix.SRC1) {
          throw new InvalidSmartRollupCommitmentHashError(address, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquitoUtils.Prefix.SRC1}'`);
      }
      return address;
  };
  const zarithEncoder = (n) => {
      const fn = [];
      let nn = new BigNumber(n, 10);
      if (nn.isNaN()) {
          throw new TypeError(`Invalid zarith number ${n}`);
      }
      // eslint-disable-next-line no-constant-condition
      while (true) {
          if (nn.lt(128)) {
              if (nn.lt(16))
                  fn.push('0');
              fn.push(nn.toString(16));
              break;
          }
          else {
              let b = nn.mod(128);
              nn = nn.minus(b);
              nn = nn.dividedBy(128);
              b = b.plus(128);
              fn.push(b.toString(16));
          }
      }
      return fn.join('');
  };
  const zarithDecoder = (n) => {
      let mostSignificantByte = 0;
      while (mostSignificantByte < n.length() && (n.get(mostSignificantByte) & 128) !== 0) {
          mostSignificantByte += 1;
      }
      let num = new BigNumber(0);
      for (let i = mostSignificantByte; i >= 0; i -= 1) {
          const tmp = n.get(i) & 0x7f;
          num = num.multipliedBy(128);
          num = num.plus(tmp);
      }
      n.consume(mostSignificantByte + 1);
      return new BigNumber(num).toString();
  };
  const entrypointDecoder = (value) => {
      const preamble = pad(value.consume(1)[0], 2);
      if (preamble in entrypointMapping) {
          return entrypointMapping[preamble];
      }
      else {
          const entry = extractRequiredLen(value, 1);
          const entrypoint = Buffer.from(entry).toString('utf8');
          if (entrypoint.length > ENTRYPOINT_MAX_LENGTH) {
              throw new OversizedEntryPointError(entrypoint);
          }
          return entrypoint;
      }
  };
  const parametersDecoder = (val) => {
      const preamble = val.consume(1);
      if (preamble[0] === 0x00) {
          return;
      }
      else {
          const encodedEntrypoint = entrypointDecoder(val);
          const params = extractRequiredLen(val);
          const parameters = valueDecoder(new Uint8ArrayConsumer(params));
          return {
              entrypoint: encodedEntrypoint,
              value: parameters,
          };
      }
  };
  const entrypointEncoder = (entrypoint) => {
      if (entrypoint in entrypointMappingReverse) {
          return `${entrypointMappingReverse[entrypoint]}`;
      }
      else {
          if (entrypoint.length > ENTRYPOINT_MAX_LENGTH) {
              throw new OversizedEntryPointError(entrypoint);
          }
          const value = { string: entrypoint };
          return `ff${valueEncoder(value).slice(8)}`;
      }
  };
  const parametersEncoder = (val) => {
      if (!val || (val.entrypoint === 'default' && 'prim' in val.value && val.value.prim === 'Unit')) {
          return '00';
      }
      const encodedEntrypoint = entrypointEncoder(val.entrypoint);
      const parameters = valueEncoder(val.value);
      const length = pad(parameters.length / 2);
      return `ff${encodedEntrypoint}${length}${parameters}`;
  };
  const valueParameterEncoder = (value) => {
      const valueEncoded = valueEncoder(value);
      return `${pad(valueEncoded.length / 2)}${valueEncoded}`;
  };
  const valueParameterDecoder = (val) => {
      const value = extractRequiredLen(val);
      return valueDecoder(new Uint8ArrayConsumer(value));
  };
  const blockPayloadHashEncoder = prefixEncoder(taquitoUtils.Prefix.VH);
  const blockPayloadHashDecoder = prefixDecoder(taquitoUtils.Prefix.VH);
  const entrypointNameEncoder = (entrypoint) => {
      const value = { string: entrypoint };
      return `${valueEncoder(value).slice(2)}`;
  };
  const entrypointNameDecoder = (val) => {
      const entry = extractRequiredLen(val);
      return Buffer.from(entry).toString('utf8');
  };
  const burnLimitEncoder = (val) => {
      return !val ? '00' : `ff${zarithEncoder(val)}`;
  };
  const burnLimitDecoder = (value) => {
      const prefix = value.consume(1);
      if (Buffer.from(prefix).toString('hex') !== '00') {
          return zarithDecoder(value);
      }
  };
  const depositsLimitEncoder = (val) => {
      return !val ? '00' : `ff${zarithEncoder(val)}`;
  };
  const depositsLimitDecoder = (value) => {
      const prefix = value.consume(1);
      if (Buffer.from(prefix).toString('hex') !== '00') {
          return zarithDecoder(value);
      }
  };
  const paddedBytesEncoder = (val, paddingLength = 8) => {
      return `${pad(val.length / 2, paddingLength)}${val}`;
  };
  const paddedBytesDecoder = (val) => {
      const value = extractRequiredLen(val);
      return Buffer.from(value).toString('hex');
  };
  const smartRollupMessageEncoder = (val) => {
      const message = val.reduce((prev, curr) => {
          return prev + `${pad(curr.length / 2)}${curr}`;
      }, '');
      return `${pad(message.length / 2)}${message}`;
  };
  const smartRollupMessageDecoder = (val) => {
      const valueArray = extractRequiredLen(val);
      const ret = stripLengthPrefixFromBytes(new Uint8ArrayConsumer(valueArray));
      return ret.map((value) => Buffer.from(value).toString('hex'));
  };
  const dalCommitmentEncoder = (val) => {
      const prefix = val.substring(0, 2);
      if (prefix === taquitoUtils.Prefix.SH) {
          return prefixEncoder(taquitoUtils.Prefix.SH)(val);
      }
      throw new InvalidDalCommitmentError(val, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquitoUtils.Prefix.SH}'`);
  };
  const dalCommitmentDecoder = (val) => {
      const commitment = prefixDecoder(taquitoUtils.Prefix.SH)(val);
      if (commitment.substring(0, 2) !== taquitoUtils.Prefix.SH) {
          throw new InvalidDalCommitmentError(commitment, taquitoUtils.invalidDetail(taquitoUtils.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquitoUtils.Prefix.SH}'`);
      }
      return commitment;
  };
  const slotHeaderEncoder = (val) => {
      return pad(val.slot_index, 2) + dalCommitmentEncoder(val.commitment) + val.commitment_proof;
  };
  const slotHeaderDecoder = (val) => {
      const preamble = val.consume(1);
      return {
          slot_index: Number(preamble[0].toString(10)),
          commitment: dalCommitmentDecoder(val),
          commitment_proof: toHexString(val.consume(96)), // rpcForger expect commitment_proof bytes to be len 96
      };
  };

  const ManagerOperationSchema = {
      branch: exports.CODEC.BRANCH,
      contents: [exports.CODEC.OPERATION],
  };
  const ActivationSchema = {
      pkh: exports.CODEC.MV1,
      secret: exports.CODEC.SECRET,
  };
  const RevealSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      public_key: exports.CODEC.PUBLIC_KEY,
  };
  const DelegationSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      delegate: exports.CODEC.DELEGATE,
  };
  const TransactionSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      amount: exports.CODEC.ZARITH,
      destination: exports.CODEC.ADDRESS,
      parameters: exports.CODEC.PARAMETERS,
  };
  const OriginationSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      balance: exports.CODEC.ZARITH,
      delegate: exports.CODEC.DELEGATE,
      script: exports.CODEC.SCRIPT,
  };
  const BallotSchema = {
      source: exports.CODEC.PKH,
      period: exports.CODEC.INT32,
      proposal: exports.CODEC.PROPOSAL,
      ballot: exports.CODEC.BALLOT_STATEMENT,
  };
  const AttestationSchema = {
      slot: exports.CODEC.INT16,
      level: exports.CODEC.INT32,
      round: exports.CODEC.INT32,
      block_payload_hash: exports.CODEC.BLOCK_PAYLOAD_HASH,
  };
  const AttestationWithDalSchema = {
      slot: exports.CODEC.INT16,
      level: exports.CODEC.INT32,
      round: exports.CODEC.INT32,
      block_payload_hash: exports.CODEC.BLOCK_PAYLOAD_HASH,
      dal_attestation: exports.CODEC.ZARITH,
  };
  const SeedNonceRevelationSchema = {
      level: exports.CODEC.INT32,
      nonce: exports.CODEC.RAW,
  };
  const ProposalsSchema = {
      source: exports.CODEC.PKH,
      period: exports.CODEC.INT32,
      proposals: exports.CODEC.PROPOSAL_ARR,
  };
  const RegisterGlobalConstantSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      value: exports.CODEC.VALUE,
  };
  const TransferTicketSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      ticket_contents: exports.CODEC.VALUE,
      ticket_ty: exports.CODEC.VALUE,
      ticket_ticketer: exports.CODEC.ADDRESS,
      ticket_amount: exports.CODEC.ZARITH,
      destination: exports.CODEC.ADDRESS,
      entrypoint: exports.CODEC.ENTRYPOINT,
  };
  const IncreasePaidStorageSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      amount: exports.CODEC.ZARITH,
      destination: exports.CODEC.SMART_CONTRACT_ADDRESS,
  };
  const UpdateConsensusKeySchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      pk: exports.CODEC.PUBLIC_KEY,
  };
  const DrainDelegateSchema = {
      consensus_key: exports.CODEC.PKH,
      delegate: exports.CODEC.PKH,
      destination: exports.CODEC.PKH,
  };
  const SetDepositsLimitSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      limit: exports.CODEC.DEPOSITS_LIMIT,
  };
  const SmartRollupOriginateSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      pvm_kind: exports.CODEC.PVM_KIND,
      kernel: exports.CODEC.PADDED_BYTES,
      parameters_ty: exports.CODEC.VALUE,
      whitelist: exports.CODEC.PKH_ARR,
  };
  const SmartRollupAddMessagesSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      message: exports.CODEC.SMART_ROLLUP_MESSAGE,
  };
  const SmartRollupExecuteOutboxMessageSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      rollup: exports.CODEC.SMART_ROLLUP_ADDRESS,
      cemented_commitment: exports.CODEC.SMART_ROLLUP_COMMITMENT_HASH,
      output_proof: exports.CODEC.PADDED_BYTES,
  };
  const DalPublishCommitmentSchema = {
      source: exports.CODEC.PKH,
      fee: exports.CODEC.ZARITH,
      counter: exports.CODEC.ZARITH,
      gas_limit: exports.CODEC.ZARITH,
      storage_limit: exports.CODEC.ZARITH,
      slot_header: exports.CODEC.SLOT_HEADER,
  };
  const FailingNoopSchema = {
      arbitrary: exports.CODEC.PADDED_BYTES,
  };
  const operationEncoder = (encoders) => (operation) => {
      if (!(operation.kind in encoders) || !(operation.kind in kindMappingReverse)) {
          throw new taquitoCore.InvalidOperationKindError(operation.kind);
      }
      return kindMappingReverse[operation.kind] + encoders[operation.kind](operation);
  };
  const operationDecoder = (decoders) => (value) => {
      const op = value.consume(1);
      const operationName = kindMapping[op[0]];
      if (operationName === undefined) {
          throw new UnsupportedOperationError(op[0].toString());
      }
      const decodedObj = decoders[operationName](value);
      if (typeof decodedObj !== 'object') {
          throw new OperationDecodingError('Invalid operation, cannot be decoded.');
      }
      return Object.assign({ kind: operationName }, decodedObj);
  };
  const schemaEncoder = (encoders) => (schema) => (value) => {
      const keys = Object.keys(schema);
      return keys.reduce((prev, key) => {
          const valueToEncode = schema[key];
          if (value && Array.isArray(valueToEncode)) {
              const encoder = encoders[valueToEncode[0]];
              const values = value[key];
              if (!Array.isArray(values)) {
                  throw new OperationEncodingError(`Invalid operation value "${JSON.stringify(values)}" of key "${key}, expected value to be Array.`);
              }
              return (prev + values.reduce((prevBytes, current) => prevBytes + encoder(current), ''));
          }
          else {
              const encoder = encoders[valueToEncode];
              return prev + encoder(value[key]);
          }
      }, '');
  };
  const schemaDecoder = (decoders) => (schema) => (value) => {
      const keys = Object.keys(schema);
      return keys.reduce((prev, key) => {
          const valueToEncode = schema[key];
          if (Array.isArray(valueToEncode)) {
              const decoder = decoders[valueToEncode[0]];
              const decoded = [];
              const lastLength = value.length();
              while (value.length() > 0) {
                  decoded.push(decoder(value));
                  if (lastLength === value.length()) {
                      throw new OperationDecodingError('Unable to decode value');
                  }
              }
              return Object.assign(Object.assign({}, prev), { [key]: decoded });
          }
          else {
              const decoder = decoders[valueToEncode];
              const result = decoder(value);
              if (typeof result !== 'undefined') {
                  return Object.assign(Object.assign({}, prev), { [key]: result });
              }
              else {
                  return Object.assign({}, prev);
              }
          }
      }, {});
  };

  const decoders = {
      [exports.CODEC.SECRET]: (val) => toHexString(val.consume(20)),
      [exports.CODEC.RAW]: (val) => toHexString(val.consume(32)),
      [exports.CODEC.MV1]: mv1Decoder,
      [exports.CODEC.BRANCH]: branchDecoder,
      [exports.CODEC.ZARITH]: zarithDecoder,
      [exports.CODEC.PUBLIC_KEY]: publicKeyDecoder,
      [exports.CODEC.PKH]: publicKeyHashDecoder,
      [exports.CODEC.PKH_ARR]: publicKeyHashesDecoder,
      [exports.CODEC.DELEGATE]: delegateDecoder,
      [exports.CODEC.INT32]: int32Decoder,
      [exports.CODEC.SCRIPT]: scriptDecoder,
      [exports.CODEC.BALLOT_STATEMENT]: ballotDecoder,
      [exports.CODEC.PROPOSAL]: proposalDecoder,
      [exports.CODEC.PROPOSAL_ARR]: proposalsDecoder,
      [exports.CODEC.PARAMETERS]: parametersDecoder,
      [exports.CODEC.ADDRESS]: addressDecoder,
      [exports.CODEC.SMART_ROLLUP_ADDRESS]: smartRollupAddressDecoder,
      [exports.CODEC.SMART_CONTRACT_ADDRESS]: smartContractAddressDecoder,
      [exports.CODEC.SMART_ROLLUP_COMMITMENT_HASH]: smartRollupCommitmentHashDecoder,
      [exports.CODEC.VALUE]: valueParameterDecoder,
      [exports.CODEC.INT16]: int16Decoder,
      [exports.CODEC.BLOCK_PAYLOAD_HASH]: blockPayloadHashDecoder,
      [exports.CODEC.ENTRYPOINT]: entrypointNameDecoder,
      [exports.CODEC.BURN_LIMIT]: burnLimitDecoder,
      [exports.CODEC.DEPOSITS_LIMIT]: depositsLimitDecoder,
      [exports.CODEC.PVM_KIND]: pvmKindDecoder,
      [exports.CODEC.PADDED_BYTES]: paddedBytesDecoder,
      [exports.CODEC.SMART_ROLLUP_MESSAGE]: smartRollupMessageDecoder,
      [exports.CODEC.SLOT_HEADER]: slotHeaderDecoder,
  };
  decoders[exports.CODEC.OPERATION] = operationDecoder(decoders);
  decoders[exports.CODEC.OP_ACTIVATE_ACCOUNT] = (val) => schemaDecoder(decoders)(ActivationSchema)(val);
  decoders[exports.CODEC.OP_FAILING_NOOP] = (val) => schemaDecoder(decoders)(FailingNoopSchema)(val);
  decoders[exports.CODEC.OP_DELEGATION] = (val) => schemaDecoder(decoders)(DelegationSchema)(val);
  decoders[exports.CODEC.OP_TRANSACTION] = (val) => schemaDecoder(decoders)(TransactionSchema)(val);
  decoders[exports.CODEC.OP_ORIGINATION] = (val) => schemaDecoder(decoders)(OriginationSchema)(val);
  decoders[exports.CODEC.OP_BALLOT] = (val) => schemaDecoder(decoders)(BallotSchema)(val);
  decoders[exports.CODEC.OP_ATTESTATION] = (val) => schemaDecoder(decoders)(AttestationSchema)(val);
  decoders[exports.CODEC.OP_ATTESTATION_WITH_DAL] = (val) => schemaDecoder(decoders)(AttestationWithDalSchema)(val);
  decoders[exports.CODEC.OP_SEED_NONCE_REVELATION] = (val) => schemaDecoder(decoders)(SeedNonceRevelationSchema)(val);
  decoders[exports.CODEC.OP_PROPOSALS] = (val) => schemaDecoder(decoders)(ProposalsSchema)(val);
  decoders[exports.CODEC.OP_REVEAL] = (val) => schemaDecoder(decoders)(RevealSchema)(val);
  decoders[exports.CODEC.OP_REGISTER_GLOBAL_CONSTANT] = (val) => schemaDecoder(decoders)(RegisterGlobalConstantSchema)(val);
  decoders[exports.CODEC.OP_TRANSFER_TICKET] = (val) => schemaDecoder(decoders)(TransferTicketSchema)(val);
  decoders[exports.CODEC.OP_INCREASE_PAID_STORAGE] = (val) => schemaDecoder(decoders)(IncreasePaidStorageSchema)(val);
  decoders[exports.CODEC.OP_UPDATE_CONSENSUS_KEY] = (val) => schemaDecoder(decoders)(UpdateConsensusKeySchema)(val);
  decoders[exports.CODEC.OP_DRAIN_DELEGATE] = (val) => schemaDecoder(decoders)(DrainDelegateSchema)(val);
  decoders[exports.CODEC.OP_SMART_ROLLUP_ORIGINATE] = (val) => schemaDecoder(decoders)(SmartRollupOriginateSchema)(val);
  decoders[exports.CODEC.OP_SMART_ROLLUP_ADD_MESSAGES] = (val) => schemaDecoder(decoders)(SmartRollupAddMessagesSchema)(val);
  decoders[exports.CODEC.OP_SMART_ROLLUP_EXECUTE_OUTBOX_MESSAGE] = (val) => schemaDecoder(decoders)(SmartRollupExecuteOutboxMessageSchema)(val);
  decoders[exports.CODEC.OP_DAL_PUBLISH_COMMITMENT] = (val) => schemaDecoder(decoders)(DalPublishCommitmentSchema)(val);
  decoders[exports.CODEC.MANAGER] = schemaDecoder(decoders)(ManagerOperationSchema);
  decoders[exports.CODEC.OP_SET_DEPOSITS_LIMIT] = (val) => schemaDecoder(decoders)(SetDepositsLimitSchema)(val);

  const encoders = {
      [exports.CODEC.SECRET]: (val) => val,
      [exports.CODEC.RAW]: (val) => val,
      [exports.CODEC.MV1]: mv1Encoder,
      [exports.CODEC.BRANCH]: branchEncoder,
      [exports.CODEC.ZARITH]: zarithEncoder,
      [exports.CODEC.PUBLIC_KEY]: publicKeyEncoder,
      [exports.CODEC.PKH]: publicKeyHashEncoder,
      [exports.CODEC.PKH_ARR]: publicKeyHashesEncoder,
      [exports.CODEC.DELEGATE]: delegateEncoder,
      [exports.CODEC.SCRIPT]: scriptEncoder,
      [exports.CODEC.BALLOT_STATEMENT]: ballotEncoder,
      [exports.CODEC.PROPOSAL]: proposalEncoder,
      [exports.CODEC.PROPOSAL_ARR]: proposalsEncoder,
      [exports.CODEC.INT32]: int32Encoder,
      [exports.CODEC.PARAMETERS]: parametersEncoder,
      [exports.CODEC.ADDRESS]: addressEncoder,
      [exports.CODEC.SMART_ROLLUP_ADDRESS]: smartRollupAddressEncoder,
      [exports.CODEC.SMART_CONTRACT_ADDRESS]: smartContractAddressEncoder,
      [exports.CODEC.SMART_ROLLUP_COMMITMENT_HASH]: smartRollupCommitmentHashEncoder,
      [exports.CODEC.VALUE]: valueParameterEncoder,
      [exports.CODEC.INT16]: int16Encoder,
      [exports.CODEC.BLOCK_PAYLOAD_HASH]: blockPayloadHashEncoder,
      [exports.CODEC.ENTRYPOINT]: entrypointNameEncoder,
      [exports.CODEC.BURN_LIMIT]: burnLimitEncoder,
      [exports.CODEC.DEPOSITS_LIMIT]: depositsLimitEncoder,
      [exports.CODEC.PVM_KIND]: pvmKindEncoder,
      [exports.CODEC.PADDED_BYTES]: paddedBytesEncoder,
      [exports.CODEC.SMART_ROLLUP_MESSAGE]: smartRollupMessageEncoder,
      [exports.CODEC.SLOT_HEADER]: slotHeaderEncoder,
  };
  encoders[exports.CODEC.OPERATION] = operationEncoder(encoders);
  encoders[exports.CODEC.OP_ACTIVATE_ACCOUNT] = (val) => schemaEncoder(encoders)(ActivationSchema)(val);
  encoders[exports.CODEC.OP_DELEGATION] = (val) => schemaEncoder(encoders)(DelegationSchema)(val);
  encoders[exports.CODEC.OP_TRANSACTION] = (val) => schemaEncoder(encoders)(TransactionSchema)(val);
  encoders[exports.CODEC.OP_ORIGINATION] = (val) => schemaEncoder(encoders)(OriginationSchema)(val);
  encoders[exports.CODEC.OP_BALLOT] = (val) => schemaEncoder(encoders)(BallotSchema)(val);
  encoders[exports.CODEC.OP_ATTESTATION] = (val) => schemaEncoder(encoders)(AttestationSchema)(val);
  encoders[exports.CODEC.OP_ATTESTATION_WITH_DAL] = (val) => schemaEncoder(encoders)(AttestationWithDalSchema)(val);
  encoders[exports.CODEC.OP_SEED_NONCE_REVELATION] = (val) => schemaEncoder(encoders)(SeedNonceRevelationSchema)(val);
  encoders[exports.CODEC.OP_PROPOSALS] = (val) => schemaEncoder(encoders)(ProposalsSchema)(val);
  encoders[exports.CODEC.OP_REVEAL] = (val) => schemaEncoder(encoders)(RevealSchema)(val);
  encoders[exports.CODEC.OP_REGISTER_GLOBAL_CONSTANT] = (val) => schemaEncoder(encoders)(RegisterGlobalConstantSchema)(val);
  encoders[exports.CODEC.OP_TRANSFER_TICKET] = (val) => schemaEncoder(encoders)(TransferTicketSchema)(val);
  encoders[exports.CODEC.OP_INCREASE_PAID_STORAGE] = (val) => schemaEncoder(encoders)(IncreasePaidStorageSchema)(val);
  encoders[exports.CODEC.OP_UPDATE_CONSENSUS_KEY] = (val) => schemaEncoder(encoders)(UpdateConsensusKeySchema)(val);
  encoders[exports.CODEC.OP_DRAIN_DELEGATE] = (val) => schemaEncoder(encoders)(DrainDelegateSchema)(val);
  encoders[exports.CODEC.OP_SMART_ROLLUP_ORIGINATE] = (val) => schemaEncoder(encoders)(SmartRollupOriginateSchema)(val);
  encoders[exports.CODEC.OP_SMART_ROLLUP_ADD_MESSAGES] = (val) => schemaEncoder(encoders)(SmartRollupAddMessagesSchema)(val);
  encoders[exports.CODEC.OP_SMART_ROLLUP_EXECUTE_OUTBOX_MESSAGE] = (val) => schemaEncoder(encoders)(SmartRollupExecuteOutboxMessageSchema)(val);
  encoders[exports.CODEC.OP_DAL_PUBLISH_COMMITMENT] = (val) => schemaEncoder(encoders)(DalPublishCommitmentSchema)(val);
  encoders[exports.CODEC.MANAGER] = schemaEncoder(encoders)(ManagerOperationSchema);
  encoders[exports.CODEC.OP_SET_DEPOSITS_LIMIT] = (val) => schemaEncoder(encoders)(SetDepositsLimitSchema)(val);
  encoders[exports.CODEC.OP_FAILING_NOOP] = (val) => schemaEncoder(encoders)(FailingNoopSchema)(val);

  const OperationKindMapping = {
      activate_account: ActivationSchema,
      reveal: RevealSchema,
      delegation: DelegationSchema,
      transaction: TransactionSchema,
      origination: OriginationSchema,
      ballot: BallotSchema,
      attestation: AttestationSchema,
      attestation_with_dal: AttestationWithDalSchema,
      seed_nonce_revelation: SeedNonceRevelationSchema,
      proposals: ProposalsSchema,
      register_global_constant: RegisterGlobalConstantSchema,
      transfer_ticket: TransferTicketSchema,
      increase_paid_storage: IncreasePaidStorageSchema,
      update_consensus_key: UpdateConsensusKeySchema,
      drain_delegate: DrainDelegateSchema,
      set_deposits_limit: SetDepositsLimitSchema,
      smart_rollup_originate: SmartRollupOriginateSchema,
      smart_rollup_add_messages: SmartRollupAddMessagesSchema,
      smart_rollup_execute_outbox_message: SmartRollupExecuteOutboxMessageSchema,
      dal_publish_commitment: DalPublishCommitmentSchema,
      failing_noop: FailingNoopSchema,
  };
  // Asymmetric difference: only account for things in arr2 that are not present in arr1, not vice versa
  const getArrayDifference = (arr1, arr2) => {
      return arr2.filter((x) => !arr1.includes(x));
  };
  const deleteArrayElementByValue = (array, item) => {
      return array.filter((e) => e !== item);
  };
  /**
   * @returns A boolean value to indicate whether the operation kind is valid or not
   */
  const validateOperationKind = (opKind) => {
      const opKindList = Object.keys(OperationKindMapping);
      return opKindList.includes(opKind);
  };
  /**
   *  returns 0 when the two array of properties are identical or the passed property
   *  does not have any missing parameters from the corresponding schema
   *
   *  @returns array element differences if there are missing required property keys
   */
  const validateMissingProperty = (operationContent) => {
      const kind = operationContent.kind;
      const keys = Object.keys(operationContent);
      const cleanKeys = deleteArrayElementByValue(keys, 'kind');
      const schemaKeys = Object.keys(OperationKindMapping[kind]);
      return getArrayDifference(cleanKeys, schemaKeys);
  };

  exports.ProtocolsHash = void 0;
  (function (ProtocolsHash) {
      ProtocolsHash["PtAtLas"] = "PtAtLasdzXg4XxeVNtWheo13nG4wHXP22qYMqFcT3fyBpWkFero";
      ProtocolsHash["PtBoreas"] = "PtBoreasK2KPuKbeYtXeEdudEHS7YcMFHE9amwheUc4kejTxgRi";
      ProtocolsHash["ProtoALpha"] = "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK";
  })(exports.ProtocolsHash || (exports.ProtocolsHash = {}));

  // IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN!
  const VERSION = {
      commitHash: '45fea4a361f29598063e448574800220c4687001',
      version: '20.0.0',
  };

  /**
   * @packageDocumentation
   * @module @mavrykdynamics/taquito-local-forging
   */
  const PROTOCOL_CURRENT = exports.ProtocolsHash.PtBoreas;
  function getCodec(codec, _proto) {
      return {
          encoder: encoders[codec],
          decoder: (hex) => {
              const consumer = Uint8ArrayConsumer.fromHexString(hex);
              return decoders[codec](consumer);
          },
      };
  }
  //
  class LocalForger {
      constructor(protocolHash = PROTOCOL_CURRENT) {
          this.protocolHash = protocolHash;
          this.codec = getCodec(exports.CODEC.MANAGER, this.protocolHash);
      }
      forge(params) {
          const branchValidation = taquitoUtils.validateBlock(params.branch);
          if (branchValidation !== taquitoUtils.ValidationResult.VALID) {
              throw new taquitoCore.InvalidBlockHashError(params.branch, taquitoUtils.invalidDetail(branchValidation));
          }
          for (const content of params.contents) {
              if (!validateOperationKind(content.kind)) {
                  throw new taquitoCore.InvalidOperationKindError(content.kind);
              }
              const diff = validateMissingProperty(content);
              if (diff.length === 1) {
                  if (content.kind === 'delegation' && diff[0] === 'delegate') {
                      continue;
                  }
                  else if (content.kind === 'origination' && diff[0] === 'delegate') {
                      continue;
                  }
                  else if (content.kind === 'transaction' && diff[0] === 'parameters') {
                      continue;
                  }
                  else if (content.kind === 'set_deposits_limit' && diff[0] === 'limit') {
                      continue;
                  }
                  else if (content.kind === 'smart_rollup_originate' && diff[0] === 'whitelist') {
                      continue;
                  }
                  else {
                      throw new InvalidOperationSchemaError(content, `missing properties "${diff.join(', ')}"`);
                  }
              }
              else if (diff.length > 1) {
                  throw new InvalidOperationSchemaError(content, `missing properties "${diff.join(', ')}"`);
              }
          }
          const forged = this.codec.encoder(params).toLowerCase();
          return Promise.resolve(forged);
      }
      parse(hex) {
          return Promise.resolve(this.codec.decoder(hex));
      }
  }
  const localForger = new LocalForger();

  exports.LocalForger = LocalForger;
  exports.Uint8ArrayConsumer = Uint8ArrayConsumer;
  exports.VERSION = VERSION;
  exports.decoders = decoders;
  exports.encoders = encoders;
  exports.getCodec = getCodec;
  exports.localForger = localForger;
  exports.opMapping = opMapping;
  exports.opMappingReverse = opMappingReverse;

}));
//# sourceMappingURL=taquito-local-forging.umd.js.map