In this tutorial we will be setting up the OpenZeppelin monitor and creating a custom monitor to get alerts on large USDC transfers and send them to a Telegram chat.

To follow along you’ll need Rust installed. Let’s start by forking and building the repository:
git clone https://github.com/openzeppelin/openzeppelin-monitor
cargo build --release
mv ./target/release/openzeppelin-monitor .
The final command moves the built program into the root folder so it can access the config files.
Token Monitor
Now we need to edit the configuration files in config/
The contract address for the USDC token on mainnet is:
CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75
We can get a contract interface using the Stellar cli
stellar contract info interface --network mainnet --rpc-url https://mainnet.sorobanrpc.com --network-passphrase "Public Global Stellar Network ; September 2015" --id CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75
This shows that the contract has the following function used to transfer funds from one account to another. Note in practice you might want to monitor transfer_from as well which you can do simultaneously:
fn transfer(
env: soroban_sdk::Env,
from: soroban_sdk::Address,
to: soroban_sdk::Address,
amount: i128,
);
Let’s open up config/monitors/stellar_swap_dex.json.example
Edit the name, contract address, match_conditions and remove the trigger_conditions, finally renaming the stellar_custom_trigger
The final file should look like this:
{
"name": "USDC Transfers",
"paused": false,
"networks": [
"stellar_mainnet"
],
"addresses": [
{
"address": "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75"
}
],
"match_conditions": {
"functions": [
{
"signature": "transfer(Address,Address,I128)",
"expression": null
}
],
"events": [],
"transactions": [
{
"status": "Success",
"expression": null
}
]
},
"trigger_conditions": [{
"script_path": "./config/filters/stellar_filter_block_number.sh",
"language": "Bash",
"timeout_ms": 1000
}],
"triggers": [
"stellar_usdc_telegram_trigger"
]
}
Save the file to a .json removing the .example file extension i.e. config/monitors/usdc_transfers.json
Note that we have the trigger condition ./config/filters/stellar_filter_block_number.sh which as default only allows even blocks. We can edit this file to remove the if statement and always return true.
echo "Ledger number $ledger_number is even"
echo "Verbose mode: $verbose"
echo "true"
exit 0
Note. I tried removing the link to this block number filter altogether from the monitor config file but this caused an issue which prevented the trigger from running.
Telegram Trigger
Now let’s create the Telegram Trigger.
We need a Telegram bot token and a chat ID, open up a new chat with @BotFather in Telegram and type /newbot, give it a name and you’ll get given a token which is your API key.

Now if we click the new bot’s address to open a chat and then click the start button or send the /start command we will provide the required access so the bot can message you.
We then need to find out our own user ID by starting a conversation with: @userinfobot

Edit the config file at ./config/triggers/telegram_notifications.json.example
Add in your token and user id as the chat_id and save it to a .json again removing the .example extension i.e. kale_telegram_trigger.json
{
"stellar_usdc_telegram_trigger": {
"name": "USDC Transfer Telegram Notification",
"trigger_type": "telegram",
"config": {
"token": "1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"chat_id": "4678159110",
"disable_web_preview": true,
"message": {
"title": "USDC Transferred",
"body": "${monitor_name} | https://stellar.expert//explorer/public/tx/${transaction_hash}"
}
}
}
}
If we want to add more context to the body we can by using inputs such as:
"body": "${monitor_name} ${function_0_3} tokens | https://stellar.expert//explorer/public/tx/${transaction_hash}"
Now let’s run it up with:
cargo run

Note that you wont get any notification in the console that a event has been triggered with the standard –log-level
Give it a while while you wait for transfers and you should get some notifications through
