follow.js

raw

#!/usr/bin/env node
/*
 * Follow accounts by username. Resolves username -> fid, then submits a LinkAdd.
 *   node follow.js lthibault midao rakshasar.eth
 */
const fs = require("fs");
const { makeLinkAdd, NobleEd25519Signer, FarcasterNetwork, Message } = require("@farcaster/core");

const HUBS = ["https://snap.farcaster.xyz:3381", "https://hub.pinata.cloud"];
const UA = { "User-Agent": "Mozilla/5.0 (compatible; agentatwork/1.0)" };

async function fidOf(username) {
  // fnames registry resolves plain fnames; the Warpcast API also handles ENS-style names
  const r = await fetch(`https://api.warpcast.com/v2/user-by-username?username=${encodeURIComponent(username)}`,
                        { headers: UA });
  if (r.ok) {
    const d = await r.json();
    const fid = d?.result?.user?.fid;
    if (fid) return { fid, followers: d.result.user.followerCount };
  }
  return null;
}

async function submit(bytes) {
  let last;
  for (const hub of HUBS) {
    try {
      const r = await fetch(hub + "/v1/submitMessage", {
        method: "POST", headers: { "Content-Type": "application/octet-stream" }, body: bytes });
      if (r.ok) return hub;
      last = `${hub} ${r.status} ${(await r.text()).slice(0, 150)}`;
    } catch (e) { last = `${hub} ${e.message}`; }
  }
  throw new Error(last);
}

(async () => {
  const names = process.argv.slice(2);
  const st = JSON.parse(fs.readFileSync(__dirname + "/farcaster.json", "utf8"));
  const der = Buffer.from(st.signerPrivateKeyPkcs8, "base64");
  const signer = new NobleEd25519Signer(der.subarray(der.length - 32));
  const fid = Number(st.fid);

  for (const name of names) {
    try {
      const who = await fidOf(name);
      if (!who) { console.log(`  ${name.padEnd(20)} not found`); continue; }
      const res = await makeLinkAdd({ type: "follow", targetFid: who.fid },
        { fid, network: FarcasterNetwork.MAINNET }, signer);
      if (res.isErr()) throw res.error;
      await submit(Message.encode(res.value).finish());
      console.log(`  followed ${name.padEnd(20)} fid=${String(who.fid).padEnd(8)} followers=${who.followers}`);
    } catch (e) {
      console.log(`  ${name.padEnd(20)} ERROR ${e.message.slice(0, 90)}`);
    }
  }
})();