Skip to content

Commit

Permalink
tried some modifier tricks, this is good enough as is
Browse files Browse the repository at this point in the history
  • Loading branch information
erhant committed Jan 3, 2024
1 parent 034d940 commit 486ba8a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 47 deletions.
48 changes: 48 additions & 0 deletions src/contracts/modifiers/apply.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type {ContractInputGeneric, ContractState} from '../types';

/**
* Apply allows one to execute modifiers which are functions that are run
* before the function body is executed, similar to [Solidity modifiers](https://docs.soliditylang.org/en/latest/contracts.html#function-modifiers).
*
* The first three arguments are mandatory, and the remaining arguments are expected to be modifier functions. These modifiers
* will run in the order they appear, and if all pass, a result with the same type of the input is returned.
*
* For example, consider a function call with the following type:
*
* ```ts
* {
* function: "divide",
* value: {
* a: number,
* b: number,
* }
* }
* ```
*
* We take two numbers and return `a/b`. We can write a modifier to ensure `b` is non-zero.
*
* ```ts
* const {a, b} = await apply(caller, input.value, state,
* (caller, input, state) => {
* if (input.b === 0) {
* throw new Error("denominator cant be zero");
* }
* return input;
* }
* );
* ```
*
* Due to the generic template parameters, when `apply` is used within the switch-case of the `handle` function, it gets type-safety
* based on which function is being handled!
*/
export async function apply<I extends ContractInputGeneric['value'], S extends ContractState>(
caller: string,
input: I,
state: S,
...modifiers: ((caller: string, input: I, state: S) => I | Promise<I>)[]
): Promise<typeof input> {
for (const modifier of modifiers) {
input = await modifier(caller, input, state);
}
return input;
}
49 changes: 2 additions & 47 deletions src/contracts/modifiers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export {apply} from './apply';

import {ExpectedProofError, InvalidProofError, NotOwnerError, NotWhitelistedError, NullValueError} from '../errors';
import {verifyProof} from '../utils';
import {ContractState} from '../types';
Expand Down Expand Up @@ -77,50 +79,3 @@ export const onlyProofVerified = <I extends {key: string; value?: unknown; proof
return input;
};
};

/**
* Apply allows one to execute modifiers which are functions that are run
* before the function body is executed, similar to [Solidity modifiers](https://docs.soliditylang.org/en/latest/contracts.html#function-modifiers).
*
* The first three arguments are mandatory, and the remaining arguments are expected to be modifier functions. These modifiers
* will run in the order they appear, and if all pass, a result with the same type of the input is returned.
*
* For example, consider a function call with the following type:
*
* ```ts
* {
* function: "divide",
* value: {
* a: number,
* b: number,
* }
* }
* ```
*
* We take two numbers and return `a/b`. We can write a modifier to ensure `b` is non-zero.
*
* ```ts
* const {a, b} = await apply(caller, input.value, state,
* (caller, input, state) => {
* if (input.b === 0) {
* throw new Error("denominator cant be zero");
* }
* return input;
* }
* );
* ```
*
* Due to the generic template parameters, when `apply` is used within the switch-case of the `handle` function, it gets type-safety
* based on which function is being handled!
*/
export async function apply<I, S extends ContractState>(
caller: string,
input: I,
state: S,
...modifiers: ((caller: string, input: I, state: S) => I | Promise<I>)[]
): Promise<typeof input> {
for (const modifier of modifiers) {
input = await modifier(caller, input, state);
}
return input;
}

0 comments on commit 486ba8a

Please sign in to comment.