mirror of
https://github.com/aljazceru/mcp-code.git
synced 2025-12-17 04:35:19 +01:00
- Implemented the `zap` command in the CLI to allow users to send sats to a user, event, or snippet using a NIP-60 wallet. - Created a new `zap.ts` file to handle the command logic and integrated it into the MCP server. - Added wallet balance command to check the balance of a user's wallet. - Enhanced the MCP server to register the new zap command and wallet balance command. - Introduced caching for wallets to optimize performance and reduce redundant network requests. - Updated database schema to include snippets table for storing code snippets. - Improved logging functionality for better debugging and tracking of operations. - Added functionality to save snippets to the database upon retrieval. - Updated project overview documentation to reflect new features and structure. - Refactored existing commands and logic for better modularity and maintainability.
125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
import NDK, { NDKPrivateKeySigner, NDKUser, NDKEvent } from "@nostr-dev-kit/ndk";
|
|
import { NDKCashuWallet } from "@nostr-dev-kit/ndk-wallet";
|
|
import { NDKCashuMintList } from "@nostr-dev-kit/ndk";
|
|
import { getWallet } from "../lib/cache/wallets.js";
|
|
import { z } from "zod";
|
|
import { getUser, saveUser } from "../config.js";
|
|
import { log } from "../lib/utils/log.js";
|
|
import { ndk } from "../ndk.js";
|
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
|
export async function createPubkey({
|
|
username,
|
|
display_name,
|
|
about,
|
|
}: {
|
|
username: string;
|
|
display_name: string;
|
|
about?: string;
|
|
}) {
|
|
try {
|
|
// Check if username already exists
|
|
const existingUser = getUser(username);
|
|
if (existingUser) {
|
|
throw new Error(`Username "${username}" already exists`);
|
|
}
|
|
|
|
// Generate a new keypair for this user
|
|
const signer = NDKPrivateKeySigner.generate();
|
|
|
|
// Create profile metadata event (kind 0)
|
|
const profileContent = JSON.stringify({
|
|
display_name,
|
|
name: display_name,
|
|
about: about || "",
|
|
});
|
|
|
|
// Create the event
|
|
const event = new NDKEvent(ndk, {
|
|
kind: 0,
|
|
content: profileContent,
|
|
tags: [],
|
|
});
|
|
|
|
// Sign with the new signer
|
|
await event.sign(signer);
|
|
|
|
// Publish the event
|
|
await event.publish();
|
|
|
|
|
|
// --- Setup Cashu Wallet (NIP-60/NIP-61) ---
|
|
log(`Setting up Cashu wallet for ${username}...`);
|
|
|
|
try {
|
|
// Use getWallet to retrieve or create a wallet for the new pubkey
|
|
const wallet = await getWallet(signer.pubkey);
|
|
|
|
if (wallet) {
|
|
log(`Cashu wallet setup complete for ${username}.`);
|
|
log(` -> P2PK: ${wallet.p2pk}`);
|
|
log(` -> Mints: ${wallet.mints.join(', ')}`);
|
|
} else {
|
|
throw new Error("Failed to create wallet");
|
|
}
|
|
} catch (walletError) {
|
|
console.error(`Failed to set up Cashu wallet for ${username}:`, walletError);
|
|
// Decide if this should be a fatal error for pubkey creation
|
|
// For now, log the error and continue
|
|
}
|
|
// --- End Cashu Wallet Setup ---
|
|
// Save the user to the config
|
|
saveUser(username, {
|
|
nsec: signer.privateKey,
|
|
display_name,
|
|
about: about || "",
|
|
});
|
|
|
|
// Create user object for return
|
|
const user = ndk.getUser({ pubkey: signer.pubkey });
|
|
|
|
// Return success message
|
|
log(`Created pubkey for ${username} with public key ${signer.pubkey}`);
|
|
|
|
return {
|
|
user,
|
|
message: `Created pubkey for ${username} with npub ${user.npub} and a NIP-60 Cashu wallet for nutzaps`,
|
|
};
|
|
} catch (error: unknown) {
|
|
const errorMessage =
|
|
error instanceof Error ? error.message : String(error);
|
|
throw new Error(`Failed to create pubkey: ${errorMessage}`);
|
|
}
|
|
}
|
|
|
|
export function addCreatePubkeyCommand(server: McpServer) {
|
|
server.tool(
|
|
"create_pubkey",
|
|
"Create a new keypair and save it to config",
|
|
{
|
|
username: z.string().describe("Username to create"),
|
|
display_name: z.string().describe("Display name for the pubkey"),
|
|
about: z
|
|
.string()
|
|
.optional()
|
|
.describe("About information for this pubkey"),
|
|
},
|
|
async ({ username, display_name, about }) => {
|
|
const result = await createPubkey({
|
|
username,
|
|
display_name,
|
|
about,
|
|
});
|
|
|
|
return {
|
|
content: [
|
|
{
|
|
type: "text",
|
|
text: result.message,
|
|
},
|
|
],
|
|
};
|
|
}
|
|
);
|
|
}
|