moltlaunch 2.0.0 → 2.0.2

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 (108) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +18 -18
  3. package/dist/index.js.map +1 -1
  4. package/package.json +6 -2
  5. package/.claude/commands/deploy.md +0 -33
  6. package/.claude/hooks/regenerate-docs.sh +0 -12
  7. package/.claude/settings.json +0 -15
  8. package/.env.example +0 -2
  9. package/.github/workflows/deploy.yml +0 -37
  10. package/ROADMAP.md +0 -29
  11. package/contracts/MandateEscrowV4.sol +0 -281
  12. package/contracts/mocks/MockFlaunchBuyback.sol +0 -24
  13. package/hardhat.config.cjs +0 -29
  14. package/scripts/check-deploy-cost.ts +0 -15
  15. package/scripts/deploy-escrow-v4.ts +0 -81
  16. package/scripts/deploy-escrow.cjs +0 -22
  17. package/scripts/generate-docs.ts +0 -309
  18. package/shared/manifest.json +0 -87
  19. package/site/.vscode/extensions.json +0 -4
  20. package/site/.vscode/launch.json +0 -11
  21. package/site/README.md +0 -43
  22. package/site/astro.config.mjs +0 -21
  23. package/site/functions/agent/[[path]].ts +0 -9
  24. package/site/functions/task/[[path]].ts +0 -9
  25. package/site/index.html.bak +0 -1755
  26. package/site/package-lock.json +0 -6165
  27. package/site/package.json +0 -17
  28. package/site/public/_redirects +0 -1
  29. package/site/public/art/hero.webp +0 -0
  30. package/site/public/favicon.ico +0 -0
  31. package/site/public/favicon.svg +0 -4
  32. package/site/public/logo.png +0 -0
  33. package/site/public/skill.md +0 -276
  34. package/site/src/components/AgentGridCard.astro +0 -97
  35. package/site/src/components/AgentRow.astro +0 -75
  36. package/site/src/components/Footer.astro +0 -71
  37. package/site/src/components/GigCard.astro +0 -36
  38. package/site/src/components/Navbar.astro +0 -93
  39. package/site/src/components/ReviewCard.astro +0 -29
  40. package/site/src/components/SkillPill.astro +0 -19
  41. package/site/src/components/StatusBadge.astro +0 -27
  42. package/site/src/components/TaskEntry.astro +0 -98
  43. package/site/src/layouts/Layout.astro +0 -268
  44. package/site/src/lib/api.ts +0 -342
  45. package/site/src/pages/404.astro +0 -33
  46. package/site/src/pages/admin.astro +0 -445
  47. package/site/src/pages/agent/[...id].astro +0 -678
  48. package/site/src/pages/agents/index.astro +0 -235
  49. package/site/src/pages/dashboard.astro +0 -244
  50. package/site/src/pages/docs.astro +0 -191
  51. package/site/src/pages/how.astro +0 -156
  52. package/site/src/pages/index.astro +0 -226
  53. package/site/src/pages/leaderboard.astro +0 -155
  54. package/site/src/pages/task/[...id].astro +0 -1467
  55. package/site/src/styles/global.css +0 -159
  56. package/site/tailwind.config.mjs +0 -94
  57. package/site/tsconfig.json +0 -5
  58. package/site/wrangler.toml +0 -5
  59. package/src/commands/accept.ts +0 -135
  60. package/src/commands/agents.ts +0 -190
  61. package/src/commands/approve.ts +0 -127
  62. package/src/commands/claim.ts +0 -130
  63. package/src/commands/decline.ts +0 -55
  64. package/src/commands/dispute.ts +0 -92
  65. package/src/commands/earnings.ts +0 -86
  66. package/src/commands/feedback.ts +0 -147
  67. package/src/commands/gig.ts +0 -141
  68. package/src/commands/hire.ts +0 -96
  69. package/src/commands/inbox.ts +0 -135
  70. package/src/commands/message.ts +0 -97
  71. package/src/commands/profile.ts +0 -62
  72. package/src/commands/quote.ts +0 -80
  73. package/src/commands/refund.ts +0 -82
  74. package/src/commands/register.ts +0 -250
  75. package/src/commands/resolve.ts +0 -104
  76. package/src/commands/reviews.ts +0 -78
  77. package/src/commands/revise.ts +0 -65
  78. package/src/commands/submit.ts +0 -123
  79. package/src/commands/tasks.ts +0 -224
  80. package/src/commands/view.ts +0 -122
  81. package/src/commands/wallet.ts +0 -42
  82. package/src/index.ts +0 -285
  83. package/src/lib/agent0.ts +0 -158
  84. package/src/lib/auth.ts +0 -25
  85. package/src/lib/constants.ts +0 -55
  86. package/src/lib/escrow.ts +0 -374
  87. package/src/lib/files.ts +0 -87
  88. package/src/lib/flaunch.ts +0 -277
  89. package/src/lib/mandate.ts +0 -623
  90. package/src/lib/tasks.ts +0 -466
  91. package/src/lib/types.ts +0 -112
  92. package/src/lib/wallet.ts +0 -119
  93. package/src/lib/x402.ts +0 -86
  94. package/test/MandateEscrowV4.test.cjs +0 -568
  95. package/tsconfig.json +0 -19
  96. package/tsup.config.ts +0 -15
  97. package/worker/package-lock.json +0 -1812
  98. package/worker/package.json +0 -18
  99. package/worker/src/agents.ts +0 -755
  100. package/worker/src/auth.ts +0 -126
  101. package/worker/src/files.ts +0 -40
  102. package/worker/src/index.ts +0 -963
  103. package/worker/src/profiles.ts +0 -85
  104. package/worker/src/ratelimit.ts +0 -45
  105. package/worker/src/tasks.ts +0 -498
  106. package/worker/src/types.ts +0 -95
  107. package/worker/tsconfig.json +0 -15
  108. package/worker/wrangler.toml +0 -19
package/src/lib/agent0.ts DELETED
@@ -1,158 +0,0 @@
1
- // Agent0 SDK wrapper for MANDATE
2
- // Uses official ERC-8004 SDK: https://github.com/agent0lab/agent0-ts
3
-
4
- import { SDK } from "agent0-sdk";
5
- import { BASE_RPC_URL } from "./constants.js";
6
- import type { Wallet } from "./types.js";
7
-
8
- const BASE_CHAIN_ID = 8453;
9
-
10
- /**
11
- * Get read-only SDK instance (no private key needed)
12
- */
13
- export function getReadOnlySDK() {
14
- return new SDK({
15
- chainId: BASE_CHAIN_ID,
16
- rpcUrl: BASE_RPC_URL,
17
- });
18
- }
19
-
20
- /**
21
- * Get SDK instance with signing capability
22
- */
23
- export function getSDK(wallet: Wallet) {
24
- return new SDK({
25
- chainId: BASE_CHAIN_ID,
26
- rpcUrl: BASE_RPC_URL,
27
- privateKey: wallet.privateKey,
28
- });
29
- }
30
-
31
- /**
32
- * Search for agents on Base
33
- */
34
- export async function searchAgents(options?: {
35
- name?: string;
36
- active?: boolean;
37
- x402support?: boolean;
38
- limit?: number;
39
- }) {
40
- const sdk = getReadOnlySDK();
41
-
42
- const results = await sdk.searchAgents({
43
- name: options?.name,
44
- active: options?.active,
45
- x402support: options?.x402support,
46
- });
47
-
48
- // Limit results
49
- const limit = options?.limit || 20;
50
- return results.slice(0, limit);
51
- }
52
-
53
- /**
54
- * Get a single agent by ID
55
- */
56
- export async function getAgentById(agentId: string) {
57
- const sdk = getReadOnlySDK();
58
-
59
- // Format: chainId:agentId or just agentId (defaults to current chain)
60
- const fullId = agentId.includes(":") ? agentId : `${BASE_CHAIN_ID}:${agentId}`;
61
-
62
- return sdk.getAgent(fullId);
63
- }
64
-
65
- /**
66
- * Register a new agent
67
- */
68
- export async function registerAgent(
69
- wallet: Wallet,
70
- config: {
71
- name: string;
72
- description: string;
73
- image?: string;
74
- endpoint?: string; // x402 endpoint
75
- skills?: string[];
76
- active?: boolean;
77
- metadata?: Record<string, string>; // Custom metadata (flaunchToken, priceWei, etc.)
78
- }
79
- ) {
80
- const sdk = getSDK(wallet);
81
-
82
- // Create agent
83
- const agent = sdk.createAgent(
84
- config.name,
85
- config.description,
86
- config.image || ""
87
- );
88
-
89
- // Configure x402 support if endpoint provided
90
- if (config.endpoint) {
91
- // Set as A2A endpoint (x402 compatible)
92
- await agent.setA2A(config.endpoint);
93
- agent.setTrust(true, false, false); // reputation-based trust
94
- }
95
-
96
- // Build metadata object
97
- const metadata: Record<string, string> = {};
98
-
99
- // Add skills to metadata
100
- if (config.skills && config.skills.length > 0) {
101
- metadata.skills = config.skills.join(",");
102
- }
103
-
104
- // Add custom metadata (flaunchToken, priceWei, symbol, etc.)
105
- if (config.metadata) {
106
- Object.assign(metadata, config.metadata);
107
- }
108
-
109
- // Set all metadata at once
110
- if (Object.keys(metadata).length > 0) {
111
- agent.setMetadata(metadata);
112
- }
113
-
114
- agent.setActive(config.active ?? true);
115
-
116
- // Register using IPFS (Agent0 SDK handles IPFS upload)
117
- // Note: This uses the default IPFS node, configure with pinata for production
118
- const txHandle = await agent.registerIPFS();
119
-
120
- // Wait for transaction to be mined
121
- const { receipt } = await txHandle.waitMined({ confirmations: 1 });
122
-
123
- // After registration, agent has ID and URI
124
- const agentId = agent.agentId;
125
- const agentURI = agent.agentURI;
126
-
127
- if (!agentId) {
128
- throw new Error("Registration failed: no agent ID returned");
129
- }
130
-
131
- return {
132
- agentId,
133
- agentURI: agentURI || "",
134
- txHash: txHandle.hash,
135
- };
136
- }
137
-
138
- /**
139
- * Give feedback to an agent
140
- */
141
- export async function giveFeedback(
142
- wallet: Wallet,
143
- agentId: string,
144
- score: number,
145
- tag?: string
146
- ): Promise<string> {
147
- const sdk = getSDK(wallet);
148
-
149
- const fullId = agentId.includes(":") ? agentId : `${BASE_CHAIN_ID}:${agentId}`;
150
-
151
- // Give feedback (score 0-100)
152
- const txHandle = await sdk.giveFeedback(fullId, score, tag || "mandate");
153
-
154
- // Wait for transaction to be mined
155
- await txHandle.waitMined({ confirmations: 1 });
156
-
157
- return txHandle.hash;
158
- }
package/src/lib/auth.ts DELETED
@@ -1,25 +0,0 @@
1
- // CLI-side message signing for authenticated API calls
2
- // Signs EIP-191 personal messages: moltlaunch:<action>:<taskId>:<timestamp>:<nonce>
3
-
4
- import { randomUUID } from "crypto";
5
- import { privateKeyToAccount } from "viem/accounts";
6
- import type { Wallet } from "./types.js";
7
-
8
- /** Build the message that must be signed (must match worker/src/auth.ts) */
9
- export function buildAuthMessage(action: string, taskId: string, timestamp: number, nonce: string): string {
10
- return `moltlaunch:${action}:${taskId}:${timestamp}:${nonce}`;
11
- }
12
-
13
- /** Sign an action with the wallet's private key. Includes a random nonce for replay protection. */
14
- export async function signAction(
15
- wallet: Wallet,
16
- action: string,
17
- taskId: string,
18
- ): Promise<{ signature: string; timestamp: number; nonce: string }> {
19
- const timestamp = Math.floor(Date.now() / 1000);
20
- const nonce = randomUUID();
21
- const message = buildAuthMessage(action, taskId, timestamp, nonce);
22
- const account = privateKeyToAccount(wallet.privateKey);
23
- const signature = await account.signMessage({ message });
24
- return { signature, timestamp, nonce };
25
- }
@@ -1,55 +0,0 @@
1
- // MANDATE: Molt's Autonomous Network for Distributed Agent Task Execution
2
- // Chain: Base Mainnet
3
-
4
- export const CHAIN_ID = 8453;
5
-
6
- export const CONTRACTS = {
7
- // ERC-8004 Registries (Base Mainnet) - https://github.com/erc-8004/erc-8004-contracts
8
- IDENTITY_REGISTRY: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432" as `0x${string}`,
9
- REPUTATION_REGISTRY: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63" as `0x${string}`,
10
- // Note: Validation Registry not yet deployed (optional in spec)
11
-
12
- // Flaunch (existing)
13
- FLAUNCH_FACTORY: "0x6A53F8b799bE11a2A3264eF0bfF183dCB12d9571" as `0x${string}`,
14
- POSITION_MANAGER: "0x51Bba15255406Cfe7099a42183302640ba7dAFDC" as `0x${string}`,
15
-
16
- // Base
17
- WETH: "0x4200000000000000000000000000000000000006" as `0x${string}`,
18
- MULTICALL3: "0xcA11bde05977b3631167028862bE2a173976CA11" as `0x${string}`,
19
- } as const;
20
-
21
- // Revenue Manager - collects 10% protocol fees from token trading
22
- export const REVENUE_MANAGER_ADDRESS = "0x3Bc08524d9DaaDEC9d1Af87818d809611F0fD669" as `0x${string}`;
23
-
24
- export const APIS = {
25
- FLAUNCH: "https://web2-api.flaunch.gg",
26
- FLAUNCH_DATA: "https://api.flayerlabs.xyz",
27
- MANDATE: "https://api.moltlaunch.com",
28
- } as const;
29
-
30
- export const CHAIN = {
31
- id: 8453,
32
- name: "Base",
33
- network: "base",
34
- explorer: "https://basescan.org",
35
- flaunchUrl: "https://flaunch.gg/base",
36
- } as const;
37
-
38
- // Flaunch polling config
39
- export const POLL_INTERVAL_MS = 2_000;
40
- export const POLL_TIMEOUT_MS = 120_000;
41
- export const MAX_IMAGE_SIZE_BYTES = 5 * 1024 * 1024; // 5MB
42
-
43
- // RPC endpoint - use env var for reliability (Alchemy, QuickNode, etc.)
44
- // Fallback to public Base RPC (may be rate limited)
45
- export const BASE_RPC_URL = process.env.BASE_RPC_URL || "https://mainnet.base.org";
46
-
47
- export const WALLET_PATH = ".moltlaunch/wallet.json";
48
-
49
- // Agent metadata keys (stored in ERC-8004 identity registry)
50
- export const METADATA_KEYS = {
51
- FLAUNCH_TOKEN: "flaunchToken", // Link to Flaunch token address
52
- SKILLS: "skills", // Comma-separated skill list
53
- ENDPOINT: "endpoint", // x402 hire endpoint
54
- PRICE_WEI: "priceWei", // Base price per hire in wei
55
- } as const;
package/src/lib/escrow.ts DELETED
@@ -1,374 +0,0 @@
1
- // Escrow contract interactions (V4 with dispute mechanism)
2
-
3
- import {
4
- createPublicClient,
5
- createWalletClient,
6
- http,
7
- keccak256,
8
- toBytes,
9
- parseAbi,
10
- } from "viem";
11
- import { privateKeyToAccount } from "viem/accounts";
12
- import { base } from "viem/chains";
13
- import { BASE_RPC_URL } from "./constants.js";
14
- import type { Wallet } from "./types.js";
15
-
16
- export enum EscrowStatus {
17
- Active = 0,
18
- Submitted = 1,
19
- Disputed = 2,
20
- Resolved = 3,
21
- Released = 4,
22
- Refunded = 5,
23
- }
24
-
25
- const ESCROW_ADDRESS = (process.env.ESCROW_ADDRESS ||
26
- "0x2c46054b4577b4fcdde28cb613dc2ba4b1127b0c") as `0x${string}`;
27
-
28
- const ESCROW_ABI = parseAbi([
29
- // Write functions
30
- "function deposit(bytes32 taskId, address agent, address token) external payable",
31
- "function markSubmitted(bytes32 taskId) external",
32
- "function release(bytes32 taskId) external",
33
- "function refund(bytes32 taskId) external",
34
- "function releaseAfterTimeout(bytes32 taskId) external",
35
- "function dispute(bytes32 taskId) external payable",
36
- "function resolveDispute(bytes32 taskId, bool clientWins) external",
37
- "function setDisputeFeeBps(uint256 bps) external",
38
- // View functions
39
- "function isPending(bytes32 taskId) external view returns (bool)",
40
- "function isTimedOut(bytes32 taskId) external view returns (bool)",
41
- "function isDisputed(bytes32 taskId) external view returns (bool)",
42
- "function timeUntilTimeout(bytes32 taskId) external view returns (uint256)",
43
- "function getEscrow(bytes32 taskId) external view returns (address client, address agent, address token, uint256 amount, uint256 depositedAt, uint256 submittedAt, uint256 disputeFee, uint8 status)",
44
- "function getDisputeFee(bytes32 taskId) external view returns (uint256)",
45
- "function getStatus(bytes32 taskId) external view returns (uint8)",
46
- "function disputeFeeBps() external view returns (uint256)",
47
- "function TIMEOUT() external view returns (uint256)",
48
- // Events
49
- "event Deposited(bytes32 indexed taskId, address indexed client, address indexed token, uint256 amount)",
50
- "event Submitted(bytes32 indexed taskId, address indexed agent, uint256 deadline)",
51
- "event Disputed(bytes32 indexed taskId, address indexed client, uint256 disputeFee)",
52
- "event DisputeResolved(bytes32 indexed taskId, bool clientWins)",
53
- "event BuybackBurned(bytes32 indexed taskId, address indexed token, uint256 ethAmount)",
54
- "event Refunded(bytes32 indexed taskId, address indexed client, uint256 amount)",
55
- "event FallbackToAgent(bytes32 indexed taskId, address indexed agent, uint256 amount)",
56
- ]);
57
-
58
- /**
59
- * Convert task ID string to bytes32 for contract
60
- */
61
- export function taskIdToBytes32(taskId: string): `0x${string}` {
62
- return keccak256(toBytes(taskId));
63
- }
64
-
65
- function getPublicClient() {
66
- return createPublicClient({
67
- chain: base,
68
- transport: http(BASE_RPC_URL),
69
- });
70
- }
71
-
72
- function getWalletClient(wallet: Wallet) {
73
- const account = privateKeyToAccount(wallet.privateKey);
74
- return createWalletClient({
75
- account,
76
- chain: base,
77
- transport: http(BASE_RPC_URL),
78
- });
79
- }
80
-
81
- /**
82
- * Deposit funds into escrow when client accepts a quote
83
- * V3: Now includes token address for buyback-and-burn
84
- */
85
- export async function depositEscrow(
86
- wallet: Wallet,
87
- taskId: string,
88
- agentAddress: string,
89
- tokenAddress: string,
90
- amountWei: bigint
91
- ): Promise<string> {
92
- const walletClient = getWalletClient(wallet);
93
- const taskIdBytes = taskIdToBytes32(taskId);
94
-
95
- const hash = await walletClient.writeContract({
96
- address: ESCROW_ADDRESS,
97
- abi: ESCROW_ABI,
98
- functionName: "deposit",
99
- args: [taskIdBytes, agentAddress as `0x${string}`, tokenAddress as `0x${string}`],
100
- value: amountWei,
101
- });
102
-
103
- return hash;
104
- }
105
-
106
- /**
107
- * Agent marks work as submitted (starts 24h timeout countdown)
108
- */
109
- export async function markSubmitted(
110
- wallet: Wallet,
111
- taskId: string
112
- ): Promise<string> {
113
- const walletClient = getWalletClient(wallet);
114
- const taskIdBytes = taskIdToBytes32(taskId);
115
-
116
- const hash = await walletClient.writeContract({
117
- address: ESCROW_ADDRESS,
118
- abi: ESCROW_ABI,
119
- functionName: "markSubmitted",
120
- args: [taskIdBytes],
121
- });
122
-
123
- return hash;
124
- }
125
-
126
- /**
127
- * Release funds from escrow to agent when client approves work
128
- */
129
- export async function releaseEscrow(
130
- wallet: Wallet,
131
- taskId: string
132
- ): Promise<string> {
133
- const walletClient = getWalletClient(wallet);
134
- const taskIdBytes = taskIdToBytes32(taskId);
135
-
136
- const hash = await walletClient.writeContract({
137
- address: ESCROW_ADDRESS,
138
- abi: ESCROW_ABI,
139
- functionName: "release",
140
- args: [taskIdBytes],
141
- gas: 1_000_000n, // Buyback swap needs ~750K gas
142
- });
143
-
144
- return hash;
145
- }
146
-
147
- /**
148
- * Refund funds from escrow back to client (only before submission)
149
- */
150
- export async function refundEscrow(
151
- wallet: Wallet,
152
- taskId: string
153
- ): Promise<string> {
154
- const walletClient = getWalletClient(wallet);
155
- const taskIdBytes = taskIdToBytes32(taskId);
156
-
157
- const hash = await walletClient.writeContract({
158
- address: ESCROW_ADDRESS,
159
- abi: ESCROW_ABI,
160
- functionName: "refund",
161
- args: [taskIdBytes],
162
- });
163
-
164
- return hash;
165
- }
166
-
167
- /**
168
- * Release funds after timeout (anyone can call, agent protection)
169
- */
170
- export async function releaseAfterTimeout(
171
- wallet: Wallet,
172
- taskId: string
173
- ): Promise<string> {
174
- const walletClient = getWalletClient(wallet);
175
- const taskIdBytes = taskIdToBytes32(taskId);
176
-
177
- const hash = await walletClient.writeContract({
178
- address: ESCROW_ADDRESS,
179
- abi: ESCROW_ABI,
180
- functionName: "releaseAfterTimeout",
181
- args: [taskIdBytes],
182
- });
183
-
184
- return hash;
185
- }
186
-
187
- /**
188
- * Check if escrow exists and is pending for a task
189
- */
190
- export async function isEscrowPending(taskId: string): Promise<boolean> {
191
- const publicClient = getPublicClient();
192
- const taskIdBytes = taskIdToBytes32(taskId);
193
-
194
- const pending = await publicClient.readContract({
195
- address: ESCROW_ADDRESS,
196
- abi: ESCROW_ABI,
197
- functionName: "isPending",
198
- args: [taskIdBytes],
199
- });
200
-
201
- return pending as boolean;
202
- }
203
-
204
- /**
205
- * Check if timeout has been reached
206
- */
207
- export async function isEscrowTimedOut(taskId: string): Promise<boolean> {
208
- const publicClient = getPublicClient();
209
- const taskIdBytes = taskIdToBytes32(taskId);
210
-
211
- const timedOut = await publicClient.readContract({
212
- address: ESCROW_ADDRESS,
213
- abi: ESCROW_ABI,
214
- functionName: "isTimedOut",
215
- args: [taskIdBytes],
216
- });
217
-
218
- return timedOut as boolean;
219
- }
220
-
221
- /**
222
- * Get seconds until timeout (0 if already timed out or not submitted)
223
- */
224
- export async function getTimeUntilTimeout(taskId: string): Promise<bigint> {
225
- const publicClient = getPublicClient();
226
- const taskIdBytes = taskIdToBytes32(taskId);
227
-
228
- const time = await publicClient.readContract({
229
- address: ESCROW_ADDRESS,
230
- abi: ESCROW_ABI,
231
- functionName: "timeUntilTimeout",
232
- args: [taskIdBytes],
233
- });
234
-
235
- return time as bigint;
236
- }
237
-
238
- /**
239
- * Get escrow details for a task
240
- * V4: Includes disputeFee and status enum
241
- */
242
- export async function getEscrowDetails(taskId: string): Promise<{
243
- client: string;
244
- agent: string;
245
- token: string;
246
- amount: bigint;
247
- depositedAt: bigint;
248
- submittedAt: bigint;
249
- disputeFee: bigint;
250
- status: EscrowStatus;
251
- } | null> {
252
- const publicClient = getPublicClient();
253
- const taskIdBytes = taskIdToBytes32(taskId);
254
-
255
- const result = await publicClient.readContract({
256
- address: ESCROW_ADDRESS,
257
- abi: ESCROW_ABI,
258
- functionName: "getEscrow",
259
- args: [taskIdBytes],
260
- });
261
-
262
- const [client, agent, token, amount, depositedAt, submittedAt, disputeFee, status] = result as [
263
- string,
264
- string,
265
- string,
266
- bigint,
267
- bigint,
268
- bigint,
269
- bigint,
270
- number
271
- ];
272
-
273
- if (amount === BigInt(0)) return null;
274
-
275
- return { client, agent, token, amount, depositedAt, submittedAt, disputeFee, status: status as EscrowStatus };
276
- }
277
-
278
- /**
279
- * Client disputes submitted work (must pay fee)
280
- */
281
- export async function disputeEscrow(
282
- wallet: Wallet,
283
- taskId: string,
284
- feeWei: bigint
285
- ): Promise<string> {
286
- const walletClient = getWalletClient(wallet);
287
- const taskIdBytes = taskIdToBytes32(taskId);
288
-
289
- const hash = await walletClient.writeContract({
290
- address: ESCROW_ADDRESS,
291
- abi: ESCROW_ABI,
292
- functionName: "dispute",
293
- args: [taskIdBytes],
294
- value: feeWei,
295
- });
296
-
297
- return hash;
298
- }
299
-
300
- /**
301
- * Get the required dispute fee for a task
302
- */
303
- export async function getDisputeFee(taskId: string): Promise<bigint> {
304
- const publicClient = getPublicClient();
305
- const taskIdBytes = taskIdToBytes32(taskId);
306
-
307
- const fee = await publicClient.readContract({
308
- address: ESCROW_ADDRESS,
309
- abi: ESCROW_ABI,
310
- functionName: "getDisputeFee",
311
- args: [taskIdBytes],
312
- });
313
-
314
- return fee as bigint;
315
- }
316
-
317
- /**
318
- * Check if escrow is in disputed state
319
- */
320
- export async function isEscrowDisputed(taskId: string): Promise<boolean> {
321
- const publicClient = getPublicClient();
322
- const taskIdBytes = taskIdToBytes32(taskId);
323
-
324
- const disputed = await publicClient.readContract({
325
- address: ESCROW_ADDRESS,
326
- abi: ESCROW_ABI,
327
- functionName: "isDisputed",
328
- args: [taskIdBytes],
329
- });
330
-
331
- return disputed as boolean;
332
- }
333
-
334
- /**
335
- * Get current escrow status
336
- */
337
- export async function getEscrowStatus(taskId: string): Promise<EscrowStatus> {
338
- const publicClient = getPublicClient();
339
- const taskIdBytes = taskIdToBytes32(taskId);
340
-
341
- const status = await publicClient.readContract({
342
- address: ESCROW_ADDRESS,
343
- abi: ESCROW_ABI,
344
- functionName: "getStatus",
345
- args: [taskIdBytes],
346
- });
347
-
348
- return (status as number) as EscrowStatus;
349
- }
350
-
351
- /**
352
- * Admin resolves a disputed escrow
353
- */
354
- export async function resolveEscrowDispute(
355
- wallet: Wallet,
356
- taskId: string,
357
- clientWins: boolean,
358
- ): Promise<string> {
359
- const walletClient = getWalletClient(wallet);
360
- const publicClient = getPublicClient();
361
- const taskIdBytes = taskIdToBytes32(taskId);
362
-
363
- const hash = await walletClient.writeContract({
364
- address: ESCROW_ADDRESS,
365
- abi: ESCROW_ABI,
366
- functionName: "resolveDispute",
367
- args: [taskIdBytes, clientWins],
368
- });
369
-
370
- await publicClient.waitForTransactionReceipt({ hash });
371
- return hash;
372
- }
373
-
374
- export { ESCROW_ADDRESS };
package/src/lib/files.ts DELETED
@@ -1,87 +0,0 @@
1
- // CLI helpers for uploading/downloading task files via Worker proxy
2
-
3
- import { readFileSync, statSync } from "fs";
4
- import { basename } from "path";
5
- import { APIS } from "./constants.js";
6
- import { signAction } from "./auth.js";
7
- import type { Wallet, TaskFile } from "./types.js";
8
-
9
- const API_BASE = APIS.MANDATE;
10
-
11
- /** Upload a single file to the task's R2 storage */
12
- export async function uploadFile(
13
- wallet: Wallet,
14
- taskId: string,
15
- filePath: string,
16
- ): Promise<TaskFile> {
17
- const { signature, timestamp, nonce } = await signAction(wallet, "upload", taskId);
18
- const filename = basename(filePath);
19
- const stat = statSync(filePath);
20
- const body = readFileSync(filePath);
21
-
22
- const params = new URLSearchParams({
23
- signature,
24
- timestamp: String(timestamp),
25
- nonce,
26
- filename,
27
- });
28
-
29
- const response = await fetch(
30
- `${API_BASE}/api/tasks/${taskId}/upload?${params.toString()}`,
31
- {
32
- method: "POST",
33
- headers: {
34
- "Content-Type": "application/octet-stream",
35
- "Content-Length": String(stat.size),
36
- },
37
- body,
38
- },
39
- );
40
-
41
- if (!response.ok) {
42
- const error = (await response.json()) as { error: string };
43
- throw new Error(error.error || `Upload failed: HTTP ${response.status}`);
44
- }
45
-
46
- const data = (await response.json()) as { file: TaskFile };
47
- return data.file;
48
- }
49
-
50
- /** Upload multiple files, return all file metadata */
51
- export async function uploadFiles(
52
- wallet: Wallet,
53
- taskId: string,
54
- filePaths: string[],
55
- ): Promise<TaskFile[]> {
56
- const results: TaskFile[] = [];
57
- for (const filePath of filePaths) {
58
- const file = await uploadFile(wallet, taskId, filePath);
59
- results.push(file);
60
- }
61
- return results;
62
- }
63
-
64
- /** Download a file from a task's R2 storage */
65
- export async function downloadTaskFile(
66
- taskId: string,
67
- fileKey: string,
68
- ): Promise<{ data: ArrayBuffer; contentType: string; filename: string }> {
69
- const response = await fetch(
70
- `${API_BASE}/api/tasks/${taskId}/files/${encodeURIComponent(fileKey)}`,
71
- );
72
-
73
- if (!response.ok) {
74
- const error = (await response.json()) as { error: string };
75
- throw new Error(error.error || `Download failed: HTTP ${response.status}`);
76
- }
77
-
78
- const disposition = response.headers.get("Content-Disposition") || "";
79
- const filenameMatch = disposition.match(/filename="(.+)"/);
80
- const filename = filenameMatch ? filenameMatch[1] : "file";
81
-
82
- return {
83
- data: await response.arrayBuffer(),
84
- contentType: response.headers.get("Content-Type") || "application/octet-stream",
85
- filename,
86
- };
87
- }