import { Field, Bool, ProvablePure, Pickles, Provable } from '../snarky.js'; import { AccountUpdate, Permissions, SetOrKeep, ZkappPublicInput, AccountUpdatesLayout } from './account_update.js'; import { PrivateKey, PublicKey } from './signature.js'; import * as Mina from './mina.js'; import { UInt32, UInt64 } from './int.js'; import { MethodInterface, Proof, GenericArgument } from './proof_system.js'; export { SmartContract, method, deploy, DeployArgs, signFeePayer, declareMethods, Callback, Account, VerificationKey, }; export { Reducer }; /** * A decorator to use in a zkapp to mark a method as callable by anyone. * You can use inside your zkapp class as: * * ``` * \@method myMethod(someArg: Field) { * // your code here * } * ``` */ declare function method(target: T & { constructor: any; }, methodName: keyof T & string, descriptor: PropertyDescriptor): void; declare class Callback extends GenericArgument { instance: SmartContract; methodIntf: MethodInterface & { returnType: Provable; }; args: any[]; result?: Result; accountUpdate: AccountUpdate; static create(instance: T, methodName: K, args: T[K] extends (...args: infer A) => any ? A : never): Callback; private constructor(); } /** * The main zkapp class. To write a zkapp, extend this class as such: * * ``` * class YourSmartContract extends SmartContract { * // your smart contract code here * } * ``` * */ declare class SmartContract { #private; address: PublicKey; tokenId: Field; static _methods?: MethodInterface[]; static _methodMetadata: Record; static _provers?: Pickles.Prover[]; static _maxProofsVerified?: 0 | 1 | 2; static _verificationKey?: { data: string; hash: Field; }; static Proof(): { new ({ proof, publicInput, maxProofsVerified, }: { proof: unknown; publicInput: ZkappPublicInput; maxProofsVerified: 0 | 2 | 1; }): { publicInput: ZkappPublicInput; proof: unknown; maxProofsVerified: 0 | 2 | 1; shouldVerify: Bool; verify(): void; verifyIf(condition: Bool): void; toJSON(): { publicInput: string[]; maxProofsVerified: 0 | 2 | 1; proof: string; }; }; publicInputType: ProvablePure<{ accountUpdate: Field; calls: Field; }> & { toInput: (x: { accountUpdate: Field; calls: Field; }) => { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; toJSON: (x: { accountUpdate: Field; calls: Field; }) => { accountUpdate: string; calls: string; }; }; tag: () => typeof SmartContract; fromJSON Proof) & { prototype: Proof; publicInputType: ProvablePure; tag: () => { name: string; }; fromJSON: typeof Proof.fromJSON; } & { prototype: Proof; }>(this: S, { maxProofsVerified, proof, publicInput, }: { publicInput: string[]; maxProofsVerified: 0 | 2 | 1; proof: string; }): Proof any ? InstanceType : never : never : never>; }; constructor(address: PublicKey, tokenId?: Field); /** * Compile your smart contract. * * This generates both the prover functions, needed to create proofs for running `@method`s, * and the verification key, needed to deploy your zkApp. * * Although provers and verification key are returned by this method, they are also cached internally and used when needed, * so you don't actually have to use the return value of this function. * * Under the hood, "compiling" means calling into the lower-level [Pickles and Kimchi libraries](https://o1-labs.github.io/proof-systems/kimchi/overview.html) to * create two prover & verifier indices (one for the "step circuit" which combines all of your smart contract methods into one circuit, * and one for the "wrap circuit" which wraps it so that proofs end up in the original finite field). These are fairly expensive * operations, so **expect compiling to take at least 20 seconds**, up to several minutes if your circuit is large or your hardware * is not optimal for these operations. */ static compile(): Promise<{ verificationKey: { data: string; hash: string; }; provers: Pickles.Prover[]; verify: (publicInput: Pickles.PublicInput, proof: unknown) => Promise; }>; /** * Computes a hash of your smart contract, which will reliably change _whenever one of your method circuits changes_. * This digest is quick to compute. it is designed to help with deciding whether a contract should be re-compiled or * a cached verification key can be used. * @returns the digest, as a hex string */ static digest(): string; deploy({ verificationKey, zkappKey, }?: { verificationKey?: { data: string; hash: Field | string; }; zkappKey?: PrivateKey; }): void; sign(zkappKey?: PrivateKey): void; skipAuthorization(): void; get self(): AccountUpdate; get account(): { nonce: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; receiptChainHash: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; delegate: { get(): PublicKey; assertEquals(value: PublicKey): void; assertNothing(): void; }; balance: { get(): UInt64; assertEquals(value: UInt64): void; assertNothing(): void; } & { assertBetween(lower: UInt64, upper: UInt64): void; }; sequenceState: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; provedState: { get(): Bool; assertEquals(value: Bool): void; assertNothing(): void; }; isNew: { get(): Bool; assertEquals(value: Bool): void; assertNothing(): void; }; }; get network(): { snarkedLedgerHash: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; timestamp: { get(): UInt64; assertEquals(value: UInt64): void; assertNothing(): void; } & { assertBetween(lower: UInt64, upper: UInt64): void; }; blockchainLength: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; minWindowDensity: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; totalCurrency: { get(): UInt64; assertEquals(value: UInt64): void; assertNothing(): void; } & { assertBetween(lower: UInt64, upper: UInt64): void; }; globalSlotSinceHardFork: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; globalSlotSinceGenesis: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; stakingEpochData: { ledger: { hash: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; totalCurrency: { get(): UInt64; assertEquals(value: UInt64): void; assertNothing(): void; } & { assertBetween(lower: UInt64, upper: UInt64): void; }; }; seed: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; startCheckpoint: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; lockCheckpoint: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; epochLength: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; }; nextEpochData: { ledger: { hash: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; totalCurrency: { get(): UInt64; assertEquals(value: UInt64): void; assertNothing(): void; } & { assertBetween(lower: UInt64, upper: UInt64): void; }; }; seed: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; startCheckpoint: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; lockCheckpoint: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; epochLength: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; }; }; get experimental(): { readonly token: { id: Field; parentTokenId: Field; tokenOwner: PublicKey; mint({ address, amount, }: { address: PublicKey; amount: number | bigint | UInt64; }): AccountUpdate; burn({ address, amount, }: { address: PublicKey; amount: number | bigint | UInt64; }): void; send({ from, to, amount, }: { from: PublicKey; to: PublicKey; amount: number | bigint | UInt64; }): AccountUpdate; }; /** * Approve an account update or callback. This will include the account update in the zkApp's public input, * which means it allows you to read and use its content in a proof, make assertions about it, and modify it. * * If this is called with a callback as the first parameter, it will first extract the account update produced by that callback. * The extracted account update is returned. * * ```ts * \@method myApprovingMethod(callback: Callback) { * let approvedUpdate = this.experimental.approve(callback); * } * ``` * * Under the hood, "approving" just means that the account update is made a child of the zkApp in the * tree of account updates that forms the transaction. * The second parameter `layout` allows you to also make assertions about the approved update's _own_ children, * by specifying a certain expected layout of children. See {@link AccountUpdate.Layout}. * * @param updateOrCallback * @param layout * @returns The account update that was approved (needed when passing in a Callback) */ approve(updateOrCallback: AccountUpdate | Callback, layout?: AccountUpdatesLayout): AccountUpdate; }; send(args: { to: PublicKey | AccountUpdate; amount: number | bigint | UInt64; }): void; get tokenSymbol(): { set(tokenSymbol: string): void; }; get balance(): { addInPlace(x: string | number | bigint | UInt64 | UInt32 | import("./int.js").Int64): void; subInPlace(x: string | number | bigint | UInt64 | UInt32 | import("./int.js").Int64): void; }; events: { [key: string]: ProvablePure; }; emitEvent(type: K, event: any): void; fetchEvents(start?: UInt32, end?: UInt32): Promise<{ type: string; event: ProvablePure; }[]>; static runOutsideCircuit(run: () => void): void; /** * This function is run internally before compiling a smart contract, to collect metadata about what each of your * smart contract methods does. * * For external usage, this function can be handy because calling it involves running all methods in the same "mode" as `compile()` does, * so it serves as a quick-to-run check for whether your contract can be compiled without errors, which can greatly speed up iterating. * * `analyzeMethods()` will also return the number of `rows` of each of your method circuits (i.e., the number of constraints in the underlying proof system), * which is a good indicator for circuit size and the time it will take to create proofs. * * Note: If this function was already called before, it will short-circuit and just return the metadata collected the first time. * * @returns an object, keyed by method name, each entry containing: * - `rows` the size of the constraint system created by this method * - `digest` a digest of the method circuit * - `hasReturn` a boolean indicating whether the method returns a value * - `sequenceEvents` the number of actions the method dispatches */ static analyzeMethods(): Record; setValue(maybeValue: SetOrKeep, value: T): void; setPermissions(permissions: Permissions): void; } declare type Reducer = { actionType: ProvablePure; }; declare type ReducerReturn = { dispatch(action: Action): void; reduce(actions: Action[][], stateType: Provable, reduce: (state: State, action: Action) => State, initial: { state: State; actionsHash: Field; }, options?: { maxTransactionsWithActions?: number; }): { state: State; actionsHash: Field; }; getActions({ fromActionHash, endActionHash, }: { fromActionHash?: Field; endActionHash?: Field; }): Action[][]; }; declare const VerificationKey_base: (new (value: { data: string; hash: Field; }) => { data: string; hash: Field; }) & Provable<{ data: string; hash: Field; }> & { toInput: (x: { data: string; hash: Field; }) => { fields?: Field[] | undefined; packed?: [Field, number][] | undefined; }; toJSON: (x: { data: string; hash: Field; }) => string; }; declare class VerificationKey extends VerificationKey_base { } declare type DeployArgs = { verificationKey?: { data: string; hash: string | Field; }; zkappKey?: PrivateKey; } | undefined; declare function deploy(SmartContract: S, { zkappKey, verificationKey, initialBalance, feePayer, tokenId, }: { zkappKey: PrivateKey; verificationKey: { data: string; hash: string | Field; }; initialBalance?: number | string; feePayer?: Mina.FeePayerSpec; tokenId?: Field; }): Promise; declare function Account(address: PublicKey, tokenId?: Field): { nonce: { get(): UInt32; assertEquals(value: UInt32): void; assertNothing(): void; } & { assertBetween(lower: UInt32, upper: UInt32): void; }; receiptChainHash: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; delegate: { get(): PublicKey; assertEquals(value: PublicKey): void; assertNothing(): void; }; balance: { get(): UInt64; assertEquals(value: UInt64): void; assertNothing(): void; } & { assertBetween(lower: UInt64, upper: UInt64): void; }; sequenceState: { get(): Field; assertEquals(value: Field): void; assertNothing(): void; }; provedState: { get(): Bool; assertEquals(value: Bool): void; assertNothing(): void; }; isNew: { get(): Bool; assertEquals(value: Bool): void; assertNothing(): void; }; }; declare function signFeePayer(transactionJson: string, feePayerKey: PrivateKey | string, { transactionFee, feePayerNonce, memo: feePayerMemo, }: { transactionFee?: string | number | undefined; feePayerNonce?: string | number | undefined; memo?: string | undefined; }): string; /** * `declareMethods` can be used in place of the `@method` decorator * to declare SmartContract methods along with their list of arguments. * It should be placed _after_ the class declaration. * Here is an example of declaring a method `update`, which takes a single argument of type `Field`: * ```ts * class MyContract extends SmartContract { * // ... * update(x: Field) { * // ... * } * } * declareMethods(MyContract, { update: [Field] }); // `[Field]` is the list of arguments! * ``` * Note that a method of the same name must still be defined on the class, just without the decorator. */ declare function declareMethods(SmartContract: T, methodArguments: Record[]>): void; declare type InferProvablePure> = T extends ProvablePure ? U : never; declare const Reducer: (, A extends InferProvablePure>(reducer: { actionType: T; }) => ReducerReturn) & { initialActionsHash: Field; };