import { base64, env, u128, util, Context } from "near-sdk-core"; import { JSONEncoder as _JSONEncoder, JSON } from "assemblyscript-json"; import { storage } from "near-sdk-core"; // Runtime functions // tslint:disable: no-unsafe-any /* eslint-disable @typescript-eslint/no-unused-vars */ // @ts-ignore @global function isNull(t: T): bool { if (isNullable() || isReference()) { return changetype(t) == 0; } return false; } // @ts-ignore @global function notPayable(): void { assert(Context.attachedDeposit == u128.Zero, "Method doesn't accept deposit"); } // @ts-ignore @global function oneYocto(): void { assert(Context.attachedDeposit == u128.One, "Requires attached deposit of exactly 1 yoctoNEAR"); } // @ts-ignore @global function requireParameter(name: string): T { assert( false, "Parameter " + name + " with type " + nameof() + " is required but missing" ); return defaultValue(); } @global class JSONEncoder extends _JSONEncoder { encode(name: string, val: T): void { encode(val, name, this); } } type Usize = u64; // @ts-ignore @global function read_register(register_id: Usize, ptr: Usize): void { env.read_register(register_id, ptr); } // @ts-ignore @global function register_len(register_id: Usize): Usize { return env.register_len(register_id); } // @ts-ignore @global function input(register_id: Usize): void { env.input(register_id); } // @ts-ignore @global function value_return(value_len: Usize, value_ptr: Usize): void { env.value_return(value_len, value_ptr); } // @ts-ignore @global function panic(): void { env.panic(); } // @ts-ignore @global function panic_utf8(len: Usize, ptr: Usize): void { env.panic_utf8(len, ptr); } // @ts-ignore @global function getInput(): JSON.Obj { // Reading input bytes. input(0); let json_len = register_len(0); if (json_len == U32.MAX_VALUE) { panic(); } let json = new Uint8Array(json_len as u32); // @ts-ignore read_register(0, json.dataStart); return JSON.parse(json); } // @ts-ignore @global function encode( value: T, name: string | null = "", encoder: JSONEncoder = new JSONEncoder() ): Output { if (isBoolean()) { // @ts-ignore encoder.setBoolean(name, value); } else if (isInteger()) { if (value instanceof i64 || value instanceof u64) { // @ts-ignore encoder.setString(name, value.toString()); } else { // @ts-ignore encoder.setInteger(name, value); } } else if (isFloat()) { // @ts-ignore encoder.setFloat(name, value); } else if (isString()) { if (isNull(value)) { encoder.setNull(name); } else { // @ts-ignore encoder.setString(name, value); } } else if (isReference()) { // @ts-ignore if (isNull(value)) { encoder.setNull(name); } else { // @ts-ignore if (isDefined(value._encode)) { if (isNullable()) { if (value != null) { // @ts-ignore value._encode(name, encoder); } else { encoder.setNull(name); } } else { // @ts-ignore value._encode(name, encoder); } } else if (isArrayLike(value)) { if (value instanceof Uint8Array) { // @ts-ignore encoder.setString(name, base64.encode(value)); } else { encoder.pushArray(name); for (let i: i32 = 0; i < value.length; i++) { // @ts-ignore encode, JSONEncoder>(value[i], null, encoder); } encoder.popArray(); } } else { // Is an object if (value instanceof u128) { // @ts-ignore encoder.setString(name, value.toString()); } else if (value instanceof Map) { assert( // @ts-ignore nameof>() == "String", "Can only encode maps with string keys" ); let keys = value.keys(); encoder.pushObject(name); for (let i = 0; i < keys.length; i++) { // @ts-ignore encode, JSONEncoder>( value.get(keys[i]), keys[i], encoder ); } encoder.popObject(); } else if (value instanceof Set) { // @ts-ignore let values: Array> = value.values(); encoder.pushArray(name); for (let i = 0; i < values.length; i++) { // @ts-ignore encode, JSONEncoder>(values[i], null, encoder); } encoder.popArray(); } } } } else { throw new Error( "Encoding failed " + (name != null && name != "" ? " for " + name : "") + " with type " + nameof() ); } var output: Output; // @ts-ignore if (output instanceof Uint8Array) { // @ts-ignore return encoder.serialize(); } assert( // @ts-ignore output instanceof JSONEncoder, // @ts-ignore "Bad return type " + nameof < Output > +" for encoder" ); // @ts-ignore return encoder; } // @ts-ignore @inline function getStr(val: JSON.Value, name: string): string { assert( val instanceof JSON.Str, "Value with Key: " + name + " is not a string or null" ); return (val)._str; } function decodeArray(val: JSON.Value, name: string): Array { assert( val instanceof JSON.Arr, "Value with Key: " + name + " is not an array or null." ); const res = new Array(); const arr = (val)._arr; for (let i: i32 = 0; i < arr.length; i++) { let item: T = decode(arr[i]); res.push(item); } return res; } function decodeMap(aVal: JSON.Value, name: string): Map { assert( aVal instanceof JSON.Obj, "Value with Key: " + name + " is not an Obj." ); let val = aVal; let map = new Map(); for (let i = 0; i < val.keys.length; i++) { let key = val.keys[i]; map.set(key, decode(val.get(key))); } return map; } function decodeSet(aVal: JSON.Value, name: string): Set { assert( aVal instanceof JSON.Arr, "Value with Key: " + name + " is not an Obj." ); let arr = (aVal)._arr; let set = new Set(); for (let i = 0; i < arr.length; i++) { let val = arr[i]; set.add(decode(val)); } return set; } function isReallyNullable(): bool { return ( isReference() || isArrayLike() || isNullable() || isString() ); } function JSONTypeToString(t: T): string { if (t instanceof JSON.Str) { return "string"; } if (t instanceof JSON.Bool) { return "Boolean"; } if (t instanceof JSON.Obj) { return "Object"; } if (t instanceof JSON.Arr) { return "Array"; } if (t instanceof JSON.Null) { return "Null"; } if (t instanceof JSON.Integer) { return "Integer"; } if (t instanceof JSON.Float) { return "Float"; } return "UNKNOWN TYPE"; } function isNumber(): boolean { return isFloat() || isInteger(); } // @ts-ignore @global function decode(buf: V, name: string = ""): T { const buffer = ( (buf instanceof Uint8Array ? JSON.parse(buf) : buf) ); var val: JSON.Value; if (buffer instanceof JSON.Obj && name != "") { const obj: JSON.Obj = buffer; let res = obj.get(name); if (res == null) { if (isReallyNullable() && !isNumber()) { if (isFloat()) { throw new Error("type " + nameof() + " cannot be null."); } else if (isInteger()) { throw new Error("type " + nameof() + " cannot be null."); } else { // @ts-ignore return changetype(res); } } else { throw new Error("type " + nameof() + " cannot be null."); } } val = res; } else { val = buffer; } if (isBoolean()) { assert( val instanceof JSON.Bool, "Value with Key: " + name + " with type " + nameof() + " is not a string" ); // @ts-ignore return (val)._bool; } var value: T; if (isInteger()) { // @ts-ignore if (value instanceof u64 || value instanceof i64) { assert( val instanceof JSON.Str, "Value with Key: " + name + " with type " + nameof() + " is an 64-bit integer and is expected to be encoded as a string" ); let str = (val)._str; // @ts-ignore return (isSigned() ? I64.parseInt(str) : U64.parseInt(str)); } assert( val instanceof JSON.Integer, "Value with Key: " + name + " with type " + nameof() + " is not an Integer" ); // @ts-ignore return (val)._num; } else if (isFloat()) { assert( val instanceof JSON.Float, "Value with Key: " + name + " with type " + nameof() + " is not a Float" ); // @ts-ignore return (val)._num; } if (val instanceof JSON.Null) { assert( isReallyNullable(), "Key: " + name + " with type " + nameof() + "is not nullable" ); // @ts-ignore return changetype(0); } if (isString()) { // @ts-ignore return getStr(val, name); } assert( isReference(), name + " with type " + nameof() + " must be an integer, boolean, string, object, or array" ); // @ts-ignore if (isDefined(value.decode)) { assert( val instanceof JSON.Obj || val instanceof JSON.Obj, "Value with Key: " + name + " with type " + nameof() + " is not an object or null " + (val instanceof JSON.Obj).toString() ); value = util.allocate(); if (isNullable()) { if (value != null) { // @ts-ignore return value.decode(val); } } else { // @ts-ignore return value.decode(val); } } // @ts-ignore if (value instanceof Map) { assert( val instanceof JSON.Obj, "Value with Key: " + name + " of type map expected a JSON.Obj, but recevied " + JSONTypeToString(val) ); assert( // @ts-ignore nameof>() == "String", "Value with Key: " + name + " cannot decode a map which has an index type " + // @ts-ignore nameof>() + ", it must be a string" ); // @ts-ignore return decodeMap>(val, name); } // @ts-ignore if (value instanceof Set) { assert( val instanceof JSON.Arr, "Value with Key: " + name + " of type map expected a JSON.Obj, but recevied " + JSONTypeToString(val) ); // @ts-ignore return decodeSet>(val, name); } if (isArrayLike()) { // @ts-ignore if (value instanceof Uint8Array) { // @ts-ignore return base64.decode(getStr(val, name)); } // @ts-ignore // assert(val instanceof Arr, "Value with Key: " + name + " with type " + nameof() + " is expected to be an array") // @ts-ignore only checking the instance return decodeArray>(val, name); } // @ts-ignore if (value instanceof u128) { assert( val instanceof JSON.Str, "Value with Key: " + name + " expected type string to decode u128 but got " + JSONTypeToString(val) ); // @ts-ignore return u128.fromString(getStr(val, name)); } throw new Error( "Error when trying to decode " + name + " with type " + nameof() + " and unexpected JSON type " + JSONTypeToString(val) + "\nPerhaps @nearBindgen decorator needs to be added to class " + nameof() ); } // @ts-ignore @global function defaultValue(): T { if (isInteger() || isFloat()) { // @ts-ignore return 0; } return changetype(0); } /** * Singleton support functions */ /* eslint-disable indent */ // @ts-ignore @lazy const __STATE_KEY = "STATE"; // @ts-ignore @global function __checkState(): bool { return storage.contains(__STATE_KEY); } // @ts-ignore @global function __getState(): T { return storage.getSome(__STATE_KEY); } // @ts-ignore @global function __setState(state: T): void { storage.set(__STATE_KEY, state); } @global function __assertPrivate(): void { let contractName = Context.contractName; assert(contractName == Context.predecessor, `Only ${contractName} can call this method.`); }