The Interface Class abstracts the encoding and decoding required to interact with contracts on the Hedera Hashgraph.
Many of the standards organically evolved along side the Solidity language, which other languages have adopted to remain compatible with existing deployed contracts.
The EVM itself does not understand what the ABI is. It is simply an agreed upon set of formats to encode various types of data which each contract can expect so they can interoperate with each other.
Creating Instances
new hethers.utils.Interface( abi )
Create a new Interface from a JSON string or object representing abi.
The abi may be a JSON string or the parsed Object (using JSON.parse) which is emitted by the Solidity compiler (or compatible languages).
// By method signature, which is normalized so whitespace// and superfluous attributes are ignorediface.getFunction("transferFrom(address, address, uint256)");// By name; this ONLY works if the method is non-ambiguousiface.getFunction("transferFrom");// By method selectoriface.getFunction("0x23b872dd");// Throws if the method does not existiface.getFunction("doesNotExist()");// [Error: no matching function] {// argument: 'signature',// code: 'INVALID_ARGUMENT',// reason: 'no matching function',// value: 'doesNotExist()'// }
// By error signature, which is normalized so whitespace// and superfluous attributes are ignorediface.getError("AccountLocked(address, uint256)");// By name; this ONLY works if the error is non-ambiguousiface.getError("AccountLocked");// By error selectoriface.getError("0xf7c3865a");// Throws if the error does not existiface.getError("DoesNotExist()");// [Error: no matching error] {// argument: 'signature',// code: 'INVALID_ARGUMENT',// reason: 'no matching error',// value: 'DoesNotExist()'// }
// By event signature, which is normalized so whitespace// and superfluous attributes are ignorediface.getEvent("Transfer(address, address, uint256)");// By name; this ONLY works if the event is non-ambiguousiface.getEvent("Transfer");// By event topic hashiface.getEvent("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef");// Throws if the event does not existiface.getEvent("DoesNotExist()");// [Error: no matching event] {// argument: 'signature',// code: 'INVALID_ARGUMENT',// reason: 'no matching event',// value: 'DoesNotExist()'// }
Signature and Topic Hashes
interface.getSighash( fragment ) ⇒ string<DataHexString<4>>
Return the sighash (or Function Selector) for fragment (see Specifying Fragments).
Return the encoded deployment data, which can be concatenated to the deployment bytecode of a contract to pass values into the contract constructor.
// The data that should be appended to the bytecode to pass// parameters to the constructor during deploymentiface.encodeDeploy([ "SYM","Some Name" ])// '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000353594d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009536f6d65204e616d650000000000000000000000000000000000000000000000'
interface.encodeErrorResult( fragment [, values ] ) ⇒ string<DataHexString>
Returns the encoded error result, which would normally be the response from a reverted call for fragment (see Specifying Fragments) for the given values.
Most developers will not need this method, but may be useful for authors of a mock hashgraph.
// Encoding result data (like is returned by eth_call during a revert)iface.encodeErrorResult("AccountLocked", ["0x8ba1f109551bD432803012645Ac136ddd64DBA72",parseHbar("1.0")]);// '0xf7c3865a0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000000de0b6b3a7640000'
// Filter that matches all Transfer eventsiface.encodeFilterTopics("Transfer", [])// [// '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'// ]// Filter that matches the senderiface.encodeFilterTopics("Transfer", ["0x8ba1f109551bD432803012645Ac136ddd64DBA72"])// [// '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',// '0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72'// ]// Filter that matches the receiveriface.encodeFilterTopics("Transfer", [null,"0x8ba1f109551bD432803012645Ac136ddd64DBA72"])// [// '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',// null,// '0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72'// ]
interface.encodeFunctionData( fragment [, values ] ) ⇒ string<DataHexString>
Returns the encoded data, which can be used as the data for a transaction for fragment (see Specifying Fragments) for the given values.
// Encoding data for the tx.data of a call or transactioniface.encodeFunctionData("transferFrom", ["0x8ba1f109551bD432803012645Ac136ddd64DBA72","0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C",parseHbar("1.0")])// '0x23b872dd0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c0000000000000000000000000000000000000000000000000de0b6b3a7640000'
// Encoding structured data (using positional Array)user = ["Richard Moore","0x8ba1f109551bD432803012645Ac136ddd64DBA72"];iface.encodeFunctionData("addUser", [ user ]);// '0x43967833000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000000000000000000000000000000000000000000d52696368617264204d6f6f726500000000000000000000000000000000000000'
// Encoding structured data, using objects. Only available// if paramters are named.user = { name:"Richard Moore", addr:"0x8ba1f109551bD432803012645Ac136ddd64DBA72"};iface.encodeFunctionData("addUser", [ user ]);// '0x43967833000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000000000000000000000000000000000000000000d52696368617264204d6f6f726500000000000000000000000000000000000000'
interface.encodeFunctionResult( fragment [, values ] ) ⇒ string<DataHexString>
Returns the encoded result, which would normally be the response from a call for fragment (see Specifying Fragments) for the given values.
Most developers will not need this method, but may be useful for authors of a mock hashgraph.
// Encoding result data (like is returned by eth_call)iface.encodeFunctionResult("balanceOf", ["0x8ba1f109551bD432803012645Ac136ddd64DBA72"])// '0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72'
Decoding Data
interface.decodeErrorResult( fragment, data ) ⇒ Result
Returns the decoded values from the result of a call during a revert for fragment (see Specifying Fragments) for the given data.
Most developers won't need this, as the decodeFunctionResult will automatically decode errors if the data represents a revert.
// Decoding result data (e.g. from an eth_call)errorData = "0xf7c3865a0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000000de0b6b3a7640000";
iface.decodeErrorResult("AccountLocked", errorData)// [// '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// { BigNumber: "1000000000000000000" },// balance: { BigNumber: "1000000000000000000" },// owner: '0x8ba1f109551bD432803012645Ac136ddd64DBA72'// ]
interface.decodeEventLog( fragment, data [, topics ] ) ⇒ Result
Returns the decoded event values from an event log for fragment (see Specifying Fragments) for the given data with the optional topics.
If topics is not specified, placeholders will be inserted into the result.
Most developers will find the parsing methods more convenient for decoding event data, as they will automatically detect the matching event.
// Decoding log data and topics (the entries in a receipt)constdata="0x0000000000000000000000000000000000000000000000000de0b6b3a7640000";consttopics= ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72","0x000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c"];iface.decodeEventLog("Transfer", data, topics);// [// '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C',// { BigNumber: "1000000000000000000" },// amount: { BigNumber: "1000000000000000000" },// from: '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// to: '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C'// ]
interface.decodeFunctionData( fragment, data ) ⇒ Result
Returns the decoded values from transaction data for fragment (see Specifying Fragments) for the given data.
Most developers will not need this method, but may be useful for debugging or inspecting transactions.
Most developers will also find the parsing methods more convenient for decoding transaction data, as they will automatically detect the matching function.
// Decoding function data (the value of tx.data)const txData = "0x23b872dd0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c0000000000000000000000000000000000000000000000000de0b6b3a7640000";
iface.decodeFunctionData("transferFrom", txData);// [// '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C',// { BigNumber: "1000000000000000000" },// amount: { BigNumber: "1000000000000000000" },// from: '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// to: '0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C'// ]
interface.decodeFunctionResult( fragment, data ) ⇒ Result
Returns the decoded values from the result of a call for fragment (see Specifying Fragments) for the given data.
// Decoding result data (e.g. from an eth_call)resultData ="0x0000000000000000000000000000000000000000000000000de0b6b3a7640000";iface.decodeFunctionResult("balanceOf", resultData)// [// { BigNumber: "1000000000000000000" }// ]// Decoding result data which was caused by a revert// Throws a CALL_EXCEPTION, with extra detailserrorData = "0xf7c3865a0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000000de0b6b3a7640000";
iface.decodeFunctionResult("balanceOf", errorData)// [Error: call revert exception] {// code: 'CALL_EXCEPTION',// errorArgs: [// '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// { BigNumber: "1000000000000000000" },// balance: { BigNumber: "1000000000000000000" },// owner: '0x8ba1f109551bD432803012645Ac136ddd64DBA72'// ],// errorName: 'AccountLocked',// errorSignature: 'AccountLocked(address,uint256)',// method: 'balanceOf(address)',// reason: null// }// Decoding structured data returns a Result object, which// will include all values positionally and if the ABI// included names, values will additionally be available// by their name.resultData = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000000000000000000000000000000000000000000d52696368617264204d6f6f726500000000000000000000000000000000000000";
result =iface.decodeFunctionResult("getUser", resultData);// [// [// 'Richard Moore',// '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// addr: '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// name: 'Richard Moore'// ],// user: [// 'Richard Moore',// '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// addr: '0x8ba1f109551bD432803012645Ac136ddd64DBA72',// name: 'Richard Moore'// ]// ]// Access positionally:// The 0th output parameter, the 0th proerty of the structureresult[0][0];// 'Richard Moore'// Access by name: (only avilable because parameters were named)result.user.name// 'Richard Moore'
Parsing
The functions are generally the most useful for most developers. They will automatically search the ABI for a matching Event or Function and decode the components as a fully specified descriptio
A Result is an array, so each value can be accessed as a positional argument.
Additionally, if values are named, the identical object as its positional value can be accessed by its name.
The name length is however reserved as it is part of the Array, so any named value for this key is renamed to _length. If there is a name collision, only the first is available by its key.