UNPKG

vana-cli

Version:

[ALPHA] Vana CLI for interacting with the Vana L1 network and related services - experimental software

174 lines (158 loc) 25.5 kB
#!/usr/bin/env node import{Cli as ge,Builtins as ie}from"clipanion";import{Command as z,Option as k}from"clipanion";import{ethers as re}from"ethers";var $=class{constructor(e){this.baseUrl=e;this.baseUrl=e}async getRefinerIngestionStats(e,t){try{let n=t.startsWith("0x")?t:`0x${t}`,r=new re.Wallet(n),o=e.toString(),s=await r.signMessage(o),u=`${this.baseUrl}/stats/refiner/${e}`,c=await fetch(u,{method:"GET",headers:{"X-Refiner-Signature":s,"Content-Type":"application/json"}});if(!c.ok){let h=await c.text(),l=`HTTP ${c.status}: ${c.statusText}`;try{let S=JSON.parse(h);l=S.detail||S.message||l}catch{l=h||l}throw new Error(l)}return await c.json()}catch(n){throw n instanceof Error?n:new Error(`Failed to get refiner ingestion stats: ${String(n)}`)}}};import{ethers as oe}from"ethers";var I=class{constructor(e){this.baseUrl=e;this.baseUrl=e}async getRefinerExecutionStats(e,t){try{let n=t.startsWith("0x")?t:`0x${t}`,r=new oe.Wallet(n),o=e.toString(),s=await r.signMessage(o),u=`${this.baseUrl}/stats/refiner/${e}`,c=await fetch(u,{method:"GET",headers:{"X-Refiner-Signature":s,"Content-Type":"application/json"}});if(!c.ok){let h=await c.text(),l=`HTTP ${c.status}: ${c.statusText}`;try{let S=JSON.parse(h);l=S.detail||S.message||l}catch{l=h||l}throw new Error(l)}return await c.json()}catch(n){throw n instanceof Error?n:new Error(`Failed to get refiner execution stats: ${String(n)}`)}}};import{promises as b}from"fs";import{join as V,dirname as se}from"path";import{homedir as ae}from"os";import F from"keytar";var P={network:"moksha",rpc_endpoint:"https://rpc.moksha.vana.org",query_engine_endpoint:"https://54531900daaa8493797db8d07d6bfbfc77f75b4b-8000.dstack-prod5.phala.network",refinement_service_endpoint:"https://a7df0ae43df690b889c1201546d7058ceb04d21b-8000.dstack-prod5.phala.network"},L="vana",D=V(ae(),".vana"),E=V(D,"cli.config.toml"),y=class i{static instance;unprotectedConfig=null;constructor(){}static getInstance(){return i.instance||(i.instance=new i),i.instance}async initialize(){try{await b.mkdir(D,{recursive:!0});try{await b.access(E)}catch{await this.writeUnprotectedConfig(P)}}catch(e){throw new Error(`Failed to initialize config: ${e instanceof Error?e.message:String(e)}`)}}async getConfig(){let e=await this.getUnprotectedConfig(),t=await this.getProtectedConfig();return{...e,...t}}async getUnprotectedConfig(){if(this.unprotectedConfig)return this.unprotectedConfig;try{let e=await b.readFile(E,"utf-8");return this.unprotectedConfig=this.parseToml(e),this.unprotectedConfig}catch{return this.unprotectedConfig={...P},this.unprotectedConfig}}async getProtectedConfig(){try{return{wallet_private_key:await F.getPassword(L,"wallet_private_key")||void 0}}catch{return{}}}async setConfig(e,t){this.isProtectedKey(e)?await this.setProtectedConfig(e,t):await this.setUnprotectedConfig(e,t)}async getConfigValue(e){return(await this.getConfig())[e]}async setUnprotectedConfig(e,t){let n=await this.getUnprotectedConfig();if(e==="network"&&!["vana","moksha"].includes(t))throw new Error(`Invalid network value: ${t}. Must be 'vana' or 'moksha'`);n[e]=t,await this.writeUnprotectedConfig(n),this.unprotectedConfig=n}async setProtectedConfig(e,t){try{await F.setPassword(L,e,t)}catch(n){throw new Error(`Failed to store ${e} in keyring: ${n instanceof Error?n.message:String(n)}`)}}async writeUnprotectedConfig(e){let t=this.generateToml(e);try{await b.mkdir(se(E),{recursive:!0}),await b.writeFile(E,t,"utf-8")}catch(n){throw new Error(`Failed to write config file: ${n instanceof Error?n.message:String(n)}`)}}isProtectedKey(e){return e==="wallet_private_key"}parseToml(e){let t={},n=e.split(` `);for(let r of n){let o=r.trim();if(o&&!o.startsWith("#")){let[s,...u]=o.split("=");if(s&&u.length>0){let c=s.trim(),h=u.join("=").trim().replace(/['"]/g,"");(c==="network"||c==="rpc_endpoint"||c==="query_engine_endpoint")&&(t[c]=h)}}}return{...P,...t}}generateToml(e){return`# Vana CLI Configuration # This file stores unprotected configuration values # Secrets like private keys are stored securely in the OS keyring network = "${e.network}" rpc_endpoint = "${e.rpc_endpoint}" query_engine_endpoint = "${e.query_engine_endpoint}" `}getConfigKeys(){return{unprotected:["network","rpc_endpoint","query_engine_endpoint"],protected:["wallet_private_key"]}}async reset(){await this.writeUnprotectedConfig(P),this.unprotectedConfig=null;try{await F.deletePassword(L,"wallet_private_key")}catch{}}getConfigPath(){return E}};import p from"chalk";function m(i,e){return i==="wallet_private_key"&&e?e.length>10?e.substring(0,6)+"..."+e.substring(e.length-4):e.substring(0,4)+"..."+e.substring(e.length-2):e}function R(i){return["wallet_private_key","private_key","secret","password","token"].some(t=>i.toLowerCase().includes(t))}function a(i,e,t={}){let{maskSensitive:n=!1,indent:r=2}=t,o=" ".repeat(r);if(e===void 0)return`${o}${p.cyan(i)}: ${p.gray("(not set)")}`;let s=n&&R(i)?m(i,e):e;return`${o}${p.cyan(i)}: ${s}`}function M(i,e){let t=p.blue.bold(` ${i}:`);return e&&(t+=p.gray(` (${e})`)),t}function f(i){return p.bold(i)+` `+"\u2500".repeat(Math.min(i.length,50))}function J(i){return p.green(`\u2713 ${i}`)}function K(i){return p.red(`\u2717 ${i}`)}function Q(i){return p.yellow(`\u26A0 ${i}`)}function B(i){return p.blue(`\u2139 ${i}`)}function H(i){return p.gray(i)}function ce(i){return p.gray(` $ ${i}`)}var g={configSection(i,e,t,n={}){let{maskSensitive:r=!1,showEmpty:o=!0}=n,s=M(i,e)+` `;for(let[u,c]of Object.entries(t))(c!==void 0||o)&&(s+=a(u,c,{maskSensitive:r})+` `);return s},examples(i,e){let t=M(i)+` `;for(let n of e)t+=ce(n)+` `;return t},nextSteps(i){let e=M("Next steps")+` `;for(let t of i)e+=H(` \u2022 ${t}`)+` `;return e},troubleshooting(i,e){let t=M(i)+` `;for(let n of e)t+=H(` \u2022 ${n}`)+` `;return t}};var N=class{constructor(e){this.context=e}success(e){this.context.stdout.write(J(e)+` `)}error(e){this.context.stderr.write(K(e)+` `)}warning(e){this.context.stderr.write(Q(e)+` `)}info(e){this.context.stdout.write(B(e)+` `)}log(e){this.context.stdout.write(e+` `)}write(e){this.context.stdout.write(e)}},d={configNotFound:i=>`Configuration key '${i}' not found`,invalidValue:(i,e,t)=>`Invalid value '${e}' for '${i}'${t?`. Expected: ${t}`:""}`,missingRequired:i=>`Missing required field: ${i}`,keyringAccess:i=>`Failed to ${i} keyring. Ensure your system keyring is accessible`,fileAccess:(i,e)=>`Failed to ${e} file: ${i}`,networkError:i=>`Network error connecting to: ${i}`,authenticationFailed:i=>`Authentication failed${i?`: ${i}`:""}`,permissionDenied:i=>`Permission denied accessing: ${i}`,unexpectedError:i=>`Unexpected error: ${i instanceof Error?i.message:String(i)}`},_={configSet:(i,e)=>`Set ${i} in ${e}`,configInitialized:()=>"Configuration initialized",configReset:()=>"Configuration reset to defaults",operationComplete:i=>`${i} completed successfully`},G={secretsCleared:()=>"Protected values (like private keys) have been cleared",keyringUnavailable:()=>"OS keyring unavailable, secrets cannot be stored securely",deprecatedOption:(i,e)=>`Option '${i}' is deprecated, use '${e}' instead`,experimentalFeature:i=>`${i} is experimental and may change in future versions`},w={configLocation:i=>`Config file: ${i}`,useSecretsFlag:()=>"Use --secrets to view protected values",interactiveMode:()=>"Interactive mode requires a prompt library like inquirer",nextSteps:{setPrivateKey:()=>"Set your wallet private key: vana config set wallet_private_key 63...",viewConfig:()=>"View all settings: vana config get",viewSecrets:()=>"View with secrets: vana config get --secrets"}};function v(i){return new N({stdout:i.stdout,stderr:i.stderr})}import W from"ora";var fe=["Verify the refiner ID exists","Check your private key is correct","Ensure the API URLs are accessible","Verify you have permission to view this refiner's stats"],U=class extends z{static paths=[["stats","refiner"]];static usage=z.Usage({category:"Stats",description:"Get comprehensive statistics for a specific refiner",details:` Retrieves comprehensive statistics for a refiner from both services: Query Engine Stats: \u2022 File contributions and data rows \u2022 Query execution metrics \u2022 Error breakdowns by type \u2022 Table-specific row counts \u2022 Contributor and timing information Refinement Service Stats: \u2022 Job processing metrics \u2022 Success/failure rates \u2022 Processing times \u2022 Error analysis \u2022 Recent activity Requires cryptographic authentication using your wallet private key. `,examples:[["Get stats for refiner ID 45","vana stats refiner --id 45"],["Get stats with custom endpoints","vana stats refiner --id 45 --query-endpoint https://query-engine.api.com --refine-endpoint https://refine.api.com"],["Get stats with private key override","vana stats refiner --id 45 --private-key 63..."],["Get stats in JSON format","vana stats refiner --id 45 --json"],["Get verbose stats with raw response","vana stats refiner --id 45 --verbose --include-raw"]]});refinerId=k.String("--id,-i",{description:"Refiner ID to get statistics for",required:!0});privateKey=k.String("--private-key,-pk",{description:"Private key for authentication (overrides config)"});queryEndpoint=k.String("--query-endpoint,-qe",{description:"Query Engine API URL (optional if configured via config)"});refineEndpoint=k.String("--refine-endpoint,-re",{description:"Refinement Service API URL (optional if configured via config)"});json=k.Boolean("--json,-j",!1,{description:"Output in JSON format"});verbose=k.Boolean("--verbose,-v",!1,{description:"Show verbose output with additional details"});includeRaw=k.Boolean("--include-raw",!1,{description:"Include raw API responses in output"});async execute(){let e=v(this.context);try{let t=this.validateRefinerId(e);if(t===null)return 1;let{privateKey:n,queryApiUrl:r,refineApiUrl:o}=await this.getConfiguration(e);if(!n)return 1;this.verbose&&this.displayVerboseInfo(e,t,n,r,o);let s=await this.fetchCombinedStats(e,t,n,r,o);return!s.ingestion_stats&&!s.execution_stats?(e.warning("No data found for this refiner in either service"),this.displayNoDataMessage(e,t,s),0):(this.displayResults(e,s),e.success(_.operationComplete("Refiner stats retrieved")),this.verbose&&e.warning("\u26A0\uFE0F Alpha software: Verify all data independently before making decisions"),0)}catch(t){return e.error(d.unexpectedError(t)),e.write(g.troubleshooting("Troubleshooting",fe)),1}}validateRefinerId(e){let t=parseInt(this.refinerId);return isNaN(t)||t<0?(e.error("Invalid refiner ID. Must be a non-negative number."),null):t}async getConfiguration(e){let t=y.getInstance();await t.initialize();let n=this.privateKey;if(!n)try{n=await t.getConfigValue("wallet_private_key")}catch{}if(!n)return e.error("No private key provided."),e.write(g.examples("Set private key with",["vana config set wallet_private_key 63...","or use --private-key option"])),{privateKey:void 0,queryApiUrl:void 0,refineApiUrl:void 0};let r=this.queryEndpoint;if(!r)try{r=await t.getConfigValue("query_engine_endpoint")}catch{}let o=this.refineEndpoint;if(!o)try{o=await t.getConfigValue("refinement_service_endpoint")}catch{}return!r&&!o?(e.error("At least one API endpoint is required (Query Engine or Refinement Service)."),e.write(g.examples("Set API endpoints with",["vana config set query_engine_endpoint https://query-engine.api.com","vana config set refinement_service_endpoint https://refine.api.com","or use --query-endpoint and --refine-endpoint options"])),{privateKey:void 0,queryApiUrl:void 0,refineApiUrl:void 0}):{privateKey:n,queryApiUrl:r,refineApiUrl:o}}displayVerboseInfo(e,t,n,r,o){e.write(f("\u{1F50D} Comprehensive Refiner Statistics")+` `),e.write(a("Refiner ID",t.toString())+` `),e.write(a("Query Engine API",r||"Not configured")+` `),e.write(a("Refinement Service API",o||"Not configured")+` `),e.write(a("Private Key",m("wallet_private_key",n))+` `),e.write(` `)}async fetchCombinedStats(e,t,n,r,o){let s={refiner_id:t,ingestion_stats:void 0,execution_stats:void 0};if(r){let u=W("Fetching ingestion stats from query engine...").start();try{let c=new $(r);s.ingestion_stats=await c.getRefinerIngestionStats(t,n),u.succeed("Ingestion stats retrieved")}catch(c){u.fail("Failed to fetch ingestion stats"),s.ingestion_error=c instanceof Error?c.message:String(c),e.warning(`Query Engine: ${s.ingestion_error}`)}}if(o){let u=W("Fetching execution stats from refinement service...").start();try{let c=new I(o);s.execution_stats=await c.getRefinerExecutionStats(t,n),u.succeed("Execution stats retrieved")}catch(c){u.fail("Failed to fetch execution stats"),s.execution_error=c instanceof Error?c.message:String(c),e.warning(`Refinement Service: ${s.execution_error}`)}}return s}displayNoDataMessage(e,t,n){e.write(f(`\u{1F4CA} Refiner ${t} - No Data Found`)+` `),e.write(`\u{1F50D} Data Availability: `),n.ingestion_error?e.write(` Query Engine: \u274C ${n.ingestion_error} `):n.ingestion_stats?e.write(` Query Engine: \u2705 Connected (no data ingested) `):e.write(` Query Engine: \u26AA Not configured `),n.execution_error?e.write(` Refinement Service: \u274C ${n.execution_error} `):n.execution_stats?e.write(` Refinement Service: \u2705 Connected (no jobs processed) `):e.write(` Refinement Service: \u26AA Not configured `),e.write(` \u{1F4A1} This could mean: `),e.write(` \u2022 The refiner ID doesn't exist `),e.write(` \u2022 The refiner hasn't processed any data or jobs yet `),e.write(` \u2022 You don't have permission to view this refiner's stats `),e.write(` \u2022 One or both services are not configured `)}displayResults(e,t){this.json?e.write(JSON.stringify(t,null,2)+` `):this.displayFormattedStats(e,t),this.includeRaw&&!this.json&&(e.write(` `+f("\u{1F4C4} Raw API Responses")+` `),e.write(JSON.stringify(t,null,2)+` `))}displayFormattedStats(e,t){e.write(f(`\u{1F4CA} Refiner ${t.refiner_id} - Comprehensive Statistics`)+` `),t.execution_stats?this.displayJobExecutionStats(e,t.execution_stats):(e.write(` `+f("\u2699\uFE0F Refiner Execution (Refinement Service)")+` `),e.write(`\u26AA No execution data available `),t.execution_error&&e.write(`\u274C Error: ${t.execution_error} `)),t.ingestion_stats?this.displayDataIngestionStats(e,t.ingestion_stats):(e.write(f("\u{1F4C1} Data Ingestion")+` `),e.write(`\u26AA No ingestion data available `),t.ingestion_error&&e.write(`\u274C Error: ${t.ingestion_error} `)),t.ingestion_stats&&this.displayQueryExecutionStats(e,t.ingestion_stats),this.displayCombinedErrorAnalysis(e,t),this.verbose&&this.displayTechnicalDetails(e,t)}displayDataIngestionStats(e,t){if(e.write(f("\u{1F4C1} Data Ingestion")+` `),t.total_file_contributions===0){e.write(`\u26AA No data has been ingested yet `);return}e.write(a("File Contributions",t.total_file_contributions.toLocaleString())+` `),e.write(a("Total Data Rows",t.total_data_rows.toLocaleString())+` `),e.write(a("Unique Contributors",t.unique_contributors.toLocaleString())+` `),t.first_ingestion_at&&e.write(a("First Ingestion",new Date(t.first_ingestion_at).toLocaleString())+` `),t.last_ingestion_at&&e.write(a("Last Ingestion",new Date(t.last_ingestion_at).toLocaleString())+` `),t.ingestion_period_days&&e.write(a("Ingestion Period",`${t.ingestion_period_days.toFixed(1)} days`)+` `),e.write(a("Avg Rate/Hour",t.average_ingestion_rate_per_hour.toFixed(2))+` `),Object.keys(t.rows_per_table).length>0&&(e.write(` `+f("\u{1F4CB} Rows per Table")+` `),Object.entries(t.rows_per_table).sort(([,n],[,r])=>r-n).forEach(([n,r])=>{e.write(a(n,r.toLocaleString())+` `)}))}displayJobExecutionStats(e,t){if(e.write(f("\u2699\uFE0F Refiner Execution (Refinement Service)")+` `),t.total_jobs===0){e.write(`\u26AA No jobs have been processed yet `);return}if(e.write(a("Total Jobs",t.total_jobs.toLocaleString())+` `),e.write(a("Successful",t.successful_jobs.toLocaleString())+` `),e.write(a("Failed",t.failed_jobs.toLocaleString())+` `),e.write(a("Currently Processing",t.processing_jobs.toLocaleString())+` `),e.write(a("In Queue",t.submitted_jobs.toLocaleString())+` `),t.total_jobs>0){let n=(t.success_rate*100).toFixed(1);e.write(a("Success Rate",`${n}%`)+` `)}t.average_processing_time_seconds>0&&e.write(a("Avg Processing Time",`${t.average_processing_time_seconds.toFixed(1)}s`)+` `),t.jobs_per_hour>0&&e.write(a("Jobs per Hour",t.jobs_per_hour.toFixed(2))+` `),t.first_job_at&&e.write(a("First Job",new Date(t.first_job_at).toLocaleString())+` `),t.last_job_at&&e.write(a("Last Job",new Date(t.last_job_at).toLocaleString())+` `),t.processing_period_days&&e.write(a("Processing Period",`${t.processing_period_days.toFixed(1)} days`)+` `),e.write(` `)}displayQueryExecutionStats(e,t){if(t.total_queries_executed!==0&&(e.write(` `+f("\u{1F50D} Query Execution")+` `),e.write(a("Total Queries",t.total_queries_executed.toLocaleString())+` `),e.write(a("Successful",t.successful_queries.toLocaleString())+` `),e.write(a("Failed",t.failed_queries.toLocaleString())+` `),t.total_queries_executed>0)){let n=(t.successful_queries/t.total_queries_executed*100).toFixed(1);e.write(a("Success Rate",`${n}%`)+` `)}}displayCombinedErrorAnalysis(e,t){let n=t.ingestion_stats&&Object.keys(t.ingestion_stats.query_errors_by_type).length>0,r=t.execution_stats&&Object.keys(t.execution_stats.error_types).length>0;!n&&!r||(e.write(` `+f("\u274C Error Analysis")+` `),n&&(e.write(`Query Errors: `),Object.entries(t.ingestion_stats.query_errors_by_type).sort(([,o],[,s])=>s-o).forEach(([o,s])=>{e.write(` ${a(o,s.toLocaleString())} `)})),r&&(e.write(`Execution Errors: `),Object.entries(t.execution_stats.error_types).sort(([,o],[,s])=>s-o).forEach(([o,s])=>{e.write(` ${a(o,s.toLocaleString())} `)})),t.execution_stats&&t.execution_stats.recent_errors.length>0&&(e.write(` Recent Execution Errors: `),t.execution_stats.recent_errors.slice(0,3).forEach((o,s)=>{e.write(` ${s+1}. ${o.error} `),e.write(` ${new Date(o.timestamp).toLocaleString()} `),o.job_id&&e.write(` Job ID: ${o.job_id} `)})))}displayTechnicalDetails(e,t){e.write(` `+f("\u{1F527} Technical Details")+` `),t.ingestion_stats?.last_processed_block&&e.write(a("Last Processed Block",t.ingestion_stats.last_processed_block.toLocaleString())+` `),t.execution_stats&&e.write(a("Service Status","Connected")+` `),t.ingestion_stats&&e.write(a("Query Engine Status","Connected")+` `)}};import{Command as X,Option as A}from"clipanion";var T=class extends X{static paths=[["config","get"]];static usage=X.Usage({category:"Configuration",description:"Get configuration values",details:` Get configuration values from the Vana CLI config. By default, only unprotected values are shown. Use --secrets to include protected values from the keyring. Examples: $ vana config get # Show all unprotected config $ vana config get network # Show specific key $ vana config get --secrets # Show all config including secrets $ vana config get --json # Output as JSON `});key=A.String({required:!1});secrets=A.Boolean("--secrets",!1,{description:"Include protected values from keyring"});json=A.Boolean("--json",!1,{description:"Output as JSON"});async execute(){let e=v(this.context);try{let t=y.getInstance();if(await t.initialize(),this.key){let n=await t.getConfigValue(this.key);if(n===void 0)return e.error(d.configNotFound(this.key)),1;if(this.json){let r=!this.secrets&&R(this.key)?m(this.key,n):n;e.write(JSON.stringify({[this.key]:r},null,2)+` `)}else{let r=!this.secrets&&R(this.key)?m(this.key,n):n;e.log(`${this.key}: ${r}`)}}else{let n;if(this.secrets?n=await t.getConfig():n=await t.getUnprotectedConfig(),this.json){let r={...n};if(!this.secrets)for(let[o,s]of Object.entries(r))typeof s=="string"&&R(o)&&(r[o]=m(o,s));e.write(JSON.stringify(r,null,2)+` `)}else this.displayConfig(n,e,t)}return 0}catch(t){return e.error(d.unexpectedError(t)),1}}displayConfig(e,t,n){t.write(f("Vana CLI Configuration")+` `);let r=n.getConfigKeys(),o={};for(let s of r.unprotected)o[s]=e[s];if(t.write(g.configSection("Unprotected","stored in ~/.vana/cli.config.toml",o,{maskSensitive:!1,showEmpty:!1})),this.secrets){let s={};for(let u of r.protected)s[u]=e[u];t.write(g.configSection("Protected","stored in OS keyring",s,{maskSensitive:!0,showEmpty:!0}))}else t.info(w.useSecretsFlag());t.info(w.configLocation(n.getConfigPath()))}};import{Command as Y,Option as O}from"clipanion";import ue from"ora";var q=class extends Y{static paths=[["config","set"]];static usage=Y.Usage({category:"Configuration",description:"Set configuration values",details:` Set configuration values for the Vana CLI. Unprotected values are stored in ~/.vana/cli.config.toml Protected values (like private keys) are stored securely in the OS keyring. Available keys: - network (vana|moksha) - rpc_endpoint (string) - wallet_private_key (string, stored in keyring) Examples: $ vana config set network moksha $ vana config set rpc_endpoint https://rpc.moksha.vana.org $ vana config set wallet_private_key 0x1234... $ vana config set --interactive `});key=O.String({required:!1});value=O.String({required:!1});interactive=O.Boolean("--interactive",!1,{description:"Interactive configuration setup"});quiet=O.Boolean("--quiet",!1,{description:"Suppress output messages"});async execute(){let e=v(this.context);try{let t=y.getInstance();if(await t.initialize(),this.interactive)return await this.runInteractiveSetup(t,e);if(!this.key||!this.value)return e.error(d.missingRequired("key and value")),e.info("Usage: vana config set <key> <value>"),e.info("Or use: vana config set --interactive"),1;let n=ue("Setting configuration...").start();try{if(await t.setConfig(this.key,this.value),n.succeed(),!this.quiet){let o=this.isProtectedKey(this.key)?"OS keyring":"~/.vana/cli.config.toml";e.success(_.configSet(this.key,o))}return 0}catch(r){throw n.fail(),r}}catch(t){return e.error(d.unexpectedError(t)),1}}async runInteractiveSetup(e,t){t.write(f("\u{1F527} Vana CLI Interactive Configuration")+` `);try{let n=await e.getConfig(),r={network:n.network,rpc_endpoint:n.rpc_endpoint},o={wallet_private_key:n.wallet_private_key};return t.write(g.configSection("Current Configuration","unprotected values",r,{maskSensitive:!1,showEmpty:!0})),t.write(g.configSection("Protected Configuration","stored in keyring",o,{maskSensitive:!0,showEmpty:!0})),t.warning(w.interactiveMode()),t.info("Use: vana config set <key> <value> to set individual values"),t.write(g.examples("Example commands",["vana config set network moksha","vana config set rpc_endpoint https://rpc.moksha.vana.org","vana config set wallet_private_key 63..."])),0}catch(n){return t.error(d.unexpectedError(n)),1}}isProtectedKey(e){return e==="wallet_private_key"}};import{Command as Z,Option as ee}from"clipanion";import te from"ora";var j=class extends Z{static paths=[["config","init"]];static usage=Z.Usage({category:"Configuration",description:"Initialize configuration with defaults",details:` Initialize the Vana CLI configuration with default values. Default configuration: - network: moksha - rpc_endpoint: https://rpc.moksha.vana.org This creates ~/.vana/cli.config.toml with the default settings. Protected values (like private keys) are not set by init. Examples: $ vana config init # Initialize with defaults $ vana config init --reset # Reset existing config to defaults `});reset=ee.Boolean("--reset",!1,{description:"Reset existing configuration to defaults"});quiet=ee.Boolean("--quiet",!1,{description:"Suppress output messages"});async execute(){let e=v(this.context);try{let t=y.getInstance();if(this.reset){let n=te("Resetting configuration to defaults...").start();try{await t.reset(),n.succeed(),this.quiet||(e.success(_.configReset()),e.warning(G.secretsCleared()))}catch(r){throw n.fail(),r}}else{let n=te("Initializing configuration...").start();try{await t.initialize(),n.succeed(),this.quiet||(e.success(_.configInitialized()),e.warning("\u26A0\uFE0F This is alpha software - only use for testing/development"))}catch(r){throw n.fail(),r}}if(!this.quiet){let n=await t.getUnprotectedConfig();e.write(` `+f("Current Configuration")+` `);let r={network:n.network,rpc_endpoint:n.rpc_endpoint};e.write(g.configSection("Configuration","unprotected values",r,{maskSensitive:!1,showEmpty:!0})),e.info(w.configLocation(t.getConfigPath())),e.write(g.nextSteps([w.nextSteps.setPrivateKey(),w.nextSteps.viewConfig(),w.nextSteps.viewSecrets()]))}return 0}catch(t){return e.error(d.unexpectedError(t)),1}}};import ne from"chalk";import{readFileSync as pe}from"fs";import{fileURLToPath as le}from"url";import{dirname as de,join as ye}from"path";var we=le(import.meta.url),ve=de(we),he=JSON.parse(pe(ye(ve,"../package.json"),"utf-8")),[lt,dt,...x]=process.argv;x.length>0&&!x.includes("--help")&&!x.includes("-h")&&!x.includes("--version")&&!x.includes("-v")&&(console.error(ne.yellow("\u26A0\uFE0F ALPHA SOFTWARE - Use only for testing/development")),console.error(ne.gray(` Not suitable for production use. Features may change without notice. `)));var C=new ge({binaryLabel:"Vana CLI (Alpha)",binaryName:"vana",binaryVersion:he.version});C.register(ie.HelpCommand);C.register(ie.VersionCommand);C.register(T);C.register(q);C.register(j);C.register(U);await C.runExit(x,{stdin:process.stdin,stdout:process.stdout});