UNPKG

snackmoney-testing

Version:

A CLI tool for sending USDC payments on Twitter and Farcaster using x402.

277 lines (274 loc) 10.2 kB
#!/usr/bin/env node import { Logger, kleur_default } from './chunk-TQEXMNGL.js'; import fs from 'fs'; import dotenv from 'dotenv'; import { Command } from 'commander'; import path2 from 'path'; import { fileURLToPath } from 'url'; import axios from 'axios'; import { privateKeyToAccount } from 'viem/accounts'; import { withPaymentInterceptor, decodeXPaymentResponse } from 'x402-axios'; import inquirer from 'inquirer'; // package.json var package_default = { name: "snackmoney-testing", version: "0.0.5", description: "A CLI tool for sending USDC payments on Twitter and Farcaster using x402."}; async function payAction(cmd) { const privateKey = process.env.PRIVATE_KEY; const baseURL = "https://api.snack.money"; const endpointPath = "/payments/pay"; if (!privateKey || !endpointPath) { Logger.error("Missing required environment variables"); process.exit(1); } const { identity, username, amount } = cmd; const allowedIdentities = ["twitter", "farcaster"]; if (!allowedIdentities.includes(identity.toLowerCase())) { Logger.error("receiver_identity must be either 'twitter' or 'farcaster'"); process.exit(1); } const parsedAmount = parseFloat(amount); if (isNaN(parsedAmount)) { Logger.error("Amount must be a valid number, e.g., 0.01"); process.exit(1); } const account = privateKeyToAccount(privateKey); const api = withPaymentInterceptor(axios.create({ baseURL }), account); try { const response = await api.post(endpointPath, { amount: parsedAmount, currency: "USDC", type: "social-network", sender_username: "snackmoney-agent-x402", receiver_username: username, receiver_identity: identity }); Logger.log("response", response.data); const paymentResponse = decodeXPaymentResponse( // eslint-disable-next-line prettier/prettier response.headers["x-payment-response"] ); Logger.log(paymentResponse); } catch (error) { Logger.error("error", error); } } var __filename = fileURLToPath(import.meta.url); var __dirname = path2.dirname(__filename); var localEnvPath = path2.resolve(__dirname, "../.env"); async function envAction() { const { privateKey } = await inquirer.prompt([ { name: "privateKey", type: "password", message: "Enter your Ethereum PRIVATE_KEY:", mask: "*", validate: (input) => { const isValid = /^0x[0-9a-fA-F]{64}$/.test(input); if (!isValid) { Logger.error("Must be a valid 0x-prefixed private key"); return "Invalid private key format."; } return true; } } ]); const envExists = fs.existsSync(localEnvPath); const envContent = envExists ? fs.readFileSync(localEnvPath, "utf-8") : ""; const lines = envContent.split("\n").filter(Boolean); const updatedLines = lines.filter((line) => !line.startsWith("PRIVATE_KEY=")); updatedLines.push(`PRIVATE_KEY=${privateKey}`); fs.writeFileSync(localEnvPath, updatedLines.join("\n"), "utf-8"); Logger.info( // eslint-disable-next-line prettier/prettier `Environment variable PRIVATE_KEY set successfully ${localEnvPath}` ); } async function batchPayAction(cmd) { const privateKey = process.env.PRIVATE_KEY; const baseURL = "https://api.snack.money"; const endpointPath = "/payments/batch-pay"; if (!privateKey || !endpointPath) { Logger.error("Missing required environment variables"); process.exit(1); } const { identity, receivers } = cmd; const allowedIdentities = ["twitter", "farcaster"]; if (!allowedIdentities.includes(identity.toLowerCase())) { Logger.error("receiver_identity must be either 'twitter' or 'farcaster'"); process.exit(1); } let parsedReceivers; try { parsedReceivers = JSON.parse(receivers); if (!Array.isArray(parsedReceivers)) { throw new Error("Receivers must be an array"); } } catch (e) { Logger.error( // eslint-disable-next-line prettier/prettier `receivers must be a valid JSON array, e.g. '[{"username":"jrsarath","name":"Sarath Singh","amount":0.5}]'` ); process.exit(1); } const account = privateKeyToAccount(privateKey); const api = withPaymentInterceptor(axios.create({ baseURL }), account); try { const response = await api.post(endpointPath, { currency: "USDC", type: "social-network", sender_username: "snackmoney-agent-x402", receiver_identity: identity, receivers: parsedReceivers }); Logger.log("response", response.data); const paymentResponse = decodeXPaymentResponse( // eslint-disable-next-line prettier/prettier response.headers["x-payment-response"] ); Logger.log(paymentResponse); } catch (error) { Logger.error("error", error); } } async function createRewardAction(cmd) { const privateKey = process.env.PRIVATE_KEY; const baseURL = "https://api.snack.money"; const endpointPath = "/rewards/create-distribution"; if (!privateKey || !endpointPath) { Logger.error("Missing required environment variables"); process.exit(1); } const { platform, contentId, budget } = cmd; const allowedPlatforms = ["twitter", "farcaster"]; if (!allowedPlatforms.includes(platform.toLowerCase())) { Logger.error("platform must be either 'twitter' or 'farcaster'"); process.exit(1); } const parsedBudget = parseFloat(budget); if (isNaN(parsedBudget)) { Logger.error("budget must be a valid number, e.g., 0.01"); process.exit(1); } const account = privateKeyToAccount(privateKey); const api = withPaymentInterceptor(axios.create({ baseURL }), account); try { const response = await api.post(endpointPath, { budget: parsedBudget, platform, content_id: contentId }); Logger.log("response", JSON.stringify(response.data, null, 2)); } catch (error) { Logger.error("error", error); } } async function confirmRewardAction(cmd) { const privateKey = process.env.PRIVATE_KEY; const baseURL = "https://api.snack.money"; const endpointPath = "/rewards/confirm-distribution"; if (!privateKey || !endpointPath) { Logger.error("Missing required environment variables"); process.exit(1); } const { orderId } = cmd; const account = privateKeyToAccount(privateKey); const api = withPaymentInterceptor(axios.create({ baseURL }), account); try { const response = await api.post(`${endpointPath}/${orderId}`); Logger.log("response", JSON.stringify(response.data, null, 2)); } catch (error) { Logger.error("error", error); } } // src/helper/math-diff.ts function matchTextScore(text, pattern) { let score = 0; const textLength = text.length; const patternLength = pattern.length; let i = 0; let j = 0; while (i < textLength && j < patternLength) { if (text[i] === pattern[j]) { score++; j++; } i++; } return score; } function findMostMatchText(list, pattern) { let maxScore = 0; let result = ""; for (const text of list) { const score = matchTextScore(text, pattern); if (score > maxScore) { maxScore = score; result = text; } } return result !== "" ? result : null; } // src/index.ts var __filename2 = fileURLToPath(import.meta.url); var __dirname2 = path2.dirname(__filename2); var localEnvPath2 = path2.resolve(__dirname2, "../.env"); var fallbackEnvPath = path2.resolve(process.cwd(), ".env"); var envPathToUse = fs.existsSync(localEnvPath2) ? localEnvPath2 : fs.existsSync(fallbackEnvPath) ? fallbackEnvPath : null; if (envPathToUse) { dotenv.config({ path: envPathToUse }); Logger.info(`Loaded .env from ${envPathToUse}`); } else { Logger.warn("\u26A0\uFE0F No .env file found, some commands may not work properly."); } var commandList = [ "pay", "batch-pay", "confirm-reward-distribution", "create-reward-distribution", "env" ]; var snackmoney = new Command(); snackmoney.name(`${package_default.name}`).usage("[command]").description(`${package_default.name} - ${package_default.description} - v${package_default.version}`).version(package_default.version, "-v, --version", "Output the current version").helpOption("-h, --help", "Display help for command").action(async (_, command) => { let isArgs = false; if (command) { const args = command.args?.[0]; if (args && !commandList.includes(args)) { isArgs = true; const matchCommand = findMostMatchText(commandList, args); if (matchCommand) { Logger.error( // eslint-disable-next-line prettier/prettier `Unknown command '${args}', Did you mean '${kleur_default.underline(matchCommand)}'?` ); } else { Logger.error(`Unknown command '${args}'`); } } } if (!isArgs) { Logger.info("snackmoney --help"); } process.exit(0); }); snackmoney.command("env").description("Set your PRIVATE_KEY to .env file securely").action(envAction); snackmoney.command("pay").description("Send USDC to a single user").requiredOption( "-i --identity <identity>", // eslint-disable-next-line prettier/prettier "Identity platform: twitter or farcaster" ).requiredOption("-u --username <username>", "Receiver username").requiredOption("-a --amount <amount>", "Amount in USDC").action(payAction); snackmoney.command("batch-pay").description("Send USDC to multiple recipients").requiredOption( "-i --identity <identity>", // eslint-disable-next-line prettier/prettier "Identity platform: twitter or farcaster" ).requiredOption("-r --receivers <json>", "Receivers JSON array string").action(batchPayAction); snackmoney.command("create-reward-distribution").description("Create a reward distribution order").requiredOption("-b --budget <budget>", "USDC budget").requiredOption("-p --platform <platform>", "Platform: twitter or farcaster").requiredOption("-c --content-id <contentId>", "Platform content ID").action(createRewardAction); snackmoney.command("confirm-reward-distribution").description("Confirm reward distribution order").requiredOption( "-o --order-id <orderId>", // eslint-disable-next-line prettier/prettier "Order ID to confirm and distribute" ).action(confirmRewardAction); snackmoney.parse(); //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map