UNPKG

@btc-vision/transaction

Version:

OPNet transaction library allows you to create and sign transactions for the OPNet network.

142 lines 5.76 kB
import shajs from 'sha.js'; import { BinaryReader } from '../buffer/BinaryReader.js'; import { ABIDataTypes } from './ABIDataTypes.js'; import { isAbiStruct, isAbiTuple } from './TupleUtils.js'; export class ABICoder { decodeData(data, types) { const byteReader = new BinaryReader(data); const result = []; for (const type of types) { result.push(this.decodeSingleValue(byteReader, type)); } return result; } encodeSelector(selectorIdentifier) { // first 4 bytes of sha256 hash of the function signature const hash = this.sha256(selectorIdentifier); const selector = hash.subarray(0, 4); // 4 bytes return Array.from(selector, (b) => b.toString(16).padStart(2, '0')).join(''); } numericSelectorToHex(selector) { return selector.toString(16); } /** * Decodes a single value from the reader based on the ABI type. * Supports ABIDataTypes enum values, tuple arrays, and struct objects. */ decodeSingleValue(reader, type) { if (isAbiTuple(type)) { // Single-element tuple: unwrap to flat array const firstType = type[0]; if (type.length === 1 && firstType !== undefined) { return this.decodeArray(reader, firstType); } return this.decodeTuple(reader, type); } if (isAbiStruct(type)) { return this.decodeStruct(reader, type); } switch (type) { case ABIDataTypes.UINT8: return reader.readU8(); case ABIDataTypes.UINT16: return reader.readU16(); case ABIDataTypes.UINT32: return reader.readU32(); case ABIDataTypes.BYTES4: return reader.readBytes(4); case ABIDataTypes.BYTES32: return reader.readBytes(32); case ABIDataTypes.BOOL: return reader.readBoolean(); case ABIDataTypes.ADDRESS: return reader.readAddress(); case ABIDataTypes.STRING: return reader.readStringWithLength(); case ABIDataTypes.UINT128: return reader.readU128(); case ABIDataTypes.UINT256: return reader.readU256(); case ABIDataTypes.INT8: return reader.readI8(); case ABIDataTypes.INT16: return reader.readI16(); case ABIDataTypes.INT32: return reader.readI32(); case ABIDataTypes.INT64: return reader.readI64(); case ABIDataTypes.INT128: return reader.readI128(); case ABIDataTypes.EXTENDED_ADDRESS: return reader.readExtendedAddress(); case ABIDataTypes.ADDRESS_UINT256_TUPLE: return reader.readAddressValueTuple(); case ABIDataTypes.EXTENDED_ADDRESS_UINT256_TUPLE: return reader.readExtendedAddressMapU256(); case ABIDataTypes.SCHNORR_SIGNATURE: return reader.readSchnorrSignature(); case ABIDataTypes.BYTES: return reader.readBytesWithLength(); case ABIDataTypes.UINT64: return reader.readU64(); case ABIDataTypes.ARRAY_OF_ADDRESSES: return reader.readAddressArray(); case ABIDataTypes.ARRAY_OF_EXTENDED_ADDRESSES: return reader.readExtendedAddressArray(); case ABIDataTypes.ARRAY_OF_UINT256: return reader.readU256Array(); case ABIDataTypes.ARRAY_OF_UINT128: return reader.readU128Array(); case ABIDataTypes.ARRAY_OF_UINT64: return reader.readU64Array(); case ABIDataTypes.ARRAY_OF_UINT32: return reader.readU32Array(); case ABIDataTypes.ARRAY_OF_UINT16: return reader.readU16Array(); case ABIDataTypes.ARRAY_OF_UINT8: return reader.readU8Array(); case ABIDataTypes.ARRAY_OF_STRING: return reader.readStringArray(); case ABIDataTypes.ARRAY_OF_BYTES: return reader.readBytesArray(); case ABIDataTypes.ARRAY_OF_BUFFERS: return reader.readArrayOfBuffer(); default: throw new Error(`Unsupported ABI type: ${type}`); } } /** Decodes a single-element tuple as a flat typed array (u16 count + values). */ decodeArray(reader, elementType) { const count = reader.readU16(); const result = []; for (let i = 0; i < count; i++) { result.push(this.decodeSingleValue(reader, elementType)); } return result; } /** Decodes a multi-element tuple as array of tuple entries (u16 count + entries). */ decodeTuple(reader, types) { const count = reader.readU16(); const result = []; for (let i = 0; i < count; i++) { const entry = []; for (const fieldType of types) { entry.push(this.decodeSingleValue(reader, fieldType)); } result.push(entry); } return result; } /** Decodes a struct as a single object with named fields (inline, no count prefix). */ decodeStruct(reader, struct) { const entry = {}; for (const [name, fieldType] of Object.entries(struct)) { entry[name] = this.decodeSingleValue(reader, fieldType); } return entry; } sha256(buffer) { return new Uint8Array(new shajs.sha256().update(buffer).digest()); } } //# sourceMappingURL=ABICoder.js.map