mint-day 0.3.0 → 0.3.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 CHANGED
@@ -1,10 +1,58 @@
1
- # mint.day
1
+ <div align="center">
2
+ <img src="site/assets/logo.png" alt="mint.day" width="80" />
3
+ <h1>mint.day</h1>
4
+ <p><strong>Free NFT minting for agents. On Base.</strong></p>
5
+ <p>Tell your agent what to mint. It lands on-chain in seconds.<br/>No wallet. No gas. No code.</p>
2
6
 
3
- Agents mint NFTs now.
7
+ [![npm](https://img.shields.io/npm/v/mint-day?color=2db87a&label=npm)](https://www.npmjs.com/package/mint-day)
8
+ [![license](https://img.shields.io/badge/license-MIT-2db87a)](LICENSE)
9
+ [![network](https://img.shields.io/badge/network-Base-0052FF)](https://basescan.org/address/0x12a1c11a0b2860f64e7d8df20989f97d40de7f2c)
10
+ [![live](https://img.shields.io/badge/live-mint.day-e5a030)](https://mint.day)
11
+ </div>
4
12
 
5
- ## Quick start
13
+ ---
6
14
 
7
- **1. Install** (zero config)
15
+ <img src="site/assets/screenshot-home.png" alt="mint.day homepage" width="100%" />
16
+
17
+ ## What is mint.day?
18
+
19
+ mint.day is an MCP server that gives any AI agent the ability to mint permanent, verifiable NFTs on Base. Identity cards, attestations, credentials, receipts, access passes — or any custom token you can describe in plain language.
20
+
21
+ Gas is sponsored. Wallets are optional. It works whether you are a seasoned Solidity developer or someone who just discovered Claude Code last month.
22
+
23
+ ---
24
+
25
+ ## Get started in 60 seconds
26
+
27
+ ### Option A: You use Claude Code, Cursor, Windsurf, or any MCP client
28
+
29
+ Copy this prompt and paste it into your AI assistant:
30
+
31
+ ```
32
+ Install mint.day for me.
33
+
34
+ mint.day is an MCP server that lets you mint NFTs on Base with natural language.
35
+ Identity, attestations, credentials, receipts, access passes, and visual tokens with images.
36
+
37
+ Add this MCP config:
38
+
39
+ {
40
+ "mcpServers": {
41
+ "mint-day": {
42
+ "command": "npx",
43
+ "args": ["mint-day"]
44
+ }
45
+ }
46
+ }
47
+
48
+ That's it. No API keys. No wallet. Gas is sponsored. Just tell me what to mint.
49
+ ```
50
+
51
+ Your assistant will handle the rest.
52
+
53
+ ### Option B: Add it manually
54
+
55
+ Drop this into your MCP config file (`~/.cursor/mcp.json`, `claude_desktop_config.json`, etc.):
8
56
 
9
57
  ```json
10
58
  {
@@ -17,56 +65,77 @@ Agents mint NFTs now.
17
65
  }
18
66
  ```
19
67
 
20
- Works with Claude Code, Cursor, Windsurf, OpenClaw, and any MCP client.
68
+ Restart your AI client. Done.
21
69
 
22
- **2. Mint**
70
+ ### Option C: npm package
23
71
 
24
- Tell your agent: "Proof I completed the security audit for 0xABC"
72
+ ```bash
73
+ npm install mint-day
74
+ ```
25
75
 
26
- **3. Verify**
76
+ ```ts
77
+ import { encodeMetadata } from 'mint-day';
27
78
 
28
- ```
29
- mint_check({ address: "0xABC..." })
79
+ const tokenURI = encodeMetadata({
80
+ name: "Audit complete: Protocol XYZ",
81
+ tokenType: "Attestation",
82
+ soulbound: true,
83
+ recipient: "0xABC..."
84
+ });
30
85
  ```
31
86
 
32
- That's it. Your agent classifies the intent, builds the token, and returns a ready-to-sign transaction.
87
+ ---
33
88
 
34
- ## Signing transactions
89
+ ## Try it now
35
90
 
36
- mint.day can sign and submit transactions directly, or return calldata for your own signer.
91
+ Once installed, tell your agent anything like:
37
92
 
38
- ### Option A: Built-in signing (recommended)
93
+ > "Proof I shipped the v2 API today"
39
94
 
40
- Save a private key and mint.day handles everything:
95
+ > "Mint me an identity token with my agent name and capabilities"
41
96
 
42
- ```bash
43
- mkdir -p ~/.mint-day
44
- node -e "const w = require('ethers').Wallet.createRandom(); console.log(w.privateKey); console.error('Address: ' + w.address)" 2>&1 | head -1 > ~/.mint-day/credentials
45
- chmod 600 ~/.mint-day/credentials
46
- ```
97
+ > "Issue an access pass to 0xABC... for the beta"
47
98
 
48
- Fund the address with a small amount of ETH on Base (gas is < $0.01 per mint). Restart the MCP server.
99
+ > "Receipt for 0.1 ETH paid to 0xDEF... on March 15"
49
100
 
50
- You can also set `PRIVATE_KEY` in your MCP env config instead of using the file.
101
+ Your agent classifies the intent, builds the metadata, and returns a ready-to-sign transaction. Confirm, and it is on-chain.
51
102
 
52
- ### Option B: Bring your own signer
103
+ ---
53
104
 
54
- Don't set a private key. mint.day returns calldata. Submit it with Coinbase AgentKit, Lit Protocol, Privy, or any EVM wallet.
105
+ ## Live feed
55
106
 
56
- ## Tools
107
+ <img src="site/assets/screenshot-feed.png" alt="mint.day live feed" width="100%" />
57
108
 
58
- ### `mint`
109
+ Browse all minted tokens at [mint.day/feed](https://mint.day/feed).
110
+
111
+ ---
112
+
113
+ ## Token types
114
+
115
+ | Type | Default | Use for |
116
+ |------|---------|---------|
117
+ | **Identity** | transferable | Agent ID card, on-chain registration, DID |
118
+ | **Attestation** | soulbound | Proof of action, task completion, audit trail |
119
+ | **Credential** | soulbound | Reputation anchor, certification, earned status |
120
+ | **Receipt** | transferable | Payment record, transaction proof between parties |
121
+ | **Pass** | transferable | API access, capability unlock, membership |
122
+
123
+ All types support `image` and `animation_url` for visual NFTs — PFPs, art, screenshots, generative visuals.
59
124
 
60
- Create a permanent, verifiable on-chain record on Base.
125
+ ---
61
126
 
62
- **Natural language:**
127
+ ## MCP tools
63
128
 
129
+ ### `mint`
130
+
131
+ Create a permanent on-chain record.
132
+
133
+ **Natural language** (agent classifies intent automatically):
64
134
  ```
65
135
  mint({ description: "Proof I completed the security audit for 0xABC" })
66
136
  ```
67
137
 
68
- **Structured** (skips classification):
69
-
138
+ **Structured** (skip classification):
70
139
  ```
71
140
  mint({
72
141
  description: "Task completion attestation",
@@ -77,80 +146,105 @@ mint({
77
146
  ```
78
147
 
79
148
  **With an image:**
80
-
81
149
  ```
82
150
  mint({
83
151
  description: "My agent identity",
84
152
  tokenType: "Identity",
85
- image: "data:image/png;base64,..."
153
+ image: "https://..." // or data:image/png;base64,...
86
154
  })
87
155
  ```
88
156
 
89
- Every mint returns a preview first. Confirm with `mintId` to execute:
157
+ Every mint returns a **preview** first. Confirm with `mintId` to execute:
90
158
 
91
159
  ```
92
160
  mint({ mintId: "a3f8c1e90b2d" })
93
161
  ```
94
162
 
95
- With built-in signing, you get back a tx hash and explorer link. Without it, you get calldata.
163
+ ---
96
164
 
97
165
  ### `mint_check`
98
166
 
99
- Look up tokens by address, transaction hash, or get global stats.
167
+ Look up tokens by address, tx hash, or get global stats.
100
168
 
101
169
  ```
102
- mint_check({ address: "0xABC..." })
103
- mint_check({ txHash: "0x230b..." })
104
- mint_check({}) // global stats
170
+ mint_check({ address: "0xABC..." }) // all tokens for a wallet
171
+ mint_check({ txHash: "0x230b..." }) // specific mint
172
+ mint_check({}) // global stats
105
173
  ```
106
174
 
175
+ ---
176
+
107
177
  ### `mint_resolve`
108
178
 
109
- Resolve an agent's on-chain identity. Returns their Identity token with ERC-8004 agent card metadata.
179
+ Resolve an agent's on-chain identity. Returns their Identity token with ERC-8004 agent card metadata — DID, capabilities, endpoints.
110
180
 
111
181
  ```
112
182
  mint_resolve({ address: "0xABC..." })
113
183
  ```
114
184
 
115
- ## Token types
185
+ ---
116
186
 
117
- | Type | Default | Use for |
118
- |------|---------|---------|
119
- | Identity | transferable | Agent ID card, on-chain registration |
120
- | Attestation | soulbound | Proof of action, task completion |
121
- | Credential | soulbound | Reputation anchor, certification |
122
- | Receipt | transferable | Payment record between two parties |
123
- | Pass | transferable | API access, capability unlock |
187
+ ## Signing transactions
188
+
189
+ ### Option A: Built-in signing (recommended)
190
+
191
+ Generate a key, fund it with a small amount of ETH on Base (gas is less than $0.01), and mint.day handles signing and submission:
192
+
193
+ ```bash
194
+ mkdir -p ~/.mint-day
195
+ node -e "
196
+ const w = require('ethers').Wallet.createRandom();
197
+ console.log(w.privateKey);
198
+ console.error('Address: ' + w.address);
199
+ " 2>&1 | head -1 > ~/.mint-day/credentials
200
+ chmod 600 ~/.mint-day/credentials
201
+ ```
202
+
203
+ Or set `PRIVATE_KEY` in your MCP env config.
124
204
 
125
- All types support `image` and `animation_url` for visual NFTs (PFPs, art, collectibles).
205
+ ### Option B: Bring your own signer
206
+
207
+ No private key needed. mint.day returns calldata you can submit with Coinbase AgentKit, Privy, Lit Protocol, or any EVM wallet.
208
+
209
+ ---
126
210
 
127
- ## Architecture
211
+ ## How it works
128
212
 
129
213
  ```
130
214
  Agent -> mint tool -> classifier (Groq Llama) -> metadata builder -> calldata
131
215
  |
132
- [if PRIVATE_KEY] sign + submit -> tx hash <----|
133
- [if no key] return calldata <-------------|
216
+ [if PRIVATE_KEY] sign + submit -> tx hash, explorer link |
217
+ [if no key] return calldata for your own signer -----|
134
218
  |
135
- MintFactory.sol (Base)
219
+ MintFactory.sol on Base mainnet
136
220
  ```
137
221
 
138
- ## Contracts
139
-
140
- - **Base Mainnet**: [`0xbf12d372444dcf69df9316d961439f6b5919e8d0`](https://basescan.org/address/0xbf12d372444dcf69df9316d961439f6b5919e8d0)
141
- - **Base Sepolia**: [`0xa52450397f312c256Bd68B202C0CF90387Ea0E67`](https://sepolia.basescan.org/address/0xa52450397f312c256Bd68B202C0CF90387Ea0E67)
222
+ ---
142
223
 
143
224
  ## Configuration
144
225
 
145
226
  All optional. mint.day works with zero config.
146
227
 
147
- | Env var | Default | Purpose |
148
- |---------|---------|---------|
228
+ | Variable | Default | Purpose |
229
+ |----------|---------|---------|
149
230
  | `PRIVATE_KEY` | `~/.mint-day/credentials` | Signs and submits transactions |
150
231
  | `BASE_RPC_URL` | `https://mainnet.base.org` | RPC endpoint |
151
232
  | `CHAIN_ID` | `8453` | Base Mainnet |
152
- | `MINT_FACTORY_ADDRESS` | `0xbf12d3...` | Contract address |
153
- | `CLASSIFY_URL` | hosted endpoint | Intent classifier |
233
+ | `MINT_FACTORY_ADDRESS` | see below | Override contract address |
234
+ | `CLASSIFY_URL` | hosted endpoint | Intent classifier service |
235
+
236
+ ---
237
+
238
+ ## Contracts
239
+
240
+ | Network | Address |
241
+ |---------|---------|
242
+ | **Base Mainnet** | [`0x12a1c11a0b2860f64e7d8df20989f97d40de7f2c`](https://basescan.org/address/0x12a1c11a0b2860f64e7d8df20989f97d40de7f2c) |
243
+ | **Base Sepolia** | [`0x16e0072Eb4131106e266035E98Cfd07532B88EAa`](https://sepolia.basescan.org/address/0x16e0072Eb4131106e266035E98Cfd07532B88EAa) |
244
+
245
+ Permissionless. Anyone can call `mint()` directly without the MCP server.
246
+
247
+ ---
154
248
 
155
249
  ## Development
156
250
 
@@ -161,6 +255,16 @@ npm run build # compile to dist/
161
255
  npm start # run compiled
162
256
  ```
163
257
 
164
- ## License
258
+ ---
259
+
260
+ ## Links
261
+
262
+ - [mint.day](https://mint.day) — live site
263
+ - [mint.day/feed](https://mint.day/feed) — live feed of all minted tokens
264
+ - [npm](https://www.npmjs.com/package/mint-day) — npm package
265
+ - [OpenSea](https://opensea.io/collection/mintdotday) — collection
266
+ - [X](https://x.com/mintdotday) — @mintdotday
267
+
268
+ ---
165
269
 
166
- MIT
270
+ MIT — built by [@jordanlyall](https://x.com/jordanlyall)
@@ -1,12 +1,20 @@
1
- const TYPE_COLORS = {
2
- Identity: { bg: "#0c1220", accent: "#60a5fa", text: "#93bbfc" },
3
- Attestation: { bg: "#0a1510", accent: "#22c55e", text: "#6ee7a0" },
4
- Credential: { bg: "#100c1e", accent: "#a78bfa", text: "#c4b5fd" },
5
- Receipt: { bg: "#151008", accent: "#fb923c", text: "#fdba74" },
6
- Pass: { bg: "#0a1518", accent: "#22d3ee", text: "#67e8f9" },
1
+ const TYPE_COLORS_DARK = {
2
+ Identity: { bg: "#0c1220", bgGrad: "#0c1220", accent: "#60a5fa", text: "#93bbfc" },
3
+ Attestation: { bg: "#0a1510", bgGrad: "#0a1510", accent: "#22c55e", text: "#6ee7a0" },
4
+ Credential: { bg: "#100c1e", bgGrad: "#100c1e", accent: "#a78bfa", text: "#c4b5fd" },
5
+ Receipt: { bg: "#151008", bgGrad: "#151008", accent: "#fb923c", text: "#fdba74" },
6
+ Pass: { bg: "#0a1518", bgGrad: "#0a1518", accent: "#22d3ee", text: "#67e8f9" },
7
+ };
8
+ const TYPE_COLORS_LIGHT = {
9
+ Identity: { bg: "#eff6ff", bgGrad: "#FFFDF8", accent: "#3b82f6", text: "#1d4ed8" },
10
+ Attestation: { bg: "#f0faf5", bgGrad: "#FFFDF8", accent: "#2db87a", text: "#1e9e65" },
11
+ Credential: { bg: "#faf5ff", bgGrad: "#FFFDF8", accent: "#a855f7", text: "#7e22ce" },
12
+ Receipt: { bg: "#fffbeb", bgGrad: "#FFFDF8", accent: "#e5a030", text: "#b45309" },
13
+ Pass: { bg: "#ecfeff", bgGrad: "#FFFDF8", accent: "#0891b2", text: "#0e7490" },
7
14
  };
8
15
  function generateDefaultImage(metadata) {
9
- const colors = TYPE_COLORS[metadata.tokenType] || TYPE_COLORS.Attestation;
16
+ const palette = metadata.theme === "light" ? TYPE_COLORS_LIGHT : TYPE_COLORS_DARK;
17
+ const colors = palette[metadata.tokenType] || palette.Attestation;
10
18
  const name = metadata.name || "mint.day token";
11
19
  const tokenType = metadata.tokenType || "Token";
12
20
  const soulbound = metadata.soulbound;
@@ -59,8 +67,12 @@ function generateDefaultImage(metadata) {
59
67
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" width="400" height="400">
60
68
  <defs>
61
69
  ${pattern}
70
+ <linearGradient id="bg-grad" x1="0" y1="0" x2="1" y2="1">
71
+ <stop offset="0%" stop-color="${colors.bgGrad}"/>
72
+ <stop offset="100%" stop-color="${colors.bg}"/>
73
+ </linearGradient>
62
74
  </defs>
63
- <rect width="400" height="400" fill="${colors.bg}"/>
75
+ <rect width="400" height="400" fill="url(#bg-grad)"/>
64
76
  <rect width="400" height="400" fill="url(#${patternId})"/>
65
77
 
66
78
  <!-- Top accent line -->
@@ -10,7 +10,7 @@ const MINT_FACTORY_ABI = [
10
10
  ];
11
11
  // Deploy blocks per chain to avoid scanning from genesis
12
12
  const DEPLOY_BLOCKS = {
13
- 8453: 28000000, // Base mainnet (approximate, update after deploy)
13
+ 8453: 43460000, // Base mainnet (MintFactory deploy block)
14
14
  84532: 22000000, // Base Sepolia (approximate)
15
15
  };
16
16
  export const mintCheckSchema = {
@@ -128,7 +128,14 @@ export async function handleMintCheck(params, calldataService, provider, contrac
128
128
  const contract = new ethers.Contract(contractAddress, MINT_FACTORY_ABI, provider);
129
129
  const fromBlock = DEPLOY_BLOCKS[chainId] || 0;
130
130
  const filter = contract.filters.Minted(null, address);
131
- const events = await contract.queryFilter(filter, fromBlock, "latest");
131
+ const latestBlock = await provider.getBlockNumber();
132
+ const CHUNK_SIZE = 9999;
133
+ const events = [];
134
+ for (let start = fromBlock; start <= latestBlock; start += CHUNK_SIZE + 1) {
135
+ const end = Math.min(start + CHUNK_SIZE, latestBlock);
136
+ const chunk = await contract.queryFilter(filter, start, end);
137
+ events.push(...chunk);
138
+ }
132
139
  if (events.length === 0) {
133
140
  return {
134
141
  content: [{
@@ -9,7 +9,7 @@ const MINT_FACTORY_ABI = [
9
9
  "function ownerOf(uint256 tokenId) view returns (address)",
10
10
  ];
11
11
  const DEPLOY_BLOCKS = {
12
- 8453: 28000000,
12
+ 8453: 43460000,
13
13
  84532: 22000000,
14
14
  };
15
15
  export const mintResolveSchema = {
@@ -42,9 +42,16 @@ export async function handleMintResolve(params, provider, contractAddress, chain
42
42
  }
43
43
  const contract = new ethers.Contract(contractAddress, MINT_FACTORY_ABI, provider);
44
44
  const fromBlock = DEPLOY_BLOCKS[chainId] || 0;
45
- // Query all Minted events to this address
45
+ // Query all Minted events to this address (chunked to avoid RPC limits)
46
46
  const filter = contract.filters.Minted(null, address);
47
- const events = await contract.queryFilter(filter, fromBlock, "latest");
47
+ const latestBlock = await provider.getBlockNumber();
48
+ const CHUNK_SIZE = 9999;
49
+ const events = [];
50
+ for (let start = fromBlock; start <= latestBlock; start += CHUNK_SIZE + 1) {
51
+ const end = Math.min(start + CHUNK_SIZE, latestBlock);
52
+ const chunk = await contract.queryFilter(filter, start, end);
53
+ events.push(...chunk);
54
+ }
48
55
  // Find Identity tokens (tokenType === 0)
49
56
  let identityEvent = null;
50
57
  for (const event of events) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mint-day",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Agent-native minting on Base. One tool call, any token type.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {