vana-cli 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +8 -1
  2. package/dist/cli.js +30 -29
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -63,6 +63,7 @@ The CLI stores configuration in:
63
63
 
64
64
  - `network` - Network to connect to (vana|moksha)
65
65
  - `rpc_endpoint` - RPC endpoint URL
66
+ - `query_engine_endpoint` - Query Engine API URL for stats commands
66
67
  - `wallet_private_key` - Your wallet private key (stored securely in keyring)
67
68
 
68
69
  ## Examples
@@ -77,6 +78,12 @@ vana config set network moksha
77
78
  # Set custom RPC endpoint
78
79
  vana config set rpc_endpoint https://rpc.moksha.vana.org
79
80
 
81
+ # Set Query Engine endpoint for stats commands
82
+ vana config set query_engine_endpoint https://query.moksha.vana.org
83
+
84
+ # Get refiner stats (uses configured endpoint)
85
+ vana stats refiner --id 45
86
+
80
87
  # Get refiner stats with verbose output
81
88
  vana stats refiner --id 45 --verbose
82
89
 
@@ -89,7 +96,7 @@ vana stats refiner --id 45 --endpoint https://custom.api.com
89
96
 
90
97
  ## Development
91
98
 
92
- See [DEVELOPMENT.md](DEVELOPMENT.md) for development setup and contribution guidelines.
99
+ See [DEVELOPMENT.md](docs/DEVELOPMENT.md) for development setup and contribution guidelines.
93
100
 
94
101
  ## License
95
102
 
package/dist/cli.js CHANGED
@@ -1,27 +1,28 @@
1
1
  #!/usr/bin/env node
2
- import{Cli as fe,Builtins as re}from"clipanion";import{Command as G,Option as k}from"clipanion";import{ethers as ne}from"ethers";var I=class{constructor(e){this.baseUrl=e;this.baseUrl=e}async getRefinerIngestionStats(e,t){try{let r=t.startsWith("0x")?t:`0x${t}`,i=new ne.Wallet(r),o=e.toString(),s=await i.signMessage(o),c=`${this.baseUrl}/stats/refiner/${e}`,u=await fetch(c,{method:"GET",headers:{"X-Refiner-Signature":s,"Content-Type":"application/json"}});if(!u.ok){let E=await u.text(),S=`HTTP ${u.status}: ${u.statusText}`;try{let N=JSON.parse(E);S=N.detail||N.message||S}catch{S=E||S}throw new Error(S)}return await u.json()}catch(r){throw r instanceof Error?r:new Error(`Failed to get refiner ingestion stats: ${String(r)}`)}}};import{promises as _}from"fs";import{join as H,dirname as ie}from"path";import{homedir as oe}from"os";import L from"keytar";var R={network:"moksha",rpc_endpoint:"https://rpc.moksha.vana.org"},q="vana",j=H(oe(),".vana"),x=H(j,"cli.config.toml"),d=class n{static instance;unprotectedConfig=null;constructor(){}static getInstance(){return n.instance||(n.instance=new n),n.instance}async initialize(){try{await _.mkdir(j,{recursive:!0});try{await _.access(x)}catch{await this.writeUnprotectedConfig(R)}}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 _.readFile(x,"utf-8");return this.unprotectedConfig=this.parseToml(e),this.unprotectedConfig}catch{return this.unprotectedConfig={...R},this.unprotectedConfig}}async getProtectedConfig(){try{return{wallet_private_key:await L.getPassword(q,"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 r=await this.getUnprotectedConfig();if(e==="network"&&!["vana","moksha"].includes(t))throw new Error(`Invalid network value: ${t}. Must be 'vana' or 'moksha'`);r[e]=t,await this.writeUnprotectedConfig(r),this.unprotectedConfig=r}async setProtectedConfig(e,t){try{await L.setPassword(q,e,t)}catch(r){throw new Error(`Failed to store ${e} in keyring: ${r instanceof Error?r.message:String(r)}`)}}async writeUnprotectedConfig(e){let t=this.generateToml(e);try{await _.mkdir(ie(x),{recursive:!0}),await _.writeFile(x,t,"utf-8")}catch(r){throw new Error(`Failed to write config file: ${r instanceof Error?r.message:String(r)}`)}}isProtectedKey(e){return e==="wallet_private_key"}parseToml(e){let t={},r=e.split(`
3
- `);for(let i of r){let o=i.trim();if(o&&!o.startsWith("#")){let[s,...c]=o.split("=");if(s&&c.length>0){let u=s.trim(),E=c.join("=").trim().replace(/['"]/g,"");(u==="network"||u==="rpc_endpoint")&&(t[u]=E)}}}return{...R,...t}}generateToml(e){return`# Vana CLI Configuration
2
+ import{Cli as fe,Builtins as ne}from"clipanion";import{Command as z,Option as k}from"clipanion";import{ethers as re}from"ethers";var E=class{constructor(e){this.baseUrl=e;this.baseUrl=e}async getRefinerIngestionStats(e,t){try{let n=t.startsWith("0x")?t:`0x${t}`,i=new re.Wallet(n),o=e.toString(),s=await i.signMessage(o),c=`${this.baseUrl}/stats/refiner/${e}`,u=await fetch(c,{method:"GET",headers:{"X-Refiner-Signature":s,"Content-Type":"application/json"}});if(!u.ok){let I=await u.text(),S=`HTTP ${u.status}: ${u.statusText}`;try{let N=JSON.parse(I);S=N.detail||N.message||S}catch{S=I||S}throw new Error(S)}return await u.json()}catch(n){throw n instanceof Error?n:new Error(`Failed to get refiner ingestion stats: ${String(n)}`)}}};import{promises as _}from"fs";import{join as H,dirname as ie}from"path";import{homedir as oe}from"os";import q from"keytar";var R={network:"moksha",rpc_endpoint:"https://rpc.moksha.vana.org",query_engine_endpoint:"https://54531900daaa8493797db8d07d6bfbfc77f75b4b-8000.dstack-prod5.phala.network"},L="vana",j=H(oe(),".vana"),x=H(j,"cli.config.toml"),d=class r{static instance;unprotectedConfig=null;constructor(){}static getInstance(){return r.instance||(r.instance=new r),r.instance}async initialize(){try{await _.mkdir(j,{recursive:!0});try{await _.access(x)}catch{await this.writeUnprotectedConfig(R)}}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 _.readFile(x,"utf-8");return this.unprotectedConfig=this.parseToml(e),this.unprotectedConfig}catch{return this.unprotectedConfig={...R},this.unprotectedConfig}}async getProtectedConfig(){try{return{wallet_private_key:await q.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 q.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 _.mkdir(ie(x),{recursive:!0}),await _.writeFile(x,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(`
3
+ `);for(let i of n){let o=i.trim();if(o&&!o.startsWith("#")){let[s,...c]=o.split("=");if(s&&c.length>0){let u=s.trim(),I=c.join("=").trim().replace(/['"]/g,"");(u==="network"||u==="rpc_endpoint"||u==="query_engine_endpoint")&&(t[u]=I)}}}return{...R,...t}}generateToml(e){return`# Vana CLI Configuration
4
4
  # This file stores unprotected configuration values
5
5
  # Secrets like private keys are stored securely in the OS keyring
6
6
 
7
7
  network = "${e.network}"
8
8
  rpc_endpoint = "${e.rpc_endpoint}"
9
- `}getConfigKeys(){return{unprotected:["network","rpc_endpoint"],protected:["wallet_private_key"]}}async reset(){await this.writeUnprotectedConfig(R),this.unprotectedConfig=null;try{await L.deletePassword(q,"wallet_private_key")}catch{}}getConfigPath(){return x}};import l from"chalk";function w(n,e){return n==="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 b(n){return["wallet_private_key","private_key","secret","password","token"].some(t=>n.toLowerCase().includes(t))}function a(n,e,t={}){let{maskSensitive:r=!1,indent:i=2}=t,o=" ".repeat(i);if(e===void 0)return`${o}${l.cyan(n)}: ${l.gray("(not set)")}`;let s=r&&b(n)?w(n,e):e;return`${o}${l.cyan(n)}: ${s}`}function P(n,e){let t=l.blue.bold(`
10
- ${n}:`);return e&&(t+=l.gray(` (${e})`)),t}function f(n){return l.bold(n)+`
11
- `+"\u2500".repeat(Math.min(n.length,50))}function K(n){return l.green(`\u2713 ${n}`)}function A(n){return l.red(`\u2717 ${n}`)}function B(n){return l.yellow(`\u26A0 ${n}`)}function J(n){return l.blue(`\u2139 ${n}`)}function D(n){return l.gray(n)}function se(n){return l.gray(` $ ${n}`)}var g={configSection(n,e,t,r={}){let{maskSensitive:i=!1,showEmpty:o=!0}=r,s=P(n,e)+`
9
+ query_engine_endpoint = "${e.query_engine_endpoint}"
10
+ `}getConfigKeys(){return{unprotected:["network","rpc_endpoint","query_engine_endpoint"],protected:["wallet_private_key"]}}async reset(){await this.writeUnprotectedConfig(R),this.unprotectedConfig=null;try{await q.deletePassword(L,"wallet_private_key")}catch{}}getConfigPath(){return x}};import l from"chalk";function m(r,e){return r==="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 b(r){return["wallet_private_key","private_key","secret","password","token"].some(t=>r.toLowerCase().includes(t))}function a(r,e,t={}){let{maskSensitive:n=!1,indent:i=2}=t,o=" ".repeat(i);if(e===void 0)return`${o}${l.cyan(r)}: ${l.gray("(not set)")}`;let s=n&&b(r)?m(r,e):e;return`${o}${l.cyan(r)}: ${s}`}function P(r,e){let t=l.blue.bold(`
11
+ ${r}:`);return e&&(t+=l.gray(` (${e})`)),t}function f(r){return l.bold(r)+`
12
+ `+"\u2500".repeat(Math.min(r.length,50))}function K(r){return l.green(`\u2713 ${r}`)}function A(r){return l.red(`\u2717 ${r}`)}function B(r){return l.yellow(`\u26A0 ${r}`)}function G(r){return l.blue(`\u2139 ${r}`)}function D(r){return l.gray(r)}function se(r){return l.gray(` $ ${r}`)}var g={configSection(r,e,t,n={}){let{maskSensitive:i=!1,showEmpty:o=!0}=n,s=P(r,e)+`
12
13
  `;for(let[c,u]of Object.entries(t))(u!==void 0||o)&&(s+=a(c,u,{maskSensitive:i})+`
13
- `);return s},examples(n,e){let t=P(n)+`
14
- `;for(let r of e)t+=se(r)+`
15
- `;return t},nextSteps(n){let e=P("Next steps")+`
16
- `;for(let t of n)e+=D(` \u2022 ${t}`)+`
17
- `;return e},troubleshooting(n,e){let t=P(n)+`
18
- `;for(let r of e)t+=D(` \u2022 ${r}`)+`
14
+ `);return s},examples(r,e){let t=P(r)+`
15
+ `;for(let n of e)t+=se(n)+`
16
+ `;return t},nextSteps(r){let e=P("Next steps")+`
17
+ `;for(let t of r)e+=D(` \u2022 ${t}`)+`
18
+ `;return e},troubleshooting(r,e){let t=P(r)+`
19
+ `;for(let n of e)t+=D(` \u2022 ${n}`)+`
19
20
  `;return t}};var F=class{constructor(e){this.context=e}success(e){this.context.stdout.write(K(e)+`
20
21
  `)}error(e){this.context.stderr.write(A(e)+`
21
22
  `)}warning(e){this.context.stderr.write(B(e)+`
22
- `)}info(e){this.context.stdout.write(J(e)+`
23
+ `)}info(e){this.context.stdout.write(G(e)+`
23
24
  `)}log(e){this.context.stdout.write(e+`
24
- `)}write(e){this.context.stdout.write(e)}},p={configNotFound:n=>`Configuration key '${n}' not found`,invalidValue:(n,e,t)=>`Invalid value '${e}' for '${n}'${t?`. Expected: ${t}`:""}`,missingRequired:n=>`Missing required field: ${n}`,keyringAccess:n=>`Failed to ${n} keyring. Ensure your system keyring is accessible`,fileAccess:(n,e)=>`Failed to ${e} file: ${n}`,networkError:n=>`Network error connecting to: ${n}`,authenticationFailed:n=>`Authentication failed${n?`: ${n}`:""}`,permissionDenied:n=>`Permission denied accessing: ${n}`,unexpectedError:n=>`Unexpected error: ${n instanceof Error?n.message:String(n)}`},v={configSet:(n,e)=>`Set ${n} in ${e}`,configInitialized:()=>"Configuration initialized",configReset:()=>"Configuration reset to defaults",operationComplete:n=>`${n} completed successfully`},z={secretsCleared:()=>"Protected values (like private keys) have been cleared",keyringUnavailable:()=>"OS keyring unavailable, secrets cannot be stored securely",deprecatedOption:(n,e)=>`Option '${n}' is deprecated, use '${e}' instead`,experimentalFeature:n=>`${n} is experimental and may change in future versions`},y={configLocation:n=>`Config file: ${n}`,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 m(n){return new F({stdout:n.stdout,stderr:n.stderr})}import ae from"ora";var Q=["Verify the refiner ID exists","Check your private key is correct","Ensure the API URL is accessible","Verify you have permission to view this refiner's stats"],$=class extends G{static paths=[["stats","refiner"]];static usage=G.Usage({category:"Stats",description:"Get ingestion statistics for a specific refiner",details:`
25
+ `)}write(e){this.context.stdout.write(e)}},p={configNotFound:r=>`Configuration key '${r}' not found`,invalidValue:(r,e,t)=>`Invalid value '${e}' for '${r}'${t?`. Expected: ${t}`:""}`,missingRequired:r=>`Missing required field: ${r}`,keyringAccess:r=>`Failed to ${r} keyring. Ensure your system keyring is accessible`,fileAccess:(r,e)=>`Failed to ${e} file: ${r}`,networkError:r=>`Network error connecting to: ${r}`,authenticationFailed:r=>`Authentication failed${r?`: ${r}`:""}`,permissionDenied:r=>`Permission denied accessing: ${r}`,unexpectedError:r=>`Unexpected error: ${r instanceof Error?r.message:String(r)}`},v={configSet:(r,e)=>`Set ${r} in ${e}`,configInitialized:()=>"Configuration initialized",configReset:()=>"Configuration reset to defaults",operationComplete:r=>`${r} completed successfully`},J={secretsCleared:()=>"Protected values (like private keys) have been cleared",keyringUnavailable:()=>"OS keyring unavailable, secrets cannot be stored securely",deprecatedOption:(r,e)=>`Option '${r}' is deprecated, use '${e}' instead`,experimentalFeature:r=>`${r} is experimental and may change in future versions`},y={configLocation:r=>`Config file: ${r}`,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 w(r){return new F({stdout:r.stdout,stderr:r.stderr})}import ae from"ora";var Q=["Verify the refiner ID exists","Check your private key is correct","Ensure the API URL is accessible","Verify you have permission to view this refiner's stats"],$=class extends z{static paths=[["stats","refiner"]];static usage=z.Usage({category:"Stats",description:"Get ingestion statistics for a specific refiner",details:`
25
26
  Retrieves comprehensive ingestion statistics for a refiner including:
26
27
  \u2022 File contributions and data rows
27
28
  \u2022 Query execution metrics
@@ -30,12 +31,12 @@ ${n}:`);return e&&(t+=l.gray(` (${e})`)),t}function f(n){return l.bold(n)+`
30
31
  \u2022 Contributor and timing information
31
32
 
32
33
  Requires cryptographic authentication using your wallet private key.
33
- `,examples:[["Get stats for refiner ID 45","vana stats refiner --id 45 --endpoint https://query-engine.api.com"],["Get stats with private key override","vana stats refiner --id 45 --private-key 63... --endpoint https://query-engine.api.com"],["Get stats in JSON format","vana stats refiner --id 45 --endpoint https://query-engine.api.com --json"],["Get verbose stats with raw response","vana stats refiner --id 45 --endpoint https://query-engine.api.com --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)"});endpoint=k.String("--endpoint,-e",{description:"Query Engine API URL (required - stats come from Query Engine, not RPC)"});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 response in output"});async execute(){let e=m(this.context);try{let t=this.validateRefinerId(e);if(t===null)return 1;let{privateKey:r,apiUrl:i}=await this.getConfiguration(e);if(!r||!i)return 1;this.verbose&&this.displayVerboseInfo(e,t,i,r);let o=await this.fetchRefinerStats(e,t,i,r);return o?(this.displayResults(e,o),e.success(v.operationComplete("Refiner stats retrieved")),this.verbose&&e.warning("\u26A0\uFE0F Alpha software: Verify all data independently before making decisions"),0):(e.write(g.troubleshooting("Troubleshooting",Q)),1)}catch(t){return e.error(p.unexpectedError(t)),e.write(g.troubleshooting("Troubleshooting",Q)),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=d.getInstance();await t.initialize();let r=this.privateKey;if(!r)try{r=await t.getConfigValue("wallet_private_key")}catch{}if(!r)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:null,apiUrl:null};let i=this.endpoint;return i?{privateKey:r,apiUrl:i}:(e.error("Query Engine API URL is required for refiner stats."),e.info("Refiner stats are retrieved from the Query Engine API, not on-chain RPC."),e.write(g.examples("Provide Query Engine API URL with",["vana stats refiner --id 45 --endpoint https://query-engine.api.com"])),{privateKey:null,apiUrl:null})}displayVerboseInfo(e,t,r,i){e.write(f("\u{1F50D} Refiner Ingestion Stats")+`
34
+ `,examples:[["Get stats for refiner ID 45","vana stats refiner --id 45"],["Get stats with custom endpoint","vana stats refiner --id 45 --endpoint https://query-engine.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)"});endpoint=k.String("--endpoint,-e",{description:"Query Engine 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 response in output"});async execute(){let e=w(this.context);try{let t=this.validateRefinerId(e);if(t===null)return 1;let{privateKey:n,apiUrl:i}=await this.getConfiguration(e);if(!n||!i)return 1;this.verbose&&this.displayVerboseInfo(e,t,i,n);let o=await this.fetchRefinerStats(e,t,i,n);return o?(this.displayResults(e,o),e.success(v.operationComplete("Refiner stats retrieved")),this.verbose&&e.warning("\u26A0\uFE0F Alpha software: Verify all data independently before making decisions"),0):(e.write(g.troubleshooting("Troubleshooting",Q)),1)}catch(t){return e.error(p.unexpectedError(t)),e.write(g.troubleshooting("Troubleshooting",Q)),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=d.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:null,apiUrl:null};let i=this.endpoint;if(!i)try{i=await t.getConfigValue("query_engine_endpoint")}catch{}return i?{privateKey:n,apiUrl:i}:(e.error("Query Engine API URL is required for refiner stats."),e.info("Refiner stats are retrieved from the Query Engine API, not on-chain RPC."),e.write(g.examples("Set Query Engine API URL with",["vana config set query_engine_endpoint https://query-engine.api.com","or use --endpoint option"])),{privateKey:null,apiUrl:null})}displayVerboseInfo(e,t,n,i){e.write(f("\u{1F50D} Refiner Ingestion Stats")+`
34
35
  `),e.write(a("Refiner ID",t.toString())+`
35
- `),e.write(a("API URL",r)+`
36
- `),e.write(a("Private Key",w("wallet_private_key",i))+`
36
+ `),e.write(a("API URL",n)+`
37
+ `),e.write(a("Private Key",m("wallet_private_key",i))+`
37
38
  `),e.write(`
38
- `)}async fetchRefinerStats(e,t,r,i){let o=new I(r),s=ae(`Fetching ingestion stats for refiner ${t}...`).start();try{let c=await o.getRefinerIngestionStats(t,i);return s.succeed(),c}catch(c){return s.fail(),e.error(`Failed to fetch refiner stats: ${c instanceof Error?c.message:String(c)}`),null}}displayResults(e,t){this.json?e.write(JSON.stringify(t,null,2)+`
39
+ `)}async fetchRefinerStats(e,t,n,i){let o=new E(n),s=ae(`Fetching ingestion stats for refiner ${t}...`).start();try{let c=await o.getRefinerIngestionStats(t,i);return s.succeed(),c}catch(c){return s.fail(),e.error(`Failed to fetch refiner stats: ${c instanceof Error?c.message:String(c)}`),null}}displayResults(e,t){this.json?e.write(JSON.stringify(t,null,2)+`
39
40
  `):this.displayFormattedStats(e,t),this.includeRaw&&!this.json&&(e.write(`
40
41
  `+f("\u{1F4C4} Raw API Response")+`
41
42
  `),e.write(JSON.stringify(t,null,2)+`
@@ -54,13 +55,13 @@ ${n}:`);return e&&(t+=l.gray(` (${e})`)),t}function f(n){return l.bold(n)+`
54
55
  `),e.write(a("Total Queries",t.total_queries_executed.toLocaleString())+`
55
56
  `),e.write(a("Successful",t.successful_queries.toLocaleString())+`
56
57
  `),e.write(a("Failed",t.failed_queries.toLocaleString())+`
57
- `),t.total_queries_executed>0){let r=(t.successful_queries/t.total_queries_executed*100).toFixed(1);e.write(a("Success Rate",`${r}%`)+`
58
+ `),t.total_queries_executed>0){let n=(t.successful_queries/t.total_queries_executed*100).toFixed(1);e.write(a("Success Rate",`${n}%`)+`
58
59
  `)}}displayQueryErrorsBreakdown(e,t){Object.keys(t.query_errors_by_type).length!==0&&(e.write(`
59
60
  `+f("\u274C Query Errors by Type")+`
60
- `),Object.entries(t.query_errors_by_type).sort(([,r],[,i])=>i-r).forEach(([r,i])=>{e.write(a(r,i.toLocaleString())+`
61
+ `),Object.entries(t.query_errors_by_type).sort(([,n],[,i])=>i-n).forEach(([n,i])=>{e.write(a(n,i.toLocaleString())+`
61
62
  `)}))}displayRowsPerTable(e,t){Object.keys(t.rows_per_table).length!==0&&(e.write(`
62
63
  `+f("\u{1F4CB} Rows per Table")+`
63
- `),Object.entries(t.rows_per_table).sort(([,r],[,i])=>i-r).forEach(([r,i])=>{e.write(a(r,i.toLocaleString())+`
64
+ `),Object.entries(t.rows_per_table).sort(([,n],[,i])=>i-n).forEach(([n,i])=>{e.write(a(n,i.toLocaleString())+`
64
65
  `)}))}displayTechnicalDetails(e,t){e.write(`
65
66
  `+f("\u{1F527} Technical Details")+`
66
67
  `),t.last_processed_block&&e.write(a("Last Processed Block",t.last_processed_block.toLocaleString())+`
@@ -75,10 +76,10 @@ ${n}:`);return e&&(t+=l.gray(` (${e})`)),t}function f(n){return l.bold(n)+`
75
76
  $ vana config get network # Show specific key
76
77
  $ vana config get --secrets # Show all config including secrets
77
78
  $ vana config get --json # Output as JSON
78
- `});key=V.String({required:!1});secrets=V.Boolean("--secrets",!1,{description:"Include protected values from keyring"});json=V.Boolean("--json",!1,{description:"Output as JSON"});async execute(){let e=m(this.context);try{let t=d.getInstance();if(await t.initialize(),this.key){let r=await t.getConfigValue(this.key);if(r===void 0)return e.error(p.configNotFound(this.key)),1;if(this.json){let i=!this.secrets&&b(this.key)?w(this.key,r):r;e.write(JSON.stringify({[this.key]:i},null,2)+`
79
- `)}else{let i=!this.secrets&&b(this.key)?w(this.key,r):r;e.log(`${this.key}: ${i}`)}}else{let r;if(this.secrets?r=await t.getConfig():r=await t.getUnprotectedConfig(),this.json){let i={...r};if(!this.secrets)for(let[o,s]of Object.entries(i))typeof s=="string"&&b(o)&&(i[o]=w(o,s));e.write(JSON.stringify(i,null,2)+`
80
- `)}else this.displayConfig(r,e,t)}return 0}catch(t){return e.error(p.unexpectedError(t)),1}}displayConfig(e,t,r){t.write(f("Vana CLI Configuration")+`
81
- `);let i=r.getConfigKeys(),o={};for(let s of i.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 c of i.protected)s[c]=e[c];t.write(g.configSection("Protected","stored in OS keyring",s,{maskSensitive:!0,showEmpty:!0}))}else t.info(y.useSecretsFlag());t.info(y.configLocation(r.getConfigPath()))}};import{Command as X,Option as U}from"clipanion";import ce from"ora";var O=class extends X{static paths=[["config","set"]];static usage=X.Usage({category:"Configuration",description:"Set configuration values",details:`
79
+ `});key=V.String({required:!1});secrets=V.Boolean("--secrets",!1,{description:"Include protected values from keyring"});json=V.Boolean("--json",!1,{description:"Output as JSON"});async execute(){let e=w(this.context);try{let t=d.getInstance();if(await t.initialize(),this.key){let n=await t.getConfigValue(this.key);if(n===void 0)return e.error(p.configNotFound(this.key)),1;if(this.json){let i=!this.secrets&&b(this.key)?m(this.key,n):n;e.write(JSON.stringify({[this.key]:i},null,2)+`
80
+ `)}else{let i=!this.secrets&&b(this.key)?m(this.key,n):n;e.log(`${this.key}: ${i}`)}}else{let n;if(this.secrets?n=await t.getConfig():n=await t.getUnprotectedConfig(),this.json){let i={...n};if(!this.secrets)for(let[o,s]of Object.entries(i))typeof s=="string"&&b(o)&&(i[o]=m(o,s));e.write(JSON.stringify(i,null,2)+`
81
+ `)}else this.displayConfig(n,e,t)}return 0}catch(t){return e.error(p.unexpectedError(t)),1}}displayConfig(e,t,n){t.write(f("Vana CLI Configuration")+`
82
+ `);let i=n.getConfigKeys(),o={};for(let s of i.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 c of i.protected)s[c]=e[c];t.write(g.configSection("Protected","stored in OS keyring",s,{maskSensitive:!0,showEmpty:!0}))}else t.info(y.useSecretsFlag());t.info(y.configLocation(n.getConfigPath()))}};import{Command as X,Option as U}from"clipanion";import ce from"ora";var O=class extends X{static paths=[["config","set"]];static usage=X.Usage({category:"Configuration",description:"Set configuration values",details:`
82
83
  Set configuration values for the Vana CLI.
83
84
 
84
85
  Unprotected values are stored in ~/.vana/cli.config.toml
@@ -94,9 +95,9 @@ ${n}:`);return e&&(t+=l.gray(` (${e})`)),t}function f(n){return l.bold(n)+`
94
95
  $ vana config set rpc_endpoint https://rpc.moksha.vana.org
95
96
  $ vana config set wallet_private_key 0x1234...
96
97
  $ vana config set --interactive
97
- `});key=U.String({required:!1});value=U.String({required:!1});interactive=U.Boolean("--interactive",!1,{description:"Interactive configuration setup"});quiet=U.Boolean("--quiet",!1,{description:"Suppress output messages"});async execute(){let e=m(this.context);try{let t=d.getInstance();if(await t.initialize(),this.interactive)return await this.runInteractiveSetup(t,e);if(!this.key||!this.value)return e.error(p.missingRequired("key and value")),e.info("Usage: vana config set <key> <value>"),e.info("Or use: vana config set --interactive"),1;let r=ce("Setting configuration...").start();try{if(await t.setConfig(this.key,this.value),r.succeed(),!this.quiet){let o=this.isProtectedKey(this.key)?"OS keyring":"~/.vana/cli.config.toml";e.success(v.configSet(this.key,o))}return 0}catch(i){throw r.fail(),i}}catch(t){return e.error(p.unexpectedError(t)),1}}async runInteractiveSetup(e,t){t.write(f("\u{1F527} Vana CLI Interactive Configuration")+`
98
+ `});key=U.String({required:!1});value=U.String({required:!1});interactive=U.Boolean("--interactive",!1,{description:"Interactive configuration setup"});quiet=U.Boolean("--quiet",!1,{description:"Suppress output messages"});async execute(){let e=w(this.context);try{let t=d.getInstance();if(await t.initialize(),this.interactive)return await this.runInteractiveSetup(t,e);if(!this.key||!this.value)return e.error(p.missingRequired("key and value")),e.info("Usage: vana config set <key> <value>"),e.info("Or use: vana config set --interactive"),1;let n=ce("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(v.configSet(this.key,o))}return 0}catch(i){throw n.fail(),i}}catch(t){return e.error(p.unexpectedError(t)),1}}async runInteractiveSetup(e,t){t.write(f("\u{1F527} Vana CLI Interactive Configuration")+`
98
99
 
99
- `);try{let r=await e.getConfig(),i={network:r.network,rpc_endpoint:r.rpc_endpoint},o={wallet_private_key:r.wallet_private_key};return t.write(g.configSection("Current Configuration","unprotected values",i,{maskSensitive:!1,showEmpty:!0})),t.write(g.configSection("Protected Configuration","stored in keyring",o,{maskSensitive:!0,showEmpty:!0})),t.warning(y.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(r){return t.error(p.unexpectedError(r)),1}}isProtectedKey(e){return e==="wallet_private_key"}};import{Command as Y,Option as Z}from"clipanion";import ee from"ora";var T=class extends Y{static paths=[["config","init"]];static usage=Y.Usage({category:"Configuration",description:"Initialize configuration with defaults",details:`
100
+ `);try{let n=await e.getConfig(),i={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",i,{maskSensitive:!1,showEmpty:!0})),t.write(g.configSection("Protected Configuration","stored in keyring",o,{maskSensitive:!0,showEmpty:!0})),t.warning(y.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(p.unexpectedError(n)),1}}isProtectedKey(e){return e==="wallet_private_key"}};import{Command as Y,Option as Z}from"clipanion";import ee from"ora";var T=class extends Y{static paths=[["config","init"]];static usage=Y.Usage({category:"Configuration",description:"Initialize configuration with defaults",details:`
100
101
  Initialize the Vana CLI configuration with default values.
101
102
 
102
103
  Default configuration:
@@ -109,7 +110,7 @@ ${n}:`);return e&&(t+=l.gray(` (${e})`)),t}function f(n){return l.bold(n)+`
109
110
  Examples:
110
111
  $ vana config init # Initialize with defaults
111
112
  $ vana config init --reset # Reset existing config to defaults
112
- `});reset=Z.Boolean("--reset",!1,{description:"Reset existing configuration to defaults"});quiet=Z.Boolean("--quiet",!1,{description:"Suppress output messages"});async execute(){let e=m(this.context);try{let t=d.getInstance();if(this.reset){let r=ee("Resetting configuration to defaults...").start();try{await t.reset(),r.succeed(),this.quiet||(e.success(v.configReset()),e.warning(z.secretsCleared()))}catch(i){throw r.fail(),i}}else{let r=ee("Initializing configuration...").start();try{await t.initialize(),r.succeed(),this.quiet||(e.success(v.configInitialized()),e.warning("\u26A0\uFE0F This is alpha software - only use for testing/development"))}catch(i){throw r.fail(),i}}if(!this.quiet){let r=await t.getUnprotectedConfig();e.write(`
113
+ `});reset=Z.Boolean("--reset",!1,{description:"Reset existing configuration to defaults"});quiet=Z.Boolean("--quiet",!1,{description:"Suppress output messages"});async execute(){let e=w(this.context);try{let t=d.getInstance();if(this.reset){let n=ee("Resetting configuration to defaults...").start();try{await t.reset(),n.succeed(),this.quiet||(e.success(v.configReset()),e.warning(J.secretsCleared()))}catch(i){throw n.fail(),i}}else{let n=ee("Initializing configuration...").start();try{await t.initialize(),n.succeed(),this.quiet||(e.success(v.configInitialized()),e.warning("\u26A0\uFE0F This is alpha software - only use for testing/development"))}catch(i){throw n.fail(),i}}if(!this.quiet){let n=await t.getUnprotectedConfig();e.write(`
113
114
  `+f("Current Configuration")+`
114
- `);let i={network:r.network,rpc_endpoint:r.rpc_endpoint};e.write(g.configSection("Configuration","unprotected values",i,{maskSensitive:!1,showEmpty:!0})),e.info(y.configLocation(t.getConfigPath())),e.write(g.nextSteps([y.nextSteps.setPrivateKey(),y.nextSteps.viewConfig(),y.nextSteps.viewSecrets()]))}return 0}catch(t){return e.error(p.unexpectedError(t)),1}}};import te from"chalk";import{readFileSync as ge}from"fs";import{fileURLToPath as ue}from"url";import{dirname as le,join as pe}from"path";var de=ue(import.meta.url),ye=le(de),me=JSON.parse(ge(pe(ye,"../package.json"),"utf-8")),[ct,ft,...C]=process.argv;C.length>0&&!C.includes("--help")&&!C.includes("-h")&&!C.includes("--version")&&!C.includes("-v")&&(console.error(te.yellow("\u26A0\uFE0F ALPHA SOFTWARE - Use only for testing/development")),console.error(te.gray(` Not suitable for production use. Features may change without notice.
115
- `)));var h=new fe({binaryLabel:"Vana CLI (Alpha)",binaryName:"vana",binaryVersion:me.version});h.register(re.HelpCommand);h.register(re.VersionCommand);h.register(M);h.register(O);h.register(T);h.register($);await h.runExit(C,{stdin:process.stdin,stdout:process.stdout});
115
+ `);let i={network:n.network,rpc_endpoint:n.rpc_endpoint};e.write(g.configSection("Configuration","unprotected values",i,{maskSensitive:!1,showEmpty:!0})),e.info(y.configLocation(t.getConfigPath())),e.write(g.nextSteps([y.nextSteps.setPrivateKey(),y.nextSteps.viewConfig(),y.nextSteps.viewSecrets()]))}return 0}catch(t){return e.error(p.unexpectedError(t)),1}}};import te from"chalk";import{readFileSync as ge}from"fs";import{fileURLToPath as ue}from"url";import{dirname as le,join as pe}from"path";var de=ue(import.meta.url),ye=le(de),we=JSON.parse(ge(pe(ye,"../package.json"),"utf-8")),[ct,ft,...C]=process.argv;C.length>0&&!C.includes("--help")&&!C.includes("-h")&&!C.includes("--version")&&!C.includes("-v")&&(console.error(te.yellow("\u26A0\uFE0F ALPHA SOFTWARE - Use only for testing/development")),console.error(te.gray(` Not suitable for production use. Features may change without notice.
116
+ `)));var h=new fe({binaryLabel:"Vana CLI (Alpha)",binaryName:"vana",binaryVersion:we.version});h.register(ne.HelpCommand);h.register(ne.VersionCommand);h.register(M);h.register(O);h.register(T);h.register($);await h.runExit(C,{stdin:process.stdin,stdout:process.stdout});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vana-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "[ALPHA] Vana CLI for interacting with the Vana L1 network and related services - experimental software",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {