Skip to content

Cast from a test account through your own node with a gasless app key.

Add an app key to a test account from the app on your own computer, then post, like and follow through your node.

You need:

  • A test Farcaster account and its recovery phrase. Read What the app does with your recovery phrase first.
  • Node.js 22.12 or later (22.x, 24.x or 26+) and this repo on your computer.
  • Your node from the Full run, and the HTTPS address that deploy-client.sh printed.

Add the key from the app on your own computer at localhost. The address deploy-client.sh prints is usually <ip-with-dashes>.sslip.io, and sslip.io is a DNS service someone else runs. Whoever controls that DNS, or the server, could serve a changed page that sends your recovery phrase elsewhere. A page served from localhost comes from files on your own disk, built from code you can read.

The local dev server passes /v1 requests on to your node’s HTTPS address, so you need no SSH tunnel, and ports 3381 and 3383 stay closed. The add-key steps show a Check the address warning whenever the app is not on localhost.

What the app does with your recovery phrase

Section titled “What the app does with your recovery phrase”

The code is in client/src/signer.ts:

  1. Your browser makes a new ed25519 app key.
  2. The browser uses the phrase once to sign one gasless KEY_ADD with your custody address. There is no transaction and no gas.
  3. Nothing stores, logs or sends the phrase. Only the signed KEY_ADD goes to your node.
  4. The app key is saved in this browser’s localStorage. Remove from this browser deletes it there; the key stays valid on the network until it expires.

JavaScript cannot promise that the browser has wiped the phrase from memory.

The app key canThe app key cannot
Post casts (CAST_ADD)Move money or sign transactions
Like and recast (REACTION_ADD)Delete casts, unfollow or edit your profile; the app does not ask for those scopes
Follow (LINK_ADD)Approve or cancel other keys (KEY_ADD and KEY_REMOVE are never scopes)
Work until it expires: 7 days by default (pick 1 day for a test), 90 at most, renewed each time it is usedKeep working after your custody address cancels it

SECURITY.md has the full list.

From the repo folder, start the app. Put your node’s HTTPS address in SNAPCHAIN_NODE_URL:

your computer
cd client
npm ci --ignore-scripts
SNAPCHAIN_NODE_URL=https://<your node> npm run dev

Leave it running. You should see ready and Local: http://localhost:5317/. Ctrl-C stops it.

npm ci installs the exact versions in package-lock.json. --ignore-scripts stops packages from running their own install scripts. The app builds and its tests pass without them.

Open http://localhost:5317. The status at the top should say Connected to your node; Details shows the version and how far behind each shard is. To see your feed, type your FID or username under Enter your FID to see your feed and press Show my feed.

The app uses port 5317, not Vite’s usual 5173, because a browser keeps one localStorage per address and port. If 5317 is taken, npm run dev stops with an error instead of moving to another port.

The page’s Content-Security-Policy lets it connect only to its own address, so a changed library cannot send data elsewhere.

Before you type the phrase, check that the address bar shows exactly localhost:5317, close other tabs, and turn off clipboard history and screen sharing.

In the post box at the top (To post, add an app key first.), press Add app key. A dialog walks you through 4 steps:

  1. What an app key is: press Next.
  2. Before you start: read it. There must be no yellow Check the address. box; if there is, you are not on localhost, so stop. Press I understand, continue.
  3. Sign and send: type the test account’s recovery phrase (12 to 24 words) under Recovery phrase. If you paste it instead, clear your clipboard afterwards: clipboard history and sync tools can keep a copy, and the app cannot clear it. Under Key expires after, pick 1 day for a test (the default is 7 days). Press Add app key. You see Signed for FID with your FID, then Sending to your node. If it shows another FID, the phrase belongs to another account.
  4. App key added: the phrase field is gone. Press Close or Write a cast.

From the phrase, the app works out your custody address, asks the node which FID that address owns, and reads currentUserNonce. Then it signs one gasless KEY_ADD and submits it.

The App key card shows Waiting for your node, then Active when GET /v1/signer returns the key. The app checks every 4 seconds. Post only after it says Active; a cast sent earlier is rejected and marked Failed.

Check it from the terminal:

Terminal window
curl -s "https://<your node>/v1/signersByFid?fid=<your-fid>" | jq '.currentUserNonce, [.signers[] | .source]'

currentUserNonce should be one higher than before, with one more signer in the list.

The app key is saved in the browser for localhost:5317 only, so post from the local app. The copy at your HTTPS address has no key, and adding one there means typing the phrase into a page served through sslip.io (Why run the app on your own computer).

ActionWhereMessage type
CastType in the post box at the top (New cast as FID …), press Post (a standard cast, up to 320 bytes)CAST_ADD
FollowIn Settings, Follow someone: type an FID in FID to follow, press FollowLINK_ADD (type follow)
Like, recastThe heart and repeat buttons under each castREACTION_ADD

A new cast shows first in the feed, with a state badge. Every message also shows up in the Sent panel (right column, or the Settings tab on a narrow window) with the same state:

StateMeaning
SendingThe app is sending it to your node
Waiting for a blockThe node accepted it and sent it on
RetryingNot seen yet, so the app sent it again
ConfirmedThe node returns it
FailedStill missing after 4 sends, or the node rejected it

A failed message shows the reason and a Retry button. Your node passes messages on explains these states.

The app can only add. It has no button to delete a cast, unfollow or unlike.

Open your profile in any other Farcaster app. The app does not show hashes; ask your node:

Terminal window
curl -s "https://<your node>/v1/castsByFid?fid=<your-fid>&pageSize=1&reverse=true" \
| jq '.messages[0] | {hash, text: .data.castAddBody.text}'
  • Remove from this browser (Settings, App key) deletes the key from this browser. The network still accepts it until its lifetime runs out.
  • This app cannot revoke keys yet. When it says your account’s wallet can revoke the key, it means a KEY_REMOVE message signed by your custody address and sent to a node, which is how a gasless key is cancelled. Removing a key through the KeyRegistry contract does not apply to it. This guide has no tested way to send a KEY_REMOVE, so pick a 1-day expiry for a test key and let it run out.

When you are done on localhost, press Remove from this browser, so no other page on localhost:5317 can read the key later. Then stop the dev server with Ctrl-C.