UNPKG

dp-contract-proxy-kit

Version:

Enable batched transactions and contract account interactions using a unique deterministic Gnosis Safe.

203 lines (174 loc) 5.88 kB
import BigNumber from 'bignumber.js' import { Abi, Address } from '../utils/basicTypes' import { joinHexData } from '../utils/hexData' import { CallOptions, EthCallTx, EthSendTx, SendOptions, TransactionResult } from '../utils/transactions' export interface Contract { address: Address call(methodName: string, params: any[], options?: CallOptions): Promise<any> send(methodName: string, params: any[], options?: SendOptions): Promise<TransactionResult> estimateGas(methodName: string, params: any[], options?: CallOptions): Promise<number> encode(methodName: string, params: any[]): string } abstract class EthLibAdapter { /** * Returns the keccak256 hash of the data. * * @param data - Desired data * @returns The keccak256 of the data */ abstract keccak256(data: string): string /** * Encodes a function parameters based on its JSON interface object. * * @param types - An array with the types or a JSON interface of a function * @param values - The parameters to encode * @returns The ABI encoded parameters */ abstract abiEncode(types: string[], values: any[]): string /** * Decodes ABI encoded parameters to is JavaScript types. * * @param types - An array with the types or a JSON interface outputs array * @param data - The ABI byte code to decode * @returns The ABI encoded parameters */ abstract abiDecode(types: string[], data: string): any[] /** * Deterministically returns the address where a contract will be deployed. * * @param deployer - Account that deploys the contract * @param salt - Salt * @param initCode - Code to be deployed * @returns The address where the contract will be deployed */ abstract calcCreate2Address(deployer: Address, salt: string, initCode: string): string /** * Returns the current provider * * @returns The current provider */ abstract getProvider(): any /** * Sends a network request via JSON-RPC. * * @param method - JSON-RPC method * @param params - Params * @returns The request response */ abstract providerSend(method: string, params: any[]): Promise<any> /** * Signs data using a specific account. * * @param message - Data to sign * @param ownerAccount - Address to sign the data with * @returns The signature */ abstract signMessage(message: string, ownerAccount: Address): Promise<string> /** * Returns the current network ID. * * @returns The network ID */ abstract getNetworkId(): Promise<number> /** * Returns the default account used as the default "from" property. * * @returns The default account address */ abstract getAccount(): Promise<Address> /** * Returns the balance of an address. * * @param address - The desired address * @returns The balance of the address */ abstract getBalance(address: Address): Promise<BigNumber> /** * Returns the code at a specific address. * * @param address - The desired address * @returns The code of the contract */ abstract getCode(address: Address): Promise<string> /** * Returns a block matching the block number or block hash. * * @param blockHashOrBlockNumber - The block number or block hash * @returns The block object */ abstract getBlock(blockHashOrBlockNumber: string | number): Promise<{ [property: string]: any }> /** * Returns an instance of a contract. * * @param abi - ABI of the desired contract * @param address - Contract address * @returns The contract instance */ abstract getContract(abi: Abi, address?: Address): Contract /** * Returns the revert reason when a call fails. * * @param tx - Transaction to execute * @param block - Block number * @returns The revert data when the call fails */ abstract getCallRevertData(tx: EthCallTx, block: string | number): Promise<string> /** * Sends a transaction to the network. * * @param tx - Transaction to send * @returns The transaction response */ abstract ethSendTransaction(tx: EthSendTx): Promise<TransactionResult> /** * Formats transaction result depending on the current provider. * * @param txHash - Transaction hash * @param tx - Transaction response * @returns The formatted transaction response */ abstract toSafeRelayTxResult(txHash: string, tx: Record<string, any>): Promise<TransactionResult> abstract toRocksideRelayTxResult(tx: Record<string, any>): Promise<TransactionResult> abiEncodePacked(...params: { type: string; value: any }[]): string { return joinHexData( params.map(({ type, value }) => { const encoded = this.abiEncode([type], [value]) if (type === 'bytes' || type === 'string') { const bytesLength = parseInt(encoded.slice(66, 130), 16) return encoded.slice(130, 130 + 2 * bytesLength) } let typeMatch = type.match(/^(?:u?int\d*|bytes\d+|address)\[\]$/) if (typeMatch) { return encoded.slice(130) } if (type.startsWith('bytes')) { const bytesLength = parseInt(type.slice(5)) return encoded.slice(2, 2 + 2 * bytesLength) } typeMatch = type.match(/^u?int(\d*)$/) if (typeMatch) { if (typeMatch[1] !== '') { const bytesLength = parseInt(typeMatch[1]) / 8 return encoded.slice(-2 * bytesLength) } return encoded.slice(-64) } if (type === 'address') { return encoded.slice(-40) } throw new Error(`unsupported type ${type}`) }) ) } decodeError(revertData: string): string { if (!revertData.startsWith('0x08c379a0')) throw new Error('Unrecognized error format') return this.abiDecode(['string'], `0x${revertData.slice(10)}`)[0] } } export default EthLibAdapter