NoHoldPay
Receiving payments

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):

SectionWhat it covers
chainsEVM 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_versionsSolana 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_walletsInformational 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.
cliPer-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:

ModeRecovery 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.
MoneroYou 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

Go to Settings in the dashboard.
Scroll to Recovery and click Download Recovery Kit.

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:

WhatWhy
The kit JSONEvery address you have ever had is derived from it.
Your treasury walletWhere swept funds land. You need it to spend them, not to run the sweep.
A gas-funded wallet on each chainPays for the sweep transaction. On EVM and TRON this can be any wallet, including a throwaway.
Your Solana control keyRequired to sweep Solana PDA balances. Nothing else can substitute for it.
A public RPC URL per chainAny 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 computerFile
Mac with Apple Silicon (M1, M2, M3, M4)noholdpay-recover-<version>-darwin-arm64
Mac with an Intel processornoholdpay-recover-<version>-darwin-amd64
Windowsnoholdpay-recover-<version>-windows-amd64.exe
Linux on a normal PC or servernoholdpay-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

FieldWhat it contains
cli.download_urlsOne download URL per platform for the signed binary. The signature location follows from the binary name, with .sigstore.json appended.
cli.sha256SHA-256 hash for each platform binary. Compare after download.
cli.verify_commandThe 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.versionThe 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.hex

Add --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.json

Both 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 chainWallet support today
EVM CREATE2 (ETH, BASE, MATIC, BSC)Any injected EVM wallet (MetaMask, Rabby, Coinbase Wallet, and others).
Solana PDA forwarderPhantom, Solflare, Backpack, Coinbase Wallet, or OKX Wallet.
TRON CREATE2Any injected TRON wallet (TronLink and compatible).

The CLI is not required for the dashboard flow.

Dashboard unreachable

  1. Run the CLI with your recovery kit and a public RPC URL.
  2. The CLI re-derives every CREATE2 forwarder address (EVM and TRON) and every PDA forwarder address (Solana), then reports unswept balances.
  3. 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_pubkey during 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, or sweepNative() 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.

On this page