Skip to content

Commit 3878cac

Browse files
committed
docs: consolidate on deploy-quicknode-filter.sh as single source of truth
The repo had two conflicting paths for QuickNode filter deployment: 1. bin/update-quicknode-filter.js → infra/quicknode.tf (legacy, never worked) 2. bin/deploy-quicknode-filter.sh → QuickNode template API (current, working) The Terraform path was always dead: ignore_all_server_changes=true prevents Terraform from pushing filter_function changes to existing webhooks. Changes: - Delete bin/update-quicknode-filter.js (zombie script) - Remove dead dev:webhook:* npm scripts that invoked it - Add prominent deprecation notice to infra/quicknode.tf explaining that filter_function blobs are not deployed and all updates go via the script - Rewrite README.md QuickNode section to document the actual deploy workflow - Rewrite ADDING_EVENTS.md to replace Terraform migration steps with deploy-quicknode-filter.sh instructions - Document the contracts address filtering quirk (silently ignored by QuickNode API — filtering must be done in the Cloud Function handler)
1 parent f283520 commit 3878cac

File tree

5 files changed

+62
-214
lines changed

5 files changed

+62
-214
lines changed

ADDING_EVENTS.md

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,20 @@ function main(data) {
5555
}
5656
```
5757

58-
**Enable hot-reload** to automatically update the filter function in Terraform:
58+
**Deploy the updated filter to QuickNode** using the deploy script:
5959

6060
```bash
61-
# For governance events
62-
npm run dev:webhook:governor
61+
# Deploy a specific webhook
62+
./bin/deploy-quicknode-filter.sh --webhook healthcheck # SortedOracles
63+
./bin/deploy-quicknode-filter.sh --webhook governor # MentoGovernor
6364

64-
# For oracle/sorted-oracles events
65-
npm run dev:webhook:healthcheck
65+
# Deploy both
66+
./bin/deploy-quicknode-filter.sh
6667
```
6768

68-
This watches for changes to your filter function file and automatically base64-encodes it into [`infra/quicknode.tf`](infra/quicknode.tf).
69+
The deploy script reads the ABI and contract addresses from the `/* template: evmAbiFilter ... */` comment header at the top of each filter file and applies the update live via `PATCH /webhooks/{id}/template/evmAbiFilterGo` (no downtime required).
70+
71+
> **Note:** The old `npm run dev:webhook:*` scripts and `bin/update-quicknode-filter.js` are legacy — they updated `infra/quicknode.tf` which is never applied to live webhooks (`ignore_all_server_changes = true`). Use `deploy-quicknode-filter.sh` instead.
6972
7073
#### 3. Test the Filter Function with Real Blockchain Data
7174

@@ -104,36 +107,29 @@ Once your filter function works correctly:
104107

105108
**Pro tip:** Using real data ensures your fixture accurately represents what QuickNode will send in production.
106109

107-
#### 5. Clean Up and Migrate to Terraform
110+
#### 5. Clean Up and Make Permanent
108111

109-
1. **Delete the temporary webhook** from the [QuickNode Webhooks Dashboard](https://dashboard.quicknode.com/webhooks)
110-
1. **Write Terraform code** in [`infra/quicknode.tf`](infra/quicknode.tf) to automate webhook creation:
112+
1. **Delete the temporary test webhook** from the [QuickNode Webhooks Dashboard](https://dashboard.quicknode.com/webhooks) (the one you created manually for testing).
111113

112-
```hcl
113-
resource "quicknode_webhook" "your_event_webhook" {
114-
name = "Your Event Webhook"
115-
url = google_cloudfunctions2_function.watchdog_notifications.url
116-
network = "celo-mainnet"
117-
dataset = "block"
118-
enabled = true
114+
2. **Update the filter file comment header** with your final ABI and contract address:
119115

120-
filter_function = base64encode(file("${path.module}/quicknode-filter-functions/your-filter.js"))
116+
```js
117+
/*
118+
template: evmAbiFilter
119+
abi: [{...your trimmed ABI events...}]
120+
contracts: 0xYourContractAddress
121+
*/
122+
```
121123

122-
headers = {
123-
"X-AUTH-TOKEN" = var.x_auth_token
124-
}
125-
}
126-
```
124+
Keep only the events your handler actually uses — this reduces Cloud Function invocation volume.
127125

128-
1. **Deploy the webhook via Terraform**:
126+
3. **Deploy to the permanent webhook** via:
129127

130-
```bash
131-
cd infra
132-
terraform plan # Review changes
133-
terraform apply # Create the webhook
134-
```
128+
```bash
129+
./bin/deploy-quicknode-filter.sh --webhook <healthcheck|governor>
130+
```
135131

136-
**Note:** If updating an existing webhook's filter function, you may need to pause it first or destroy and recreate it (see [README](README.md#workflow) for details).
132+
> **Note:** Terraform (`infra/quicknode.tf`) manages webhook _creation_ but cannot update filter configuration on existing webhooks (`ignore_all_server_changes = true`). All filter updates go through `bin/deploy-quicknode-filter.sh`.
137133
138134
### Part 2: Implement TypeScript Event Handler
139135

README.md

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -209,55 +209,40 @@ The centralized event system makes adding new events straightforward—just upda
209209

210210
## Developing QuickNode Webhook Filter Functions
211211

212-
QuickNode webhooks use [JavaScript filter functions](https://www.quicknode.com/docs/streams/filters?#example-filter-functions) that run on QuickNode's servers to determine which blockchain events should trigger notifications to our Cloud Function. These filters are base64-encoded and stored in [`infra/quicknode.tf`](./infra/quicknode.tf) under the `filter_function` properties.
212+
QuickNode webhooks use the `evmAbiFilter` template to match blockchain events by ABI event signature. Filter configuration (ABI and contract addresses) lives in the comment header of each filter file under [`infra/quicknode-filter-functions/`](./infra/quicknode-filter-functions/).
213213

214-
### Workflow
214+
> **Note:** The `filter_function` base64 blobs in `infra/quicknode.tf` and the old `bin/update-quicknode-filter.js` script are **legacy artefacts**. They are not deployed — `ignore_all_server_changes = true` in Terraform prevents Terraform from pushing any changes to existing webhooks. All deploys go through `bin/deploy-quicknode-filter.sh`.
215215
216-
1. [OPTIONAL] If you want to first double-check which code is actually deployed right now:
217-
- Navigate to the [QuickNode Webhooks Dashboard](https://dashboard.quicknode.com/webhooks)
218-
- Click the Webhook you're developing
219-
- Copy the webhook ID from the URL into your clipboard
220-
- Obtain the current filter function via:
216+
### Workflow
221217

222-
```bash
223-
curl -X GET \
224-
"https://api.quicknode.com/webhooks/rest/v1/webhooks/$webhook_id" \
225-
-H "accept: application/json" \
226-
-H "x-api-key: $quicknode_api_key" \
227-
| jq -r .filter_function \
228-
| base64 -d
229-
```
218+
1. **Edit the filter file** at [`infra/quicknode-filter-functions/sorted-oracles.js`](./infra/quicknode-filter-functions/sorted-oracles.js) or [`governor.js`](./infra/quicknode-filter-functions/governor.js).
230219

231-
2. **Open the filter function** in plain JavaScript at [`infra/quicknode-filter-functions/sorted-oracles.js`](./infra/quicknode-filter-functions/sorted-oracles.js)
220+
The comment header at the top of each file is the deployment source of truth:
221+
```js
222+
/*
223+
template: evmAbiFilter
224+
abi: [{...}]
225+
contracts: 0xYourContractAddress
226+
*/
227+
```
232228

233-
3. **Enable hot-reload** to automatically update the Terraform file:
229+
2. **Deploy to QuickNode** using the deploy script:
234230

235231
```sh
236-
# Run the cmd for the webhook you're interested in
237-
npm run dev:webhook:healthcheck
232+
./bin/deploy-quicknode-filter.sh --webhook healthcheck # SortedOracles
233+
./bin/deploy-quicknode-filter.sh --webhook governor # MentoGovernor
234+
./bin/deploy-quicknode-filter.sh # both
238235
```
239236

240-
This will watch for changes to `sorted-oracles.js` (which we're using as the healthcheck) and automatically:
241-
- Base64 encode the updated function
242-
- Update the `filter_function` field in the `quicknode_webhook_healthcheck` resource in `quicknode.tf`
243-
- Create a timestamped backup of `quicknode.tf` before making changes
244-
245-
4. **Make your changes** to `sorted-oracles.js` and save the file. The script will automatically update `quicknode.tf`.
237+
This reads the ABI and contract addresses from the comment header, builds the `templateArgs` payload, and calls `PATCH /webhooks/{id}/template/evmAbiFilterGo` to apply the update live (no downtime).
246238

247-
5. **Review the changes** with `git diff infra/quicknode.tf` to ensure the filter function was updated correctly.
239+
3. **Verify** by checking the [QuickNode Webhooks Dashboard](https://dashboard.quicknode.com/webhooks) or inspecting the raw webhook via:
248240

249-
6. **Deploy to QuickNode**:
250-
251-
```sh
252-
cd infra
253-
terraform plan # Review changes
254-
terraform apply # Deploy
241+
```bash
242+
curl -X GET "https://api.quicknode.com/webhooks/rest/v1/webhooks/$webhook_id" \
243+
-H "x-api-key: $quicknode_api_key"
255244
```
256245

257-
**⚠️ Important:** QuickNode rejects updates to active webhooks. You must either:
258-
- Pause the webhook first (set `status = "paused"` in the resource, run `terraform apply`, then update the filter function, then set `status = "active"` and `terraform apply` again)
259-
- OR comment out the webhook resource, `terraform apply` to delete it, uncomment with your changes, and `terraform apply` to recreate it
260-
261246
### Filter Function Structure
262247

263248
The filter functions follow QuickNode's `evmAbiFilter` template:
@@ -267,6 +252,8 @@ The filter functions follow QuickNode's `evmAbiFilter` template:
267252
- They can include custom filtering logic (e.g., filtering by specific token addresses)
268253
- They return matching events or `null` if no matches found
269254

255+
> **Important quirk:** The `evmAbiFilter` template filters by topic hash only — the `contracts` address filter in `templateArgs` is currently **silently ignored** by QuickNode's API. All addresses that emit a matching event signature will trigger the webhook. Address filtering must be done in the Cloud Function handler.
256+
270257
See the [QuickNode Webhooks documentation](https://www.quicknode.com/docs/webhooks/getting-started) for more details on filter function syntax.
271258

272259
## Deploying from Scratch

bin/update-quicknode-filter.js

Lines changed: 0 additions & 148 deletions
This file was deleted.

infra/quicknode.tf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# ⚠️ IMPORTANT: The `filter_function` blobs in this file are NOT the deployment source of truth.
2+
#
3+
# These base64-encoded JS blobs were used historically, but `ignore_all_server_changes = true`
4+
# prevents Terraform from ever pushing filter changes to existing webhooks. The live webhook
5+
# configuration is managed separately via `bin/deploy-quicknode-filter.sh`, which reads the
6+
# ABI and contracts from the comment header in each filter file and calls the QuickNode
7+
# template API directly.
8+
#
9+
# To update a webhook filter, edit the comment header in the relevant filter file
10+
# (infra/quicknode-filter-functions/*.js) and run:
11+
# ./bin/deploy-quicknode-filter.sh --webhook <healthcheck|governor>
12+
#
13+
# Terraform is only used here to CREATE webhooks (on initial bootstrap). Updates use the script.
14+
#
115
# 🚨 Note: The QuickNode API rejects updates to active webhooks
216
#
317
# It needs to be paused before updating. To update one of the below webhooks EITHER:

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"deploy:function": "./bin/deploy-via-gcloud.sh",
1313
"destroy": "terraform -chdir=infra destroy",
1414
"dev": "nodemon --ext ts --ignore dist --exec \"npm run start\"",
15-
"dev:webhook:healthcheck": "nodemon --watch infra/quicknode-filter-functions/sorted-oracles.js --exec \"node bin/update-quicknode-filter.js\"",
1615
"gcp-build": "npm run build",
1716
"generate:env": "terraform -chdir=infra apply -target=local_file.env_file",
1817
"logs": "./bin/get-logs.sh",

0 commit comments

Comments
 (0)