diff --git a/CHANGELOG.md b/CHANGELOG.md index dc74a2d3..c32538bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changes +- Use generic ledger type in ZOwnablePKWitnesses (#389) - Bump compact compiler to v0.29.0 (#366) ## 0.0.1-alpha.1 (2025-12-2) diff --git a/contracts/src/access/test/simulators/ZOwnablePKSimulator.ts b/contracts/src/access/test/simulators/ZOwnablePKSimulator.ts index 5dd24cf9..b1227ee1 100644 --- a/contracts/src/access/test/simulators/ZOwnablePKSimulator.ts +++ b/contracts/src/access/test/simulators/ZOwnablePKSimulator.ts @@ -14,15 +14,16 @@ import { ZOwnablePKWitnesses, } from '../../witnesses/ZOwnablePKWitnesses.js'; -/** - * Type constructor args - */ +/** Type constructor args */ type ZOwnablePKArgs = readonly [ owner: Uint8Array, instanceSalt: Uint8Array, isInit: boolean, ]; +/** Concrete ledger type extracted from the generated artifact */ +type ZOwnablePKLedger = ReturnType; + /** * Base simulator * @dev We deliberately use `any` as the base simulator type. @@ -47,7 +48,7 @@ const ZOwnablePKSimulatorBase: any = createSimulator< return [owner, instanceSalt, isInit]; }, ledgerExtractor: (state) => ledger(state), - witnessesFactory: () => ZOwnablePKWitnesses(), + witnessesFactory: () => ZOwnablePKWitnesses(), }); /** diff --git a/contracts/src/access/witnesses/ZOwnablePKWitnesses.ts b/contracts/src/access/witnesses/ZOwnablePKWitnesses.ts index 6453011d..61269a2a 100644 --- a/contracts/src/access/witnesses/ZOwnablePKWitnesses.ts +++ b/contracts/src/access/witnesses/ZOwnablePKWitnesses.ts @@ -1,18 +1,18 @@ import { getRandomValues } from 'node:crypto'; import type { WitnessContext } from '@midnight-ntwrk/compact-runtime'; -import type { Ledger } from '../../../artifacts/MockZOwnablePK/contract/index.js'; /** * @description Interface defining the witness methods for ZOwnablePK operations. + * @template L - The ledger type. * @template P - The private state type. */ -export interface IZOwnablePKWitnesses

{ +export interface IZOwnablePKWitnesses { /** * Retrieves the secret nonce from the private state. - * @param context - The witness context containing the private state. + * @param context - The witness context containing the ledger and private state. * @returns A tuple of the private state and the secret nonce as a Uint8Array. */ - wit_secretNonce(context: WitnessContext): [P, Uint8Array]; + wit_secretNonce(context: WitnessContext): [P, Uint8Array]; } /** @@ -56,13 +56,16 @@ export const ZOwnablePKPrivateState = { /** * @description Factory function creating witness implementations for Ownable operations. + * @template L - The ledger type, supplied by the simulator. * @returns An object implementing the Witnesses interface for ZOwnablePKPrivateState. */ -export const ZOwnablePKWitnesses = - (): IZOwnablePKWitnesses => ({ - wit_secretNonce( - context: WitnessContext, - ): [ZOwnablePKPrivateState, Uint8Array] { - return [context.privateState, context.privateState.secretNonce]; - }, - }); +export const ZOwnablePKWitnesses = (): IZOwnablePKWitnesses< + L, + ZOwnablePKPrivateState +> => ({ + wit_secretNonce( + context: WitnessContext, + ): [ZOwnablePKPrivateState, Uint8Array] { + return [context.privateState, context.privateState.secretNonce]; + }, +}); diff --git a/packages/simulator/README.md b/packages/simulator/README.md index fcfd3ec0..48b2b496 100644 --- a/packages/simulator/README.md +++ b/packages/simulator/README.md @@ -20,7 +20,10 @@ import { Contract, ledger } from './artifacts/MyContract/contract/index.js'; // 1. Define your contract arguments type type MyContractArgs = readonly [owner: Uint8Array, value: bigint]; -// 2. Create the simulator +// 2. Define the extracted ledger type +type MyContractLedger = ReturnType; + +// 3. Create the simulator const MySimulator = createSimulator< MyPrivateState, ReturnType, @@ -31,10 +34,10 @@ const MySimulator = createSimulator< defaultPrivateState: () => MyPrivateState.generate(), contractArgs: (owner, value) => [owner, value], ledgerExtractor: (state) => ledger(state), - witnessesFactory: () => MyWitnesses(), + witnessesFactory: () => MyWitnesses(), }); -// 3. Use it! +// 4. Use it! const sim = new MySimulator([ownerAddress, 100n], { coinPK: deployerPK }); ``` @@ -52,6 +55,9 @@ import { MyContractWitnesses, MyContractPrivateState } from './MyContractWitness // Define contract constructor arguments as a tuple type type MyContractArgs = readonly [arg1: bigint, arg2: string]; +// Define the extracted ledger type +type MyContractLedger = ReturnType; + // Create the base simulator with full type information const MyContractSimulatorBase = createSimulator< MyContractPrivateState, // Private state type @@ -63,7 +69,7 @@ const MyContractSimulatorBase = createSimulator< defaultPrivateState: () => MyContractPrivateState.generate(), contractArgs: (arg1, arg2) => [arg1, arg2], ledgerExtractor: (state) => ledger(state), - witnessesFactory: () => MyContractWitnesses(), // Note: Must be a function! + witnessesFactory: () => MyContractWitnesses(), // Note: Must be a function! }); ``` @@ -76,7 +82,7 @@ If the Compact contract has no witnesses: // Some Compact contract examples use: export const MyContractWitnesses = {}; -// But for the simulator, wrap it in a function: +// But for the simulator, wrap it in a generic function: export const MyContractWitnesses = () => ({}); ``` diff --git a/packages/simulator/test/fixtures/sample-contracts/witnesses/SampleZOwnableWitnesses.ts b/packages/simulator/test/fixtures/sample-contracts/witnesses/SampleZOwnableWitnesses.ts index 464007f1..af447156 100644 --- a/packages/simulator/test/fixtures/sample-contracts/witnesses/SampleZOwnableWitnesses.ts +++ b/packages/simulator/test/fixtures/sample-contracts/witnesses/SampleZOwnableWitnesses.ts @@ -1,18 +1,18 @@ import { getRandomValues } from 'node:crypto'; import type { WitnessContext } from '@midnight-ntwrk/compact-runtime'; -import type { Ledger } from '../../artifacts/SampleZOwnable/contract/index.js'; /** * @description Interface defining the witness methods for SampleZOwnable operations. + * @template L - The ledger type. * @template P - The private state type. */ -export interface ISampleZOwnableWitnesses

{ +export interface ISampleZOwnableWitnesses { /** * Retrieves the secret nonce from the private state. - * @param context - The witness context containing the private state. + * @param context - The witness context containing the ledger and private state. * @returns A tuple of the private state and the secret nonce as a Uint8Array. */ - secretNonce(context: WitnessContext): [P, Uint8Array]; + secretNonce(context: WitnessContext): [P, Uint8Array]; } /** @@ -56,13 +56,16 @@ export const SampleZOwnablePrivateState = { /** * @description Factory function creating witness implementations for Ownable operations. + * @template L - The ledger type, supplied by the simulator. * @returns An object implementing the Witnesses interface for SampleZOwnablePrivateState. */ -export const SampleZOwnableWitnesses = - (): ISampleZOwnableWitnesses => ({ - secretNonce( - context: WitnessContext, - ): [SampleZOwnablePrivateState, Uint8Array] { - return [context.privateState, context.privateState.secretNonce]; - }, - }); +export const SampleZOwnableWitnesses = (): ISampleZOwnableWitnesses< + L, + SampleZOwnablePrivateState +> => ({ + secretNonce( + context: WitnessContext, + ): [SampleZOwnablePrivateState, Uint8Array] { + return [context.privateState, context.privateState.secretNonce]; + }, +}); diff --git a/packages/simulator/test/fixtures/sample-contracts/witnesses/WitnessWitnesses.ts b/packages/simulator/test/fixtures/sample-contracts/witnesses/WitnessWitnesses.ts index 7795cdfc..47c8009f 100644 --- a/packages/simulator/test/fixtures/sample-contracts/witnesses/WitnessWitnesses.ts +++ b/packages/simulator/test/fixtures/sample-contracts/witnesses/WitnessWitnesses.ts @@ -1,6 +1,5 @@ import { getRandomValues } from 'node:crypto'; import type { WitnessContext } from '@midnight-ntwrk/compact-runtime'; -import type { Ledger } from '../../artifacts/Witness/contract/index.js'; const randomBigInt = (bits: number): bigint => { const bytes = Math.ceil(bits / 8); @@ -16,14 +15,14 @@ const randomBigInt = (bits: number): bigint => { return result % max; }; -export interface IWitnessWitnesses

{ - wit_secretBytes(context: WitnessContext): [P, Uint8Array]; +export interface IWitnessWitnesses { + wit_secretBytes(context: WitnessContext): [P, Uint8Array]; wit_secretFieldPlusArg( - context: WitnessContext, + context: WitnessContext, arg: bigint, ): [P, bigint]; wit_secretUintPlusArgs( - context: WitnessContext, + context: WitnessContext, arg1: bigint, arg2: bigint, ): [P, bigint]; @@ -45,20 +44,23 @@ export const WitnessPrivateState = { }, }; -export const WitnessWitnesses = (): IWitnessWitnesses => ({ +export const WitnessWitnesses = (): IWitnessWitnesses< + L, + WitnessPrivateState +> => ({ wit_secretBytes( - context: WitnessContext, + context: WitnessContext, ): [WitnessPrivateState, Uint8Array] { return [context.privateState, context.privateState.secretBytes]; }, wit_secretFieldPlusArg( - context: WitnessContext, + context: WitnessContext, arg: bigint, ): [WitnessPrivateState, bigint] { return [context.privateState, context.privateState.secretField + arg]; }, wit_secretUintPlusArgs( - context: WitnessContext, + context: WitnessContext, arg1: bigint, arg2: bigint, ): [WitnessPrivateState, bigint] { diff --git a/packages/simulator/test/integration/SampleZOwnableSimulator.ts b/packages/simulator/test/integration/SampleZOwnableSimulator.ts index c288e259..e2e26f2f 100644 --- a/packages/simulator/test/integration/SampleZOwnableSimulator.ts +++ b/packages/simulator/test/integration/SampleZOwnableSimulator.ts @@ -11,14 +11,15 @@ import { SampleZOwnableWitnesses, } from '../fixtures/sample-contracts/witnesses/SampleZOwnableWitnesses'; -/** - * Type constructor args - */ +/** Type constructor args */ type SampleZOwnableArgs = readonly [ owner: Uint8Array, instanceSalt: Uint8Array, ]; +/** Concrete ledger type extracted from the generated artifact */ +type SampleZOwnableLedger = ReturnType; + /** * Base simulator */ @@ -36,7 +37,7 @@ const SampleZOwnableSimulatorBase = createSimulator< return [owner, instanceSalt]; }, ledgerExtractor: (state) => ledger(state), - witnessesFactory: () => SampleZOwnableWitnesses(), + witnessesFactory: () => SampleZOwnableWitnesses(), }); /** diff --git a/packages/simulator/test/integration/WitnessSimulator.ts b/packages/simulator/test/integration/WitnessSimulator.ts index c5b07041..e03ac46f 100644 --- a/packages/simulator/test/integration/WitnessSimulator.ts +++ b/packages/simulator/test/integration/WitnessSimulator.ts @@ -8,11 +8,12 @@ import { WitnessWitnesses, } from '../fixtures/sample-contracts/witnesses/WitnessWitnesses'; -/** - * Type constructor args - */ +/** Type constructor args */ type WitnessArgs = readonly []; +/** Concrete ledger type extracted from the generated artifact */ +type WitnessLedger = ReturnType; + /** * Base simulator */ @@ -30,7 +31,7 @@ const WitnessSimulatorBase = createSimulator< return []; }, ledgerExtractor: (state) => ledger(state), - witnessesFactory: () => WitnessWitnesses(), + witnessesFactory: () => WitnessWitnesses(), }); /**