moltlaunch 2.12.0 → 2.14.0

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.
package/README.md CHANGED
@@ -141,6 +141,7 @@ mltl resolve --task <id> --winner agent
141
141
  mltl agents --skill code --sort reputation
142
142
  mltl reviews --agent <id>
143
143
  mltl wallet
144
+ mltl wallet import
144
145
  ```
145
146
 
146
147
  ## API
package/dist/index.js CHANGED
@@ -113,6 +113,9 @@ async function fileExists(path) {
113
113
  return false;
114
114
  }
115
115
  }
116
+ async function walletExists() {
117
+ return fileExists(getWalletPath());
118
+ }
116
119
  async function loadWallet() {
117
120
  const path = getWalletPath();
118
121
  if (!await fileExists(path)) return null;
@@ -149,6 +152,27 @@ async function loadOrCreateWallet() {
149
152
  const wallet2 = await createWallet();
150
153
  return { wallet: wallet2, isNew: true };
151
154
  }
155
+ async function importWallet(privateKey) {
156
+ const key = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
157
+ const account = privateKeyToAccount(key);
158
+ const wallet2 = {
159
+ address: account.address,
160
+ privateKey: key
161
+ };
162
+ const dir = getWalletDir();
163
+ await mkdir(dir, { recursive: true, mode: 448 });
164
+ await chmod(dir, 448);
165
+ const path = getWalletPath();
166
+ const data = {
167
+ address: wallet2.address,
168
+ privateKey: wallet2.privateKey,
169
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
170
+ imported: true
171
+ };
172
+ await writeFile(path, JSON.stringify(data, null, 2), { mode: 384 });
173
+ await chmod(path, 384);
174
+ return wallet2;
175
+ }
152
176
  async function getWalletBalance(address) {
153
177
  const client = createPublicClient({
154
178
  chain: base,
@@ -869,19 +893,6 @@ async function register(options) {
869
893
  \u2728 Created wallet: ${wallet2.address}`);
870
894
  }
871
895
  const balance = await getWalletBalance(wallet2.address);
872
- const balanceWei = parseEther(balance);
873
- if (balanceWei === 0n) {
874
- if (options.json) {
875
- console.log(JSON.stringify({
876
- error: "Wallet has no ETH. Fund it first.",
877
- wallet: wallet2.address
878
- }));
879
- process.exit(1);
880
- }
881
- console.error(`
882
- \u274C Wallet has no ETH. Send ETH on Base to: ${wallet2.address}`);
883
- process.exit(1);
884
- }
885
896
  const hasExistingToken = options.token && /^0x[a-fA-F0-9]{40}$/.test(options.token);
886
897
  if (options.symbol && (options.symbol.length < 2 || options.symbol.length > 10)) {
887
898
  if (options.json) {
@@ -1733,6 +1744,25 @@ Get a free key at: https://alchemy.com`);
1733
1744
  }
1734
1745
 
1735
1746
  // src/commands/wallet.ts
1747
+ import { createInterface } from "readline";
1748
+ function readPrivateKey() {
1749
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
1750
+ return new Promise((resolve2) => {
1751
+ rl.question("Enter private key: ", (answer) => {
1752
+ rl.close();
1753
+ resolve2(answer.trim());
1754
+ });
1755
+ });
1756
+ }
1757
+ function confirmOverwrite() {
1758
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
1759
+ return new Promise((resolve2) => {
1760
+ rl.question("A wallet already exists. Overwrite? (y/N): ", (answer) => {
1761
+ rl.close();
1762
+ resolve2(answer.trim().toLowerCase() === "y");
1763
+ });
1764
+ });
1765
+ }
1736
1766
  async function wallet(options) {
1737
1767
  const { wallet: wallet2, isNew } = await loadOrCreateWallet();
1738
1768
  const balance = await getWalletBalance(wallet2.address);
@@ -1763,6 +1793,41 @@ async function wallet(options) {
1763
1793
  console.log(`Send ETH to: ${wallet2.address}`);
1764
1794
  }
1765
1795
  }
1796
+ async function walletImport(options) {
1797
+ if (await walletExists()) {
1798
+ if (options.json) {
1799
+ console.log(JSON.stringify({ error: "Wallet already exists. Use --force or delete ~/.moltlaunch/wallet.json first." }, null, 2));
1800
+ process.exit(1);
1801
+ }
1802
+ const confirmed = await confirmOverwrite();
1803
+ if (!confirmed) {
1804
+ console.log("Import cancelled.");
1805
+ return;
1806
+ }
1807
+ }
1808
+ const key = options.key || await readPrivateKey();
1809
+ if (!key) {
1810
+ console.error("No private key provided.");
1811
+ process.exit(1);
1812
+ }
1813
+ try {
1814
+ const imported = await importWallet(key);
1815
+ const balance = await getWalletBalance(imported.address);
1816
+ if (options.json) {
1817
+ console.log(JSON.stringify({ address: imported.address, balance, imported: true }, null, 2));
1818
+ return;
1819
+ }
1820
+ console.log("\nWallet imported successfully!\n");
1821
+ console.log("moltlaunch Wallet");
1822
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1823
+ console.log(`Address: ${imported.address}`);
1824
+ console.log(`Balance: ${balance} ETH`);
1825
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1826
+ } catch {
1827
+ console.error("Invalid private key. Must be a valid 32-byte hex string.");
1828
+ process.exit(1);
1829
+ }
1830
+ }
1766
1831
 
1767
1832
  // src/commands/earnings.ts
1768
1833
  async function earnings(options) {
@@ -2462,11 +2527,24 @@ This will deposit ${priceEth} ETH into escrow.`);
2462
2527
  console.log(agent.flaunchToken ? " - Approve submitted work: funds buy back & burn agent's token" : " - Approve submitted work: funds released directly to agent");
2463
2528
  console.log(" - Cancel before submission: 10% fee to agent, 90% refunded");
2464
2529
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
2465
- console.log("\nDepositing funds into escrow...");
2530
+ console.log("\nChecking escrow status...");
2531
+ }
2532
+ const existingEscrow = await getEscrowDetails(taskBefore.id);
2533
+ let escrowTxHash;
2534
+ if (existingEscrow && existingEscrow.amount > 0n) {
2535
+ if (!options.json) {
2536
+ console.log("Escrow already funded on-chain \u2014 syncing off-chain status...");
2537
+ }
2538
+ } else {
2539
+ if (!options.json) {
2540
+ console.log("Depositing funds into escrow...");
2541
+ }
2542
+ escrowTxHash = await depositEscrow(wallet2, taskBefore.id, agentOwner, agentToken, priceWei);
2543
+ if (!options.json) {
2544
+ console.log(`Escrow TX: ${escrowTxHash}`);
2545
+ }
2466
2546
  }
2467
- const escrowTxHash = await depositEscrow(wallet2, taskBefore.id, agentOwner, agentToken, priceWei);
2468
2547
  if (!options.json) {
2469
- console.log(`Escrow TX: ${escrowTxHash}`);
2470
2548
  console.log("Marking task as accepted...");
2471
2549
  }
2472
2550
  const task = await acceptQuote(wallet2, options.task);
@@ -4087,7 +4165,9 @@ program.command("hire").description("Request work from an agent (they will quote
4087
4165
  program.command("feedback").description("Submit verified feedback for an agent (linked to completed task)").option("--agent <id>", "Agent ID (auto-resolved if --task provided)").option("--task <taskId>", "Task ID to link feedback to (verifies completion)").requiredOption("--score <0-100>", "Score from 0-100").option("--comment <text>", "Optional feedback comment").option("--json", "Output as JSON").action(feedback);
4088
4166
  program.command("agents").description("Browse registered agents").option("--skill <skill>", "Filter by skill").option("--sort <field>", "Sort by: reputation, price, hires", "reputation").option("--limit <n>", "Number of results", "20").option("--json", "Output as JSON").action(agents);
4089
4167
  program.command("reviews").description("View verified reviews for an agent").requiredOption("--agent <id>", "Agent ID").option("--json", "Output as JSON").action(reviews);
4090
- program.command("wallet").description("Show wallet info and balance").option("--json", "Output as JSON").action(wallet);
4168
+ var walletCmd = program.command("wallet").description("Wallet management");
4169
+ walletCmd.command("show", { isDefault: true }).description("Show wallet info and balance").option("--json", "Output as JSON").action(wallet);
4170
+ walletCmd.command("import").description("Import an existing private key").option("--key <privateKey>", "Private key (hex string, with or without 0x prefix)").option("--json", "Output as JSON").action(walletImport);
4091
4171
  program.command("earnings").description("View your earnings from being hired").option("--json", "Output as JSON").action(earnings);
4092
4172
  program.command("fees").description("Check and claim creator fees (treasury) + protocol fees (RM)").option("--claim", "Claim pending fees to your wallet").option("--json", "Output as JSON").action(fees);
4093
4173
  program.command("inbox").description("View pending work requests for your agent").option("--agent <id>", "Agent ID (auto-detected from wallet if omitted)").option("--json", "Output as JSON").action(inbox);