@btcemail/cli 0.1.1 → 0.3.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/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\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":";;;AAUA,SAAS,eAAe;AACxB,OAAOA,SAAQ;;;ACDf,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB,OAAO,SAAS;AAChB,OAAO,QAAQ;;;ACPf,OAAO,UAAU;AAkBjB,IAAM,SAAS,IAAI,KAAgB;AAAA,EAClC,aAAa;AAAA,EACb,QAAQ;AAAA,IACP,MAAM;AAAA,MACL,MAAM;AAAA,MACN,YAAY;AAAA,QACX,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,WAAW,EAAE,MAAM,SAAS;AAAA,QAC5B,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,OAAO,EAAE,MAAM,SAAS;AAAA,MACzB;AAAA,IACD;AAAA,IACA,KAAK;AAAA,MACJ,MAAM;AAAA,MACN,YAAY;AAAA,QACX,SAAS,EAAE,MAAM,SAAS;AAAA,MAC3B;AAAA,MACA,SAAS;AAAA,QACR,SAAS;AAAA,MACV;AAAA,IACD;AAAA,IACA,aAAa;AAAA,MACZ,MAAM;AAAA,MACN,YAAY;AAAA,QACX,YAAY,EAAE,MAAM,UAAU;AAAA,QAC9B,eAAe,EAAE,MAAM,SAAS;AAAA,MACjC;AAAA,MACA,SAAS;AAAA,QACR,YAAY;AAAA,QACZ,eAAe;AAAA,MAChB;AAAA,IACD;AAAA,EACD;AACD,CAAC;AAMM,SAAS,UAAyC;AACxD,SAAO,OAAO,IAAI,MAAM;AACzB;AAEO,SAAS,QAAQ,MAA+B;AACtD,SAAO,IAAI,QAAQ,IAAI;AACxB;AAEO,SAAS,YAAkB;AACjC,SAAO,OAAO,MAAM;AACrB;AAEO,SAAS,gBAAwB;AACvC,SACC,QAAQ,IAAI,oBACZ,OAAO,IAAI,aAAa,KACxB;AAEF;AAEO,SAAS,kBAA2B;AAC1C,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM,SAAS,CAAC,MAAM,WAAW;AACrC,WAAO;AAAA,EACR;AAGA,QAAM,YAAY,IAAI,KAAK,KAAK,SAAS;AACzC,SAAO,YAAY,oBAAI,KAAK;AAC7B;AAKO,SAAS,sBAA+B;AAC9C,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM,SAAS,CAAC,MAAM,WAAW;AACrC,WAAO;AAAA,EACR;AAEA,QAAM,YAAY,IAAI,KAAK,KAAK,SAAS;AACzC,QAAM,qBAAqB,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,GAAI;AAC9D,SAAO,aAAa,sBAAsB,YAAY,oBAAI,KAAK;AAChE;AAKO,SAAS,qBAA+D;AAC9E,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM,SAAS,CAAC,MAAM,WAAW;AACrC,WAAO,EAAE,SAAS,KAAK;AAAA,EACxB;AAEA,QAAM,YAAY,IAAI,KAAK,KAAK,SAAS;AACzC,QAAM,MAAM,oBAAI,KAAK;AAErB,MAAI,aAAa,KAAK;AACrB,WAAO,EAAE,SAAS,KAAK;AAAA,EACxB;AAEA,QAAM,SAAS,UAAU,QAAQ,IAAI,IAAI,QAAQ;AACjD,QAAM,WAAW,KAAK,MAAM,SAAS,GAAK;AAC1C,QAAM,YAAY,KAAK,MAAM,WAAW,EAAE;AAE1C,MAAI,YAAY,GAAG;AAClB,WAAO,EAAE,SAAS,OAAO,WAAW,GAAG,SAAS,KAAK,WAAW,EAAE,IAAI;AAAA,EACvE;AACA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,IAAI;AACpD;AAEO,SAAS,WAA0B;AACzC,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM,MAAO,QAAO;AAGzB,QAAM,YAAY,IAAI,KAAK,KAAK,SAAS;AACzC,MAAI,aAAa,oBAAI,KAAK,GAAG;AAC5B,cAAU;AACV,WAAO;AAAA,EACR;AAEA,SAAO,KAAK;AACb;;;ADlIA,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AAcxB,eAAsB,eAA8B;AACnD,QAAM,YAAY,WAAW;AAC7B,QAAM,UAAU,cAAc,EAAE,QAAQ,WAAW,EAAE;AACrD,QAAM,UAAU,GAAG,OAAO,wBAAwB,SAAS;AAC3D,QAAM,UAAU,GAAG,OAAO,oCAAoC,SAAS;AAEvE,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAG,KAAK,qBAAqB,CAAC;AAC1C,UAAQ,IAAI;AAGZ,MAAI;AACH,UAAM,iBAAiB,MAAM;AAAA,MAC5B,GAAG,OAAO;AAAA,MACV;AAAA,QACC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,YAAY,UAAU,CAAC;AAAA,MAC/C;AAAA,IACD;AAEA,QAAI,CAAC,eAAe,IAAI;AACvB,cAAQ,MAAM,GAAG,IAAI,oCAAoC,CAAC;AAC1D,cAAQ,KAAK,CAAC;AAAA,IACf;AAAA,EACD,SAAS,OAAO;AACf,YAAQ,MAAM,GAAG,IAAI,uCAAuC,CAAC;AAC7D,YAAQ;AAAA,MACP,GAAG,IAAI,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,IAChE;AACA,YAAQ,KAAK,CAAC;AAAA,EACf;AAGA,UAAQ,IAAI,GAAG,IAAI,uCAAuC,CAAC;AAC3D,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAG,IAAI,qCAAqC,CAAC;AACzD,UAAQ,IAAI,GAAG,KAAK,OAAO,CAAC;AAC5B,UAAQ,IAAI;AAEZ,MAAI;AACH,UAAM,KAAK,OAAO;AAAA,EACnB,QAAQ;AAAA,EAER;AAGA,QAAM,UAAU,IAAI,+BAA+B,EAAE,MAAM;AAC3D,QAAM,YAAY,KAAK,IAAI;AAE3B,SAAO,KAAK,IAAI,IAAI,YAAY,iBAAiB;AAChD,QAAI;AACH,YAAM,WAAW,MAAM,MAAM,OAAO;AAEpC,UAAI,SAAS,WAAW,KAAK;AAE5B,cAAM,MAAM,gBAAgB;AAC5B;AAAA,MACD;AAEA,UAAI,SAAS,WAAW,KAAK;AAC5B,gBAAQ,KAAK,oCAAoC;AACjD,gBAAQ,KAAK,CAAC;AAAA,MACf;AAEA,UAAI,SAAS,IAAI;AAChB,cAAM,OAA2B,MAAM,SAAS,KAAK;AAErD,YAAI,KAAK,WAAW,YAAY;AAE/B,kBAAQ;AAAA,YACP,OAAO,KAAK,KAAK;AAAA,YACjB,WAAW,KAAK,KAAK;AAAA,YACrB,QAAQ,KAAK,KAAK;AAAA,YAClB,OAAO,KAAK,KAAK;AAAA,UAClB,CAAC;AAED,kBAAQ,QAAQ,GAAG,MAAM,yBAAyB,CAAC;AACnD,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,KAAK,GAAG,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,KAAK,EAAE;AACtD,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,GAAG,IAAI,oCAAoC,CAAC;AACxD,kBAAQ,IAAI,GAAG,IAAI,kDAAkD,CAAC;AACtE;AAAA,QACD;AAAA,MACD;AAEA,YAAM,MAAM,gBAAgB;AAAA,IAC7B,SAAS,OAAO;AAEf,YAAM,MAAM,gBAAgB;AAAA,IAC7B;AAAA,EACD;AAEA,UAAQ,KAAK,6CAA6C;AAC1D,UAAQ,KAAK,CAAC;AACf;AAEA,SAAS,MAAM,IAA2B;AACzC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACxD;;;AE7HA,OAAOC,SAAQ;AAGf,eAAsB,gBAA+B;AACpD,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIC,IAAG,OAAO,wBAAwB,CAAC;AAC/C;AAAA,EACD;AAEA,YAAU;AACV,UAAQ,IAAIA,IAAG,MAAM,0BAA0B,CAAC;AACjD;;;ACXA,OAAOC,SAAQ;;;ACoCf,eAAsB,WACrB,UACA,UAAuB,CAAC,GACE;AAC1B,QAAM,QAAQ,SAAS;AACvB,QAAM,UAAU,cAAc;AAE9B,QAAM,UAAkC;AAAA,IACvC,gBAAgB;AAAA,EACjB;AAEA,MAAI,OAAO;AACV,YAAQ,gBAAgB,UAAU,KAAK;AAAA,EACxC;AAEA,MAAI;AACH,UAAM,WAAW,MAAM,MAAM,GAAG,OAAO,GAAG,QAAQ,IAAI;AAAA,MACrD,GAAG;AAAA,MACH;AAAA,IACD,CAAC;AAED,UAAM,OAAQ,MAAM,SAAS,KAAK;AAGlC,QAAI,CAAC,SAAS,MAAM,KAAK,YAAY,OAAO;AAC3C,aAAO;AAAA,QACN,IAAI;AAAA,QACJ,OAAO,KAAK,SAAS;AAAA,UACpB,MAAM;AAAA,UACN,SAAS,8BAA8B,SAAS,MAAM;AAAA,QACvD;AAAA,MACD;AAAA,IACD;AAGA,QAAI,KAAK,YAAY;AACpB,aAAO;AAAA,QACN,IAAI;AAAA,QACJ,MAAM,EAAE,MAAM,KAAK,MAAM,YAAY,KAAK,WAAW;AAAA,MACtD;AAAA,IACD;AAGA,WAAO,EAAE,IAAI,MAAM,MAAM,KAAK,KAAU;AAAA,EACzC,SAAS,OAAO;AACf,WAAO;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,QACN,MAAM;AAAA,QACN,SACC,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAC3C;AAAA,IACD;AAAA,EACD;AACD;AA+CA,eAAsB,UAAU,SAK7B;AACF,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,QAAQ,MAAM;AACvD,MAAI,QAAQ,MAAO,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAC5D,MAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,OAAO,QAAQ,MAAM,CAAC;AAC/D,MAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,QAAQ,MAAM;AAEvD,SAAO,WAAqC,UAAU,MAAM,EAAE;AAC/D;AAEA,eAAsB,SAAS,IAAY;AAC1C,SAAO,WAAkB,UAAU,EAAE,EAAE;AACxC;AAEA,eAAsB,oBAAoB;AACzC,SAAO,WAA0B,kBAAkB;AACpD;AASA,eAAsB,YAAY;AACjC,SAAO;AAAA,IACN;AAAA,EACD;AACD;AAIA,eAAsB,iBAAiB,UAA+C,CAAC,GAAG;AACzF,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,QAAQ,MAAO,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAC5D,MAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,OAAO,QAAQ,MAAM,CAAC;AAE/D,SAAO,WAA4C,oBAAoB,MAAM,EAAE;AAChF;AAEA,eAAsB,gBAAgB,IAAY;AACjD,SAAO,WAA+B,YAAY,EAAE,EAAE;AACvD;AAEA,eAAsB,YAAY,IAAY,aAAqB;AAClE,SAAO,WAAgD,YAAY,EAAE,QAAQ;AAAA,IAC5E,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,YAAY,CAAC;AAAA,EACrC,CAAC;AACF;AAIA,eAAsB,UAAU,SAO7B;AACF,SAAO,WAAoE,eAAe;AAAA,IACzF,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,OAAO;AAAA,EAC7B,CAAC;AACF;AAEA,eAAsB,eAAe,SAIlC;AAGF,QAAM,YAAY,cAAc;AAChC,QAAM,aAAa,UAAU,QAAQ,WAAW,MAAM;AACtD,QAAM,QAAQ,SAAS;AAEvB,QAAM,UAAuB;AAAA,IAC5B,gBAAgB;AAAA,EACjB;AACA,MAAI,OAAO;AACV,YAAQ,gBAAgB,UAAU,KAAK;AAAA,EACxC;AAEA,MAAI;AACH,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,iBAAiB;AAAA,MAC1D,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACpB,cAAc,QAAQ;AAAA,QACtB,kBAAkB,QAAQ;AAAA,QAC1B,aAAa,QAAQ;AAAA,MACtB,CAAC;AAAA,IACF,CAAC;AAED,UAAM,OAAQ,MAAM,SAAS,KAAK;AAMlC,QAAI,CAAC,SAAS,MAAM,KAAK,YAAY,OAAO;AAC3C,aAAO;AAAA,QACN,IAAI;AAAA,QACJ,OAAO,KAAK,SAAS;AAAA,UACpB,MAAM;AAAA,UACN,SAAS,8BAA8B,SAAS,MAAM;AAAA,QACvD;AAAA,MACD;AAAA,IACD;AAEA,WAAO,EAAE,IAAI,MAAe,MAAM,KAAK,KAAoB;AAAA,EAC5D,SAAS,OAAO;AACf,WAAO;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,QACN,MAAM;AAAA,QACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MACnD;AAAA,IACD;AAAA,EACD;AACD;;;ADhQA,eAAsB,gBAA+B;AACpD,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIC,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,MAAM;AACV,YAAQ,IAAIA,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,KAAK,CAAC;AAAA,EACf;AAGA,QAAM,SAAS,MAAM,UAAU;AAE/B,MAAI,OAAO,IAAI;AACd,YAAQ,IAAI;AACZ,YAAQ,IAAIA,IAAG,KAAK,cAAc,CAAC;AACnC,YAAQ,IAAI;AACZ,YAAQ,IAAI,KAAKA,IAAG,IAAI,QAAQ,CAAC,OAAO,OAAO,KAAK,KAAK,EAAE;AAC3D,QAAI,OAAO,KAAK,UAAU;AACzB,cAAQ,IAAI,KAAKA,IAAG,IAAI,WAAW,CAAC,IAAI,OAAO,KAAK,QAAQ,EAAE;AAAA,IAC/D;AACA,YAAQ,IAAI,KAAKA,IAAG,IAAI,UAAU,CAAC,KAAK,OAAO,KAAK,EAAE,EAAE;AAGxD,UAAM,aAAa,mBAAmB;AACtC,QAAI,WAAW,WAAW;AACzB,YAAM,cAAc,oBAAoB,IAAIA,IAAG,SAASA,IAAG;AAC3D,cAAQ,IAAI,KAAKA,IAAG,IAAI,UAAU,CAAC,KAAK,YAAY,cAAc,WAAW,SAAS,EAAE,CAAC,EAAE;AAAA,IAC5F;AACA,YAAQ,IAAI;AAEZ,QAAI,oBAAoB,GAAG;AAC1B,cAAQ,IAAIA,IAAG,OAAO,yDAAyD,CAAC;AAChF,cAAQ,IAAI;AAAA,IACb;AAAA,EACD,OAAO;AAEN,YAAQ,IAAI;AACZ,YAAQ,IAAIA,IAAG,KAAK,uBAAuB,CAAC;AAC5C,YAAQ,IAAI;AACZ,YAAQ,IAAI,KAAKA,IAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,KAAK,EAAE;AACnD,YAAQ,IAAI,KAAKA,IAAG,IAAI,UAAU,CAAC,IAAI,KAAK,MAAM,EAAE;AACpD,YAAQ,IAAI;AAEZ,QAAI,OAAO,MAAM,SAAS,qBAAqB,OAAO,MAAM,SAAS,gBAAgB;AACpF,cAAQ,IAAIA,IAAG,OAAO,2DAA2D,CAAC;AAAA,IACnF;AAAA,EACD;AACD;;;AE5DA,OAAOC,SAAQ;AAUf,eAAsB,YAAY,SAAqC;AACtE,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIC,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,SAAS,MAAM,UAAU;AAAA,IAC9B,QAAQ,QAAQ,UAAU;AAAA,IAC1B,OAAO,QAAQ,SAAS;AAAA,EACzB,CAAC;AAED,MAAI,CAAC,OAAO,IAAI;AACf,YAAQ,MAAMA,IAAG,IAAI,UAAU,OAAO,MAAM,OAAO,EAAE,CAAC;AACtD,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,EAAE,MAAM,QAAQ,WAAW,IAAI,OAAO;AAG5C,MAAI,QAAQ,MAAM;AACjB,YAAQ,IAAI,KAAK,UAAU,EAAE,QAAQ,WAAW,GAAG,MAAM,CAAC,CAAC;AAC3D;AAAA,EACD;AAGA,UAAQ,IAAI;AACZ,UAAQ;AAAA,IACPA,IAAG,KAAK,GAAG,QAAQ,UAAU,OAAO,KAAK,WAAW,KAAK,UAAU;AAAA,EACpE;AACA,UAAQ,IAAI;AAEZ,MAAI,OAAO,WAAW,GAAG;AACxB,YAAQ,IAAIA,IAAG,IAAI,oBAAoB,CAAC;AACxC,YAAQ,IAAI;AACZ;AAAA,EACD;AAGA,UAAQ;AAAA,IACP,KAAKA,IAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,OAAO,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,UAAU,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,MAAM,CAAC;AAAA,EAC5G;AACA,UAAQ,IAAIA,IAAG,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;AAGzC,aAAW,SAAS,QAAQ;AAC3B,UAAM,eAAe,MAAM,SAASA,IAAG,KAAK,GAAG,IAAI;AACnD,UAAM,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,EAAE,OAAO,EAAE;AAC1C,UAAM,OAAO,SAAS,MAAM,KAAK,QAAQ,MAAM,KAAK,OAAO,EAAE,EAAE,OAAO,EAAE;AACxE,UAAM,UAAU,SAAS,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE;AACrD,UAAM,OAAO,WAAW,MAAM,IAAI;AAElC,YAAQ,IAAI,GAAG,YAAY,IAAI,EAAE,IAAI,IAAI,IAAI,OAAO,IAAIA,IAAG,IAAI,IAAI,CAAC,EAAE;AAAA,EACvE;AAEA,UAAQ,IAAI;AAEZ,MAAI,WAAW,SAAS;AACvB,YAAQ;AAAA,MACPA,IAAG;AAAA,QACF,aAAa,OAAO,MAAM,OAAO,WAAW,KAAK;AAAA,MAClD;AAAA,IACD;AACA,YAAQ,IAAI;AAAA,EACb;AACD;AAEA,SAAS,SAAS,KAAa,WAA2B;AACzD,MAAI,IAAI,UAAU,UAAW,QAAO;AACpC,SAAO,IAAI,MAAM,GAAG,YAAY,CAAC,IAAI;AACtC;AAEA,SAAS,WAAW,YAA4B;AAC/C,QAAM,OAAO,IAAI,KAAK,UAAU;AAChC,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,SAAS,IAAI,QAAQ,IAAI,KAAK,QAAQ;AAC5C,QAAM,WAAW,KAAK,MAAM,UAAU,MAAO,KAAK,KAAK,GAAG;AAE1D,MAAI,aAAa,GAAG;AACnB,WAAO,KAAK,mBAAmB,SAAS;AAAA,MACvC,MAAM;AAAA,MACN,QAAQ;AAAA,IACT,CAAC;AAAA,EACF;AAEA,MAAI,WAAW,GAAG;AACjB,WAAO,KAAK,mBAAmB,SAAS,EAAE,SAAS,QAAQ,CAAC;AAAA,EAC7D;AAEA,SAAO,KAAK,mBAAmB,SAAS;AAAA,IACvC,OAAO;AAAA,IACP,KAAK;AAAA,EACN,CAAC;AACF;;;ACvGA,OAAOC,SAAQ;AAQf,eAAsB,YAAY,IAAY,SAAqC;AAClF,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIC,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,SAAS,MAAM,SAAS,EAAE;AAEhC,MAAI,CAAC,OAAO,IAAI;AACf,QAAI,OAAO,MAAM,SAAS,aAAa;AACtC,cAAQ,MAAMA,IAAG,IAAI,oBAAoB,EAAE,EAAE,CAAC;AAAA,IAC/C,OAAO;AACN,cAAQ,MAAMA,IAAG,IAAI,UAAU,OAAO,MAAM,OAAO,EAAE,CAAC;AAAA,IACvD;AACA,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,QAAQ,OAAO;AAGrB,MAAI,QAAQ,MAAM;AACjB,YAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAC1C;AAAA,EACD;AAGA,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,KAAK,MAAM,WAAW,cAAc,CAAC;AACpD,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAGA,IAAG,IAAI,OAAO,CAAC,OAAO,cAAc,MAAM,IAAI,CAAC,EAAE;AAChE,UAAQ,IAAI,GAAGA,IAAG,IAAI,KAAK,CAAC,SAAS,MAAM,GAAG,IAAI,aAAa,EAAE,KAAK,IAAI,CAAC,EAAE;AAC7E,UAAQ,IAAI,GAAGA,IAAG,IAAI,OAAO,CAAC,OAAO,eAAe,MAAM,IAAI,CAAC,EAAE;AACjE,UAAQ,IAAI,GAAGA,IAAG,IAAI,KAAK,CAAC,SAAS,MAAM,EAAE,EAAE;AAE/C,MAAI,MAAM,OAAO,SAAS,GAAG;AAC5B,YAAQ,IAAI,GAAGA,IAAG,IAAI,SAAS,CAAC,KAAK,MAAM,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,EAC/D;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;AAClC,UAAQ,IAAI;AAGZ,QAAM,UAAU,MAAM,YAAY,MAAM,QAAQ,MAAM;AACtD,MAAI,SAAS;AAEZ,UAAM,iBAAiB,MAAM,YAAY,UAAU,MAAM,QAAQ,MAAM,OAAO;AAC9E,YAAQ,IAAI,cAAc;AAAA,EAC3B,OAAO;AACN,YAAQ,IAAIA,IAAG,IAAI,cAAc,CAAC;AAAA,EACnC;AACA,UAAQ,IAAI;AACb;AAEA,SAAS,UAAU,MAAsB;AAExC,SAAO,KACL,QAAQ,gBAAgB,IAAI,EAC5B,QAAQ,WAAW,MAAM,EACzB,QAAQ,aAAa,IAAI,EACzB,QAAQ,YAAY,EAAE,EACtB,QAAQ,WAAW,GAAG,EACtB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,UAAU,GAAG,EACrB,QAAQ,WAAW,GAAG,EACtB,KAAK;AACR;AAEA,SAAS,cAAc,MAAgD;AACtE,MAAI,KAAK,MAAM;AACd,WAAO,GAAG,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EACnC;AACA,SAAO,KAAK;AACb;AAEA,SAAS,eAAe,YAA4B;AACnD,QAAM,OAAO,IAAI,KAAK,UAAU;AAChC,SAAO,KAAK,eAAe,SAAS;AAAA,IACnC,SAAS;AAAA,IACT,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EACT,CAAC;AACF;;;AC/FA,OAAOC,SAAQ;AAIf,eAAsB,wBAAuC;AAC5D,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIC,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,SAAS,MAAM,kBAAkB;AAEvC,MAAI,CAAC,OAAO,IAAI;AACf,YAAQ,MAAMA,IAAG,IAAI,UAAU,OAAO,MAAM,OAAO,EAAE,CAAC;AACtD,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,EAAE,YAAY,IAAI,OAAO;AAE/B,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,KAAK,gBAAgB,CAAC;AACrC,UAAQ,IAAI;AACZ,UAAQ,IAAI,KAAKA,IAAG,MAAM,WAAW,WAAW,CAAC,CAAC,OAAO;AACzD,UAAQ,IAAI;AAEZ,MAAI,gBAAgB,GAAG;AACtB,YAAQ,IAAIA,IAAG,IAAI,yBAAyB,CAAC;AAC7C,YAAQ,IAAIA,IAAG,IAAI,kDAAkD,CAAC;AACtE,YAAQ,IAAI;AAAA,EACb;AACD;AAEA,SAAS,WAAW,MAAsB;AACzC,SAAO,KAAK,eAAe;AAC5B;;;ACnCA,OAAOC,SAAQ;AAYf,eAAsB,YAAY,SAAqC;AACtE,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIC,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAGA,MAAI,YAAY,QAAQ;AACxB,MAAI,CAAC,WAAW;AACf,UAAM,eAAe,MAAM,UAAU;AACrC,QAAI,aAAa,MAAM,aAAa,KAAK,UAAU;AAClD,kBAAY,GAAG,aAAa,KAAK,QAAQ;AAAA,IAC1C,OAAO;AACN,YAAM,OAAO,QAAQ;AACrB,UAAI,MAAM,OAAO,SAAS,YAAY,GAAG;AACxC,oBAAY,KAAK;AAAA,MAClB;AAAA,IACD;AAAA,EACD;AAEA,MAAI,CAAC,aAAa,CAAC,UAAU,SAAS,YAAY,GAAG;AACpD,YAAQ,MAAMA,IAAG,IAAI,8BAA8B,CAAC;AACpD,YAAQ,IAAIA,IAAG,IAAI,0CAA0C,CAAC;AAC9D,YAAQ,KAAK,CAAC;AAAA,EACf;AAGA,MAAI,CAAC,QAAQ,IAAI;AAChB,YAAQ,MAAMA,IAAG,IAAI,yCAAyC,CAAC;AAC/D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,MAAI,CAAC,QAAQ,SAAS;AACrB,YAAQ,MAAMA,IAAG,IAAI,2CAA2C,CAAC;AACjE,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,MAAI,CAAC,QAAQ,MAAM;AAClB,YAAQ,MAAMA,IAAG,IAAI,qCAAqC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,WAAW,QAAQ,GAAG,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAE1D,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,KAAK,eAAe,CAAC;AACpC,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAGA,IAAG,IAAI,OAAO,CAAC,OAAO,SAAS,EAAE;AAChD,UAAQ,IAAI,GAAGA,IAAG,IAAI,KAAK,CAAC,SAAS,SAAS,KAAK,IAAI,CAAC,EAAE;AAC1D,UAAQ,IAAI,GAAGA,IAAG,IAAI,UAAU,CAAC,IAAI,QAAQ,OAAO,EAAE;AACtD,UAAQ,IAAI;AAGZ,MAAI,CAAC,QAAQ,aAAa;AACzB,UAAM,gBAAgB,MAAM,eAAe;AAAA,MAC1C;AAAA,MACA;AAAA,IACD,CAAC;AAED,QAAI,cAAc,MAAM,cAAc,KAAK,aAAa,GAAG;AAE1D,YAAM,UAAU,cAAc;AAC9B,cAAQ,IAAIA,IAAG,OAAO,qBAAqB,QAAQ,UAAU,OAAO,CAAC;AACrE,cAAQ,IAAI;AACZ,cAAQ,IAAIA,IAAG,IAAI,oBAAoB,CAAC;AACxC,cAAQ,IAAIA,IAAG,KAAK,QAAQ,OAAO,CAAC;AACpC,cAAQ,IAAI;AACZ,cAAQ,IAAIA,IAAG,IAAI,wDAAwD,CAAC;AAC5E,cAAQ;AAAA,QACPA,IAAG;AAAA,UACF,yBAAyB,QAAQ,EAAE,gBAAgB,QAAQ,OAAO,aAAa,QAAQ,IAAI,oBAAoB,QAAQ,WAAW;AAAA,QACnI;AAAA,MACD;AACA,cAAQ,IAAI;AACZ;AAAA,IACD;AAAA,EACD;AAGA,QAAM,SAAS,MAAM,UAAU;AAAA,IAC9B,IAAI;AAAA,IACJ,SAAS,QAAQ;AAAA,IACjB,MAAM,QAAQ;AAAA,IACd;AAAA,IACA,aAAa,QAAQ;AAAA,EACtB,CAAC;AAED,MAAI,CAAC,OAAO,IAAI;AACf,QAAI,OAAO,MAAM,SAAS,oBAAoB;AAC7C,cAAQ,MAAMA,IAAG,OAAO,sCAAsC,CAAC;AAC/D,cAAQ,IAAIA,IAAG,IAAI,2DAA2D,CAAC;AAAA,IAChF,OAAO;AACN,cAAQ,MAAMA,IAAG,IAAI,UAAU,OAAO,MAAM,OAAO,EAAE,CAAC;AAAA,IACvD;AACA,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,UAAQ,IAAIA,IAAG,MAAM,0BAA0B,CAAC;AAChD,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAGA,IAAG,IAAI,WAAW,CAAC,IAAI,OAAO,KAAK,OAAO,EAAE;AAC3D,MAAI,OAAO,KAAK,WAAW;AAC1B,YAAQ,IAAI,GAAGA,IAAG,IAAI,aAAa,CAAC,IAAI,OAAO,KAAK,SAAS,EAAE;AAAA,EAChE;AACA,UAAQ,IAAI;AACb;;;ACrHA,OAAOC,SAAQ;AAcf,eAAsB,sBAAsB,SAA4C;AACvF,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIC,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,SAAS,MAAM,iBAAiB;AAAA,IACrC,OAAO,QAAQ,SAAS;AAAA,EACzB,CAAC;AAED,MAAI,CAAC,OAAO,IAAI;AACf,YAAQ,MAAMA,IAAG,IAAI,UAAU,OAAO,MAAM,OAAO,EAAE,CAAC;AACtD,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,EAAE,MAAM,QAAQ,WAAW,IAAI,OAAO;AAG5C,MAAI,QAAQ,MAAM;AACjB,YAAQ,IAAI,KAAK,UAAU,EAAE,QAAQ,WAAW,GAAG,MAAM,CAAC,CAAC;AAC3D;AAAA,EACD;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,KAAK,mBAAmB,WAAW,KAAK,oBAAoB,CAAC;AAC5E,UAAQ,IAAI;AAEZ,MAAI,OAAO,WAAW,GAAG;AACxB,YAAQ,IAAIA,IAAG,IAAI,sBAAsB,CAAC;AAC1C,YAAQ,IAAI;AACZ;AAAA,EACD;AAGA,UAAQ;AAAA,IACP,KAAKA,IAAG,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,OAAO,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,UAAU,OAAO,EAAE,CAAC,CAAC,IAAIA,IAAG,IAAI,MAAM,CAAC;AAAA,EAC5G;AACA,UAAQ,IAAIA,IAAG,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;AAGzC,aAAW,SAAS,QAAQ;AAC3B,UAAM,KAAK,MAAM,GAAG,MAAM,GAAG,EAAE,EAAE,OAAO,EAAE;AAC1C,UAAM,OAAOC,UAAS,MAAM,KAAK,QAAQ,MAAM,KAAK,OAAO,EAAE,EAAE,OAAO,EAAE;AACxE,UAAM,UAAUA,UAAS,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE;AACrD,UAAM,OAAOD,IAAG,OAAO,OAAO,MAAM,UAAU,CAAC;AAE/C,YAAQ,IAAI,KAAK,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,EAAE;AAAA,EACjD;AAEA,UAAQ,IAAI;AAEZ,MAAI,WAAW,SAAS;AACvB,YAAQ;AAAA,MACPA,IAAG,IAAI,aAAa,OAAO,MAAM,OAAO,WAAW,KAAK,4BAA4B;AAAA,IACrF;AACA,YAAQ,IAAI;AAAA,EACb;AAEA,UAAQ,IAAIA,IAAG,IAAI,wEAAwE,CAAC;AAC5F,UAAQ,IAAI;AACb;AAMA,eAAsB,mBAAmB,IAAY,SAA4C;AAChG,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAIA,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,SAAS,MAAM,gBAAgB,EAAE;AAEvC,MAAI,CAAC,OAAO,IAAI;AACf,QAAI,OAAO,MAAM,SAAS,aAAa;AACtC,cAAQ,MAAMA,IAAG,IAAI,4BAA4B,EAAE,EAAE,CAAC;AAAA,IACvD,OAAO;AACN,cAAQ,MAAMA,IAAG,IAAI,UAAU,OAAO,MAAM,OAAO,EAAE,CAAC;AAAA,IACvD;AACA,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,QAAQ,OAAO;AAGrB,MAAI,QAAQ,MAAM;AACjB,YAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAC1C;AAAA,EACD;AAGA,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,KAAK,MAAM,WAAW,cAAc,CAAC;AACpD,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAGA,IAAG,IAAI,OAAO,CAAC,OAAOE,eAAc,MAAM,IAAI,CAAC,EAAE;AAChE,UAAQ,IAAI,GAAGF,IAAG,IAAI,OAAO,CAAC,OAAOG,gBAAe,MAAM,SAAS,CAAC,EAAE;AACtE,UAAQ,IAAI,GAAGH,IAAG,IAAI,KAAK,CAAC,SAAS,MAAM,EAAE,EAAE;AAC/C,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,OAAO,qBAAqB,MAAM,UAAU,OAAO,CAAC;AACnE,UAAQ,IAAI;AAEZ,MAAI,MAAM,aAAa;AACtB,YAAQ,IAAIA,IAAG,IAAI,iDAAiD,CAAC;AACrE,YAAQ,IAAIA,IAAG,KAAK,0BAA0B,MAAM,EAAE,4BAA4B,CAAC;AAAA,EACpF,OAAO;AACN,YAAQ,IAAIA,IAAG,IAAI,oCAAoC,CAAC;AAAA,EACzD;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;AAClC,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,IAAI,iDAAiD,CAAC;AACrE,UAAQ,IAAI;AACZ,UAAQ,IAAIC,UAAS,MAAM,YAAY,MAAM,MAAM,GAAG,CAAC;AACvD,UAAQ,IAAI;AACb;AAMA,eAAsB,kBAAkB,IAAY,SAA2C;AAC9F,MAAI,CAAC,gBAAgB,GAAG;AACvB,YAAQ,IAAID,IAAG,OAAO,gBAAgB,CAAC;AACvC,YAAQ,IAAIA,IAAG,IAAI,uCAAuC,CAAC;AAC3D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,MAAI,CAAC,QAAQ,aAAa;AACzB,YAAQ,MAAMA,IAAG,IAAI,yDAAyD,CAAC;AAC/E,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,IAAI,sBAAsB,CAAC;AAE1C,QAAM,SAAS,MAAM,YAAY,IAAI,QAAQ,WAAW;AAExD,MAAI,CAAC,OAAO,IAAI;AACf,QAAI,OAAO,MAAM,SAAS,mBAAmB;AAC5C,cAAQ,MAAMA,IAAG,IAAI,8BAA8B,CAAC;AACpD,cAAQ,IAAIA,IAAG,IAAI,mEAAmE,CAAC;AAAA,IACxF,WAAW,OAAO,MAAM,SAAS,aAAa;AAC7C,cAAQ,MAAMA,IAAG,IAAI,iDAAiD,EAAE,EAAE,CAAC;AAAA,IAC5E,OAAO;AACN,cAAQ,MAAMA,IAAG,IAAI,UAAU,OAAO,MAAM,OAAO,EAAE,CAAC;AAAA,IACvD;AACA,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,MAAM,oCAAoC,CAAC;AAC1D,UAAQ,IAAI;AACZ,UAAQ,IAAI,GAAGA,IAAG,IAAI,WAAW,CAAC,IAAI,OAAO,KAAK,OAAO,EAAE;AAC3D,UAAQ,IAAI,GAAGA,IAAG,IAAI,SAAS,CAAC,MAAM,OAAO,KAAK,MAAM,EAAE;AAC1D,UAAQ,IAAI;AACZ,UAAQ,IAAIA,IAAG,IAAI,wBAAwB,OAAO,KAAK,UAAU,sBAAsB,CAAC;AACxF,UAAQ,IAAI;AACb;AAEA,SAASC,UAAS,KAAa,WAA2B;AACzD,MAAI,IAAI,UAAU,UAAW,QAAO;AACpC,SAAO,IAAI,MAAM,GAAG,YAAY,CAAC,IAAI;AACtC;AAEA,SAASC,eAAc,MAAgD;AACtE,MAAI,KAAK,MAAM;AACd,WAAO,GAAG,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EACnC;AACA,SAAO,KAAK;AACb;AAEA,SAASC,gBAAe,YAA4B;AACnD,QAAM,OAAO,IAAI,KAAK,UAAU;AAChC,SAAO,KAAK,eAAe,SAAS;AAAA,IACnC,SAAS;AAAA,IACT,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EACT,CAAC;AACF;;;AVpLA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACE,KAAK,UAAU,EACf,YAAY,8DAA8D,EAC1E,QAAQ,OAAO;AAGjB,QACE,QAAQ,OAAO,EACf,YAAY,6CAA6C,EACzD,OAAO,YAAY;AAErB,QACE,QAAQ,QAAQ,EAChB,YAAY,0BAA0B,EACtC,OAAO,aAAa;AAEtB,QACE,QAAQ,QAAQ,EAChB,YAAY,iCAAiC,EAC7C,OAAO,aAAa;AAGtB,QACE,QAAQ,MAAM,EACd,YAAY,aAAa,EACzB,OAAO,yBAAyB,wCAAwC,OAAO,EAC/E,OAAO,wBAAwB,4BAA4B,IAAI,EAC/D,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,YAAY;AAC1B,QAAM,YAAY;AAAA,IACjB,QAAQ,QAAQ;AAAA,IAChB,OAAO,SAAS,QAAQ,OAAO,EAAE;AAAA,IACjC,MAAM,QAAQ;AAAA,EACf,CAAC;AACF,CAAC;AAEF,QACE,QAAQ,WAAW,EACnB,YAAY,qBAAqB,EACjC,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,IAAI,YAAY;AAC9B,QAAM,YAAY,IAAI,EAAE,MAAM,QAAQ,KAAK,CAAC;AAC7C,CAAC;AAEF,QACE,QAAQ,MAAM,EACd,YAAY,eAAe,EAC3B,OAAO,qBAAqB,qCAAqC,EACjE,OAAO,2BAA2B,eAAe,EACjD,OAAO,qBAAqB,YAAY,EACxC,OAAO,sBAAsB,iCAAiC,EAC9D,OAAO,yBAAyB,gCAAgC,EAChE,OAAO,OAAO,YAAY;AAC1B,QAAM,YAAY;AAAA,IACjB,IAAI,QAAQ;AAAA,IACZ,SAAS,QAAQ;AAAA,IACjB,MAAM,QAAQ;AAAA,IACd,WAAW,QAAQ;AAAA,IACnB,aAAa,QAAQ;AAAA,EACtB,CAAC;AACF,CAAC;AAGF,IAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,yCAAyC;AAEhG,QACE,QAAQ,SAAS,EACjB,YAAY,sCAAsC,EAClD,OAAO,wBAAwB,4BAA4B,IAAI,EAC/D,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,YAAY;AAC1B,QAAM,sBAAsB;AAAA,IAC3B,OAAO,SAAS,QAAQ,OAAO,EAAE;AAAA,IACjC,MAAM,QAAQ;AAAA,EACf,CAAC;AACF,CAAC;AAEF,QACE,QAAQ,WAAW,EACnB,YAAY,6CAA6C,EACzD,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,IAAI,YAAY;AAC9B,QAAM,mBAAmB,IAAI,EAAE,MAAM,QAAQ,KAAK,CAAC;AACpD,CAAC;AAEF,QACE,QAAQ,UAAU,EAClB,YAAY,yBAAyB,EACrC,eAAe,yBAAyB,yCAAyC,EACjF,OAAO,OAAO,IAAI,YAAY;AAC9B,QAAM,kBAAkB,IAAI,EAAE,aAAa,QAAQ,YAAY,CAAC;AACjE,CAAC;AAGF,IAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,gBAAgB;AAEvE,QACE,QAAQ,SAAS,EACjB,YAAY,qBAAqB,EACjC,OAAO,qBAAqB;AAG9B,QAAQ,OAAO,MAAM;AACpB,UAAQ,IAAI;AACZ,UAAQ,IAAIC,IAAG,KAAK,eAAe,CAAC;AACpC,UAAQ,IAAIA,IAAG,IAAI,8CAA8C,CAAC;AAClE,UAAQ,IAAI;AACZ,UAAQ,WAAW;AACpB,CAAC;AAGD,QAAQ,MAAM;","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/utils/cache.ts","../src/commands/read.ts","../src/commands/search.ts","../src/commands/credits.ts","../src/utils/payment-polling.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\tsearchCommand,\n\tcreditsBalanceCommand,\n\tcreditsHistoryCommand,\n\tcreditsPurchaseCommand,\n\tsendCommand,\n\tinboundDeliveredCommand,\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.3.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.alias(\"ls\")\n\t.description(\"List emails (numbered for quick access)\")\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(\"-p, --page <number>\", \"Page number\", \"1\")\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\tpage: parseInt(options.page, 10),\n\t\t\tjson: options.json,\n\t\t})\n\t})\n\nprogram\n\t.command(\"read <id>\")\n\t.alias(\"r\")\n\t.description(\"Read an email by # (from list) or 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(\"search <query>\")\n\t.alias(\"s\")\n\t.description(\"Search emails by subject, body, or sender\")\n\t.option(\"-l, --limit <number>\", \"Number of results to show\", \"20\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (query, options) => {\n\t\tawait searchCommand(query, {\n\t\t\tlimit: parseInt(options.limit, 10),\n\t\t\tjson: options.json,\n\t\t})\n\t})\n\nprogram\n\t.command(\"send\")\n\t.description(\"Send an email (with Lightning payment)\")\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 preimage for L402\")\n\t.option(\"-w, --wait\", \"Wait for payment confirmation\")\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\twait: options.wait,\n\t\t})\n\t})\n\n// Inbound commands (pending and delivered emails)\nconst inbound = program.command(\"inbound\").description(\"Manage inbound emails (pending and delivered)\")\n\ninbound\n\t.command(\"pending\")\n\t.alias(\"p\")\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(\"delivered\")\n\t.alias(\"d\")\n\t.description(\"List delivered emails (paid by senders)\")\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 inboundDeliveredCommand({\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.alias(\"bal\")\n\t.description(\"Show credit balance\")\n\t.action(creditsBalanceCommand)\n\ncredits\n\t.command(\"history\")\n\t.description(\"Show transaction history\")\n\t.option(\"-l, --limit <number>\", \"Number of transactions to show\", \"20\")\n\t.option(\"-t, --type <type>\", \"Filter by type (topup, email_sent, email_received, refund, bonus)\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (options) => {\n\t\tawait creditsHistoryCommand({\n\t\t\tlimit: parseInt(options.limit, 10),\n\t\t\ttype: options.type,\n\t\t\tjson: options.json,\n\t\t})\n\t})\n\ncredits\n\t.command(\"purchase\")\n\t.alias(\"buy\")\n\t.description(\"Purchase credits with Lightning\")\n\t.option(\"-o, --option <index>\", \"Purchase option index (0-3)\")\n\t.option(\"-w, --wait\", \"Wait for payment confirmation\")\n\t.option(\"--json\", \"Output as JSON\")\n\t.action(async (options) => {\n\t\tawait creditsPurchaseCommand({\n\t\t\toption: options.option !== undefined ? parseInt(options.option, 10) : undefined,\n\t\t\tjson: options.json,\n\t\t\twait: options.wait,\n\t\t})\n\t})\n\n// Default action (no command specified)\nprogram.action(() => {\n\tconsole.log()\n\tconsole.log(pc.bold(\"btc.email CLI\") + 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 ora from \"ora\"\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\tconst spinner = ora(\"Fetching account info...\").start()\n\n\t// Try to get fresh info from API\n\tconst result = await getWhoami()\n\n\tspinner.stop()\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}@btc.email`)\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\") + pc.dim(\" (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// Delivered emails (paid inbound emails)\n\nexport type DeliveredEmail = {\n\tid: string\n\tsubject: string\n\tfrom: { email: string; name?: string }\n\tsnippet: string\n\tdate: string\n}\n\nexport async function getDeliveredEmails(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<DeliveredEmail>>(`/inbound/delivered?${params}`)\n}\n\n// Credit transactions\n\nexport type CreditTransaction = {\n\tid: string\n\tamountSats: number\n\ttransactionType: string\n\tbalanceAfter: number\n\treferenceId?: string\n\tcreatedAt: string\n}\n\nexport async function getCreditTransactions(options: {\n\tlimit?: number\n\toffset?: number\n\ttype?: string\n} = {}) {\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\tif (options.type) params.set(\"type\", options.type)\n\n\treturn apiRequest<PaginatedResponse<CreditTransaction>>(`/credits/transactions?${params}`)\n}\n\n// Credit purchase\n\nexport type CreditPurchaseOption = {\n\tamountSats: number\n\tpriceSats: number\n\tbonusSats: number\n\tlabel: string\n\tdescription: string\n}\n\nexport type CreditPurchaseResult = {\n\tpaymentId: string\n\tinvoice: string\n\tpaymentHash: string\n\tamountSats: number\n\tcreditsToReceive: number\n\tbonusSats: number\n\texpiresAt: string\n}\n\nexport async function purchaseCredits(optionIndex: number) {\n\treturn apiRequest<CreditPurchaseResult>(\"/credits/purchase\", {\n\t\tmethod: \"POST\",\n\t\tbody: JSON.stringify({ optionIndex }),\n\t})\n}\n\n// Check payment status\nexport type PaymentStatusResult = {\n\tpaid: boolean\n\tdelivered?: boolean\n\tstatus?: string\n\tpendingEmailId?: string\n}\n\nexport async function checkPaymentStatus(paymentHash: string): Promise<ApiResponse<PaymentStatusResult>> {\n\t// Payment status endpoint is at /api/lightning/webhook (GET)\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}/lightning/webhook?payment_hash=${paymentHash}`, {\n\t\t\theaders,\n\t\t})\n\n\t\tconst json = (await response.json()) as {\n\t\t\tsuccess: boolean\n\t\t\tpaid?: boolean\n\t\t\tdelivered?: boolean\n\t\t\tstatus?: string\n\t\t\tstate?: string\n\t\t\tpendingEmailId?: string\n\t\t\terror?: { code: string; message: string }\n\t\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 {\n\t\t\tok: true,\n\t\t\tdata: {\n\t\t\t\tpaid: json.paid || false,\n\t\t\t\tdelivered: json.delivered,\n\t\t\t\tstatus: json.status || json.state,\n\t\t\t\tpendingEmailId: json.pendingEmailId,\n\t\t\t},\n\t\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: error instanceof Error ? error.message : \"Network request failed\",\n\t\t\t},\n\t\t}\n\t}\n}\n\n// Get purchase options (hardcoded since they match server)\nexport function getCreditPurchaseOptions(): CreditPurchaseOption[] {\n\treturn [\n\t\t{\n\t\t\tamountSats: 1000,\n\t\t\tpriceSats: 1000,\n\t\t\tbonusSats: 0,\n\t\t\tlabel: \"1,000 sats\",\n\t\t\tdescription: \"Good for ~10 emails\",\n\t\t},\n\t\t{\n\t\t\tamountSats: 5000,\n\t\t\tpriceSats: 4500,\n\t\t\tbonusSats: 500,\n\t\t\tlabel: \"5,000 sats\",\n\t\t\tdescription: \"Good for ~50 emails (+10% bonus)\",\n\t\t},\n\t\t{\n\t\t\tamountSats: 10000,\n\t\t\tpriceSats: 8500,\n\t\t\tbonusSats: 1500,\n\t\t\tlabel: \"10,000 sats\",\n\t\t\tdescription: \"Good for ~100 emails (+15% bonus)\",\n\t\t},\n\t\t{\n\t\t\tamountSats: 50000,\n\t\t\tpriceSats: 40000,\n\t\t\tbonusSats: 10000,\n\t\t\tlabel: \"50,000 sats\",\n\t\t\tdescription: \"Good for ~500 emails (+20% bonus)\",\n\t\t},\n\t]\n}\n","/**\n * List Command\n *\n * Lists emails with pagination, numbering, and caching.\n * Cached list enables number-based access: `btcemail read 3`\n */\n\nimport pc from \"picocolors\"\nimport ora from \"ora\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getEmails, type Email } from \"../api.js\"\nimport { cacheEmailList, type CachedEmail } from \"../utils/cache.js\"\n\nexport type ListOptions = {\n\tfolder?: string\n\tlimit?: number\n\tpage?: 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 folder = options.folder || \"inbox\"\n\tconst limit = options.limit || 20\n\tconst page = options.page || 1\n\tconst offset = (page - 1) * limit\n\n\tconst spinner = ora(\"Loading emails...\").start()\n\n\tconst result = await getEmails({\n\t\tfolder,\n\t\tlimit,\n\t\toffset,\n\t})\n\n\tif (!result.ok) {\n\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\tspinner.stop()\n\n\t// Cache emails for number-based access\n\tconst cachedEmails: CachedEmail[] = emails.map((e) => ({\n\t\tid: e.id,\n\t\tsubject: e.subject,\n\t\tfrom: e.from.name || e.from.email,\n\t}))\n\tcacheEmailList(folder, cachedEmails)\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(pc.bold(`${capitalize(folder)} (${pagination.total} emails)`))\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 with # column\n\tconsole.log(\n\t\t` ${pc.dim(\"#\".padEnd(4))} ${pc.dim(\"From\".padEnd(25))} ${pc.dim(\"Subject\".padEnd(45))} ${pc.dim(\"Date\")}`,\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(85)))\n\n\t// Rows with numbering\n\temails.forEach((email, index) => {\n\t\tconst num = pc.cyan(String(index + 1).padEnd(4))\n\t\tconst unreadMarker = email.unread ? pc.cyan(\"●\") : \" \"\n\t\tconst from = truncate(email.from.name || email.from.email, 23).padEnd(25)\n\t\tconst subject = truncate(email.subject, 43).padEnd(45)\n\t\tconst date = formatDate(email.date)\n\n\t\tconsole.log(`${unreadMarker} ${num}${from} ${subject} ${pc.dim(date)}`)\n\t})\n\n\tconsole.log()\n\n\t// Pagination info\n\tconst totalPages = Math.ceil(pagination.total / limit)\n\tconst currentPage = page\n\n\tif (totalPages > 1) {\n\t\tconsole.log(\n\t\t\tpc.dim(` Page ${currentPage} of ${totalPages} (${emails.length} of ${pagination.total})`),\n\t\t)\n\n\t\tif (currentPage < totalPages) {\n\t\t\tconsole.log(pc.dim(` Next page: btcemail list --page ${currentPage + 1}`))\n\t\t}\n\t\tconsole.log()\n\t}\n\n\t// Hint for reading\n\tconsole.log(pc.dim(\" Read email: btcemail read <#> or btcemail read <id>\"))\n\tconsole.log()\n}\n\nfunction capitalize(str: string): string {\n\treturn str.charAt(0).toUpperCase() + str.slice(1)\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 * Email Cache Utility\n *\n * Caches email lists for number-based selection (btcemail read 3).\n * Cache is per-folder and cleared on each new list command.\n */\n\nimport { config } from \"../config.js\"\n\nexport type CachedEmail = {\n\tid: string\n\tsubject: string\n\tfrom: string\n}\n\nexport type EmailCache = {\n\tfolder: string\n\temails: CachedEmail[]\n\ttimestamp: number\n}\n\nconst CACHE_KEY = \"emailCache\"\nconst CACHE_TTL_MS = 30 * 60 * 1000 // 30 minutes\n\n/**\n * Store email list for number-based access\n */\nexport function cacheEmailList(folder: string, emails: CachedEmail[]): void {\n\tconfig.set(CACHE_KEY, {\n\t\tfolder,\n\t\temails,\n\t\ttimestamp: Date.now(),\n\t})\n}\n\n/**\n * Get cached email list if valid\n */\nexport function getCachedEmailList(folder?: string): EmailCache | null {\n\tconst cache = config.get(CACHE_KEY) as EmailCache | undefined\n\tif (!cache) return null\n\n\t// Check if expired\n\tif (Date.now() - cache.timestamp > CACHE_TTL_MS) {\n\t\tconfig.delete(CACHE_KEY)\n\t\treturn null\n\t}\n\n\t// Check folder match if specified\n\tif (folder && cache.folder !== folder) {\n\t\treturn null\n\t}\n\n\treturn cache\n}\n\n/**\n * Get email ID by index (1-based)\n * Returns null if not found or cache is invalid\n */\nexport function getEmailIdByIndex(index: number): string | null {\n\tconst cache = getCachedEmailList()\n\tif (!cache) return null\n\n\t// Convert to 0-based index\n\tconst idx = index - 1\n\tif (idx < 0 || idx >= cache.emails.length) {\n\t\treturn null\n\t}\n\n\treturn cache.emails[idx].id\n}\n\n/**\n * Check if ID is a number (for index-based access)\n */\nexport function isNumericId(id: string): boolean {\n\treturn /^\\d+$/.test(id)\n}\n\n/**\n * Clear the email cache\n */\nexport function clearEmailCache(): void {\n\tconfig.delete(CACHE_KEY)\n}\n","/**\n * Read Command\n *\n * Display a single email by ID or number (from cached list).\n * Supports: btcemail read 3 (number) or btcemail read abc123 (ID)\n */\n\nimport pc from \"picocolors\"\nimport ora from \"ora\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getEmail, type Email } from \"../api.js\"\nimport { isNumericId, getEmailIdByIndex, getCachedEmailList } from \"../utils/cache.js\"\n\nexport type ReadOptions = {\n\tjson?: boolean\n}\n\nexport async function readCommand(idOrNumber: 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\tlet emailId = idOrNumber\n\n\t// Check if this is a number reference\n\tif (isNumericId(idOrNumber)) {\n\t\tconst index = parseInt(idOrNumber, 10)\n\t\tconst cachedId = getEmailIdByIndex(index)\n\n\t\tif (cachedId) {\n\t\t\temailId = cachedId\n\t\t} else {\n\t\t\t// Check if cache exists but index is out of range\n\t\t\tconst cache = getCachedEmailList()\n\t\t\tif (cache) {\n\t\t\t\tconsole.error(pc.red(`Email #${index} not found in list.`))\n\t\t\t\tconsole.log(pc.dim(`List has ${cache.emails.length} emails. Run 'btcemail list' to refresh.`))\n\t\t\t} else {\n\t\t\t\tconsole.error(pc.red(`No email list cached.`))\n\t\t\t\tconsole.log(pc.dim(`Run 'btcemail list' first, then use 'btcemail read <#>'.`))\n\t\t\t}\n\t\t\tprocess.exit(1)\n\t\t}\n\t}\n\n\tconst spinner = ora(\"Loading email...\").start()\n\n\tconst result = await getEmail(emailId)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"NOT_FOUND\") {\n\t\t\tspinner.fail(`Email not found: ${emailId}`)\n\t\t} else {\n\t\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.stop()\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 * Search Command\n *\n * Searches emails by subject, body, or sender.\n */\n\nimport pc from \"picocolors\"\nimport ora from \"ora\"\nimport { isAuthenticated } from \"../config.js\"\nimport { getEmails, type Email } from \"../api.js\"\nimport { cacheEmailList, type CachedEmail } from \"../utils/cache.js\"\n\nexport type SearchOptions = {\n\tlimit?: number\n\tjson?: boolean\n}\n\nexport async function searchCommand(query: string, options: SearchOptions): 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 (!query || query.trim().length === 0) {\n\t\tconsole.error(pc.red(\"Error: Search query is required\"))\n\t\tprocess.exit(1)\n\t}\n\n\tconst spinner = ora(`Searching for \"${query}\"...`).start()\n\n\tconst result = await getEmails({\n\t\tsearch: query.trim(),\n\t\tlimit: options.limit || 20,\n\t})\n\n\tif (!result.ok) {\n\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\tspinner.stop()\n\n\t// Cache results for number-based access\n\tconst cachedEmails: CachedEmail[] = emails.map((e) => ({\n\t\tid: e.id,\n\t\tsubject: e.subject,\n\t\tfrom: e.from.name || e.from.email,\n\t}))\n\tcacheEmailList(\"search\", cachedEmails)\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify({ query, emails, pagination }, null, 2))\n\t\treturn\n\t}\n\n\t// Table output\n\tconsole.log()\n\tconsole.log(pc.bold(`Search: \"${query}\" (${pagination.total} found)`))\n\tconsole.log()\n\n\tif (emails.length === 0) {\n\t\tconsole.log(pc.dim(\" No emails found matching your search.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Header with # column\n\tconsole.log(\n\t\t` ${pc.dim(\"#\".padEnd(4))} ${pc.dim(\"From\".padEnd(25))} ${pc.dim(\"Subject\".padEnd(45))} ${pc.dim(\"Date\")}`,\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(85)))\n\n\t// Rows with numbering\n\temails.forEach((email, index) => {\n\t\tconst num = pc.cyan(String(index + 1).padEnd(4))\n\t\tconst unreadMarker = email.unread ? pc.cyan(\"●\") : \" \"\n\t\tconst from = truncate(email.from.name || email.from.email, 23).padEnd(25)\n\t\tconst subject = truncate(email.subject, 43).padEnd(45)\n\t\tconst date = formatDate(email.date)\n\n\t\tconsole.log(`${unreadMarker} ${num}${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\tconsole.log(pc.dim(\" Read email: btcemail read <#> or btcemail read <id>\"))\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 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 * Credits Command\n *\n * Shows credit balance, transaction history, and purchase options.\n */\n\nimport pc from \"picocolors\"\nimport ora from \"ora\"\nimport qrcode from \"qrcode-terminal\"\nimport { isAuthenticated } from \"../config.js\"\nimport {\n\tgetCreditsBalance,\n\tgetCreditTransactions,\n\tpurchaseCredits,\n\tgetCreditPurchaseOptions,\n\tcheckPaymentStatus,\n} from \"../api.js\"\nimport { pollForPayment } from \"../utils/payment-polling.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 spinner = ora(\"Fetching balance...\").start()\n\n\tconst result = await getCreditsBalance()\n\n\tif (!result.ok) {\n\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.stop()\n\n\tconst { balanceSats, lifetimePurchasedSats, lifetimeSpentSats } = 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 (lifetimePurchasedSats > 0 || lifetimeSpentSats > 0) {\n\t\tconsole.log(pc.dim(` Purchased: ${formatSats(lifetimePurchasedSats)} sats`))\n\t\tconsole.log(pc.dim(` Spent: ${formatSats(lifetimeSpentSats)} sats`))\n\t\tconsole.log()\n\t}\n\n\tif (balanceSats === 0) {\n\t\tconsole.log(pc.dim(\" No credits available.\"))\n\t\tconsole.log(pc.dim(\" Run `btcemail credits purchase` to buy credits.\"))\n\t\tconsole.log()\n\t}\n}\n\nexport type CreditsHistoryOptions = {\n\tlimit?: number\n\ttype?: string\n\tjson?: boolean\n}\n\nexport async function creditsHistoryCommand(options: CreditsHistoryOptions): 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 spinner = ora(\"Loading transaction history...\").start()\n\n\tconst result = await getCreditTransactions({\n\t\tlimit: options.limit || 20,\n\t\ttype: options.type,\n\t})\n\n\tif (!result.ok) {\n\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: transactions, pagination } = result.data\n\n\tspinner.stop()\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify({ transactions, pagination }, null, 2))\n\t\treturn\n\t}\n\n\t// Table output\n\tconsole.log()\n\tconsole.log(pc.bold(\"Transaction History\"))\n\tconsole.log()\n\n\tif (transactions.length === 0) {\n\t\tconsole.log(pc.dim(\" No transactions found.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Header\n\tconsole.log(\n\t\t` ${pc.dim(\"Date\".padEnd(12))} ${pc.dim(\"Type\".padEnd(15))} ${pc.dim(\"Amount\".padEnd(12))} ${pc.dim(\"Balance\")}`,\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(55)))\n\n\t// Rows\n\tfor (const tx of transactions) {\n\t\tconst date = formatDate(tx.createdAt)\n\t\tconst type = formatTransactionType(tx.transactionType).padEnd(15)\n\t\tconst amount = formatAmount(tx.amountSats).padEnd(12)\n\t\tconst balance = formatSats(tx.balanceAfter)\n\n\t\tconsole.log(` ${date.padEnd(12)} ${type} ${amount} ${pc.dim(balance)}`)\n\t}\n\n\tconsole.log()\n\n\tif (pagination.hasMore) {\n\t\tconsole.log(pc.dim(` Use --limit to see more transactions.`))\n\t\tconsole.log()\n\t}\n}\n\nexport type CreditsPurchaseOptions = {\n\toption?: number\n\tjson?: boolean\n\twait?: boolean\n}\n\nexport async function creditsPurchaseCommand(options: CreditsPurchaseOptions): 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 purchaseOptions = getCreditPurchaseOptions()\n\n\t// If no option specified, show available options\n\tif (options.option === undefined) {\n\t\tconsole.log()\n\t\tconsole.log(pc.bold(\"Purchase Options\"))\n\t\tconsole.log()\n\n\t\tpurchaseOptions.forEach((opt, index) => {\n\t\t\tconsole.log(` ${pc.cyan(`[${index}]`)} ${opt.label}`)\n\t\t\tconsole.log(` ${pc.dim(opt.description)}`)\n\t\t\tconsole.log(` ${pc.dim(`Price: ${formatSats(opt.priceSats)} sats`)}`)\n\t\t\tif (opt.bonusSats > 0) {\n\t\t\t\tconsole.log(` ${pc.green(`+${formatSats(opt.bonusSats)} bonus sats`)}`)\n\t\t\t}\n\t\t\tconsole.log()\n\t\t})\n\n\t\tconsole.log(pc.dim(\" Usage: btcemail credits purchase --option <index>\"))\n\t\tconsole.log(pc.dim(\" Add --wait to wait for payment confirmation.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Validate option index\n\tif (options.option < 0 || options.option >= purchaseOptions.length) {\n\t\tconsole.error(pc.red(`Error: Invalid option. Choose 0-${purchaseOptions.length - 1}.`))\n\t\tprocess.exit(1)\n\t}\n\n\tconst selectedOption = purchaseOptions[options.option]\n\n\tconst spinner = ora(\"Creating invoice...\").start()\n\n\tconst result = await purchaseCredits(options.option)\n\n\tif (!result.ok) {\n\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.stop()\n\n\tconst purchase = result.data\n\n\t// JSON output mode\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(purchase, null, 2))\n\t\treturn\n\t}\n\n\tconsole.log()\n\tconsole.log(pc.bold(\"Lightning Invoice\"))\n\tconsole.log()\n\tconsole.log(` ${pc.dim(\"Amount:\")} ${formatSats(purchase.amountSats)} sats`)\n\tconsole.log(` ${pc.dim(\"Credits:\")} ${formatSats(purchase.creditsToReceive)} sats`)\n\tif (purchase.bonusSats > 0) {\n\t\tconsole.log(` ${pc.dim(\"Bonus:\")} ${pc.green(`+${formatSats(purchase.bonusSats)} sats`)}`)\n\t}\n\tconsole.log()\n\n\t// Display QR code\n\tconsole.log(pc.bold(\"Scan to pay:\"))\n\tconsole.log()\n\tqrcode.generate(purchase.invoice, { small: true }, (qr) => {\n\t\t// Indent the QR code\n\t\tconst indentedQr = qr\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => \" \" + line)\n\t\t\t.join(\"\\n\")\n\t\tconsole.log(indentedQr)\n\t})\n\tconsole.log()\n\n\tconsole.log(pc.bold(\"Invoice:\"))\n\tconsole.log()\n\tconsole.log(` ${purchase.invoice}`)\n\tconsole.log()\n\tconsole.log(pc.dim(` Payment hash: ${purchase.paymentHash}`))\n\tconsole.log(pc.dim(` Expires: ${new Date(purchase.expiresAt).toLocaleString()}`))\n\tconsole.log()\n\n\t// If --wait flag is set, poll for payment\n\tif (options.wait) {\n\t\tconsole.log()\n\t\tconst status = await pollForPayment({\n\t\t\tpaymentHash: purchase.paymentHash,\n\t\t\tcheckFn: async (hash) => {\n\t\t\t\tconst result = await checkPaymentStatus(hash)\n\t\t\t\tif (result.ok) {\n\t\t\t\t\treturn { paid: result.data.paid }\n\t\t\t\t}\n\t\t\t\treturn { paid: false }\n\t\t\t},\n\t\t\tonPaid: async () => {\n\t\t\t\t// Check updated balance\n\t\t\t\tconst balanceResult = await getCreditsBalance()\n\t\t\t\tif (balanceResult.ok) {\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(`${pc.dim(\"New balance:\")} ${pc.green(formatSats(balanceResult.data.balanceSats))} sats`)\n\t\t\t\t}\n\t\t\t},\n\t\t})\n\n\t\tif (!status.paid) {\n\t\t\tconsole.log(pc.dim(\" You can still pay the invoice and credits will be added.\"))\n\t\t}\n\t\tconsole.log()\n\t} else {\n\t\tconsole.log(pc.dim(\" Scan the QR code or copy the invoice above to pay.\"))\n\t\tconsole.log(pc.dim(\" Use --wait to wait for payment confirmation.\"))\n\t\tconsole.log()\n\t}\n}\n\nfunction formatSats(sats: number): string {\n\treturn sats.toLocaleString()\n}\n\nfunction formatAmount(sats: number): string {\n\tif (sats >= 0) {\n\t\treturn pc.green(`+${formatSats(sats)}`)\n\t}\n\treturn pc.red(formatSats(sats))\n}\n\nfunction formatTransactionType(type: string): string {\n\tconst types: Record<string, string> = {\n\t\ttopup: \"Top-up\",\n\t\temail_sent: \"Email Sent\",\n\t\temail_received: \"Email Received\",\n\t\trefund: \"Refund\",\n\t\tbonus: \"Bonus\",\n\t}\n\treturn types[type] || type\n}\n\nfunction formatDate(dateString: string): string {\n\tconst date = new Date(dateString)\n\treturn date.toLocaleDateString(\"en-US\", {\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t})\n}\n","/**\n * Payment Polling Utility\n *\n * Polls for payment status and shows a progress indicator.\n */\n\nimport pc from \"picocolors\"\n\nexport type PaymentStatus = {\n\tpaid: boolean\n\tdelivered?: boolean\n\tstatus?: string\n}\n\nexport type PollOptions = {\n\tpaymentHash: string\n\tcheckFn: (paymentHash: string) => Promise<PaymentStatus>\n\tmaxAttempts?: number\n\tintervalMs?: number\n\tonPaid?: () => void\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"]\n\n/**\n * Poll for payment status with a spinner\n */\nexport async function pollForPayment(options: PollOptions): Promise<PaymentStatus> {\n\tconst { paymentHash, checkFn, maxAttempts = 120, intervalMs = 2500, onPaid } = options\n\n\tlet frame = 0\n\tlet attempts = 0\n\n\t// Print initial status\n\tprocess.stdout.write(`${pc.cyan(SPINNER_FRAMES[0])} Waiting for payment...`)\n\n\twhile (attempts < maxAttempts) {\n\t\ttry {\n\t\t\tconst status = await checkFn(paymentHash)\n\n\t\t\tif (status.paid) {\n\t\t\t\t// Clear the spinner line\n\t\t\t\tprocess.stdout.write(\"\\r\" + \" \".repeat(50) + \"\\r\")\n\t\t\t\tconsole.log(pc.green(\"✓\") + \" Payment received!\")\n\t\t\t\tif (onPaid) onPaid()\n\t\t\t\treturn status\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore errors, keep polling\n\t\t}\n\n\t\t// Update spinner\n\t\tframe = (frame + 1) % SPINNER_FRAMES.length\n\t\tconst timeLeft = Math.ceil(((maxAttempts - attempts) * intervalMs) / 1000 / 60)\n\t\tprocess.stdout.write(\n\t\t\t`\\r${pc.cyan(SPINNER_FRAMES[frame])} Waiting for payment... (${timeLeft}m remaining)`\n\t\t)\n\n\t\t// Wait before next check\n\t\tawait sleep(intervalMs)\n\t\tattempts++\n\t}\n\n\t// Clear the spinner line\n\tprocess.stdout.write(\"\\r\" + \" \".repeat(60) + \"\\r\")\n\tconsole.log(pc.yellow(\"⚠\") + \" Timed out waiting for payment.\")\n\n\treturn { paid: false }\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Create a simple progress indicator (non-polling)\n */\nexport function createSpinner(message: string): { stop: (success?: boolean) => void } {\n\tlet frame = 0\n\tlet running = true\n\n\tconst interval = setInterval(() => {\n\t\tif (!running) return\n\t\tframe = (frame + 1) % SPINNER_FRAMES.length\n\t\tprocess.stdout.write(`\\r${pc.cyan(SPINNER_FRAMES[frame])} ${message}`)\n\t}, 80)\n\n\treturn {\n\t\tstop: (success = true) => {\n\t\t\trunning = false\n\t\t\tclearInterval(interval)\n\t\t\tprocess.stdout.write(\"\\r\" + \" \".repeat(message.length + 5) + \"\\r\")\n\t\t\tif (success) {\n\t\t\t\tconsole.log(pc.green(\"✓\") + \" \" + message)\n\t\t\t} else {\n\t\t\t\tconsole.log(pc.red(\"✗\") + \" \" + message)\n\t\t\t}\n\t\t},\n\t}\n}\n","/**\n * Send Command\n *\n * Compose and send an email with L402 payment flow.\n * Supports --wait to poll for payment confirmation.\n */\n\nimport pc from \"picocolors\"\nimport ora from \"ora\"\nimport qrcode from \"qrcode-terminal\"\nimport { isAuthenticated, getAuth } from \"../config.js\"\nimport { sendEmail, getL402Invoice, getWhoami, checkPaymentStatus } from \"../api.js\"\nimport { pollForPayment } from \"../utils/payment-polling.js\"\n\nexport type SendOptions = {\n\tto?: string\n\tsubject?: string\n\tbody?: string\n\tfromEmail?: string\n\tpaymentHash?: string\n\twait?: boolean\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 spinner = ora(\"Fetching account info...\").start()\n\t\tconst whoamiResult = await getWhoami()\n\t\tspinner.stop()\n\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 spinner = ora(\"Getting invoice...\").start()\n\t\tconst invoiceResult = await getL402Invoice({\n\t\t\tfromEmail,\n\t\t\ttoEmails,\n\t\t})\n\t\tspinner.stop()\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\n\t\t\t// Display QR code\n\t\t\tconsole.log(pc.bold(\"Scan to pay:\"))\n\t\t\tconsole.log()\n\t\t\tqrcode.generate(invoice.invoice, { small: true }, (qr) => {\n\t\t\t\tconst indentedQr = qr\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.map((line) => \" \" + line)\n\t\t\t\t\t.join(\"\\n\")\n\t\t\t\tconsole.log(indentedQr)\n\t\t\t})\n\t\t\tconsole.log()\n\n\t\t\tconsole.log(pc.dim(\"Lightning Invoice:\"))\n\t\t\tconsole.log(pc.cyan(invoice.invoice))\n\t\t\tconsole.log()\n\n\t\t\t// If --wait flag is set, poll for payment\n\t\t\tif (options.wait) {\n\t\t\t\tconst status = await pollForPayment({\n\t\t\t\t\tpaymentHash: invoice.paymentHash,\n\t\t\t\t\tcheckFn: async (hash) => {\n\t\t\t\t\t\tconst result = await checkPaymentStatus(hash)\n\t\t\t\t\t\tif (result.ok) {\n\t\t\t\t\t\t\treturn { paid: result.data.paid }\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn { paid: false }\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\tif (status.paid) {\n\t\t\t\t\t// Payment received, now send the email\n\t\t\t\t\tconst sendSpinner = ora(\"Sending email...\").start()\n\t\t\t\t\tconst result = await sendEmail({\n\t\t\t\t\t\tto: toEmails,\n\t\t\t\t\t\tsubject: options.subject,\n\t\t\t\t\t\tbody: options.body,\n\t\t\t\t\t\tfromEmail,\n\t\t\t\t\t\tpaymentHash: invoice.paymentHash,\n\t\t\t\t\t})\n\n\t\t\t\t\tif (!result.ok) {\n\t\t\t\t\t\tsendSpinner.fail(`Error: ${result.error.message}`)\n\t\t\t\t\t\tprocess.exit(1)\n\t\t\t\t\t}\n\n\t\t\t\t\tsendSpinner.succeed(\"Email sent!\")\n\t\t\t\t\tconsole.log()\n\t\t\t\t\tconsole.log(`${pc.dim(\"Email ID:\")} ${result.data.emailId}`)\n\t\t\t\t\tif (result.data.messageId) {\n\t\t\t\t\t\tconsole.log(`${pc.dim(\"Message ID:\")} ${result.data.messageId}`)\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log()\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log(pc.dim(\"Payment not confirmed. You can still pay and resend with --payment-hash.\"))\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\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\tconsole.log(pc.dim(\"Or use --wait to automatically wait for payment.\"))\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 spinner = ora(\"Sending email...\").start()\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\tspinner.fail(\"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\tspinner.fail(`Error: ${result.error.message}`)\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.succeed(\"Email sent!\")\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 ora from \"ora\"\nimport { isAuthenticated } from \"../config.js\"\nimport {\n\tgetPendingEmails,\n\tgetPendingEmail,\n\tpayForEmail,\n\tgetDeliveredEmails,\n\ttype PendingEmail,\n} from \"../api.js\"\n\nexport type InboundListOptions = {\n\tlimit?: number\n\tjson?: boolean\n}\n\nexport async function inboundDeliveredCommand(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 spinner = ora(\"Loading delivered emails...\").start()\n\n\tconst result = await getDeliveredEmails({\n\t\tlimit: options.limit || 20,\n\t})\n\n\tif (!result.ok) {\n\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\tspinner.stop()\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(`Delivered (${pagination.total} paid emails received)`))\n\tconsole.log()\n\n\tif (emails.length === 0) {\n\t\tconsole.log(pc.dim(\" No delivered emails yet.\"))\n\t\tconsole.log()\n\t\treturn\n\t}\n\n\t// Header\n\tconsole.log(\n\t\t` ${pc.dim(\"#\".padEnd(4))} ${pc.dim(\"From\".padEnd(28))} ${pc.dim(\"Subject\".padEnd(40))} ${pc.dim(\"Date\")}`\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(85)))\n\n\t// Rows\n\temails.forEach((email, index) => {\n\t\tconst num = pc.cyan(String(index + 1).padEnd(4))\n\t\tconst from = truncate(email.from.name || email.from.email, 26).padEnd(28)\n\t\tconst subject = truncate(email.subject, 38).padEnd(40)\n\t\tconst date = formatDate(email.date)\n\n\t\tconsole.log(` ${num}${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(` 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(\" Read email: btcemail read <id>\"))\n\tconsole.log()\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 spinner = ora(\"Loading pending emails...\").start()\n\n\tconst result = await getPendingEmails({\n\t\tlimit: options.limit || 20,\n\t})\n\n\tif (!result.ok) {\n\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\tprocess.exit(1)\n\t}\n\n\tconst { data: emails, pagination } = result.data\n\n\tspinner.stop()\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 (${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(\"#\".padEnd(4))} ${pc.dim(\"From\".padEnd(28))} ${pc.dim(\"Subject\".padEnd(35))} ${pc.dim(\"Sats\")}`\n\t)\n\tconsole.log(pc.dim(\" \" + \"-\".repeat(80)))\n\n\t// Rows\n\temails.forEach((email, index) => {\n\t\tconst num = pc.cyan(String(index + 1).padEnd(4))\n\t\tconst from = truncate(email.from.name || email.from.email, 26).padEnd(28)\n\t\tconst subject = truncate(email.subject, 33).padEnd(35)\n\t\tconst sats = pc.yellow(String(email.amountSats))\n\n\t\tconsole.log(` ${num}${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(\" View details: btcemail inbound view <id>\"))\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 spinner = ora(\"Loading email details...\").start()\n\n\tconst result = await getPendingEmail(id)\n\n\tif (!result.ok) {\n\t\tif (result.error.code === \"NOT_FOUND\") {\n\t\t\tspinner.fail(`Pending email not found: ${id}`)\n\t\t} else {\n\t\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.stop()\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\tconst spinner = ora(\"Verifying payment...\").start()\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\tspinner.fail(\"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\tspinner.fail(`Pending email not found or already delivered: ${id}`)\n\t\t} else {\n\t\t\tspinner.fail(`Error: ${result.error.message}`)\n\t\t}\n\t\tprocess.exit(1)\n\t}\n\n\tspinner.succeed(\"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(`Read email: btcemail read ${result.data.emailId}`))\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\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"],"mappings":"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","names":["pc","pc","pc","pc","ora","pc","ora","pc","ora","pc","ora","pc","ora","pc","ora","pc","ora","pc","ora","truncate","formatDate","pc","ora","pc","sleep","pc","ora","formatDate","result","pc","ora","qrcode","pc","spinner","ora","qrcode","result","pc","ora","pc","ora","truncate","formatDate","formatAddress","formatFullDate","pc"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btcemail/cli",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "btc.email CLI - Spam-free email powered by Bitcoin Lightning",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,10 +42,12 @@
42
42
  "conf": "^13.0.1",
43
43
  "open": "^10.1.0",
44
44
  "ora": "^8.1.1",
45
- "picocolors": "^1.1.1"
45
+ "picocolors": "^1.1.1",
46
+ "qrcode-terminal": "0.12.0"
46
47
  },
47
48
  "devDependencies": {
48
49
  "@types/node": "^22.10.2",
50
+ "@types/qrcode-terminal": "0.12.2",
49
51
  "tsup": "^8.3.5",
50
52
  "typescript": "^5.7.2"
51
53
  },