UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

511 lines (485 loc) 11.1 kB
import { UInt32 } from '../provable/int.js'; import type { ZkappCommand } from './account-update.js'; import type { ActionStatesStringified } from './fetch.js'; import { Types } from '../../bindings/mina-transaction/types.js'; export { type EpochData, type LastBlockQueryResponse, type GenesisConstantsResponse, type FailureReasonResponse, type LastBlockQueryFailureCheckResponse, type FetchedBlock, type TransactionStatus, type TransactionStatusQueryResponse, type EventQueryResponse, type ActionQueryResponse, type EventActionFilterOptions, type SendZkAppResponse, type FetchedAccount, type FetchedAccountResponse, type CurrentSlotResponse, getEventsQuery, getActionsQuery, sendZkappQuery, transactionStatusQuery, lastBlockQueryFailureCheck, accountQuery, currentSlotQuery, genesisConstantsQuery, lastBlockQuery, removeJsonQuotes, }; // removes the quotes on JSON keys function removeJsonQuotes(json: string) { let cleaned = JSON.stringify(JSON.parse(json), null, 2); return cleaned.replace(/\"(\S+)\"\s*:/gm, '$1:'); } type AuthRequired = Types.Json.AuthRequired; // TODO auto-generate this type and the query type FetchedAccount = { publicKey: string; token: string; nonce: string; balance: { total: string }; tokenSymbol: string | null; receiptChainHash: string | null; timing: { initialMinimumBalance: string | null; cliffTime: string | null; cliffAmount: string | null; vestingPeriod: string | null; vestingIncrement: string | null; }; permissions: { editState: AuthRequired; access: AuthRequired; send: AuthRequired; receive: AuthRequired; setDelegate: AuthRequired; setPermissions: AuthRequired; setVerificationKey: { auth: AuthRequired; txnVersion: string; }; setZkappUri: AuthRequired; editActionState: AuthRequired; setTokenSymbol: AuthRequired; incrementNonce: AuthRequired; setVotingFor: AuthRequired; setTiming: AuthRequired; } | null; delegateAccount: { publicKey: string } | null; votingFor: string | null; zkappState: string[] | null; verificationKey: { verificationKey: string; hash: string } | null; actionState: string[] | null; provedState: boolean | null; zkappUri: string | null; }; type FetchedAccountResponse = { account: FetchedAccount; }; type EpochData = { ledger: { hash: string; totalCurrency: string; }; seed: string; startCheckpoint: string; lockCheckpoint: string; epochLength: string; }; type LastBlockQueryResponse = { bestChain: { protocolState: { blockchainState: { snarkedLedgerHash: string; stagedLedgerHash: string; date: string; utcDate: string; stagedLedgerProofEmitted: boolean; }; previousStateHash: string; consensusState: { blockHeight: string; slotSinceGenesis: string; slot: string; nextEpochData: EpochData; stakingEpochData: EpochData; epochCount: string; minWindowDensity: string; totalCurrency: string; epoch: string; }; }; }[]; }; type FailureReasonResponse = { failures: string[]; index: number; }[]; type LastBlockQueryFailureCheckResponse = { bestChain: { transactions: { zkappCommands: { hash: string; failureReason: FailureReasonResponse; }[]; }; }[]; }; type FetchedBlock = { protocolState: { blockchainState: { snarkedLedgerHash: string; // hash-like encoding stagedLedgerHash: string; // hash-like encoding date: string; // String(Date.now()) utcDate: string; // String(Date.now()) stagedLedgerProofEmitted: boolean; // bool }; previousStateHash: string; // hash-like encoding consensusState: { blockHeight: string; // String(number) slotSinceGenesis: string; // String(number) slot: string; // String(number) nextEpochData: { ledger: { hash: string; // hash-like encoding totalCurrency: string; // String(number) }; seed: string; // hash-like encoding startCheckpoint: string; // hash-like encoding lockCheckpoint: string; // hash-like encoding epochLength: string; // String(number) }; stakingEpochData: { ledger: { hash: string; // hash-like encoding totalCurrency: string; // String(number) }; seed: string; // hash-like encoding startCheckpoint: string; // hash-like encoding lockCheckpoint: string; // hash-like encoding epochLength: string; // String(number) }; epochCount: string; // String(number) minWindowDensity: string; // String(number) totalCurrency: string; // String(number) epoch: string; // String(number) }; }; }; type GenesisConstantsResponse = { genesisConstants: { genesisTimestamp: string; coinbase: string; accountCreationFee: string; }; daemonStatus: { consensusConfiguration: { epochDuration: string; k: string; slotDuration: string; slotsPerEpoch: string; }; }; }; type CurrentSlotResponse = { bestChain: Array<{ protocolState: { consensusState: { slot: number; }; }; }>; }; /** * INCLUDED: A transaction that is on the longest chain * * PENDING: A transaction either in the transition frontier or in transaction pool but is not on the longest chain * * UNKNOWN: The transaction has either been snarked, reached finality through consensus or has been dropped * */ type TransactionStatus = 'INCLUDED' | 'PENDING' | 'UNKNOWN'; type TransactionStatusQueryResponse = { transactionStatus: TransactionStatus; }; type SendZkAppResponse = { sendZkapp: { zkapp: { hash: string; id: string; zkappCommand: ZkappCommand; failureReasons: FailureReasonResponse; }; }; }; type EventQueryResponse = { events: { blockInfo: { distanceFromMaxBlockHeight: number; globalSlotSinceGenesis: number; height: number; stateHash: string; parentHash: string; chainStatus: string; }; eventData: { transactionInfo: { hash: string; memo: string; status: string; }; data: string[]; }[]; }[]; }; type ActionQueryResponse = { actions: { blockInfo: { distanceFromMaxBlockHeight: number; }; actionState: { actionStateOne: string; actionStateTwo: string; }; actionData: { accountUpdateId: string; data: string[]; }[]; }[]; }; type EventActionFilterOptions = { to?: UInt32; from?: UInt32; }; const transactionStatusQuery = (txId: string) => `query { transactionStatus(zkappTransaction:"${txId}") }`; const getEventsQuery = ( publicKey: string, tokenId: string, filterOptions?: EventActionFilterOptions ) => { const { to, from } = filterOptions ?? {}; let input = `address: "${publicKey}", tokenId: "${tokenId}"`; if (to !== undefined) { input += `, to: ${to}`; } if (from !== undefined) { input += `, from: ${from}`; } return `{ events(input: { ${input} }) { blockInfo { distanceFromMaxBlockHeight height globalSlotSinceGenesis stateHash parentHash chainStatus } eventData { transactionInfo { hash memo status } data } } }`; }; const getActionsQuery = ( publicKey: string, actionStates: ActionStatesStringified, tokenId: string, _filterOptions?: EventActionFilterOptions ) => { const { fromActionState, endActionState } = actionStates ?? {}; let input = `address: "${publicKey}", tokenId: "${tokenId}"`; if (fromActionState !== undefined) { input += `, fromActionState: "${fromActionState}"`; } if (endActionState !== undefined) { input += `, endActionState: "${endActionState}"`; } return `{ actions(input: { ${input} }) { blockInfo { distanceFromMaxBlockHeight } actionState { actionStateOne actionStateTwo } actionData { accountUpdateId data } } }`; }; const genesisConstantsQuery = `{ genesisConstants { genesisTimestamp coinbase accountCreationFee } daemonStatus { consensusConfiguration { epochDuration k slotDuration slotsPerEpoch } } }`; const lastBlockQuery = `{ bestChain(maxLength: 1) { protocolState { blockchainState { snarkedLedgerHash stagedLedgerHash date utcDate stagedLedgerProofEmitted } previousStateHash consensusState { blockHeight slotSinceGenesis slot nextEpochData { ledger {hash totalCurrency} seed startCheckpoint lockCheckpoint epochLength } stakingEpochData { ledger {hash totalCurrency} seed startCheckpoint lockCheckpoint epochLength } epochCount minWindowDensity totalCurrency epoch } } } }`; const lastBlockQueryFailureCheck = (length: number) => `{ bestChain(maxLength: ${length}) { transactions { zkappCommands { hash failureReason { failures index } } } stateHash protocolState { consensusState { blockHeight epoch slotSinceGenesis } previousStateHash } } }`; // TODO: Decide an appropriate response structure. function sendZkappQuery(json: string) { return `mutation { sendZkapp(input: { zkappCommand: ${removeJsonQuotes(json)} }) { zkapp { hash id failureReason { failures index } zkappCommand { memo feePayer { body { publicKey } } accountUpdates { body { publicKey useFullCommitment incrementNonce } } } } } } `; } const accountQuery = (publicKey: string, tokenId: string) => `{ account(publicKey: "${publicKey}", token: "${tokenId}") { publicKey token nonce balance { total } tokenSymbol receiptChainHash timing { initialMinimumBalance cliffTime cliffAmount vestingPeriod vestingIncrement } permissions { editState access send receive setDelegate setPermissions setVerificationKey { auth txnVersion } setZkappUri editActionState setTokenSymbol incrementNonce setVotingFor setTiming } delegateAccount { publicKey } votingFor zkappState verificationKey { verificationKey hash } actionState provedState zkappUri } } `; const currentSlotQuery = `{ bestChain(maxLength: 1) { protocolState { consensusState { slot } } } }`;