solana-mint-recovery-engine
v1.3.1
Published
Solana Mint & Token Account Recovery Engine (SMRE) CLI tool
Readme
Solana Mint & Token Account Recovery Engine (SMRE)
SMRE is an enterprise-grade Command Line Interface (CLI) tool and programmatic library designed to safely scan, inspect, build, sign, simulate, and submit transactions to recover excess SOL (lamports) lying above the rent-exempt minimum in Solana Token-2022 (Token Extensions) accounts, mints, and multisigs.
Table of Contents
- Core Features
- Architectural Highlights
- Installation & Setup
- CLI Command Reference
- Configuration Schema
- Offline Transaction Envelope Schema
- Programmatic Library Usage
- NPM Publishing Guide (Developer Release Flow)
Core Features
- Zero-Loss Float Arithmetic: Operates entirely with native TypeScript
BigInttypes to prevent floating-point inaccuracies for multi-million SOL recoveries. - Multisig Support: Handles Token-2022 multisig accounts, tracking thresholds and collecting multi-signatures offline.
- Offline / Air-Gapped Signature Collection: Supports separation of duties. Build transactions online, sign offline, and broadcast from a secure node.
- On-Chain Simulations: Employs stable, public
@solana/web3.jssimulation APIs to run pre-execution checks and print execution logs. - Network Resilience: Automatically injects Compute Budget and Priority Fee instructions to land transactions during times of high congestion.
- Secure Key Handling: Automatically scrubs private key arrays from memory immediately after keypair instantiation.
Architectural Highlights
Precision-Safe Fee Routing (HIGH-08 Fix)
In standard implementations, splitting fees requires both the destination address and the authority to sign the transaction. SMRE avoids this requirement:
- Withdraws excess lamports from the Token-2022 account to the Authority address.
- Transfers the platform fee from the Authority to the Fee Wallet.
- Forwards the net amount from the Authority to the final Destination.
Since the Authority is already a required signer on the WithdrawExcessLamports instruction, no additional signature is required from the destination wallet.
Installation & Setup
Requirements
- Node.js: >= 18.0.0
- NPM: (Included with Node.js)
1. Global Installation (Recommended)
To install the CLI globally on your system and run it from any directory:
npm install -g solana-mint-recovery-engineOnce installed, verify the installation by checking the version or running the diagnostics:
smre --version
smre doctor2. Run Instantly with NPX (No Installation Required)
If you prefer not to install the package permanently, you can execute commands on-demand directly from the npm registry using npx:
npx solana-mint-recovery-engine doctor
npx solana-mint-recovery-engine scan addresses.txt3. Local Development & Contribution
If you want to build and run the project locally from source:
- Clone the repository and install dependencies:
npm install - Build the TypeScript files:
npm run build - Link the package to your global bin path for local testing:
You can now runnpm linksmreglobally, and it will execute your local build.
CLI Command Reference
1. Diagnostics: doctor
Performs comprehensive checks on the system environment, Node.js version, configuration file health, RPC connection latency, and rent exemption estimates.
smre doctor [--config <path>]2. Config Initialization: config init
Creates a default smre.config.json configuration file in the working directory.
smre config init [-o <output-path>]3. Batch Scanning: scan
Scans a text file containing base58-encoded Solana addresses for recoverable excess lamports. Uses high-performance batching (100 accounts per batch) and reports results in a clean table or structured JSON.
smre scan <address-file> [--json] [--config <path>]Note: The address file should contain one address per line. Lines starting with # or // are treated as comments.
4. Single Inspection: inspect
Analyzes a single Token-2022 account, mint, or multisig on-chain, rendering details about owner program, balance, rent floor, authority, and recovery status.
smre inspect <address> [--json] [--config <path>]5. Building Transaction Envelopes: build
Constructs an unsigned transaction to recover excess lamports and saves it into an offline Transaction Envelope JSON file.
smre build <source-address> \
-d <destination-address> \
-o <output-envelope.json> \
[--fee-wallet <address>] \
[--fee-percent <number>] \
[--fee-payer <address>] \
[--nonce <nonce-account-address>] \
[--nonce-authority <address>] \
[--close]6. Simulation: simulate
Runs an on-chain simulation of the constructed Transaction Envelope to verify instructions, print execution logs, and measure compute unit consumption without broadcasting.
smre simulate <envelope-file>7. Offline Signing: sign
Signs an offline Transaction Envelope. Supports JSON keypair files, raw base58 private key strings, or direct JSON private key arrays. Automatically tracks signature slots.
smre sign <envelope-file> \
-k <keypair-secret-or-path> \
[-o <output-envelope.json>]8. Submission: submit
Validates that the required signature threshold is met (including multisig threshold), broadcasts the transaction to the network, and polls the node for confirmation.
smre submit <envelope-file>9. Inline Recovery: recover
Convenience command that performs inspection, building, signing, simulation, submission, and confirmation in a single online step.
smre recover <source-address> \
-k <keypair-secret-or-path> \
-d <destination-address> \
[--fee-wallet <address>] \
[--fee-percent <number>] \
[--nonce <nonce-account-address>] \
[--nonce-authority <address>] \
[--close]Configuration Schema
Configuration options can be placed in smre.config.json or passed as a custom file using the -c flag.
{
"rpcUrl": "https://api.mainnet-beta.solana.com",
"commitment": "confirmed",
"defaultDestination": "9xQdBNbLqP55ePE1R24g5652uhGzTsw34JmUCwm",
"feeWallet": "EGMQSHdW5vLvTZ4ro8BkGjWerXcWH7oHVW2EDMJqPA4x",
"feePercentage": 2.5,
"priorityFee": 5000
}Offline Transaction Envelope Schema
Transaction envelopes use a strict, schema-validated JSON format:
{
"version": "1.1.0",
"type": "withdraw-excess-lamports",
"metadata": {
"sourceAddress": "4zMMC9ZdZhLx2u223612q76Cc223612q76Cc223612",
"sourceType": "mint",
"destinationAddress": "9xQdBNbLqP55ePE1R24g5652uhGzTsw34JmUCwm",
"authorityAddress": "F223612q76Cc223612q76Cc223612q76Cc223612q",
"excessLamports": "2960720",
"rentFloor": "1461600",
"createdAt": "2026-07-07T13:25:28Z",
"blockhash": "D9yVwZ9p8N...WdQsK",
"lastValidBlockHeight": 268495034,
"feePercentage": 2.5,
"feeWallet": "EGMQSHdW5vLvTZ4ro8BkGjWerXcWH7oHVW2EDMJqPA4x",
"isToken2022": true
},
"rawTransactionB64": "AYADg...",
"signatures": [
{
"pubkey": "F223612q76Cc223612q76Cc223612q76Cc223612q",
"signature": "3uXp9G..."
}
]
}Programmatic Library Usage
SMRE is fully typed and can be imported directly into node-based scripts:
import { RpcAdapter, buildRecoveryInstructions, lamportsToSolString } from 'solana-mint-recovery-engine';
import { PublicKey, Transaction } from '@solana/web3.js';
async function main() {
const rpc = new RpcAdapter('https://api.mainnet-beta.solana.com', 'confirmed');
// Inspect
const target = new PublicKey('...');
const account = await rpc.inspectAccount(target);
const rentFloor = await rpc.getMinimumBalanceForRentExemption(account.dataSize);
const excess = account.balance - rentFloor;
console.log(`Recoverable amount: ${lamportsToSolString(excess)} SOL`);
if (excess > 0n && account.authority) {
const instructions = buildRecoveryInstructions({
source: target,
destination: new PublicKey('...'),
authority: account.authority,
excessAmount: excess,
priorityFee: 1000,
});
const tx = new Transaction().add(...instructions);
// Continue with sign/submit...
}
}NPM Publishing Guide (Developer Release Flow)
Follow these steps to publish or update the package on the NPM registry:
1. Prerequisite Checks
Before publishing, ensure the codebase is completely clean, builds successfully, and passes all tests.
# Verify TypeScript compiles without errors
npm run lint
# Run Jest tests and verification tests
npm run test
npm run test:run2. Configure package.json Metadata
Ensure the following fields are correct in package.json:
"name": Set to your package name (e.g.,solana-mint-recovery-engineor a scoped package name like@my-org/smre)."publishConfig": If using a scoped package, you may want to set it to public:"publishConfig": { "access": "public" }
3. Versioning
Increment the package version according to Semantic Versioning (SemVer):
- Patch release (bug fixes):
npm version patch(e.g.,1.1.0→1.1.1) - Minor release (new backward-compatible features):
npm version minor(e.g.,1.1.0→1.2.0) - Major release (breaking changes):
npm version major(e.g.,1.1.0→2.0.0)
This command updates package.json, package-lock.json, and creates a local Git tag.
4. Authenticate with NPM
If you are not logged in, run:
npm loginProvide your username, password, email, and one-time password (OTP).
5. Publish to the Registry
Publish the package. The "prepack" script in package.json will automatically trigger npm run build to compile the TypeScript code to ./dist before packaging:
npm publishIf you are publishing a scoped package for the first time:
npm publish --access publicLicense
MIT
