Chapter 4: Hands-On Exercise
Now that you understand the building blocks from Chapter 3, letβs build our complete price alert workflow. This workflow combines all the Capabilities we learned:
- HTTP Trigger - Receives alert data from the server
- EVM Write - Writes alerts to the RuleRegistry contract
- Cron Trigger - Monitors prices on a schedule
- EVM Read - Reads prices from Chainlink feeds and rules from the contract
- HTTP Client - Sends notifications when conditions are met
Our Workflow Structure
The complete workflow consists of:
main.ts- Initializes both HTTP and Cron triggers (see Chapter 3 for the pattern)httpCallback.ts- Handles HTTP trigger, decodes alert data, and writes to RuleRegistry using the two-step write patterncronCallback.ts- Handles cron trigger, reads prices and rules, evaluates conditions, and sends notificationstypes.ts- TypeScript type definitions for Config, Rule, PriceData, etc.config.staging.json- Workflow configuration
All the code patterns you need are covered in Chapter 3. Here, weβll focus on setting up and running the complete system.
Complete Demo Sequence
Step 0: Deploy RuleRegistry Contract
Deploy contracts/RuleRegistry.sol to Base Sepolia. Set USDC token address in constructor (Base Sepolia USDC: 0x036CbD53842c5426634e7929541eC2318f3dCF7e).
You can use this Remix IDE link for this.
π‘ Note the deployed contract address, we will use this later.
If you do not have testnet tokens or canβt deploy the contract for other reasons, you may use this one 0x9B9fC1EeF6BFC76CD07501Ae81b66f24fAB322B1. However, keep in mind that this demo contract may be populated with multiple alerts from other developers.
Step 1: Clone and Install
git clone https://github.com/smartcontractkit/x402-cre-price-alerts.git
cd x402-cre-price-alerts
npm install
This will install dependencies for both the server and cre/alerts workspaces. The cre/alerts post install script will automatically run bunx cre-setup.
Step 2: Configure Environment Variables
Create a .env file in the project root (workspace root):
cp .env.example .env
β οΈ The workspace setup uses a single
.envfile at the project root. Bothserverandcreworkspaces can access environment variables from this root.envfile. You may specify the.envfile when using the CRE CLI by passing the--envargument.
Edit .env with your values:
# Server Configuration
PORT=3000
X402_RECEIVER_ADDRESS=0x... # Your wallet or RuleRegistry address
X402_FACILITATOR_URL=https://x402.org/facilitator
GEMINI_API_KEY=your_gemini_api_key
AGENT_WALLET_PRIVATE_KEY=your_private_key # Must have USDC on Base Sepolia
# CRE Configuration
CRE_ETH_PRIVATE_KEY=your_eth_private_key
CRE_TARGET=staging-settings
PUSHOVER_USER_KEY_VAR=your_pushover_user_key
PUSHOVER_API_KEY_VAR=your_pushover_api_key
Environment Variables Explained:
PORT: Server port (default: 3000)X402_RECEIVER_ADDRESS: Address that receives x402 payments (Can be an EOA or Deployed RuleRegistry contract/contracts)X402_FACILITATOR_URL: x402 facilitator endpoint (default: https://x402.org/facilitator)GEMINI_API_KEY: Your Gemini API key for natural language processingAGENT_WALLET_PRIVATE_KEY: Private key of wallet used to make x402 payments (must have USDC on Base Sepolia). You can use the same key as your CRE PK.CRE_ETH_PRIVATE_KEY: ETH private key used for local simulation of EVM Write capabilityCRE_TARGET: Target profile for CLI commandsPUSHOVER_USER_KEY_VAR: Your Pushover user keyPUSHOVER_API_KEY_VAR: Your Pushover API key
Step 3: Configure CRE Workflow
Edit cre/alerts/config.staging.json for staging/testing (add your ruleRegistryAddress):
{
"schedule": "0 0 * * * *",
"ruleTTL": 1800,
"publicKey": "",
"evms": [
{
"ruleRegistryAddress": "your_deployed_rule_registry",
"chainSelectorName": "ethereum-testnet-sepolia-base-1",
"gasLimit": "1000000",
"dataFeeds": {
"BTC": "0x0FB99723Aee6f420beAD13e6bBB79b7E6F034298",
"ETH": "0x4aDC67696bA383F43DD60A9e78F2C97Fbbfc7cb1",
"LINK": "0xb113F5A928BCfF189C998ab20d753a47F9dE5A61"
}
}
]
}
Configuration Fields:
schedule: Cron expression for price checks (default: hourly -"0 0 * * * *")ruleTTL: Time to live of a created rule (30 minutes by default. Older rules will not receive alerts.)publicKey: Public key used to verify incoming HTTP Trigger requests. This field is empty for this demo. However, it is required when the full HTTP Trigger is implemented for production. See Line 64 ofserver/src/server.ts.ruleRegistryAddress: Address of your deployed RuleRegistry contractchainSelectorName: Chain selector for Base Sepolia ("ethereum-testnet-sepolia-base-1") See the chain selector referencegasLimit: Gas limit for on-chain writesdataFeeds: Chainlink price feed addresses for BTC, ETH, LINK on Base Sepolia. You can find Base Sepolia Price Feed addresses here.
Important:
- Replace
your_deployed_rule_registrywith the address from Step 0 - If you were unable to deploy, you may use
0x9B9fC1EeF6BFC76CD07501Ae81b66f24fAB322B1. Be aware that this demo contract may be populated with multiple alerts from other developers.
Step 4: Start the Server
From the repository root:
npm run dev:server
The server will start on http://localhost:3000 (or your configured PORT).
You should see:
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Unified API Server
Port: 3000 | Payment: $0.01 USDC
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Server ready
http://localhost:3000
POST /chat (natural language, no payment)
POST /alerts (requires x402 payment)
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Interactive Chat Enabled
Type your message and press Enter (type 'exit' or 'quit' to leave)
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Live Demo
Step 5: User Creates Alert (Natural Language)
Option A: Interactive Chat (Recommended)
In the server terminal, type:
> Create an alert when BTC is greater than 60000
[!NOTE]: this is deliberately set to below current market price so that the trigger fires.
Type exit or quit to disable chat (server continues running).
Option B: Direct API Call
Alternatively, send a POST request to the /chat endpoint:
curl -X POST http://localhost:3000/chat \
-H "Content-Type: application/json" \
-d '{"message":"Create an alert when BTC is greater than 60000"}'
What happens:
- Gemini AI interprets your message
- Extracts alert parameters (asset, condition, target price)
- Creates a paid alert via
/alertsendpoint with x402 payment - Returns alert details and payment transaction hash
Supported Assets: BTC, ETH, LINK only
Step 6: Copy Alert JSON Payload
From the server console output, copy the CRE payload JSON. It will look like:
CRE Workflow Payload (copy for HTTP trigger):
{"id":"42d2ea846d5b5e0ba439b68f8835188e023b74454c504df80ae0a0eb329eccd6","asset":"BTC","condition":"gt","targetPriceUsd":60000,"createdAt":1765324585}
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Step 7: Register the Alert in RuleRegistry ( using CRE HTTP Trigger)
Open a new terminal window so you can run commands.
Simulate the CRE HTTP Trigger to write the alert on-chain:
cd cre
cre workflow simulate alerts --env ../.env --broadcast
When prompted:
- Select HTTP trigger (option 2)
- Paste the JSON payload from Step 6
- The workflow will write the alert to the RuleRegistry contract on-chain
Example output:
2025-12-10T17:21:20Z [SIMULATION] Simulator Initialized
2025-12-10T17:21:20Z [SIMULATION] Running trigger trigger=http-trigger@1.0.0-alpha
2025-12-10T17:21:21Z [USER LOG] ββββββββββββββββββββββββββββββββββββββββββββββββββββ
2025-12-10T17:21:21Z [USER LOG] CRE Workflow: HTTP Trigger
2025-12-10T17:21:21Z [USER LOG] ββββββββββββββββββββββββββββββββββββββββββββββββββββ
2025-12-10T17:21:21Z [USER LOG] [Step 1] Received alert data: {"asset":"BTC","condition":"gt","createdAt":1765416045,"id":"1b381294cc2a9771743d80a3d11380cf4e377b64802a1c728776d2f6defed3cc","targetPriceUsd":10}
2025-12-10T17:21:21Z [USER LOG] [Step 2] Encoding alert data for on-chain write...
2025-12-10T17:21:21Z [USER LOG] [Step 3] Generating CRE report...
2025-12-10T17:21:21Z [USER LOG] [Step 4] Writing to RuleRegistry contract: 0x9B9fC1EeF6BFC76CD07501Ae81b66f24fAB322B1
2025-12-10T17:21:22Z [USER LOG] [Step 5] [SUCCESS] Transaction successful: 0x66b8b811d6902bfcfc5e5b4890602ec2620084f8dcc2a02e49a2dddc8d9f1a8a
2025-12-10T17:21:22Z [USER LOG] ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Workflow Simulation Result:
"0x66b8b811d6902bfcfc5e5b4890602ec2620084f8dcc2a02e49a2dddc8d9f1a8a"
2025-12-10T17:21:22Z [SIMULATION] Execution finished signal received
2025-12-10T17:21:22Z [SIMULATION] Skipping WorkflowEngineV2
Step 8: Simulate Cron Check On Price Conditions (using CRE Cron Trigger)
Execute the CRE CRON Trigger to check prices and send notifications:
cre workflow simulate alerts --env ../.env
When prompted:
- Select Cron trigger (option 1)
- The workflow will:
- Fetch current prices for BTC, ETH, LINK from Chainlink feeds
- Check all rules stored on-chain
- Send Pushover notifications when conditions are met
Example output:
2025-12-10T17:22:53Z [SIMULATION] Simulator Initialized
2025-12-10T17:22:53Z [SIMULATION] Running trigger trigger=cron-trigger@1.0.0
2025-12-10T17:22:53Z [USER LOG] ββββββββββββββββββββββββββββββββββββββββββββββββββββ
2025-12-10T17:22:53Z [USER LOG] CRE Workflow: Cron Trigger
2025-12-10T17:22:53Z [USER LOG] ββββββββββββββββββββββββββββββββββββββββββββββββββββ
2025-12-10T17:22:53Z [USER LOG] [Step 1] Fetching price data from Chainlink feeds...
2025-12-10T17:22:53Z [USER LOG] β’ BTC: $90855.76
2025-12-10T17:22:53Z [USER LOG] β’ ETH: $3253.52
2025-12-10T17:22:53Z [USER LOG] β’ LINK: $13.76
2025-12-10T17:22:53Z [USER LOG] [Step 2] Found 2 rules on-chain
2025-12-10T17:22:53Z [USER LOG] [Step 3] Checking 2 rules...
2025-12-10T17:22:53Z [USER LOG] [Rule 1] [SUCCESS] Condition met: BTC $90855 gt $5
2025-12-10T17:22:53Z [USER LOG] -> Pushover notification sent (Status: 200)
2025-12-10T17:22:53Z [USER LOG] [Rule 2] [SUCCESS] Condition met: BTC $90855 gt $10
2025-12-10T17:22:54Z [USER LOG] -> Pushover notification sent (Status: 200)
2025-12-10T17:22:54Z [USER LOG] [Step 4] [SUCCESS] Complete: 2 notification(s) sent
2025-12-10T17:22:54Z [USER LOG] ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Workflow Simulation Result:
"Processed 2 rules, sent 2 notifications"
2025-12-10T17:22:54Z [SIMULATION] Execution finished signal received
2025-12-10T17:22:54Z [SIMULATION] Skipping WorkflowEngineV2
β οΈ The cron trigger runs automatically on the configured schedule once deployed. The frequency of the CRON trigger is set within
cre/alerts/config.staging.json, as well as the Rule TTL.
Step 9: Review the Pushover notification on your device
π Check your phone!
You should receive a push notification when the price condition is met.
Step 10: (Optional) View balance of x402 Receiver
If you set your x402 Receiver in the root .env file (X402_RECEIVER_ADDRESS) to your RuleRegistry contract, call the getUSDCBalance() function to see the USDC received from x402 payments.
Step 11: (Optional) Withdraw USDC tokens from RuleRegistry
If you set your x402 Receiver in the root .env file (X402_RECEIVER_ADDRESS) to your RuleRegistry contract, call the withdrawUSDC(address, amount) function to withdraw USDC received from x402 payments. Reminder, USDC uses 6 decimal places!
Success Checklist
- β Contract deployed to Base Sepolia
- β Server running and configured
- β Alert created via natural language chat
- β x402 payment processed ($0.01 USDC)
- β Alert written to contract (transaction hash verified)
- β Cron trigger executed
- β Push notification received π―
Troubleshooting
No notification?
- Verify Pushover credentials in
.env(PUSHOVER_USER_KEY_VARandPUSHOVER_API_KEY_VAR) - Check rule was written to contract (verify transaction hash on Base Sepolia Explorer)
- Current price must meet condition (e.g., BTC > $60,000 in example)
- Rule TTL is 30 minutes (1800 seconds) - create new alert if expired
Workflow errors?
- Verify contract address in
config.staging.jsonmatches deployed address - Check wallet has ETH for gas (simulation mode)
- Verify CRE CLI authenticated:
cre auth status - Check all environment variables are set correctly
- Verify
CRE_TARGET=staging-settingsmatches your workflow target configuration
x402 payment issues?
- Verify
AGENT_WALLET_PRIVATE_KEYhas USDC on Base Sepolia - Check
X402_RECEIVER_ADDRESSis set correctly - Verify facilitator URL is accessible
Gemini API issues?
- Rate limit exceeded error? Make sure you set up billing. Free tier for this masterclass is fine, but Google sometimes still requires your credit card is connected to the Gemini API key.