solana-mint-recovery-engine 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +297 -0
  2. package/dist/bin/smre.js +21 -1
  3. package/dist/bin/smre.js.map +1 -0
  4. package/dist/src/commands/build.js +86 -20
  5. package/dist/src/commands/build.js.map +1 -0
  6. package/dist/src/commands/config.js +6 -2
  7. package/dist/src/commands/config.js.map +1 -0
  8. package/dist/src/commands/doctor.js +64 -15
  9. package/dist/src/commands/doctor.js.map +1 -0
  10. package/dist/src/commands/inspect.js +48 -20
  11. package/dist/src/commands/inspect.js.map +1 -0
  12. package/dist/src/commands/recover.js +93 -30
  13. package/dist/src/commands/recover.js.map +1 -0
  14. package/dist/src/commands/scan.js +77 -25
  15. package/dist/src/commands/scan.js.map +1 -0
  16. package/dist/src/commands/sign.js +24 -8
  17. package/dist/src/commands/sign.js.map +1 -0
  18. package/dist/src/commands/simulate.d.ts +5 -0
  19. package/dist/src/commands/simulate.js +13 -6
  20. package/dist/src/commands/simulate.js.map +1 -0
  21. package/dist/src/commands/submit.js +44 -10
  22. package/dist/src/commands/submit.js.map +1 -0
  23. package/dist/src/core/constants.d.ts +65 -0
  24. package/dist/src/core/constants.js +93 -0
  25. package/dist/src/core/constants.js.map +1 -0
  26. package/dist/src/core/format.d.ts +35 -0
  27. package/dist/src/core/format.js +62 -0
  28. package/dist/src/core/format.js.map +1 -0
  29. package/dist/src/core/rent.d.ts +17 -1
  30. package/dist/src/core/rent.js +25 -4
  31. package/dist/src/core/rent.js.map +1 -0
  32. package/dist/src/core/transaction.d.ts +32 -5
  33. package/dist/src/core/transaction.js +74 -22
  34. package/dist/src/core/transaction.js.map +1 -0
  35. package/dist/src/core/validation.d.ts +66 -23
  36. package/dist/src/core/validation.js +31 -4
  37. package/dist/src/core/validation.js.map +1 -0
  38. package/dist/src/index.d.ts +14 -0
  39. package/dist/src/index.js +51 -0
  40. package/dist/src/index.js.map +1 -0
  41. package/dist/src/io/file.d.ts +5 -2
  42. package/dist/src/io/file.js +64 -11
  43. package/dist/src/io/file.js.map +1 -0
  44. package/dist/src/io/logger.d.ts +31 -0
  45. package/dist/src/io/logger.js +95 -0
  46. package/dist/src/io/logger.js.map +1 -0
  47. package/dist/src/io/rpc.d.ts +75 -5
  48. package/dist/src/io/rpc.js +213 -109
  49. package/dist/src/io/rpc.js.map +1 -0
  50. package/dist/src/signers/signer.d.ts +6 -3
  51. package/dist/src/signers/signer.js +38 -14
  52. package/dist/src/signers/signer.js.map +1 -0
  53. package/package.json +18 -6
package/README.md ADDED
@@ -0,0 +1,297 @@
1
+ # Solana Mint & Token Account Recovery Engine (SMRE)
2
+
3
+ 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.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+ 1. [Core Features](#core-features)
9
+ 2. [Architectural Highlights](#architectural-highlights)
10
+ 3. [Installation & Setup](#installation--setup)
11
+ 4. [CLI Command Reference](#cli-command-reference)
12
+ - [1. Diagnostics: `doctor`](#1-diagnostics-doctor)
13
+ - [2. Config Initialization: `config init`](#2-config-initialization-config-init)
14
+ - [3. Batch Scanning: `scan`](#3-batch-scanning-scan)
15
+ - [4. Single Inspection: `inspect`](#4-single-inspection-inspect)
16
+ - [5. Building Transaction Envelopes: `build`](#5-building-transaction-envelopes-build)
17
+ - [6. Simulation: `simulate`](#6-simulation-simulate)
18
+ - [7. Offline Signing: `sign`](#7-offline-signing-sign)
19
+ - [8. Submission: `submit`](#8-submission-submit)
20
+ - [9. Inline Recovery: `recover`](#9-inline-recovery-recover)
21
+ 5. [Configuration Schema](#configuration-schema)
22
+ 6. [Offline Transaction Envelope Schema](#offline-transaction-envelope-schema)
23
+ 7. [Programmatic Library Usage](#programmatic-library-usage)
24
+ 8. [NPM Publishing Guide (Developer Release Flow)](#npm-publishing-guide-developer-release-flow)
25
+
26
+ ---
27
+
28
+ ## Core Features
29
+ - **Zero-Loss Float Arithmetic:** Operates entirely with native TypeScript `BigInt` types to prevent floating-point inaccuracies for multi-million SOL recoveries.
30
+ - **Multisig Support:** Handles Token-2022 multisig accounts, tracking thresholds and collecting multi-signatures offline.
31
+ - **Offline / Air-Gapped Signature Collection:** Supports separation of duties. Build transactions online, sign offline, and broadcast from a secure node.
32
+ - **On-Chain Simulations:** Employs stable, public `@solana/web3.js` simulation APIs to run pre-execution checks and print execution logs.
33
+ - **Network Resilience:** Automatically injects Compute Budget and Priority Fee instructions to land transactions during times of high congestion.
34
+ - **Secure Key Handling:** Automatically scrubs private key arrays from memory immediately after keypair instantiation.
35
+
36
+ ---
37
+
38
+ ## Architectural Highlights
39
+
40
+ ### Precision-Safe Fee Routing (HIGH-08 Fix)
41
+ In standard implementations, splitting fees requires both the destination address and the authority to sign the transaction. SMRE avoids this requirement:
42
+ 1. Withdraws excess lamports from the Token-2022 account to the **Authority** address.
43
+ 2. Transfers the platform fee from the **Authority** to the **Fee Wallet**.
44
+ 3. Forwards the net amount from the **Authority** to the final **Destination**.
45
+
46
+ Since the **Authority** is already a required signer on the `WithdrawExcessLamports` instruction, no additional signature is required from the destination wallet.
47
+
48
+ ---
49
+
50
+ ## Installation & Setup
51
+
52
+ ### Requirements
53
+ - **Node.js:** >= 18.0.0
54
+ - **NPM:** (Included with Node.js)
55
+
56
+ ### 1. Global Installation (Recommended)
57
+ To install the CLI globally on your system and run it from any directory:
58
+ ```bash
59
+ npm install -g solana-mint-recovery-engine
60
+ ```
61
+ Once installed, verify the installation by checking the version or running the diagnostics:
62
+ ```bash
63
+ smre --version
64
+ smre doctor
65
+ ```
66
+
67
+ ### 2. Run Instantly with NPX (No Installation Required)
68
+ If you prefer not to install the package permanently, you can execute commands on-demand directly from the npm registry using `npx`:
69
+ ```bash
70
+ npx solana-mint-recovery-engine doctor
71
+ npx solana-mint-recovery-engine scan addresses.txt
72
+ ```
73
+
74
+ ### 3. Local Development & Contribution
75
+ If you want to build and run the project locally from source:
76
+ 1. Clone the repository and install dependencies:
77
+ ```bash
78
+ npm install
79
+ ```
80
+ 2. Build the TypeScript files:
81
+ ```bash
82
+ npm run build
83
+ ```
84
+ 3. Link the package to your global bin path for local testing:
85
+ ```bash
86
+ npm link
87
+ ```
88
+ You can now run `smre` globally, and it will execute your local build.
89
+
90
+ ---
91
+
92
+ ## CLI Command Reference
93
+
94
+ ### 1. Diagnostics: `doctor`
95
+ Performs comprehensive checks on the system environment, Node.js version, configuration file health, RPC connection latency, and rent exemption estimates.
96
+ ```bash
97
+ smre doctor [--config <path>]
98
+ ```
99
+
100
+ ### 2. Config Initialization: `config init`
101
+ Creates a default `smre.config.json` configuration file in the working directory.
102
+ ```bash
103
+ smre config init [-o <output-path>]
104
+ ```
105
+
106
+ ### 3. Batch Scanning: `scan`
107
+ 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.
108
+ ```bash
109
+ smre scan <address-file> [--json] [--config <path>]
110
+ ```
111
+ *Note: The address file should contain one address per line. Lines starting with `#` or `//` are treated as comments.*
112
+
113
+ ### 4. Single Inspection: `inspect`
114
+ Analyzes a single Token-2022 account, mint, or multisig on-chain, rendering details about owner program, balance, rent floor, authority, and recovery status.
115
+ ```bash
116
+ smre inspect <address> [--json] [--config <path>]
117
+ ```
118
+
119
+ ### 5. Building Transaction Envelopes: `build`
120
+ Constructs an unsigned transaction to recover excess lamports and saves it into an offline Transaction Envelope JSON file.
121
+ ```bash
122
+ smre build <source-address> \
123
+ -d <destination-address> \
124
+ -o <output-envelope.json> \
125
+ [--fee-wallet <address>] \
126
+ [--fee-percent <number>] \
127
+ [--fee-payer <address>]
128
+ ```
129
+
130
+ ### 6. Simulation: `simulate`
131
+ Runs an on-chain simulation of the constructed Transaction Envelope to verify instructions, print execution logs, and measure compute unit consumption without broadcasting.
132
+ ```bash
133
+ smre simulate <envelope-file>
134
+ ```
135
+
136
+ ### 7. Offline Signing: `sign`
137
+ Signs an offline Transaction Envelope. Supports JSON keypair files, raw base58 private key strings, or direct JSON private key arrays. Automatically tracks signature slots.
138
+ ```bash
139
+ smre sign <envelope-file> \
140
+ -k <keypair-secret-or-path> \
141
+ [-o <output-envelope.json>]
142
+ ```
143
+
144
+ ### 8. Submission: `submit`
145
+ Validates that the required signature threshold is met (including multisig threshold), broadcasts the transaction to the network, and polls the node for confirmation.
146
+ ```bash
147
+ smre submit <envelope-file>
148
+ ```
149
+
150
+ ### 9. Inline Recovery: `recover`
151
+ Convenience command that performs inspection, building, signing, simulation, submission, and confirmation in a single online step.
152
+ ```bash
153
+ smre recover <source-address> \
154
+ -k <keypair-secret-or-path> \
155
+ -d <destination-address> \
156
+ [--fee-wallet <address>] \
157
+ [--fee-percent <number>]
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Configuration Schema
163
+ Configuration options can be placed in `smre.config.json` or passed as a custom file using the `-c` flag.
164
+ ```json
165
+ {
166
+ "rpcUrl": "https://api.mainnet-beta.solana.com",
167
+ "commitment": "confirmed",
168
+ "defaultDestination": "9xQdBNbLqP55ePE1R24g5652uhGzTsw34JmUCwm",
169
+ "feeWallet": "EGMQSHdW5vLvTZ4ro8BkGjWerXcWH7oHVW2EDMJqPA4x",
170
+ "feePercentage": 2.5,
171
+ "priorityFee": 5000
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Offline Transaction Envelope Schema
178
+ Transaction envelopes use a strict, schema-validated JSON format:
179
+ ```json
180
+ {
181
+ "version": "1.1.0",
182
+ "type": "withdraw-excess-lamports",
183
+ "metadata": {
184
+ "sourceAddress": "4zMMC9ZdZhLx2u223612q76Cc223612q76Cc223612",
185
+ "sourceType": "mint",
186
+ "destinationAddress": "9xQdBNbLqP55ePE1R24g5652uhGzTsw34JmUCwm",
187
+ "authorityAddress": "F223612q76Cc223612q76Cc223612q76Cc223612q",
188
+ "excessLamports": "2960720",
189
+ "rentFloor": "1461600",
190
+ "createdAt": "2026-07-07T13:25:28Z",
191
+ "blockhash": "D9yVwZ9p8N...WdQsK",
192
+ "lastValidBlockHeight": 268495034,
193
+ "feePercentage": 2.5,
194
+ "feeWallet": "EGMQSHdW5vLvTZ4ro8BkGjWerXcWH7oHVW2EDMJqPA4x",
195
+ "isToken2022": true
196
+ },
197
+ "rawTransactionB64": "AYADg...",
198
+ "signatures": [
199
+ {
200
+ "pubkey": "F223612q76Cc223612q76Cc223612q76Cc223612q",
201
+ "signature": "3uXp9G..."
202
+ }
203
+ ]
204
+ }
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Programmatic Library Usage
210
+ SMRE is fully typed and can be imported directly into node-based scripts:
211
+ ```typescript
212
+ import { RpcAdapter, buildRecoveryInstructions, lamportsToSolString } from 'solana-mint-recovery-engine';
213
+ import { PublicKey, Transaction } from '@solana/web3.js';
214
+
215
+ async function main() {
216
+ const rpc = new RpcAdapter('https://api.mainnet-beta.solana.com', 'confirmed');
217
+
218
+ // Inspect
219
+ const target = new PublicKey('...');
220
+ const account = await rpc.inspectAccount(target);
221
+
222
+ const rentFloor = await rpc.getMinimumBalanceForRentExemption(account.dataSize);
223
+ const excess = account.balance - rentFloor;
224
+
225
+ console.log(`Recoverable amount: ${lamportsToSolString(excess)} SOL`);
226
+
227
+ if (excess > 0n && account.authority) {
228
+ const instructions = buildRecoveryInstructions({
229
+ source: target,
230
+ destination: new PublicKey('...'),
231
+ authority: account.authority,
232
+ excessAmount: excess,
233
+ priorityFee: 1000,
234
+ });
235
+
236
+ const tx = new Transaction().add(...instructions);
237
+ // Continue with sign/submit...
238
+ }
239
+ }
240
+ ```
241
+
242
+ ---
243
+
244
+ ## NPM Publishing Guide (Developer Release Flow)
245
+
246
+ Follow these steps to publish or update the package on the NPM registry:
247
+
248
+ ### 1. Prerequisite Checks
249
+ Before publishing, ensure the codebase is completely clean, builds successfully, and passes all tests.
250
+ ```bash
251
+ # Verify TypeScript compiles without errors
252
+ npm run lint
253
+
254
+ # Run Jest tests and verification tests
255
+ npm run test
256
+ npm run test:run
257
+ ```
258
+
259
+ ### 2. Configure package.json Metadata
260
+ Ensure the following fields are correct in `package.json`:
261
+ - `"name"`: Set to your package name (e.g., `solana-mint-recovery-engine` or a scoped package name like `@my-org/smre`).
262
+ - `"publishConfig"`: If using a scoped package, you may want to set it to public:
263
+ ```json
264
+ "publishConfig": {
265
+ "access": "public"
266
+ }
267
+ ```
268
+
269
+ ### 3. Versioning
270
+ Increment the package version according to Semantic Versioning (SemVer):
271
+ - **Patch release** (bug fixes): `npm version patch` (e.g., `1.1.0` → `1.1.1`)
272
+ - **Minor release** (new backward-compatible features): `npm version minor` (e.g., `1.1.0` → `1.2.0`)
273
+ - **Major release** (breaking changes): `npm version major` (e.g., `1.1.0` → `2.0.0`)
274
+
275
+ This command updates `package.json`, `package-lock.json`, and creates a local Git tag.
276
+
277
+ ### 4. Authenticate with NPM
278
+ If you are not logged in, run:
279
+ ```bash
280
+ npm login
281
+ ```
282
+ Provide your username, password, email, and one-time password (OTP).
283
+
284
+ ### 5. Publish to the Registry
285
+ Publish the package. The `"prepack"` script in `package.json` will automatically trigger `npm run build` to compile the TypeScript code to `./dist` before packaging:
286
+ ```bash
287
+ npm publish
288
+ ```
289
+ If you are publishing a scoped package for the first time:
290
+ ```bash
291
+ npm publish --access public
292
+ ```
293
+
294
+ ---
295
+
296
+ ## License
297
+ MIT
package/dist/bin/smre.js CHANGED
@@ -11,11 +11,30 @@ const submit_1 = require("../src/commands/submit");
11
11
  const recover_1 = require("../src/commands/recover");
12
12
  const config_1 = require("../src/commands/config");
13
13
  const doctor_1 = require("../src/commands/doctor");
14
+ // Determine package.json path dynamically based on runtime location
15
+ let packageJson;
16
+ try {
17
+ // Production path (dist/bin/smre.js -> ../../package.json)
18
+ packageJson = require('../../package.json');
19
+ }
20
+ catch {
21
+ // Development path (bin/smre.ts -> ../package.json)
22
+ packageJson = require('../package.json');
23
+ }
24
+ // MED-12: Global error handler for unhandled exceptions/rejections
25
+ process.on('unhandledRejection', (reason) => {
26
+ console.error(`\n✘ Unhandled error: ${reason}`);
27
+ process.exit(1);
28
+ });
29
+ process.on('uncaughtException', (err) => {
30
+ console.error(`\n✘ Fatal error: ${err.message}`);
31
+ process.exit(1);
32
+ });
14
33
  const program = new commander_1.Command();
15
34
  program
16
35
  .name('smre')
17
36
  .description('Solana Mint & Token Account Recovery Engine (SMRE) CLI')
18
- .version('1.0.0')
37
+ .version(packageJson.version)
19
38
  .option('-c, --config <path>', 'Path to custom configuration JSON file');
20
39
  program
21
40
  .command('scan <address-file>')
@@ -104,3 +123,4 @@ program
104
123
  (0, doctor_1.runDoctor)(program.opts().config);
105
124
  });
106
125
  program.parse(process.argv);
126
+ //# sourceMappingURL=smre.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smre.js","sourceRoot":"","sources":["../../bin/smre.ts"],"names":[],"mappings":"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"}
@@ -9,40 +9,82 @@ const rpc_1 = require("../io/rpc");
9
9
  const rent_1 = require("../core/rent");
10
10
  const transaction_1 = require("../core/transaction");
11
11
  const file_1 = require("../io/file");
12
+ const constants_1 = require("../core/constants");
13
+ const format_1 = require("../core/format");
14
+ const logger_1 = require("../io/logger");
12
15
  const chalk_1 = __importDefault(require("chalk"));
13
16
  async function runBuild(addressStr, options) {
14
17
  try {
15
18
  const config = (0, file_1.loadConfig)(options.config);
16
19
  const rpc = new rpc_1.RpcAdapter(config.rpcUrl, config.commitment);
17
- const source = new web3_js_1.PublicKey(addressStr);
20
+ // MED-07: Validate public key input
21
+ let source;
22
+ try {
23
+ source = new web3_js_1.PublicKey(addressStr);
24
+ }
25
+ catch {
26
+ throw new Error(`Invalid source address: "${addressStr}". Expected a valid base58-encoded public key.`);
27
+ }
18
28
  // 1. Inspect account state
29
+ logger_1.logger.step(1, 8, 'Inspecting target account...');
19
30
  const account = await rpc.inspectAccount(source);
31
+ // CRIT-03: Reject legacy token accounts
20
32
  if (!account.isToken2022) {
21
- throw new Error(`Account is not owned by the Token-2022 program. Recoveries are not supported.`);
33
+ throw new Error(`Account ${source.toBase58()} is owned by the legacy SPL Token Program. ` +
34
+ `The WithdrawExcessLamports instruction is a Token-2022-only feature. ` +
35
+ `Recovery from legacy token accounts requires a different mechanism.`);
36
+ }
37
+ // HIGH-04: Use RPC-based rent floor
38
+ let rentFloor;
39
+ let excess;
40
+ try {
41
+ rentFloor = await rpc.getMinimumBalanceForRentExemption(account.dataSize);
42
+ excess = account.balance > rentFloor ? account.balance - rentFloor : 0n;
43
+ }
44
+ catch {
45
+ const offlineResult = (0, rent_1.calculateExcessLamports)(account.dataSize, account.balance);
46
+ rentFloor = offlineResult.rentFloor;
47
+ excess = offlineResult.excess;
22
48
  }
23
- const { excess, rentFloor } = (0, rent_1.calculateExcessLamports)(account.dataSize, account.balance);
24
49
  if (excess <= 0n) {
25
50
  throw new Error(`Account has no excess lamports above the rent floor (${rentFloor.toLocaleString()} lamports).`);
26
51
  }
27
52
  // 2. Resolve destination
53
+ logger_1.logger.step(2, 8, 'Resolving destination...');
28
54
  const destinationStr = options.destination || config.defaultDestination;
29
55
  if (!destinationStr) {
30
56
  throw new Error(`No destination address specified. Use --destination <address> or define defaultDestination in config.`);
31
57
  }
32
- const destination = new web3_js_1.PublicKey(destinationStr);
58
+ let destination;
59
+ try {
60
+ destination = new web3_js_1.PublicKey(destinationStr);
61
+ }
62
+ catch {
63
+ throw new Error(`Invalid destination address: "${destinationStr}". Expected a valid base58-encoded public key.`);
64
+ }
33
65
  // 3. Resolve authority
34
- const authority = account.authority;
66
+ logger_1.logger.step(3, 8, 'Resolving authority...');
67
+ let authority = account.authority;
35
68
  if (!authority) {
36
- throw new Error(`No authority found for account. It is not recoverable.`);
69
+ if (account.type === 'mint') {
70
+ authority = source;
71
+ // CRIT-05: Clear messaging about what this means
72
+ logger_1.logger.warn(`Mint authority is revoked. Recovery will require the ORIGINAL MINT KEYPAIR ` +
73
+ `(the private key that created mint address ${source.toBase58()}). ` +
74
+ `If you do not possess this keypair, the transaction will fail to sign.`);
75
+ }
76
+ else {
77
+ throw new Error(`No authority found for account ${source.toBase58()}. Recovery is not possible.`);
78
+ }
37
79
  }
38
80
  // 4. Resolve fee payer
81
+ logger_1.logger.step(4, 8, 'Resolving fee payer...');
39
82
  let feePayer = authority;
40
83
  if (account.type === 'multisig' && account.multisigSigners && account.multisigSigners.length > 0) {
41
84
  if (options.feePayer) {
42
85
  feePayer = new web3_js_1.PublicKey(options.feePayer);
43
86
  }
44
87
  else {
45
- // Default to the first co-signer for multisig accounts
46
88
  feePayer = account.multisigSigners[0];
47
89
  }
48
90
  }
@@ -50,14 +92,26 @@ async function runBuild(addressStr, options) {
50
92
  feePayer = new web3_js_1.PublicKey(options.feePayer);
51
93
  }
52
94
  // 5. Resolve platform fee wallet & percentage
95
+ logger_1.logger.step(5, 8, 'Resolving fee configuration...');
53
96
  const feeWalletStr = options.feeWallet || config.feeWallet;
54
- const feePercentage = options.feePercent !== undefined
55
- ? parseInt(options.feePercent, 10)
56
- : config.feePercentage;
97
+ // CRIT-06 FIX: Proper fee percentage parsing with validation
98
+ let feePercentage = config.feePercentage;
99
+ if (options.feePercent !== undefined) {
100
+ const parsed = parseFloat(options.feePercent);
101
+ if (isNaN(parsed) || parsed < 0 || parsed > 100) {
102
+ throw new Error(`Invalid fee percentage: "${options.feePercent}". Must be a number between 0 and 100.`);
103
+ }
104
+ feePercentage = parsed;
105
+ }
57
106
  const feeWallet = feeWalletStr ? new web3_js_1.PublicKey(feeWalletStr) : undefined;
58
- // 6. Fetch latest blockhash
59
- const blockhash = await rpc.getLatestBlockhash();
107
+ if (feeWallet && feePercentage > 0) {
108
+ logger_1.logger.info(`Platform fee: ${feePercentage}% to ${feeWallet.toBase58()}`);
109
+ }
110
+ // 6. Fetch latest blockhash (HIGH-02: include lastValidBlockHeight)
111
+ logger_1.logger.step(6, 8, 'Fetching latest blockhash...');
112
+ const { blockhash, lastValidBlockHeight } = await rpc.getLatestBlockhash();
60
113
  // 7. Build instructions
114
+ logger_1.logger.step(7, 8, 'Building transaction instructions...');
61
115
  const instructions = (0, transaction_1.buildRecoveryInstructions)({
62
116
  source,
63
117
  destination,
@@ -66,8 +120,11 @@ async function runBuild(addressStr, options) {
66
120
  developerFeeWallet: feeWallet,
67
121
  feePercentage,
68
122
  multiSigners: account.multisigSigners,
123
+ programId: account.ownerProgram,
124
+ priorityFee: config.priorityFee,
69
125
  });
70
126
  // 8. Compile transaction
127
+ logger_1.logger.step(8, 8, 'Compiling transaction...');
71
128
  const tx = new web3_js_1.Transaction();
72
129
  tx.add(...instructions);
73
130
  tx.recentBlockhash = blockhash;
@@ -78,9 +135,9 @@ async function runBuild(addressStr, options) {
78
135
  verifySignatures: false,
79
136
  });
80
137
  const rawTransactionB64 = serialized.toString('base64');
81
- // 9. Create envelope JSON
138
+ // Create envelope JSON
82
139
  const envelope = {
83
- version: '1.0.0',
140
+ version: constants_1.ENVELOPE_VERSION,
84
141
  type: 'withdraw-excess-lamports',
85
142
  metadata: {
86
143
  sourceAddress: source.toBase58(),
@@ -91,6 +148,10 @@ async function runBuild(addressStr, options) {
91
148
  rentFloor: rentFloor.toString(),
92
149
  createdAt: new Date().toISOString(),
93
150
  blockhash,
151
+ lastValidBlockHeight,
152
+ isToken2022: account.isToken2022,
153
+ feePercentage: feeWallet ? feePercentage : undefined,
154
+ feeWallet: feeWallet?.toBase58(),
94
155
  },
95
156
  rawTransactionB64,
96
157
  signatures: [],
@@ -120,20 +181,25 @@ async function runBuild(addressStr, options) {
120
181
  }
121
182
  // Write envelope file
122
183
  (0, file_1.writeEnvelope)(options.output, envelope);
123
- console.log(chalk_1.default.green(`✔ Built transaction envelope and saved to ${options.output}`));
124
- console.log('\nTransaction Metadata:');
184
+ logger_1.logger.success(`Built transaction envelope ${options.output}`);
185
+ console.log('\nTransaction Details:');
125
186
  console.log(` Source: ${envelope.metadata.sourceAddress} (${envelope.metadata.sourceType})`);
126
187
  console.log(` Destination: ${envelope.metadata.destinationAddress}`);
127
188
  console.log(` Authority: ${envelope.metadata.authorityAddress}`);
128
189
  console.log(` Fee Payer: ${feePayer.toBase58()}`);
129
- console.log(` Recoverable: ${Number(excess) / 1e9} SOL`);
130
- if (feeWallet) {
131
- console.log(` Fee Split: ${feePercentage}% to ${feeWallet.toBase58()}`);
190
+ console.log(` Recoverable: ${(0, format_1.formatSol)(excess)}`);
191
+ if (feeWallet && feePercentage > 0) {
192
+ const feeAmount = (excess * BigInt(Math.round(feePercentage * 100))) / 10000n;
193
+ const netAmount = excess - feeAmount;
194
+ console.log(` Fee Split: ${feePercentage}% → ${feeWallet.toBase58()} (${(0, format_1.formatSol)(feeAmount)})`);
195
+ console.log(` Net Amount: ${(0, format_1.formatSol)(netAmount)}`);
132
196
  }
133
197
  console.log(` Blockhash: ${envelope.metadata.blockhash}`);
198
+ console.log(chalk_1.default.yellow(` ⚠ Blockhash expires in ~60-90 seconds. Sign and submit promptly.`));
134
199
  }
135
200
  catch (err) {
136
- console.error(chalk_1.default.red(`✘ Failed to build transaction: ${err.message}`));
201
+ logger_1.logger.fail(`Failed to build transaction: ${err.message}`);
137
202
  process.exit(1);
138
203
  }
139
204
  }
205
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -6,16 +6,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.initConfig = initConfig;
7
7
  const file_1 = require("../io/file");
8
8
  const validation_1 = require("../core/validation");
9
+ const logger_1 = require("../io/logger");
9
10
  const chalk_1 = __importDefault(require("chalk"));
10
11
  function initConfig(outputPath = 'smre.config.json') {
11
12
  try {
12
13
  const defaultConfig = validation_1.ConfigSchema.parse({});
13
14
  (0, file_1.writeConfig)(outputPath, defaultConfig);
14
- console.log(chalk_1.default.green(`✔ Initialized default configuration at ${outputPath}`));
15
+ logger_1.logger.success(`Initialized default configuration at ${outputPath}`);
15
16
  console.log(JSON.stringify(defaultConfig, null, 2));
17
+ console.log(chalk_1.default.yellow(`\n ⚠ Review and customize this file before use.\n` +
18
+ ` In particular, set your defaultDestination and review fee settings.`));
16
19
  }
17
20
  catch (err) {
18
- console.error(chalk_1.default.red(`✘ Failed to initialize configuration: ${err.message}`));
21
+ logger_1.logger.fail(`Failed to initialize configuration: ${err.message}`);
19
22
  process.exit(1);
20
23
  }
21
24
  }
25
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/commands/config.ts"],"names":[],"mappings":";;;;;AAKA,gCAcC;AAnBD,qCAAyC;AACzC,mDAAkD;AAClD,yCAAsC;AACtC,kDAA0B;AAE1B,SAAgB,UAAU,CAAC,aAAqB,kBAAkB;IAChE,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,yBAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAA,kBAAW,EAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QACvC,eAAM,CAAC,OAAO,CAAC,wCAAwC,UAAU,EAAE,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CACtB,oDAAoD;YACpD,uEAAuE,CACxE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,IAAI,CAAC,uCAAwC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}