Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions typescript/agentkit/src/action-providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export * from "./erc721";
export * from "./farcaster";
export * from "./jupiter";
export * from "./messari";
export * from "./mintclub";
export * from "./pyth";
export * from "./moonwell";
export * from "./morpho";
Expand Down
42 changes: 42 additions & 0 deletions typescript/agentkit/src/action-providers/mintclub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Mint Club V2 Action Provider

This directory contains the **MintclubActionProvider** implementation, which provides actions to interact with the **Mint Club V2 protocol** on Base mainnet.

## Directory Structure

```
mintclub/
├── mintclubActionProvider.ts # Main provider with Mint Club V2 functionality
├── mintclubActionProvider.test.ts # Test file for Mint Club provider
├── constants.ts # Mint Club contract constants and ABIs
├── schemas.ts # Mint Club action schemas
├── utils.ts # Mint Club utility functions
├── index.ts # Main exports
└── README.md # This file
```

## Actions

- `get_token_info`: Get detailed information about a Mint Club token including bonding curve details
- `get_token_price`: Get the current price of a Mint Club token in reserve tokens and USD
- `buy_token`: Buy Mint Club tokens via the bonding curve mechanism
- `sell_token`: Sell Mint Club tokens via the bonding curve mechanism
- `create_token`: Create a new Mint Club token with bonding curve

## Adding New Actions

To add new Mint Club actions:

1. Define your action schema in `schemas.ts`
2. Implement the action in `mintclubActionProvider.ts`
3. Add tests in `mintclubActionProvider.test.ts`

## Network Support

The Mint Club provider supports Base mainnet only.

## Notes

Mint Club V2 is a bonding curve token protocol that allows anyone to create tokens backed by reserve assets. The protocol uses mathematical curves to determine token prices based on supply and demand.

For more information on the **Mint Club V2 protocol**, visit [Mint Club Documentation](https://mint.club/).
252 changes: 252 additions & 0 deletions typescript/agentkit/src/action-providers/mintclub/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
import type { Abi } from "abitype";

export const SUPPORTED_NETWORKS = ["base-mainnet"];

/**
* MCV2 Bond contract ABI - minimal functions needed for Mint Club V2 interactions.
*/
export const MCV2_BOND_ABI: Abi = [
{
type: "function",
name: "tokenBond",
inputs: [{ name: "token", type: "address", internalType: "address" }],
outputs: [
{ name: "creator", type: "address", internalType: "address" },
{ name: "mintRoyalty", type: "uint16", internalType: "uint16" },
{ name: "burnRoyalty", type: "uint16", internalType: "uint16" },
{ name: "createdAt", type: "uint40", internalType: "uint40" },
{ name: "reserveToken", type: "address", internalType: "address" },
{ name: "reserveBalance", type: "uint256", internalType: "uint256" },
],
stateMutability: "view",
},
{
type: "function",
name: "getReserveForToken",
inputs: [
{ name: "token", type: "address", internalType: "address" },
{ name: "tokensToMint", type: "uint256", internalType: "uint256" },
],
outputs: [
{ name: "reserveAmount", type: "uint256", internalType: "uint256" },
{ name: "royalty", type: "uint256", internalType: "uint256" },
],
stateMutability: "view",
},
{
type: "function",
name: "getRefundForTokens",
inputs: [
{ name: "token", type: "address", internalType: "address" },
{ name: "tokensToBurn", type: "uint256", internalType: "uint256" },
],
outputs: [
{ name: "refundAmount", type: "uint256", internalType: "uint256" },
{ name: "royalty", type: "uint256", internalType: "uint256" },
],
stateMutability: "view",
},
{
type: "function",
name: "mint",
inputs: [
{ name: "token", type: "address", internalType: "address" },
{ name: "tokensToMint", type: "uint256", internalType: "uint256" },
{ name: "maxReserveAmount", type: "uint256", internalType: "uint256" },
{ name: "receiver", type: "address", internalType: "address" },
],
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
stateMutability: "nonpayable",
},
{
type: "function",
name: "burn",
inputs: [
{ name: "token", type: "address", internalType: "address" },
{ name: "tokensToBurn", type: "uint256", internalType: "uint256" },
{ name: "minRefund", type: "uint256", internalType: "uint256" },
{ name: "receiver", type: "address", internalType: "address" },
],
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
stateMutability: "nonpayable",
},
{
type: "function",
name: "createToken",
inputs: [
{
name: "tp",
type: "tuple",
internalType: "struct MCV2_Bond.TokenParams",
components: [
{ name: "name", type: "string", internalType: "string" },
{ name: "symbol", type: "string", internalType: "string" },
],
},
{
name: "bp",
type: "tuple",
internalType: "struct MCV2_Bond.BondParams",
components: [
{ name: "mintRoyalty", type: "uint16", internalType: "uint16" },
{ name: "burnRoyalty", type: "uint16", internalType: "uint16" },
{ name: "reserveToken", type: "address", internalType: "address" },
{ name: "maxSupply", type: "uint128", internalType: "uint128" },
{ name: "stepRanges", type: "uint128[]", internalType: "uint128[]" },
{ name: "stepPrices", type: "uint128[]", internalType: "uint128[]" },
],
},
],
outputs: [{ name: "token", type: "address", internalType: "address" }],
stateMutability: "payable",
},
{
type: "function",
name: "creationFee",
inputs: [],
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
stateMutability: "view",
},
] as const;

/**
* ERC20 token ABI - standard functions needed for token interactions.
*/
export const ERC20_ABI: Abi = [
{
type: "function",
name: "symbol",
inputs: [],
outputs: [{ name: "", type: "string", internalType: "string" }],
stateMutability: "view",
},
{
type: "function",
name: "decimals",
inputs: [],
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
stateMutability: "view",
},
{
type: "function",
name: "totalSupply",
inputs: [],
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
stateMutability: "view",
},
{
type: "function",
name: "balanceOf",
inputs: [{ name: "account", type: "address", internalType: "address" }],
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
stateMutability: "view",
},
{
type: "function",
name: "approve",
inputs: [
{ name: "spender", type: "address", internalType: "address" },
{ name: "amount", type: "uint256", internalType: "uint256" },
],
outputs: [{ name: "", type: "bool", internalType: "bool" }],
stateMutability: "nonpayable",
},
{
type: "function",
name: "allowance",
inputs: [
{ name: "owner", type: "address", internalType: "address" },
{ name: "spender", type: "address", internalType: "address" },
],
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
stateMutability: "view",
},
] as const;

/**
* 1inch Spot Price Aggregator ABI for USD pricing.
*/
export const SPOT_PRICE_AGGREGATOR_ABI: Abi = [
{
type: "function",
name: "getRate",
inputs: [
{ name: "srcToken", type: "address", internalType: "contract IERC20" },
{ name: "dstToken", type: "address", internalType: "contract IERC20" },
{ name: "useWrappers", type: "bool", internalType: "bool" },
],
outputs: [{ name: "weightedRate", type: "uint256", internalType: "uint256" }],
stateMutability: "view",
},
] as const;

/**
* Contract addresses on Base mainnet.
*/
export const MINTCLUB_CONTRACT_ADDRESSES = {
"base-mainnet": {
MCV2_Bond: "0xc5a076cad94176c2996B32d8466Be1cE757FAa27",
SpotPriceAggregator: "0x00000000000D6FFc74A8feb35aF5827bf57f6786",
USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
},
} as const;

/**
* Gets the MCV2 Bond contract address for the specified network.
*
* @param network - The network ID to get the contract address for.
* @returns The contract address for the specified network.
* @throws Error if the specified network is not supported.
*/
export function getBondAddress(network: string): string {
const addresses =
MINTCLUB_CONTRACT_ADDRESSES[
network.toLowerCase() as keyof typeof MINTCLUB_CONTRACT_ADDRESSES
];
if (!addresses) {
throw new Error(
`Unsupported network: ${network}. Supported: ${Object.keys(MINTCLUB_CONTRACT_ADDRESSES).join(", ")}`,
);
}
return addresses.MCV2_Bond;
}

/**
* Gets the Spot Price Aggregator contract address for the specified network.
*
* @param network - The network ID to get the contract address for.
* @returns The contract address for the specified network.
* @throws Error if the specified network is not supported.
*/
export function getSpotPriceAggregatorAddress(network: string): string {
const addresses =
MINTCLUB_CONTRACT_ADDRESSES[
network.toLowerCase() as keyof typeof MINTCLUB_CONTRACT_ADDRESSES
];
if (!addresses) {
throw new Error(
`Unsupported network: ${network}. Supported: ${Object.keys(MINTCLUB_CONTRACT_ADDRESSES).join(", ")}`,
);
}
return addresses.SpotPriceAggregator;
}

/**
* Gets the USDC contract address for the specified network.
*
* @param network - The network ID to get the contract address for.
* @returns The contract address for the specified network.
* @throws Error if the specified network is not supported.
*/
export function getUsdcAddress(network: string): string {
const addresses =
MINTCLUB_CONTRACT_ADDRESSES[
network.toLowerCase() as keyof typeof MINTCLUB_CONTRACT_ADDRESSES
];
if (!addresses) {
throw new Error(
`Unsupported network: ${network}. Supported: ${Object.keys(MINTCLUB_CONTRACT_ADDRESSES).join(", ")}`,
);
}
return addresses.USDC;
}
2 changes: 2 additions & 0 deletions typescript/agentkit/src/action-providers/mintclub/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./schemas";
export * from "./mintclubActionProvider";
Loading