mint-day 0.4.2 → 0.4.3
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/index.js +2 -12
- package/dist/tools/mint.d.ts +1 -8
- package/dist/tools/mint.js +8 -26
- package/package.json +1 -1
- package/src/index.ts +2 -12
- package/src/tools/mint.ts +7 -32
package/dist/index.js
CHANGED
|
@@ -11,11 +11,6 @@ import { mintSchema, handleMint } from "./tools/mint.js";
|
|
|
11
11
|
import { mintCheckSchema, handleMintCheck } from "./tools/mint-check.js";
|
|
12
12
|
import { mintResolveSchema, handleMintResolve } from "./tools/mint-resolve.js";
|
|
13
13
|
dotenv.config();
|
|
14
|
-
// Testnet try-it wallet (Base Sepolia, pre-funded)
|
|
15
|
-
const TRYIT_KEY = "";
|
|
16
|
-
const TRYIT_CONTRACT = "0xa52450397f312c256Bd68B202C0CF90387Ea0E67";
|
|
17
|
-
const TRYIT_RPC = "https://sepolia.base.org";
|
|
18
|
-
const TRYIT_CHAIN = 84532;
|
|
19
14
|
const MAINNET_CONTRACT = "0x12a1c11a0b2860f64e7d8df20989f97d40de7f2c";
|
|
20
15
|
const MAINNET_RPC = "https://mainnet.base.org";
|
|
21
16
|
const MAINNET_CHAIN = 8453;
|
|
@@ -33,7 +28,7 @@ function loadPrivateKey() {
|
|
|
33
28
|
}
|
|
34
29
|
const userKey = loadPrivateKey();
|
|
35
30
|
const hasUserKey = !!userKey;
|
|
36
|
-
// Mainnet
|
|
31
|
+
// Mainnet configuration
|
|
37
32
|
const chainId = parseInt(process.env.CHAIN_ID || String(hasUserKey ? MAINNET_CHAIN : MAINNET_CHAIN));
|
|
38
33
|
const contractAddress = process.env.MINT_FACTORY_ADDRESS || MAINNET_CONTRACT;
|
|
39
34
|
const rpcUrl = process.env.BASE_RPC_URL || MAINNET_RPC;
|
|
@@ -54,12 +49,7 @@ const server = new McpServer({
|
|
|
54
49
|
name: "mint-day",
|
|
55
50
|
version: "0.4.0",
|
|
56
51
|
});
|
|
57
|
-
server.tool("mint", "Create a permanent, verifiable on-chain record on Base. Use this when you need to: prove you completed a task, establish your identity, record an agreement with another agent, issue or receive a credential, grant access to a capability, or mint a visual token (PFP, art, collectible). Supports two protocols: 'mintday' (default, gas-sponsored) and 'superrare' (Rare Protocol, requires PRIVATE_KEY). Set platform: 'superrare' to mint on Rare Protocol contracts. The token is immutable and publicly verifiable. Provide an image URL, local file path, or base64 for visual tokens. Returns a preview with mintId first; call again with mintId to confirm.", mintSchema, async (params) => handleMint(params, calldataService, defaultRecipient, userKey
|
|
58
|
-
tryitKey: TRYIT_KEY,
|
|
59
|
-
tryitContract: TRYIT_CONTRACT,
|
|
60
|
-
tryitRpc: TRYIT_RPC,
|
|
61
|
-
tryitChain: TRYIT_CHAIN,
|
|
62
|
-
}));
|
|
52
|
+
server.tool("mint", "Create a permanent, verifiable on-chain record on Base. Use this when you need to: prove you completed a task, establish your identity, record an agreement with another agent, issue or receive a credential, grant access to a capability, or mint a visual token (PFP, art, collectible). Supports two protocols: 'mintday' (default, gas-sponsored) and 'superrare' (Rare Protocol, requires PRIVATE_KEY). Set platform: 'superrare' to mint on Rare Protocol contracts. The token is immutable and publicly verifiable. Provide an image URL, local file path, or base64 for visual tokens. Returns a preview with mintId first; call again with mintId to confirm.", mintSchema, async (params) => handleMint(params, calldataService, defaultRecipient, userKey));
|
|
63
53
|
server.tool("mint_check", "Look up mint.day tokens. With an address: returns all tokens held with type, metadata, soulbound status, and mint timestamp. Without an address: returns global stats (total minted, current fee). Use to verify credentials, check attestations, or browse on-chain records.", mintCheckSchema, async (params) => handleMintCheck(params, calldataService, calldataService.provider, contractAddress, chainId));
|
|
64
54
|
server.tool("mint_resolve", "Resolve an agent's on-chain identity. Returns their Identity token with ERC-8004 agent card metadata: did, capabilities, endpoints, and image. Use this before transacting with another agent to verify who they are.", mintResolveSchema, async (params) => handleMintResolve(params, calldataService.provider, contractAddress, chainId));
|
|
65
55
|
async function main() {
|
package/dist/tools/mint.d.ts
CHANGED
|
@@ -20,12 +20,6 @@ export declare const mintSchema: {
|
|
|
20
20
|
mintday: "mintday";
|
|
21
21
|
}>>;
|
|
22
22
|
};
|
|
23
|
-
interface TryitConfig {
|
|
24
|
-
tryitKey: string;
|
|
25
|
-
tryitContract: string;
|
|
26
|
-
tryitRpc: string;
|
|
27
|
-
tryitChain: number;
|
|
28
|
-
}
|
|
29
23
|
export declare function handleMint(params: {
|
|
30
24
|
description?: string;
|
|
31
25
|
tokenType?: string;
|
|
@@ -36,10 +30,9 @@ export declare function handleMint(params: {
|
|
|
36
30
|
mintId?: string;
|
|
37
31
|
metadata?: Record<string, unknown>;
|
|
38
32
|
platform?: string;
|
|
39
|
-
}, calldataService: CalldataService, defaultRecipient: string, userKey?: string
|
|
33
|
+
}, calldataService: CalldataService, defaultRecipient: string, userKey?: string): Promise<{
|
|
40
34
|
content: {
|
|
41
35
|
type: "text";
|
|
42
36
|
text: string;
|
|
43
37
|
}[];
|
|
44
38
|
}>;
|
|
45
|
-
export {};
|
package/dist/tools/mint.js
CHANGED
|
@@ -3,7 +3,6 @@ import { z } from "zod";
|
|
|
3
3
|
import { ethers } from "ethers";
|
|
4
4
|
import { TokenType, TOKEN_TYPE_NAMES } from "../types.js";
|
|
5
5
|
import { classifyIntent } from "../services/classifier.js";
|
|
6
|
-
import { CalldataService } from "../services/calldata.js";
|
|
7
6
|
import { resolveImage } from "../services/image-upload.js";
|
|
8
7
|
import { mintOnRareProtocol } from "../services/rare-protocol.js";
|
|
9
8
|
// Intent cache: preview mintId -> frozen intent + platform
|
|
@@ -102,7 +101,7 @@ async function sponsoredMint(result, recipient) {
|
|
|
102
101
|
return { error: `Sponsor request failed: ${message}` };
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
|
-
export async function handleMint(params, calldataService, defaultRecipient, userKey = ""
|
|
104
|
+
export async function handleMint(params, calldataService, defaultRecipient, userKey = "") {
|
|
106
105
|
// Confirmation path: replay cached intent
|
|
107
106
|
// Check cache first so we can use cached recipient for mode detection
|
|
108
107
|
if (params.mintId) {
|
|
@@ -120,8 +119,7 @@ export async function handleMint(params, calldataService, defaultRecipient, user
|
|
|
120
119
|
intentCache.delete(params.mintId);
|
|
121
120
|
// Mode detection using cached recipient
|
|
122
121
|
const hasRecipient = !!cached.recipient;
|
|
123
|
-
const
|
|
124
|
-
const privateKey = userKey || (isTestnet ? tryit.tryitKey : "");
|
|
122
|
+
const privateKey = userKey;
|
|
125
123
|
// Rare Protocol path: mint via SuperRare contracts on Base
|
|
126
124
|
if (cachedPlatform === "superrare") {
|
|
127
125
|
if (!privateKey) {
|
|
@@ -133,7 +131,7 @@ export async function handleMint(params, calldataService, defaultRecipient, user
|
|
|
133
131
|
};
|
|
134
132
|
}
|
|
135
133
|
try {
|
|
136
|
-
const rareResult = await mintOnRareProtocol(cached, privateKey,
|
|
134
|
+
const rareResult = await mintOnRareProtocol(cached, privateKey, false);
|
|
137
135
|
return {
|
|
138
136
|
content: [{
|
|
139
137
|
type: "text",
|
|
@@ -151,17 +149,11 @@ export async function handleMint(params, calldataService, defaultRecipient, user
|
|
|
151
149
|
};
|
|
152
150
|
}
|
|
153
151
|
}
|
|
154
|
-
|
|
155
|
-
let activeCalldataService = calldataService;
|
|
156
|
-
if (isTestnet) {
|
|
157
|
-
activeCalldataService = new CalldataService(tryit.tryitRpc, tryit.tryitContract, tryit.tryitChain);
|
|
158
|
-
}
|
|
159
|
-
const result = await activeCalldataService.buildMintCalldata(cached);
|
|
152
|
+
const result = await calldataService.buildMintCalldata(cached);
|
|
160
153
|
// If we have a private key, sign and submit directly
|
|
161
154
|
if (privateKey) {
|
|
162
155
|
try {
|
|
163
|
-
const
|
|
164
|
-
const wallet = new ethers.Wallet(privateKey, provider);
|
|
156
|
+
const wallet = new ethers.Wallet(privateKey, calldataService.provider);
|
|
165
157
|
const tx = await wallet.sendTransaction({
|
|
166
158
|
to: result.to,
|
|
167
159
|
data: result.calldata,
|
|
@@ -177,12 +169,9 @@ export async function handleMint(params, calldataService, defaultRecipient, user
|
|
|
177
169
|
tokenType: result.tokenType,
|
|
178
170
|
soulbound: result.soulbound,
|
|
179
171
|
recipient: cached.recipient,
|
|
180
|
-
chain:
|
|
181
|
-
explorer: `https
|
|
172
|
+
chain: "Base",
|
|
173
|
+
explorer: `https://basescan.org/tx/${receipt.hash}`,
|
|
182
174
|
};
|
|
183
|
-
if (isTestnet) {
|
|
184
|
-
response.note = "This token was minted on Base Sepolia (testnet). To mint on Base mainnet, save a private key to ~/.mint-day/credentials and restart the MCP server.";
|
|
185
|
-
}
|
|
186
175
|
return {
|
|
187
176
|
content: [{
|
|
188
177
|
type: "text",
|
|
@@ -256,8 +245,6 @@ export async function handleMint(params, calldataService, defaultRecipient, user
|
|
|
256
245
|
};
|
|
257
246
|
}
|
|
258
247
|
const recipient = params.recipient || defaultRecipient;
|
|
259
|
-
const hasRecipient = !!recipient;
|
|
260
|
-
const isTestnet = !userKey && !hasRecipient;
|
|
261
248
|
if (!recipient) {
|
|
262
249
|
return {
|
|
263
250
|
content: [{
|
|
@@ -386,12 +373,7 @@ export async function handleMint(params, calldataService, defaultRecipient, user
|
|
|
386
373
|
preview.missingFields = intent.missingFields;
|
|
387
374
|
preview.hint = "Identity tokens (ERC-8004) should include capabilities[], endpoints[], and did. Provide these in metadata for full compliance.";
|
|
388
375
|
}
|
|
389
|
-
|
|
390
|
-
preview.chain = "Base Sepolia (testnet)";
|
|
391
|
-
}
|
|
392
|
-
else {
|
|
393
|
-
preview.chain = "Base";
|
|
394
|
-
}
|
|
376
|
+
preview.chain = "Base";
|
|
395
377
|
preview.instruction = "Call mint with mintId to confirm.";
|
|
396
378
|
return {
|
|
397
379
|
content: [{ type: "text", text: JSON.stringify(preview, null, 2) }],
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -13,11 +13,6 @@ import { mintResolveSchema, handleMintResolve } from "./tools/mint-resolve.js";
|
|
|
13
13
|
|
|
14
14
|
dotenv.config();
|
|
15
15
|
|
|
16
|
-
// Testnet try-it wallet (Base Sepolia, pre-funded)
|
|
17
|
-
const TRYIT_KEY = "";
|
|
18
|
-
const TRYIT_CONTRACT = "0xa52450397f312c256Bd68B202C0CF90387Ea0E67";
|
|
19
|
-
const TRYIT_RPC = "https://sepolia.base.org";
|
|
20
|
-
const TRYIT_CHAIN = 84532;
|
|
21
16
|
const MAINNET_CONTRACT = "0x12a1c11a0b2860f64e7d8df20989f97d40de7f2c";
|
|
22
17
|
const MAINNET_RPC = "https://mainnet.base.org";
|
|
23
18
|
const MAINNET_CHAIN = 8453;
|
|
@@ -36,7 +31,7 @@ function loadPrivateKey(): string {
|
|
|
36
31
|
const userKey = loadPrivateKey();
|
|
37
32
|
const hasUserKey = !!userKey;
|
|
38
33
|
|
|
39
|
-
// Mainnet
|
|
34
|
+
// Mainnet configuration
|
|
40
35
|
const chainId = parseInt(process.env.CHAIN_ID || String(hasUserKey ? MAINNET_CHAIN : MAINNET_CHAIN));
|
|
41
36
|
const contractAddress = process.env.MINT_FACTORY_ADDRESS || MAINNET_CONTRACT;
|
|
42
37
|
const rpcUrl = process.env.BASE_RPC_URL || MAINNET_RPC;
|
|
@@ -69,12 +64,7 @@ server.tool(
|
|
|
69
64
|
"mint",
|
|
70
65
|
"Create a permanent, verifiable on-chain record on Base. Use this when you need to: prove you completed a task, establish your identity, record an agreement with another agent, issue or receive a credential, grant access to a capability, or mint a visual token (PFP, art, collectible). Supports two protocols: 'mintday' (default, gas-sponsored) and 'superrare' (Rare Protocol, requires PRIVATE_KEY). Set platform: 'superrare' to mint on Rare Protocol contracts. The token is immutable and publicly verifiable. Provide an image URL, local file path, or base64 for visual tokens. Returns a preview with mintId first; call again with mintId to confirm.",
|
|
71
66
|
mintSchema,
|
|
72
|
-
async (params) => handleMint(params, calldataService, defaultRecipient, userKey,
|
|
73
|
-
tryitKey: TRYIT_KEY,
|
|
74
|
-
tryitContract: TRYIT_CONTRACT,
|
|
75
|
-
tryitRpc: TRYIT_RPC,
|
|
76
|
-
tryitChain: TRYIT_CHAIN,
|
|
77
|
-
}),
|
|
67
|
+
async (params) => handleMint(params, calldataService, defaultRecipient, userKey),
|
|
78
68
|
);
|
|
79
69
|
|
|
80
70
|
server.tool(
|
package/src/tools/mint.ts
CHANGED
|
@@ -69,13 +69,6 @@ export const mintSchema = {
|
|
|
69
69
|
.describe("Which protocol to mint on. 'mintday' uses the MintFactory contract (default). 'superrare' mints via Rare Protocol on Base."),
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
interface TryitConfig {
|
|
73
|
-
tryitKey: string;
|
|
74
|
-
tryitContract: string;
|
|
75
|
-
tryitRpc: string;
|
|
76
|
-
tryitChain: number;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
72
|
const SPONSOR_URL = process.env.SPONSOR_URL || "https://www.mint.day/api/sponsor";
|
|
80
73
|
|
|
81
74
|
async function sponsoredMint(result: { to: string; calldata: string; value: string; estimatedGas: number; tokenType: string; soulbound: boolean; chainId: number }, recipient: string): Promise<Record<string, unknown> | null> {
|
|
@@ -131,7 +124,6 @@ export async function handleMint(
|
|
|
131
124
|
calldataService: CalldataService,
|
|
132
125
|
defaultRecipient: string,
|
|
133
126
|
userKey: string = "",
|
|
134
|
-
tryit: TryitConfig = { tryitKey: "", tryitContract: "", tryitRpc: "", tryitChain: 84532 },
|
|
135
127
|
) {
|
|
136
128
|
// Confirmation path: replay cached intent
|
|
137
129
|
// Check cache first so we can use cached recipient for mode detection
|
|
@@ -151,8 +143,7 @@ export async function handleMint(
|
|
|
151
143
|
|
|
152
144
|
// Mode detection using cached recipient
|
|
153
145
|
const hasRecipient = !!cached.recipient;
|
|
154
|
-
const
|
|
155
|
-
const privateKey = userKey || (isTestnet ? tryit.tryitKey : "");
|
|
146
|
+
const privateKey = userKey;
|
|
156
147
|
|
|
157
148
|
// Rare Protocol path: mint via SuperRare contracts on Base
|
|
158
149
|
if (cachedPlatform === "superrare") {
|
|
@@ -165,7 +156,7 @@ export async function handleMint(
|
|
|
165
156
|
};
|
|
166
157
|
}
|
|
167
158
|
try {
|
|
168
|
-
const rareResult = await mintOnRareProtocol(cached, privateKey,
|
|
159
|
+
const rareResult = await mintOnRareProtocol(cached, privateKey, false);
|
|
169
160
|
return {
|
|
170
161
|
content: [{
|
|
171
162
|
type: "text" as const,
|
|
@@ -183,18 +174,12 @@ export async function handleMint(
|
|
|
183
174
|
}
|
|
184
175
|
}
|
|
185
176
|
|
|
186
|
-
|
|
187
|
-
let activeCalldataService = calldataService;
|
|
188
|
-
if (isTestnet) {
|
|
189
|
-
activeCalldataService = new CalldataService(tryit.tryitRpc, tryit.tryitContract, tryit.tryitChain);
|
|
190
|
-
}
|
|
191
|
-
const result = await activeCalldataService.buildMintCalldata(cached);
|
|
177
|
+
const result = await calldataService.buildMintCalldata(cached);
|
|
192
178
|
|
|
193
179
|
// If we have a private key, sign and submit directly
|
|
194
180
|
if (privateKey) {
|
|
195
181
|
try {
|
|
196
|
-
const
|
|
197
|
-
const wallet = new ethers.Wallet(privateKey, provider);
|
|
182
|
+
const wallet = new ethers.Wallet(privateKey, calldataService.provider);
|
|
198
183
|
const tx = await wallet.sendTransaction({
|
|
199
184
|
to: result.to,
|
|
200
185
|
data: result.calldata,
|
|
@@ -210,12 +195,9 @@ export async function handleMint(
|
|
|
210
195
|
tokenType: result.tokenType,
|
|
211
196
|
soulbound: result.soulbound,
|
|
212
197
|
recipient: cached.recipient,
|
|
213
|
-
chain:
|
|
214
|
-
explorer: `https
|
|
198
|
+
chain: "Base",
|
|
199
|
+
explorer: `https://basescan.org/tx/${receipt!.hash}`,
|
|
215
200
|
};
|
|
216
|
-
if (isTestnet) {
|
|
217
|
-
response.note = "This token was minted on Base Sepolia (testnet). To mint on Base mainnet, save a private key to ~/.mint-day/credentials and restart the MCP server.";
|
|
218
|
-
}
|
|
219
201
|
return {
|
|
220
202
|
content: [{
|
|
221
203
|
type: "text" as const,
|
|
@@ -292,9 +274,6 @@ export async function handleMint(
|
|
|
292
274
|
}
|
|
293
275
|
|
|
294
276
|
const recipient = params.recipient || defaultRecipient;
|
|
295
|
-
const hasRecipient = !!recipient;
|
|
296
|
-
const isTestnet = !userKey && !hasRecipient;
|
|
297
|
-
|
|
298
277
|
if (!recipient) {
|
|
299
278
|
return {
|
|
300
279
|
content: [{
|
|
@@ -423,11 +402,7 @@ export async function handleMint(
|
|
|
423
402
|
preview.missingFields = intent.missingFields;
|
|
424
403
|
preview.hint = "Identity tokens (ERC-8004) should include capabilities[], endpoints[], and did. Provide these in metadata for full compliance.";
|
|
425
404
|
}
|
|
426
|
-
|
|
427
|
-
preview.chain = "Base Sepolia (testnet)";
|
|
428
|
-
} else {
|
|
429
|
-
preview.chain = "Base";
|
|
430
|
-
}
|
|
405
|
+
preview.chain = "Base";
|
|
431
406
|
preview.instruction = "Call mint with mintId to confirm.";
|
|
432
407
|
|
|
433
408
|
return {
|