@graphprotocol/graph-ts
Version:
TypeScript/AssemblyScript library for writing subgraph mappings for The Graph
730 lines (651 loc) • 22.4 kB
text/typescript
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,
) {}
lt(_: Value): boolean {
abort("Less than operator isn't supported in Value");
return false;
}
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;
}
}
}