{
  "id": "HIxxNcuu7D2E91u7",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Paid X Amplification w/ x402",
  "tags": [],
  "nodes": [
    {
      "id": "11dec1d0-79e7-4b81-a5b0-0e6ce638524a",
      "name": "Approve or Decline?",
      "type": "n8n-nodes-base.if",
      "position": [
        1104,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f021075c-1415-4cf9-825f-eedc01e0a369",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.data.Confirm }}",
              "rightValue": "no"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1b1640b7-8f36-4b61-a814-5956fcd1877f",
      "name": "Forward the URL to a Moderator",
      "type": "n8n-nodes-base.telegram",
      "position": [
        656,
        -64
      ],
      "parameters": {
        "text": "=Promote URL on X: {{ $json.body.tweet }}",
        "chatId": "123456789",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b657d961-e3e4-44b4-aa5d-9ea6e368a12a",
      "name": "Get Moderator Approval",
      "type": "n8n-nodes-base.telegram",
      "position": [
        880,
        -64
      ],
      "parameters": {
        "chatId": "=5034284669",
        "message": "=Approve or Deny Amplification Request?",
        "options": {
          "limitWaitTime": {
            "values": {
              "resumeUnit": "minutes"
            }
          }
        },
        "operation": "sendAndWait",
        "formFields": {
          "values": [
            {
              "fieldType": "dropdown",
              "fieldLabel": "Confirm",
              "fieldOptions": {
                "values": [
                  {
                    "option": "approve"
                  },
                  {
                    "option": "deny"
                  }
                ]
              },
              "requiredField": true
            }
          ]
        },
        "responseType": "customForm"
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6c660e32-ec43-4a2e-914f-6433b6d91a8a",
      "name": "Retweet the Post",
      "type": "n8n-nodes-base.twitter",
      "position": [
        1392,
        -176
      ],
      "parameters": {
        "tweetId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('x402 Webhook Gateway').item.json.body.tweet }}"
        },
        "operation": "retweet"
      },
      "credentials": {
        "twitterOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9a90fcd1-d2fb-4c79-917d-6925ebfb106e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -528,
        -928
      ],
      "parameters": {
        "width": 712,
        "height": 1036,
        "content": "# Get Paid to Promote!\n\nWith the [x402 Webhook Gateway](https://youtu.be/SzuSpIWLy5k?si=inDuPG06x5SCetW2), you can quickly set up an n8n workflow to allow X users to pay your for likes & reposts. \n\n## How it Works\n\nThis workflow uses the x402 standard to provide an API where payment is required to request a repost on X. The workflow validates the submitted URL, refunds the money if its invalid, then forwards the URL to a moderator to give final approval before automatically reposting using the X/Twitter node connected to your X account. \n\nHere is how the x402 endpoint should be called (be sure to use a properly formatted x-payment header payload): \n\n```sh\n#### IMPORTANT: swap out the URL here for your webhook URL endpoint\ncurl -X POST \\\n  https://n8n.1shotapi.dev/webhook-test/x-amplification \\\n  -H \"x-payment: YOUR-BASE64-ENCODED-PAYMENT-PAYLOAD\" \\\n  -H \"User-Agent: CustomUserAgent/1.0\" \\\n  -H \"Accept: application/json\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"tweet\": \"https://x.com/1shotapi/status/1980730376638316726\"\n  }'\n```\n\n## Setup Steps\n\n1. Sign up for an [X Developer Account](https://developer.x.com/en) and create an API key to authenticate the X node against your account. \n2. Create a free [1Shot API](https://1shotapi.com) account and generate an API key and secret to authenticate the 1Shot API nodes against your developer account. \n3. User the Telegram [BotFather](https://t.me/BotFather) to create a Telegram bot to communicate with your account moderators. Use the access token to authenticate the Telegram nodes to your bot. \n4. In 1Shot API, import the `transferWithAuthorization` function on the payment token you want to accept as payment for reposts. "
      },
      "typeVersion": 1
    },
    {
      "id": "75a8f239-ce2e-4b0d-a006-99a6bbb146ae",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 416,
        "content": "## X V2 API\n\nThe X V2 API lets you like, repost, and DM from your X account. It requires a [developer account](https://docs.x.com/x-api/introduction) in order to authenticate the n8n node against X. \n\nWith the free version of X Developer, you'll be able to repost from n8n. If you want to be able to like posts or DM, you'll need to upgrade your developer account to at least the Basic paid package.  "
      },
      "typeVersion": 1
    },
    {
      "id": "a22c5d0c-e825-4ea6-b60c-9000957cd2c8",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        224,
        -48
      ],
      "parameters": {
        "jsCode": "function isValidXPostUrl(url) {\n  // Regex covers:\n  // - https://x.com/{username}/status/{tweetId}\n  // - https://twitter.com/{username}/status/{tweetId}\n  const pattern = /^https:\\/\\/(?:x\\.com|twitter\\.com)\\/([A-Za-z0-9_]{1,15})\\/status\\/(\\d+)(?:[/?#].*)?$/;\n\n  return pattern.test(url);\n}\n\n$input.first().json.isValidPostUrl = isValidXPostUrl($input.first().json.body.tweet);\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "3dce7d15-1595-401b-a1f4-be67616bbe9f",
      "name": "x402 Webhook Gateway",
      "type": "n8n-nodes-1shot.oneShotWebhook",
      "position": [
        0,
        -48
      ],
      "parameters": {
        "path": "x-amplification",
        "tokens": {
          "paymentToken": [
            {
              "payToAddress": "0xb841cf79121e068c283929f5e91c7fe405064dc0",
              "paymentToken": "sepolia:0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
              "paymentAmount": 100000
            }
          ]
        },
        "options": {},
        "httpMethod": "POST",
        "webhookType": "x402",
        "responseData": "noData"
      },
      "credentials": {
        "oneShotOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "eb4d965e-e1ed-4083-b77e-eea84ff01730",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        -304
      ],
      "parameters": {
        "color": 5,
        "width": 656,
        "height": 416,
        "content": "## Human in the Loop Moderation\n\nN8n's X node doesn't have a way to read posts from X, so in this workflow we'll send the URL to a moderation channel where you or your assistants can quickly review the post by clicking the link, then hitting approve or deny in Telegram. \n\nYou'll need an active Telegram bot API key as well as the Chat ID between you and your bot in order to receive the moderation requests. "
      },
      "typeVersion": 1
    },
    {
      "id": "eb0dee71-7ab1-4679-a2ce-a6f51c4f88c3",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        432,
        -48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9d78c0fa-aba4-4226-a498-ab820fb61f33",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.isValidPostUrl }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4e2fa88e-852a-4add-8c72-35cbd36680ba",
      "name": "Refund for Invalid URL",
      "type": "n8n-nodes-1shot.oneShot",
      "position": [
        704,
        160
      ],
      "parameters": {
        "params": "={\n  \"to\": \"{{ $('x402 Webhook Gateway').item.json.paymentPayload.payload.authorization.from }}\",\n  \"value\": \"{{ $('x402 Webhook Gateway').item.json.paymentPayload.payload.authorization.value }}\"\n}",
        "options": {},
        "additionalFields": {
          "memo": "=Bad URL Refund for wallet: {{ $json.paymentPayload.payload.authorization.from }}"
        },
        "contractMethodId": "dfb6b80a-d881-4bb7-8dda-db16648ad0bd"
      },
      "credentials": {
        "oneShotOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8356c67b-cea8-4b47-9939-8e0547950a07",
      "name": "Refund for Denied Promotion",
      "type": "n8n-nodes-1shot.oneShot",
      "position": [
        1312,
        160
      ],
      "parameters": {
        "params": "={\n  \"to\": \"{{ $('x402 Webhook Gateway').item.json.paymentPayload.payload.authorization.from }}\",\n  \"value\": \"{{ $('x402 Webhook Gateway').item.json.paymentPayload.payload.authorization.value }}\"\n}",
        "options": {},
        "additionalFields": {
          "memo": "=Post Denied Refund for wallet: {{ $json.paymentPayload.payload.authorization.from }}"
        },
        "contractMethodId": "dfb6b80a-d881-4bb7-8dda-db16648ad0bd"
      },
      "credentials": {
        "oneShotOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "db029e55-3c5c-4be0-a69d-28914fbb2aeb",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        128
      ],
      "parameters": {
        "color": 3,
        "width": 976,
        "height": 352,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Refund the Caller\n\nSince the x402 Gateway will block until the caller's payment settles, we'll refund the payment amount back to the `from` address if either the repost URL is bad or if the moderator denies their request for a repost.\n\nYou'll need to import the `transfer` function of your payment token into your 1Shot API account and select it in both refund nodes. "
      },
      "typeVersion": 1
    },
    {
      "id": "577f9026-091a-476e-8c93-c7d695440568",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        192,
        -240
      ],
      "parameters": {
        "color": 2,
        "width": 416,
        "height": 352,
        "content": "## X Post Validation\n\nThis section ensures that the caller has provided a valid link to a post on X. "
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a7ea776a-a716-4032-b22e-c6d2fb0666bf",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Forward the URL to a Moderator",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Refund for Invalid URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retweet the Post": {
      "main": [
        []
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Approve or Decline?": {
      "main": [
        [
          {
            "node": "Retweet the Post",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Refund for Denied Promotion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "x402 Webhook Gateway": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Moderator Approval": {
      "main": [
        [
          {
            "node": "Approve or Decline?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Refund for Denied Promotion": {
      "main": [
        []
      ]
    },
    "Forward the URL to a Moderator": {
      "main": [
        [
          {
            "node": "Get Moderator Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}