agent-escrow 0.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.
- package/LICENSE +21 -0
- package/PROTOCOL.md +180 -0
- package/README.md +179 -0
- package/package.json +57 -0
- package/src/bid.cjs +92 -0
- package/src/cli.cjs +263 -0
- package/src/delivery.cjs +85 -0
- package/src/escrow.cjs +97 -0
- package/src/index.cjs +50 -0
- package/src/marketplace.cjs +362 -0
- package/src/nostr.cjs +150 -0
- package/src/resolution.cjs +80 -0
- package/src/task.cjs +148 -0
- package/src/trust.cjs +120 -0
package/src/cli.cjs
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { createMarketplace, TASK_STATUS } = require('./index.cjs');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const COMMANDS = {
|
|
9
|
+
'post': 'Post a new task',
|
|
10
|
+
'browse': 'Browse open tasks',
|
|
11
|
+
'bid': 'Bid on a task',
|
|
12
|
+
'bids': 'View bids for a task',
|
|
13
|
+
'deliver': 'Submit work for a task',
|
|
14
|
+
'approve': 'Approve delivery and pay worker',
|
|
15
|
+
'dispute': 'Dispute a delivery',
|
|
16
|
+
'cancel': 'Cancel an open task',
|
|
17
|
+
'help': 'Show this help'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function usage() {
|
|
21
|
+
console.log('agent-escrow — Decentralized marketplace for AI agents\n');
|
|
22
|
+
console.log('Usage: agent-escrow <command> [options]\n');
|
|
23
|
+
console.log('Commands:');
|
|
24
|
+
for (const [cmd, desc] of Object.entries(COMMANDS)) {
|
|
25
|
+
console.log(` ${cmd.padEnd(12)} ${desc}`);
|
|
26
|
+
}
|
|
27
|
+
console.log('\nEnvironment:');
|
|
28
|
+
console.log(' NOSTR_SECRET_KEY Nostr secret key (hex)');
|
|
29
|
+
console.log(' NWC_URL Nostr Wallet Connect URL');
|
|
30
|
+
console.log(' LIGHTNING_ADDRESS Your Lightning address');
|
|
31
|
+
console.log(' ESCROW_RELAYS Comma-separated relay URLs');
|
|
32
|
+
console.log('\nOr provide a JSON config via --config <path>');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parseArgs(args) {
|
|
36
|
+
const result = { _: [] };
|
|
37
|
+
for (let i = 0; i < args.length; i++) {
|
|
38
|
+
if (args[i].startsWith('--')) {
|
|
39
|
+
const key = args[i].slice(2);
|
|
40
|
+
const val = args[i + 1] && !args[i + 1].startsWith('--') ? args[++i] : true;
|
|
41
|
+
result[key] = val;
|
|
42
|
+
} else {
|
|
43
|
+
result._.push(args[i]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function loadConfig(args) {
|
|
50
|
+
// Try config file
|
|
51
|
+
if (args.config) {
|
|
52
|
+
const raw = fs.readFileSync(args.config, 'utf8');
|
|
53
|
+
return JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Try environment
|
|
57
|
+
const secretKey = args['secret-key'] || process.env.NOSTR_SECRET_KEY;
|
|
58
|
+
if (!secretKey) {
|
|
59
|
+
console.error('Error: No secret key. Set NOSTR_SECRET_KEY or use --secret-key');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
secretKey,
|
|
65
|
+
nwcUrl: args['nwc-url'] || process.env.NWC_URL,
|
|
66
|
+
lightningAddress: args['ln-address'] || process.env.LIGHTNING_ADDRESS,
|
|
67
|
+
relays: (args.relays || process.env.ESCROW_RELAYS || 'wss://relay.damus.io,wss://nos.lol').split(',')
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function main() {
|
|
72
|
+
const args = parseArgs(process.argv.slice(2));
|
|
73
|
+
const command = args._[0];
|
|
74
|
+
|
|
75
|
+
if (!command || command === 'help') {
|
|
76
|
+
usage();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!COMMANDS[command]) {
|
|
81
|
+
console.error(`Unknown command: ${command}\nRun 'agent-escrow help' for usage`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const config = loadConfig(args);
|
|
86
|
+
const market = createMarketplace(config);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
switch (command) {
|
|
90
|
+
case 'post': {
|
|
91
|
+
const title = args.title || args._[1];
|
|
92
|
+
const budget = parseInt(args.budget || args._[2], 10);
|
|
93
|
+
if (!title || !budget) {
|
|
94
|
+
console.error('Usage: agent-escrow post --title "..." --budget <sats> [--caps "a,b"] [--min-trust N] [--deadline <ms>]');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
const task = await market.postTask({
|
|
98
|
+
title,
|
|
99
|
+
description: args.description || args.desc || '',
|
|
100
|
+
budget,
|
|
101
|
+
capabilities: args.caps ? args.caps.split(',') : [],
|
|
102
|
+
minTrust: args['min-trust'] ? parseInt(args['min-trust'], 10) : undefined,
|
|
103
|
+
deadline: args.deadline ? parseInt(args.deadline, 10) : undefined
|
|
104
|
+
});
|
|
105
|
+
console.log('✅ Task posted!');
|
|
106
|
+
console.log(` ID: ${task.taskId}`);
|
|
107
|
+
console.log(` Title: ${task.title}`);
|
|
108
|
+
console.log(` Budget: ${task.budget} sats`);
|
|
109
|
+
console.log(` Event: ${task.eventId}`);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
case 'browse': {
|
|
114
|
+
const tasks = await market.browseTasks({
|
|
115
|
+
capabilities: args.caps ? args.caps.split(',') : undefined,
|
|
116
|
+
minBudget: args['min-budget'] ? parseInt(args['min-budget'], 10) : undefined,
|
|
117
|
+
maxBudget: args['max-budget'] ? parseInt(args['max-budget'], 10) : undefined,
|
|
118
|
+
limit: args.limit ? parseInt(args.limit, 10) : 20
|
|
119
|
+
});
|
|
120
|
+
if (tasks.length === 0) {
|
|
121
|
+
console.log('No open tasks found.');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
console.log(`Found ${tasks.length} open tasks:\n`);
|
|
125
|
+
for (const task of tasks) {
|
|
126
|
+
const caps = task.capabilities.length > 0 ? ` [${task.capabilities.join(', ')}]` : '';
|
|
127
|
+
const trust = task.minTrust ? ` (trust≥${task.minTrust})` : '';
|
|
128
|
+
console.log(` 📋 ${task.title}${caps}${trust}`);
|
|
129
|
+
console.log(` Budget: ${task.budget} sats | Poster: ${task.poster.slice(0, 12)}...`);
|
|
130
|
+
console.log(` Event: ${task.eventId}`);
|
|
131
|
+
if (task.description) console.log(` ${task.description.slice(0, 100)}${task.description.length > 100 ? '...' : ''}`);
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
case 'bid': {
|
|
138
|
+
const taskEventId = args.task || args._[1];
|
|
139
|
+
const posterPubkey = args.poster || args._[2];
|
|
140
|
+
const amount = parseInt(args.amount || args._[3], 10);
|
|
141
|
+
if (!taskEventId || !posterPubkey || !amount) {
|
|
142
|
+
console.error('Usage: agent-escrow bid --task <event-id> --poster <pubkey> --amount <sats> [--message "..."] [--eta <ms>]');
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
const bid = await market.submitBid({
|
|
146
|
+
taskEventId,
|
|
147
|
+
posterPubkey,
|
|
148
|
+
amount,
|
|
149
|
+
message: args.message || '',
|
|
150
|
+
eta: args.eta ? parseInt(args.eta, 10) : undefined
|
|
151
|
+
});
|
|
152
|
+
console.log('✅ Bid submitted!');
|
|
153
|
+
console.log(` Amount: ${bid.amount} sats`);
|
|
154
|
+
console.log(` Event: ${bid.eventId}`);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
case 'bids': {
|
|
159
|
+
const taskEventId = args.task || args._[1];
|
|
160
|
+
if (!taskEventId) {
|
|
161
|
+
console.error('Usage: agent-escrow bids --task <event-id>');
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
const bids = await market.getBids(taskEventId);
|
|
165
|
+
if (bids.length === 0) {
|
|
166
|
+
console.log('No bids found.');
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
console.log(`Found ${bids.length} bids:\n`);
|
|
170
|
+
for (const bid of bids) {
|
|
171
|
+
console.log(` 💰 ${bid.amount} sats — ${bid.bidder.slice(0, 12)}...`);
|
|
172
|
+
console.log(` LN: ${bid.lightningAddress}`);
|
|
173
|
+
if (bid.message) console.log(` "${bid.message}"`);
|
|
174
|
+
console.log(` Event: ${bid.eventId}`);
|
|
175
|
+
console.log();
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
case 'deliver': {
|
|
181
|
+
const taskEventId = args.task || args._[1];
|
|
182
|
+
const posterPubkey = args.poster || args._[2];
|
|
183
|
+
const result = args.result || args._[3];
|
|
184
|
+
if (!taskEventId || !posterPubkey || !result) {
|
|
185
|
+
console.error('Usage: agent-escrow deliver --task <event-id> --poster <pubkey> --result "..."');
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
// If result is a file path, read it
|
|
189
|
+
let deliverable = result;
|
|
190
|
+
if (fs.existsSync(result)) {
|
|
191
|
+
deliverable = fs.readFileSync(result, 'utf8');
|
|
192
|
+
}
|
|
193
|
+
const delivery = await market.deliver({
|
|
194
|
+
taskEventId,
|
|
195
|
+
posterPubkey,
|
|
196
|
+
result: deliverable
|
|
197
|
+
});
|
|
198
|
+
console.log('✅ Work delivered!');
|
|
199
|
+
console.log(` Hash: ${delivery.hash}`);
|
|
200
|
+
console.log(` Event: ${delivery.eventId}`);
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
case 'approve': {
|
|
205
|
+
const taskId = args.task || args._[1];
|
|
206
|
+
const workerPubkey = args.worker || args._[2];
|
|
207
|
+
const workerLn = args['worker-ln'] || args._[3];
|
|
208
|
+
const amount = parseInt(args.amount || args._[4], 10);
|
|
209
|
+
if (!taskId || !workerPubkey || !amount) {
|
|
210
|
+
console.error('Usage: agent-escrow approve --task <task-id> --worker <pubkey> --amount <sats> [--worker-ln <address>]');
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
const result = await market.approve({
|
|
214
|
+
taskId,
|
|
215
|
+
workerPubkey,
|
|
216
|
+
workerLightningAddress: workerLn,
|
|
217
|
+
amount,
|
|
218
|
+
message: args.message
|
|
219
|
+
});
|
|
220
|
+
console.log('✅ Task approved!');
|
|
221
|
+
if (result.payment && result.payment.preimage) {
|
|
222
|
+
console.log(` Payment: ${amount} sats`);
|
|
223
|
+
console.log(` Preimage: ${result.payment.preimage}`);
|
|
224
|
+
} else if (result.payment && result.payment.manual) {
|
|
225
|
+
console.log(` ⚠️ Manual payment needed: ${amount} sats to worker`);
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
case 'dispute': {
|
|
231
|
+
const taskId = args.task || args._[1];
|
|
232
|
+
const workerPubkey = args.worker || args._[2];
|
|
233
|
+
const reason = args.reason || args._[3];
|
|
234
|
+
if (!taskId || !workerPubkey || !reason) {
|
|
235
|
+
console.error('Usage: agent-escrow dispute --task <task-id> --worker <pubkey> --reason "..."');
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
await market.dispute({ taskId, workerPubkey, reason });
|
|
239
|
+
console.log('⚠️ Task disputed.');
|
|
240
|
+
console.log(` Reason: ${reason}`);
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
case 'cancel': {
|
|
245
|
+
const taskId = args.task || args._[1];
|
|
246
|
+
if (!taskId) {
|
|
247
|
+
console.error('Usage: agent-escrow cancel --task <task-id>');
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
await market.cancelTask(taskId);
|
|
251
|
+
console.log('✅ Task cancelled.');
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
} finally {
|
|
256
|
+
await market.close();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
main().catch(err => {
|
|
261
|
+
console.error('Error:', err.message);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
});
|
package/src/delivery.cjs
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const { KINDS, queryRelays, getTag } = require('./nostr.cjs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Create a delivery event template
|
|
8
|
+
*/
|
|
9
|
+
function createDeliveryEvent(opts) {
|
|
10
|
+
const {
|
|
11
|
+
taskEventId,
|
|
12
|
+
posterPubkey,
|
|
13
|
+
result,
|
|
14
|
+
includeHash
|
|
15
|
+
} = opts;
|
|
16
|
+
|
|
17
|
+
if (!taskEventId) throw new Error('taskEventId is required');
|
|
18
|
+
if (!posterPubkey) throw new Error('posterPubkey is required');
|
|
19
|
+
if (!result) throw new Error('result is required');
|
|
20
|
+
|
|
21
|
+
const tags = [
|
|
22
|
+
['e', taskEventId],
|
|
23
|
+
['p', posterPubkey]
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
if (includeHash !== false) {
|
|
27
|
+
const hash = crypto.createHash('sha256').update(result).digest('hex');
|
|
28
|
+
tags.push(['hash', hash]);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
kind: KINDS.DELIVERY,
|
|
33
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
34
|
+
tags,
|
|
35
|
+
content: result
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parse a delivery event into a structured object
|
|
41
|
+
*/
|
|
42
|
+
function parseDelivery(event) {
|
|
43
|
+
return {
|
|
44
|
+
eventId: event.id,
|
|
45
|
+
worker: event.pubkey,
|
|
46
|
+
taskEventId: getTag(event, 'e'),
|
|
47
|
+
posterPubkey: getTag(event, 'p'),
|
|
48
|
+
result: event.content,
|
|
49
|
+
hash: getTag(event, 'hash'),
|
|
50
|
+
createdAt: event.created_at * 1000,
|
|
51
|
+
raw: event
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Verify delivery hash matches content
|
|
57
|
+
*/
|
|
58
|
+
function verifyDelivery(delivery) {
|
|
59
|
+
if (!delivery.hash) return { valid: true, reason: 'no hash to verify' };
|
|
60
|
+
const computed = crypto.createHash('sha256').update(delivery.result).digest('hex');
|
|
61
|
+
return {
|
|
62
|
+
valid: computed === delivery.hash,
|
|
63
|
+
expected: delivery.hash,
|
|
64
|
+
actual: computed
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Find deliveries for a specific task
|
|
70
|
+
*/
|
|
71
|
+
async function findDeliveries(relays, taskEventId, timeoutMs = 8000) {
|
|
72
|
+
const filter = {
|
|
73
|
+
kinds: [KINDS.DELIVERY],
|
|
74
|
+
'#e': [taskEventId]
|
|
75
|
+
};
|
|
76
|
+
const events = await queryRelays(relays, filter, timeoutMs);
|
|
77
|
+
return events.map(parseDelivery);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
createDeliveryEvent,
|
|
82
|
+
parseDelivery,
|
|
83
|
+
verifyDelivery,
|
|
84
|
+
findDeliveries
|
|
85
|
+
};
|
package/src/escrow.cjs
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Payment coordination — optional lightning-agent dependency
|
|
5
|
+
*
|
|
6
|
+
* Handles Lightning payments between poster and worker.
|
|
7
|
+
* Falls back gracefully if lightning-agent is not installed.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
let lightningAgent = null;
|
|
11
|
+
try {
|
|
12
|
+
lightningAgent = require('lightning-agent');
|
|
13
|
+
} catch (e) {
|
|
14
|
+
// lightning-agent not installed — payment features require manual handling
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Check if Lightning payment features are available
|
|
19
|
+
*/
|
|
20
|
+
function paymentsAvailable() {
|
|
21
|
+
return lightningAgent !== null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create a wallet instance from NWC URL
|
|
26
|
+
*/
|
|
27
|
+
function createWallet(nwcUrl) {
|
|
28
|
+
if (!lightningAgent) {
|
|
29
|
+
throw new Error('lightning-agent is required for payment features. Install with: npm install lightning-agent');
|
|
30
|
+
}
|
|
31
|
+
return lightningAgent.createWallet(nwcUrl);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Pay a worker by resolving their Lightning address and paying
|
|
36
|
+
*/
|
|
37
|
+
async function payWorker(wallet, lightningAddress, amountSats, memo) {
|
|
38
|
+
if (!lightningAgent) {
|
|
39
|
+
throw new Error('lightning-agent is required for payment features');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Resolve Lightning address to get invoice
|
|
43
|
+
const invoice = await lightningAgent.resolveLightningAddress
|
|
44
|
+
? await resolveAndPay(wallet, lightningAddress, amountSats, memo)
|
|
45
|
+
: await wallet.payAddress(lightningAddress, amountSats * 1000, memo);
|
|
46
|
+
|
|
47
|
+
return invoice;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Internal: resolve address and pay
|
|
52
|
+
*/
|
|
53
|
+
async function resolveAndPay(wallet, address, amountSats, memo) {
|
|
54
|
+
const resolved = await lightningAgent.resolveLightningAddress(address, amountSats * 1000);
|
|
55
|
+
if (!resolved || !resolved.pr) {
|
|
56
|
+
throw new Error(`Failed to resolve Lightning address: ${address}`);
|
|
57
|
+
}
|
|
58
|
+
const result = await wallet.payInvoice(resolved.pr);
|
|
59
|
+
return {
|
|
60
|
+
bolt11: resolved.pr,
|
|
61
|
+
preimage: result.preimage,
|
|
62
|
+
amountSats
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Check wallet balance
|
|
68
|
+
*/
|
|
69
|
+
async function checkBalance(wallet) {
|
|
70
|
+
if (!wallet || !wallet.getBalance) return null;
|
|
71
|
+
try {
|
|
72
|
+
const balance = await wallet.getBalance();
|
|
73
|
+
return balance;
|
|
74
|
+
} catch (e) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Payment result object for manual payment flows
|
|
81
|
+
*/
|
|
82
|
+
function createManualPaymentResult(bolt11, preimage, amountSats) {
|
|
83
|
+
return {
|
|
84
|
+
bolt11: bolt11 || null,
|
|
85
|
+
preimage: preimage || null,
|
|
86
|
+
amountSats,
|
|
87
|
+
manual: true
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
paymentsAvailable,
|
|
93
|
+
createWallet,
|
|
94
|
+
payWorker,
|
|
95
|
+
checkBalance,
|
|
96
|
+
createManualPaymentResult
|
|
97
|
+
};
|
package/src/index.cjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { createMarketplace } = require('./marketplace.cjs');
|
|
4
|
+
const { KINDS, TASK_STATUS, RESOLUTION_TYPES } = require('./nostr.cjs');
|
|
5
|
+
const { createTaskEvent, parseTask, findTasks, getTask } = require('./task.cjs');
|
|
6
|
+
const { createBidEvent, parseBid, findBids } = require('./bid.cjs');
|
|
7
|
+
const { createDeliveryEvent, parseDelivery, verifyDelivery, findDeliveries } = require('./delivery.cjs');
|
|
8
|
+
const { createResolutionEvent, parseResolution, findResolutions } = require('./resolution.cjs');
|
|
9
|
+
const { trustAvailable, getTrustScore, meetsTrustThreshold } = require('./trust.cjs');
|
|
10
|
+
const { paymentsAvailable } = require('./escrow.cjs');
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
// Main factory
|
|
14
|
+
createMarketplace,
|
|
15
|
+
|
|
16
|
+
// Constants
|
|
17
|
+
KINDS,
|
|
18
|
+
TASK_STATUS,
|
|
19
|
+
RESOLUTION_TYPES,
|
|
20
|
+
|
|
21
|
+
// Low-level event creators (for custom flows)
|
|
22
|
+
createTaskEvent,
|
|
23
|
+
createBidEvent,
|
|
24
|
+
createDeliveryEvent,
|
|
25
|
+
createResolutionEvent,
|
|
26
|
+
|
|
27
|
+
// Parsers
|
|
28
|
+
parseTask,
|
|
29
|
+
parseBid,
|
|
30
|
+
parseDelivery,
|
|
31
|
+
parseResolution,
|
|
32
|
+
|
|
33
|
+
// Queries
|
|
34
|
+
findTasks,
|
|
35
|
+
findBids,
|
|
36
|
+
findDeliveries,
|
|
37
|
+
findResolutions,
|
|
38
|
+
getTask,
|
|
39
|
+
|
|
40
|
+
// Verification
|
|
41
|
+
verifyDelivery,
|
|
42
|
+
|
|
43
|
+
// Trust
|
|
44
|
+
trustAvailable,
|
|
45
|
+
getTrustScore,
|
|
46
|
+
meetsTrustThreshold,
|
|
47
|
+
|
|
48
|
+
// Payments
|
|
49
|
+
paymentsAvailable
|
|
50
|
+
};
|