@moltium/world-core 0.1.22 → 0.1.23
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/dist/{CardFetcher-4ENWKI6E.js → CardFetcher-IMUPYNEQ.js} +2 -2
- package/dist/CardFetcher-ZD4YSGJE.cjs +9 -0
- package/dist/{CardFetcher-UCJGPZ7X.cjs.map → CardFetcher-ZD4YSGJE.cjs.map} +1 -1
- package/dist/{chunk-DHQFXIEW.cjs → chunk-WI7EASJJ.cjs} +30 -6
- package/dist/chunk-WI7EASJJ.cjs.map +1 -0
- package/dist/{chunk-DWXNX5V3.js → chunk-Y563WZWH.js} +30 -6
- package/dist/chunk-Y563WZWH.js.map +1 -0
- package/dist/index.cjs +247 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -66
- package/dist/index.d.ts +85 -66
- package/dist/index.js +207 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/CardFetcher-UCJGPZ7X.cjs +0 -9
- package/dist/chunk-DHQFXIEW.cjs.map +0 -1
- package/dist/chunk-DWXNX5V3.js.map +0 -1
- /package/dist/{CardFetcher-4ENWKI6E.js.map → CardFetcher-IMUPYNEQ.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createLogger,
|
|
4
4
|
logger,
|
|
5
5
|
normalizeAgentUrl
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-Y563WZWH.js";
|
|
7
7
|
|
|
8
8
|
// src/config/types.ts
|
|
9
9
|
function profileFromCard(card, walletAddress) {
|
|
@@ -766,7 +766,7 @@ var BlockchainClient = class {
|
|
|
766
766
|
return this.wallet.address;
|
|
767
767
|
}
|
|
768
768
|
/**
|
|
769
|
-
* Get entry fee in MON
|
|
769
|
+
* Get entry fee in MON (formatted)
|
|
770
770
|
*/
|
|
771
771
|
async getEntryFee() {
|
|
772
772
|
if (!this.membershipContract) {
|
|
@@ -780,6 +780,78 @@ var BlockchainClient = class {
|
|
|
780
780
|
return "0";
|
|
781
781
|
}
|
|
782
782
|
}
|
|
783
|
+
/**
|
|
784
|
+
* Get entry fee in wei (raw BigInt string)
|
|
785
|
+
*/
|
|
786
|
+
async getEntryFeeWei() {
|
|
787
|
+
if (!this.membershipContract) {
|
|
788
|
+
return "0";
|
|
789
|
+
}
|
|
790
|
+
try {
|
|
791
|
+
const fee = await this.membershipContract.entryFee();
|
|
792
|
+
return fee.toString();
|
|
793
|
+
} catch (error) {
|
|
794
|
+
logger3.error("Failed to get entry fee (wei)", { error: error.message });
|
|
795
|
+
return "0";
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
// Track used payment tx hashes to prevent replay attacks
|
|
799
|
+
usedPayments = /* @__PURE__ */ new Set();
|
|
800
|
+
/**
|
|
801
|
+
* Verify a payment transaction from an agent.
|
|
802
|
+
* Checks: tx confirmed, correct sender, correct recipient (world wallet), sufficient amount.
|
|
803
|
+
* Prevents replay attacks by tracking used tx hashes.
|
|
804
|
+
*/
|
|
805
|
+
async verifyPayment(txHash, expectedSender, expectedAmountWei) {
|
|
806
|
+
const normalizedHash = txHash.toLowerCase();
|
|
807
|
+
if (this.usedPayments.has(normalizedHash)) {
|
|
808
|
+
logger3.warn("Payment verification: transaction already used", { txHash });
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
try {
|
|
812
|
+
const receipt = await this.provider.getTransactionReceipt(txHash);
|
|
813
|
+
if (!receipt || receipt.status !== 1) {
|
|
814
|
+
logger3.warn("Payment verification: transaction not confirmed or failed", { txHash });
|
|
815
|
+
return false;
|
|
816
|
+
}
|
|
817
|
+
const tx = await this.provider.getTransaction(txHash);
|
|
818
|
+
if (!tx) {
|
|
819
|
+
logger3.warn("Payment verification: transaction not found", { txHash });
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
if (tx.from.toLowerCase() !== expectedSender.toLowerCase()) {
|
|
823
|
+
logger3.warn("Payment verification: wrong sender", {
|
|
824
|
+
expected: expectedSender,
|
|
825
|
+
actual: tx.from
|
|
826
|
+
});
|
|
827
|
+
return false;
|
|
828
|
+
}
|
|
829
|
+
if (tx.to?.toLowerCase() !== this.wallet.address.toLowerCase()) {
|
|
830
|
+
logger3.warn("Payment verification: wrong recipient", {
|
|
831
|
+
expected: this.wallet.address,
|
|
832
|
+
actual: tx.to
|
|
833
|
+
});
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
if (tx.value < BigInt(expectedAmountWei)) {
|
|
837
|
+
logger3.warn("Payment verification: insufficient amount", {
|
|
838
|
+
expected: expectedAmountWei,
|
|
839
|
+
actual: tx.value.toString()
|
|
840
|
+
});
|
|
841
|
+
return false;
|
|
842
|
+
}
|
|
843
|
+
this.usedPayments.add(normalizedHash);
|
|
844
|
+
logger3.info("Payment verified successfully", {
|
|
845
|
+
txHash,
|
|
846
|
+
sender: tx.from,
|
|
847
|
+
amount: ethers.formatEther(tx.value)
|
|
848
|
+
});
|
|
849
|
+
return true;
|
|
850
|
+
} catch (error) {
|
|
851
|
+
logger3.error("Payment verification error", { txHash, error: error.message });
|
|
852
|
+
return false;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
783
855
|
};
|
|
784
856
|
|
|
785
857
|
// src/a2a/WorldA2AClient.ts
|
|
@@ -1246,6 +1318,18 @@ var TickOrchestrator = class {
|
|
|
1246
1318
|
|
|
1247
1319
|
// src/a2a/MessageRouter.ts
|
|
1248
1320
|
var logger8 = createLogger("MessageRouter");
|
|
1321
|
+
var c = {
|
|
1322
|
+
reset: "\x1B[0m",
|
|
1323
|
+
bold: "\x1B[1m",
|
|
1324
|
+
dim: "\x1B[2m",
|
|
1325
|
+
blue: "\x1B[34m",
|
|
1326
|
+
green: "\x1B[32m",
|
|
1327
|
+
yellow: "\x1B[33m",
|
|
1328
|
+
magenta: "\x1B[35m",
|
|
1329
|
+
cyan: "\x1B[36m",
|
|
1330
|
+
red: "\x1B[31m",
|
|
1331
|
+
gray: "\x1B[90m"
|
|
1332
|
+
};
|
|
1249
1333
|
var MessageRouter = class {
|
|
1250
1334
|
constructor(a2aClient, getAgents) {
|
|
1251
1335
|
this.a2aClient = a2aClient;
|
|
@@ -1258,6 +1342,7 @@ var MessageRouter = class {
|
|
|
1258
1342
|
const agents = this.getAgents();
|
|
1259
1343
|
const sender = agents.find((a) => a.url === fromAgentUrl);
|
|
1260
1344
|
if (!sender) {
|
|
1345
|
+
logger8.warn(`Message rejected \u2014 sender not in world: ${fromAgentUrl}`);
|
|
1261
1346
|
return {
|
|
1262
1347
|
success: false,
|
|
1263
1348
|
error: `Sender not in world: ${fromAgentUrl}`
|
|
@@ -1265,11 +1350,19 @@ var MessageRouter = class {
|
|
|
1265
1350
|
}
|
|
1266
1351
|
const recipient = agents.find((a) => a.url === toAgentUrl);
|
|
1267
1352
|
if (!recipient) {
|
|
1353
|
+
logger8.warn(`Message rejected \u2014 recipient not in world: ${toAgentUrl}`);
|
|
1268
1354
|
return {
|
|
1269
1355
|
success: false,
|
|
1270
1356
|
error: `Recipient not in world: ${toAgentUrl}`
|
|
1271
1357
|
};
|
|
1272
1358
|
}
|
|
1359
|
+
console.log(
|
|
1360
|
+
`
|
|
1361
|
+
${c.cyan}\u2501\u2501\u2501 MESSAGE \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}
|
|
1362
|
+
${c.bold}${c.blue}${sender.name}${c.reset} ${c.dim}\u2192${c.reset} ${c.bold}${c.green}${recipient.name}${c.reset}
|
|
1363
|
+
${c.dim}\u2502${c.reset} ${this.truncate(message, 300)}
|
|
1364
|
+
${c.cyan}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}`
|
|
1365
|
+
);
|
|
1273
1366
|
const wrappedMessage = JSON.stringify({
|
|
1274
1367
|
type: "world_message",
|
|
1275
1368
|
from: {
|
|
@@ -1279,11 +1372,24 @@ var MessageRouter = class {
|
|
|
1279
1372
|
},
|
|
1280
1373
|
message
|
|
1281
1374
|
});
|
|
1282
|
-
|
|
1283
|
-
return this.a2aClient.sendToAgent(toAgentUrl, wrappedMessage, {
|
|
1375
|
+
const response = await this.a2aClient.sendToAgent(toAgentUrl, wrappedMessage, {
|
|
1284
1376
|
type: "world_message",
|
|
1285
1377
|
fromAgentUrl
|
|
1286
1378
|
});
|
|
1379
|
+
if (response.success && response.reply) {
|
|
1380
|
+
console.log(
|
|
1381
|
+
`
|
|
1382
|
+
${c.green}\u2501\u2501\u2501 REPLY \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}
|
|
1383
|
+
${c.bold}${c.green}${recipient.name}${c.reset} ${c.dim}\u2192${c.reset} ${c.bold}${c.blue}${sender.name}${c.reset}
|
|
1384
|
+
${c.dim}\u2502${c.reset} ${this.truncate(response.reply, 300)}
|
|
1385
|
+
${c.green}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}`
|
|
1386
|
+
);
|
|
1387
|
+
} else if (!response.success) {
|
|
1388
|
+
console.log(
|
|
1389
|
+
`${c.red} \u2717 ${recipient.name} failed to respond: ${response.error || "no response"}${c.reset}`
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
return response;
|
|
1287
1393
|
}
|
|
1288
1394
|
/**
|
|
1289
1395
|
* Broadcast a message from one agent to all other agents in the world
|
|
@@ -1292,6 +1398,7 @@ var MessageRouter = class {
|
|
|
1292
1398
|
const agents = this.getAgents();
|
|
1293
1399
|
const sender = agents.find((a) => a.url === fromAgentUrl);
|
|
1294
1400
|
if (!sender) {
|
|
1401
|
+
logger8.warn(`Broadcast rejected \u2014 sender not in world: ${fromAgentUrl}`);
|
|
1295
1402
|
const result = /* @__PURE__ */ new Map();
|
|
1296
1403
|
result.set(fromAgentUrl, {
|
|
1297
1404
|
success: false,
|
|
@@ -1299,6 +1406,14 @@ var MessageRouter = class {
|
|
|
1299
1406
|
});
|
|
1300
1407
|
return result;
|
|
1301
1408
|
}
|
|
1409
|
+
const recipients = agents.filter((a) => a.url !== fromAgentUrl);
|
|
1410
|
+
console.log(
|
|
1411
|
+
`
|
|
1412
|
+
${c.yellow}\u2501\u2501\u2501 BROADCAST \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}
|
|
1413
|
+
${c.bold}${c.blue}${sender.name}${c.reset} ${c.dim}\u2192${c.reset} ${c.bold}${c.yellow}ALL (${recipients.length} agents)${c.reset}
|
|
1414
|
+
${c.dim}\u2502${c.reset} ${this.truncate(message, 300)}
|
|
1415
|
+
${c.yellow}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${c.reset}`
|
|
1416
|
+
);
|
|
1302
1417
|
const wrappedMessage = JSON.stringify({
|
|
1303
1418
|
type: "world_broadcast",
|
|
1304
1419
|
from: {
|
|
@@ -1309,7 +1424,6 @@ var MessageRouter = class {
|
|
|
1309
1424
|
message
|
|
1310
1425
|
});
|
|
1311
1426
|
const results = /* @__PURE__ */ new Map();
|
|
1312
|
-
const recipients = agents.filter((a) => a.url !== fromAgentUrl);
|
|
1313
1427
|
const promises = recipients.map(async (recipient) => {
|
|
1314
1428
|
const response = await this.a2aClient.sendToAgent(
|
|
1315
1429
|
recipient.url,
|
|
@@ -1317,11 +1431,32 @@ var MessageRouter = class {
|
|
|
1317
1431
|
{ type: "world_broadcast", fromAgentUrl }
|
|
1318
1432
|
);
|
|
1319
1433
|
results.set(recipient.url, response);
|
|
1434
|
+
if (response.success && response.reply) {
|
|
1435
|
+
console.log(
|
|
1436
|
+
`${c.green} \u21A9 ${c.bold}${recipient.name}${c.reset}${c.green} replied:${c.reset} ${this.truncate(response.reply, 200)}`
|
|
1437
|
+
);
|
|
1438
|
+
} else if (!response.success) {
|
|
1439
|
+
console.log(
|
|
1440
|
+
`${c.red} \u2717 ${recipient.name} failed: ${response.error || "no response"}${c.reset}`
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1320
1443
|
});
|
|
1321
1444
|
await Promise.allSettled(promises);
|
|
1322
|
-
|
|
1445
|
+
const succeeded = Array.from(results.values()).filter((r) => r.success).length;
|
|
1446
|
+
const failed = Array.from(results.values()).filter((r) => !r.success).length;
|
|
1447
|
+
console.log(
|
|
1448
|
+
`${c.dim} Broadcast complete: ${c.green}${succeeded} replied${c.reset}${c.dim}${failed > 0 ? `, ${c.red}${failed} failed${c.reset}` : ""}${c.reset}
|
|
1449
|
+
`
|
|
1450
|
+
);
|
|
1323
1451
|
return results;
|
|
1324
1452
|
}
|
|
1453
|
+
/**
|
|
1454
|
+
* Truncate long messages for logging
|
|
1455
|
+
*/
|
|
1456
|
+
truncate(text, maxLen) {
|
|
1457
|
+
if (text.length <= maxLen) return text;
|
|
1458
|
+
return text.slice(0, maxLen) + "...";
|
|
1459
|
+
}
|
|
1325
1460
|
};
|
|
1326
1461
|
|
|
1327
1462
|
// src/engine/World.ts
|
|
@@ -1476,10 +1611,16 @@ var World = class {
|
|
|
1476
1611
|
});
|
|
1477
1612
|
logger9.info("World stopped");
|
|
1478
1613
|
}
|
|
1614
|
+
/**
|
|
1615
|
+
* Get the blockchain client (for server endpoints)
|
|
1616
|
+
*/
|
|
1617
|
+
getBlockchainClient() {
|
|
1618
|
+
return this.blockchainClient;
|
|
1619
|
+
}
|
|
1479
1620
|
/**
|
|
1480
1621
|
* Admit an agent to the world
|
|
1481
1622
|
*/
|
|
1482
|
-
async admitAgent(card, walletAddress) {
|
|
1623
|
+
async admitAgent(card, walletAddress, paymentTxHash) {
|
|
1483
1624
|
const decision = await this.evaluator.evaluate(card, this.agents.size, walletAddress);
|
|
1484
1625
|
if (!decision.admitted) {
|
|
1485
1626
|
throw new Error(`Agent admission denied: ${decision.reason}`);
|
|
@@ -1494,6 +1635,28 @@ var World = class {
|
|
|
1494
1635
|
if (this.blockchainClient && this.config.blockchain?.requireMembership && walletAddress) {
|
|
1495
1636
|
const hasMembership = await this.blockchainClient.hasMembership(walletAddress);
|
|
1496
1637
|
if (!hasMembership) {
|
|
1638
|
+
const entryFeeWei = await this.blockchainClient.getEntryFeeWei();
|
|
1639
|
+
if (entryFeeWei !== "0" && BigInt(entryFeeWei) > 0n) {
|
|
1640
|
+
if (!paymentTxHash) {
|
|
1641
|
+
throw new Error(
|
|
1642
|
+
`Entry fee required: ${entryFeeWei} wei. Query GET /world/join-info for payment details, pay the fee, then include paymentTxHash in your join request.`
|
|
1643
|
+
);
|
|
1644
|
+
}
|
|
1645
|
+
const paymentValid = await this.blockchainClient.verifyPayment(
|
|
1646
|
+
paymentTxHash,
|
|
1647
|
+
walletAddress,
|
|
1648
|
+
entryFeeWei
|
|
1649
|
+
);
|
|
1650
|
+
if (!paymentValid) {
|
|
1651
|
+
throw new Error(
|
|
1652
|
+
`Payment verification failed for tx ${paymentTxHash}. Ensure the transaction is confirmed, sent from ${walletAddress}, to ${this.blockchainClient.getWalletAddress()}, for at least ${entryFeeWei} wei.`
|
|
1653
|
+
);
|
|
1654
|
+
}
|
|
1655
|
+
logger9.info(`Entry fee payment verified for ${card.name}`, {
|
|
1656
|
+
txHash: paymentTxHash,
|
|
1657
|
+
amount: entryFeeWei
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1497
1660
|
logger9.info(`Minting membership NFT for agent: ${card.name}`);
|
|
1498
1661
|
await this.blockchainClient.mintMembership(walletAddress);
|
|
1499
1662
|
} else {
|
|
@@ -1677,9 +1840,40 @@ function createWorldApp(world) {
|
|
|
1677
1840
|
}
|
|
1678
1841
|
});
|
|
1679
1842
|
});
|
|
1843
|
+
app.get("/world/join-info", async (req, res) => {
|
|
1844
|
+
try {
|
|
1845
|
+
const blockchain = world.config.blockchain;
|
|
1846
|
+
const client = world.getBlockchainClient();
|
|
1847
|
+
if (!blockchain || !client) {
|
|
1848
|
+
return res.json({
|
|
1849
|
+
worldName: world.config.name,
|
|
1850
|
+
requiresPayment: false,
|
|
1851
|
+
entryFee: "0",
|
|
1852
|
+
paymentAddress: null,
|
|
1853
|
+
chainId: null,
|
|
1854
|
+
rpcUrl: null
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
const entryFeeWei = await client.getEntryFeeWei();
|
|
1858
|
+
res.json({
|
|
1859
|
+
worldName: world.config.name,
|
|
1860
|
+
requiresPayment: entryFeeWei !== "0" && BigInt(entryFeeWei) > 0n,
|
|
1861
|
+
entryFee: entryFeeWei,
|
|
1862
|
+
paymentAddress: client.getWalletAddress(),
|
|
1863
|
+
chainId: blockchain.chainId || null,
|
|
1864
|
+
rpcUrl: blockchain.rpcUrl
|
|
1865
|
+
});
|
|
1866
|
+
} catch (error) {
|
|
1867
|
+
logger10.error("Failed to get join info:", error);
|
|
1868
|
+
res.status(500).json({
|
|
1869
|
+
success: false,
|
|
1870
|
+
error: error.message || "Failed to get join info"
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
});
|
|
1680
1874
|
app.post("/world/join", async (req, res) => {
|
|
1681
1875
|
try {
|
|
1682
|
-
const { agentUrl, walletAddress } = req.body;
|
|
1876
|
+
const { agentUrl, walletAddress, paymentTxHash } = req.body;
|
|
1683
1877
|
if (!agentUrl) {
|
|
1684
1878
|
return res.status(400).json({
|
|
1685
1879
|
success: false,
|
|
@@ -1687,9 +1881,10 @@ function createWorldApp(world) {
|
|
|
1687
1881
|
});
|
|
1688
1882
|
}
|
|
1689
1883
|
logger10.info(`Agent join request from: ${agentUrl}`, {
|
|
1690
|
-
wallet: walletAddress || "none"
|
|
1884
|
+
wallet: walletAddress || "none",
|
|
1885
|
+
paymentTx: paymentTxHash ? `${paymentTxHash.slice(0, 10)}...` : "none"
|
|
1691
1886
|
});
|
|
1692
|
-
const cardFetcher = new (await import("./CardFetcher-
|
|
1887
|
+
const cardFetcher = new (await import("./CardFetcher-IMUPYNEQ.js")).CardFetcher();
|
|
1693
1888
|
const result = await cardFetcher.fetchCard(agentUrl);
|
|
1694
1889
|
if (!result.success || !result.card) {
|
|
1695
1890
|
return res.status(400).json({
|
|
@@ -1697,7 +1892,7 @@ function createWorldApp(world) {
|
|
|
1697
1892
|
error: `Failed to fetch agent card: ${result.error}`
|
|
1698
1893
|
});
|
|
1699
1894
|
}
|
|
1700
|
-
await world.admitAgent(result.card, walletAddress);
|
|
1895
|
+
await world.admitAgent(result.card, walletAddress, paymentTxHash);
|
|
1701
1896
|
res.json({
|
|
1702
1897
|
success: true,
|
|
1703
1898
|
message: "Agent admitted to world",
|
|
@@ -1855,6 +2050,7 @@ async function startWorldServer(world) {
|
|
|
1855
2050
|
logger10.info("");
|
|
1856
2051
|
logger10.info("Endpoints:");
|
|
1857
2052
|
logger10.info(` GET / - World info`);
|
|
2053
|
+
logger10.info(` GET /world/join-info - Join requirements & entry fee`);
|
|
1858
2054
|
logger10.info(` POST /world/join - Agent join request`);
|
|
1859
2055
|
logger10.info(` GET /world/agents - List agents`);
|
|
1860
2056
|
logger10.info(` GET /world/state - World state`);
|