Recovery Kit
A JSON bundle plus a standalone CLI that re-derive every forwarder address you have ever had, so you can recover funds with no platform involvement.
What it is
A JSON file you download from the dashboard, plus a standalone CLI (noholdpay-recover). Together they re-derive every forwarder address you have ever had (EVM and TRON CREATE2 clones, Solana PDAs) and check on-chain balances. When you decide to sweep, you sign the transaction yourself with any wallet that holds a little gas on that chain (Solana requires your registered control key). Funds can only ever move to your registered treasury. The CLI never sees a seed phrase.
The bundle is a point-in-time snapshot. Re-download it whenever the dashboard's Recovery panel flags it as out of date, which happens after:
- a treasury rotation (registering a new payout address),
- adding a wallet on a new chain,
- completing a wallet replacement (replacing the wallet bound to your on-chain identity), and
- finishing a forwarder-contract migration.
Ordinary activity does not stale it. Taking payments, editing a label, or changing gas settings all leave the bundle complete, because it describes the whole address range for each treasury version rather than one entry per payment.
What's inside
The downloaded JSON has four payload sections plus identification metadata (merchant_uuid and generated_at):
| Section | What it covers |
|---|---|
chains | EVM and TRON CREATE2 forwarders. Per chain: factory address, implementation address, your on-chain merchant ID, every treasury version with a bounded recovery range that covers every forwarder address ever derivable for it, and the full history of factory deployments for that chain. If you have ever replaced a bound wallet, an epochs list carries each identity generation separately, each with its own merchant ID and treasury versions, so addresses from before and after the replacement are both recoverable. The CLI recovers abandoned addresses from those ranges without needing one entry per payment. |
solana_chain_versions | Solana PDA forwarders. Per chain: program ID, your merchant ID, every treasury pubkey version with its recovery index range, the chain's recoverable asset list, and per-payment unswept rows only for older payments created before sequential derivation. |
self_recovery_wallets | Informational pointers to your UTXO HD wallets (xpub plus written recovery instructions naming the derivation standard used), your XRPL classic address, your Stellar account ID, and your Monero primary address. You already have everything needed to spend from these. Your own wallet software is the recovery tool. |
cli | Per-platform download URLs, SHA-256 hashes, and the Cosign verification command for the recovery CLI. |
The kit contains no private keys. Multiple copies are safe.
Do I need this now?
It depends on the payment modes you use:
| Mode | Recovery story |
|---|---|
| Direct-to-account (XRP, Stellar, TON) | Funds land directly in your account with a per-payment tag, reference, or comment. Nothing to recover. |
| Gasless (Solana sponsored) | Settles straight into your treasury. Nothing sits in a forwarder, so there is nothing to recover. |
| Gasless (EVM x402) | The transfer settles into the per-payment forwarder unless direct settlement is enabled for the chain, so those payments are covered by auto-sweep and, if NoHoldPay is offline, by this kit and the CLI. |
| HD-derived (BTC, LTC, BCH, DOGE) | Your seed phrase plus standard wallet software recovers everything. The kit lists your xpub and per-chain recovery instructions as a courtesy. |
| Monero | You hold the spend key. Your wallet recovers itself. The kit lists your primary address as a courtesy. |
| CREATE2 forwarder (EVM, TRON) | Funds sit briefly in per-payment forwarder contracts. The CLI is how you sweep them if NoHoldPay is offline. |
| PDA forwarder (Solana) | Funds sit briefly in per-payment forwarder PDAs. The CLI is how you sweep them if NoHoldPay is offline. |
Download the kit anyway. It costs nothing and is your safety net.
Download
Save the JSON file offline, alongside your wallet seed phrase. Not in email or cloud storage alone.
The dashboard shows the time of your last successful download, recorded in that browser. Checking from a different machine, or after clearing site data, will report no download even if you have one saved. Treat the file you have stored as the source of truth.
The file is named noholdpay-recovery-kit-<timestamp>.json so weekly snapshots do not overwrite each other.
Have these ready before you need them
Recovery is not the moment to go looking for missing pieces. Keep all of these together, offline:
| What | Why |
|---|---|
| The kit JSON | Every address you have ever had is derived from it. |
| Your treasury wallet | Where swept funds land. You need it to spend them, not to run the sweep. |
| A gas-funded wallet on each chain | Pays for the sweep transaction. On EVM and TRON this can be any wallet, including a throwaway. |
| Your Solana control key | Required to sweep Solana PDA balances. Nothing else can substitute for it. |
| A public RPC URL per chain | Any provider. No account with us is needed. |
Everything above except the kit is yours already. The kit is the only piece you get from us, which is why the download matters.
Using the recovery CLI
noholdpay-recover is a standalone, dependency-free Go binary. Signed releases are published as one artifact per platform and architecture, named noholdpay-recover-<version>-<os>-<arch> (Windows builds add .exe): linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, and windows-amd64. Each signed release ships with a Sigstore Cosign keyless signature and certificate so you can verify what you are about to run.
Releases live in a public repository so you can fetch them with no account and no NoHoldPay involvement, which is the whole point of a tool for when we are unreachable:
https://github.com/NoHoldPay/noholdpay-recover/releases
Which file do I download?
| Your computer | File |
|---|---|
| Mac with Apple Silicon (M1, M2, M3, M4) | noholdpay-recover-<version>-darwin-arm64 |
| Mac with an Intel processor | noholdpay-recover-<version>-darwin-amd64 |
| Windows | noholdpay-recover-<version>-windows-amd64.exe |
| Linux on a normal PC or server | noholdpay-recover-<version>-linux-amd64 |
| Linux on ARM (Raspberry Pi, ARM server) | noholdpay-recover-<version>-linux-arm64 |
"darwin" is the internal name for macOS, and "amd64" means a normal 64-bit Intel or AMD chip rather than an AMD-only one. Those terms are in the file names because the checksums and signatures are issued against them, so they have to match exactly. On a Mac, check the Apple menu then About This Mac: a Chip line reading Apple M-something means Apple Silicon.
Take the matching .sigstore.json beside your binary as well. That is the
signature, and you need both to verify.
Verify before running it
This binary handles a key that controls your funds, so check it first.
Compare its SHA-256 against the value in your kit's cli.sha256, then run the
cosign verify-blob command from cli.verify_command. The signature is
recorded in a public transparency log, and verification is entirely offline
against that log - it never contacts NoHoldPay, and it keeps working if this
company does not.
Use the values from your own kit rather than copying a command from here: they are pinned to the exact version your kit was generated against.
What the kit's cli block contains
| Field | What it contains |
|---|---|
cli.download_urls | One download URL per platform for the signed binary. The signature location follows from the binary name, with .sigstore.json appended. |
cli.sha256 | SHA-256 hash for each platform binary. Compare after download. |
cli.verify_command | The exact cosign verify-blob invocation, including the OIDC issuer and certificate-identity pattern that proves the binary was built by our CI on a tagged release. |
cli.version | The released version these URLs and hashes describe. |
A platform appears in download_urls only when its checksum is also published.
If an operator has not finished configuring a release, that platform is omitted
rather than offered without a way to check it - and if none are configured, the
block tells you to contact support instead. A download link you cannot verify
would be worse than no link.
Once verified, invoke it with your kit:
./noholdpay-recover --kit recovery-kit.json --rpc https://your-rpc-url--rpc accepts any public RPC endpoint for the chain you are recovering. Private-network or localhost RPC URLs (your own node) additionally require the --allow-private-rpc flag. For TRON, pass a TronGrid base URL (https://api.trongrid.io for mainnet, https://nile.trongrid.io for Nile testnet). No API key is needed for read-only scans.
One chain at a time
--rpc is a single endpoint, so if your kit covers several chains, scan them one at a time with --chain:
./noholdpay-recover --kit recovery-kit.json --chain ETH --rpc https://<ethereum-rpc>
./noholdpay-recover --kit recovery-kit.json --chain BASE --rpc https://<base-rpc>The CLI checks the endpoint's chain id against the kit and refuses to scan a chain the endpoint does not serve, so a mismatch is an error rather than a silent "no balances found".
Sweeping
Scanning is read-only. Add --sweep to build the recovery transaction for every funded address it found:
# Print the calldata only. Broadcast it yourself from any wallet.
./noholdpay-recover --kit recovery-kit.json --chain ETH --rpc https://<rpc> --sweep
# Or let the CLI sign and broadcast. The key is read from a file, never the command line.
./noholdpay-recover --kit recovery-kit.json --chain ETH --rpc https://<rpc> \
--sweep --signer-key-file ./gas-wallet.hexAdd --token <contract-address> to sweep an ERC-20 or TRC-20 balance; run again without it to recover residual native balance. Solana needs your control key instead of a gas key:
./noholdpay-recover --kit recovery-kit.json --chain SOL --rpc https://<solana-rpc> \
--sweep --solana-control-key-file ./control-key.jsonBoth key flags also accept --signer-key-stdin / --solana-control-key-stdin if you would rather pipe the key than write it to disk.
A scan of a complete address range can take a while on a rate-limited public endpoint, especially on TRON. If it hits the deadline it reports which range it did not reach and exits non-zero; re-run with a longer --timeout to cover the rest. Addresses it already found are printed as it goes.
Recovery scenarios
Dashboard reachable but a payment is stuck
Use the Sweep manually button on the stuck-payment detail page. The dashboard builds the sweep transaction. You sign it in your own wallet.
| Stuck-payment chain | Wallet support today |
|---|---|
| EVM CREATE2 (ETH, BASE, MATIC, BSC) | Any injected EVM wallet (MetaMask, Rabby, Coinbase Wallet, and others). |
| Solana PDA forwarder | Phantom, Solflare, Backpack, Coinbase Wallet, or OKX Wallet. |
| TRON CREATE2 | Any injected TRON wallet (TronLink and compatible). |
The CLI is not required for the dashboard flow.
Dashboard unreachable
- Run the CLI with your recovery kit and a public RPC URL.
- The CLI re-derives every CREATE2 forwarder address (EVM and TRON) and every PDA forwarder address (Solana), then reports unswept balances.
- The CLI prints sweep calldata. For EVM and TRON, any gas-funded wallet can sign and broadcast it - the forwarder contracts only ever release funds to your registered treasury, so the signer cannot redirect them. You need control of the treasury wallet to spend the recovered funds, not to run the sweep. For Solana, sign with the wallet whose pubkey you registered as
control_pubkeyduring onboarding.
The CLI never asks for a seed phrase. It needs your signing wallet only at the final broadcast step.
If you cannot obtain the CLI at all
On EVM and TRON the CLI is a convenience, not a requirement. Sweeping is a permissionless contract call and the payout address is fixed inside each forwarder when it is created, so you can do it with any standard tooling:
- Already-deployed forwarder: call
sweep(address token)on the forwarder for a token balance, orsweepNative()for the native coin. Neither takes a recipient argument, because the forwarder can only pay your registered treasury. - Not yet deployed: call
deployAndSweepBatch(bytes32 merchantId, (uint256 salt, uint256 version)[] requests, address token)on the factory. It creates the forwarder and drains it in one transaction.
Both are unauthenticated. Any wallet holding gas on that chain can send them, including one that has nothing to do with your account, and the funds still land only in your treasury.
The addresses come from your kit. chains[].factory_address, implementation_address, merchant_id, and each treasury version's treasury, init_code_hash and salt range are exactly the inputs a standard CREATE2 address computation needs, so the address set is reproducible from the JSON without our software.
Solana has no equivalent fallback: merchant_recover verifies a signature from your registered control key, so that key is genuinely required.
If you lose your Solana control key
This is the one unrecoverable combination. Changing a Solana control key requires a platform-signed instruction, so losing the key while we are unreachable leaves PDA balances stranded. There is no workaround after the fact. Register a control key you keep in cold storage, and treat it with the same care as a seed phrase.
EVM and TRON have no equivalent single point of failure: the treasury is welded into the contract, so no key of ours and no key of yours is needed to move funds to it.
Limits
- The kit alone cannot give anyone else your funds. For EVM and TRON, sweeping needs only a gas-funded signing key, and the swept funds always land in your registered treasury - you need that treasury wallet to spend them. For Solana, the sweep itself requires the wallet whose pubkey you registered as
control_pubkey. - Losing the wallet seed phrase is unrecoverable. The kit cannot substitute for it.
- Losing your Solana control key while NoHoldPay is unreachable is unrecoverable for PDA forwarder balances. See above.
- A Solana Token-2022 mint that carries any token extension cannot be swept, by either the platform or the CLI. The forwarder program rejects every mint extension rather than guess how a transfer fee, hook, or permanent delegate should affect a payment, and the CLI mirrors that policy exactly - it reports the balance and skips it with the extension named, rather than building a transaction that would revert. Coins with mint extensions are refused at the point they are enabled, so this should never arise in practice; if it does, the funds are visible but not movable by this path.
- The CLI's sweep mode covers CREATE2 and PDA forwarder payments only. UTXO, XRP, Stellar, and Monero do not need the CLI. Recover with your own wallet software.
Portfolio
An optional read-only view of what your receiving wallets hold, valued at current rates. Read-only, non-custodial, and easy to cross-check on public explorers.
Supported blockchains
Every chain NoHoldPay can watch for you, with a setup guide for each. All of them settle to wallets you control.