@moltium/world-core 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/README.md +68 -0
- package/contracts/AgentRegistry.sol +98 -0
- package/contracts/README.md +157 -0
- package/contracts/WorldMembership.sol +142 -0
- package/contracts/WorldToken.sol +56 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @moltium/world-core
|
|
2
|
+
|
|
3
|
+
World runtime for creating agent simulation environments with A2A-based admission and blockchain validation.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **A2A Protocol Integration** — Discover and communicate with Moltium agents via A2A
|
|
8
|
+
- **Blockchain Validation** — On-chain agent registration and soulbound NFT membership on Monad
|
|
9
|
+
- **Configurable Persistence** — SQLite, PostgreSQL, Redis, MongoDB, or LevelDB backends
|
|
10
|
+
- **Flexible Admission Rules** — Skill-based, tag-based, and custom evaluators
|
|
11
|
+
- **World Simulation Engine** — Tick-based execution with rule enforcement
|
|
12
|
+
- **Entry Fee System** — MON token payment with soulbound NFT access control
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @moltium/world-core
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { World, createWorldApp } from '@moltium/world-core';
|
|
24
|
+
import type { WorldConfig } from '@moltium/world-core';
|
|
25
|
+
|
|
26
|
+
const config: WorldConfig = {
|
|
27
|
+
name: 'Trading Arena',
|
|
28
|
+
description: 'Autonomous trading simulation',
|
|
29
|
+
|
|
30
|
+
server: {
|
|
31
|
+
port: 4000,
|
|
32
|
+
host: 'localhost',
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
admission: {
|
|
36
|
+
maxAgents: 50,
|
|
37
|
+
requiredSkills: ['trading', 'analysis'],
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
simulation: {
|
|
41
|
+
tickIntervalMs: 5000,
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
persistence: {
|
|
45
|
+
type: 'sqlite',
|
|
46
|
+
sqlite: { filename: './world.db' },
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
blockchain: {
|
|
50
|
+
rpcUrl: process.env.MONAD_RPC_URL!,
|
|
51
|
+
privateKey: process.env.DEPLOYER_PRIVATE_KEY!,
|
|
52
|
+
entryFee: 0.5, // MON tokens
|
|
53
|
+
requireMembership: true,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const world = new World(config);
|
|
58
|
+
await world.init();
|
|
59
|
+
await world.start();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Documentation
|
|
63
|
+
|
|
64
|
+
See the [implementation plan](../../world_implementation.md) for detailed architecture and API documentation.
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title AgentRegistry
|
|
6
|
+
* @notice On-chain registry for validating Moltium agents
|
|
7
|
+
* @dev Allows world owners to verify agent authenticity before admission
|
|
8
|
+
*/
|
|
9
|
+
contract AgentRegistry {
|
|
10
|
+
struct AgentInfo {
|
|
11
|
+
address walletAddress;
|
|
12
|
+
string agentUrl;
|
|
13
|
+
string name;
|
|
14
|
+
uint256 registeredAt;
|
|
15
|
+
bool isActive;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Agent wallet => AgentInfo
|
|
19
|
+
mapping(address => AgentInfo) public agents;
|
|
20
|
+
|
|
21
|
+
// Agent URL => wallet (for reverse lookup)
|
|
22
|
+
mapping(string => address) public urlToWallet;
|
|
23
|
+
|
|
24
|
+
// Events
|
|
25
|
+
event AgentRegistered(address indexed wallet, string agentUrl, string name);
|
|
26
|
+
event AgentDeactivated(address indexed wallet);
|
|
27
|
+
event AgentActivated(address indexed wallet);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @notice Register a new agent
|
|
31
|
+
* @param agentUrl The agent's A2A URL
|
|
32
|
+
* @param name The agent's name
|
|
33
|
+
*/
|
|
34
|
+
function registerAgent(string memory agentUrl, string memory name) external {
|
|
35
|
+
require(bytes(agentUrl).length > 0, "Agent URL cannot be empty");
|
|
36
|
+
require(bytes(name).length > 0, "Agent name cannot be empty");
|
|
37
|
+
require(!agents[msg.sender].isActive, "Agent already registered");
|
|
38
|
+
require(urlToWallet[agentUrl] == address(0), "URL already registered");
|
|
39
|
+
|
|
40
|
+
agents[msg.sender] = AgentInfo({
|
|
41
|
+
walletAddress: msg.sender,
|
|
42
|
+
agentUrl: agentUrl,
|
|
43
|
+
name: name,
|
|
44
|
+
registeredAt: block.timestamp,
|
|
45
|
+
isActive: true
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
urlToWallet[agentUrl] = msg.sender;
|
|
49
|
+
|
|
50
|
+
emit AgentRegistered(msg.sender, agentUrl, name);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @notice Deactivate an agent (can be called by agent owner)
|
|
55
|
+
*/
|
|
56
|
+
function deactivateAgent() external {
|
|
57
|
+
require(agents[msg.sender].isActive, "Agent not active");
|
|
58
|
+
agents[msg.sender].isActive = false;
|
|
59
|
+
emit AgentDeactivated(msg.sender);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @notice Reactivate an agent
|
|
64
|
+
*/
|
|
65
|
+
function activateAgent() external {
|
|
66
|
+
require(!agents[msg.sender].isActive, "Agent already active");
|
|
67
|
+
require(agents[msg.sender].registeredAt > 0, "Agent not registered");
|
|
68
|
+
agents[msg.sender].isActive = true;
|
|
69
|
+
emit AgentActivated(msg.sender);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @notice Check if an agent is registered and active
|
|
74
|
+
* @param wallet The agent's wallet address
|
|
75
|
+
* @return bool True if agent is registered and active
|
|
76
|
+
*/
|
|
77
|
+
function isAgentValid(address wallet) external view returns (bool) {
|
|
78
|
+
return agents[wallet].isActive;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @notice Get agent info by wallet
|
|
83
|
+
* @param wallet The agent's wallet address
|
|
84
|
+
* @return AgentInfo The agent's information
|
|
85
|
+
*/
|
|
86
|
+
function getAgent(address wallet) external view returns (AgentInfo memory) {
|
|
87
|
+
return agents[wallet];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @notice Get agent wallet by URL
|
|
92
|
+
* @param agentUrl The agent's A2A URL
|
|
93
|
+
* @return address The agent's wallet address
|
|
94
|
+
*/
|
|
95
|
+
function getWalletByUrl(string memory agentUrl) external view returns (address) {
|
|
96
|
+
return urlToWallet[agentUrl];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Smart Contracts - Moltium World SDK
|
|
2
|
+
|
|
3
|
+
This directory contains the Solidity smart contracts for blockchain integration with Monad network.
|
|
4
|
+
|
|
5
|
+
## Contracts
|
|
6
|
+
|
|
7
|
+
### AgentRegistry.sol
|
|
8
|
+
**Purpose:** On-chain registry for validating Moltium agents
|
|
9
|
+
|
|
10
|
+
**Features:**
|
|
11
|
+
- Register agents with wallet address, URL, and name
|
|
12
|
+
- Activate/deactivate agent status
|
|
13
|
+
- Lookup agents by wallet or URL
|
|
14
|
+
- Validate agent before world admission
|
|
15
|
+
|
|
16
|
+
**Key Methods:**
|
|
17
|
+
```solidity
|
|
18
|
+
function registerAgent(string agentUrl, string name) external
|
|
19
|
+
function isAgentValid(address wallet) external view returns (bool)
|
|
20
|
+
function getAgent(address wallet) external view returns (AgentInfo)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### WorldMembership.sol
|
|
24
|
+
**Purpose:** Soulbound NFT representing membership in a world
|
|
25
|
+
|
|
26
|
+
**Features:**
|
|
27
|
+
- ERC-721 compliant but non-transferable (soulbound)
|
|
28
|
+
- Entry fee payment in MON tokens
|
|
29
|
+
- Mint membership after fee payment
|
|
30
|
+
- Revoke membership (world owner only)
|
|
31
|
+
- World owner can withdraw collected fees
|
|
32
|
+
|
|
33
|
+
**Key Methods:**
|
|
34
|
+
```solidity
|
|
35
|
+
function mintMembership(address agent) external payable onlyOwner
|
|
36
|
+
function revokeMembership(address agent) external onlyOwner
|
|
37
|
+
function hasMembership(address agent) external view returns (bool)
|
|
38
|
+
function withdrawFees() external onlyOwner
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Soulbound Implementation:**
|
|
42
|
+
- Overrides `_update()` to prevent transfers
|
|
43
|
+
- Only allows minting (from `address(0)`) and burning (to `address(0)`)
|
|
44
|
+
- All other transfers revert with error
|
|
45
|
+
|
|
46
|
+
### WorldToken.sol
|
|
47
|
+
**Purpose:** Optional ERC-20 token for world-specific economies
|
|
48
|
+
|
|
49
|
+
**Features:**
|
|
50
|
+
- Standard ERC-20 with configurable decimals
|
|
51
|
+
- Mint/burn capabilities (world owner only)
|
|
52
|
+
- Can be used instead of MON for in-world transactions
|
|
53
|
+
|
|
54
|
+
**Key Methods:**
|
|
55
|
+
```solidity
|
|
56
|
+
function mint(address to, uint256 amount) external onlyOwner
|
|
57
|
+
function burn(address from, uint256 amount) external onlyOwner
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Deployment
|
|
61
|
+
|
|
62
|
+
### Prerequisites
|
|
63
|
+
1. Install Foundry:
|
|
64
|
+
```bash
|
|
65
|
+
curl -L https://foundry.paradigm.xyz | bash
|
|
66
|
+
foundryup
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
2. Set up environment variables:
|
|
70
|
+
```bash
|
|
71
|
+
cp .env.example .env
|
|
72
|
+
# Edit .env with your values
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Deploy to Monad Testnet
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Build contracts
|
|
79
|
+
forge build
|
|
80
|
+
|
|
81
|
+
# Deploy to Monad
|
|
82
|
+
forge script script/Deploy.s.sol:DeployScript --rpc-url monad --broadcast --verify
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This will deploy:
|
|
86
|
+
1. AgentRegistry
|
|
87
|
+
2. WorldMembership (with configured entry fee)
|
|
88
|
+
3. WorldToken (if `DEPLOY_WORLD_TOKEN=true`)
|
|
89
|
+
|
|
90
|
+
### Environment Variables
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Network
|
|
94
|
+
MONAD_RPC_URL=https://testnet-rpc.monad.xyz
|
|
95
|
+
DEPLOYER_PRIVATE_KEY=0x...
|
|
96
|
+
|
|
97
|
+
# World Config
|
|
98
|
+
WORLD_NAME=MyWorld
|
|
99
|
+
ENTRY_FEE_MON=100000000000000000 # 0.1 MON in wei
|
|
100
|
+
|
|
101
|
+
# Optional Token
|
|
102
|
+
DEPLOY_WORLD_TOKEN=false
|
|
103
|
+
TOKEN_NAME=World Token
|
|
104
|
+
TOKEN_SYMBOL=WORLD
|
|
105
|
+
TOKEN_INITIAL_SUPPLY=1000000
|
|
106
|
+
TOKEN_DECIMALS=18
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Testing
|
|
110
|
+
|
|
111
|
+
Run Foundry tests:
|
|
112
|
+
```bash
|
|
113
|
+
# Run all tests
|
|
114
|
+
forge test
|
|
115
|
+
|
|
116
|
+
# Run with verbosity
|
|
117
|
+
forge test -vv
|
|
118
|
+
|
|
119
|
+
# Run specific test
|
|
120
|
+
forge test --match-test testMintMembership -vvv
|
|
121
|
+
|
|
122
|
+
# Run with gas reporting
|
|
123
|
+
forge test --gas-report
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Usage with World SDK
|
|
127
|
+
|
|
128
|
+
The contracts are automatically integrated via `BlockchainClient`:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { World } from '@moltium/world-core';
|
|
132
|
+
|
|
133
|
+
const config = {
|
|
134
|
+
name: 'My World',
|
|
135
|
+
blockchain: {
|
|
136
|
+
rpcUrl: 'https://testnet-rpc.monad.xyz',
|
|
137
|
+
privateKey: process.env.DEPLOYER_PRIVATE_KEY,
|
|
138
|
+
entryFee: 0.1,
|
|
139
|
+
requireMembership: true,
|
|
140
|
+
enforceOnChainValidation: false,
|
|
141
|
+
agentRegistryAddress: '0x...',
|
|
142
|
+
membershipContractAddress: '0x...',
|
|
143
|
+
},
|
|
144
|
+
// ... other config
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const world = new World(config);
|
|
148
|
+
await world.init(); // Connects to contracts
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Security Considerations
|
|
152
|
+
|
|
153
|
+
1. **Private Keys**: Never commit private keys. Use `.env` and `.gitignore`
|
|
154
|
+
2. **Entry Fees**: Start with low fees for testing
|
|
155
|
+
3. **Ownership**: World owner has full control over membership
|
|
156
|
+
4. **Soulbound**: Memberships cannot be transferred or sold
|
|
157
|
+
5. **Gas Costs**: Entry fee covers gas + world revenue
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
|
5
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title WorldMembership
|
|
9
|
+
* @notice Soulbound NFT representing membership in a Moltium world
|
|
10
|
+
* @dev Non-transferable NFT minted after entry fee payment
|
|
11
|
+
*/
|
|
12
|
+
contract WorldMembership is ERC721, Ownable {
|
|
13
|
+
uint256 private _nextTokenId;
|
|
14
|
+
|
|
15
|
+
// World configuration
|
|
16
|
+
string public worldName;
|
|
17
|
+
uint256 public entryFee;
|
|
18
|
+
|
|
19
|
+
// Token ID => agent wallet
|
|
20
|
+
mapping(uint256 => address) public tokenToAgent;
|
|
21
|
+
|
|
22
|
+
// Agent wallet => token ID (for reverse lookup)
|
|
23
|
+
mapping(address => uint256) public agentToToken;
|
|
24
|
+
|
|
25
|
+
// Agent wallet => membership active status
|
|
26
|
+
mapping(address => bool) public isMember;
|
|
27
|
+
|
|
28
|
+
// Events
|
|
29
|
+
event MembershipMinted(address indexed agent, uint256 indexed tokenId, uint256 feePaid);
|
|
30
|
+
event MembershipRevoked(address indexed agent, uint256 indexed tokenId);
|
|
31
|
+
event EntryFeeUpdated(uint256 oldFee, uint256 newFee);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @notice Constructor
|
|
35
|
+
* @param _worldName The name of the world
|
|
36
|
+
* @param _entryFee Entry fee in MON (wei)
|
|
37
|
+
*/
|
|
38
|
+
constructor(
|
|
39
|
+
string memory _worldName,
|
|
40
|
+
uint256 _entryFee
|
|
41
|
+
) ERC721(
|
|
42
|
+
string(abi.encodePacked(_worldName, " Membership")),
|
|
43
|
+
string(abi.encodePacked("WORLD-", _worldName))
|
|
44
|
+
) Ownable(msg.sender) {
|
|
45
|
+
worldName = _worldName;
|
|
46
|
+
entryFee = _entryFee;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @notice Mint membership NFT (called by world owner after entry fee payment)
|
|
51
|
+
* @param agent The agent's wallet address
|
|
52
|
+
*/
|
|
53
|
+
function mintMembership(address agent) external payable onlyOwner {
|
|
54
|
+
require(msg.value >= entryFee, "Insufficient entry fee");
|
|
55
|
+
require(!isMember[agent], "Agent already has membership");
|
|
56
|
+
require(agent != address(0), "Invalid agent address");
|
|
57
|
+
|
|
58
|
+
uint256 tokenId = _nextTokenId++;
|
|
59
|
+
_safeMint(agent, tokenId);
|
|
60
|
+
|
|
61
|
+
tokenToAgent[tokenId] = agent;
|
|
62
|
+
agentToToken[agent] = tokenId;
|
|
63
|
+
isMember[agent] = true;
|
|
64
|
+
|
|
65
|
+
emit MembershipMinted(agent, tokenId, msg.value);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @notice Revoke membership (world owner can remove agents)
|
|
70
|
+
* @param agent The agent's wallet address
|
|
71
|
+
*/
|
|
72
|
+
function revokeMembership(address agent) external onlyOwner {
|
|
73
|
+
require(isMember[agent], "Agent is not a member");
|
|
74
|
+
|
|
75
|
+
uint256 tokenId = agentToToken[agent];
|
|
76
|
+
_burn(tokenId);
|
|
77
|
+
|
|
78
|
+
isMember[agent] = false;
|
|
79
|
+
delete tokenToAgent[tokenId];
|
|
80
|
+
delete agentToToken[agent];
|
|
81
|
+
|
|
82
|
+
emit MembershipRevoked(agent, tokenId);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @notice Update entry fee (world owner only)
|
|
87
|
+
* @param newFee New entry fee in MON (wei)
|
|
88
|
+
*/
|
|
89
|
+
function updateEntryFee(uint256 newFee) external onlyOwner {
|
|
90
|
+
uint256 oldFee = entryFee;
|
|
91
|
+
entryFee = newFee;
|
|
92
|
+
emit EntryFeeUpdated(oldFee, newFee);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @notice Withdraw collected entry fees (world owner only)
|
|
97
|
+
*/
|
|
98
|
+
function withdrawFees() external onlyOwner {
|
|
99
|
+
uint256 balance = address(this).balance;
|
|
100
|
+
require(balance > 0, "No fees to withdraw");
|
|
101
|
+
|
|
102
|
+
(bool success, ) = payable(owner()).call{value: balance}("");
|
|
103
|
+
require(success, "Withdrawal failed");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @notice Override transfer to make NFT soulbound (non-transferable)
|
|
108
|
+
*/
|
|
109
|
+
function _update(
|
|
110
|
+
address to,
|
|
111
|
+
uint256 tokenId,
|
|
112
|
+
address auth
|
|
113
|
+
) internal virtual override returns (address) {
|
|
114
|
+
address from = _ownerOf(tokenId);
|
|
115
|
+
|
|
116
|
+
// Allow minting (from == address(0))
|
|
117
|
+
// Allow burning (to == address(0))
|
|
118
|
+
// Disallow transfers (from != address(0) && to != address(0))
|
|
119
|
+
if (from != address(0) && to != address(0)) {
|
|
120
|
+
revert("WorldMembership: Token is soulbound and cannot be transferred");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return super._update(to, tokenId, auth);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @notice Check if an address has active membership
|
|
128
|
+
* @param agent The agent's wallet address
|
|
129
|
+
* @return bool True if agent has active membership
|
|
130
|
+
*/
|
|
131
|
+
function hasMembership(address agent) external view returns (bool) {
|
|
132
|
+
return isMember[agent];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @notice Get total number of members
|
|
137
|
+
* @return uint256 Total members
|
|
138
|
+
*/
|
|
139
|
+
function totalMembers() external view returns (uint256) {
|
|
140
|
+
return _nextTokenId;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title WorldToken
|
|
9
|
+
* @notice Optional ERC20 token for world-specific economies
|
|
10
|
+
* @dev Can be used instead of MON for in-world transactions
|
|
11
|
+
*/
|
|
12
|
+
contract WorldToken is ERC20, Ownable {
|
|
13
|
+
uint8 private _decimals;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @notice Constructor
|
|
17
|
+
* @param name Token name
|
|
18
|
+
* @param symbol Token symbol
|
|
19
|
+
* @param initialSupply Initial supply (will be minted to deployer)
|
|
20
|
+
* @param tokenDecimals Number of decimals
|
|
21
|
+
*/
|
|
22
|
+
constructor(
|
|
23
|
+
string memory name,
|
|
24
|
+
string memory symbol,
|
|
25
|
+
uint256 initialSupply,
|
|
26
|
+
uint8 tokenDecimals
|
|
27
|
+
) ERC20(name, symbol) Ownable(msg.sender) {
|
|
28
|
+
_decimals = tokenDecimals;
|
|
29
|
+
_mint(msg.sender, initialSupply * (10 ** tokenDecimals));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @notice Mint new tokens (world owner only)
|
|
34
|
+
* @param to Recipient address
|
|
35
|
+
* @param amount Amount to mint
|
|
36
|
+
*/
|
|
37
|
+
function mint(address to, uint256 amount) external onlyOwner {
|
|
38
|
+
_mint(to, amount);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @notice Burn tokens (world owner only)
|
|
43
|
+
* @param from Address to burn from
|
|
44
|
+
* @param amount Amount to burn
|
|
45
|
+
*/
|
|
46
|
+
function burn(address from, uint256 amount) external onlyOwner {
|
|
47
|
+
_burn(from, amount);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @notice Override decimals
|
|
52
|
+
*/
|
|
53
|
+
function decimals() public view virtual override returns (uint8) {
|
|
54
|
+
return _decimals;
|
|
55
|
+
}
|
|
56
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@moltium/world-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "World runtime for creating agent simulation environments with A2A-based admission and blockchain validation",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"module": "./dist/index.mjs",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"contracts"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"dev": "tsup --watch",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"clean": "rm -rf dist",
|
|
27
|
+
"compile-contracts": "cd contracts && hardhat compile",
|
|
28
|
+
"test-contracts": "cd contracts && hardhat test"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@moltium/core": "^0.1.20",
|
|
35
|
+
"@a2a-js/sdk": "^0.3.0",
|
|
36
|
+
"express": "^4.21.0",
|
|
37
|
+
"winston": "^3.17.0",
|
|
38
|
+
"uuid": "^11.0.3",
|
|
39
|
+
"zod": "^3.24.0",
|
|
40
|
+
"ethers": "^6.13.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"better-sqlite3": "^11.0.0",
|
|
44
|
+
"level": "^8.0.0",
|
|
45
|
+
"ioredis": "^5.0.0",
|
|
46
|
+
"pg": "^8.11.0",
|
|
47
|
+
"mongodb": "^6.0.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"better-sqlite3": {
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"level": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
56
|
+
"ioredis": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"pg": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"mongodb": {
|
|
63
|
+
"optional": true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/express": "^5.0.0",
|
|
68
|
+
"@types/node": "^22.0.0",
|
|
69
|
+
"@types/better-sqlite3": "^7.6.0",
|
|
70
|
+
"hardhat": "^2.22.0",
|
|
71
|
+
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
|
|
72
|
+
"@openzeppelin/contracts": "^5.0.0",
|
|
73
|
+
"tsup": "^8.3.0",
|
|
74
|
+
"typescript": "^5.3.0",
|
|
75
|
+
"vitest": "^2.1.0"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=18.0.0"
|
|
79
|
+
}
|
|
80
|
+
}
|