@paylobster/cli 4.0.2 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IMPLEMENTATION_SUMMARY.md +288 -0
- package/NEW_FEATURES.md +228 -0
- package/dist/src/commands/bridge.d.ts +6 -0
- package/dist/src/commands/bridge.d.ts.map +1 -0
- package/dist/src/commands/bridge.js +273 -0
- package/dist/src/commands/bridge.js.map +1 -0
- package/dist/src/commands/cascade.d.ts +3 -0
- package/dist/src/commands/cascade.d.ts.map +1 -0
- package/dist/src/commands/cascade.js +242 -0
- package/dist/src/commands/cascade.js.map +1 -0
- package/dist/src/commands/compliance.d.ts +3 -0
- package/dist/src/commands/compliance.d.ts.map +1 -0
- package/dist/src/commands/compliance.js +121 -0
- package/dist/src/commands/compliance.js.map +1 -0
- package/dist/src/commands/credit-score.d.ts +3 -0
- package/dist/src/commands/credit-score.d.ts.map +1 -0
- package/dist/src/commands/credit-score.js +174 -0
- package/dist/src/commands/credit-score.js.map +1 -0
- package/dist/src/commands/dispute.d.ts +3 -0
- package/dist/src/commands/dispute.d.ts.map +1 -0
- package/dist/src/commands/dispute.js +241 -0
- package/dist/src/commands/dispute.js.map +1 -0
- package/dist/src/commands/intent.d.ts +3 -0
- package/dist/src/commands/intent.d.ts.map +1 -0
- package/dist/src/commands/intent.js +227 -0
- package/dist/src/commands/intent.js.map +1 -0
- package/dist/src/commands/oracle.d.ts +3 -0
- package/dist/src/commands/oracle.d.ts.map +1 -0
- package/dist/src/commands/oracle.js +114 -0
- package/dist/src/commands/oracle.js.map +1 -0
- package/dist/src/commands/portfolio.d.ts +6 -0
- package/dist/src/commands/portfolio.d.ts.map +1 -0
- package/dist/src/commands/portfolio.js +179 -0
- package/dist/src/commands/portfolio.js.map +1 -0
- package/dist/src/commands/revenue-share.d.ts +3 -0
- package/dist/src/commands/revenue-share.d.ts.map +1 -0
- package/dist/src/commands/revenue-share.js +185 -0
- package/dist/src/commands/revenue-share.js.map +1 -0
- package/dist/src/commands/stream.d.ts +3 -0
- package/dist/src/commands/stream.d.ts.map +1 -0
- package/dist/src/commands/stream.js +213 -0
- package/dist/src/commands/stream.js.map +1 -0
- package/dist/src/commands/swap.d.ts +6 -0
- package/dist/src/commands/swap.d.ts.map +1 -0
- package/dist/src/commands/swap.js +278 -0
- package/dist/src/commands/swap.js.map +1 -0
- package/dist/src/index.js +23 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/types.d.ts +1 -0
- package/dist/src/lib/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/commands/bridge.ts +443 -0
- package/src/commands/cascade.ts +280 -0
- package/src/commands/compliance.ts +123 -0
- package/src/commands/credit-score.ts +193 -0
- package/src/commands/dispute.ts +274 -0
- package/src/commands/intent.ts +261 -0
- package/src/commands/oracle.ts +116 -0
- package/src/commands/portfolio.ts +227 -0
- package/src/commands/revenue-share.ts +213 -0
- package/src/commands/stream.ts +244 -0
- package/src/commands/swap.ts +365 -0
- package/src/index.ts +23 -1
- package/src/lib/types.ts +1 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { success, error, info, warning, withSpinner, outputJSON, formatAddress, confirm, createTable, formatStatus } from '../lib/display';
|
|
3
|
+
import type { OutputOptions } from '../lib/types';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
export function createDisputeCommand(): Command {
|
|
8
|
+
const cmd = new Command('dispute')
|
|
9
|
+
.description('Manage escrow disputes');
|
|
10
|
+
|
|
11
|
+
// plob dispute open
|
|
12
|
+
cmd
|
|
13
|
+
.command('open')
|
|
14
|
+
.description('Open a dispute for an escrow')
|
|
15
|
+
.requiredOption('--escrow <id>', 'Escrow ID')
|
|
16
|
+
.requiredOption('--reason <reason>', 'Dispute reason')
|
|
17
|
+
.option('--evidence <file>', 'Evidence file path')
|
|
18
|
+
.option('--json', 'Output as JSON')
|
|
19
|
+
.action(async (options: {
|
|
20
|
+
escrow: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
evidence?: string;
|
|
23
|
+
} & OutputOptions) => {
|
|
24
|
+
try {
|
|
25
|
+
let evidenceHash = null;
|
|
26
|
+
|
|
27
|
+
// Handle evidence file if provided
|
|
28
|
+
if (options.evidence) {
|
|
29
|
+
const evidencePath = path.resolve(options.evidence);
|
|
30
|
+
try {
|
|
31
|
+
const evidenceData = await fs.readFile(evidencePath);
|
|
32
|
+
info(`Evidence file loaded: ${path.basename(evidencePath)} (${evidenceData.length} bytes)`);
|
|
33
|
+
|
|
34
|
+
// Placeholder: Upload to IPFS or similar
|
|
35
|
+
evidenceHash = '0x' + Math.random().toString(16).substring(2, 66);
|
|
36
|
+
info(`Evidence uploaded: ${evidenceHash}`);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
error(`Failed to read evidence file: ${err}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const disputeId = Math.floor(Math.random() * 1000000);
|
|
44
|
+
|
|
45
|
+
const txHash = await withSpinner(
|
|
46
|
+
'Opening dispute...',
|
|
47
|
+
async () => {
|
|
48
|
+
// Placeholder - implement actual contract call
|
|
49
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
50
|
+
return '0x' + Math.random().toString(16).substring(2, 66);
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (outputJSON({
|
|
55
|
+
disputeId,
|
|
56
|
+
escrowId: options.escrow,
|
|
57
|
+
reason: options.reason,
|
|
58
|
+
evidenceHash,
|
|
59
|
+
txHash,
|
|
60
|
+
}, options)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
success('Dispute opened!');
|
|
65
|
+
info(`Dispute ID: ${disputeId}`);
|
|
66
|
+
info(`Escrow ID: ${options.escrow}`);
|
|
67
|
+
info(`Reason: ${options.reason}`);
|
|
68
|
+
if (evidenceHash) {
|
|
69
|
+
info(`Evidence: ${evidenceHash}`);
|
|
70
|
+
}
|
|
71
|
+
info(`Transaction: ${txHash}`);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
error(`Failed to open dispute: ${err}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// plob dispute submit
|
|
79
|
+
cmd
|
|
80
|
+
.command('submit')
|
|
81
|
+
.description('Submit additional evidence for a dispute')
|
|
82
|
+
.argument('<disputeId>', 'Dispute ID')
|
|
83
|
+
.requiredOption('--evidence <file>', 'Evidence file path')
|
|
84
|
+
.option('--json', 'Output as JSON')
|
|
85
|
+
.action(async (disputeId: string, options: { evidence: string } & OutputOptions) => {
|
|
86
|
+
try {
|
|
87
|
+
const evidencePath = path.resolve(options.evidence);
|
|
88
|
+
const evidenceData = await fs.readFile(evidencePath);
|
|
89
|
+
|
|
90
|
+
info(`Submitting evidence: ${path.basename(evidencePath)} (${evidenceData.length} bytes)`);
|
|
91
|
+
|
|
92
|
+
const evidenceHash = '0x' + Math.random().toString(16).substring(2, 66);
|
|
93
|
+
|
|
94
|
+
const txHash = await withSpinner(
|
|
95
|
+
'Submitting evidence...',
|
|
96
|
+
async () => {
|
|
97
|
+
// Placeholder - implement actual contract call
|
|
98
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
99
|
+
return '0x' + Math.random().toString(16).substring(2, 66);
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
if (outputJSON({
|
|
104
|
+
disputeId,
|
|
105
|
+
evidenceHash,
|
|
106
|
+
txHash,
|
|
107
|
+
}, options)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
success('Evidence submitted!');
|
|
112
|
+
info(`Dispute ID: ${disputeId}`);
|
|
113
|
+
info(`Evidence: ${evidenceHash}`);
|
|
114
|
+
info(`Transaction: ${txHash}`);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
error(`Failed to submit evidence: ${err}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// plob dispute get
|
|
122
|
+
cmd
|
|
123
|
+
.command('get')
|
|
124
|
+
.description('Get dispute details')
|
|
125
|
+
.argument('<disputeId>', 'Dispute ID')
|
|
126
|
+
.option('--json', 'Output as JSON')
|
|
127
|
+
.action(async (disputeId: string, options: OutputOptions) => {
|
|
128
|
+
try {
|
|
129
|
+
// Placeholder data
|
|
130
|
+
const dispute = {
|
|
131
|
+
id: disputeId,
|
|
132
|
+
escrowId: '123',
|
|
133
|
+
plaintiff: '0x1234567890123456789012345678901234567890',
|
|
134
|
+
defendant: '0x0987654321098765432109876543210987654321',
|
|
135
|
+
reason: 'Service not delivered as agreed',
|
|
136
|
+
status: 'pending',
|
|
137
|
+
evidence: [
|
|
138
|
+
'0xabcd1234...',
|
|
139
|
+
'0xef567890...',
|
|
140
|
+
],
|
|
141
|
+
createdAt: new Date().toISOString(),
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
if (outputJSON(dispute, options)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
console.log();
|
|
149
|
+
console.log('Dispute ID: ', dispute.id);
|
|
150
|
+
console.log('Escrow ID: ', dispute.escrowId);
|
|
151
|
+
console.log('Plaintiff: ', dispute.plaintiff);
|
|
152
|
+
console.log('Defendant: ', dispute.defendant);
|
|
153
|
+
console.log('Reason: ', dispute.reason);
|
|
154
|
+
console.log('Status: ', formatStatus(dispute.status));
|
|
155
|
+
console.log('Evidence: ', dispute.evidence.length, 'file(s)');
|
|
156
|
+
console.log('Created: ', dispute.createdAt);
|
|
157
|
+
console.log();
|
|
158
|
+
} catch (err) {
|
|
159
|
+
error(`Failed to get dispute: ${err}`);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// plob dispute settle
|
|
165
|
+
cmd
|
|
166
|
+
.command('settle')
|
|
167
|
+
.description('Settle a dispute')
|
|
168
|
+
.argument('<disputeId>', 'Dispute ID')
|
|
169
|
+
.requiredOption('--terms <terms>', 'Settlement terms')
|
|
170
|
+
.option('--yes', 'Skip confirmation')
|
|
171
|
+
.option('--json', 'Output as JSON')
|
|
172
|
+
.action(async (disputeId: string, options: {
|
|
173
|
+
terms: string;
|
|
174
|
+
yes?: boolean;
|
|
175
|
+
} & OutputOptions) => {
|
|
176
|
+
try {
|
|
177
|
+
if (!options.yes) {
|
|
178
|
+
console.log();
|
|
179
|
+
console.log('Settlement terms:', options.terms);
|
|
180
|
+
console.log();
|
|
181
|
+
|
|
182
|
+
const confirmed = await confirm(`Settle dispute ${disputeId}?`);
|
|
183
|
+
if (!confirmed) {
|
|
184
|
+
info('Cancelled');
|
|
185
|
+
process.exit(0);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const txHash = await withSpinner(
|
|
190
|
+
'Settling dispute...',
|
|
191
|
+
async () => {
|
|
192
|
+
// Placeholder - implement actual contract call
|
|
193
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
194
|
+
return '0x' + Math.random().toString(16).substring(2, 66);
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
if (outputJSON({
|
|
199
|
+
disputeId,
|
|
200
|
+
terms: options.terms,
|
|
201
|
+
txHash,
|
|
202
|
+
}, options)) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
success('Dispute settled!');
|
|
207
|
+
info(`Dispute ID: ${disputeId}`);
|
|
208
|
+
info(`Terms: ${options.terms}`);
|
|
209
|
+
info(`Transaction: ${txHash}`);
|
|
210
|
+
} catch (err) {
|
|
211
|
+
error(`Failed to settle dispute: ${err}`);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// plob dispute list
|
|
217
|
+
cmd
|
|
218
|
+
.command('list')
|
|
219
|
+
.description('List disputes')
|
|
220
|
+
.option('--json', 'Output as JSON')
|
|
221
|
+
.action(async (options: OutputOptions) => {
|
|
222
|
+
try {
|
|
223
|
+
// Placeholder data
|
|
224
|
+
const disputes = [
|
|
225
|
+
{
|
|
226
|
+
id: 1,
|
|
227
|
+
escrowId: 123,
|
|
228
|
+
plaintiff: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
|
|
229
|
+
defendant: '0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199',
|
|
230
|
+
reason: 'Service not delivered',
|
|
231
|
+
status: 'pending',
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
id: 2,
|
|
235
|
+
escrowId: 456,
|
|
236
|
+
plaintiff: '0x1234567890123456789012345678901234567890',
|
|
237
|
+
defendant: '0x0987654321098765432109876543210987654321',
|
|
238
|
+
reason: 'Quality issues',
|
|
239
|
+
status: 'settled',
|
|
240
|
+
},
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
if (outputJSON(disputes, options)) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (disputes.length === 0) {
|
|
248
|
+
info('No disputes found');
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const table = createTable({
|
|
253
|
+
head: ['ID', 'Escrow', 'Plaintiff', 'Defendant', 'Status'],
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
for (const dispute of disputes) {
|
|
257
|
+
table.push([
|
|
258
|
+
dispute.id,
|
|
259
|
+
dispute.escrowId,
|
|
260
|
+
formatAddress(dispute.plaintiff),
|
|
261
|
+
formatAddress(dispute.defendant),
|
|
262
|
+
formatStatus(dispute.status),
|
|
263
|
+
]);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
console.log(table.toString());
|
|
267
|
+
} catch (err) {
|
|
268
|
+
error(`Failed to list disputes: ${err}`);
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
return cmd;
|
|
274
|
+
}
|
|
@@ -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
|
+
}
|