UNPKG

@graphprotocol/graph-ts

Version:

TypeScript/AssemblyScript library for writing subgraph mappings for The Graph

730 lines (651 loc) 22.4 kB
import { Bytes, Wrapped } from '../common/collections'; import { Address, BigInt } from '../common/numbers'; /** Host Ethereum interface */ export declare namespace ethereum { function call(call: SmartContractCall): Array<Value> | null; function getBalance(address: Address): BigInt; function hasCode(address: Address): Wrapped<bool>; function encode(token: Value): Bytes | null; function decode(types: string, data: Bytes): Value | null; } export namespace ethereum { /** Type hint for Ethereum values. */ export enum ValueKind { ADDRESS = 0, FIXED_BYTES = 1, BYTES = 2, INT = 3, UINT = 4, BOOL = 5, STRING = 6, FIXED_ARRAY = 7, ARRAY = 8, TUPLE = 9, } /** * Pointer type for Ethereum value data. * * Big enough to fit any pointer or native `this.data`. */ export type ValuePayload = u64; /** * A dynamically typed value used when accessing Ethereum data. */ export class Value { constructor( public kind: ValueKind, public data: ValuePayload, ) {} @operator('<') lt(_: Value): boolean { abort("Less than operator isn't supported in Value"); return false; } @operator('>') gt(_: Value): boolean { abort("Greater than operator isn't supported in Value"); return false; } toAddress(): Address { assert(this.kind == ValueKind.ADDRESS, 'Ethereum value is not an address'); return changetype<Address>(this.data as u32); } toBoolean(): boolean { assert(this.kind == ValueKind.BOOL, 'Ethereum value is not a boolean.'); return this.data != 0; } toBytes(): Bytes { assert( this.kind == ValueKind.FIXED_BYTES || this.kind == ValueKind.BYTES, 'Ethereum value is not bytes.', ); return changetype<Bytes>(this.data as u32); } toI32(): i32 { assert( this.kind == ValueKind.INT || this.kind == ValueKind.UINT, 'Ethereum value is not an int or uint.', ); const bigInt = changetype<BigInt>(this.data as u32); return bigInt.toI32(); } toBigInt(): BigInt { assert( this.kind == ValueKind.INT || this.kind == ValueKind.UINT, 'Ethereum value is not an int or uint.', ); return changetype<BigInt>(this.data as u32); } toString(): string { assert(this.kind == ValueKind.STRING, 'Ethereum value is not a string.'); return changetype<string>(this.data as u32); } toArray(): Array<Value> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array.', ); return changetype<Array<Value>>(this.data as u32); } toTuple(): Tuple { assert(this.kind == ValueKind.TUPLE, 'Ethereum value is not a tuple.'); return changetype<Tuple>(this.data as u32); } toMatrix(): Array<Array<Value>> { const valueArray = this.toArray(); const out = new Array<Array<Value>>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = valueArray[i].toArray(); } return out; } toTupleArray<T extends Tuple>(): Array<T> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array.', ); const valueArray = this.toArray(); const out = new Array<T>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = changetype<T>(valueArray[i].toTuple()); } return out; } toTupleMatrix<T extends Tuple>(): Array<Array<T>> { const valueMatrix = this.toMatrix(); const out = new Array<Array<T>>(valueMatrix.length); for (let i: i32 = 0; i < valueMatrix.length; i++) { out[i] = new Array<T>(valueMatrix[i].length); for (let j: i32 = 0; j < valueMatrix[i].length; j++) { out[i][j] = changetype<T>(valueMatrix[i][j].toTuple()); } } return out; } toBooleanArray(): Array<boolean> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array or fixed array.', ); const valueArray = this.toArray(); const out = new Array<boolean>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = valueArray[i].toBoolean(); } return out; } toBytesArray(): Array<Bytes> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array or fixed array.', ); const valueArray = this.toArray(); const out = new Array<Bytes>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = valueArray[i].toBytes(); } return out; } toAddressArray(): Array<Address> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array or fixed array.', ); const valueArray = this.toArray(); const out = new Array<Address>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = valueArray[i].toAddress(); } return out; } toStringArray(): Array<string> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array or fixed array.', ); const valueArray = this.toArray(); const out = new Array<string>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = valueArray[i].toString(); } return out; } toI32Array(): Array<i32> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array or fixed array.', ); const valueArray = this.toArray(); const out = new Array<i32>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = valueArray[i].toI32(); } return out; } toBigIntArray(): Array<BigInt> { assert( this.kind == ValueKind.ARRAY || this.kind == ValueKind.FIXED_ARRAY, 'Ethereum value is not an array or fixed array.', ); const valueArray = this.toArray(); const out = new Array<BigInt>(valueArray.length); for (let i: i32 = 0; i < valueArray.length; i++) { out[i] = valueArray[i].toBigInt(); } return out; } toBooleanMatrix(): Array<Array<boolean>> { const valueMatrix = this.toMatrix(); const out = new Array<Array<boolean>>(valueMatrix.length); for (let i: i32 = 0; i < valueMatrix.length; i++) { out[i] = new Array<boolean>(valueMatrix[i].length); for (let j: i32 = 0; j < valueMatrix[i].length; j++) { out[i][j] = valueMatrix[i][j].toBoolean(); } } return out; } toBytesMatrix(): Array<Array<Bytes>> { const valueMatrix = this.toMatrix(); const out = new Array<Array<Bytes>>(valueMatrix.length); for (let i: i32 = 0; i < valueMatrix.length; i++) { out[i] = new Array<Bytes>(valueMatrix[i].length); for (let j: i32 = 0; j < valueMatrix[i].length; j++) { out[i][j] = valueMatrix[i][j].toBytes(); } } return out; } toAddressMatrix(): Array<Array<Address>> { const valueMatrix = this.toMatrix(); const out = new Array<Array<Address>>(valueMatrix.length); for (let i: i32 = 0; i < valueMatrix.length; i++) { out[i] = new Array<Address>(valueMatrix[i].length); for (let j: i32 = 0; j < valueMatrix[i].length; j++) { out[i][j] = valueMatrix[i][j].toAddress(); } } return out; } toStringMatrix(): Array<Array<string>> { const valueMatrix = this.toMatrix(); const out = new Array<Array<string>>(valueMatrix.length); for (let i: i32 = 0; i < valueMatrix.length; i++) { out[i] = new Array<string>(valueMatrix[i].length); for (let j: i32 = 0; j < valueMatrix[i].length; j++) { out[i][j] = valueMatrix[i][j].toString(); } } return out; } toI32Matrix(): Array<Array<i32>> { const valueMatrix = this.toMatrix(); const out = new Array<Array<i32>>(valueMatrix.length); for (let i: i32 = 0; i < valueMatrix.length; i++) { out[i] = new Array<i32>(valueMatrix[i].length); for (let j: i32 = 0; j < valueMatrix[i].length; j++) { out[i][j] = valueMatrix[i][j].toI32(); } } return out; } toBigIntMatrix(): Array<Array<BigInt>> { const valueMatrix = this.toMatrix(); const out = new Array<Array<BigInt>>(valueMatrix.length); for (let i: i32 = 0; i < valueMatrix.length; i++) { out[i] = new Array<BigInt>(valueMatrix[i].length); for (let j: i32 = 0; j < valueMatrix[i].length; j++) { out[i][j] = valueMatrix[i][j].toBigInt(); } } return out; } static fromAddress(address: Address): Value { assert(address.length == 20, 'Address must contain exactly 20 bytes'); return new Value(ValueKind.ADDRESS, changetype<u32>(address)); } static fromBoolean(b: boolean): Value { return new Value(ValueKind.BOOL, b ? 1 : 0); } static fromBytes(bytes: Bytes): Value { return new Value(ValueKind.BYTES, changetype<u32>(bytes)); } static fromFixedBytes(bytes: Bytes): Value { return new Value(ValueKind.FIXED_BYTES, changetype<u32>(bytes)); } static fromI32(i: i32): Value { return new Value(ValueKind.INT, changetype<u32>(BigInt.fromI32(i))); } static fromSignedBigInt(i: BigInt): Value { return new Value(ValueKind.INT, changetype<u32>(i)); } static fromUnsignedBigInt(i: BigInt): Value { return new Value(ValueKind.UINT, changetype<u32>(i)); } static fromString(s: string): Value { return new Value(ValueKind.STRING, changetype<u32>(s)); } static fromArray(values: Array<Value>): Value { return new Value(ValueKind.ARRAY, changetype<u32>(values)); } static fromFixedSizedArray(values: Array<Value>): Value { return new Value(ValueKind.FIXED_ARRAY, changetype<u32>(values)); } static fromTuple(values: Tuple): Value { return new Value(ValueKind.TUPLE, changetype<u32>(values)); } static fromMatrix(values: Array<Array<Value>>): Value { const innerOut = new Array<Value>(values.length); for (let i: i32 = 0; i < innerOut.length; i++) { innerOut[i] = Value.fromArray(values[i]); } return Value.fromArray(innerOut); } static fromTupleArray(values: Array<Tuple>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromTuple(values[i]); } return Value.fromArray(out); } static fromTupleMatrix(values: Array<Array<Tuple>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromTuple(values[i][j]); } } return Value.fromMatrix(out); } static fromBooleanArray(values: Array<boolean>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromBoolean(values[i]); } return Value.fromArray(out); } static fromBytesArray(values: Array<Bytes>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromBytes(values[i]); } return Value.fromArray(out); } static fromFixedBytesArray(values: Array<Bytes>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromFixedBytes(values[i]); } return Value.fromArray(out); } static fromAddressArray(values: Array<Address>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromAddress(values[i]); } return Value.fromArray(out); } static fromStringArray(values: Array<string>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromString(values[i]); } return Value.fromArray(out); } static fromI32Array(values: Array<i32>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromI32(values[i]); } return Value.fromArray(out); } static fromSignedBigIntArray(values: Array<BigInt>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromSignedBigInt(values[i]); } return Value.fromArray(out); } static fromUnsignedBigIntArray(values: Array<BigInt>): Value { const out = new Array<Value>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = Value.fromUnsignedBigInt(values[i]); } return Value.fromArray(out); } static fromBooleanMatrix(values: Array<Array<boolean>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromBoolean(values[i][j]); } } return Value.fromMatrix(out); } static fromBytesMatrix(values: Array<Array<Bytes>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromBytes(values[i][j]); } } return Value.fromMatrix(out); } static fromFixedBytesMatrix(values: Array<Array<Bytes>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromFixedBytes(values[i][j]); } } return Value.fromMatrix(out); } static fromAddressMatrix(values: Array<Array<Address>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromAddress(values[i][j]); } } return Value.fromMatrix(out); } static fromStringMatrix(values: Array<Array<string>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromString(values[i][j]); } } return Value.fromMatrix(out); } static fromI32Matrix(values: Array<Array<i32>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromI32(values[i][j]); } } return Value.fromMatrix(out); } static fromSignedBigIntMatrix(values: Array<Array<BigInt>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromSignedBigInt(values[i][j]); } } return Value.fromMatrix(out); } static fromUnsignedBigIntMatrix(values: Array<Array<BigInt>>): Value { const out = new Array<Array<Value>>(values.length); for (let i: i32 = 0; i < values.length; i++) { out[i] = new Array<Value>(values[i].length); for (let j: i32 = 0; j < values[i].length; j++) { out[i][j] = Value.fromUnsignedBigInt(values[i][j]); } } return Value.fromMatrix(out); } } /** * Common representation for Ethereum tuples / Solidity structs. * * This base class stores the tuple/struct values in an array. The Graph CLI * code generation then creates subclasses that provide named getters to * access the members by name. */ export class Tuple extends Array<Value> {} /** * An Ethereum block. */ export class Block { constructor( public hash: Bytes, public parentHash: Bytes, public unclesHash: Bytes, public author: Address, public stateRoot: Bytes, public transactionsRoot: Bytes, public receiptsRoot: Bytes, public number: BigInt, public gasUsed: BigInt, public gasLimit: BigInt, public timestamp: BigInt, public difficulty: BigInt, public totalDifficulty: BigInt, public size: BigInt | null, public baseFeePerGas: BigInt | null, ) {} } /** * An Ethereum transaction. */ export class Transaction { constructor( public hash: Bytes, public index: BigInt, public from: Address, public to: Address | null, public value: BigInt, public gasLimit: BigInt, public gasPrice: BigInt, public input: Bytes, public nonce: BigInt, ) {} } /** * An Ethereum transaction receipt. */ export class TransactionReceipt { constructor( public transactionHash: Bytes, public transactionIndex: BigInt, public blockHash: Bytes, public blockNumber: BigInt, public cumulativeGasUsed: BigInt, public gasUsed: BigInt, public contractAddress: Address, public logs: Array<Log>, public status: BigInt, public root: Bytes, public logsBloom: Bytes, ) {} } /** * An Ethereum event log. */ export class Log { constructor( public address: Address, public topics: Array<Bytes>, public data: Bytes, public blockHash: Bytes, public blockNumber: Bytes, public transactionHash: Bytes, public transactionIndex: BigInt, public logIndex: BigInt, public transactionLogIndex: BigInt, public logType: string, public removed: Wrapped<bool> | null, ) {} } /** * Common representation for Ethereum smart contract calls. */ export class Call { constructor( public to: Address, public from: Address, public block: Block, public transaction: Transaction, public inputValues: Array<EventParam>, public outputValues: Array<EventParam>, ) {} } /** * Common representation for Ethereum smart contract events. */ export class Event { constructor( public address: Address, public logIndex: BigInt, public transactionLogIndex: BigInt, public logType: string | null, public block: Block, public transaction: Transaction, public parameters: Array<EventParam>, public receipt: TransactionReceipt | null, ) {} } /** * A dynamically-typed Ethereum event parameter. */ export class EventParam { constructor( public name: string, public value: Value, ) {} } export class SmartContractCall { contractName: string; contractAddress: Address; functionName: string; functionSignature: string; functionParams: Array<Value>; constructor( contractName: string, contractAddress: Address, functionName: string, functionSignature: string, functionParams: Array<Value>, ) { this.contractName = contractName; this.contractAddress = contractAddress; this.functionName = functionName; this.functionSignature = functionSignature; this.functionParams = functionParams; } } /** * Low-level interaction with Ethereum smart contracts */ export class SmartContract { _name: string; _address: Address; protected constructor(name: string, address: Address) { this._name = name; this._address = address; } call(name: string, signature: string, params: Array<Value>): Array<Value> { const call = new SmartContractCall(this._name, this._address, name, signature, params); const result = ethereum.call(call); assert( result != null, 'Call reverted, probably because an `assert` or `require` in the contract failed, ' + 'consider using `try_' + name + '` to handle this in the mapping.', ); return changetype<Array<Value>>(result); } tryCall(name: string, signature: string, params: Array<Value>): CallResult<Array<Value>> { const call = new SmartContractCall(this._name, this._address, name, signature, params); const result = ethereum.call(call); if (result == null) { return new CallResult(); } return CallResult.fromValue(changetype<Array<Value>>(result)); } } export class CallResult<T> { // `null` indicates a reverted call. private _value: Wrapped<T> | null; constructor() { this._value = null; } static fromValue<T>(value: T): CallResult<T> { const result = new CallResult<T>(); result._value = new Wrapped(value); return result; } get reverted(): bool { return this._value == null; } get value(): T { assert( !this.reverted, 'accessed value of a reverted call, ' + 'please check the `reverted` field before accessing the `value` field', ); return changetype<Wrapped<T>>(this._value).inner; } } }