UNPKG

opnet

Version:

The perfect library for building Bitcoin-based applications.

664 lines (483 loc) 12.7 kB
# ABI Data Types This guide covers the supported data types in OPNet ABIs. ## Overview ABIDataTypes define how values are encoded and decoded when calling contracts. Each type maps to a specific binary representation. The `type` field of a `BitcoinAbiValue` accepts three forms: - **Simple**: An `ABIDataTypes` enum value (e.g., `ABIDataTypes.UINT256`) - **Tuple**: An array of `AbiType` (e.g., `[ABIDataTypes.ADDRESS, ABIDataTypes.UINT256]`) - **Struct**: An object with named fields (e.g., `{ minted: ABIDataTypes.UINT256, active: ABIDataTypes.BOOL }`) --- ## ABIDataTypes Enum ```typescript enum ABIDataTypes { // Unsigned integers UINT8 = 'UINT8', UINT16 = 'UINT16', UINT32 = 'UINT32', UINT64 = 'UINT64', UINT128 = 'UINT128', UINT256 = 'UINT256', // Signed integers INT8 = 'INT8', INT16 = 'INT16', INT32 = 'INT32', INT64 = 'INT64', INT128 = 'INT128', // Basic types BOOL = 'BOOL', ADDRESS = 'ADDRESS', EXTENDED_ADDRESS = 'EXTENDED_ADDRESS', STRING = 'STRING', BYTES4 = 'BYTES4', BYTES32 = 'BYTES32', BYTES = 'BYTES', // Tuples/Maps ADDRESS_UINT256_TUPLE = 'ADDRESS_UINT256_TUPLE', EXTENDED_ADDRESS_UINT256_TUPLE = 'EXTENDED_ADDRESS_UINT256_TUPLE', // Signatures SCHNORR_SIGNATURE = 'SCHNORR_SIGNATURE', // Arrays ARRAY_OF_ADDRESSES = 'ARRAY_OF_ADDRESSES', ARRAY_OF_EXTENDED_ADDRESSES = 'ARRAY_OF_EXTENDED_ADDRESSES', ARRAY_OF_UINT256 = 'ARRAY_OF_UINT256', ARRAY_OF_UINT128 = 'ARRAY_OF_UINT128', ARRAY_OF_UINT64 = 'ARRAY_OF_UINT64', ARRAY_OF_UINT32 = 'ARRAY_OF_UINT32', ARRAY_OF_UINT16 = 'ARRAY_OF_UINT16', ARRAY_OF_UINT8 = 'ARRAY_OF_UINT8', ARRAY_OF_STRING = 'ARRAY_OF_STRING', ARRAY_OF_BYTES = 'ARRAY_OF_BYTES', ARRAY_OF_BUFFERS = 'ARRAY_OF_BUFFERS', } ``` --- ## Type Mapping ### TypeScript to ABI Types | TypeScript Type | ABI Type | Notes | |----------------|----------|-------| | `number` | `UINT8`, `UINT16`, `UINT32`, `INT8`, `INT16`, `INT32` | Small integers | | `bigint` | `UINT64`, `UINT128`, `UINT256`, `INT64`, `INT128` | Large integers | | `boolean` | `BOOL` | True/false | | `string` | `STRING` | UTF-8 text | | `Uint8Array` | `BYTES`, `BYTES4`, `BYTES32` | Raw bytes | | `Address` | `ADDRESS` | OPNet address | | `Address` | `EXTENDED_ADDRESS` | Extended address type | | `SchnorrSignature` | `SCHNORR_SIGNATURE` | Schnorr signature | | `AddressMap<bigint>` | `ADDRESS_UINT256_TUPLE` | Address-to-uint256 map | | `ExtendedAddressMap<bigint>` | `EXTENDED_ADDRESS_UINT256_TUPLE` | Extended-address-to-uint256 map | | `Address[]` | `ARRAY_OF_ADDRESSES`, `ARRAY_OF_EXTENDED_ADDRESSES` | Arrays of addresses | | `bigint[]` | `ARRAY_OF_UINT256`, `ARRAY_OF_UINT128`, `ARRAY_OF_UINT64` | Arrays of large integers | | `number[]` | `ARRAY_OF_UINT32`, `ARRAY_OF_UINT16`, `ARRAY_OF_UINT8` | Arrays of small integers | | `string[]` | `ARRAY_OF_STRING` | Array of strings | | `Uint8Array[]` | `ARRAY_OF_BYTES`, `ARRAY_OF_BUFFERS` | Arrays of byte arrays | --- ## Unsigned Integers ### UINT8 8-bit unsigned integer (0 to 255). ```typescript { name: 'decimals', type: ABIDataTypes.UINT8, } ``` **TypeScript**: `number` ### UINT16 16-bit unsigned integer (0 to 65,535). ```typescript { name: 'smallValue', type: ABIDataTypes.UINT16, } ``` **TypeScript**: `number` ### UINT32 32-bit unsigned integer (0 to 4,294,967,295). ```typescript { name: 'mediumValue', type: ABIDataTypes.UINT32, } ``` **TypeScript**: `number` ### UINT64 64-bit unsigned integer. ```typescript { name: 'timestamp', type: ABIDataTypes.UINT64, } ``` **TypeScript**: `bigint` ### UINT128 128-bit unsigned integer. ```typescript { name: 'largeValue', type: ABIDataTypes.UINT128, } ``` **TypeScript**: `bigint` ### UINT256 256-bit unsigned integer (most common for token amounts). ```typescript { name: 'amount', type: ABIDataTypes.UINT256, } ``` **TypeScript**: `bigint` --- ## Signed Integers ### INT8 to INT128 Signed versions of the unsigned integer types (INT8, INT16, INT32, INT64, INT128). ```typescript { name: 'signedAmount', type: ABIDataTypes.INT128, } ``` **TypeScript**: `number` (INT8, INT16, INT32) or `bigint` (INT64, INT128) --- ## Boolean ### BOOL Boolean true or false value. ```typescript { name: 'isActive', type: ABIDataTypes.BOOL, } ``` **TypeScript**: `boolean` --- ## Bytes ### BYTES Variable-length byte array. ```typescript { name: 'data', type: ABIDataTypes.BYTES, } ``` **TypeScript**: `Uint8Array` ### BYTES4 Fixed 4-byte array (common for function selectors). ```typescript { name: 'selector', type: ABIDataTypes.BYTES4, } ``` **TypeScript**: `Uint8Array` (4 bytes) ### BYTES32 Fixed 32-byte array (common for hashes). ```typescript { name: 'hash', type: ABIDataTypes.BYTES32, } ``` **TypeScript**: `Uint8Array` (32 bytes) --- ## String ### STRING UTF-8 encoded string. ```typescript { name: 'tokenName', type: ABIDataTypes.STRING, } ``` **TypeScript**: `string` --- ## Address ### ADDRESS OPNet address type. ```typescript { name: 'recipient', type: ABIDataTypes.ADDRESS, } ``` **TypeScript**: `Address` (from `@btc-vision/transaction`) ### EXTENDED_ADDRESS Extended address type with additional metadata. ```typescript { name: 'extRecipient', type: ABIDataTypes.EXTENDED_ADDRESS, } ``` **TypeScript**: `Address` (from `@btc-vision/transaction`) --- ## Tuples/Maps ### ADDRESS_UINT256_TUPLE Built-in tuple mapping addresses to uint256 values. Used for address-keyed maps (e.g., balance snapshots). ```typescript { name: 'balances', type: ABIDataTypes.ADDRESS_UINT256_TUPLE, } ``` **TypeScript**: `AddressMap<bigint>` (from `@btc-vision/transaction`) ### EXTENDED_ADDRESS_UINT256_TUPLE Same as `ADDRESS_UINT256_TUPLE` but uses extended addresses. ```typescript { name: 'extBalances', type: ABIDataTypes.EXTENDED_ADDRESS_UINT256_TUPLE, } ``` **TypeScript**: `ExtendedAddressMap<bigint>` (from `@btc-vision/transaction`) --- ## Signatures ### SCHNORR_SIGNATURE Schnorr signature type for on-chain signature verification. ```typescript { name: 'signature', type: ABIDataTypes.SCHNORR_SIGNATURE, } ``` **TypeScript**: `SchnorrSignature` (from `@btc-vision/transaction`) --- ## Arrays ### Array Types Built-in arrays of basic types: ```typescript // Array of addresses { name: 'recipients', type: ABIDataTypes.ARRAY_OF_ADDRESSES, } // Array of extended addresses { name: 'extRecipients', type: ABIDataTypes.ARRAY_OF_EXTENDED_ADDRESSES, } // Array of amounts { name: 'amounts', type: ABIDataTypes.ARRAY_OF_UINT256, } // Array of strings { name: 'names', type: ABIDataTypes.ARRAY_OF_STRING, } // Array of byte arrays { name: 'buffers', type: ABIDataTypes.ARRAY_OF_BUFFERS, } ``` **TypeScript**: `Address[]`, `bigint[]`, `number[]`, `string[]`, `Uint8Array[]`, etc. --- ## Tuples (Custom Composite Types) Beyond the built-in `ABIDataTypes` enum, the `type` field of a `BitcoinAbiValue` can be an **array of types** to define a tuple. Tuples represent ordered, multi-field composite values. ### Single-Element Tuple (Typed Array) A single-element tuple `[T]` encodes as a **flat array** of that type: ```typescript { name: 'scores', type: [ABIDataTypes.UINT256], } ``` **TypeScript**: `bigint[]` This is equivalent to using a built-in `ARRAY_OF_*` type, but works for any type including nested tuples and structs. **Encoding**: writes count (u16), then each element in sequence. **Passing values**: ```typescript const result = await contract.getScores(); // result.properties.scores bigint[] await contract.setScores([100n, 200n, 300n], txParams); ``` ### Multi-Element Tuple (Array of Ordered Entries) A multi-element tuple `[T1, T2, ...]` encodes as an **array of ordered entries**, where each entry contains one value per tuple element: ```typescript { name: 'transfers', type: [ABIDataTypes.ADDRESS, ABIDataTypes.UINT256], } ``` **TypeScript**: `[Address, bigint][]` **Encoding**: writes count (u16), then for each entry writes the fields in order. **Passing values**: ```typescript // Each entry is an array matching the tuple shape await contract.batchTransfer( [ [recipientA, 100n], [recipientB, 200n], ], txParams ); // Reading results const result = await contract.getTransfers(); // result.properties.transfers [Address, bigint][] for (const [addr, amount] of result.properties.transfers) { console.log(`${addr}: ${amount}`); } ``` --- ## Structs (Named Field Objects) A **struct** is an object mapping field names to types. Unlike tuples, structs encode a **single inline value** with named fields (no count prefix, no array wrapping). ```typescript { name: 'status', type: { minted: ABIDataTypes.UINT256, active: ABIDataTypes.BOOL, }, } ``` **TypeScript**: `{ minted: bigint; active: boolean }` **Encoding**: writes each field in declaration order (no count prefix). **Passing values**: ```typescript // Reading a struct output const result = await contract.getStatus(); // result.properties.status { minted: bigint, active: boolean } console.log(result.properties.status.minted); console.log(result.properties.status.active); // Passing a struct input await contract.setStatus( { minted: 1000n, active: true }, txParams ); ``` ### Nested Structs and Tuples Structs and tuples can be nested arbitrarily: ```typescript // Struct with a nested tuple field { name: 'pool', type: { token: ABIDataTypes.ADDRESS, reserves: [ABIDataTypes.UINT256], // array of uint256 }, } // TypeScript: { token: Address; reserves: bigint[] } // Tuple with a struct element { name: 'entries', type: [ABIDataTypes.ADDRESS, { amount: ABIDataTypes.UINT256, active: ABIDataTypes.BOOL }], } // TypeScript: [Address, { amount: bigint; active: boolean }][] ``` --- ## Common Type Patterns ### Token Amount ```typescript { name: 'amount', type: ABIDataTypes.UINT256, } ``` ### Address Parameters ```typescript { name: 'from', type: ABIDataTypes.ADDRESS, }, { name: 'to', type: ABIDataTypes.ADDRESS, } ``` ### Metadata Strings ```typescript { name: 'name', type: ABIDataTypes.STRING, }, { name: 'symbol', type: ABIDataTypes.STRING, } ``` ### Hash Values ```typescript { name: 'txHash', type: ABIDataTypes.BYTES32, } ``` ### Batch Operations ```typescript { name: 'recipients', type: ABIDataTypes.ARRAY_OF_ADDRESSES, }, { name: 'amounts', type: ABIDataTypes.ARRAY_OF_UINT256, } ``` --- ## Example ABI Definitions ### Transfer Function ```typescript { name: 'transfer', type: BitcoinAbiTypes.Function, inputs: [ { name: 'to', type: ABIDataTypes.ADDRESS }, { name: 'amount', type: ABIDataTypes.UINT256 }, ], outputs: [], } ``` ### Balance Query ```typescript { name: 'balanceOf', type: BitcoinAbiTypes.Function, constant: true, inputs: [ { name: 'owner', type: ABIDataTypes.ADDRESS }, ], outputs: [ { name: 'balance', type: ABIDataTypes.UINT256 }, ], } ``` ### Transfer Event ```typescript { name: 'Transferred', type: BitcoinAbiTypes.Event, values: [ { name: 'from', type: ABIDataTypes.ADDRESS }, { name: 'to', type: ABIDataTypes.ADDRESS }, { name: 'amount', type: ABIDataTypes.UINT256 }, ], } ``` ### Batch Transfer ```typescript { name: 'batchTransfer', type: BitcoinAbiTypes.Function, inputs: [ { name: 'recipients', type: ABIDataTypes.ARRAY_OF_ADDRESSES }, { name: 'amounts', type: ABIDataTypes.ARRAY_OF_UINT256 }, ], outputs: [], } ``` --- ## Best Practices 1. **Use Appropriate Sizes**: Choose the smallest type that fits your data 2. **UINT256 for Tokens**: Always use UINT256 for token amounts 3. **ADDRESS for Addresses**: Use ADDRESS type, not BYTES32 4. **Arrays for Batches**: Use array types for batch operations 5. **BYTES32 for Hashes**: Use BYTES32 for fixed-size hashes 6. **Structs for Named Data**: Use structs when fields have distinct meanings 7. **Tuples for Tabular Data**: Use multi-element tuples for arrays of grouped values (e.g., address+amount pairs) --- ## Next Steps - [ABI Overview](./abi-overview.md) - ABI system overview - [OP20 ABI](./op20-abi.md) - Token standard - [Custom ABIs](./custom-abis.md) - Creating custom ABIs --- [ Previous: ABI Overview](./abi-overview.md) | [Next: OP20 ABI ](./op20-abi.md)