@trust-ethos/cli 0.0.5

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 (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1791 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.js +5 -0
  5. package/bin/run.cmd +3 -0
  6. package/bin/run.js +5 -0
  7. package/dist/commands/auction/active.d.ts +10 -0
  8. package/dist/commands/auction/active.js +39 -0
  9. package/dist/commands/auction/info.d.ts +16 -0
  10. package/dist/commands/auction/info.js +46 -0
  11. package/dist/commands/auction/list.d.ts +14 -0
  12. package/dist/commands/auction/list.js +61 -0
  13. package/dist/commands/broker/info.d.ts +16 -0
  14. package/dist/commands/broker/info.js +37 -0
  15. package/dist/commands/broker/list.d.ts +15 -0
  16. package/dist/commands/broker/list.js +62 -0
  17. package/dist/commands/config/get.d.ts +9 -0
  18. package/dist/commands/config/get.js +29 -0
  19. package/dist/commands/config/path.d.ts +6 -0
  20. package/dist/commands/config/path.js +12 -0
  21. package/dist/commands/config/set.d.ts +9 -0
  22. package/dist/commands/config/set.js +28 -0
  23. package/dist/commands/listing/info.d.ts +13 -0
  24. package/dist/commands/listing/info.js +41 -0
  25. package/dist/commands/listing/list.d.ts +13 -0
  26. package/dist/commands/listing/list.js +46 -0
  27. package/dist/commands/listing/voters.d.ts +19 -0
  28. package/dist/commands/listing/voters.js +48 -0
  29. package/dist/commands/market/featured.d.ts +10 -0
  30. package/dist/commands/market/featured.js +34 -0
  31. package/dist/commands/market/holders.d.ts +14 -0
  32. package/dist/commands/market/holders.js +46 -0
  33. package/dist/commands/market/info.d.ts +14 -0
  34. package/dist/commands/market/info.js +48 -0
  35. package/dist/commands/market/list.d.ts +16 -0
  36. package/dist/commands/market/list.js +55 -0
  37. package/dist/commands/nft/list.d.ts +15 -0
  38. package/dist/commands/nft/list.js +64 -0
  39. package/dist/commands/review/info.d.ts +17 -0
  40. package/dist/commands/review/info.js +49 -0
  41. package/dist/commands/review/list.d.ts +16 -0
  42. package/dist/commands/review/list.js +68 -0
  43. package/dist/commands/review/votes.d.ts +21 -0
  44. package/dist/commands/review/votes.js +91 -0
  45. package/dist/commands/score/status.d.ts +13 -0
  46. package/dist/commands/score/status.js +54 -0
  47. package/dist/commands/slash/info.d.ts +16 -0
  48. package/dist/commands/slash/info.js +42 -0
  49. package/dist/commands/slash/list.d.ts +15 -0
  50. package/dist/commands/slash/list.js +50 -0
  51. package/dist/commands/slash/votes.d.ts +21 -0
  52. package/dist/commands/slash/votes.js +91 -0
  53. package/dist/commands/user/activity.d.ts +15 -0
  54. package/dist/commands/user/activity.js +71 -0
  55. package/dist/commands/user/info.d.ts +14 -0
  56. package/dist/commands/user/info.js +51 -0
  57. package/dist/commands/user/invitations.d.ts +16 -0
  58. package/dist/commands/user/invitations.js +73 -0
  59. package/dist/commands/user/search.d.ts +15 -0
  60. package/dist/commands/user/search.js +59 -0
  61. package/dist/commands/user/summary.d.ts +14 -0
  62. package/dist/commands/user/summary.js +134 -0
  63. package/dist/commands/validator/info.d.ts +13 -0
  64. package/dist/commands/validator/info.js +53 -0
  65. package/dist/commands/validator/list.d.ts +13 -0
  66. package/dist/commands/validator/list.js +64 -0
  67. package/dist/commands/validator/sales.d.ts +12 -0
  68. package/dist/commands/validator/sales.js +52 -0
  69. package/dist/commands/vouch/info.d.ts +17 -0
  70. package/dist/commands/vouch/info.js +53 -0
  71. package/dist/commands/vouch/list.d.ts +18 -0
  72. package/dist/commands/vouch/list.js +89 -0
  73. package/dist/commands/vouch/mutual.d.ts +15 -0
  74. package/dist/commands/vouch/mutual.js +68 -0
  75. package/dist/commands/vouch/votes.d.ts +21 -0
  76. package/dist/commands/vouch/votes.js +91 -0
  77. package/dist/commands/xp/rank.d.ts +15 -0
  78. package/dist/commands/xp/rank.js +74 -0
  79. package/dist/commands/xp/seasons.d.ts +10 -0
  80. package/dist/commands/xp/seasons.js +42 -0
  81. package/dist/hooks/init.d.ts +3 -0
  82. package/dist/hooks/init.js +40 -0
  83. package/dist/index.d.ts +1 -0
  84. package/dist/index.js +1 -0
  85. package/dist/lib/api/echo-client.d.ts +624 -0
  86. package/dist/lib/api/echo-client.js +408 -0
  87. package/dist/lib/config/index.d.ts +6 -0
  88. package/dist/lib/config/index.js +32 -0
  89. package/dist/lib/errors/cli-error.d.ts +23 -0
  90. package/dist/lib/errors/cli-error.js +57 -0
  91. package/dist/lib/formatting/colors.d.ts +13 -0
  92. package/dist/lib/formatting/colors.js +22 -0
  93. package/dist/lib/formatting/error.d.ts +1 -0
  94. package/dist/lib/formatting/error.js +64 -0
  95. package/dist/lib/formatting/output.d.ts +45 -0
  96. package/dist/lib/formatting/output.js +753 -0
  97. package/dist/lib/help.d.ts +4 -0
  98. package/dist/lib/help.js +28 -0
  99. package/dist/lib/update/index.d.ts +37 -0
  100. package/dist/lib/update/index.js +286 -0
  101. package/dist/lib/validation/userkey.d.ts +11 -0
  102. package/dist/lib/validation/userkey.js +81 -0
  103. package/oclif.manifest.json +2224 -0
  104. package/package.json +87 -0
@@ -0,0 +1,134 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import pc from 'picocolors';
3
+ import { EchoClient } from '../../lib/api/echo-client.js';
4
+ import { formatError } from '../../lib/formatting/error.js';
5
+ import { output } from '../../lib/formatting/output.js';
6
+ function getScoreLevel(score) {
7
+ if (score < 800)
8
+ return 'untrusted';
9
+ if (score < 1200)
10
+ return 'questionable';
11
+ if (score < 1600)
12
+ return 'neutral';
13
+ if (score < 2000)
14
+ return 'reputable';
15
+ return 'exemplary';
16
+ }
17
+ const LEVEL_COLORS = {
18
+ untrusted: pc.red,
19
+ questionable: pc.yellow,
20
+ neutral: pc.white,
21
+ reputable: pc.green,
22
+ exemplary: pc.cyan,
23
+ };
24
+ export default class UserSummary extends Command {
25
+ static aliases = ['us'];
26
+ static args = {
27
+ identifier: Args.string({
28
+ description: 'Twitter username, ETH address, or ENS name',
29
+ required: true,
30
+ }),
31
+ };
32
+ static description = 'Display comprehensive user summary with activity and vouches';
33
+ static examples = [
34
+ '<%= config.bin %> <%= command.id %> sethgho',
35
+ '<%= config.bin %> <%= command.id %> 0xNowater',
36
+ '<%= config.bin %> <%= command.id %> vitalik.eth --json',
37
+ ];
38
+ static flags = {
39
+ json: Flags.boolean({
40
+ char: 'j',
41
+ description: 'Output as JSON',
42
+ default: false,
43
+ }),
44
+ verbose: Flags.boolean({
45
+ char: 'v',
46
+ description: 'Show detailed error information',
47
+ default: false,
48
+ }),
49
+ };
50
+ async run() {
51
+ const { args, flags } = await this.parse(UserSummary);
52
+ const client = new EchoClient();
53
+ try {
54
+ const user = await client.resolveUser(args.identifier);
55
+ const userkey = client.getPrimaryUserkey(user);
56
+ const [activities, vouches] = await Promise.all([
57
+ userkey ? client.getActivities(userkey, ['review', 'vouch'], 5) : [],
58
+ user.profileId ? client.getVouches({ subjectProfileIds: [user.profileId], archived: false, limit: 5 }) : { values: [], total: 0 },
59
+ ]);
60
+ if (flags.json) {
61
+ this.log(output({
62
+ user,
63
+ recentActivity: activities,
64
+ topVouches: vouches.values,
65
+ }));
66
+ return;
67
+ }
68
+ const displayName = user.displayName || user.username || 'Unknown';
69
+ const level = getScoreLevel(user.score);
70
+ const levelColor = LEVEL_COLORS[level];
71
+ const lines = [
72
+ pc.bold(pc.cyan(`User Summary: ${displayName}`)),
73
+ '',
74
+ ];
75
+ if (user.username) {
76
+ lines.push(`${pc.dim('Username:')} @${user.username}`);
77
+ }
78
+ lines.push(`${pc.dim('Score:')} ${pc.green(String(user.score))} ${levelColor(`(${level.toUpperCase()})`)}`);
79
+ lines.push(`${pc.dim('XP:')} ${pc.green(user.xpTotal.toLocaleString())}`);
80
+ if (user.stats) {
81
+ const reviews = user.stats.review.received;
82
+ const reviewTotal = reviews.positive + reviews.neutral + reviews.negative;
83
+ if (reviewTotal > 0) {
84
+ lines.push(`${pc.dim('Reviews:')} ${pc.green(`+${reviews.positive}`)} / ${reviews.neutral} / ${pc.red(`-${reviews.negative}`)}`);
85
+ }
86
+ const vouches = user.stats.vouch;
87
+ lines.push(`${pc.dim('Vouches:')} ${vouches.received.count} received, ${vouches.given.count} given`);
88
+ }
89
+ if (activities.length > 0) {
90
+ lines.push('');
91
+ lines.push(pc.bold('Recent Activity'));
92
+ for (const activity of activities.slice(0, 5)) {
93
+ const typeIcon = activity.type === 'vouch' ? '🤝' : activity.type === 'review' ? '📝' : '❌';
94
+ const authorName = activity.author.username ? `@${activity.author.username}` : activity.author.name;
95
+ const subjectName = activity.subject.username ? `@${activity.subject.username}` : activity.subject.name;
96
+ const date = new Date(activity.timestamp * 1000).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
97
+ lines.push(` ${typeIcon} ${authorName} → ${subjectName} ${pc.dim(`(${date})`)}`);
98
+ }
99
+ }
100
+ if (vouches.values.length > 0) {
101
+ lines.push('');
102
+ lines.push(pc.bold('Top Vouchers'));
103
+ for (const v of vouches.values.slice(0, 5)) {
104
+ const authorName = v.authorUser?.username ? `@${v.authorUser.username}` : v.authorUser?.displayName || `#${v.authorProfileId}`;
105
+ const amount = formatVouchAmount(v.balance);
106
+ const mutualTag = v.mutualId ? pc.cyan(' [MUTUAL]') : '';
107
+ lines.push(` 🤝 ${authorName} - ${pc.green(amount)}${mutualTag}`);
108
+ }
109
+ }
110
+ if (user.links?.profile) {
111
+ lines.push('');
112
+ lines.push(`${pc.dim('Profile:')} ${user.links.profile}`);
113
+ }
114
+ this.log(lines.join('\n'));
115
+ }
116
+ catch (error) {
117
+ if (error instanceof Error) {
118
+ this.log(formatError(error, flags.verbose));
119
+ this.exit(1);
120
+ }
121
+ }
122
+ }
123
+ }
124
+ function formatVouchAmount(wei) {
125
+ const cleanWei = wei.replace(/n$/, '');
126
+ const eth = Number(BigInt(cleanWei)) / 1e18;
127
+ if (eth >= 1)
128
+ return eth.toFixed(4) + ' ETH';
129
+ if (eth >= 0.001)
130
+ return eth.toFixed(6) + ' ETH';
131
+ if (eth > 0)
132
+ return eth.toExponential(2) + ' ETH';
133
+ return '0 ETH';
134
+ }
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class ValidatorInfo extends Command {
3
+ static description: string;
4
+ static args: {
5
+ tokenId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static examples: string[];
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,53 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { EchoClient } from '../../lib/api/echo-client.js';
3
+ import { formatError } from '../../lib/formatting/error.js';
4
+ import { formatValidator, output } from '../../lib/formatting/output.js';
5
+ export default class ValidatorInfo extends Command {
6
+ static description = 'Get details of a specific validator NFT';
7
+ static args = {
8
+ tokenId: Args.string({
9
+ description: 'Validator token ID',
10
+ required: true,
11
+ }),
12
+ };
13
+ static examples = [
14
+ '<%= config.bin %> <%= command.id %> 1',
15
+ '<%= config.bin %> <%= command.id %> 42 --json',
16
+ ];
17
+ static flags = {
18
+ json: Flags.boolean({
19
+ char: 'j',
20
+ description: 'Output as JSON',
21
+ default: false,
22
+ }),
23
+ verbose: Flags.boolean({
24
+ char: 'v',
25
+ description: 'Show detailed error information',
26
+ default: false,
27
+ }),
28
+ };
29
+ async run() {
30
+ const { args, flags } = await this.parse(ValidatorInfo);
31
+ const client = new EchoClient();
32
+ try {
33
+ const validator = await client.getValidatorByTokenId(args.tokenId);
34
+ if (!validator) {
35
+ this.log(`Validator with token ID ${args.tokenId} not found.`);
36
+ this.exit(1);
37
+ return;
38
+ }
39
+ if (flags.json) {
40
+ this.log(output(validator));
41
+ }
42
+ else {
43
+ this.log(formatValidator(validator));
44
+ }
45
+ }
46
+ catch (error) {
47
+ if (error instanceof Error) {
48
+ this.log(formatError(error, flags.verbose));
49
+ this.exit(1);
50
+ }
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class ValidatorList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
+ offset: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
+ available: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,64 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { EchoClient } from '../../lib/api/echo-client.js';
3
+ import { formatError } from '../../lib/formatting/error.js';
4
+ import { formatValidators, output } from '../../lib/formatting/output.js';
5
+ export default class ValidatorList extends Command {
6
+ static description = 'List all Ethos validator NFT owners';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %>',
9
+ '<%= config.bin %> <%= command.id %> --limit 20',
10
+ '<%= config.bin %> <%= command.id %> --available',
11
+ '<%= config.bin %> <%= command.id %> --json',
12
+ ];
13
+ static flags = {
14
+ json: Flags.boolean({
15
+ char: 'j',
16
+ description: 'Output as JSON',
17
+ default: false,
18
+ }),
19
+ verbose: Flags.boolean({
20
+ char: 'v',
21
+ description: 'Show detailed error information',
22
+ default: false,
23
+ }),
24
+ limit: Flags.integer({
25
+ char: 'l',
26
+ description: 'Max results to display',
27
+ default: 10,
28
+ }),
29
+ offset: Flags.integer({
30
+ char: 'o',
31
+ description: 'Number of results to skip',
32
+ default: 0,
33
+ }),
34
+ available: Flags.boolean({
35
+ char: 'a',
36
+ description: 'Show only validators with remaining XP capacity',
37
+ default: false,
38
+ }),
39
+ };
40
+ async run() {
41
+ const { flags } = await this.parse(ValidatorList);
42
+ const client = new EchoClient();
43
+ try {
44
+ let validators = await client.getValidators();
45
+ if (flags.available) {
46
+ validators = validators.filter(v => !v.isFull);
47
+ }
48
+ const total = validators.length;
49
+ validators = validators.slice(flags.offset, flags.offset + flags.limit);
50
+ if (flags.json) {
51
+ this.log(output({ values: validators, total, limit: flags.limit, offset: flags.offset }));
52
+ }
53
+ else {
54
+ this.log(formatValidators(validators, total));
55
+ }
56
+ }
57
+ catch (error) {
58
+ if (error instanceof Error) {
59
+ this.log(formatError(error, flags.verbose));
60
+ this.exit(1);
61
+ }
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class ValidatorSales extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
+ offset: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,52 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { EchoClient } from '../../lib/api/echo-client.js';
3
+ import { formatError } from '../../lib/formatting/error.js';
4
+ import { formatValidatorListings, output } from '../../lib/formatting/output.js';
5
+ export default class ValidatorSales extends Command {
6
+ static description = 'List validator NFTs for sale on OpenSea';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %>',
9
+ '<%= config.bin %> <%= command.id %> --limit 20 --json',
10
+ ];
11
+ static flags = {
12
+ json: Flags.boolean({
13
+ char: 'j',
14
+ description: 'Output as JSON',
15
+ default: false,
16
+ }),
17
+ verbose: Flags.boolean({
18
+ char: 'v',
19
+ description: 'Show detailed error information',
20
+ default: false,
21
+ }),
22
+ limit: Flags.integer({
23
+ char: 'l',
24
+ description: 'Max results per request',
25
+ default: 10,
26
+ }),
27
+ offset: Flags.integer({
28
+ char: 'o',
29
+ description: 'Number of results to skip',
30
+ default: 0,
31
+ }),
32
+ };
33
+ async run() {
34
+ const { flags } = await this.parse(ValidatorSales);
35
+ const client = new EchoClient();
36
+ try {
37
+ const response = await client.getValidatorListings({ limit: flags.limit, offset: flags.offset });
38
+ if (flags.json) {
39
+ this.log(output(response));
40
+ }
41
+ else {
42
+ this.log(formatValidatorListings(response.values, response.total));
43
+ }
44
+ }
45
+ catch (error) {
46
+ if (error instanceof Error) {
47
+ this.log(formatError(error, flags.verbose));
48
+ this.exit(1);
49
+ }
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,17 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class VouchInfo extends Command {
3
+ static aliases: string[];
4
+ static args: {
5
+ id: import("@oclif/core/interfaces").Arg<number, {
6
+ max?: number;
7
+ min?: number;
8
+ }>;
9
+ };
10
+ static description: string;
11
+ static examples: string[];
12
+ static flags: {
13
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,53 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { EchoClient } from '../../lib/api/echo-client.js';
3
+ import { formatError } from '../../lib/formatting/error.js';
4
+ import { formatVouch, output } from '../../lib/formatting/output.js';
5
+ export default class VouchInfo extends Command {
6
+ static aliases = ['vi'];
7
+ static args = {
8
+ id: Args.integer({
9
+ description: 'Vouch ID',
10
+ required: true,
11
+ }),
12
+ };
13
+ static description = 'Get details of a specific vouch';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %> 123',
16
+ '<%= config.bin %> <%= command.id %> 123 --json',
17
+ ];
18
+ static flags = {
19
+ json: Flags.boolean({
20
+ char: 'j',
21
+ description: 'Output as JSON',
22
+ default: false,
23
+ }),
24
+ verbose: Flags.boolean({
25
+ char: 'v',
26
+ description: 'Show detailed error information',
27
+ default: false,
28
+ }),
29
+ };
30
+ async run() {
31
+ const { args, flags } = await this.parse(VouchInfo);
32
+ const client = new EchoClient();
33
+ try {
34
+ const response = await client.getVouches({ ids: [args.id], limit: 1 });
35
+ if (!response.values.length) {
36
+ this.error(`Vouch #${args.id} not found`, { exit: 1 });
37
+ }
38
+ const vouch = response.values[0];
39
+ if (flags.json) {
40
+ this.log(output(vouch));
41
+ }
42
+ else {
43
+ this.log(formatVouch(vouch));
44
+ }
45
+ }
46
+ catch (error) {
47
+ if (error instanceof Error) {
48
+ this.log(formatError(error, flags.verbose));
49
+ this.exit(1);
50
+ }
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,18 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class VouchList extends Command {
3
+ static aliases: string[];
4
+ static args: {
5
+ identifier: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ author: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ active: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
15
+ offset: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,89 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { EchoClient } from '../../lib/api/echo-client.js';
3
+ import { formatError } from '../../lib/formatting/error.js';
4
+ import { formatVouches, output } from '../../lib/formatting/output.js';
5
+ export default class VouchList extends Command {
6
+ static aliases = ['vl'];
7
+ static args = {
8
+ identifier: Args.string({
9
+ description: 'Twitter username, ETH address, or ENS name (optional, filter by subject)',
10
+ required: false,
11
+ }),
12
+ };
13
+ static description = 'List vouches for a user or all vouches';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %>',
16
+ '<%= config.bin %> <%= command.id %> 0xNowater',
17
+ '<%= config.bin %> <%= command.id %> --author 0xNowater',
18
+ '<%= config.bin %> <%= command.id %> --active',
19
+ '<%= config.bin %> <%= command.id %> --limit 20 --json',
20
+ ];
21
+ static flags = {
22
+ json: Flags.boolean({
23
+ char: 'j',
24
+ description: 'Output as JSON',
25
+ default: false,
26
+ }),
27
+ verbose: Flags.boolean({
28
+ char: 'v',
29
+ description: 'Show detailed error information',
30
+ default: false,
31
+ }),
32
+ author: Flags.string({
33
+ description: 'Filter by author (Twitter username, ETH address, or ENS name)',
34
+ }),
35
+ active: Flags.boolean({
36
+ description: 'Show only active (non-archived) vouches',
37
+ default: false,
38
+ }),
39
+ limit: Flags.integer({
40
+ char: 'l',
41
+ description: 'Max results per request',
42
+ default: 10,
43
+ }),
44
+ offset: Flags.integer({
45
+ char: 'o',
46
+ description: 'Number of results to skip',
47
+ default: 0,
48
+ }),
49
+ };
50
+ async run() {
51
+ const { args, flags } = await this.parse(VouchList);
52
+ const client = new EchoClient();
53
+ try {
54
+ const params = {
55
+ limit: flags.limit,
56
+ offset: flags.offset,
57
+ };
58
+ if (flags.active) {
59
+ params.archived = false;
60
+ }
61
+ if (args.identifier) {
62
+ const user = await client.resolveUser(args.identifier);
63
+ const userkey = client.getPrimaryUserkey(user);
64
+ if (userkey) {
65
+ params.subjectUserkeys = [userkey];
66
+ }
67
+ }
68
+ if (flags.author) {
69
+ const authorUser = await client.resolveUser(flags.author);
70
+ if (authorUser.profileId) {
71
+ params.authorProfileIds = [authorUser.profileId];
72
+ }
73
+ }
74
+ const response = await client.getVouches(params);
75
+ if (flags.json) {
76
+ this.log(output(response));
77
+ }
78
+ else {
79
+ this.log(formatVouches(response.values, response.total));
80
+ }
81
+ }
82
+ catch (error) {
83
+ if (error instanceof Error) {
84
+ this.log(formatError(error, flags.verbose));
85
+ this.exit(1);
86
+ }
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,15 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class VouchMutual extends Command {
3
+ static args: {
4
+ viewer: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ target: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,68 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { EchoClient } from '../../lib/api/echo-client.js';
3
+ import { formatError } from '../../lib/formatting/error.js';
4
+ import { formatMutualVouchers, output } from '../../lib/formatting/output.js';
5
+ export default class VouchMutual extends Command {
6
+ static args = {
7
+ viewer: Args.string({
8
+ description: 'Viewer user (Twitter username, ETH address, or ENS name)',
9
+ required: true,
10
+ }),
11
+ target: Args.string({
12
+ description: 'Target user (Twitter username, ETH address, or ENS name)',
13
+ required: true,
14
+ }),
15
+ };
16
+ static description = 'Find mutual vouchers between two users';
17
+ static examples = [
18
+ '<%= config.bin %> <%= command.id %> 0xNowater VitalikButerin',
19
+ '<%= config.bin %> <%= command.id %> 0xNowater VitalikButerin --limit 20',
20
+ '<%= config.bin %> <%= command.id %> 0xNowater VitalikButerin --json',
21
+ ];
22
+ static flags = {
23
+ json: Flags.boolean({
24
+ char: 'j',
25
+ description: 'Output as JSON',
26
+ default: false,
27
+ }),
28
+ verbose: Flags.boolean({
29
+ char: 'v',
30
+ description: 'Show detailed error information',
31
+ default: false,
32
+ }),
33
+ limit: Flags.integer({
34
+ char: 'l',
35
+ description: 'Max results',
36
+ default: 10,
37
+ }),
38
+ };
39
+ async run() {
40
+ const { args, flags } = await this.parse(VouchMutual);
41
+ const client = new EchoClient();
42
+ try {
43
+ const [viewerUser, targetUser] = await Promise.all([
44
+ client.resolveUser(args.viewer),
45
+ client.resolveUser(args.target),
46
+ ]);
47
+ if (!viewerUser.profileId) {
48
+ this.error(`User ${args.viewer} does not have an Ethos profile`, { exit: 1 });
49
+ }
50
+ if (!targetUser.profileId) {
51
+ this.error(`User ${args.target} does not have an Ethos profile`, { exit: 1 });
52
+ }
53
+ const response = await client.getMutualVouchers(viewerUser.profileId, targetUser.profileId, { limit: flags.limit });
54
+ if (flags.json) {
55
+ this.log(output(response));
56
+ }
57
+ else {
58
+ this.log(formatMutualVouchers(response.values, response.total));
59
+ }
60
+ }
61
+ catch (error) {
62
+ if (error instanceof Error) {
63
+ this.log(formatError(error, flags.verbose));
64
+ this.exit(1);
65
+ }
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,21 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class VouchVotes extends Command {
3
+ static args: {
4
+ id: import("@oclif/core/interfaces").Arg<number, {
5
+ max?: number;
6
+ min?: number;
7
+ }>;
8
+ };
9
+ static description: string;
10
+ static examples: string[];
11
+ static flags: {
12
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ stats: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ upvotes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ downvotes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
18
+ offset: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
19
+ };
20
+ run(): Promise<void>;
21
+ }