Local-only OpenSea mint bot for personal use.
This bot watches OpenSea collection slugs from watchlist.json, checks whether a public Ethereum drop stage is currently live, blocks mints above your configured maxPriceEth, and prints timestamped logs for each decision.
- watches OpenSea drop collections by slug
- supports
ethereumonly in v1 - only mints
public_salestages - supports strict
free mint onlymode - blocks mint attempts above
maxPriceEth - blocks mint attempts when final transaction value exceeds the allowed cap
- validates that
rpcUrlpoints to Ethereum mainnet in live mode - uses
OPENSEA_API_KEYfrom.envfirst - supports
--dry-runmode for safe simulation - prevents repeated successful mints for the same slug in one bot session
- never logs the private key
--dry-run is simulation mode.
In dry-run mode, the bot:
- loads config
- checks the collection
- reads drop stages
- detects whether a public mint is live
- logs what it would do
In dry-run mode, the bot does not:
- sign transactions
- send transactions
- mint NFTs
Use dry-run to safely test:
- whether the slug is correct
- whether the public mint is detected
- whether the mint price is really free
- whether the bot logs look correct
- Bun
- global
@opensea/cli - an Ethereum mainnet RPC URL from Alchemy, QuickNode, Infura, or Ankr
- an OpenSea API key
- a local
pk.txtfile for live mode
bun installOPENSEA_API_KEY=your_opensea_api_key0xyour_private_key_here
Notes:
pk.txtis local-only and ignored by git- never share your private key
- the wallet still needs ETH for gas, even for free mints
Example for a free mint target:
{
"pollIntervalMs": 3000,
"rpcUrl": "https://eth-mainnet.g.alchemy.com/v2/YOUR_RPC_KEY",
"gas": {
"mode": "preset",
"preset": "normal"
},
"collections": [
{
"slug": "theoremnft-official",
"chain": "ethereum",
"enabled": true,
"maxPriceEth": 0,
"quantity": 1
}
]
}Field meanings:
pollIntervalMs: polling interval in millisecondsrpcUrl: Ethereum mainnet RPC URLgas: top-level gas config for Ethereum transactionsgas.mode:auto,manual, orpresetgas.preset: one ofslow,normal,fast,turbowhenmodeispresetgas.maxFeePerGasGwei: required whenmodeismanualgas.maxPriorityFeePerGasGwei: required whenmodeismanualgas.gasLimit: optional whenmodeismanualslug: OpenSea collection slugchain: must beethereumenabled: enables or disables the targetmaxPriceEth: maximum allowed mint pricequantity: mint quantity
Gas modes:
auto: let the provider estimate gas fieldsmanual: use the exactmaxFeePerGasGweiandmaxPriorityFeePerGasGweivalues you provide, with optionalgasLimitpreset: use one of the built-in presets
Preset values:
slow:15 / 1gweinormal:25 / 2gweifast:40 / 3gweiturbo:60 / 5gwei
Run tests:
bun testRun typecheck:
bun run checkRun dry-run:
bun run index.ts --dry-runRun live mode:
bun run index.tsRun dry-run 10-15 minutes before the mint window:
bun run index.ts --dry-runExpected behavior:
- before public mint is live:
no live public mint - once public mint is detected:
dry-run mint preview
If dry-run shows the correct collection and expected price, stop dry-run and start live mode:
bun run index.tsLive mode will:
- load the wallet
- build mint transaction data
- sign the transaction
- broadcast the transaction
-
opensea api key source selected source="env"The bot is using the API key from.env. -
watchlist loadedThe config was loaded successfully. -
gas mode selectedThe bot loaded your selected gas mode and, formanualorpreset, logs the effective values. -
wallet loadedThe wallet is ready for live mode. -
checking collectionThe bot is currently checking the configured slug. -
no live public mintNo active public mint was found yet. -
dry-run mint previewA mintable public stage was detected, but no transaction was sent because this is simulation mode. -
mint blocked by max priceThe detected stage price is above the configuredmaxPriceEth. -
mint blocked by total priceThe final mint transaction value is higher than the allowed cap. -
mint submittedThe transaction was signed and sent successfully.
For strict free mint only mode, use:
"maxPriceEth": 0This means the bot will only proceed if:
- the detected stage price is free
- the final transaction value is also
0
Note:
- free mint still requires ETH for gas
- do not run multiple bot instances at the same time
- do not share
.envorpk.txt - always test with
--dry-runfirst - keep
quantitywithin the collection's wallet limit - only use live mode when you are ready to send a real transaction
The bot was trying to create a new instant key too often. Current startup should prefer OPENSEA_API_KEY from .env.
Add rpcUrl to watchlist.json.
Your private key format is invalid.
This is normal before the public mint is active.
The bot has been tested against:
- slug:
theoremnft-official - chain:
ethereum - public price target:
0.00 ETH - quantity:
1