A Node.js script that talks to Flipt on Arc testnet. You run it in a terminal. It can make wallets, buy coins on bonding curves, sit on them, dump them, and loop that forever.
It is not the Flipt website. You do not click around. You type commands.
Works the same on:
- a Linux VPS (Ubuntu, Debian, whatever)
- a phone via Termux
- a normal Linux laptop
You need Node 18 or newer. node -v should print something like v22.23.2. If it says v16 or “command not found”, install Node first (see the bottom of this file).
There are two different “USDC” on Arc. Mixing them up is why the bot used to say “no test USDC” even after you used Circle.
- Gas USDC (native,
0x3600…0000). This pays for transactions, like ETH on Ethereum. You get it from faucet.circle.com — pick Arc Testnet. Cap is 20 USDC per address every 2 hours. Without this, every tx reverts or never sends. - Flipt USDC (
0x4F3b8005d6b3F4994a791D971bcD153E114D20C2). This is what you actually spend on coins. The script callsfaucet()on that contract and you get 500,000 test USDC per wallet. Circle cannot give you this token.
If list shows gas 19.9 and flipt 0.00, you have fuel and no ammo. Run the bot once (or run --no-claim) so it hits Flipt’s faucet. If it shows flipt 500000 and gas 0.00, you cannot send anything until Circle gas lands.
Two files are created next to the script and must never go on GitHub:
| File | What’s in it |
|---|---|
wallets.json |
Every private key the script made or imported. Lose it = lose the wallets. Leak it = someone else owns them. |
config.json |
Buy size, and your Circle TEST_API_KEY if you saved one. |
.gitignore already blocks both. If git status ever lists them, do not commit.
Do this once.
sudo apt-get update
sudo apt-get install -y git tmux
# Node 18+:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
node -vThen:
git clone https://github.com/YOUR_USER/flip-bonded.git
cd flip-bonded
npm install
node stay-bonded.mjs doctordoctor talks to Arc RPC. You want rpc ok and a number of live Flipt markets. If RPC fails, wait and run doctor again — testnet nodes flake.
tmux is so the bot keeps running after you close SSH. Termux people: see below, tmux is optional.
pkg update && pkg upgrade -y
pkg install -y nodejs git
termux-setup-storagetermux-setup-storage asks for permission. Allow it if you want the repo on shared storage (~/storage/shared). You can also just stay in ~ (Termux home).
cd ~
git clone https://github.com/YOUR_USER/flip-bonded.git
cd flip-bonded
npm install
node stay-bonded.mjs doctorAndroid will suspend Termux if you leave. For a long loop, keep Termux in the foreground, or:
pkg install -y tmux
tmux new -s bondednohup node stay-bonded.mjs loop --yes --hold 12 > bonded.log 2>&1 & also works until the OS kills it.
Always cd into the folder that contains stay-bonded.mjs and wallets.json. If you run the script from some other directory, it will look for wallets.json there and think you have zero wallets.
cd /home/YOU/grok/cli # Linux example
# or
cd ~/flip-bonded # after a git clone
node stay-bonded.mjs helpEvery command is node stay-bonded.mjs SOMETHING. Flags come after.
--wallet 0xf142 means “only the wallet whose address contains f142”. A unique suffix is enough. Omit --wallet and it uses all wallets in the file. If you write --wallet with nothing after it, that now means all wallets too.
--dry means “print what you would do, send no transactions”. Use it when you are unsure.
node stay-bonded.mjs generate 5Creates 5 fresh private keys, writes them into wallets.json, prints the addresses. Default is 5 if you omit the number.
It appends. Run it again and you get 10 wallets, not a replacement of the first 5. That is on purpose so you do not wipe keys by accident.
The only wipe is:
node stay-bonded.mjs generate 5 --resetThat deletes the old wallets.json contents and starts over. Do not do this unless you copied the file somewhere else.
New wallets have zero gas and zero Flipt USDC. They cannot buy until you:
- Put Circle Arc USDC on each address (website or Circle API key).
- Let the script call Flipt
faucet()(happens insiderun/loop).
If generate says Saved 0 new wallets, those keys were already in the file.
node stay-bonded.mjs import 0xYOUR_PRIVATE_KEYYou can paste a 12/24-word seed instead of a hex key. Same file, same append rules. If the address is already saved, it will not duplicate.
Never paste keys into Discord, GitHub, or a screenshot.
node stay-bonded.mjs addressesOne address per line. This is what you copy into faucet.circle.com. It does not hit the chain. If it prints nothing, you never generated.
node stay-bonded.mjs list
node stay-bonded.mjs list --wallet 0xf142Talks to Arc. For each wallet you get:
gas— native USDC, the fuelflipt— Flipt quote USDC, the spendable money
It does not list MNK, GRK, SHIB, etc. That is portfolio.
If list hangs, RPC is slow. If it errors, doctor the RPC. If gas is 19.9 and flipt is 500077, that wallet is funded and has already been buying/selling a bit (the 500k faucet plus leftovers).
node stay-bonded.mjs portfolio
node stay-bonded.mjs portfolio --wallet 0xf142Pulls every ERC-20 on that address from Arcscan. You will see token symbols, amounts, and explorer links.
There is no live USD price on chain. A line that says MNK 1685907 is a token amount, not “1.6 million dollars”. The only honest PnL is: Flipt USDC after a sell minus Flipt USDC before the buy.
If portfolio shows bags none, that wallet never bought, or you already sold everything.
If it says No wallet matched --wallet …, the suffix is wrong. Run addresses and copy a real chunk of the address.
Show:
node stay-bonded.mjs configSave buy size (this is the one you want for “each wallet spends X”):
node stay-bonded.mjs config --buy 5000 --buys 20Math: each wallet spends roughly --buy × --buys Flipt USDC per run or per loop cycle.
| You want | Command |
|---|---|
| 10k / wallet | --buy 500 --buys 20 |
| 100k / wallet | --buy 5000 --buys 20 |
| one fat bag | --buy 10000 --buys 1 |
A 100k single buy on a baby testnet curve will often revert. Split it.
If you only have ~500k Flipt USDC, 100k per cycle is fine; 500 × 50 = 25k is also fine. If you set --buy 5000 --buys 50 (= 250k) and the wallet only has 80k, it buys until the cash runs out, then logs Not enough Flipt USDC for another buy.
There are usually not 50 brand-new markets. The loop buys however many new ones it finds. You asked for 20 buys and only 4 new launches exist → it buys 4.
Optional Circle key (gas faucet, not Flipt USDC):
node stay-bonded.mjs config --key 'TEST_API_KEY:paste-here'Must be a testnet Standard key from console.circle.com. Restricted keys and LIVE_API_KEY get rejected. Circle code: 5 is a throttle — wait, do not spam. Env CIRCLE_API_KEY overrides the file if set.
createSeedUsdc is only for launching your own coin. Launches on this testnet often revert (salt / params). You can ignore it. Loop does not launch unless you pass --launch.
node stay-bonded.mjs doctorPrints Node version, where you are, how many wallets, whether the Circle key looks like a test key, and whether Arc RPC answers.
wallets 0→ you are in the wrong folder, or never generated.circle no key→ fine if you claim gas by hand.rpc failed→ internet, or Arc testnet is down. Not your wallets.
node stay-bonded.mjs run --no-claim--no-claim means “do not call Circle”. Use this when you already have gas. The script will still try Flipt faucet() if that wallet’s Flipt USDC is basically empty.
What you should see, in order:
Found N live Flipt marketsStarting wallet 0x…Calling Flipt faucet() — 500korFlipt USDC 500077if you already claimedFlipt USDC approved- Maybe
Launching SB….thenLaunch reverted— annoying, not fatal Buying curve … for X USDCCurve buy confirmed — position is bondedStaying bonded — no sells
If it says Circle rate limit (20 USDC / 2h / address) or API rate limit error, that wallet already took Circle gas this window. Manual claim on the site is the same cap. Wait two hours or skip that wallet.
If it says No native Arc USDC for gas, Circle never landed. Check the address on testnet.arcscan.app.
If every buy reverts, you are probably still on the wrong USDC (old script) or you have no Flipt USDC. list should show a fat flipt number.
One wallet only:
node stay-bonded.mjs run --no-claim --wallet 0xf142 --buy 500 --buys 20--buy / --buys on the command line override config for this process only. They do not rewrite config.json unless you used config --buy ….
--no-launch skips creating a ticker. Useful; launches revert a lot.
--concurrency 2 is how many wallets it starts at once. Keep it small or Arc RPC will scream rate limit exceeded.
Leave a long run in tmux:
tmux new -s bonded
cd /home/YOU/grok/cli
node stay-bonded.mjs run --no-claim
# detach: Ctrl+b, then d
# come back: tmux attach -t bondedCtrl+C once finishes the current transaction then stops. Twice kills immediately.
This is the farm. It sells. Selling is public on Flipt. It can wreck Gold / Silver / Bronze for the testnet NFT. If you care about Stay Bonded rank, do not loop; use run and never sell.
node stay-bonded.mjs loop --yes --hold 12That is all wallets. --yes is required because it dumps bags. --hold 12 waits 12 minutes after buying before it sells. Use --hold 20 for twenty minutes.
One wallet:
node stay-bonded.mjs loop --yes --hold 12 --wallet 0xf142Each cycle:
- Looks at live Flipt markets, preferring brand-new launches.
- Skips anything that wallet already bought this loop, and anything still sitting in the bag.
- Buys
--buysof those new names at--buyUSDC each (or fewer if the chain is quiet). - Logs
NEW launch 0x…ornew-to-you 0x…. - Waits
--holdminutes. Logs once a minute. - Sells the bags back to Flipt USDC.
- Goes to step 1.
If nobody launched anything new, it waits 15 seconds and looks again. If still nothing, that cycle skips the buy rather than rebuying the same coin.
Ctrl+C once: it does not die mid-wait. It finishes the current hold, sells, and does not start another cycle. You will see Ctrl+C — finishing this 20m hold…. Ctrl+C a second time force-quits (you may still be in a bag).
Preview with no money moved:
node stay-bonded.mjs loop --dry --hold 12 --wallet 0xf142--dry still needs no --yes.
Preview:
node stay-bonded.mjs sell --dry --wallet 0xf142That lists every token it would sell. If the list is 19 tokens, --yes will try to dump all 19.
Actually sell:
node stay-bonded.mjs sell --yes --wallet 0xf142One token only:
node stay-bonded.mjs sell --yes --wallet 0xf142 --token 0x109C0c9e2C7daeae9eba8B716c8e8AfB79b669d2After it finishes, list should show Flipt USDC up (you got quote token back) and portfolio should be empty or nearly empty. Some sells revert (bonded, no liquidity, RPC). Those lines stay in the bag; run sell again later.
If you forget --yes it refuses on purpose.
node stay-bonded.mjs claimOnly tries to get gas. It will not buy. Most people who already clicked the Circle website never need this. If you saved a Standard test key, it drips one address at a time with a long gap so Circle does not return code: 5.
The script cannot print your Flipt rank. Open testnet.flipt.fun → Leaderboard → paste an address from addresses.
Live board is roughly profit. Final Gold / Silver / Bronze is after they review activity when testnet closes (16 Sep 2026 09:00 UTC). They also look at bonding and graduation. Dumping every 12 minutes is the opposite of “stay bonded”.
| You see | It means | What to do |
|---|---|---|
No wallet matched --wallet true |
You typed --wallet with no address |
Omit --wallet for all, or pass 0xf142 |
cd: no such file or directory: ~/grok/cli |
A backslash ate ~ |
cd /home/YOU/grok/cli — no tilde |
pathspec 'stay-bonded.mjs' did not match |
Git was initialized in ~/grok not cli/ |
cd into cli, then git add |
git status shows src/, AGENTS.md, wallets.json |
Wrong folder | Do not add those. Only the five CLI files |
No native Arc USDC for gas |
Circle never hit this address | faucet.circle.com, Arc Testnet, wait 2h if capped |
No Flipt USDC. faucet() failed |
RPC limit or already claimed empty | Wait, list, run again |
Circle rate limit / code: 5 |
Throttle | Wait. Do not fire five claims at once |
Launch reverted |
CREATE2 / params | Ignore. Buys still work |
Curve buy reverted then pool confirmed |
Curve was already a pool | Fine |
rate limit exceeded on eth_sendRawTransaction |
Arc RPC | Lower --concurrency, wait, retry |
Flipt faucet: Request exceeds defined limit |
Same RPC cap | Next wallet / later |
| Portfolio full, Flipt USDC barely moved | Buys used 4 USDC on a 500k faucet | Expected until you raise --buy |
| Sell reverted | No liquidity or still bonded | Try again; skip that ticker with --token on the others |
| Termux process vanished | Android slept | tmux + keep the app open |
From inside the cli folder only:
git add .gitignore stay-bonded.mjs package.json package-lock.json README.md
git statusYou should see those files, not wallets.json, not config.json, not the parent src/ app.
git commit -m "Flip Bonded CLI"
gh repo create flip-bonded --public --source=. --remote=origin --pushNever git add -A from ~/grok. That is the whole Grok workspace.
| File | Role |
|---|---|
stay-bonded.mjs |
The bot |
package.json |
npm install pulls viem |
README.md |
This |
.gitignore |
Blocks secrets |
wallets.json |
Local only — keys |
config.json |
Local only — sizes + Circle key |
That is the whole product. There is no dashboard to start.