import { Bool } from '../../provable/bool.js'; import { Field } from '../../provable/field.js'; import { Provable } from '../../provable/types/provable-intf.js'; import * as Bindings from '../../../bindings/mina-transaction/v2/index.js'; import { bytesToBits, stringToBytes } from '../../../bindings/lib/binable.js'; import { GenericHashInput } from '../../../bindings/lib/generic.js'; import { hashWithPrefix, packToFields } from '../../../lib/provable/crypto/poseidon.js'; import { prefixes } from '../../../bindings/crypto/constants.js'; import { Types } from '../../../bindings/mina-transaction/v1/types.js'; export { Option, Range, mapUndefined, Empty, Update, Compare, Eq, ToFields, Tuple, ProvableTuple, ProvableInstance, ProvableTupleInstances, TokenId, ZkappUri, mapObject, }; // boo typescript function mapObject( object: In, f: (key: Key) => Out[Key] ): { [key in keyof In]: Out[key] } { const newObject: Partial<{ [key in keyof In]: Out[key] }> = {}; for (const key in object) { newObject[key] = f(key); } return newObject as { [key in keyof In]: Out[key] }; } const { Option, Range } = Bindings.Leaves; type Option = Bindings.Leaves.Option; type Range = Bindings.Leaves.Range; class ZkappUri { readonly data: string; readonly hash: Field; constructor(uri: string | { data: string; hash: Field }) { if (typeof uri === 'object') { this.data = uri.data; this.hash = uri.hash; } else { this.data = uri; let packed: Field[]; if (uri.length === 0) { packed = [new Field(0), new Field(0)]; } else { const bits = bytesToBits(stringToBytes(uri)); bits.push(true); const input: GenericHashInput = { packed: bits.map((b) => [new Field(Number(b)), 1]), }; packed = packToFields(input); } this.hash = hashWithPrefix(prefixes.zkappUri, packed); } } toJSON(): Types.Json.AccountUpdate['body']['update']['zkappUri'] { return this.data.toString(); } static empty(): ZkappUri { return new ZkappUri(''); } static from(uri: ZkappUri | string): ZkappUri { return uri instanceof ZkappUri ? uri : new ZkappUri(uri); } } class TokenId { // TODO: construct this from it's parts, don't pass in the raw Field directly constructor(public value: Field) {} equals(x: TokenId): Bool { return this.value.equals(x.value); } toString(): string { return this.value.toString(); } static MINA: TokenId = new TokenId(new Field(1)); } function mapUndefined(value: A | undefined, f: (a: A) => B): B | undefined { return value === undefined ? undefined : f(value); } interface Empty { empty: () => T; } interface Eq { equals(x: T): Bool; } type Compare> = Eq & { lessThan(x: T): Bool; lessThanOrEqual(x: T): Bool; greaterThan(x: T): Bool; greaterThanOrEqual(x: T): Bool; }; interface ToFields { toFields(): Field[]; } type Tuple = [T, ...T[]] | []; type ProvableTuple = Tuple>; type ProvableInstance

= P extends Provable ? (unknown extends T ? T : never) : never; type ProvableTupleInstances = { [I in keyof T]: ProvableInstance; }; class Update { constructor( public set: Bool, public value: T ) {} toOption(): Option { return { isSome: this.set, value: this.value }; } static fromOption(option: Option): Update { return new Update(option.isSome, option.value); } static disabled(defaultValue: T): Update { return new Update(new Bool(false), defaultValue); } static set(value: T): Update { return new Update(new Bool(true), value); } static from(value: Update | T | undefined, defaultValue: T): Update { if (value instanceof Update) { return value; } else if (value !== undefined) { return Update.set(value); } else { return Update.disabled(defaultValue); } } }