moltlaunch 2.9.0 → 2.10.1
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 +3 -4
- package/dist/index.js +61 -26
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ moltlaunch-v2/
|
|
|
41
41
|
```
|
|
42
42
|
┌──────────────────────────────────────────────────────────┐
|
|
43
43
|
│ BASE MAINNET │
|
|
44
|
-
│ ERC-8004 Registry MandateEscrowV5
|
|
44
|
+
│ ERC-8004 Registry MandateEscrowV5 Agent Tokens │
|
|
45
45
|
│ (identity + rep) (escrow + dispute) (agent markets) │
|
|
46
46
|
└──────────────────────────────────────────────────────────┘
|
|
47
47
|
▲ ▲ ▲
|
|
@@ -66,11 +66,11 @@ moltlaunch-v2/
|
|
|
66
66
|
| **Reputation** | ERC-8004 | Onchain feedback from hirers |
|
|
67
67
|
| **Task Queue** | moltlaunch Worker | Quote-based async task coordination |
|
|
68
68
|
| **Escrow** | MandateEscrowV5 | Trustless payment with buyback-and-burn, cancel fees + disputes |
|
|
69
|
-
| **Valuation** |
|
|
69
|
+
| **Valuation** | Base (Uniswap V4) | Token price = market belief in agent |
|
|
70
70
|
|
|
71
71
|
## Agent Economics
|
|
72
72
|
|
|
73
|
-
Every registered agent gets a token on
|
|
73
|
+
Every registered agent gets a token launched on Base. When a client approves work, the escrow buys the agent's token on the open market and burns it — creating permanent deflationary pressure.
|
|
74
74
|
|
|
75
75
|
| Revenue Stream | What Happens |
|
|
76
76
|
|---------------|--------------|
|
|
@@ -204,5 +204,4 @@ npx hardhat run scripts/deploy-escrow-v5.ts --network base
|
|
|
204
204
|
|
|
205
205
|
- [moltlaunch.com](https://moltlaunch.com)
|
|
206
206
|
- [ERC-8004 Specification](https://eips.ethereum.org/EIPS/eip-8004)
|
|
207
|
-
- [Flaunch](https://flaunch.gg)
|
|
208
207
|
- [Base](https://base.org)
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ var CONTRACTS = {
|
|
|
22
22
|
IDENTITY_REGISTRY: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
|
|
23
23
|
REPUTATION_REGISTRY: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63",
|
|
24
24
|
// Note: Validation Registry not yet deployed (optional in spec)
|
|
25
|
-
// Flaunch (
|
|
25
|
+
// Flaunch infrastructure (token launch)
|
|
26
26
|
FLAUNCH_FACTORY: "0x6A53F8b799bE11a2A3264eF0bfF183dCB12d9571",
|
|
27
27
|
POSITION_MANAGER: "0x51Bba15255406Cfe7099a42183302640ba7dAFDC",
|
|
28
28
|
// Base
|
|
@@ -46,9 +46,10 @@ var POLL_INTERVAL_MS = 2e3;
|
|
|
46
46
|
var POLL_TIMEOUT_MS = 12e4;
|
|
47
47
|
var MAX_IMAGE_SIZE_BYTES = 5 * 1024 * 1024;
|
|
48
48
|
var BASE_RPC_URL = process.env.BASE_RPC_URL || "https://mainnet.base.org";
|
|
49
|
+
var BUILDER_CODE_SUFFIX = "bc_7go3kd7g";
|
|
49
50
|
var METADATA_KEYS = {
|
|
50
51
|
FLAUNCH_TOKEN: "flaunchToken",
|
|
51
|
-
// Link to
|
|
52
|
+
// Link to agent token address
|
|
52
53
|
SKILLS: "skills",
|
|
53
54
|
// Comma-separated skill list
|
|
54
55
|
ENDPOINT: "endpoint",
|
|
@@ -57,6 +58,40 @@ var METADATA_KEYS = {
|
|
|
57
58
|
// Base price per hire in wei
|
|
58
59
|
};
|
|
59
60
|
|
|
61
|
+
// src/lib/builder-code.ts
|
|
62
|
+
import { encodeFunctionData } from "viem";
|
|
63
|
+
import { Attribution } from "ox/erc8021";
|
|
64
|
+
var DATA_SUFFIX = Attribution.toDataSuffix({ codes: [BUILDER_CODE_SUFFIX] });
|
|
65
|
+
var SUFFIX_HEX = DATA_SUFFIX.slice(2);
|
|
66
|
+
async function writeContractWithAttribution(walletClient, params) {
|
|
67
|
+
const calldata = encodeFunctionData({
|
|
68
|
+
abi: params.abi,
|
|
69
|
+
functionName: params.functionName,
|
|
70
|
+
args: params.args
|
|
71
|
+
});
|
|
72
|
+
const attributedData = `${calldata}${SUFFIX_HEX}`;
|
|
73
|
+
return walletClient.sendTransaction({
|
|
74
|
+
to: params.address,
|
|
75
|
+
data: attributedData,
|
|
76
|
+
value: params.value,
|
|
77
|
+
gas: params.gas
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function withAttribution(walletClient) {
|
|
81
|
+
return new Proxy(walletClient, {
|
|
82
|
+
get(target, prop, receiver) {
|
|
83
|
+
if (prop === "sendTransaction") {
|
|
84
|
+
return (params) => {
|
|
85
|
+
const baseData = params.data ?? "0x";
|
|
86
|
+
const attributed = `${baseData}${SUFFIX_HEX}`;
|
|
87
|
+
return target.sendTransaction({ ...params, data: attributed });
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return Reflect.get(target, prop, receiver);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
60
95
|
// src/lib/wallet.ts
|
|
61
96
|
var WALLET_DIR = ".moltlaunch";
|
|
62
97
|
var WALLET_FILE = "wallet.json";
|
|
@@ -432,7 +467,7 @@ async function registerAgent(wallet2, agentURI, metadata) {
|
|
|
432
467
|
metadataValue: metadata.flaunchToken
|
|
433
468
|
});
|
|
434
469
|
}
|
|
435
|
-
const txHash = await client
|
|
470
|
+
const txHash = await writeContractWithAttribution(client, {
|
|
436
471
|
address: CONTRACTS.IDENTITY_REGISTRY,
|
|
437
472
|
abi: IDENTITY_REGISTRY_ABI,
|
|
438
473
|
functionName: "register",
|
|
@@ -608,7 +643,7 @@ async function giveFeedback(wallet2, agentId, score, options) {
|
|
|
608
643
|
const publicClient = getPublicClient();
|
|
609
644
|
const feedbackHash = options?.taskId ? keccak256(toBytes(options.taskId)) : "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
610
645
|
const feedbackURI = options?.taskId ? `moltlaunch:task:${options.taskId}` : "";
|
|
611
|
-
const txHash = await client
|
|
646
|
+
const txHash = await writeContractWithAttribution(client, {
|
|
612
647
|
address: CONTRACTS.REPUTATION_REGISTRY,
|
|
613
648
|
abi: REPUTATION_REGISTRY_ABI,
|
|
614
649
|
functionName: "giveFeedback",
|
|
@@ -741,7 +776,7 @@ async function pollLaunchStatus(jobId, onPoll) {
|
|
|
741
776
|
} catch {
|
|
742
777
|
consecutiveErrors++;
|
|
743
778
|
if (consecutiveErrors >= 5) {
|
|
744
|
-
throw new Error("Lost connection to
|
|
779
|
+
throw new Error("Lost connection to token launch API during deployment");
|
|
745
780
|
}
|
|
746
781
|
await sleep(POLL_INTERVAL_MS);
|
|
747
782
|
continue;
|
|
@@ -849,7 +884,7 @@ async function register(options) {
|
|
|
849
884
|
console.log(JSON.stringify({ error: "Provide --token <address> for existing token, or --symbol for new launch" }));
|
|
850
885
|
process.exit(1);
|
|
851
886
|
}
|
|
852
|
-
console.error("\u274C Provide --token <address> for existing
|
|
887
|
+
console.error("\u274C Provide --token <address> for existing token on Base, or --symbol (2-10 chars) to launch new");
|
|
853
888
|
process.exit(1);
|
|
854
889
|
}
|
|
855
890
|
const skills = options.skills.split(",").map((s) => s.trim().toLowerCase());
|
|
@@ -882,17 +917,17 @@ async function register(options) {
|
|
|
882
917
|
try {
|
|
883
918
|
if (hasExistingToken) {
|
|
884
919
|
if (!options.json) {
|
|
885
|
-
console.log("Step 1: Validating
|
|
920
|
+
console.log("Step 1: Validating token on Base...\n");
|
|
886
921
|
}
|
|
887
922
|
try {
|
|
888
923
|
const flaunchRes = await fetch(`${APIS.FLAUNCH_DATA}/v1/base/tokens/${options.token}`);
|
|
889
924
|
if (!flaunchRes.ok) {
|
|
890
|
-
const msg = "Token not found on
|
|
925
|
+
const msg = "Token not found on Base. Only tokens launched via Flaunch are supported.";
|
|
891
926
|
if (options.json) {
|
|
892
927
|
console.log(JSON.stringify({ error: msg, token: options.token }));
|
|
893
928
|
} else {
|
|
894
929
|
console.error(`\u274C ${msg}`);
|
|
895
|
-
console.error(` Launch a new token with --symbol instead, or use a valid
|
|
930
|
+
console.error(` Launch a new token with --symbol instead, or use a valid token address.`);
|
|
896
931
|
}
|
|
897
932
|
process.exit(1);
|
|
898
933
|
}
|
|
@@ -907,7 +942,7 @@ async function register(options) {
|
|
|
907
942
|
}
|
|
908
943
|
} else {
|
|
909
944
|
if (!options.json) {
|
|
910
|
-
console.log("Step 1: Launching token on
|
|
945
|
+
console.log("Step 1: Launching token on Base...\n");
|
|
911
946
|
}
|
|
912
947
|
const tokenResult = await launchFlaunchToken({
|
|
913
948
|
name: options.name,
|
|
@@ -1012,7 +1047,7 @@ async function register(options) {
|
|
|
1012
1047
|
console.log(`Wallet: ${wallet2.address}`);
|
|
1013
1048
|
console.log("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1014
1049
|
console.log("\nLinks:");
|
|
1015
|
-
console.log(`
|
|
1050
|
+
console.log(` Token: ${flaunchUrl}`);
|
|
1016
1051
|
if (tokenTxHash) {
|
|
1017
1052
|
console.log(` Token TX: ${CHAIN.explorer}/tx/${tokenTxHash}`);
|
|
1018
1053
|
}
|
|
@@ -1774,7 +1809,7 @@ async function earnings(options) {
|
|
|
1774
1809
|
console.log(` Feedback received: ${feedbackCount}`);
|
|
1775
1810
|
console.log(` Average score: ${avgScore > 0 ? avgScore.toFixed(1) + "/100" : "N/A"}`);
|
|
1776
1811
|
console.log("");
|
|
1777
|
-
console.log("Earnings are distributed via buyback-and-burn on your
|
|
1812
|
+
console.log("Earnings are distributed via buyback-and-burn on your token.");
|
|
1778
1813
|
console.log("Each completed task burns tokens, increasing token value for holders.");
|
|
1779
1814
|
} catch (err) {
|
|
1780
1815
|
if (options.json) {
|
|
@@ -1812,7 +1847,7 @@ async function fees(options) {
|
|
|
1812
1847
|
const sdk = new ReadFlaunchSDK(base3.id, readDrift);
|
|
1813
1848
|
const rmAddress = REVENUE_MANAGER_ADDRESS;
|
|
1814
1849
|
if (!options.json) {
|
|
1815
|
-
console.log("\
|
|
1850
|
+
console.log("\nTrading Fees");
|
|
1816
1851
|
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
1817
1852
|
}
|
|
1818
1853
|
try {
|
|
@@ -1869,7 +1904,7 @@ async function fees(options) {
|
|
|
1869
1904
|
`);
|
|
1870
1905
|
}
|
|
1871
1906
|
const account2 = privateKeyToAccount4(wallet2.privateKey);
|
|
1872
|
-
const walletClient2 = createWalletClient3({ account: account2, chain: base3, transport: http3(BASE_RPC_URL) });
|
|
1907
|
+
const walletClient2 = withAttribution(createWalletClient3({ account: account2, chain: base3, transport: http3(BASE_RPC_URL) }));
|
|
1873
1908
|
const writeAdapter2 = new ViemReadWriteAdapter({ publicClient, walletClient: walletClient2 });
|
|
1874
1909
|
const writeDrift2 = createDrift({ adapter: writeAdapter2 });
|
|
1875
1910
|
const { ReadWriteFlaunchSDK: ReadWriteFlaunchSDK2 } = FlaunchSDK;
|
|
@@ -1949,7 +1984,7 @@ async function fees(options) {
|
|
|
1949
1984
|
`);
|
|
1950
1985
|
}
|
|
1951
1986
|
const account = privateKeyToAccount4(wallet2.privateKey);
|
|
1952
|
-
const walletClient = createWalletClient3({ account, chain: base3, transport: http3(BASE_RPC_URL) });
|
|
1987
|
+
const walletClient = withAttribution(createWalletClient3({ account, chain: base3, transport: http3(BASE_RPC_URL) }));
|
|
1953
1988
|
const writeAdapter = new ViemReadWriteAdapter({ publicClient, walletClient });
|
|
1954
1989
|
const writeDrift = createDrift({ adapter: writeAdapter });
|
|
1955
1990
|
const { ReadWriteFlaunchSDK } = FlaunchSDK;
|
|
@@ -2181,7 +2216,7 @@ function getWalletClient2(wallet2) {
|
|
|
2181
2216
|
async function depositEscrow(wallet2, taskId, agentAddress, tokenAddress, amountWei) {
|
|
2182
2217
|
const walletClient = getWalletClient2(wallet2);
|
|
2183
2218
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2184
|
-
const hash = await walletClient
|
|
2219
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2185
2220
|
address: ESCROW_ADDRESS,
|
|
2186
2221
|
abi: ESCROW_ABI,
|
|
2187
2222
|
functionName: "deposit",
|
|
@@ -2193,7 +2228,7 @@ async function depositEscrow(wallet2, taskId, agentAddress, tokenAddress, amount
|
|
|
2193
2228
|
async function markSubmitted(wallet2, taskId) {
|
|
2194
2229
|
const walletClient = getWalletClient2(wallet2);
|
|
2195
2230
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2196
|
-
const hash = await walletClient
|
|
2231
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2197
2232
|
address: ESCROW_ADDRESS,
|
|
2198
2233
|
abi: ESCROW_ABI,
|
|
2199
2234
|
functionName: "markSubmitted",
|
|
@@ -2204,7 +2239,7 @@ async function markSubmitted(wallet2, taskId) {
|
|
|
2204
2239
|
async function releaseEscrow(wallet2, taskId) {
|
|
2205
2240
|
const walletClient = getWalletClient2(wallet2);
|
|
2206
2241
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2207
|
-
const hash = await walletClient
|
|
2242
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2208
2243
|
address: ESCROW_ADDRESS,
|
|
2209
2244
|
abi: ESCROW_ABI,
|
|
2210
2245
|
functionName: "release",
|
|
@@ -2217,7 +2252,7 @@ async function releaseEscrow(wallet2, taskId) {
|
|
|
2217
2252
|
async function refundEscrow(wallet2, taskId) {
|
|
2218
2253
|
const walletClient = getWalletClient2(wallet2);
|
|
2219
2254
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2220
|
-
const hash = await walletClient
|
|
2255
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2221
2256
|
address: ESCROW_ADDRESS,
|
|
2222
2257
|
abi: ESCROW_ABI,
|
|
2223
2258
|
functionName: "refund",
|
|
@@ -2228,7 +2263,7 @@ async function refundEscrow(wallet2, taskId) {
|
|
|
2228
2263
|
async function releaseAfterTimeout(wallet2, taskId) {
|
|
2229
2264
|
const walletClient = getWalletClient2(wallet2);
|
|
2230
2265
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2231
|
-
const hash = await walletClient
|
|
2266
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2232
2267
|
address: ESCROW_ADDRESS,
|
|
2233
2268
|
abi: ESCROW_ABI,
|
|
2234
2269
|
functionName: "releaseAfterTimeout",
|
|
@@ -2239,7 +2274,7 @@ async function releaseAfterTimeout(wallet2, taskId) {
|
|
|
2239
2274
|
async function markAccepted(wallet2, taskId) {
|
|
2240
2275
|
const walletClient = getWalletClient2(wallet2);
|
|
2241
2276
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2242
|
-
const hash = await walletClient
|
|
2277
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2243
2278
|
address: ESCROW_ADDRESS,
|
|
2244
2279
|
abi: ESCROW_ABI,
|
|
2245
2280
|
functionName: "markAccepted",
|
|
@@ -2250,7 +2285,7 @@ async function markAccepted(wallet2, taskId) {
|
|
|
2250
2285
|
async function cancelEscrow(wallet2, taskId) {
|
|
2251
2286
|
const walletClient = getWalletClient2(wallet2);
|
|
2252
2287
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2253
|
-
const hash = await walletClient
|
|
2288
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2254
2289
|
address: ESCROW_ADDRESS,
|
|
2255
2290
|
abi: ESCROW_ABI,
|
|
2256
2291
|
functionName: "cancel",
|
|
@@ -2318,7 +2353,7 @@ async function getEscrowDetails(taskId) {
|
|
|
2318
2353
|
async function disputeEscrow(wallet2, taskId, feeWei) {
|
|
2319
2354
|
const walletClient = getWalletClient2(wallet2);
|
|
2320
2355
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2321
|
-
const hash = await walletClient
|
|
2356
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2322
2357
|
address: ESCROW_ADDRESS,
|
|
2323
2358
|
abi: ESCROW_ABI,
|
|
2324
2359
|
functionName: "dispute",
|
|
@@ -2353,7 +2388,7 @@ async function resolveEscrowDispute(wallet2, taskId, clientWins) {
|
|
|
2353
2388
|
const walletClient = getWalletClient2(wallet2);
|
|
2354
2389
|
const publicClient = getPublicClient2();
|
|
2355
2390
|
const taskIdBytes = taskIdToBytes32(taskId);
|
|
2356
|
-
const hash = await walletClient
|
|
2391
|
+
const hash = await writeContractWithAttribution(walletClient, {
|
|
2357
2392
|
address: ESCROW_ADDRESS,
|
|
2358
2393
|
abi: ESCROW_ABI,
|
|
2359
2394
|
functionName: "resolveDispute",
|
|
@@ -2395,7 +2430,7 @@ async function accept(options) {
|
|
|
2395
2430
|
}
|
|
2396
2431
|
const agentToken = agent.flaunchToken;
|
|
2397
2432
|
if (!agentToken) {
|
|
2398
|
-
throw new Error("Agent has no
|
|
2433
|
+
throw new Error("Agent has no token linked. Cannot deposit to escrow without token for buyback.");
|
|
2399
2434
|
}
|
|
2400
2435
|
const priceWei = BigInt(taskBefore.quotedPriceWei || "0");
|
|
2401
2436
|
const balance = await getWalletBalance(wallet2.address);
|
|
@@ -4044,7 +4079,7 @@ async function verifyX(options) {
|
|
|
4044
4079
|
// src/index.ts
|
|
4045
4080
|
var program = new Command();
|
|
4046
4081
|
program.name("mltl").description("moltlaunch \u2014 hire AI agents with onchain reputation").version("2.8.0");
|
|
4047
|
-
program.command("register").description("Register an agent (launches token + registers identity)").requiredOption("--name <name>", "Agent name").option("--symbol <symbol>", "Token symbol for NEW token (2-10 chars)").option("--token <address>", "Existing
|
|
4082
|
+
program.command("register").description("Register an agent (launches token + registers identity)").requiredOption("--name <name>", "Agent name").option("--symbol <symbol>", "Token symbol for NEW token (2-10 chars)").option("--token <address>", "Existing token address on Base (skips token launch)").requiredOption("--description <desc>", "Agent description").requiredOption("--skills <skills>", "Comma-separated skills (e.g., code,research,review)").option("--endpoint <url>", "x402 endpoint URL (optional - can use task queue instead)").option("--image <path>", "Image file path (PNG, JPG, etc.)").option("--price <eth>", "Price per hire in ETH", "0.001").option("--website <url>", "Website URL").option("--json", "Output as JSON").action(register);
|
|
4048
4083
|
program.command("hire").description("Request work from an agent (they will quote a price)").requiredOption("--agent <id>", "Agent ID (ERC-8004 token ID)").requiredOption("--task <description>", "Task description").option("--json", "Output as JSON").action(hire);
|
|
4049
4084
|
program.command("feedback").description("Submit verified feedback for an agent (linked to completed task)").option("--agent <id>", "Agent ID (auto-resolved if --task provided)").option("--task <taskId>", "Task ID to link feedback to (verifies completion)").requiredOption("--score <0-100>", "Score from 0-100").option("--comment <text>", "Optional feedback comment").option("--json", "Output as JSON").action(feedback);
|
|
4050
4085
|
program.command("agents").description("Browse registered agents").option("--skill <skill>", "Filter by skill").option("--sort <field>", "Sort by: reputation, price, hires", "reputation").option("--limit <n>", "Number of results", "20").option("--json", "Output as JSON").action(agents);
|