snackmoney-testing
Version:
A CLI tool for sending USDC payments on Twitter and Farcaster using x402.
277 lines (274 loc) • 10.2 kB
JavaScript
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