diff --git a/common/collections.ts b/common/collections.ts index e2043b2..e197cc6 100644 --- a/common/collections.ts +++ b/common/collections.ts @@ -1,4 +1,4 @@ -import { BigInt, BigDecimal } from './numbers' +import { BigInt, BigDecimal, Address } from './numbers' import { Value } from './value' import { typeConversion } from './conversion' @@ -67,7 +67,9 @@ export class ByteArray extends Uint8Array { } /** - * Input length must be even. + * Convert the string `hex` which must consist of an even number of + * hexadecimal digits to a `ByteArray`. The string `hex` can optionally + * start with '0x' */ static fromHexString(hex: string): ByteArray { assert(hex.length % 2 == 0, 'input ' + hex + ' has odd length') @@ -165,6 +167,21 @@ export class ByteArray extends Uint8Array { return x } + /** Create a new `ByteArray` that consist of `this` directly followed by + * the bytes from `other` */ + concat(other: ByteArray): ByteArray { + let newArray = new ByteArray(this.length + other.length) + newArray.set(this, 0) + newArray.set(other, this.length) + return newArray + } + + /** Create a new `ByteArray` that consists of `this` directly followed by + * the representation of `other` as bytes */ + concatI32(other: i32): ByteArray { + return this.concat(ByteArray.fromI32(other)) + } + /** * Interprets the byte array as a little-endian I64. * Throws in case of overflow. @@ -268,13 +285,34 @@ export class Bytes extends ByteArray { return changetype(uint8Array) } + /** + * Convert the string `hex` which must consist of an even number of + * hexadecimal digits to a `ByteArray`. The string `hex` can optionally + * start with '0x' + */ + static fromHexString(str: string): Bytes { + return changetype(ByteArray.fromHexString(str)) + } + static fromUTF8(str: string): Bytes { return Bytes.fromByteArray(ByteArray.fromUTF8(str)) } + static fromI32(i: i32): Bytes { + return changetype(ByteArray.fromI32(i)) + } + static empty(): Bytes { return changetype(ByteArray.empty()) } + + concat(other: Bytes): Bytes { + return changetype(super.concat(other)) + } + + concatI32(other: i32): Bytes { + return changetype(super.concat(ByteArray.fromI32(other))) + } } /** diff --git a/common/numbers.ts b/common/numbers.ts index f53c8eb..48ae2af 100644 --- a/common/numbers.ts +++ b/common/numbers.ts @@ -35,6 +35,17 @@ export class Address extends Bytes { return changetype
(typeConversion.stringToH160(s)) } + /** Convert `Bytes` that must be exactly 20 bytes long to an address. + * Passing in a value with fewer or more bytes will result in an error */ + static fromBytes(b: Bytes): Address { + if (b.length != 20) { + throw new Error( + `Bytes of length ${b.length} can not be converted to 20 byte addresses`, + ) + } + return changetype
(b) + } + static zero(): Address { let self = new ByteArray(20) diff --git a/common/value.ts b/common/value.ts index e229198..f2f5ec8 100644 --- a/common/value.ts +++ b/common/value.ts @@ -16,6 +16,17 @@ export enum ValueKind { BIGINT = 7, } +const VALUE_KIND_NAMES = [ + 'String', + 'Int', + 'BigDecimal', + 'bool', + 'Array', + 'null', + 'Bytes', + 'BigInt', +] + /** * Pointer type for Value data. * @@ -129,6 +140,42 @@ export class Value { return output } + /** Return a string that indicates the kind of value `this` contains for + * logging and error messages */ + displayKind(): string { + if (this.kind >= VALUE_KIND_NAMES.length) { + return `Unknown (${this.kind})` + } else { + return VALUE_KIND_NAMES[this.kind] + } + } + + /** Return a string representation of the value of `this` for logging and + * error messages */ + displayData(): string { + switch (this.kind) { + case ValueKind.STRING: + return this.toString() + case ValueKind.INT: + return this.toI32().toString() + case ValueKind.BIGDECIMAL: + return this.toBigDecimal().toString() + case ValueKind.BOOL: + return this.toBoolean().toString() + case ValueKind.ARRAY: + let arr = this.toArray() + return '[' + arr.map((elt) => elt.displayData()).join(', ') + ']' + case ValueKind.NULL: + return 'null' + case ValueKind.BYTES: + return this.toBytes().toHexString() + case ValueKind.BIGINT: + return this.toBigInt().toString() + default: + return `Unknown data (kind = ${this.kind})` + } + } + static fromBooleanArray(input: Array): Value { let output = new Array(input.length) for (let i: i32 = 0; i < input.length; i++) { diff --git a/package.json b/package.json index aaf742d..74b4597 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "scripts": { "lint": "prettier -c **/*.{js,ts}", + "format": "prettier --write -c **/*.{js,ts}", "build": "asc --explicitStart --exportRuntime --runtime stub index.ts helper-functions.ts --lib graph-ts -b index.wasm", "test": "node test/test.js" }