API ReferenceValidationFunction
runValidation()
function runValidation<P>(ctx, rules, params, signal?): Promise<ValidationIssue[]>;Runs a set of ValidationRules against (possibly partial)
operation parameters, without touching a wallet. This is the engine behind sdk.loc.validate* and
sdk.vault.validate*; call it directly only when composing your own rule set. Sync checks are pure;
async checks read chain and subgraph state through ctx.
Type Parameters
| Type Parameter |
|---|
P |
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | SDKContext | The SDK context — pass your AnvilSDK instance, which implements SDKContext. Rules read ctx.deps for the RPC client, subgraph, and locConfig. |
rules | readonly ValidationRule<P>[] | The rule set to evaluate, normally one of the exported per-operation arrays such as createStaticLOCRules or redeemLOCRules. Rules run in array order; a rule only fires when every dependsOn field is non-nullish. |
params | Partial<P> | The operation’s parameters, possibly incomplete — a form’s current values are the intended input. A missing field that is a rule’s own errorField reports FieldRequired for that rule; a missing field that is only a foreign dependency skips the rule silently. |
signal? | AbortSignal | Optional AbortSignal forwarded to async rules. When omitted a no-op signal is used (never aborted). Caller cancellation rejects with the signal’s exact reason, without normalization. |
Returns
Promise<ValidationIssue[]>
Remarks
Executes all rules eagerly (no debouncing). For each rule:
- If the rule’s own
errorFieldis among itsdependsOnand that value is missing, report oneFieldRequiredissue for that field and skip the rule’s sync/async callbacks entirely — a rule declares a field required by depending on the field it reports on. - Otherwise, if any
dependsOnfield is missing, skip the rule silently (a foreign dependency isn’t ready yet; that isn’t this field’s verdict). - Run sync. If sync returns issues, skip async.
- If sync passes and rule has async, run async with the caller’s signal.
- Collect all issues from all rules. Duplicate
FieldRequiredissues for the same field (e.g. two rule factories composed for one field) collapse to one.
A resolved array means every applicable rule completed: empty is valid, non-empty is domain-invalid.
It never carries a partial list — an infrastructure failure rejects instead of resolving.
Critically, an empty list never means “nothing could run” — a rule whose own required field is
absent reports that absence rather than being silently skipped, so [] unambiguously means checked
and valid.
useIncrementalValidation’s field-level dependency gating is unchanged: its per-keystroke path
still defers a rule silently while dependencies are incomplete, so a form doesn’t flash unrelated
errors mid-entry. Only this eager path and its validateAll submit-time counterpart report the
required-field absence. A rule whose errorField is not one of its own dependsOn entries is
optional by construction and never reports absence.
A rejected async rule is not a field verdict: this promise rejects with a normalized SDK error and
exposes none of the issues collected by the incomplete run. Existing
BaseError instances preserve identity; recognizable provider failures
become ProviderConnectionError; and unclassifiable failures
become ContactSupportError with the original rejection as
cause.
Throws
ProviderConnectionError when a rule rejects with a recognizable provider or transport failure.
Throws
ContactSupportError when a rejected rule failure cannot be classified. Existing SDK errors and caller abort reasons propagate unchanged.
Example
// Partial params are safe to call with: a rule whose own required field is// absent reports `FieldRequired` for that field instead of being silently// skipped, while a rule missing only a foreign (non-required) dependency// still defers silently. This draft deliberately omits the required// `expirationTimestampSeconds`, so that rule reports it instead of being// silently skipped. `tokenAmount` is well-formed here, so// `staticLOCCollateralRules`' async checks also run against live chain// state alongside it -- expect more than just the one field, and a// rejection instead of a resolved array without a connected wallet.const draft: Partial<CreateStaticLOCParams> = { beneficiary: '0x1111111111111111111111111111111111111111', tokenAmount: { tokenAddress: testnetProfile.contracts.USDC.address, amount: 250_000_000n, },};// The SDK instance is the SDKContext; async rules read chain and subgraph// state through it.const issues = await runValidation(sdk, createStaticLOCRules, draft);if (issues.length === 0) return 'ok';return issues.map(i => `${i.field}: ${getValidationErrorMessage(i)}`);