@btcemail/cli 0.1.0 → 0.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.
package/dist/index.js CHANGED
@@ -206,8 +206,7 @@ async function apiRequest(endpoint, options = {}) {
206
206
  const token = getToken();
207
207
  const baseUrl = getApiBaseUrl();
208
208
  const headers = {
209
- "Content-Type": "application/json",
210
- ...options.headers
209
+ "Content-Type": "application/json"
211
210
  };
212
211
  if (token) {
213
212
  headers.Authorization = `Bearer ${token}`;
@@ -285,14 +284,45 @@ async function sendEmail(options) {
285
284
  });
286
285
  }
287
286
  async function getL402Invoice(options) {
288
- return apiRequest("/l402/invoice", {
289
- method: "POST",
290
- body: JSON.stringify({
291
- sender_email: options.fromEmail,
292
- recipient_emails: options.toEmails,
293
- amount_sats: options.amountSats
294
- })
295
- });
287
+ const v1BaseUrl = getApiBaseUrl();
288
+ const rootApiUrl = v1BaseUrl.replace("/api/v1", "/api");
289
+ const token = getToken();
290
+ const headers = {
291
+ "Content-Type": "application/json"
292
+ };
293
+ if (token) {
294
+ headers.Authorization = `Bearer ${token}`;
295
+ }
296
+ try {
297
+ const response = await fetch(`${rootApiUrl}/l402/invoice`, {
298
+ method: "POST",
299
+ headers,
300
+ body: JSON.stringify({
301
+ sender_email: options.fromEmail,
302
+ recipient_emails: options.toEmails,
303
+ amount_sats: options.amountSats
304
+ })
305
+ });
306
+ const json = await response.json();
307
+ if (!response.ok || json.success === false) {
308
+ return {
309
+ ok: false,
310
+ error: json.error || {
311
+ code: "UNKNOWN_ERROR",
312
+ message: `Request failed with status ${response.status}`
313
+ }
314
+ };
315
+ }
316
+ return { ok: true, data: json.data };
317
+ } catch (error) {
318
+ return {
319
+ ok: false,
320
+ error: {
321
+ code: "NETWORK_ERROR",
322
+ message: error instanceof Error ? error.message : "Network request failed"
323
+ }
324
+ };
325
+ }
296
326
  }
297
327
 
298
328
  // src/commands/whoami.ts
@@ -556,31 +586,34 @@ async function sendCommand(options) {
556
586
  console.log(`${pc7.dim("To:")} ${toEmails.join(", ")}`);
557
587
  console.log(`${pc7.dim("Subject:")} ${options.subject}`);
558
588
  console.log();
559
- const invoiceResult = await getL402Invoice({
560
- fromEmail,
561
- toEmails
562
- });
563
- if (invoiceResult.ok && invoiceResult.data.amountSats > 0) {
564
- const invoice = invoiceResult.data;
565
- console.log(pc7.yellow(`Payment required: ${invoice.amountSats} sats`));
566
- console.log();
567
- console.log(pc7.dim("Lightning Invoice:"));
568
- console.log(pc7.cyan(invoice.invoice));
569
- console.log();
570
- console.log(pc7.dim("Pay this invoice with your Lightning wallet, then run:"));
571
- console.log(
572
- pc7.cyan(
573
- ` btcemail send --to "${options.to}" --subject "${options.subject}" --body "${options.body}" --payment-hash ${invoice.paymentHash}`
574
- )
575
- );
576
- console.log();
577
- return;
589
+ if (!options.paymentHash) {
590
+ const invoiceResult = await getL402Invoice({
591
+ fromEmail,
592
+ toEmails
593
+ });
594
+ if (invoiceResult.ok && invoiceResult.data.amountSats > 0) {
595
+ const invoice = invoiceResult.data;
596
+ console.log(pc7.yellow(`Payment required: ${invoice.amountSats} sats`));
597
+ console.log();
598
+ console.log(pc7.dim("Lightning Invoice:"));
599
+ console.log(pc7.cyan(invoice.invoice));
600
+ console.log();
601
+ console.log(pc7.dim("Pay this invoice with your Lightning wallet, then run:"));
602
+ console.log(
603
+ pc7.cyan(
604
+ ` btcemail send --to "${options.to}" --subject "${options.subject}" --body "${options.body}" --payment-hash ${invoice.paymentHash}`
605
+ )
606
+ );
607
+ console.log();
608
+ return;
609
+ }
578
610
  }
579
611
  const result = await sendEmail({
580
612
  to: toEmails,
581
613
  subject: options.subject,
582
614
  body: options.body,
583
- fromEmail
615
+ fromEmail,
616
+ paymentHash: options.paymentHash
584
617
  });
585
618
  if (!result.ok) {
586
619
  if (result.error.code === "PAYMENT_REQUIRED") {
@@ -768,7 +801,8 @@ program.command("send").description("Send an email").option("-t, --to <emails>",
768
801
  to: options.to,
769
802
  subject: options.subject,
770
803
  body: options.body,
771
- fromEmail: options.from
804
+ fromEmail: options.from,
805
+ paymentHash: options.paymentHash
772
806
  });
773
807
  });
774
808
  var inbound = program.command("inbound").description("Manage pending emails requiring payment");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/config.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/api.ts","../src/commands/list.ts","../src/commands/read.ts","../src/commands/credits.ts","../src/commands/send.ts","../src/commands/inbound.ts"],"sourcesContent":["/**\n * btc.email CLI\n *\n * Spam-free email powered by Bitcoin Lightning.\n *\n * Pattern from Claude Code:\n * - No args → Show help (TUI coming later)\n * - btcemail <command> → Execute and exit\n */\n\nimport { Command } from \"commander\"\nimport pc from \"picocolors\"\nimport {\n\tloginCommand,\n\tlogoutCommand,\n\twhoamiCommand,\n\tlistCommand,\n\treadCommand,\n\tcreditsBalanceCommand,\n\tsendCommand,\n\tinboundPendingCommand,\n\tinboundViewCommand,\n\tinboundPayCommand,\n} from \"./commands/index.js\"\n\nconst program = new Command()\n\nprogram\n\t.name(\"btcemail\")\n\t.description(\"btc.email CLI - Spam-free email powered by Bitcoin Lightning\")\n\t.version(\"0.1.0\")\n\n// Authentication commands\nprogram\n\t.command(\"login\")\n\t.description(\"Authenticate with btc.email (opens browser)\")\n\t.action(loginCommand)\n\nprogram\n\t.command(\"logout\")\n\t.description(\"Clear stored credentials\")\n\t.action(logoutCommand)\n\nprogram\n\t.command(\"whoami\")\n\t.description(\"Show current authenticated user\")\n\t.action(whoamiCommand)\n\n// Email commands\nprogram\n\t.command(\"list\")\n\t.description(\"List emails\")\n\t.option(\"-f, --folder <folder>\", \"Folder to list (inbox, sent, drafts)\", \"inbox\")\n\t.option(\"-l, --limit <number>\", \"Number of emails to show\", \"20\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (options) => {\n\t\tawait listCommand({\n\t\t\tfolder: options.folder,\n\t\t\tlimit: parseInt(options.limit, 10),\n\t\t\tjson: options.json,\n\t\t})\n\t})\n\nprogram\n\t.command(\"read <id>\")\n\t.description(\"Read an email by ID\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (id, options) => {\n\t\tawait readCommand(id, { json: options.json })\n\t})\n\nprogram\n\t.command(\"send\")\n\t.description(\"Send an email\")\n\t.option(\"-t, --to <emails>\", \"Recipient email(s), comma-separated\")\n\t.option(\"-s, --subject <subject>\", \"Email subject\")\n\t.option(\"-b, --body <body>\", \"Email body\")\n\t.option(\"-f, --from <email>\", \"From email (@btc.email address)\")\n\t.option(\"--payment-hash <hash>\", \"Payment hash/preimage for L402\")\n\t.action(async (options) => {\n\t\tawait sendCommand({\n\t\t\tto: options.to,\n\t\t\tsubject: options.subject,\n\t\t\tbody: options.body,\n\t\t\tfromEmail: options.from,\n\t\t})\n\t})\n\n// Inbound commands (pending emails requiring payment)\nconst inbound = program.command(\"inbound\").description(\"Manage pending emails requiring payment\")\n\ninbound\n\t.command(\"pending\")\n\t.description(\"List pending emails awaiting payment\")\n\t.option(\"-l, --limit <number>\", \"Number of emails to show\", \"20\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (options) => {\n\t\tawait inboundPendingCommand({\n\t\t\tlimit: parseInt(options.limit, 10),\n\t\t\tjson: options.json,\n\t\t})\n\t})\n\ninbound\n\t.command(\"view <id>\")\n\t.description(\"View pending email details and payment info\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (id, options) => {\n\t\tawait inboundViewCommand(id, { json: options.json })\n\t})\n\ninbound\n\t.command(\"pay <id>\")\n\t.description(\"Pay for a pending email\")\n\t.requiredOption(\"--payment-hash <hash>\", \"Payment preimage from Lightning invoice\")\n\t.action(async (id, options) => {\n\t\tawait inboundPayCommand(id, { paymentHash: options.paymentHash })\n\t})\n\n// Credits commands\nconst credits = program.command(\"credits\").description(\"Manage credits\")\n\ncredits\n\t.command(\"balance\")\n\t.description(\"Show credit balance\")\n\t.action(creditsBalanceCommand)\n\n// Default action (no command specified)\nprogram.action(() => {\n\tconsole.log()\n\tconsole.log(pc.bold(\"btc.email CLI\"))\n\tconsole.log(pc.dim(\"Spam-free email powered by Bitcoin Lightning\"))\n\tconsole.log()\n\tprogram.outputHelp()\n})\n\n// Parse and run\nprogram.parse()\n","/**\n * Login Command\n *\n * Implements polling-based browser authentication:\n * 1. Generate session_id\n * 2. Open browser to auth page\n * 3. Poll for tokens\n * 4. Store tokens in config\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport open from \"open\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { setAuth, getApiBaseUrl } from \"../config.js\"\n\nconst POLL_INTERVAL_MS = 2000\nconst POLL_TIMEOUT_MS = 300000 // 5 minutes\n\ntype CLISessionResponse =\n\t| { status: \"pending\" }\n\t| {\n\t\t\tstatus: \"complete\"\n\t\t\tdata: {\n\t\t\t\ttoken: string\n\t\t\t\texpiresAt: string\n\t\t\t\tuserId: string\n\t\t\t\temail: string\n\t\t\t}\n\t }\n\nexport async function loginCommand(): Promise<void> {\n\tconst sessionId = randomUUID()\n\tconst baseUrl = getApiBaseUrl().replace(\"/api/v1\", \"\")\n\tconst authUrl = `${baseUrl}/auth/cli?session_id=${sessionId}`\n\tconst pollUrl = `${baseUrl}/api/auth/cli-session?session_id=${sessionId}`\n\n\tconsole.log()\n\tconsole.log(pc.bold(\"btc.email CLI Login\"))\n\tconsole.log()\n\n\t// Create pending session first\n\ttry {\n\t\tconst createResponse = await fetch(\n\t\t\t`${baseUrl}/api/auth/cli-session`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ session_id: sessionId }),\n\t\t\t},\n\t\t)\n\n\t\tif (!createResponse.ok) {\n\t\t\tconsole.error(pc.red(\"Failed to initialize login session\"))\n\t\t\tprocess.exit(1)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(pc.red(\"Failed to connect to btc.email server\"))\n\t\tconsole.error(\n\t\t\tpc.dim(error instanceof Error ? error.message : \"Unknown error\"),\n\t\t)\n\t\tprocess.exit(1)\n\t}\n\n\t// Open browser\n\tconsole.log(pc.dim(\"Opening browser for authentication...\"))\n\tconsole.log()\n\tconsole.log(pc.dim(\"If the browser doesn't open, visit:\"))\n\tconsole.log(pc.cyan(authUrl))\n\tconsole.log()\n\n\ttry {\n\t\tawait open(authUrl)\n\t} catch {\n\t\t// Browser open failed, user can use the URL\n\t}\n\n\t// Poll for tokens\n\tconst spinner = ora(\"Waiting for authentication...\").start()\n\tconst startTime = Date.now()\n\n\twhile (Date.now() - startTime < POLL_TIMEOUT_MS) {\n\t\ttry {\n\t\t\tconst response = await fetch(pollUrl)\n\n\t\t\tif (response.status === 202) {\n\t\t\t\t// Still pending, continue polling\n\t\t\t\tawait sleep(POLL_INTERVAL_MS)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (response.status === 410) {\n\t\t\t\tspinner.fail(\"Session expired. Please try again.\")\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data: CLISessionResponse = await response.json()\n\n\t\t\t\tif (data.status === \"complete\") {\n\t\t\t\t\t// Store tokens\n\t\t\t\t\tsetAuth({\n\t\t\t\t\t\ttoken: data.data.token,\n\t\t\t\t\t\texpiresAt: data.data.expiresAt,\n\t\t\t\t\t\tuserId: data.data.userId,\n\t\t\t\t\t\temail: data.data.email,\n\t\t\t\t\t})\n\n\t\t\t\t\tspinner.succeed(pc.green(\"Successfully logged in!\"))\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(` ${pc.dim(\"Email:\")} ${data.data.email}`)\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(pc.dim(\"You can now use btcemail commands.\"))\n\t\t\t\t\tconsole.log(pc.dim(\"Run `btcemail --help` to see available commands.\"))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait sleep(POLL_INTERVAL_MS)\n\t\t} catch (error) {\n\t\t\t// Network error, continue polling\n\t\t\tawait sleep(POLL_INTERVAL_MS)\n\t\t}\n\t}\n\n\tspinner.fail(\"Authentication timed out. Please try again.\")\n\tprocess.exit(1)\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/**\n * CLI Configuration Management\n *\n * Stores auth tokens and user preferences in ~/.btcemail/config.json\n */\n\nimport Conf from \"conf\"\n\nexport type CLIConfig = {\n\tauth?: {\n\t\ttoken: string\n\t\texpiresAt: string\n\t\tuserId: string\n\t\temail: string\n\t}\n\tapi?: {\n\t\tbaseUrl: string\n\t}\n\tpreferences?: {\n\t\tuseCredits: boolean\n\t\tdefaultEditor: string\n\t}\n}\n\nconst config = new Conf<CLIConfig>({\n\tprojectName: \"btcemail\",\n\tschema: {\n\t\tauth: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\ttoken: { type: \"string\" },\n\t\t\t\texpiresAt: { type: \"string\" },\n\t\t\t\tuserId: { type: \"string\" },\n\t\t\t\temail: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tapi: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tbaseUrl: { type: \"string\" },\n\t\t\t},\n\t\t\tdefault: {\n\t\t\t\tbaseUrl: \"https://btc.email/api/v1\",\n\t\t\t},\n\t\t},\n\t\tpreferences: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tuseCredits: { type: \"boolean\" },\n\t\t\t\tdefaultEditor: { type: \"string\" },\n\t\t\t},\n\t\t\tdefault: {\n\t\t\t\tuseCredits: true,\n\t\t\t\tdefaultEditor: \"vim\",\n\t\t\t},\n\t\t},\n\t},\n})\n\nexport function getConfig(): CLIConfig {\n\treturn config.store\n}\n\nexport function getAuth(): CLIConfig[\"auth\"] | undefined {\n\treturn config.get(\"auth\")\n}\n\nexport function setAuth(auth: CLIConfig[\"auth\"]): void {\n\tconfig.set(\"auth\", auth)\n}\n\nexport function clearAuth(): void {\n\tconfig.delete(\"auth\")\n}\n\nexport function getApiBaseUrl(): string {\n\treturn (\n\t\tprocess.env.BTCEMAIL_API_URL ||\n\t\tconfig.get(\"api.baseUrl\") ||\n\t\t\"https://btc.email/api/v1\"\n\t)\n}\n\nexport function isAuthenticated(): boolean {\n\tconst auth = getAuth()\n\tif (!auth?.token || !auth?.expiresAt) {\n\t\treturn false\n\t}\n\n\t// Check if token is expired\n\tconst expiresAt = new Date(auth.expiresAt)\n\treturn expiresAt > new Date()\n}\n\n/**\n * Check if token is expiring soon (within 5 minutes)\n */\nexport function isTokenExpiringSoon(): boolean {\n\tconst auth = getAuth()\n\tif (!auth?.token || !auth?.expiresAt) {\n\t\treturn false\n\t}\n\n\tconst expiresAt = new Date(auth.expiresAt)\n\tconst fiveMinutesFromNow = new Date(Date.now() + 5 * 60 * 1000)\n\treturn expiresAt <= fiveMinutesFromNow && expiresAt > new Date()\n}\n\n/**\n * Get time until token expires in human-readable format\n */\nexport function getTokenExpiryInfo(): { expired: boolean; expiresIn?: string } {\n\tconst auth = getAuth()\n\tif (!auth?.token || !auth?.expiresAt) {\n\t\treturn { expired: true }\n\t}\n\n\tconst expiresAt = new Date(auth.expiresAt)\n\tconst now = new Date()\n\n\tif (expiresAt <= now) {\n\t\treturn { expired: true }\n\t}\n\n\tconst diffMs = expiresAt.getTime() - now.getTime()\n\tconst diffMins = Math.floor(diffMs / 60000)\n\tconst diffHours = Math.floor(diffMins / 60)\n\n\tif (diffHours > 0) {\n\t\treturn { expired: false, expiresIn: `${diffHours}h ${diffMins % 60}m` }\n\t}\n\treturn { expired: false, expiresIn: `${diffMins}m` }\n}\n\nexport function getToken(): string | null {\n\tconst auth = getAuth()\n\tif (!auth?.token) return null\n\n\t// Check if token is expired\n\tconst expiresAt = new Date(auth.expiresAt)\n\tif (expiresAt <= new Date()) {\n\t\tclearAuth()\n\t\treturn null\n\t}\n\n\treturn auth.token\n}\n\nexport { config }\n","/**\n * Logout Command\n *\n * Clears stored authentication tokens.\n */\n\nimport pc from \"picocolors\"\nimport { clearAuth, isAuthenticated } from \"../config.js\"\n\nexport async function logoutCommand(): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"You are not logged in.\"))\n\t\treturn\n\t}\n\n\tclearAuth()\n\tconsole.log(pc.green(\"Successfully logged out.\"))\n}\n","/**\n * Whoami Command\n *\n * Shows current authenticated user info.\n */\n\nimport pc from \"picocolors\"\nimport {\n\tgetAuth,\n\tgetTokenExpiryInfo,\n\tisAuthenticated,\n\tisTokenExpiringSoon,\n} from \"../config.js\"\nimport { getWhoami } from \"../api.js\"\n\nexport async function whoamiCommand(): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst auth = getAuth()\n\tif (!auth) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Try to get fresh info from API\n\tconst result = await getWhoami()\n\n\tif (result.ok) {\n\t\tconsole.log()\n\t\tconsole.log(pc.bold(\"Current User\"))\n\t\tconsole.log()\n\t\tconsole.log(` ${pc.dim(\"Email:\")} ${result.data.email}`)\n\t\tif (result.data.username) {\n\t\t\tconsole.log(` ${pc.dim(\"Username:\")} ${result.data.username}`)\n\t\t}\n\t\tconsole.log(` ${pc.dim(\"User ID:\")} ${result.data.id}`)\n\n\t\t// Show token expiry info\n\t\tconst expiryInfo = getTokenExpiryInfo()\n\t\tif (expiryInfo.expiresIn) {\n\t\t\tconst expiryColor = isTokenExpiringSoon() ? pc.yellow : pc.dim\n\t\t\tconsole.log(` ${pc.dim(\"Session:\")} ${expiryColor(`expires in ${expiryInfo.expiresIn}`)}`)\n\t\t}\n\t\tconsole.log()\n\n\t\tif (isTokenExpiringSoon()) {\n\t\t\tconsole.log(pc.yellow(\"Session expiring soon. Run `btcemail login` to refresh.\"))\n\t\t\tconsole.log()\n\t\t}\n\t} else {\n\t\t// Fall back to cached info\n\t\tconsole.log()\n\t\tconsole.log(pc.bold(\"Current User (cached)\"))\n\t\tconsole.log()\n\t\tconsole.log(` ${pc.dim(\"Email:\")} ${auth.email}`)\n\t\tconsole.log(` ${pc.dim(\"User ID:\")} ${auth.userId}`)\n\t\tconsole.log()\n\n\t\tif (result.error.code === \"UNAUTHENTICATED\" || result.error.code === \"UNAUTHORIZED\") {\n\t\t\tconsole.log(pc.yellow(\"Session expired. Run `btcemail login` to re-authenticate.\"))\n\t\t}\n\t}\n}\n","/**\n * API Client for btc.email CLI\n *\n * Handles all HTTP requests to the btc.email API.\n * v1 API returns: { success: true, data: {...}, meta: {...} }\n */\n\nimport { getApiBaseUrl, getToken } from \"./config.js\"\n\nexport type ApiResponse<T> =\n\t| { ok: true; data: T }\n\t| { ok: false; error: { code: string; message: string; details?: unknown } }\n\nexport type PaginatedResponse<T> = {\n\tdata: T[]\n\tpagination: {\n\t\ttotal: number\n\t\tlimit: number\n\t\toffset: number\n\t\thasMore: boolean\n\t}\n}\n\n/**\n * v1 API response format\n */\ntype V1ApiResponse<T> = {\n\tsuccess: boolean\n\tdata?: T\n\terror?: { code: string; message: string; details?: unknown }\n\tmeta?: { requestId: string; timestamp: string }\n\tpagination?: {\n\t\ttotal: number\n\t\tlimit: number\n\t\toffset: number\n\t\thasMore: boolean\n\t}\n}\n\n/**\n * Make an authenticated API request\n */\nexport async function apiRequest<T>(\n\tendpoint: string,\n\toptions: RequestInit = {},\n): Promise<ApiResponse<T>> {\n\tconst token = getToken()\n\tconst baseUrl = getApiBaseUrl()\n\n\tconst headers: HeadersInit = {\n\t\t\"Content-Type\": \"application/json\",\n\t\t...options.headers,\n\t}\n\n\tif (token) {\n\t\theaders.Authorization = `Bearer ${token}`\n\t}\n\n\ttry {\n\t\tconst response = await fetch(`${baseUrl}${endpoint}`, {\n\t\t\t...options,\n\t\t\theaders,\n\t\t})\n\n\t\tconst json = (await response.json()) as V1ApiResponse<T>\n\n\t\t// Handle v1 API format: { success: boolean, data?: T, error?: {...} }\n\t\tif (!response.ok || json.success === false) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: json.error || {\n\t\t\t\t\tcode: \"UNKNOWN_ERROR\",\n\t\t\t\t\tmessage: `Request failed with status ${response.status}`,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\t// For paginated responses, include pagination in the result\n\t\tif (json.pagination) {\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tdata: { data: json.data, pagination: json.pagination } as T,\n\t\t\t}\n\t\t}\n\n\t\t// Extract data from v1 response format\n\t\treturn { ok: true, data: json.data as T }\n\t} catch (error) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"NETWORK_ERROR\",\n\t\t\t\tmessage:\n\t\t\t\t\terror instanceof Error ? error.message : \"Network request failed\",\n\t\t\t},\n\t\t}\n\t}\n}\n\n/**\n * Make an unauthenticated API request (for login, etc.)\n */\nexport async function publicRequest<T>(\n\tendpoint: string,\n\toptions: RequestInit = {},\n): Promise<ApiResponse<T>> {\n\tconst baseUrl = getApiBaseUrl()\n\n\ttry {\n\t\tconst response = await fetch(`${baseUrl}${endpoint}`, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t})\n\n\t\tconst json = (await response.json()) as V1ApiResponse<T>\n\n\t\tif (!response.ok || json.success === false) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: json.error || {\n\t\t\t\t\tcode: \"UNKNOWN_ERROR\",\n\t\t\t\t\tmessage: `Request failed with status ${response.status}`,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn { ok: true, data: json.data as T }\n\t} catch (error) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"NETWORK_ERROR\",\n\t\t\t\tmessage:\n\t\t\t\t\terror instanceof Error ? error.message : \"Network request failed\",\n\t\t\t},\n\t\t}\n\t}\n}\n\n// API endpoint helpers\n\nexport async function getEmails(options: {\n\tfolder?: string\n\tlimit?: number\n\toffset?: number\n\tsearch?: string\n}) {\n\tconst params = new URLSearchParams()\n\tif (options.folder) params.set(\"folder\", options.folder)\n\tif (options.limit) params.set(\"limit\", String(options.limit))\n\tif (options.offset) params.set(\"offset\", String(options.offset))\n\tif (options.search) params.set(\"search\", options.search)\n\n\treturn apiRequest<PaginatedResponse<Email>>(`/email?${params}`)\n}\n\nexport async function getEmail(id: string) {\n\treturn apiRequest<Email>(`/email/${id}`)\n}\n\nexport async function getCreditsBalance() {\n\treturn apiRequest<CreditBalance>(\"/credits/balance\")\n}\n\nexport type CreditBalance = {\n\tbalanceSats: number\n\tlifetimePurchasedSats: number\n\tlifetimeSpentSats: number\n\tlastPurchaseAt: string | null\n}\n\nexport async function getWhoami() {\n\treturn apiRequest<{ id: string; email: string; username?: string }>(\n\t\t\"/auth/whoami\",\n\t)\n}\n\n// Pending/Inbound email functions\n\nexport async function getPendingEmails(options: { limit?: number; offset?: number } = {}) {\n\tconst params = new URLSearchParams()\n\tif (options.limit) params.set(\"limit\", String(options.limit))\n\tif (options.offset) params.set(\"offset\", String(options.offset))\n\n\treturn apiRequest<PaginatedResponse<PendingEmail>>(`/inbound/pending?${params}`)\n}\n\nexport async function getPendingEmail(id: string) {\n\treturn apiRequest<PendingEmailDetail>(`/inbound/${id}`)\n}\n\nexport async function payForEmail(id: string, paymentHash: string) {\n\treturn apiRequest<{ emailId: string; status: string }>(`/inbound/${id}/pay`, {\n\t\tmethod: \"POST\",\n\t\tbody: JSON.stringify({ paymentHash }),\n\t})\n}\n\n// Send email functions\n\nexport async function sendEmail(options: {\n\tto: string[]\n\tsubject: string\n\tbody: string\n\tbodyText?: string\n\tfromEmail: string\n\tpaymentHash?: string\n}) {\n\treturn apiRequest<{ emailId: string; status: string; messageId?: string }>(\"/email/send\", {\n\t\tmethod: \"POST\",\n\t\tbody: JSON.stringify(options),\n\t})\n}\n\nexport async function getL402Invoice(options: {\n\tfromEmail: string\n\ttoEmails: string[]\n\tamountSats?: number\n}) {\n\treturn apiRequest<L402Invoice>(\"/l402/invoice\", {\n\t\tmethod: \"POST\",\n\t\tbody: JSON.stringify({\n\t\t\tsender_email: options.fromEmail,\n\t\t\trecipient_emails: options.toEmails,\n\t\t\tamount_sats: options.amountSats,\n\t\t}),\n\t})\n}\n\n// Types\n\nexport type Email = {\n\tid: string\n\tsubject: string\n\tfrom: { email: string; name?: string }\n\tto: { email: string; name?: string }[]\n\tsnippet: string\n\tbody?: string\n\tbodyText?: string\n\tdate: string\n\tunread: boolean\n\tlabels: string[]\n}\n\nexport type PendingEmail = {\n\tid: string\n\tsubject: string\n\tfrom: { email: string; name?: string }\n\tamountSats: number\n\tcreatedAt: string\n}\n\nexport type PendingEmailDetail = {\n\tid: string\n\tsubject: string\n\tfrom: { email: string; name?: string }\n\tbody: string\n\tbodyText: string\n\tamountSats: number\n\tcreatedAt: string\n\tpaymentHash: string | null\n}\n\nexport type L402Invoice = {\n\tinvoice: string\n\tpaymentHash: string\n\tamountSats: number\n\texpiresAt: string\n}\n","/**\n * List Command\n *\n * Lists emails with pagination and filtering.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getEmails, type Email } from \"../api.js\"\n\nexport type ListOptions = {\n\tfolder?: string\n\tlimit?: number\n\tjson?: boolean\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getEmails({\n\t\tfolder: options.folder || \"inbox\",\n\t\tlimit: options.limit || 20,\n\t})\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify({ emails, pagination }, null, 2))\n\t\treturn\n\t}\n\n\t// Table output\n\tconsole.log()\n\tconsole.log(\n\t\tpc.bold(`${options.folder || \"Inbox\"} (${pagination.total} emails)`),\n\t)\n\tconsole.log()\n\n\tif (emails.length === 0) {\n\t\tconsole.log(pc.dim(\" No emails found.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Header\n\tconsole.log(\n\t\t` ${pc.dim(\"ID\".padEnd(12))} ${pc.dim(\"From\".padEnd(25))} ${pc.dim(\"Subject\".padEnd(40))} ${pc.dim(\"Date\")}`,\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(90)))\n\n\t// Rows\n\tfor (const email of emails) {\n\t\tconst unreadMarker = email.unread ? pc.cyan(\"*\") : \" \"\n\t\tconst id = email.id.slice(0, 10).padEnd(12)\n\t\tconst from = truncate(email.from.name || email.from.email, 23).padEnd(25)\n\t\tconst subject = truncate(email.subject, 38).padEnd(40)\n\t\tconst date = formatDate(email.date)\n\n\t\tconsole.log(`${unreadMarker} ${id} ${from} ${subject} ${pc.dim(date)}`)\n\t}\n\n\tconsole.log()\n\n\tif (pagination.hasMore) {\n\t\tconsole.log(\n\t\t\tpc.dim(\n\t\t\t\t` Showing ${emails.length} of ${pagination.total}. Use --limit to see more.`,\n\t\t\t),\n\t\t)\n\t\tconsole.log()\n\t}\n}\n\nfunction truncate(str: string, maxLength: number): string {\n\tif (str.length <= maxLength) return str\n\treturn str.slice(0, maxLength - 1) + \"…\"\n}\n\nfunction formatDate(dateString: string): string {\n\tconst date = new Date(dateString)\n\tconst now = new Date()\n\tconst diffMs = now.getTime() - date.getTime()\n\tconst diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))\n\n\tif (diffDays === 0) {\n\t\treturn date.toLocaleTimeString(\"en-US\", {\n\t\t\thour: \"numeric\",\n\t\t\tminute: \"2-digit\",\n\t\t})\n\t}\n\n\tif (diffDays < 7) {\n\t\treturn date.toLocaleDateString(\"en-US\", { weekday: \"short\" })\n\t}\n\n\treturn date.toLocaleDateString(\"en-US\", {\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t})\n}\n","/**\n * Read Command\n *\n * Display a single email by ID.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getEmail, type Email } from \"../api.js\"\n\nexport type ReadOptions = {\n\tjson?: boolean\n}\n\nexport async function readCommand(id: string, options: ReadOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getEmail(id)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"NOT_FOUND\") {\n\t\t\tconsole.error(pc.red(`Email not found: ${id}`))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconst email = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(email, null, 2))\n\t\treturn\n\t}\n\n\t// Formatted output\n\tconsole.log()\n\tconsole.log(pc.bold(email.subject || \"(No subject)\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"From:\")} ${formatAddress(email.from)}`)\n\tconsole.log(`${pc.dim(\"To:\")} ${email.to.map(formatAddress).join(\", \")}`)\n\tconsole.log(`${pc.dim(\"Date:\")} ${formatFullDate(email.date)}`)\n\tconsole.log(`${pc.dim(\"ID:\")} ${email.id}`)\n\n\tif (email.labels.length > 0) {\n\t\tconsole.log(`${pc.dim(\"Labels:\")} ${email.labels.join(\", \")}`)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.dim(\"-\".repeat(60)))\n\tconsole.log()\n\n\t// Show full body if available, otherwise fall back to snippet\n\tconst content = email.bodyText || email.body || email.snippet\n\tif (content) {\n\t\t// Strip HTML tags for plain text display if showing HTML body\n\t\tconst displayContent = email.bodyText || stripHtml(email.body || email.snippet)\n\t\tconsole.log(displayContent)\n\t} else {\n\t\tconsole.log(pc.dim(\"(No content)\"))\n\t}\n\tconsole.log()\n}\n\nfunction stripHtml(html: string): string {\n\t// Basic HTML stripping for terminal display\n\treturn html\n\t\t.replace(/<br\\s*\\/?>/gi, \"\\n\")\n\t\t.replace(/<\\/p>/gi, \"\\n\\n\")\n\t\t.replace(/<\\/div>/gi, \"\\n\")\n\t\t.replace(/<[^>]*>/g, \"\")\n\t\t.replace(/&nbsp;/g, \" \")\n\t\t.replace(/&lt;/g, \"<\")\n\t\t.replace(/&gt;/g, \">\")\n\t\t.replace(/&amp;/g, \"&\")\n\t\t.replace(/&quot;/g, '\"')\n\t\t.trim()\n}\n\nfunction formatAddress(addr: { email: string; name?: string }): string {\n\tif (addr.name) {\n\t\treturn `${addr.name} <${addr.email}>`\n\t}\n\treturn addr.email\n}\n\nfunction formatFullDate(dateString: string): string {\n\tconst date = new Date(dateString)\n\treturn date.toLocaleString(\"en-US\", {\n\t\tweekday: \"short\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\thour: \"numeric\",\n\t\tminute: \"2-digit\",\n\t})\n}\n","/**\n * Credits Command\n *\n * Shows credit balance and transaction history.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getCreditsBalance } from \"../api.js\"\n\nexport async function creditsBalanceCommand(): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getCreditsBalance()\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconst { balanceSats } = result.data\n\n\tconsole.log()\n\tconsole.log(pc.bold(\"Credit Balance\"))\n\tconsole.log()\n\tconsole.log(` ${pc.green(formatSats(balanceSats))} sats`)\n\tconsole.log()\n\n\tif (balanceSats === 0) {\n\t\tconsole.log(pc.dim(\" No credits available.\"))\n\t\tconsole.log(pc.dim(\" Purchase credits at https://btc.email/payments\"))\n\t\tconsole.log()\n\t}\n}\n\nfunction formatSats(sats: number): string {\n\treturn sats.toLocaleString()\n}\n","/**\n * Send Command\n *\n * Compose and send an email with L402 payment flow.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated, getAuth } from \"../config.js\"\nimport { sendEmail, getL402Invoice, getWhoami } from \"../api.js\"\n\nexport type SendOptions = {\n\tto?: string\n\tsubject?: string\n\tbody?: string\n\tfromEmail?: string\n}\n\nexport async function sendCommand(options: SendOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Get user's email address\n\tlet fromEmail = options.fromEmail\n\tif (!fromEmail) {\n\t\tconst whoamiResult = await getWhoami()\n\t\tif (whoamiResult.ok && whoamiResult.data.username) {\n\t\t\tfromEmail = `${whoamiResult.data.username}@btc.email`\n\t\t} else {\n\t\t\tconst auth = getAuth()\n\t\t\tif (auth?.email?.endsWith(\"@btc.email\")) {\n\t\t\t\tfromEmail = auth.email\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!fromEmail || !fromEmail.endsWith(\"@btc.email\")) {\n\t\tconsole.error(pc.red(\"No @btc.email address found.\"))\n\t\tconsole.log(pc.dim(\"Register a username at https://btc.email\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Validate required fields\n\tif (!options.to) {\n\t\tconsole.error(pc.red(\"Recipient is required. Use --to <email>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.subject) {\n\t\tconsole.error(pc.red(\"Subject is required. Use --subject <text>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.body) {\n\t\tconsole.error(pc.red(\"Body is required. Use --body <text>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst toEmails = options.to.split(\",\").map((e) => e.trim())\n\n\tconsole.log()\n\tconsole.log(pc.bold(\"Sending Email\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"From:\")} ${fromEmail}`)\n\tconsole.log(`${pc.dim(\"To:\")} ${toEmails.join(\", \")}`)\n\tconsole.log(`${pc.dim(\"Subject:\")} ${options.subject}`)\n\tconsole.log()\n\n\t// Get L402 invoice to check if payment is required\n\tconst invoiceResult = await getL402Invoice({\n\t\tfromEmail,\n\t\ttoEmails,\n\t})\n\n\tif (invoiceResult.ok && invoiceResult.data.amountSats > 0) {\n\t\t// Payment required\n\t\tconst invoice = invoiceResult.data\n\t\tconsole.log(pc.yellow(`Payment required: ${invoice.amountSats} sats`))\n\t\tconsole.log()\n\t\tconsole.log(pc.dim(\"Lightning Invoice:\"))\n\t\tconsole.log(pc.cyan(invoice.invoice))\n\t\tconsole.log()\n\t\tconsole.log(pc.dim(\"Pay this invoice with your Lightning wallet, then run:\"))\n\t\tconsole.log(\n\t\t\tpc.cyan(\n\t\t\t\t` btcemail send --to \"${options.to}\" --subject \"${options.subject}\" --body \"${options.body}\" --payment-hash ${invoice.paymentHash}`\n\t\t\t)\n\t\t)\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// No payment required or payment hash provided - send email\n\tconst result = await sendEmail({\n\t\tto: toEmails,\n\t\tsubject: options.subject,\n\t\tbody: options.body,\n\t\tfromEmail,\n\t})\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"PAYMENT_REQUIRED\") {\n\t\t\tconsole.error(pc.yellow(\"Payment required to send this email.\"))\n\t\t\tconsole.log(pc.dim(\"Use the invoice above to pay, then include --payment-hash\"))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log(pc.green(\"Email sent successfully!\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"Email ID:\")} ${result.data.emailId}`)\n\tif (result.data.messageId) {\n\t\tconsole.log(`${pc.dim(\"Message ID:\")} ${result.data.messageId}`)\n\t}\n\tconsole.log()\n}\n\nexport type SendWithPaymentOptions = SendOptions & {\n\tpaymentHash?: string\n}\n\nexport async function sendWithPaymentCommand(options: SendWithPaymentOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Get user's email address\n\tlet fromEmail = options.fromEmail\n\tif (!fromEmail) {\n\t\tconst whoamiResult = await getWhoami()\n\t\tif (whoamiResult.ok && whoamiResult.data.username) {\n\t\t\tfromEmail = `${whoamiResult.data.username}@btc.email`\n\t\t}\n\t}\n\n\tif (!fromEmail || !fromEmail.endsWith(\"@btc.email\")) {\n\t\tconsole.error(pc.red(\"No @btc.email address found.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.to || !options.subject || !options.body) {\n\t\tconsole.error(pc.red(\"Missing required fields: --to, --subject, --body\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst toEmails = options.to.split(\",\").map((e) => e.trim())\n\n\tconst result = await sendEmail({\n\t\tto: toEmails,\n\t\tsubject: options.subject,\n\t\tbody: options.body,\n\t\tfromEmail,\n\t\tpaymentHash: options.paymentHash,\n\t})\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.green(\"Email sent successfully!\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"Email ID:\")} ${result.data.emailId}`)\n\tconsole.log()\n}\n","/**\n * Inbound Commands\n *\n * View and pay for pending emails that require payment.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport {\n\tgetPendingEmails,\n\tgetPendingEmail,\n\tpayForEmail,\n\ttype PendingEmail,\n} from \"../api.js\"\n\nexport type InboundListOptions = {\n\tlimit?: number\n\tjson?: boolean\n}\n\nexport async function inboundPendingCommand(options: InboundListOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getPendingEmails({\n\t\tlimit: options.limit || 20,\n\t})\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify({ emails, pagination }, null, 2))\n\t\treturn\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.bold(`Pending Emails (${pagination.total} awaiting payment)`))\n\tconsole.log()\n\n\tif (emails.length === 0) {\n\t\tconsole.log(pc.dim(\" No pending emails.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Header\n\tconsole.log(\n\t\t` ${pc.dim(\"ID\".padEnd(12))} ${pc.dim(\"From\".padEnd(30))} ${pc.dim(\"Subject\".padEnd(30))} ${pc.dim(\"Sats\")}`\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(85)))\n\n\t// Rows\n\tfor (const email of emails) {\n\t\tconst id = email.id.slice(0, 10).padEnd(12)\n\t\tconst from = truncate(email.from.name || email.from.email, 28).padEnd(30)\n\t\tconst subject = truncate(email.subject, 28).padEnd(30)\n\t\tconst sats = pc.yellow(String(email.amountSats))\n\n\t\tconsole.log(` ${id} ${from} ${subject} ${sats}`)\n\t}\n\n\tconsole.log()\n\n\tif (pagination.hasMore) {\n\t\tconsole.log(\n\t\t\tpc.dim(` Showing ${emails.length} of ${pagination.total}. Use --limit to see more.`)\n\t\t)\n\t\tconsole.log()\n\t}\n\n\tconsole.log(pc.dim(\" Use `btcemail inbound view <id>` to see details and payment invoice.\"))\n\tconsole.log()\n}\n\nexport type InboundViewOptions = {\n\tjson?: boolean\n}\n\nexport async function inboundViewCommand(id: string, options: InboundViewOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getPendingEmail(id)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"NOT_FOUND\") {\n\t\t\tconsole.error(pc.red(`Pending email not found: ${id}`))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconst email = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(email, null, 2))\n\t\treturn\n\t}\n\n\t// Formatted output\n\tconsole.log()\n\tconsole.log(pc.bold(email.subject || \"(No subject)\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"From:\")} ${formatAddress(email.from)}`)\n\tconsole.log(`${pc.dim(\"Date:\")} ${formatFullDate(email.createdAt)}`)\n\tconsole.log(`${pc.dim(\"ID:\")} ${email.id}`)\n\tconsole.log()\n\tconsole.log(pc.yellow(`Payment Required: ${email.amountSats} sats`))\n\tconsole.log()\n\n\tif (email.paymentHash) {\n\t\tconsole.log(pc.dim(\"To receive this email, pay the invoice and run:\"))\n\t\tconsole.log(pc.cyan(` btcemail inbound pay ${email.id} --payment-hash <preimage>`))\n\t} else {\n\t\tconsole.log(pc.dim(\"Payment information not available.\"))\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.dim(\"-\".repeat(60)))\n\tconsole.log()\n\tconsole.log(pc.dim(\"Preview (full content available after payment):\"))\n\tconsole.log()\n\tconsole.log(truncate(email.bodyText || email.body, 200))\n\tconsole.log()\n}\n\nexport type InboundPayOptions = {\n\tpaymentHash: string\n}\n\nexport async function inboundPayCommand(id: string, options: InboundPayOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.paymentHash) {\n\t\tconsole.error(pc.red(\"Payment hash is required. Use --payment-hash <preimage>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.dim(\"Verifying payment...\"))\n\n\tconst result = await payForEmail(id, options.paymentHash)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"PAYMENT_INVALID\") {\n\t\t\tconsole.error(pc.red(\"Payment verification failed.\"))\n\t\t\tconsole.log(pc.dim(\"Make sure you paid the correct invoice and provided the preimage.\"))\n\t\t} else if (result.error.code === \"NOT_FOUND\") {\n\t\t\tconsole.error(pc.red(`Pending email not found or already delivered: ${id}`))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.green(\"Payment verified! Email delivered.\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"Email ID:\")} ${result.data.emailId}`)\n\tconsole.log(`${pc.dim(\"Status:\")} ${result.data.status}`)\n\tconsole.log()\n\tconsole.log(pc.dim(\"Run `btcemail read \" + result.data.emailId + \"` to read the email.\"))\n\tconsole.log()\n}\n\nfunction truncate(str: string, maxLength: number): string {\n\tif (str.length <= maxLength) return str\n\treturn str.slice(0, maxLength - 1) + \"…\"\n}\n\nfunction formatAddress(addr: { email: string; name?: string }): string {\n\tif (addr.name) {\n\t\treturn `${addr.name} <${addr.email}>`\n\t}\n\treturn addr.email\n}\n\nfunction formatFullDate(dateString: string): string {\n\tconst date = new Date(dateString)\n\treturn date.toLocaleString(\"en-US\", {\n\t\tweekday: \"short\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\thour: \"numeric\",\n\t\tminute: \"2-digit\",\n\t})\n}\n"],"mappings":"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","names":["pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","truncate","formatAddress","formatFullDate","pc"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/login.ts","../src/config.ts","../src/commands/logout.ts","../src/commands/whoami.ts","../src/api.ts","../src/commands/list.ts","../src/commands/read.ts","../src/commands/credits.ts","../src/commands/send.ts","../src/commands/inbound.ts"],"sourcesContent":["/**\n * btc.email CLI\n *\n * Spam-free email powered by Bitcoin Lightning.\n *\n * Pattern from Claude Code:\n * - No args → Show help (TUI coming later)\n * - btcemail <command> → Execute and exit\n */\n\nimport { Command } from \"commander\"\nimport pc from \"picocolors\"\nimport {\n\tloginCommand,\n\tlogoutCommand,\n\twhoamiCommand,\n\tlistCommand,\n\treadCommand,\n\tcreditsBalanceCommand,\n\tsendCommand,\n\tinboundPendingCommand,\n\tinboundViewCommand,\n\tinboundPayCommand,\n} from \"./commands/index.js\"\n\nconst program = new Command()\n\nprogram\n\t.name(\"btcemail\")\n\t.description(\"btc.email CLI - Spam-free email powered by Bitcoin Lightning\")\n\t.version(\"0.1.0\")\n\n// Authentication commands\nprogram\n\t.command(\"login\")\n\t.description(\"Authenticate with btc.email (opens browser)\")\n\t.action(loginCommand)\n\nprogram\n\t.command(\"logout\")\n\t.description(\"Clear stored credentials\")\n\t.action(logoutCommand)\n\nprogram\n\t.command(\"whoami\")\n\t.description(\"Show current authenticated user\")\n\t.action(whoamiCommand)\n\n// Email commands\nprogram\n\t.command(\"list\")\n\t.description(\"List emails\")\n\t.option(\"-f, --folder <folder>\", \"Folder to list (inbox, sent, drafts)\", \"inbox\")\n\t.option(\"-l, --limit <number>\", \"Number of emails to show\", \"20\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (options) => {\n\t\tawait listCommand({\n\t\t\tfolder: options.folder,\n\t\t\tlimit: parseInt(options.limit, 10),\n\t\t\tjson: options.json,\n\t\t})\n\t})\n\nprogram\n\t.command(\"read <id>\")\n\t.description(\"Read an email by ID\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (id, options) => {\n\t\tawait readCommand(id, { json: options.json })\n\t})\n\nprogram\n\t.command(\"send\")\n\t.description(\"Send an email\")\n\t.option(\"-t, --to <emails>\", \"Recipient email(s), comma-separated\")\n\t.option(\"-s, --subject <subject>\", \"Email subject\")\n\t.option(\"-b, --body <body>\", \"Email body\")\n\t.option(\"-f, --from <email>\", \"From email (@btc.email address)\")\n\t.option(\"--payment-hash <hash>\", \"Payment hash/preimage for L402\")\n\t.action(async (options) => {\n\t\tawait sendCommand({\n\t\t\tto: options.to,\n\t\t\tsubject: options.subject,\n\t\t\tbody: options.body,\n\t\t\tfromEmail: options.from,\n\t\t\tpaymentHash: options.paymentHash,\n\t\t})\n\t})\n\n// Inbound commands (pending emails requiring payment)\nconst inbound = program.command(\"inbound\").description(\"Manage pending emails requiring payment\")\n\ninbound\n\t.command(\"pending\")\n\t.description(\"List pending emails awaiting payment\")\n\t.option(\"-l, --limit <number>\", \"Number of emails to show\", \"20\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (options) => {\n\t\tawait inboundPendingCommand({\n\t\t\tlimit: parseInt(options.limit, 10),\n\t\t\tjson: options.json,\n\t\t})\n\t})\n\ninbound\n\t.command(\"view <id>\")\n\t.description(\"View pending email details and payment info\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (id, options) => {\n\t\tawait inboundViewCommand(id, { json: options.json })\n\t})\n\ninbound\n\t.command(\"pay <id>\")\n\t.description(\"Pay for a pending email\")\n\t.requiredOption(\"--payment-hash <hash>\", \"Payment preimage from Lightning invoice\")\n\t.action(async (id, options) => {\n\t\tawait inboundPayCommand(id, { paymentHash: options.paymentHash })\n\t})\n\n// Credits commands\nconst credits = program.command(\"credits\").description(\"Manage credits\")\n\ncredits\n\t.command(\"balance\")\n\t.description(\"Show credit balance\")\n\t.action(creditsBalanceCommand)\n\n// Default action (no command specified)\nprogram.action(() => {\n\tconsole.log()\n\tconsole.log(pc.bold(\"btc.email CLI\"))\n\tconsole.log(pc.dim(\"Spam-free email powered by Bitcoin Lightning\"))\n\tconsole.log()\n\tprogram.outputHelp()\n})\n\n// Parse and run\nprogram.parse()\n","/**\n * Login Command\n *\n * Implements polling-based browser authentication:\n * 1. Generate session_id\n * 2. Open browser to auth page\n * 3. Poll for tokens\n * 4. Store tokens in config\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport open from \"open\"\nimport ora from \"ora\"\nimport pc from \"picocolors\"\nimport { setAuth, getApiBaseUrl } from \"../config.js\"\n\nconst POLL_INTERVAL_MS = 2000\nconst POLL_TIMEOUT_MS = 300000 // 5 minutes\n\ntype CLISessionResponse =\n\t| { status: \"pending\" }\n\t| {\n\t\t\tstatus: \"complete\"\n\t\t\tdata: {\n\t\t\t\ttoken: string\n\t\t\t\texpiresAt: string\n\t\t\t\tuserId: string\n\t\t\t\temail: string\n\t\t\t}\n\t }\n\nexport async function loginCommand(): Promise<void> {\n\tconst sessionId = randomUUID()\n\tconst baseUrl = getApiBaseUrl().replace(\"/api/v1\", \"\")\n\tconst authUrl = `${baseUrl}/auth/cli?session_id=${sessionId}`\n\tconst pollUrl = `${baseUrl}/api/auth/cli-session?session_id=${sessionId}`\n\n\tconsole.log()\n\tconsole.log(pc.bold(\"btc.email CLI Login\"))\n\tconsole.log()\n\n\t// Create pending session first\n\ttry {\n\t\tconst createResponse = await fetch(\n\t\t\t`${baseUrl}/api/auth/cli-session`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ session_id: sessionId }),\n\t\t\t},\n\t\t)\n\n\t\tif (!createResponse.ok) {\n\t\t\tconsole.error(pc.red(\"Failed to initialize login session\"))\n\t\t\tprocess.exit(1)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(pc.red(\"Failed to connect to btc.email server\"))\n\t\tconsole.error(\n\t\t\tpc.dim(error instanceof Error ? error.message : \"Unknown error\"),\n\t\t)\n\t\tprocess.exit(1)\n\t}\n\n\t// Open browser\n\tconsole.log(pc.dim(\"Opening browser for authentication...\"))\n\tconsole.log()\n\tconsole.log(pc.dim(\"If the browser doesn't open, visit:\"))\n\tconsole.log(pc.cyan(authUrl))\n\tconsole.log()\n\n\ttry {\n\t\tawait open(authUrl)\n\t} catch {\n\t\t// Browser open failed, user can use the URL\n\t}\n\n\t// Poll for tokens\n\tconst spinner = ora(\"Waiting for authentication...\").start()\n\tconst startTime = Date.now()\n\n\twhile (Date.now() - startTime < POLL_TIMEOUT_MS) {\n\t\ttry {\n\t\t\tconst response = await fetch(pollUrl)\n\n\t\t\tif (response.status === 202) {\n\t\t\t\t// Still pending, continue polling\n\t\t\t\tawait sleep(POLL_INTERVAL_MS)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (response.status === 410) {\n\t\t\t\tspinner.fail(\"Session expired. Please try again.\")\n\t\t\t\tprocess.exit(1)\n\t\t\t}\n\n\t\t\tif (response.ok) {\n\t\t\t\tconst data: CLISessionResponse = await response.json()\n\n\t\t\t\tif (data.status === \"complete\") {\n\t\t\t\t\t// Store tokens\n\t\t\t\t\tsetAuth({\n\t\t\t\t\t\ttoken: data.data.token,\n\t\t\t\t\t\texpiresAt: data.data.expiresAt,\n\t\t\t\t\t\tuserId: data.data.userId,\n\t\t\t\t\t\temail: data.data.email,\n\t\t\t\t\t})\n\n\t\t\t\t\tspinner.succeed(pc.green(\"Successfully logged in!\"))\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(` ${pc.dim(\"Email:\")} ${data.data.email}`)\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(pc.dim(\"You can now use btcemail commands.\"))\n\t\t\t\t\tconsole.log(pc.dim(\"Run `btcemail --help` to see available commands.\"))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait sleep(POLL_INTERVAL_MS)\n\t\t} catch (error) {\n\t\t\t// Network error, continue polling\n\t\t\tawait sleep(POLL_INTERVAL_MS)\n\t\t}\n\t}\n\n\tspinner.fail(\"Authentication timed out. Please try again.\")\n\tprocess.exit(1)\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/**\n * CLI Configuration Management\n *\n * Stores auth tokens and user preferences in ~/.btcemail/config.json\n */\n\nimport Conf from \"conf\"\n\nexport type CLIConfig = {\n\tauth?: {\n\t\ttoken: string\n\t\texpiresAt: string\n\t\tuserId: string\n\t\temail: string\n\t}\n\tapi?: {\n\t\tbaseUrl: string\n\t}\n\tpreferences?: {\n\t\tuseCredits: boolean\n\t\tdefaultEditor: string\n\t}\n}\n\nconst config = new Conf<CLIConfig>({\n\tprojectName: \"btcemail\",\n\tschema: {\n\t\tauth: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\ttoken: { type: \"string\" },\n\t\t\t\texpiresAt: { type: \"string\" },\n\t\t\t\tuserId: { type: \"string\" },\n\t\t\t\temail: { type: \"string\" },\n\t\t\t},\n\t\t},\n\t\tapi: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tbaseUrl: { type: \"string\" },\n\t\t\t},\n\t\t\tdefault: {\n\t\t\t\tbaseUrl: \"https://btc.email/api/v1\",\n\t\t\t},\n\t\t},\n\t\tpreferences: {\n\t\t\ttype: \"object\",\n\t\t\tproperties: {\n\t\t\t\tuseCredits: { type: \"boolean\" },\n\t\t\t\tdefaultEditor: { type: \"string\" },\n\t\t\t},\n\t\t\tdefault: {\n\t\t\t\tuseCredits: true,\n\t\t\t\tdefaultEditor: \"vim\",\n\t\t\t},\n\t\t},\n\t},\n})\n\nexport function getConfig(): CLIConfig {\n\treturn config.store\n}\n\nexport function getAuth(): CLIConfig[\"auth\"] | undefined {\n\treturn config.get(\"auth\")\n}\n\nexport function setAuth(auth: CLIConfig[\"auth\"]): void {\n\tconfig.set(\"auth\", auth)\n}\n\nexport function clearAuth(): void {\n\tconfig.delete(\"auth\")\n}\n\nexport function getApiBaseUrl(): string {\n\treturn (\n\t\tprocess.env.BTCEMAIL_API_URL ||\n\t\tconfig.get(\"api.baseUrl\") ||\n\t\t\"https://btc.email/api/v1\"\n\t)\n}\n\nexport function isAuthenticated(): boolean {\n\tconst auth = getAuth()\n\tif (!auth?.token || !auth?.expiresAt) {\n\t\treturn false\n\t}\n\n\t// Check if token is expired\n\tconst expiresAt = new Date(auth.expiresAt)\n\treturn expiresAt > new Date()\n}\n\n/**\n * Check if token is expiring soon (within 5 minutes)\n */\nexport function isTokenExpiringSoon(): boolean {\n\tconst auth = getAuth()\n\tif (!auth?.token || !auth?.expiresAt) {\n\t\treturn false\n\t}\n\n\tconst expiresAt = new Date(auth.expiresAt)\n\tconst fiveMinutesFromNow = new Date(Date.now() + 5 * 60 * 1000)\n\treturn expiresAt <= fiveMinutesFromNow && expiresAt > new Date()\n}\n\n/**\n * Get time until token expires in human-readable format\n */\nexport function getTokenExpiryInfo(): { expired: boolean; expiresIn?: string } {\n\tconst auth = getAuth()\n\tif (!auth?.token || !auth?.expiresAt) {\n\t\treturn { expired: true }\n\t}\n\n\tconst expiresAt = new Date(auth.expiresAt)\n\tconst now = new Date()\n\n\tif (expiresAt <= now) {\n\t\treturn { expired: true }\n\t}\n\n\tconst diffMs = expiresAt.getTime() - now.getTime()\n\tconst diffMins = Math.floor(diffMs / 60000)\n\tconst diffHours = Math.floor(diffMins / 60)\n\n\tif (diffHours > 0) {\n\t\treturn { expired: false, expiresIn: `${diffHours}h ${diffMins % 60}m` }\n\t}\n\treturn { expired: false, expiresIn: `${diffMins}m` }\n}\n\nexport function getToken(): string | null {\n\tconst auth = getAuth()\n\tif (!auth?.token) return null\n\n\t// Check if token is expired\n\tconst expiresAt = new Date(auth.expiresAt)\n\tif (expiresAt <= new Date()) {\n\t\tclearAuth()\n\t\treturn null\n\t}\n\n\treturn auth.token\n}\n\nexport { config }\n","/**\n * Logout Command\n *\n * Clears stored authentication tokens.\n */\n\nimport pc from \"picocolors\"\nimport { clearAuth, isAuthenticated } from \"../config.js\"\n\nexport async function logoutCommand(): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"You are not logged in.\"))\n\t\treturn\n\t}\n\n\tclearAuth()\n\tconsole.log(pc.green(\"Successfully logged out.\"))\n}\n","/**\n * Whoami Command\n *\n * Shows current authenticated user info.\n */\n\nimport pc from \"picocolors\"\nimport {\n\tgetAuth,\n\tgetTokenExpiryInfo,\n\tisAuthenticated,\n\tisTokenExpiringSoon,\n} from \"../config.js\"\nimport { getWhoami } from \"../api.js\"\n\nexport async function whoamiCommand(): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst auth = getAuth()\n\tif (!auth) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Try to get fresh info from API\n\tconst result = await getWhoami()\n\n\tif (result.ok) {\n\t\tconsole.log()\n\t\tconsole.log(pc.bold(\"Current User\"))\n\t\tconsole.log()\n\t\tconsole.log(` ${pc.dim(\"Email:\")} ${result.data.email}`)\n\t\tif (result.data.username) {\n\t\t\tconsole.log(` ${pc.dim(\"Username:\")} ${result.data.username}`)\n\t\t}\n\t\tconsole.log(` ${pc.dim(\"User ID:\")} ${result.data.id}`)\n\n\t\t// Show token expiry info\n\t\tconst expiryInfo = getTokenExpiryInfo()\n\t\tif (expiryInfo.expiresIn) {\n\t\t\tconst expiryColor = isTokenExpiringSoon() ? pc.yellow : pc.dim\n\t\t\tconsole.log(` ${pc.dim(\"Session:\")} ${expiryColor(`expires in ${expiryInfo.expiresIn}`)}`)\n\t\t}\n\t\tconsole.log()\n\n\t\tif (isTokenExpiringSoon()) {\n\t\t\tconsole.log(pc.yellow(\"Session expiring soon. Run `btcemail login` to refresh.\"))\n\t\t\tconsole.log()\n\t\t}\n\t} else {\n\t\t// Fall back to cached info\n\t\tconsole.log()\n\t\tconsole.log(pc.bold(\"Current User (cached)\"))\n\t\tconsole.log()\n\t\tconsole.log(` ${pc.dim(\"Email:\")} ${auth.email}`)\n\t\tconsole.log(` ${pc.dim(\"User ID:\")} ${auth.userId}`)\n\t\tconsole.log()\n\n\t\tif (result.error.code === \"UNAUTHENTICATED\" || result.error.code === \"UNAUTHORIZED\") {\n\t\t\tconsole.log(pc.yellow(\"Session expired. Run `btcemail login` to re-authenticate.\"))\n\t\t}\n\t}\n}\n","/**\n * API Client for btc.email CLI\n *\n * Handles all HTTP requests to the btc.email API.\n * v1 API returns: { success: true, data: {...}, meta: {...} }\n */\n\nimport { getApiBaseUrl, getToken } from \"./config.js\"\n\nexport type ApiResponse<T> =\n\t| { ok: true; data: T }\n\t| { ok: false; error: { code: string; message: string; details?: unknown } }\n\nexport type PaginatedResponse<T> = {\n\tdata: T[]\n\tpagination: {\n\t\ttotal: number\n\t\tlimit: number\n\t\toffset: number\n\t\thasMore: boolean\n\t}\n}\n\n/**\n * v1 API response format\n */\ntype V1ApiResponse<T> = {\n\tsuccess: boolean\n\tdata?: T\n\terror?: { code: string; message: string; details?: unknown }\n\tmeta?: { requestId: string; timestamp: string }\n\tpagination?: {\n\t\ttotal: number\n\t\tlimit: number\n\t\toffset: number\n\t\thasMore: boolean\n\t}\n}\n\n/**\n * Make an authenticated API request\n */\nexport async function apiRequest<T>(\n\tendpoint: string,\n\toptions: RequestInit = {},\n): Promise<ApiResponse<T>> {\n\tconst token = getToken()\n\tconst baseUrl = getApiBaseUrl()\n\n\tconst headers: Record<string, string> = {\n\t\t\"Content-Type\": \"application/json\",\n\t}\n\n\tif (token) {\n\t\theaders.Authorization = `Bearer ${token}`\n\t}\n\n\ttry {\n\t\tconst response = await fetch(`${baseUrl}${endpoint}`, {\n\t\t\t...options,\n\t\t\theaders,\n\t\t})\n\n\t\tconst json = (await response.json()) as V1ApiResponse<T>\n\n\t\t// Handle v1 API format: { success: boolean, data?: T, error?: {...} }\n\t\tif (!response.ok || json.success === false) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: json.error || {\n\t\t\t\t\tcode: \"UNKNOWN_ERROR\",\n\t\t\t\t\tmessage: `Request failed with status ${response.status}`,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\t// For paginated responses, include pagination in the result\n\t\tif (json.pagination) {\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tdata: { data: json.data, pagination: json.pagination } as T,\n\t\t\t}\n\t\t}\n\n\t\t// Extract data from v1 response format\n\t\treturn { ok: true, data: json.data as T }\n\t} catch (error) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"NETWORK_ERROR\",\n\t\t\t\tmessage:\n\t\t\t\t\terror instanceof Error ? error.message : \"Network request failed\",\n\t\t\t},\n\t\t}\n\t}\n}\n\n/**\n * Make an unauthenticated API request (for login, etc.)\n */\nexport async function publicRequest<T>(\n\tendpoint: string,\n\toptions: RequestInit = {},\n): Promise<ApiResponse<T>> {\n\tconst baseUrl = getApiBaseUrl()\n\n\ttry {\n\t\tconst response = await fetch(`${baseUrl}${endpoint}`, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t})\n\n\t\tconst json = (await response.json()) as V1ApiResponse<T>\n\n\t\tif (!response.ok || json.success === false) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: json.error || {\n\t\t\t\t\tcode: \"UNKNOWN_ERROR\",\n\t\t\t\t\tmessage: `Request failed with status ${response.status}`,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn { ok: true, data: json.data as T }\n\t} catch (error) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: {\n\t\t\t\tcode: \"NETWORK_ERROR\",\n\t\t\t\tmessage:\n\t\t\t\t\terror instanceof Error ? error.message : \"Network request failed\",\n\t\t\t},\n\t\t}\n\t}\n}\n\n// API endpoint helpers\n\nexport async function getEmails(options: {\n\tfolder?: string\n\tlimit?: number\n\toffset?: number\n\tsearch?: string\n}) {\n\tconst params = new URLSearchParams()\n\tif (options.folder) params.set(\"folder\", options.folder)\n\tif (options.limit) params.set(\"limit\", String(options.limit))\n\tif (options.offset) params.set(\"offset\", String(options.offset))\n\tif (options.search) params.set(\"search\", options.search)\n\n\treturn apiRequest<PaginatedResponse<Email>>(`/email?${params}`)\n}\n\nexport async function getEmail(id: string) {\n\treturn apiRequest<Email>(`/email/${id}`)\n}\n\nexport async function getCreditsBalance() {\n\treturn apiRequest<CreditBalance>(\"/credits/balance\")\n}\n\nexport type CreditBalance = {\n\tbalanceSats: number\n\tlifetimePurchasedSats: number\n\tlifetimeSpentSats: number\n\tlastPurchaseAt: string | null\n}\n\nexport async function getWhoami() {\n\treturn apiRequest<{ id: string; email: string; username?: string }>(\n\t\t\"/auth/whoami\",\n\t)\n}\n\n// Pending/Inbound email functions\n\nexport async function getPendingEmails(options: { limit?: number; offset?: number } = {}) {\n\tconst params = new URLSearchParams()\n\tif (options.limit) params.set(\"limit\", String(options.limit))\n\tif (options.offset) params.set(\"offset\", String(options.offset))\n\n\treturn apiRequest<PaginatedResponse<PendingEmail>>(`/inbound/pending?${params}`)\n}\n\nexport async function getPendingEmail(id: string) {\n\treturn apiRequest<PendingEmailDetail>(`/inbound/${id}`)\n}\n\nexport async function payForEmail(id: string, paymentHash: string) {\n\treturn apiRequest<{ emailId: string; status: string }>(`/inbound/${id}/pay`, {\n\t\tmethod: \"POST\",\n\t\tbody: JSON.stringify({ paymentHash }),\n\t})\n}\n\n// Send email functions\n\nexport async function sendEmail(options: {\n\tto: string[]\n\tsubject: string\n\tbody: string\n\tbodyText?: string\n\tfromEmail: string\n\tpaymentHash?: string\n}) {\n\treturn apiRequest<{ emailId: string; status: string; messageId?: string }>(\"/email/send\", {\n\t\tmethod: \"POST\",\n\t\tbody: JSON.stringify(options),\n\t})\n}\n\nexport async function getL402Invoice(options: {\n\tfromEmail: string\n\ttoEmails: string[]\n\tamountSats?: number\n}) {\n\t// L402 endpoint is at /api/l402, not /api/v1/l402\n\t// Derive root API URL from v1 base URL\n\tconst v1BaseUrl = getApiBaseUrl()\n\tconst rootApiUrl = v1BaseUrl.replace(\"/api/v1\", \"/api\")\n\tconst token = getToken()\n\n\tconst headers: HeadersInit = {\n\t\t\"Content-Type\": \"application/json\",\n\t}\n\tif (token) {\n\t\theaders.Authorization = `Bearer ${token}`\n\t}\n\n\ttry {\n\t\tconst response = await fetch(`${rootApiUrl}/l402/invoice`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify({\n\t\t\t\tsender_email: options.fromEmail,\n\t\t\t\trecipient_emails: options.toEmails,\n\t\t\t\tamount_sats: options.amountSats,\n\t\t\t}),\n\t\t})\n\n\t\tconst json = (await response.json()) as {\n\t\t\tsuccess: boolean\n\t\t\tdata?: L402Invoice\n\t\t\terror?: { code: string; message: string; details?: unknown }\n\t\t}\n\n\t\tif (!response.ok || json.success === false) {\n\t\t\treturn {\n\t\t\t\tok: false as const,\n\t\t\t\terror: json.error || {\n\t\t\t\t\tcode: \"UNKNOWN_ERROR\",\n\t\t\t\t\tmessage: `Request failed with status ${response.status}`,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn { ok: true as const, data: json.data as L402Invoice }\n\t} catch (error) {\n\t\treturn {\n\t\t\tok: false as const,\n\t\t\terror: {\n\t\t\t\tcode: \"NETWORK_ERROR\",\n\t\t\t\tmessage: error instanceof Error ? error.message : \"Network request failed\",\n\t\t\t},\n\t\t}\n\t}\n}\n\n// Types\n\nexport type Email = {\n\tid: string\n\tsubject: string\n\tfrom: { email: string; name?: string }\n\tto: { email: string; name?: string }[]\n\tsnippet: string\n\tbody?: string\n\tbodyText?: string\n\tdate: string\n\tunread: boolean\n\tlabels: string[]\n}\n\nexport type PendingEmail = {\n\tid: string\n\tsubject: string\n\tfrom: { email: string; name?: string }\n\tamountSats: number\n\tcreatedAt: string\n}\n\nexport type PendingEmailDetail = {\n\tid: string\n\tsubject: string\n\tfrom: { email: string; name?: string }\n\tbody: string\n\tbodyText: string\n\tamountSats: number\n\tcreatedAt: string\n\tpaymentHash: string | null\n}\n\nexport type L402Invoice = {\n\tinvoice: string\n\tpaymentHash: string\n\tamountSats: number\n\texpiresAt: string\n}\n","/**\n * List Command\n *\n * Lists emails with pagination and filtering.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getEmails, type Email } from \"../api.js\"\n\nexport type ListOptions = {\n\tfolder?: string\n\tlimit?: number\n\tjson?: boolean\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getEmails({\n\t\tfolder: options.folder || \"inbox\",\n\t\tlimit: options.limit || 20,\n\t})\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify({ emails, pagination }, null, 2))\n\t\treturn\n\t}\n\n\t// Table output\n\tconsole.log()\n\tconsole.log(\n\t\tpc.bold(`${options.folder || \"Inbox\"} (${pagination.total} emails)`),\n\t)\n\tconsole.log()\n\n\tif (emails.length === 0) {\n\t\tconsole.log(pc.dim(\" No emails found.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Header\n\tconsole.log(\n\t\t` ${pc.dim(\"ID\".padEnd(12))} ${pc.dim(\"From\".padEnd(25))} ${pc.dim(\"Subject\".padEnd(40))} ${pc.dim(\"Date\")}`,\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(90)))\n\n\t// Rows\n\tfor (const email of emails) {\n\t\tconst unreadMarker = email.unread ? pc.cyan(\"*\") : \" \"\n\t\tconst id = email.id.slice(0, 10).padEnd(12)\n\t\tconst from = truncate(email.from.name || email.from.email, 23).padEnd(25)\n\t\tconst subject = truncate(email.subject, 38).padEnd(40)\n\t\tconst date = formatDate(email.date)\n\n\t\tconsole.log(`${unreadMarker} ${id} ${from} ${subject} ${pc.dim(date)}`)\n\t}\n\n\tconsole.log()\n\n\tif (pagination.hasMore) {\n\t\tconsole.log(\n\t\t\tpc.dim(\n\t\t\t\t` Showing ${emails.length} of ${pagination.total}. Use --limit to see more.`,\n\t\t\t),\n\t\t)\n\t\tconsole.log()\n\t}\n}\n\nfunction truncate(str: string, maxLength: number): string {\n\tif (str.length <= maxLength) return str\n\treturn str.slice(0, maxLength - 1) + \"…\"\n}\n\nfunction formatDate(dateString: string): string {\n\tconst date = new Date(dateString)\n\tconst now = new Date()\n\tconst diffMs = now.getTime() - date.getTime()\n\tconst diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))\n\n\tif (diffDays === 0) {\n\t\treturn date.toLocaleTimeString(\"en-US\", {\n\t\t\thour: \"numeric\",\n\t\t\tminute: \"2-digit\",\n\t\t})\n\t}\n\n\tif (diffDays < 7) {\n\t\treturn date.toLocaleDateString(\"en-US\", { weekday: \"short\" })\n\t}\n\n\treturn date.toLocaleDateString(\"en-US\", {\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t})\n}\n","/**\n * Read Command\n *\n * Display a single email by ID.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getEmail, type Email } from \"../api.js\"\n\nexport type ReadOptions = {\n\tjson?: boolean\n}\n\nexport async function readCommand(id: string, options: ReadOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getEmail(id)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"NOT_FOUND\") {\n\t\t\tconsole.error(pc.red(`Email not found: ${id}`))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconst email = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(email, null, 2))\n\t\treturn\n\t}\n\n\t// Formatted output\n\tconsole.log()\n\tconsole.log(pc.bold(email.subject || \"(No subject)\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"From:\")} ${formatAddress(email.from)}`)\n\tconsole.log(`${pc.dim(\"To:\")} ${email.to.map(formatAddress).join(\", \")}`)\n\tconsole.log(`${pc.dim(\"Date:\")} ${formatFullDate(email.date)}`)\n\tconsole.log(`${pc.dim(\"ID:\")} ${email.id}`)\n\n\tif (email.labels.length > 0) {\n\t\tconsole.log(`${pc.dim(\"Labels:\")} ${email.labels.join(\", \")}`)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.dim(\"-\".repeat(60)))\n\tconsole.log()\n\n\t// Show full body if available, otherwise fall back to snippet\n\tconst content = email.bodyText || email.body || email.snippet\n\tif (content) {\n\t\t// Strip HTML tags for plain text display if showing HTML body\n\t\tconst displayContent = email.bodyText || stripHtml(email.body || email.snippet)\n\t\tconsole.log(displayContent)\n\t} else {\n\t\tconsole.log(pc.dim(\"(No content)\"))\n\t}\n\tconsole.log()\n}\n\nfunction stripHtml(html: string): string {\n\t// Basic HTML stripping for terminal display\n\treturn html\n\t\t.replace(/<br\\s*\\/?>/gi, \"\\n\")\n\t\t.replace(/<\\/p>/gi, \"\\n\\n\")\n\t\t.replace(/<\\/div>/gi, \"\\n\")\n\t\t.replace(/<[^>]*>/g, \"\")\n\t\t.replace(/&nbsp;/g, \" \")\n\t\t.replace(/&lt;/g, \"<\")\n\t\t.replace(/&gt;/g, \">\")\n\t\t.replace(/&amp;/g, \"&\")\n\t\t.replace(/&quot;/g, '\"')\n\t\t.trim()\n}\n\nfunction formatAddress(addr: { email: string; name?: string }): string {\n\tif (addr.name) {\n\t\treturn `${addr.name} <${addr.email}>`\n\t}\n\treturn addr.email\n}\n\nfunction formatFullDate(dateString: string): string {\n\tconst date = new Date(dateString)\n\treturn date.toLocaleString(\"en-US\", {\n\t\tweekday: \"short\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\thour: \"numeric\",\n\t\tminute: \"2-digit\",\n\t})\n}\n","/**\n * Credits Command\n *\n * Shows credit balance and transaction history.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getCreditsBalance } from \"../api.js\"\n\nexport async function creditsBalanceCommand(): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getCreditsBalance()\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconst { balanceSats } = result.data\n\n\tconsole.log()\n\tconsole.log(pc.bold(\"Credit Balance\"))\n\tconsole.log()\n\tconsole.log(` ${pc.green(formatSats(balanceSats))} sats`)\n\tconsole.log()\n\n\tif (balanceSats === 0) {\n\t\tconsole.log(pc.dim(\" No credits available.\"))\n\t\tconsole.log(pc.dim(\" Purchase credits at https://btc.email/payments\"))\n\t\tconsole.log()\n\t}\n}\n\nfunction formatSats(sats: number): string {\n\treturn sats.toLocaleString()\n}\n","/**\n * Send Command\n *\n * Compose and send an email with L402 payment flow.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated, getAuth } from \"../config.js\"\nimport { sendEmail, getL402Invoice, getWhoami } from \"../api.js\"\n\nexport type SendOptions = {\n\tto?: string\n\tsubject?: string\n\tbody?: string\n\tfromEmail?: string\n\tpaymentHash?: string\n}\n\nexport async function sendCommand(options: SendOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Get user's email address\n\tlet fromEmail = options.fromEmail\n\tif (!fromEmail) {\n\t\tconst whoamiResult = await getWhoami()\n\t\tif (whoamiResult.ok && whoamiResult.data.username) {\n\t\t\tfromEmail = `${whoamiResult.data.username}@btc.email`\n\t\t} else {\n\t\t\tconst auth = getAuth()\n\t\t\tif (auth?.email?.endsWith(\"@btc.email\")) {\n\t\t\t\tfromEmail = auth.email\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!fromEmail || !fromEmail.endsWith(\"@btc.email\")) {\n\t\tconsole.error(pc.red(\"No @btc.email address found.\"))\n\t\tconsole.log(pc.dim(\"Register a username at https://btc.email\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Validate required fields\n\tif (!options.to) {\n\t\tconsole.error(pc.red(\"Recipient is required. Use --to <email>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.subject) {\n\t\tconsole.error(pc.red(\"Subject is required. Use --subject <text>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.body) {\n\t\tconsole.error(pc.red(\"Body is required. Use --body <text>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst toEmails = options.to.split(\",\").map((e) => e.trim())\n\n\tconsole.log()\n\tconsole.log(pc.bold(\"Sending Email\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"From:\")} ${fromEmail}`)\n\tconsole.log(`${pc.dim(\"To:\")} ${toEmails.join(\", \")}`)\n\tconsole.log(`${pc.dim(\"Subject:\")} ${options.subject}`)\n\tconsole.log()\n\n\t// If no payment hash provided, check if payment is required\n\tif (!options.paymentHash) {\n\t\tconst invoiceResult = await getL402Invoice({\n\t\t\tfromEmail,\n\t\t\ttoEmails,\n\t\t})\n\n\t\tif (invoiceResult.ok && invoiceResult.data.amountSats > 0) {\n\t\t\t// Payment required\n\t\t\tconst invoice = invoiceResult.data\n\t\t\tconsole.log(pc.yellow(`Payment required: ${invoice.amountSats} sats`))\n\t\t\tconsole.log()\n\t\t\tconsole.log(pc.dim(\"Lightning Invoice:\"))\n\t\t\tconsole.log(pc.cyan(invoice.invoice))\n\t\t\tconsole.log()\n\t\t\tconsole.log(pc.dim(\"Pay this invoice with your Lightning wallet, then run:\"))\n\t\t\tconsole.log(\n\t\t\t\tpc.cyan(\n\t\t\t\t\t` btcemail send --to \"${options.to}\" --subject \"${options.subject}\" --body \"${options.body}\" --payment-hash ${invoice.paymentHash}`\n\t\t\t\t)\n\t\t\t)\n\t\t\tconsole.log()\n\t\t\treturn\n\t\t}\n\t}\n\n\t// Send email (with payment hash if provided)\n\tconst result = await sendEmail({\n\t\tto: toEmails,\n\t\tsubject: options.subject,\n\t\tbody: options.body,\n\t\tfromEmail,\n\t\tpaymentHash: options.paymentHash,\n\t})\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"PAYMENT_REQUIRED\") {\n\t\t\tconsole.error(pc.yellow(\"Payment required to send this email.\"))\n\t\t\tconsole.log(pc.dim(\"Use the invoice above to pay, then include --payment-hash\"))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log(pc.green(\"Email sent successfully!\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"Email ID:\")} ${result.data.emailId}`)\n\tif (result.data.messageId) {\n\t\tconsole.log(`${pc.dim(\"Message ID:\")} ${result.data.messageId}`)\n\t}\n\tconsole.log()\n}\n\nexport type SendWithPaymentOptions = SendOptions & {\n\tpaymentHash?: string\n}\n\nexport async function sendWithPaymentCommand(options: SendWithPaymentOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\t// Get user's email address\n\tlet fromEmail = options.fromEmail\n\tif (!fromEmail) {\n\t\tconst whoamiResult = await getWhoami()\n\t\tif (whoamiResult.ok && whoamiResult.data.username) {\n\t\t\tfromEmail = `${whoamiResult.data.username}@btc.email`\n\t\t}\n\t}\n\n\tif (!fromEmail || !fromEmail.endsWith(\"@btc.email\")) {\n\t\tconsole.error(pc.red(\"No @btc.email address found.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.to || !options.subject || !options.body) {\n\t\tconsole.error(pc.red(\"Missing required fields: --to, --subject, --body\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst toEmails = options.to.split(\",\").map((e) => e.trim())\n\n\tconst result = await sendEmail({\n\t\tto: toEmails,\n\t\tsubject: options.subject,\n\t\tbody: options.body,\n\t\tfromEmail,\n\t\tpaymentHash: options.paymentHash,\n\t})\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.green(\"Email sent successfully!\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"Email ID:\")} ${result.data.emailId}`)\n\tconsole.log()\n}\n","/**\n * Inbound Commands\n *\n * View and pay for pending emails that require payment.\n */\n\nimport pc from \"picocolors\"\nimport { isAuthenticated } from \"../config.js\"\nimport {\n\tgetPendingEmails,\n\tgetPendingEmail,\n\tpayForEmail,\n\ttype PendingEmail,\n} from \"../api.js\"\n\nexport type InboundListOptions = {\n\tlimit?: number\n\tjson?: boolean\n}\n\nexport async function inboundPendingCommand(options: InboundListOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getPendingEmails({\n\t\tlimit: options.limit || 20,\n\t})\n\n\tif (!result.ok) {\n\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify({ emails, pagination }, null, 2))\n\t\treturn\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.bold(`Pending Emails (${pagination.total} awaiting payment)`))\n\tconsole.log()\n\n\tif (emails.length === 0) {\n\t\tconsole.log(pc.dim(\" No pending emails.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Header\n\tconsole.log(\n\t\t` ${pc.dim(\"ID\".padEnd(12))} ${pc.dim(\"From\".padEnd(30))} ${pc.dim(\"Subject\".padEnd(30))} ${pc.dim(\"Sats\")}`\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(85)))\n\n\t// Rows\n\tfor (const email of emails) {\n\t\tconst id = email.id.slice(0, 10).padEnd(12)\n\t\tconst from = truncate(email.from.name || email.from.email, 28).padEnd(30)\n\t\tconst subject = truncate(email.subject, 28).padEnd(30)\n\t\tconst sats = pc.yellow(String(email.amountSats))\n\n\t\tconsole.log(` ${id} ${from} ${subject} ${sats}`)\n\t}\n\n\tconsole.log()\n\n\tif (pagination.hasMore) {\n\t\tconsole.log(\n\t\t\tpc.dim(` Showing ${emails.length} of ${pagination.total}. Use --limit to see more.`)\n\t\t)\n\t\tconsole.log()\n\t}\n\n\tconsole.log(pc.dim(\" Use `btcemail inbound view <id>` to see details and payment invoice.\"))\n\tconsole.log()\n}\n\nexport type InboundViewOptions = {\n\tjson?: boolean\n}\n\nexport async function inboundViewCommand(id: string, options: InboundViewOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst result = await getPendingEmail(id)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"NOT_FOUND\") {\n\t\t\tconsole.error(pc.red(`Pending email not found: ${id}`))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconst email = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(email, null, 2))\n\t\treturn\n\t}\n\n\t// Formatted output\n\tconsole.log()\n\tconsole.log(pc.bold(email.subject || \"(No subject)\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"From:\")} ${formatAddress(email.from)}`)\n\tconsole.log(`${pc.dim(\"Date:\")} ${formatFullDate(email.createdAt)}`)\n\tconsole.log(`${pc.dim(\"ID:\")} ${email.id}`)\n\tconsole.log()\n\tconsole.log(pc.yellow(`Payment Required: ${email.amountSats} sats`))\n\tconsole.log()\n\n\tif (email.paymentHash) {\n\t\tconsole.log(pc.dim(\"To receive this email, pay the invoice and run:\"))\n\t\tconsole.log(pc.cyan(` btcemail inbound pay ${email.id} --payment-hash <preimage>`))\n\t} else {\n\t\tconsole.log(pc.dim(\"Payment information not available.\"))\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.dim(\"-\".repeat(60)))\n\tconsole.log()\n\tconsole.log(pc.dim(\"Preview (full content available after payment):\"))\n\tconsole.log()\n\tconsole.log(truncate(email.bodyText || email.body, 200))\n\tconsole.log()\n}\n\nexport type InboundPayOptions = {\n\tpaymentHash: string\n}\n\nexport async function inboundPayCommand(id: string, options: InboundPayOptions): Promise<void> {\n\tif (!isAuthenticated()) {\n\t\tconsole.log(pc.yellow(\"Not logged in.\"))\n\t\tconsole.log(pc.dim(\"Run `btcemail login` to authenticate.\"))\n\t\tprocess.exit(1)\n\t}\n\n\tif (!options.paymentHash) {\n\t\tconsole.error(pc.red(\"Payment hash is required. Use --payment-hash <preimage>\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.dim(\"Verifying payment...\"))\n\n\tconst result = await payForEmail(id, options.paymentHash)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"PAYMENT_INVALID\") {\n\t\t\tconsole.error(pc.red(\"Payment verification failed.\"))\n\t\t\tconsole.log(pc.dim(\"Make sure you paid the correct invoice and provided the preimage.\"))\n\t\t} else if (result.error.code === \"NOT_FOUND\") {\n\t\t\tconsole.error(pc.red(`Pending email not found or already delivered: ${id}`))\n\t\t} else {\n\t\t\tconsole.error(pc.red(`Error: ${result.error.message}`))\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.green(\"Payment verified! Email delivered.\"))\n\tconsole.log()\n\tconsole.log(`${pc.dim(\"Email ID:\")} ${result.data.emailId}`)\n\tconsole.log(`${pc.dim(\"Status:\")} ${result.data.status}`)\n\tconsole.log()\n\tconsole.log(pc.dim(\"Run `btcemail read \" + result.data.emailId + \"` to read the email.\"))\n\tconsole.log()\n}\n\nfunction truncate(str: string, maxLength: number): string {\n\tif (str.length <= maxLength) return str\n\treturn str.slice(0, maxLength - 1) + \"…\"\n}\n\nfunction formatAddress(addr: { email: string; name?: string }): string {\n\tif (addr.name) {\n\t\treturn `${addr.name} <${addr.email}>`\n\t}\n\treturn addr.email\n}\n\nfunction formatFullDate(dateString: string): string {\n\tconst date = new Date(dateString)\n\treturn date.toLocaleString(\"en-US\", {\n\t\tweekday: \"short\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\thour: \"numeric\",\n\t\tminute: \"2-digit\",\n\t})\n}\n"],"mappings":"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","names":["pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","pc","truncate","formatAddress","formatFullDate","pc"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btcemail/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "btc.email CLI - Spam-free email powered by Bitcoin Lightning",
5
5
  "type": "module",
6
6
  "bin": {