import { AbiEncoder } from "@ingocollatz/sdk-interfaces";
import Web3 from "web3";

export class Web3AbiEncoder implements AbiEncoder {
  private readonly _web3: Web3;

  /**
   * Constructs an instance of the Web3AbiEncoder.
   *
   * @param web3 - An instance of the web3.js library.
   */
  constructor(web3: Web3) {
    this._web3 = web3;
  }

  /**
   * Encodes the ABI call data for a specific function using the web3.js library.
   *
   * Given a contract ABI, a function name, and the function's arguments, it will generate
   * the call data string which can be used to invoke the specific function on the Ethereum blockchain.
   *
   * @param abi - The ABI (Application Binary Interface) of the smart contract.
   * @param functionName - The name of the function to encode.
   * @param args - The arguments to pass to the function.
   *
   * @returns A promise that resolves to the encoded call data string.
   *
   * @throws Will throw an error if:
   *         - The provided ABI, function name, or args are invalid or not compatible.
   *         - Encoding fails due to any reason.
   */
  async encodeCallData(
    abi: any,
    functionName: string,
    args: any[]
  ): Promise<any> {
    const contract = new this._web3.eth.Contract(abi);

    const callData = await contract.methods[functionName](...args).encodeABI();

    return callData;
  }
}
