Workflow Automation with n8n | BTC Price Alert

9 min read

First thing first

Check my previous post about what is and how to install n8n: Workflow Automation with n8n | Installation

What it will do?

The idea is to make price alert using the API from indodax (IDR Price) and set initial price first time and then check periodically if price is raised or dropped more than IDR X  then send notification via pushover with a funny message. Here’s the summary of the workflow.

How to configure it to run properly?

First you need to create new app on pushover and set the appropriate icon for it.

Second you need to copy paste json file on the bottom of this post on new workflow.

Next you need to edit the HTTP Request node for BTC Up Alert and BTC Down Alert, modify the token with Application Token and user with User Token from pushover, you can change the sound and the title too if you like.

You can change the price bar for the alert by editing the Compile Summary by changing the highBar and lowBar definition and you can change the “funny” message too on the priceDown and priceUp variable.

Next you need to enable Create Table (Run Once) and run it and then disable it. That’s it.

Here’s the json file:

{
  "id": "9",
  "name": "BTC Price Alert",
  "active": true,
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$node[\"Merge\"].json[\"currentPrice\"]}}",
              "operation": "largerEqual",
              "value2": "={{$node[\"Merge\"].json[\"high\"]}}"
            }
          ]
        }
      },
      "name": "IF Price Goes Up",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        960,
        320
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "select * from check_btc"
      },
      "name": "Get Previous Price",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 1,
      "position": [
        450,
        300
      ],
      "credentials": {
        "postgres": "Postgres-n8n"
      }
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$node[\"Merge\"].json[\"currentPrice\"]}}",
              "value2": "={{$node[\"Merge\"].json[\"low\"]}}"
            }
          ]
        }
      },
      "name": "IF Price Goes Down",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        960,
        490
      ]
    },
    {
      "parameters": {},
      "name": "Do Nothing",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        960,
        640
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "=DROP TABLE IF EXISTS check_btc;\n\nCREATE TABLE check_btc (\n\tcheck_id serial PRIMARY KEY,\n\tlast INT,\n\thigh INT, \n\tlow INT,    \n\tposting_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n);\n\nINSERT INTO check_btc (last, high, low)\nVALUES(200000000,200000000,200000000);\n\nSELECT * FROM check_btc;"
      },
      "name": "Create Table (Run Once)",
      "type": "n8n-nodes-base.postgres",
      "position": [
        250,
        660
      ],
      "typeVersion": 1,
      "alwaysOutputData": true,
      "credentials": {
        "postgres": "Postgres-n8n"
      },
      "disabled": true,
      "continueOnFail": true
    },
    {
      "parameters": {
        "url": "https://vip.bitcoin.co.id/api/btc_idr/webdata",
        "options": {}
      },
      "name": "Get Price Data",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        450,
        500
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "=UPDATE check_btc\nSET last = {{$node[\"Compile Summary\"].json[\"currentPrice\"]}},\n    high = {{$node[\"Compile Summary\"].json[\"highBar\"]}},\n    low = {{$node[\"Compile Summary\"].json[\"lowBar\"]}}\nWHERE check_id = {{$node[\"Get Previous Price\"].json[\"check_id\"]}};"
      },
      "name": "Update Price Bar",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1220,
        400
      ],
      "typeVersion": 1,
      "alwaysOutputData": true,
      "executeOnce": false,
      "credentials": {
        "postgres": "Postgres-n8n"
      }
    },
    {
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "custom",
              "cronExpression": "*/5 * * * *"
            }
          ]
        }
      },
      "name": "Cron",
      "type": "n8n-nodes-base.cron",
      "typeVersion": 1,
      "position": [
        250,
        500
      ]
    },
    {
      "parameters": {
        "mode": "mergeByIndex"
      },
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        790,
        320
      ]
    },
    {
      "parameters": {
        "functionCode": "\nvar currentPrice = items[0].json._24h.last_price - 0;\nvar highBar = currentPrice + 2000000;\nvar lowBar = currentPrice - 1500000;\nvar highestPrice = items[0].json._24h.high - 0;\nvar lowestPrice = items[0].json._24h.low - 0;\nvar bsvPrice = items[0].json.prices.bchsvidr - 0;\n\nvar priceDown = [\n  \"PANIC SELLING!!!\", \n  \"DUMPPP!\", \n  \"Ya ampun, kapan beli lambo klo kayak gini :(\", \n  \"Ga jadi lambo deh, paling mentok hot wheels :(\", \n  \"MANA NIH SATOSHI? KOK GAK DI PUMP!\", \n  \"Buy da dip.\", \n  \"Bitcoin lagi diskon 10%\",\n  \"Sasha liat portfolio kamu turun 80%\",\n  \"Sasha, just sell now and recover later.\",\n  \"You're not going to the moon, Sasha.\",\n  \"Trust me mom, it will moon, I have insider dev info.\",\n  \"Ma, pls, I'm gonna make 1000% gains.\"\n];\nvar priceUp = [\n  \"Lambo sudah di depan mata.\", \n  \"Hodloor.\", \n  \"To da mooooon!\", \n  \"ASOY!! BENTAR LAGI KE 1M!!!\", \n  \"BITCOIN WILL TAKE OVER THE WORLD!\", \n  \"JUAL RUMAH! BELI BITCOIN!!\", \n  \"Apakah ini mimpi?\",\n  \"We're going to the moon mom\",\n  \"look mom, it's green candle.\",\n  \"See I told you, it's not shitcoin.\",\n  \"Look it was just about to moon.\",\n  \"Ada yang tau dealer lambo dimana?\"\n];\nvar maximum = priceUp.length;\nvar randomNumber = getRandom(maximum);\nvar dateNow = getDate();\n\nvar messageGood = priceUp[randomNumber] + \" \\nBTC naik jadi IDR \";\nvar messageBad = priceDown[randomNumber] + \" \\nBTC turun jadi IDR \";\nvar messageTrailer = currentPrice.toLocaleString('en-US', {minimumFractionDigits: 0}) + \" dan sekarang \" + dateNow + \n                  \" \\nharga tertinggi di IDR \" + highestPrice.toLocaleString('en-US', {minimumFractionDigits: 0}) + \n                  \" \\ndan terendah IDR \" + lowestPrice.toLocaleString('en-US', {minimumFractionDigits: 0}) + \n                  \"\\n\\nBSV = IDR \" + bsvPrice.toLocaleString('en-US', {minimumFractionDigits: 0});\n\nreturn [\n  {\n  json: {\n    check_id: 1,\n    currentPrice: currentPrice,\n    bsvPrice: bsvPrice,\n    highBar: highBar,\n    lowBar: lowBar,\n    messageGood: messageGood + messageTrailer,\n    messageBad: messageBad + messageTrailer\n   }\n  }\n]\n\nfunction getRandom(max) {\n  return Math.round(Math.random() * max);\n}\n\nfunction getDate() {\n  var d = new Date(),\n    year = d.getFullYear(),\n    month = d.getMonth()+1,\n    day = d.getDate(),\n    hour = d.getHours(),\n    minute = d.getMinutes();\n    \n  month = month < 10 ? \"0\" + month : month;\n  day = day < 10 ? \"0\" + day : day;\n  hour = hour < 10 ? \"0\" + hour : hour;\n  minute = minute < 10 ? \"0\" + minute : minute;\n  \n  return year + \"-\" + month + \"-\" + day + \" \" + hour + \":\" + minute;\n}"
      },
      "name": "Compile Summary",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        610,
        500
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://api.pushover.net/1/messages.json",
        "options": {},
        "bodyParametersUi": {
          "parameter": [
            {
              "name": "token",
              "value": ""
            },
            {
              "name": "user",
              "value": ""
            },
            {
              "name": "title",
              "value": "BTC Price Up"
            },
            {
              "name": "sound",
              "value": "cashregister"
            },
            {
              "name": "message",
              "value": "={{$node[\"Merge\"].json[\"messageGood\"]}}"
            }
          ]
        }
      },
      "name": "BTC Up Alert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1220,
        240
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://api.pushover.net/1/messages.json",
        "options": {},
        "bodyParametersUi": {
          "parameter": [
            {
              "name": "token",
              "value": ""
            },
            {
              "name": "user",
              "value": ""
            },
            {
              "name": "title",
              "value": "BTC Price Down"
            },
            {
              "name": "sound",
              "value": "tugboat"
            },
            {
              "name": "message",
              "value": "={{$node[\"Merge\"].json[\"messageBad\"]}}"
            }
          ]
        }
      },
      "name": "BTC Down Alert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1220,
        560
      ]
    }
  ],
  "connections": {
    "IF Price Goes Up": {
      "main": [
        [
          {
            "node": "Update Price Bar",
            "type": "main",
            "index": 0
          },
          {
            "node": "BTC Up Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IF Price Goes Down",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Previous Price": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Price Goes Down": {
      "main": [
        [
          {
            "node": "Update Price Bar",
            "type": "main",
            "index": 0
          },
          {
            "node": "BTC Down Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Do Nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Price Data": {
      "main": [
        [
          {
            "node": "Compile Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cron": {
      "main": [
        [
          {
            "node": "Get Price Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Previous Price",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "IF Price Goes Up",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compile Summary": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Start": {
      "main": [
        [
          {
            "node": "Get Price Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Previous Price",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "staticData": null
}