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.
- package/README.md +2 -2
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/.claude/commands/deploy.md +0 -33
- package/.claude/hooks/regenerate-docs.sh +0 -12
- package/.claude/settings.json +0 -15
- package/.env.example +0 -2
- package/.github/workflows/deploy.yml +0 -37
- package/ROADMAP.md +0 -29
- package/contracts/MandateEscrowV4.sol +0 -281
- package/contracts/mocks/MockFlaunchBuyback.sol +0 -24
- package/hardhat.config.cjs +0 -29
- package/scripts/check-deploy-cost.ts +0 -15
- package/scripts/deploy-escrow-v4.ts +0 -81
- package/scripts/deploy-escrow.cjs +0 -22
- package/scripts/generate-docs.ts +0 -309
- package/shared/manifest.json +0 -87
- package/site/.vscode/extensions.json +0 -4
- package/site/.vscode/launch.json +0 -11
- package/site/README.md +0 -43
- package/site/astro.config.mjs +0 -21
- package/site/functions/agent/[[path]].ts +0 -9
- package/site/functions/task/[[path]].ts +0 -9
- package/site/index.html.bak +0 -1755
- package/site/package-lock.json +0 -6165
- package/site/package.json +0 -17
- package/site/public/_redirects +0 -1
- package/site/public/art/hero.webp +0 -0
- package/site/public/favicon.ico +0 -0
- package/site/public/favicon.svg +0 -4
- package/site/public/logo.png +0 -0
- package/site/public/skill.md +0 -276
- package/site/src/components/AgentGridCard.astro +0 -97
- package/site/src/components/AgentRow.astro +0 -75
- package/site/src/components/Footer.astro +0 -71
- package/site/src/components/GigCard.astro +0 -36
- package/site/src/components/Navbar.astro +0 -93
- package/site/src/components/ReviewCard.astro +0 -29
- package/site/src/components/SkillPill.astro +0 -19
- package/site/src/components/StatusBadge.astro +0 -27
- package/site/src/components/TaskEntry.astro +0 -98
- package/site/src/layouts/Layout.astro +0 -268
- package/site/src/lib/api.ts +0 -342
- package/site/src/pages/404.astro +0 -33
- package/site/src/pages/admin.astro +0 -445
- package/site/src/pages/agent/[...id].astro +0 -678
- package/site/src/pages/agents/index.astro +0 -235
- package/site/src/pages/dashboard.astro +0 -244
- package/site/src/pages/docs.astro +0 -191
- package/site/src/pages/how.astro +0 -156
- package/site/src/pages/index.astro +0 -226
- package/site/src/pages/leaderboard.astro +0 -155
- package/site/src/pages/task/[...id].astro +0 -1467
- package/site/src/styles/global.css +0 -159
- package/site/tailwind.config.mjs +0 -94
- package/site/tsconfig.json +0 -5
- package/site/wrangler.toml +0 -5
- package/src/commands/accept.ts +0 -135
- package/src/commands/agents.ts +0 -190
- package/src/commands/approve.ts +0 -127
- package/src/commands/claim.ts +0 -130
- package/src/commands/decline.ts +0 -55
- package/src/commands/dispute.ts +0 -92
- package/src/commands/earnings.ts +0 -86
- package/src/commands/feedback.ts +0 -147
- package/src/commands/gig.ts +0 -141
- package/src/commands/hire.ts +0 -96
- package/src/commands/inbox.ts +0 -135
- package/src/commands/message.ts +0 -97
- package/src/commands/profile.ts +0 -62
- package/src/commands/quote.ts +0 -80
- package/src/commands/refund.ts +0 -82
- package/src/commands/register.ts +0 -250
- package/src/commands/resolve.ts +0 -104
- package/src/commands/reviews.ts +0 -78
- package/src/commands/revise.ts +0 -65
- package/src/commands/submit.ts +0 -123
- package/src/commands/tasks.ts +0 -224
- package/src/commands/view.ts +0 -122
- package/src/commands/wallet.ts +0 -42
- package/src/index.ts +0 -285
- package/src/lib/agent0.ts +0 -158
- package/src/lib/auth.ts +0 -25
- package/src/lib/constants.ts +0 -55
- package/src/lib/escrow.ts +0 -374
- package/src/lib/files.ts +0 -87
- package/src/lib/flaunch.ts +0 -277
- package/src/lib/mandate.ts +0 -623
- package/src/lib/tasks.ts +0 -466
- package/src/lib/types.ts +0 -112
- package/src/lib/wallet.ts +0 -119
- package/src/lib/x402.ts +0 -86
- package/test/MandateEscrowV4.test.cjs +0 -568
- package/tsconfig.json +0 -19
- package/tsup.config.ts +0 -15
- package/worker/package-lock.json +0 -1812
- package/worker/package.json +0 -18
- package/worker/src/agents.ts +0 -755
- package/worker/src/auth.ts +0 -126
- package/worker/src/files.ts +0 -40
- package/worker/src/index.ts +0 -963
- package/worker/src/profiles.ts +0 -85
- package/worker/src/ratelimit.ts +0 -45
- package/worker/src/tasks.ts +0 -498
- package/worker/src/types.ts +0 -95
- package/worker/tsconfig.json +0 -15
- package/worker/wrangler.toml +0 -19
package/worker/src/auth.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// Wallet signature verification for agent/client actions
|
|
2
|
-
// EIP-191 personal sign: moltlaunch:<action>:<taskId>:<timestamp>:<nonce>
|
|
3
|
-
|
|
4
|
-
import { recoverMessageAddress, keccak256, toBytes } from 'viem';
|
|
5
|
-
import type { Env } from './types';
|
|
6
|
-
|
|
7
|
-
const IDENTITY_REGISTRY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432';
|
|
8
|
-
const ESCROW_ADDRESS = '0x2c46054b4577b4fcdde28cb613dc2ba4b1127b0c';
|
|
9
|
-
const OWNER_SELECTOR = '0x6352211e'; // ownerOf(uint256)
|
|
10
|
-
const GET_ESCROW_SELECTOR = '0xf023b811'; // getEscrow(bytes32)
|
|
11
|
-
const MAX_TIMESTAMP_DRIFT = 300; // 5 minutes
|
|
12
|
-
const OWNER_CACHE_PREFIX = 'owner:';
|
|
13
|
-
const OWNER_CACHE_TTL = 86400; // 24 hours
|
|
14
|
-
const NONCE_PREFIX = 'nonce:';
|
|
15
|
-
|
|
16
|
-
/** Build the message that must be signed */
|
|
17
|
-
export function buildAuthMessage(action: string, taskId: string, timestamp: number, nonce: string): string {
|
|
18
|
-
return `moltlaunch:${action}:${taskId}:${timestamp}:${nonce}`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Verify signature, check nonce for replay protection, return recovered signer (lowercase) */
|
|
22
|
-
export async function verifySigner(
|
|
23
|
-
env: Env,
|
|
24
|
-
action: string,
|
|
25
|
-
taskId: string,
|
|
26
|
-
timestamp: number,
|
|
27
|
-
signature: string,
|
|
28
|
-
nonce: string,
|
|
29
|
-
): Promise<string> {
|
|
30
|
-
const now = Math.floor(Date.now() / 1000);
|
|
31
|
-
if (Math.abs(now - timestamp) > MAX_TIMESTAMP_DRIFT) {
|
|
32
|
-
throw new Error('Signature expired');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (!nonce) {
|
|
36
|
-
throw new Error('Missing nonce');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const message = buildAuthMessage(action, taskId, timestamp, nonce);
|
|
40
|
-
const address = await recoverMessageAddress({
|
|
41
|
-
message,
|
|
42
|
-
signature: signature as `0x${string}`,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Replay protection: check if nonce was already used
|
|
46
|
-
const nonceKey = `${NONCE_PREFIX}${keccak256(toBytes(nonce))}`;
|
|
47
|
-
const existing = await env.TASKS_KV.get(nonceKey);
|
|
48
|
-
if (existing) {
|
|
49
|
-
throw new Error('Nonce already used (replay detected)');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Store nonce with TTL matching timestamp drift window
|
|
53
|
-
await env.TASKS_KV.put(nonceKey, '1', { expirationTtl: MAX_TIMESTAMP_DRIFT });
|
|
54
|
-
|
|
55
|
-
return address.toLowerCase();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Get agent owner address via ownerOf() call (cached in KV for 24h) */
|
|
59
|
-
export async function getAgentOwner(env: Env, agentId: string): Promise<string> {
|
|
60
|
-
const cacheKey = `${OWNER_CACHE_PREFIX}${agentId}`;
|
|
61
|
-
const cached = await env.TASKS_KV.get(cacheKey);
|
|
62
|
-
if (cached) return cached.toLowerCase();
|
|
63
|
-
|
|
64
|
-
const rpcUrl = env.ALCHEMY_RPC || env.BASE_RPC || 'https://mainnet.base.org';
|
|
65
|
-
const id = agentId.startsWith('0x') ? BigInt(agentId) : BigInt(agentId);
|
|
66
|
-
const agentIdHex = id.toString(16).padStart(64, '0');
|
|
67
|
-
|
|
68
|
-
const res = await fetch(rpcUrl, {
|
|
69
|
-
method: 'POST',
|
|
70
|
-
headers: { 'Content-Type': 'application/json' },
|
|
71
|
-
body: JSON.stringify({
|
|
72
|
-
jsonrpc: '2.0',
|
|
73
|
-
method: 'eth_call',
|
|
74
|
-
params: [{ to: IDENTITY_REGISTRY, data: OWNER_SELECTOR + agentIdHex }, 'latest'],
|
|
75
|
-
id: 1,
|
|
76
|
-
}),
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const json = await res.json() as { result?: string; error?: { message: string } };
|
|
80
|
-
if (json.error || !json.result || json.result === '0x') {
|
|
81
|
-
throw new Error('Failed to get agent owner');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const owner = ('0x' + json.result.slice(-40)).toLowerCase();
|
|
85
|
-
await env.TASKS_KV.put(cacheKey, owner, { expirationTtl: OWNER_CACHE_TTL });
|
|
86
|
-
return owner;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Verify that escrow deposit exists on-chain for a task.
|
|
91
|
-
* Returns the deposited amount in wei, or 0 if no deposit or already released.
|
|
92
|
-
* getEscrow returns: (client, agent, token, amount, depositedAt, submittedAt, disputeFee, status)
|
|
93
|
-
*/
|
|
94
|
-
export async function verifyEscrowDeposit(env: Env, taskId: string): Promise<bigint> {
|
|
95
|
-
const rpcUrl = env.ALCHEMY_RPC || env.BASE_RPC || 'https://mainnet.base.org';
|
|
96
|
-
const taskIdBytes32 = keccak256(toBytes(taskId));
|
|
97
|
-
const taskIdHex = taskIdBytes32.slice(2);
|
|
98
|
-
|
|
99
|
-
const res = await fetch(rpcUrl, {
|
|
100
|
-
method: 'POST',
|
|
101
|
-
headers: { 'Content-Type': 'application/json' },
|
|
102
|
-
body: JSON.stringify({
|
|
103
|
-
jsonrpc: '2.0',
|
|
104
|
-
method: 'eth_call',
|
|
105
|
-
params: [{ to: ESCROW_ADDRESS, data: GET_ESCROW_SELECTOR + taskIdHex }, 'latest'],
|
|
106
|
-
id: 1,
|
|
107
|
-
}),
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const json = await res.json() as { result?: string; error?: { message: string } };
|
|
111
|
-
if (json.error || !json.result || json.result === '0x') {
|
|
112
|
-
return 0n;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// V4: status is the 8th 32-byte word (offset 224 bytes = 448 hex chars) — uint8 enum
|
|
116
|
-
// Active=0, Submitted=1, Disputed=2, Resolved=3, Released=4, Refunded=5
|
|
117
|
-
const statusHex = json.result.slice(2 + 64 * 7, 2 + 64 * 8);
|
|
118
|
-
const status = Number(BigInt('0x' + (statusHex || '0')));
|
|
119
|
-
if (status >= 4) {
|
|
120
|
-
return 0n; // Released or Refunded, treat as no deposit
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// amount is the 4th 32-byte word (offset 96 bytes = 192 hex chars)
|
|
124
|
-
const amountHex = json.result.slice(2 + 64 * 3, 2 + 64 * 4);
|
|
125
|
-
return BigInt('0x' + (amountHex || '0'));
|
|
126
|
-
}
|
package/worker/src/files.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// R2 file upload/download handlers for task file exchange
|
|
2
|
-
// Files stored at key: tasks/<taskId>/<timestamp>-<filename>
|
|
3
|
-
|
|
4
|
-
import type { Env, TaskFile } from './types';
|
|
5
|
-
|
|
6
|
-
const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25MB
|
|
7
|
-
|
|
8
|
-
/** Upload a file to R2, return metadata */
|
|
9
|
-
export async function uploadFile(
|
|
10
|
-
env: Env,
|
|
11
|
-
taskId: string,
|
|
12
|
-
filename: string,
|
|
13
|
-
body: ReadableStream | ArrayBuffer,
|
|
14
|
-
contentType: string,
|
|
15
|
-
size: number,
|
|
16
|
-
): Promise<TaskFile> {
|
|
17
|
-
if (size > MAX_FILE_SIZE) {
|
|
18
|
-
throw new Error(`File too large: ${size} bytes (max ${MAX_FILE_SIZE})`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const timestamp = Date.now();
|
|
22
|
-
// Sanitize filename to prevent path traversal
|
|
23
|
-
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
24
|
-
const key = `tasks/${taskId}/${timestamp}-${safeName}`;
|
|
25
|
-
|
|
26
|
-
await env.TASK_FILES.put(key, body, {
|
|
27
|
-
httpMetadata: { contentType },
|
|
28
|
-
customMetadata: { taskId, originalName: filename },
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
return { key, name: filename, size, uploadedAt: timestamp };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Download a file from R2, return the R2 object (or null) */
|
|
35
|
-
export async function downloadFile(
|
|
36
|
-
env: Env,
|
|
37
|
-
key: string,
|
|
38
|
-
): Promise<R2ObjectBody | null> {
|
|
39
|
-
return env.TASK_FILES.get(key);
|
|
40
|
-
}
|