AutomationFlowsSlack & Telegram › Dca

Dca

dca. Uses httpRequest, telegram, executeWorkflowTrigger. Event-driven trigger; 16 nodes.

Event trigger★★★★☆ complexity16 nodesHTTP RequestTelegramExecute Workflow Trigger
Slack & Telegram Trigger: Event Nodes: 16 Complexity: ★★★★☆ Added:

This workflow follows the Execute Workflow Trigger → 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
{
  "name": "dca",
  "nodes": [
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.action}}",
              "value2": "BUY"
            }
          ]
        }
      },
      "id": "ad12524b-bb69-4c23-b29f-f408d15814dd",
      "name": "Should Execute Trade?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        656,
        176
      ],
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "jsCode": "const data = $json;\n\n// Binance order parameters\nconst orderParams = {\n  side: data.action,\n  quoteOrderQty: data.amount,\n  symbol: data.symbol,\n  type: 'MARKET',\n  timestamp: Date.now(),\n  recvWindow: 30000\n};\n\nconsole.log('Order Calculation:', orderParams);\n\n// Generate query string for signature\nconst queryString = Object.entries(orderParams)\n  .map(([key, value]) => `${key}=${value}`)\n  .join('&');\n\nreturn [{\n  json: {\n    dcaParams: data,\n    orderParams,\n    queryString,    \n  }\n}];"
      },
      "id": "0c40c93c-a6d1-4cf8-b00c-35f2cb1e107f",
      "name": "Prepare Order Parameters",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        880,
        -240
      ]
    },
    {
      "parameters": {
        "jsCode": "// Generate HMAC SHA256 signature for order\nconst crypto = require('crypto');\n\n// Check if environment variables are set\nif (!$env.BINANCE_SECRET_KEY) {\n  throw new Error('BINANCE_SECRET_KEY environment variable not set');\n}\n\nconst API_SECRET = $env.BINANCE_SECRET_KEY;\nconst queryString = $json.queryString;\nconsole.log('Order signature query string:', queryString);\n\nconst signature = crypto.createHmac('sha256', API_SECRET)\n  .update(queryString)\n  .digest('hex');\n\nconsole.log('Generated order signature:', signature);\n\nreturn [{\n  json: {\n    dcaParams: $json.dcaParams,\n    orderParams: {\n      ...$json.orderParams,\n      signature\n    }\n  }\n}];"
      },
      "id": "32c2c388-0e2d-4ca7-ac46-ef2bf0e4c23c",
      "name": "Sign Order",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1168,
        -240
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.BINANCE_API_BASE_URL }}/api/v3/order",
        "sendQuery": true,
        "specifyQuery": "json",
        "jsonQuery": "={\n  \"side\": \"{{ $json.orderParams.side }}\",\n  \"quoteOrderQty\": {{ $json.orderParams.quoteOrderQty }},\n  \"symbol\": \"{{ $json.orderParams.symbol }}\",\n  \"type\": \"{{ $json.orderParams.type }}\",  \n  \"timestamp\": {{ $json.orderParams.timestamp }},\n  \"recvWindow\": {{ $json.orderParams.recvWindow }},\n  \"signature\": \"{{ $json.orderParams.signature }}\"\n}",
        "sendHeaders": true,
        "specifyHeaders": "json",
        "jsonHeaders": "={\n  \"X-MBX-APIKEY\": \"{{ $env.BINANCE_API_KEY }}\"\n}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "262fa2dd-6839-4e3e-b096-68db27d59388",
      "name": "Execute Trade on Binance",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        1440,
        -240
      ],
      "alwaysOutputData": false,
      "notesInFlow": false,
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "chatId": "={{$env.TELEGRAM_CHAT_ID}}",
        "text": "={{$json.formattedMessage}}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "84727dc8-4100-4c81-aa4a-5216c313b586",
      "name": "Send Telegram Notification",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        2160,
        192
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Format DCA Alert Message\nconst workflowInput = $node['workflow-input'].json;\nconst data = $json;\nconst dcaParams = data.dcaParams;\nconst orderParams = data.orderParams;\nconst error = data.error;\n\n// Debug log to see what we're receiving\nconsole.log('\ud83d\udd0d Debug - Raw data received:', JSON.stringify(data, null, 2));\n\n// Format numbers with proper decimals\nconst formatNumber = (num, decimals = 6) => {\n  if (num === null || num === undefined || num === '' || isNaN(num)) return 'None';\n  return new Intl.NumberFormat(\"en-US\", {\n  minimumFractionDigits: 0,\n  maximumFractionDigits: decimals\n}).format(num);\n};\n\nreturn {\n  formattedMessage: `\u274c *DCA Execution Failed*\n\n\u2757\ufe0f Error status: ${error.status}\n\u2757\ufe0f Error code: ${error.code}\n\u2757\ufe0f Error message: ${error.message}\n\n\ud83d\udcb0 ${workflowInput.targetSymbol} Price: $${formatNumber(dcaParams.targetPrice)}\n\ud83d\udcb0 ${workflowInput.targetSymbol} AVG Price: $${formatNumber(dcaParams.avgPrice)}\n\ud83c\udfaf Action: ${dcaParams.action || 'None'}\n\ud83d\udcb5 ${workflowInput.sourceSymbol} amount: $${formatNumber(dcaParams.amount)}\n\ud83d\udcb2 ${workflowInput.sourceSymbol} available: $${formatNumber(dcaParams.amountAvailable)}\n\u23f0 Time: ${new Date(orderParams.timestamp).toLocaleString('ES')}\n`\n};\n"
      },
      "id": "fbcbb388-2f6d-43c2-9cb0-a1b5cb02ab10",
      "name": "Format Error Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1680,
        -16
      ]
    },
    {
      "parameters": {
        "jsCode": "// Format DCA Alert Message\nconst workflowInput = $node['workflow-input'].json;\nconst dcaParams = $json;\n\n// Debug log to see what we're receiving\nconsole.log('\ud83d\udd0d Debug - Raw data received:', JSON.stringify(dcaParams, null, 2));\n\n// Format numbers with proper decimals\nconst formatNumber = (num, decimals = 6) => {\n  if (num === null || num === undefined || num === '' || isNaN(num)) return 'None';\n  return new Intl.NumberFormat(\"en-US\", {\n  minimumFractionDigits: 0,\n  maximumFractionDigits: decimals\n}).format(num);\n};\n\nreturn {\n  formattedMessage: `\ud83e\udd1a *DCA On Hold*\n\n\ud83d\udcb0 ${workflowInput.targetSymbol} Price: $${formatNumber(dcaParams.targetPrice)}\n\ud83d\udcb0 ${workflowInput.targetSymbol} AVG Price: $${formatNumber(dcaParams.avgPrice)}\n\ud83c\udfaf Action: ${dcaParams.action || 'None'}\n\ud83e\udd1a Action reason: ${dcaParams.actionReason}\n\ud83d\udcb5 ${workflowInput.sourceSymbol} amount: $${formatNumber(dcaParams.amount)}\n\ud83d\udcb2 ${workflowInput.sourceSymbol} available: $${formatNumber(dcaParams.amountAvailable)}\n\u23f0 Time: ${new Date().toLocaleString('ES')}`\n};"
      },
      "id": "6fa03666-ca5f-47fb-b0f1-0c7bfece97b9",
      "name": "Format Hold Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1040,
        192
      ]
    },
    {
      "parameters": {
        "jsCode": "// Format DCA Alert Message\nconst workflowInput = $node['workflow-input'].json;\nconst data = $node[\"Execute Trade on Binance\"].json;\nconst orderFills = data.fills[0];\nconst dcaParams = $node[\"Sign Order\"].json.dcaParams;\n\nlet avgPrice = null;\ntry {\n  avgPrice = parseFloat($node[\"get-avg-price-after-order\"].json.avgPrice);\n} catch (e) {}\n  \n\n// Debug log to see what we're receiving\nconsole.log('\ud83d\udd0d Debug - Raw data received:', JSON.stringify(data, null, 2));\n\n// Format numbers with proper decimals\nconst formatNumber = (num, decimals = 6) => {\n  if (num === null || num === undefined || num === '' || isNaN(num)) return 'None';\n  return new Intl.NumberFormat(\"en-US\", {\n  minimumFractionDigits: 0,\n  maximumFractionDigits: decimals\n}).format(num);\n};\n\nreturn {\n  formattedMessage: `\u2705 *DCA Executed Successfully*\n\n\ud83d\udcca Status: ${data.status}\n\ud83c\udfea Type: ${data.type}\n\n\ud83d\udcb0 ${workflowInput.targetSymbol} Price: $${formatNumber(orderFills.price)}\n\ud83d\udcb0 ${workflowInput.targetSymbol} AVG Price: $${formatNumber(avgPrice)}\n\ud83e\udd11 Order quantity: ${formatNumber(orderFills.qty)} BTC\n\ud83d\udcb8 Order commission: ${formatNumber(orderFills.commission)} ${orderFills.commissionAsset}\n\ud83c\udfaf Action: ${data.side || 'None'}\n\ud83d\udcb5 ${workflowInput.sourceSymbol} amount: $${formatNumber(data.origQuoteOrderQty)}\n\ud83d\udcb2 ${workflowInput.sourceSymbol} available: $${formatNumber(dcaParams.amountAvailable - data.origQuoteOrderQty)}\n\u23f0 Time: ${new Date(data.transactTime).toLocaleString('ES')}\n`\n};"
      },
      "id": "c4225a46-c4c9-4d87-b42d-ebdda69297b9",
      "name": "Format Success Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1904,
        -256
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "qhGDV6b3XcjmL6Bc",
          "mode": "list",
          "cachedResultUrl": "/workflow/qhGDV6b3XcjmL6Bc",
          "cachedResultName": "get-balance-on-spot"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "symbol": "={{ $('workflow-input').item.json.sourceSymbol }}",
            "amount": "={{ $('workflow-input').item.json.sourceAmount }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "symbol",
              "displayName": "symbol",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string"
            },
            {
              "id": "amount",
              "displayName": "amount",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "number"
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {}
      },
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        -384,
        160
      ],
      "id": "6fcaff96-c2fc-4de0-8ccd-0d0ce94428b2",
      "name": "get-balance-on-spot"
    },
    {
      "parameters": {
        "url": "={{ $env.BINANCE_API_BASE_URL }}/api/v3/klines?symbol=BTCUSDC&interval=1d&limit=20",
        "options": {
          "timeout": 10000
        }
      },
      "id": "4c64a471-86a6-4a1e-828c-ee73197fb26a",
      "name": "get-btc-20-day-ma",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        -736,
        -112
      ],
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "jsCode": "const workflowInput = $node['workflow-input'].json;\nconst getPriceNode = $node[\"get-price\"].json;\nconst getBalanceOnSpotNode = $node[\"get-balance-on-spot\"].json;\nconst targetPrice = parseFloat(getPriceNode.price);\nconst amount = workflowInput.sourceAmount; // TODO: recalculate this value depending on the current Price and the avg buy price. If currentPrice < avgBuyPrice, then increase amount, otherwise decrease\nconst amountAvailable = getBalanceOnSpotNode.amountAvailable\n\nlet avgPrice = null;\ntry {\n  avgPrice = parseFloat($node[\"get-avg-price\"].json.avgPrice);\n} catch (e) {}\n\n\nlet action = 'BUY';\nlet actionReason = null;\nif(avgPrice != null && targetPrice > avgPrice) {\n  action = 'HOLD';\n  actionReason = `Current ${workflowInput.targetSymbol} price is greater than your avg price.`;\n}\n\nreturn result = {  \n  action: action,\n  actionReason: actionReason,\n  amount: amount,\n  symbol: `${workflowInput.targetSymbol}${workflowInput.sourceSymbol}`,\n  targetPrice: targetPrice,\n  amountAvailable: amountAvailable,\n  avgPrice: avgPrice\n};\n"
      },
      "id": "685ae862-ab70-4bc7-aecb-0f64582aca8f",
      "name": "dca-logic",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        416,
        176
      ]
    },
    {
      "parameters": {
        "inputSource": "jsonExample",
        "jsonExample": "{\n  \"targetSymbol\": \"BTC\",\n  \"sourceSymbol\": \"USDC\",\n  \"sourceAmount\": 10,\n  \"onlyIfPriceBelowAvgPrice\": false,\n  \"avgPriceFrom\": \"2026-01-29T18:48:55.496Z\"\n}"
      },
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1.1,
      "position": [
        -928,
        160
      ],
      "id": "4532fb27-6baf-49b4-8baa-407ccab49632",
      "name": "workflow-input"
    },
    {
      "parameters": {
        "url": "={{ $env.BINANCE_API_BASE_URL }}/api/v3/ticker/price?symbol={{$json.targetSymbol}}{{$json.sourceSymbol}}",
        "options": {
          "timeout": 10000
        }
      },
      "id": "58ddc7e1-6667-429a-a1b4-0f8ee6cfb9be",
      "name": "get-price",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        -656,
        160
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "iYMeKoezdxGXpy0l",
          "mode": "list",
          "cachedResultUrl": "/workflow/iYMeKoezdxGXpy0l",
          "cachedResultName": "get-avg-price"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "targetSymbol": "={{ $('workflow-input').item.json.targetSymbol }}",
            "sourceSymbol": "={{ $('workflow-input').item.json.sourceSymbol }}",
            "startTime": "={{ $('workflow-input').item.json.avgPriceFrom }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "targetSymbol",
              "displayName": "targetSymbol",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "sourceSymbol",
              "displayName": "sourceSymbol",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "startTime",
              "displayName": "startTime",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {}
      },
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        128,
        -128
      ],
      "id": "0f57349c-8c8a-4b9d-a91b-400ae52b11fb",
      "name": "get-avg-price",
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "d0ea373b-57c3-47ab-99e9-5a7b1bad1da8",
              "leftValue": "={{ $('workflow-input').item.json.onlyIfPriceBelowAvgPrice }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            },
            {
              "id": "4274d8eb-4596-481e-a08b-ce6f3943207e",
              "leftValue": "={{ $('workflow-input').item.json.avgPriceFrom }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -176,
        160
      ],
      "id": "3c20f273-799f-4f15-8bba-f1e1c3733a7e",
      "name": "If",
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "iYMeKoezdxGXpy0l",
          "mode": "list",
          "cachedResultUrl": "/workflow/iYMeKoezdxGXpy0l",
          "cachedResultName": "get-avg-price"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "targetSymbol": "={{ $('workflow-input').item.json.targetSymbol }}",
            "sourceSymbol": "={{ $('workflow-input').item.json.sourceSymbol }}",
            "startTime": "={{ $('workflow-input').item.json.avgPriceFrom }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "targetSymbol",
              "displayName": "targetSymbol",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "sourceSymbol",
              "displayName": "sourceSymbol",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "startTime",
              "displayName": "startTime",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {}
      },
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.3,
      "position": [
        1680,
        -432
      ],
      "id": "f72ae6d1-2c91-4ede-bef4-82acccaea7dc",
      "name": "get-avg-price-after-order",
      "alwaysOutputData": false
    }
  ],
  "connections": {
    "Should Execute Trade?": {
      "main": [
        [
          {
            "node": "Prepare Order Parameters",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format Hold Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Order Parameters": {
      "main": [
        [
          {
            "node": "Sign Order",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sign Order": {
      "main": [
        [
          {
            "node": "Execute Trade on Binance",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Trade on Binance": {
      "main": [
        [
          {
            "node": "get-avg-price-after-order",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format Error Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Error Message": {
      "main": [
        [
          {
            "node": "Send Telegram Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Hold Message": {
      "main": [
        [
          {
            "node": "Send Telegram Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Success Message": {
      "main": [
        [
          {
            "node": "Send Telegram Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get-balance-on-spot": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get-btc-20-day-ma": {
      "main": [
        []
      ]
    },
    "dca-logic": {
      "main": [
        [
          {
            "node": "Should Execute Trade?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "workflow-input": {
      "main": [
        [
          {
            "node": "get-price",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get-price": {
      "main": [
        [
          {
            "node": "get-balance-on-spot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get-avg-price": {
      "main": [
        [
          {
            "node": "dca-logic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "get-avg-price",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "dca-logic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get-avg-price-after-order": {
      "main": [
        [
          {
            "node": "Format Success Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7aa13cda-77ae-4f7d-8380-287f4bff7943",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "9Vv6fuCH1BIlYnX0",
  "tags": []
}

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

dca. Uses httpRequest, telegram, executeWorkflowTrigger. Event-driven trigger; 16 nodes.

Source: https://github.com/luis901101/n8n/blob/0239052cbcf52682e1494538f1fd4d133b75d8d8/workflows/binance/dca.json — 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

03 - Command Handler. Uses executeWorkflowTrigger, telegram, executeCommand, postgres. Event-driven trigger; 53 nodes.

Execute Workflow Trigger, Telegram, Execute Command +2
Slack & Telegram

Deal-Finder. Uses executeWorkflowTrigger, googleSheets, perplexity, httpRequest. Event-driven trigger; 49 nodes.

Execute Workflow Trigger, Google Sheets, Perplexity +2
Slack & Telegram

This workflow provides a complete solution for handling Telegram Stars payments, invoicing and refunds using n8n. It automates the process of sending invoices, managing pre-checkout approvals, recordi

HTTP Request, Execute Workflow Trigger, Google Sheets +2
Slack & Telegram

VIVID v5.0 — Chapter Sub-workflow. Uses executeWorkflowTrigger, executeCommand, itemLists, httpRequest. Event-driven trigger; 21 nodes.

Execute Workflow Trigger, Execute Command, Item Lists +2
Slack & Telegram

[HUB] Жора Action. Uses executeWorkflowTrigger, supabase, telegram, httpRequest. Event-driven trigger; 19 nodes.

Execute Workflow Trigger, Supabase, Telegram +1