AutomationFlowsSlack & Telegram › Daily Eth Wallet Monitoring with Etherscan, Coingecko Pricing & Discord Alerts

Daily Eth Wallet Monitoring with Etherscan, Coingecko Pricing & Discord Alerts

ByKaden Reese @kadenreese on n8n.io

Never miss a snapshot of your (or others) ETH wallet, this workflow polls your wallet on a schedule, fetches balances and current ETH prices, formats a concise summary, and posts it to Discord (or email/Slack/Telegram). Easy to customize to track multiple wallets, tokens, or…

Cron / scheduled trigger★★★★☆ complexity13 nodesHTTP RequestDiscord
Slack & Telegram Trigger: Cron / scheduled Nodes: 13 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #8992 — we link there as the canonical source.

This workflow follows the Discord → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "220614c6-c32f-41ba-9669-2532c13a21f6",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "45 7,17 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2fbe1f25-d09c-43da-933e-6903c6b2155b",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        208,
        0
      ],
      "parameters": {
        "url": "=https://api.etherscan.io/v2/api?chainid=1&module=account&action=tokentx&address=YOUR_WALLET_HERE&sort=asc&apikey=YOUR_KEY_HERE",
        "method": "=GET",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "755d4d95-2ff5-4023-8c37-005dc7f3ea69",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        416,
        0
      ],
      "parameters": {
        "jsCode": "// Input: JSON response from Etherscan tokentx endpoint\nconst wallet = \"YOUR_WALLET_ADDRESS\".toLowerCase();\nconst txs = items[0].json.result;  // Assuming the HTTP node passed the Etherscan JSON\n\n// Reduce transactions into balances\nconst balances = {};\n\nfor (const tx of txs) {\n  const symbol = tx.tokenSymbol;\n  const decimals = parseInt(tx.tokenDecimal);\n  const value = BigInt(tx.value);\n\n  // Initialize token entry if missing\n  if (!balances[symbol]) {\n    balances[symbol] = {\n      contract: tx.contractAddress,\n      tokenName: tx.tokenName,\n      tokenSymbol: tx.tokenSymbol,\n      decimals: decimals,\n      raw: BigInt(0)\n    };\n  }\n\n  // If wallet is the recipient => add\n  if (tx.to.toLowerCase() === wallet) {\n    balances[symbol].raw += value;\n  }\n\n  // If wallet is the sender => subtract\n  if (tx.from.toLowerCase() === wallet) {\n    balances[symbol].raw -= value;\n  }\n}\n\n// Convert raw balances to human-readable\nconst results = Object.values(balances).map(t => {\n  return {\n    token: t.tokenSymbol,\n    contract: t.contract,\n    amount: Number(t.raw) / (10 ** t.decimals),\n    decimals: t.decimals\n  };\n});\n\n// Return in N8N format\nreturn results.map(r => ({ json: r }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "4abe9847-da8e-47a2-ae69-5918545e0cc1",
      "name": "Code in JavaScript1",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        0
      ],
      "parameters": {
        "jsCode": "const balances = items.map(i => i.json);\n\n// Join all contract addresses into a comma-separated string\nconst contracts = balances.map(b => b.contract).join(',');\n\n// Pass both balances and contracts downstream\nreturn [\n  {\n    json: {\n      balances,\n      contracts\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "dd3ca09d-2eb4-45e0-ad0d-dc9c7f093404",
      "name": "HTTP Request1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1456,
        0
      ],
      "parameters": {
        "url": "=https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses={{ $('Code in JavaScript1').item.json.contracts }}&vs_currencies=usd",
        "options": {},
        "jsonHeaders": "{\n  \"accept\": \"application/json\",\n  \"x-cg-demo-api-key\": \"COIN_GECKO_KEY_HERE\"\n}\n",
        "sendHeaders": true,
        "specifyHeaders": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "21538827-f180-4012-ac7d-7567da5f251c",
      "name": "Code in JavaScript2",
      "type": "n8n-nodes-base.code",
      "position": [
        1664,
        0
      ],
      "parameters": {
        "jsCode": "// ---- Pull inputs safely ----\nconst erc20 = $node[\"Code in JavaScript1\"].json?.balances ?? [];\nconst eth   = $node[\"Code ETH Balance\"].json ?? null;\n\nconst cgTokenPrices = $node[\"HTTP Request1\"].json ?? {}; // { [contract]: { usd } }\nconst ethUsd        = $node[\"HTTP Request ETH Price\"].json?.ethereum?.usd ?? 0;\n\n// ---- Combine balances (ETH + ERC-20) ----\nconst balances = eth ? [eth, ...erc20] : [...erc20];\n\n// ---- Build a single price map (token prices + ETH) ----\nconst priceMap = { ...cgTokenPrices };\n// Give ETH a fake \"contract\" key so it matches by contract like the tokens\nconst ETH_KEY = \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\";\npriceMap[ETH_KEY] = { usd: ethUsd };\n\n// ---- Enrich balances with prices ----\nconst enriched = balances.map(b => {\n  const key = (b.contract || \"\").toLowerCase();\n  const usdPrice = priceMap[key]?.usd ?? 0;\n  const amount = Number(b.amount || 0);       // already human-readable amounts\n  const usdValue = amount * usdPrice;\n\n  return {\n    token: b.token,\n    contract: b.contract,\n    amount,\n    usdPrice,\n    usdValue,\n  };\n}).sort((a, b) => b.usdValue - a.usdValue);\n\n// ---- Totals & quick diagnostics ----\nconst totalUsd = enriched.reduce((s, t) => s + (t.usdValue || 0), 0);\nconst ethLine  = enriched.find(t => t.token === \"ETH\");\nconst ethUsdValue = ethLine ? ethLine.usdValue : 0;\nconst restUsd = totalUsd - ethUsdValue;\n\n// ---- Discord message ----\nlet message = `**ETH Wallet Update \ud83d\udcb0**\\n\\n`;\nmessage += `**Total Value:** $${totalUsd.toFixed(2)} USD\\n`;\nif (ethLine) {\n  message += `\u2022 ETH: ${ethLine.amount.toFixed(6)} @ $${(ethLine.usdPrice||0).toFixed(2)} = $${ethUsdValue.toFixed(2)}\\n`;\n  message += `\u2022 Other tokens (priced): $${restUsd.toFixed(2)}\\n\\n`;\n} else {\n  message += `\u2022 No ETH price/balance found\\n\\n`;\n}\n\nmessage += enriched\n  .filter(t => t.usdValue > 0.01)\n  .map(t => `${t.token}: $${t.usdValue.toFixed(2)} (px $${t.usdPrice.toFixed(6)})`)\n  .join(\"\\n\");\n\nreturn [{\n  json: {\n    totalUsd,\n    tokens: enriched,\n    discordMessage: message\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a6dffe53-b602-40dc-bd08-87175da21bab",
      "name": "Discord",
      "type": "n8n-nodes-base.discord",
      "position": [
        1872,
        0
      ],
      "parameters": {
        "content": "={{ $json.discordMessage }}",
        "options": {},
        "authentication": "webhook"
      },
      "credentials": {
        "discordWebhookApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "f01b5fec-fdb8-42a5-9abf-6676a47ca321",
      "name": "HTTP Request ETH",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        832,
        0
      ],
      "parameters": {
        "url": "https://api.etherscan.io/v2/api?chainid=1&module=account&action=balance&address=YOUR_WALLET_HERE&apikey=YOUR_TOKEN_HERE",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "8c0c8162-c9c4-442e-be11-1a8820ce43e4",
      "name": "Code ETH Balance",
      "type": "n8n-nodes-base.code",
      "position": [
        1040,
        0
      ],
      "parameters": {
        "jsCode": "const wei = BigInt($node[\"HTTP Request ETH\"].json.result);\nconst eth = Number(wei) / 1e18;\n\nreturn [{\n  json: {\n    token: \"ETH\",\n    contract: \"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\", // dummy\n    amount: eth,\n    decimals: 18\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "b7de03cb-f775-4aea-8445-d401ecca2f31",
      "name": "HTTP Request ETH Price",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1248,
        0
      ],
      "parameters": {
        "url": "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd",
        "options": {},
        "jsonHeaders": "{\n  \"accept\": \"application/json\",\n  \"x-cg-demo-api-key\": \"COIN_GEKCO_KEY_HERE\"\n}\n",
        "sendHeaders": true,
        "specifyHeaders": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "85e8bac4-d42a-4d36-8496-2d1e6d19ea04",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        -160
      ],
      "parameters": {
        "height": 96,
        "content": "## Set Coin Gecko Keys Here"
      },
      "typeVersion": 1
    },
    {
      "id": "39647a8d-f10f-4cc2-aefe-1f53d304e59c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        272,
        -240
      ],
      "parameters": {
        "height": 192,
        "content": "## Add Etherscan API Key to first 2 HTTP nodes. Add Wallet Address to Code Block as well."
      },
      "typeVersion": 1
    },
    {
      "id": "1b94d811-6947-46a1-b6b7-e928d74b7c73",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -288
      ],
      "parameters": {
        "height": 256,
        "content": "## Daily ETH Wallet Balance sent to Discord. Currently you get two updates. One in the Morning and Evening."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request1": {
      "main": [
        [
          {
            "node": "Code in JavaScript2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code ETH Balance": {
      "main": [
        [
          {
            "node": "HTTP Request ETH Price",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request ETH": {
      "main": [
        [
          {
            "node": "Code ETH Balance",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Code in JavaScript1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript1": {
      "main": [
        [
          {
            "node": "HTTP Request ETH",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript2": {
      "main": [
        [
          {
            "node": "Discord",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request ETH Price": {
      "main": [
        [
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Never miss a snapshot of your (or others) ETH wallet, this workflow polls your wallet on a schedule, fetches balances and current ETH prices, formats a concise summary, and posts it to Discord (or email/Slack/Telegram). Easy to customize to track multiple wallets, tokens, or…

Source: https://n8n.io/workflows/8992/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

I wanted a journal but never had the discipline to write one. Most of my day happens in Discord anyway, so I built this to do it for me.

Discord, HTTP Request, Notion
Slack & Telegram

This workflow monitors product prices from BooksToScrape and sends alerts to a Discord channel via webhook when competitor's prices are lower than our prices. Schedule (for daily or required schedule)

Discord, Google Sheets, HTTP Request
Slack & Telegram

This workflow provides an automated, intelligent solution for global weather monitoring. It goes beyond simple data fetching by calculating a custom "Comfort Index" and using AI to provide human-like

OpenWeatherMap, HTTP Request, Discord +1
Slack & Telegram

AmazonLuna-Games-Fetch. Uses httpRequest, scheduleTrigger, googleSheets, stickyNote. Scheduled trigger; 16 nodes.

HTTP Request, Google Sheets, Discord
Slack & Telegram

This n8n workflow monitors Donald Trump’s Truth Social posts and sends alerts to Telegram & Discord on auto-pilot. Stay instantly updated with every new post, repost, or reply without delays.

Supabase, HTTP Request, Telegram +1