Variables are the mechanism that keeps your rules flexible and maintainable over time. Instead of hardcoding values directly into rule logic, variables allow you to reference externally-managed data — sanctions lists, risk thresholds, account categories — that can be updated independently of the rules themselves.Documentation Index
Fetch the complete documentation index at: https://docs.finwatch.finance/llms.txt
Use this file to discover all available pages before exploring further.
The Problem: Hardcoded Data in Rules
Consider this rule:- Edit the
.wsfile. - Commit the change.
- Get it reviewed and merged.
- Wait for FinWatch to pick up the change.
Variable Syntax
Variables in Watch Script are prefixed with$:
Naming Conventions
- Always use
$snake_case. - The name should clearly describe the content.
- Good:
$sanctioned_countries,$high_risk_mccs,$blocked_card_bins - Bad:
$list1,$data,$x,$SC
Where Variables Are Used
Variables appear in two contexts within the Watch Script DSL:- As values in comparisons — typically with the
inoperator: - As dynamic field references with
$current— inside function arguments:
$sanctioned_countries) reference static or semi-static data managed outside the rule. The $current variable references the transaction currently being evaluated.
$current — The Current Transaction Context
The $current variable is a special, built-in variable that provides access to the fields of the transaction currently being evaluated. It is the bridge between “this transaction” and “historical transactions” — enabling you to ask questions like “how many other transactions share characteristics with this one?”
Syntax
<field_name> is any top-level field on the transaction: source, destination, amount, currency, description, status, etc.
How It Works Internally
When the interpreter encounters a$current.* reference, it calls the resolvePlaceholder() function:
- Checks if the value is a string starting with
"$current.". - Strips the
"$current."prefix to get the field path. - Calls
dig()to look up the field in the current transaction’s data. - Returns the resolved value.
nil and the condition evaluates to false.
Common Usage Patterns
Inside Aggregate Functions
The most common use of$current is inside aggregate function filters, where it creates self-referencing queries:
$current, you’d have no way to make an aggregate filter relative to the current transaction. You’d have to hardcode a specific account ID, which would make the rule useless for anyone else.
Inside previous_transaction() Match
$current references are also used inside the match object of previous_transaction():
match, the $current reference is a string value (with quotes): "$current.source". This is because the match object uses string values that are resolved at runtime by the interpreter.
In Simple Comparisons
You can also use$current in simple conditions to compare fields:
Example: Self-Transfer Detection
External Variable Lists
External variables like$sanctioned_countries reference data that lives outside the rule file. This data is managed separately and injected into the rule engine at evaluation time.
How External Variables Work
When the parser encounters a variable like$sanctioned_countries, it stores it as a Variable AST node with the name sanctioned_countries. During compilation to the JSON rule format, the variable is preserved as a reference. At evaluation time, the interpreter resolves the variable against a variable registry — a key-value store of variable names to their values.
Defining Variable Lists
Variables are typically defined in a configuration file or through an API. The exact mechanism depends on your FinWatch deployment, but the pattern is always the same:Using Variables in Rules
Once defined, variables can be used in any rule:Updating Variables Without Redeploying Rules
The key benefit of variables is operational agility. When the OFAC sanctions list is updated:- Update the
$sanctioned_countriesvariable in your configuration. - FinWatch picks up the new values.
- All rules referencing
$sanctioned_countriesimmediately use the updated list. - No rule files are modified. No Git commits. No PR reviews for the rule itself.
Practical Patterns
Pattern 1: Blacklists
Block or flag transactions involving known-bad entities:Pattern 2: Whitelists
Allow transactions that match trusted criteria (use withallow verdict):
Pattern 3: Dynamic Thresholds
Use variables for thresholds that vary by region or account type:Pattern 4: Regional Configuration
Different regions may have different risk profiles:$high_risk_regions variable can be maintained by your regional compliance teams without touching the rule logic.
Variable Resolution Order
When the interpreter evaluates a condition, it resolves values in this order:- Literal values — Numbers (
10000), strings ("USD"), booleans (true,false), and inline arrays (("a", "b", "c")) are used as-is. $current.*references — Resolved against the current transaction’s fields usingresolvePlaceholder().- External variables — Resolved against the variable registry.
- Missing values — If a
$current.*field doesn’t exist, the condition returnsfalse. If an external variable isn’t defined, the behavior depends on the operator (forin, an empty list means no match).
Best Practices
Keep Rules Logic-Only
A rule should contain logic, not data. If you find yourself listing more than 2-3 values inline, extract them into a variable:Name Variables Descriptively
The variable name should tell a reader exactly what it contains without needing to look up the definition:| Bad | Good |
|---|---|
$list | $sanctioned_countries |
$codes | $high_risk_mcc_codes |
$bad | $blocked_card_bins |
$t | $max_daily_transfer_limit |
Document Variable Sources
For each variable, document:- Where the data comes from (OFAC, internal fraud database, compliance team).
- How often it’s updated (daily, weekly, quarterly).
- Who is responsible for maintaining it.
- What format the values are in (ISO country codes, 6-digit BINs, account IDs).
Use $current Consistently
When writing aggregate filters or previous_transaction() match criteria, always use $current.* to reference the current transaction. Never hardcode account IDs or other transaction-specific values in a rule.
Next Steps
- GitOps Rule Management — Learn how to version and deploy your rules (and variable configurations) using Git.
- Aggregate Functions Guide — See how
$currentis used extensively in aggregate filters. - Previous Transaction Lookups — Use
$currentreferences inmatchobjects. - The Rule Cookbook — Production-ready rules that demonstrate variable usage patterns.
- DSL Reference — Complete variable syntax reference.
.png?fit=max&auto=format&n=0JF6z69u57hmqsWm&q=85&s=531373acedba0eb783b669f6d558dfd8)