@paylobster/cli 4.0.1 → 4.1.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.
Files changed (45) hide show
  1. package/README.md +78 -249
  2. package/dist/src/commands/cascade.d.ts +3 -0
  3. package/dist/src/commands/cascade.d.ts.map +1 -0
  4. package/dist/src/commands/cascade.js +242 -0
  5. package/dist/src/commands/cascade.js.map +1 -0
  6. package/dist/src/commands/compliance.d.ts +3 -0
  7. package/dist/src/commands/compliance.d.ts.map +1 -0
  8. package/dist/src/commands/compliance.js +121 -0
  9. package/dist/src/commands/compliance.js.map +1 -0
  10. package/dist/src/commands/credit-score.d.ts +3 -0
  11. package/dist/src/commands/credit-score.d.ts.map +1 -0
  12. package/dist/src/commands/credit-score.js +174 -0
  13. package/dist/src/commands/credit-score.js.map +1 -0
  14. package/dist/src/commands/dispute.d.ts +3 -0
  15. package/dist/src/commands/dispute.d.ts.map +1 -0
  16. package/dist/src/commands/dispute.js +241 -0
  17. package/dist/src/commands/dispute.js.map +1 -0
  18. package/dist/src/commands/intent.d.ts +3 -0
  19. package/dist/src/commands/intent.d.ts.map +1 -0
  20. package/dist/src/commands/intent.js +227 -0
  21. package/dist/src/commands/intent.js.map +1 -0
  22. package/dist/src/commands/oracle.d.ts +3 -0
  23. package/dist/src/commands/oracle.d.ts.map +1 -0
  24. package/dist/src/commands/oracle.js +114 -0
  25. package/dist/src/commands/oracle.js.map +1 -0
  26. package/dist/src/commands/revenue-share.d.ts +3 -0
  27. package/dist/src/commands/revenue-share.d.ts.map +1 -0
  28. package/dist/src/commands/revenue-share.js +185 -0
  29. package/dist/src/commands/revenue-share.js.map +1 -0
  30. package/dist/src/commands/stream.d.ts +3 -0
  31. package/dist/src/commands/stream.d.ts.map +1 -0
  32. package/dist/src/commands/stream.js +213 -0
  33. package/dist/src/commands/stream.js.map +1 -0
  34. package/dist/src/index.js +16 -0
  35. package/dist/src/index.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/commands/cascade.ts +280 -0
  38. package/src/commands/compliance.ts +123 -0
  39. package/src/commands/credit-score.ts +193 -0
  40. package/src/commands/dispute.ts +274 -0
  41. package/src/commands/intent.ts +261 -0
  42. package/src/commands/oracle.ts +116 -0
  43. package/src/commands/revenue-share.ts +213 -0
  44. package/src/commands/stream.ts +244 -0
  45. package/src/index.ts +16 -0
@@ -0,0 +1,261 @@
1
+ import { Command } from 'commander';
2
+ import { success, error, info, withSpinner, outputJSON, formatAddress, createTable } from '../lib/display';
3
+ import type { OutputOptions } from '../lib/types';
4
+
5
+ export function createIntentCommand(): Command {
6
+ const cmd = new Command('intent')
7
+ .description('Manage payment intents');
8
+
9
+ // plob intent post
10
+ cmd
11
+ .command('post')
12
+ .description('Post a payment intent')
13
+ .requiredOption('--description <desc>', 'Intent description')
14
+ .requiredOption('--budget <amount>', 'Budget in USDC')
15
+ .option('--tags <tags>', 'Comma-separated tags', '')
16
+ .option('--json', 'Output as JSON')
17
+ .action(async (options: {
18
+ description: string;
19
+ budget: string;
20
+ tags: string;
21
+ } & OutputOptions) => {
22
+ try {
23
+ const budget = parseFloat(options.budget);
24
+ if (isNaN(budget) || budget <= 0) {
25
+ error('Invalid budget. Must be a positive number');
26
+ process.exit(1);
27
+ }
28
+
29
+ const tags = options.tags ? options.tags.split(',').map(t => t.trim()) : [];
30
+
31
+ info('Posting payment intent');
32
+ info(`Description: ${options.description}`);
33
+ info(`Budget: ${options.budget} USDC`);
34
+ if (tags.length > 0) {
35
+ info(`Tags: ${tags.join(', ')}`);
36
+ }
37
+
38
+ const intentId = Math.floor(Math.random() * 1000000);
39
+
40
+ const txHash = await withSpinner(
41
+ 'Creating intent...',
42
+ async () => {
43
+ // Placeholder - implement actual contract call
44
+ await new Promise(resolve => setTimeout(resolve, 2000));
45
+ return '0x' + Math.random().toString(16).substring(2, 66);
46
+ }
47
+ );
48
+
49
+ if (outputJSON({
50
+ intentId,
51
+ description: options.description,
52
+ budget: options.budget,
53
+ tags,
54
+ txHash,
55
+ }, options)) {
56
+ return;
57
+ }
58
+
59
+ success('Payment intent posted!');
60
+ info(`Intent ID: ${intentId}`);
61
+ info(`Transaction: ${txHash}`);
62
+ } catch (err) {
63
+ error(`Failed to post intent: ${err}`);
64
+ process.exit(1);
65
+ }
66
+ });
67
+
68
+ // plob intent offer
69
+ cmd
70
+ .command('offer')
71
+ .description('Make an offer on an intent')
72
+ .argument('<intentId>', 'Intent ID')
73
+ .requiredOption('--amount <amount>', 'Offer amount in USDC')
74
+ .option('--message <message>', 'Offer message', '')
75
+ .option('--json', 'Output as JSON')
76
+ .action(async (intentId: string, options: {
77
+ amount: string;
78
+ message: string;
79
+ } & OutputOptions) => {
80
+ try {
81
+ const amount = parseFloat(options.amount);
82
+ if (isNaN(amount) || amount <= 0) {
83
+ error('Invalid amount. Must be a positive number');
84
+ process.exit(1);
85
+ }
86
+
87
+ const offerId = Math.floor(Math.random() * 1000000);
88
+
89
+ const txHash = await withSpinner(
90
+ 'Submitting offer...',
91
+ async () => {
92
+ // Placeholder - implement actual contract call
93
+ await new Promise(resolve => setTimeout(resolve, 1500));
94
+ return '0x' + Math.random().toString(16).substring(2, 66);
95
+ }
96
+ );
97
+
98
+ if (outputJSON({
99
+ offerId,
100
+ intentId,
101
+ amount: options.amount,
102
+ message: options.message,
103
+ txHash,
104
+ }, options)) {
105
+ return;
106
+ }
107
+
108
+ success('Offer submitted!');
109
+ info(`Offer ID: ${offerId}`);
110
+ info(`Intent ID: ${intentId}`);
111
+ info(`Amount: ${options.amount} USDC`);
112
+ if (options.message) {
113
+ info(`Message: ${options.message}`);
114
+ }
115
+ info(`Transaction: ${txHash}`);
116
+ } catch (err) {
117
+ error(`Failed to submit offer: ${err}`);
118
+ process.exit(1);
119
+ }
120
+ });
121
+
122
+ // plob intent accept
123
+ cmd
124
+ .command('accept')
125
+ .description('Accept an offer on your intent')
126
+ .argument('<intentId>', 'Intent ID')
127
+ .argument('<offerId>', 'Offer ID')
128
+ .option('--json', 'Output as JSON')
129
+ .action(async (intentId: string, offerId: string, options: OutputOptions) => {
130
+ try {
131
+ const txHash = await withSpinner(
132
+ 'Accepting offer...',
133
+ async () => {
134
+ // Placeholder - implement actual contract call
135
+ await new Promise(resolve => setTimeout(resolve, 1500));
136
+ return '0x' + Math.random().toString(16).substring(2, 66);
137
+ }
138
+ );
139
+
140
+ if (outputJSON({
141
+ intentId,
142
+ offerId,
143
+ txHash,
144
+ }, options)) {
145
+ return;
146
+ }
147
+
148
+ success('Offer accepted!');
149
+ info(`Intent ID: ${intentId}`);
150
+ info(`Offer ID: ${offerId}`);
151
+ info(`Transaction: ${txHash}`);
152
+ } catch (err) {
153
+ error(`Failed to accept offer: ${err}`);
154
+ process.exit(1);
155
+ }
156
+ });
157
+
158
+ // plob intent list
159
+ cmd
160
+ .command('list')
161
+ .description('List payment intents')
162
+ .option('--json', 'Output as JSON')
163
+ .action(async (options: OutputOptions) => {
164
+ try {
165
+ // Placeholder data
166
+ const intents = [
167
+ {
168
+ id: 1,
169
+ description: 'Code review for TypeScript project',
170
+ budget: '50 USDC',
171
+ offers: 3,
172
+ status: 'open',
173
+ },
174
+ {
175
+ id: 2,
176
+ description: 'Design new logo',
177
+ budget: '100 USDC',
178
+ offers: 5,
179
+ status: 'accepted',
180
+ },
181
+ ];
182
+
183
+ if (outputJSON(intents, options)) {
184
+ return;
185
+ }
186
+
187
+ if (intents.length === 0) {
188
+ info('No intents found');
189
+ return;
190
+ }
191
+
192
+ const table = createTable({
193
+ head: ['ID', 'Description', 'Budget', 'Offers', 'Status'],
194
+ });
195
+
196
+ for (const intent of intents) {
197
+ table.push([
198
+ intent.id,
199
+ intent.description.substring(0, 40) + (intent.description.length > 40 ? '...' : ''),
200
+ intent.budget,
201
+ intent.offers,
202
+ intent.status,
203
+ ]);
204
+ }
205
+
206
+ console.log(table.toString());
207
+ } catch (err) {
208
+ error(`Failed to list intents: ${err}`);
209
+ process.exit(1);
210
+ }
211
+ });
212
+
213
+ // plob intent get
214
+ cmd
215
+ .command('get')
216
+ .description('Get intent details')
217
+ .argument('<intentId>', 'Intent ID')
218
+ .option('--json', 'Output as JSON')
219
+ .action(async (intentId: string, options: OutputOptions) => {
220
+ try {
221
+ // Placeholder data
222
+ const intent = {
223
+ id: intentId,
224
+ creator: '0x1234567890123456789012345678901234567890',
225
+ description: 'Code review for TypeScript project',
226
+ budget: '50 USDC',
227
+ tags: ['code-review', 'typescript'],
228
+ status: 'open',
229
+ offers: [
230
+ { id: 1, provider: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', amount: '40 USDC' },
231
+ { id: 2, provider: '0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199', amount: '45 USDC' },
232
+ ],
233
+ createdAt: new Date().toISOString(),
234
+ };
235
+
236
+ if (outputJSON(intent, options)) {
237
+ return;
238
+ }
239
+
240
+ console.log();
241
+ console.log('Intent ID: ', intent.id);
242
+ console.log('Creator: ', intent.creator);
243
+ console.log('Description: ', intent.description);
244
+ console.log('Budget: ', intent.budget);
245
+ console.log('Tags: ', intent.tags.join(', '));
246
+ console.log('Status: ', intent.status);
247
+ console.log('Created: ', intent.createdAt);
248
+ console.log();
249
+ console.log('Offers:');
250
+ intent.offers.forEach((offer, i) => {
251
+ console.log(` ${offer.id}. ${formatAddress(offer.provider)} - ${offer.amount}`);
252
+ });
253
+ console.log();
254
+ } catch (err) {
255
+ error(`Failed to get intent: ${err}`);
256
+ process.exit(1);
257
+ }
258
+ });
259
+
260
+ return cmd;
261
+ }
@@ -0,0 +1,116 @@
1
+ import { Command } from 'commander';
2
+ import { success, error, info, outputJSON, formatBoolean } from '../lib/display';
3
+ import type { OutputOptions } from '../lib/types';
4
+ import chalk from 'chalk';
5
+
6
+ export function createOracleCommand(): Command {
7
+ const cmd = new Command('oracle')
8
+ .description('Check oracle requirements and status');
9
+
10
+ // plob oracle status
11
+ cmd
12
+ .command('status')
13
+ .description('Check oracle status for an escrow')
14
+ .argument('<escrowId>', 'Escrow ID')
15
+ .option('--json', 'Output as JSON')
16
+ .action(async (escrowId: string, options: OutputOptions) => {
17
+ try {
18
+ // Placeholder data
19
+ const oracleStatus = {
20
+ escrowId,
21
+ oracleRequired: true,
22
+ oracleApproved: true,
23
+ oracleProvider: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
24
+ approvalTime: new Date().toISOString(),
25
+ conditions: [
26
+ { name: 'Delivery confirmation', met: true },
27
+ { name: 'Quality threshold', met: true },
28
+ { name: 'Time limit', met: true },
29
+ ],
30
+ };
31
+
32
+ if (outputJSON(oracleStatus, options)) {
33
+ return;
34
+ }
35
+
36
+ console.log();
37
+ console.log(chalk.bold.cyan('🦞 Oracle Status'));
38
+ console.log(chalk.gray('─'.repeat(50)));
39
+ console.log('Escrow ID: ', oracleStatus.escrowId);
40
+ console.log('Oracle Required: ', formatBoolean(oracleStatus.oracleRequired));
41
+ console.log('Oracle Approved: ', formatBoolean(oracleStatus.oracleApproved));
42
+ console.log('Oracle Provider: ', oracleStatus.oracleProvider);
43
+ if (oracleStatus.approvalTime) {
44
+ console.log('Approval Time: ', oracleStatus.approvalTime);
45
+ }
46
+ console.log();
47
+ console.log(chalk.bold('Conditions:'));
48
+ oracleStatus.conditions.forEach(condition => {
49
+ console.log(` ${formatBoolean(condition.met)} ${condition.name}`);
50
+ });
51
+ console.log();
52
+
53
+ if (oracleStatus.oracleApproved) {
54
+ success('Oracle has approved this escrow');
55
+ } else {
56
+ info('Oracle approval pending');
57
+ }
58
+ } catch (err) {
59
+ error(`Failed to check oracle status: ${err}`);
60
+ process.exit(1);
61
+ }
62
+ });
63
+
64
+ // plob oracle required
65
+ cmd
66
+ .command('required')
67
+ .description('Check if oracle is required for a value')
68
+ .requiredOption('--value <amount>', 'Transaction value in USDC')
69
+ .option('--json', 'Output as JSON')
70
+ .action(async (options: { value: string } & OutputOptions) => {
71
+ try {
72
+ const value = parseFloat(options.value);
73
+ if (isNaN(value) || value < 0) {
74
+ error('Invalid value. Must be a non-negative number');
75
+ process.exit(1);
76
+ }
77
+
78
+ // Placeholder logic - oracle required for transactions > 1000 USDC
79
+ const threshold = 1000;
80
+ const required = value > threshold;
81
+
82
+ const result = {
83
+ value: options.value,
84
+ threshold: `${threshold} USDC`,
85
+ oracleRequired: required,
86
+ reason: required
87
+ ? 'Value exceeds threshold for automated release'
88
+ : 'Value is below oracle requirement threshold',
89
+ };
90
+
91
+ if (outputJSON(result, options)) {
92
+ return;
93
+ }
94
+
95
+ console.log();
96
+ console.log(chalk.bold.cyan('🦞 Oracle Requirement Check'));
97
+ console.log(chalk.gray('─'.repeat(50)));
98
+ console.log('Transaction Value: ', result.value, 'USDC');
99
+ console.log('Oracle Threshold: ', result.threshold);
100
+ console.log('Oracle Required: ', formatBoolean(result.oracleRequired));
101
+ console.log('Reason: ', result.reason);
102
+ console.log();
103
+
104
+ if (required) {
105
+ info('An oracle will be required to approve this transaction');
106
+ } else {
107
+ success('No oracle required for this transaction value');
108
+ }
109
+ } catch (err) {
110
+ error(`Failed to check oracle requirement: ${err}`);
111
+ process.exit(1);
112
+ }
113
+ });
114
+
115
+ return cmd;
116
+ }
@@ -0,0 +1,213 @@
1
+ import { Command } from 'commander';
2
+ import { success, error, info, warning, withSpinner, outputJSON, formatAddress, confirm, createTable } from '../lib/display';
3
+ import type { OutputOptions } from '../lib/types';
4
+
5
+ export function createRevenueShareCommand(): Command {
6
+ const cmd = new Command('revenue-share')
7
+ .description('Manage revenue sharing agreements');
8
+
9
+ // plob revenue-share create
10
+ cmd
11
+ .command('create')
12
+ .description('Create a revenue sharing agreement')
13
+ .requiredOption('--participants <addresses>', 'Comma-separated participant addresses')
14
+ .requiredOption('--splits <percentages>', 'Comma-separated split percentages (must sum to 100)')
15
+ .option('--json', 'Output as JSON')
16
+ .action(async (options: {
17
+ participants: string;
18
+ splits: string;
19
+ } & OutputOptions) => {
20
+ try {
21
+ const participants = options.participants.split(',').map(p => p.trim());
22
+ const splits = options.splits.split(',').map(s => parseFloat(s.trim()));
23
+
24
+ // Validate addresses
25
+ for (const participant of participants) {
26
+ if (!participant.startsWith('0x') || participant.length !== 42) {
27
+ error(`Invalid participant address: ${participant}`);
28
+ process.exit(1);
29
+ }
30
+ }
31
+
32
+ // Validate splits
33
+ if (participants.length !== splits.length) {
34
+ error('Number of participants must match number of splits');
35
+ process.exit(1);
36
+ }
37
+
38
+ for (const split of splits) {
39
+ if (isNaN(split) || split < 0 || split > 100) {
40
+ error('Each split must be between 0 and 100');
41
+ process.exit(1);
42
+ }
43
+ }
44
+
45
+ const totalSplit = splits.reduce((a, b) => a + b, 0);
46
+ if (Math.abs(totalSplit - 100) > 0.01) {
47
+ error(`Splits must sum to 100 (current: ${totalSplit})`);
48
+ process.exit(1);
49
+ }
50
+
51
+ info('Creating revenue share agreement');
52
+ participants.forEach((p, i) => {
53
+ info(` ${formatAddress(p)}: ${splits[i]}%`);
54
+ });
55
+
56
+ const shareId = Math.floor(Math.random() * 1000000);
57
+
58
+ const txHash = await withSpinner(
59
+ 'Creating revenue share...',
60
+ async () => {
61
+ // Placeholder - implement actual contract call
62
+ await new Promise(resolve => setTimeout(resolve, 2000));
63
+ return '0x' + Math.random().toString(16).substring(2, 66);
64
+ }
65
+ );
66
+
67
+ if (outputJSON({
68
+ shareId,
69
+ participants,
70
+ splits,
71
+ txHash,
72
+ }, options)) {
73
+ return;
74
+ }
75
+
76
+ success('Revenue share created!');
77
+ info(`Share ID: ${shareId}`);
78
+ info(`Transaction: ${txHash}`);
79
+ } catch (err) {
80
+ error(`Failed to create revenue share: ${err}`);
81
+ process.exit(1);
82
+ }
83
+ });
84
+
85
+ // plob revenue-share deposit
86
+ cmd
87
+ .command('deposit')
88
+ .description('Deposit funds to revenue share')
89
+ .argument('<shareId>', 'Share ID')
90
+ .requiredOption('--amount <amount>', 'Amount in USDC')
91
+ .option('--json', 'Output as JSON')
92
+ .action(async (shareId: string, options: { amount: string } & OutputOptions) => {
93
+ try {
94
+ const amount = parseFloat(options.amount);
95
+ if (isNaN(amount) || amount <= 0) {
96
+ error('Invalid amount. Must be a positive number');
97
+ process.exit(1);
98
+ }
99
+
100
+ const txHash = await withSpinner(
101
+ `Depositing ${options.amount} USDC to revenue share...`,
102
+ async () => {
103
+ // Placeholder - implement actual contract call
104
+ await new Promise(resolve => setTimeout(resolve, 1500));
105
+ return '0x' + Math.random().toString(16).substring(2, 66);
106
+ }
107
+ );
108
+
109
+ if (outputJSON({
110
+ shareId,
111
+ amount: options.amount,
112
+ txHash,
113
+ }, options)) {
114
+ return;
115
+ }
116
+
117
+ success('Deposit successful!');
118
+ info(`Share ID: ${shareId}`);
119
+ info(`Amount: ${options.amount} USDC`);
120
+ info(`Transaction: ${txHash}`);
121
+ } catch (err) {
122
+ error(`Failed to deposit: ${err}`);
123
+ process.exit(1);
124
+ }
125
+ });
126
+
127
+ // plob revenue-share distribute
128
+ cmd
129
+ .command('distribute')
130
+ .description('Distribute revenue to participants')
131
+ .argument('<shareId>', 'Share ID')
132
+ .option('--yes', 'Skip confirmation')
133
+ .option('--json', 'Output as JSON')
134
+ .action(async (shareId: string, options: { yes?: boolean } & OutputOptions) => {
135
+ try {
136
+ if (!options.yes) {
137
+ const confirmed = await confirm(`Distribute revenue for share ${shareId}?`);
138
+ if (!confirmed) {
139
+ info('Cancelled');
140
+ process.exit(0);
141
+ }
142
+ }
143
+
144
+ const txHash = await withSpinner(
145
+ 'Distributing revenue...',
146
+ async () => {
147
+ // Placeholder - implement actual contract call
148
+ await new Promise(resolve => setTimeout(resolve, 2000));
149
+ return '0x' + Math.random().toString(16).substring(2, 66);
150
+ }
151
+ );
152
+
153
+ if (outputJSON({
154
+ shareId,
155
+ txHash,
156
+ }, options)) {
157
+ return;
158
+ }
159
+
160
+ success('Revenue distributed!');
161
+ info(`Share ID: ${shareId}`);
162
+ info(`Transaction: ${txHash}`);
163
+ } catch (err) {
164
+ error(`Failed to distribute: ${err}`);
165
+ process.exit(1);
166
+ }
167
+ });
168
+
169
+ // plob revenue-share get
170
+ cmd
171
+ .command('get')
172
+ .description('Get revenue share details')
173
+ .argument('<shareId>', 'Share ID')
174
+ .option('--json', 'Output as JSON')
175
+ .action(async (shareId: string, options: OutputOptions) => {
176
+ try {
177
+ // Placeholder data
178
+ const share = {
179
+ id: shareId,
180
+ totalDeposited: '1000 USDC',
181
+ totalDistributed: '600 USDC',
182
+ pending: '400 USDC',
183
+ participants: [
184
+ { address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', split: 60, received: '360 USDC' },
185
+ { address: '0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199', split: 40, received: '240 USDC' },
186
+ ],
187
+ createdAt: new Date().toISOString(),
188
+ };
189
+
190
+ if (outputJSON(share, options)) {
191
+ return;
192
+ }
193
+
194
+ console.log();
195
+ console.log('Share ID: ', share.id);
196
+ console.log('Total Deposited: ', share.totalDeposited);
197
+ console.log('Total Distributed: ', share.totalDistributed);
198
+ console.log('Pending: ', share.pending);
199
+ console.log('Created: ', share.createdAt);
200
+ console.log();
201
+ console.log('Participants:');
202
+ share.participants.forEach(p => {
203
+ console.log(` ${formatAddress(p.address)}: ${p.split}% (received ${p.received})`);
204
+ });
205
+ console.log();
206
+ } catch (err) {
207
+ error(`Failed to get revenue share: ${err}`);
208
+ process.exit(1);
209
+ }
210
+ });
211
+
212
+ return cmd;
213
+ }