Skip to content

Commit 73ff94a

Browse files
authored
feat: Update tools to use unified response formatting and error handling (#7)
1 parent 19cd5cf commit 73ff94a

36 files changed

Lines changed: 2145 additions & 1486 deletions

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Log levels: DEBUG, INFO, WARN, ERROR
22
LOG_LEVEL=DEBUG
33

4-
# Your wallet private key (this is a test private key, DO NOT use in production)
4+
# Your wallet private key (this is a test private key, DO NOT use in production, 0x...)
55
PRIVATE_KEY=your_private_key
66

77
# Server configuration (optional, will use default values if not set)

bun.lockb

1 Byte
Binary file not shown.

e2e/basic.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { describe, expect, it } from "bun:test"
2+
3+
import { getClient } from "./util"
4+
5+
describe("Basic Test", async () => {
6+
const client = await getClient()
7+
8+
it("list all mcp tools", async () => {
9+
const toolResult = await client.listTools()
10+
const names = toolResult.tools.map((tool) => tool.name)
11+
console.log("all MCP tools: ", names)
12+
13+
expect(names).toBeArray()
14+
})
15+
})

e2e/evm/blocks.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { describe, expect, it } from "bun:test"
2+
3+
import { getClient, parseText } from "../util"
4+
5+
describe("EVM Blocks Test", async () => {
6+
const client = await getClient()
7+
8+
it("get latest block", async () => {
9+
const res = await client.callTool({
10+
name: "get_latest_block",
11+
arguments: {}
12+
})
13+
const text = res.content?.[0]?.text
14+
const obj = parseText<{
15+
hash: string
16+
}>(text)
17+
expect(obj.hash).toStartWith("0x")
18+
})
19+
20+
it("get block by hash", async () => {
21+
const res = await client.callTool({
22+
name: "get_block_by_hash",
23+
arguments: {
24+
blockHash:
25+
"0x5443cc9cf2820982843ac91095827561f31f595e75932c9f87c6fe610b95243c",
26+
network: "bsc"
27+
}
28+
})
29+
const text = res.content?.[0]?.text
30+
const obj = parseText<{
31+
withdrawalsRoot: string
32+
}>(text)
33+
expect(obj.withdrawalsRoot).toStartWith("0x")
34+
})
35+
})

e2e/evm/contracts.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { describe, expect, it } from "bun:test"
2+
3+
import { getClient, parseText } from "../util"
4+
5+
describe("EVM Contracts Test", async () => {
6+
const client = await getClient()
7+
8+
// WBNB contract on BSC
9+
const WBNB_ADDRESS = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"
10+
11+
it("check if address is contract", async () => {
12+
const res = await client.callTool({
13+
name: "is_contract",
14+
arguments: {
15+
address: WBNB_ADDRESS,
16+
network: "bsc"
17+
}
18+
})
19+
const text = res.content?.[0]?.text
20+
const obj = parseText<{
21+
isContract: boolean
22+
}>(text)
23+
expect(obj.isContract).toBe(true)
24+
})
25+
26+
it("read contract name", async () => {
27+
const res = await client.callTool({
28+
name: "read_contract",
29+
arguments: {
30+
contractAddress: WBNB_ADDRESS,
31+
abi: [
32+
{
33+
constant: true,
34+
inputs: [],
35+
name: "name",
36+
outputs: [{ name: "", type: "string" }],
37+
payable: false,
38+
stateMutability: "view",
39+
type: "function"
40+
}
41+
],
42+
functionName: "name",
43+
network: "bsc"
44+
}
45+
})
46+
const text = res.content?.[0]?.text
47+
const obj = parseText<string>(text)
48+
expect(obj).toBe("Wrapped BNB")
49+
})
50+
51+
it("read contract totalSupply", async () => {
52+
const res = await client.callTool({
53+
name: "read_contract",
54+
arguments: {
55+
contractAddress: WBNB_ADDRESS,
56+
abi: [
57+
{
58+
constant: true,
59+
inputs: [],
60+
name: "totalSupply",
61+
outputs: [{ name: "", type: "uint256" }],
62+
payable: false,
63+
stateMutability: "view",
64+
type: "function"
65+
}
66+
],
67+
functionName: "totalSupply",
68+
network: "bsc"
69+
}
70+
})
71+
const text = res.content?.[0]?.text
72+
const totalSupply = parseText<bigint>(text)
73+
expect(BigInt(totalSupply)).toBeTypeOf("bigint")
74+
})
75+
})

e2e/evm/ens.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, expect, it } from "bun:test"
2+
3+
import { getClient, parseText } from "../util"
4+
5+
describe("EVM ENS Test", async () => {
6+
const client = await getClient()
7+
8+
it("resolve ETH ENS name", async () => {
9+
const res = await client.callTool({
10+
name: "resolve_ens",
11+
arguments: {
12+
ensName: "vitalik.eth",
13+
network: "eth" // only for eth mainnet
14+
}
15+
})
16+
const text = res.content?.[0]?.text
17+
const obj = parseText<{
18+
resolvedAddress: string
19+
}>(text)
20+
expect(obj.resolvedAddress).toStartWith("0x")
21+
})
22+
})

e2e/evm/network.test.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { describe, expect, it } from "bun:test"
2+
3+
import { getClient, parseText } from "../util"
4+
5+
describe("EVM Network Test", async () => {
6+
const client = await getClient()
7+
8+
it("get chain info for BSC", async () => {
9+
const res = await client.callTool({
10+
name: "get_chain_info",
11+
arguments: {
12+
network: "bsc"
13+
}
14+
})
15+
const text = res.content?.[0]?.text
16+
const obj = parseText<{
17+
chainId: number
18+
}>(text)
19+
expect(obj.chainId).toBe(56) // BSC mainnet chain ID
20+
})
21+
22+
it("get chain info for BSC testnet", async () => {
23+
const res = await client.callTool({
24+
name: "get_chain_info",
25+
arguments: {
26+
network: "bsc-testnet"
27+
}
28+
})
29+
const text = res.content?.[0]?.text
30+
const obj = parseText<{
31+
chainId: number
32+
}>(text)
33+
expect(obj.chainId).toBe(97) // BSC testnet chain ID
34+
})
35+
36+
it("get chain info for opBNB", async () => {
37+
const res = await client.callTool({
38+
name: "get_chain_info",
39+
arguments: {
40+
network: "opbnb"
41+
}
42+
})
43+
const text = res.content?.[0]?.text
44+
const obj = parseText<{
45+
chainId: number
46+
}>(text)
47+
expect(obj.chainId).toBe(204) // opBNB mainnet chain ID
48+
})
49+
50+
it("get chain info for opBNB testnet", async () => {
51+
const res = await client.callTool({
52+
name: "get_chain_info",
53+
arguments: {
54+
network: "opbnb-testnet"
55+
}
56+
})
57+
const text = res.content?.[0]?.text
58+
const obj = parseText<{
59+
chainId: number
60+
}>(text)
61+
expect(obj.chainId).toBe(5611) // opBNB testnet chain ID
62+
})
63+
64+
it("get supported networks", async () => {
65+
const res = await client.callTool({
66+
name: "get_supported_networks",
67+
arguments: {
68+
random_string: "dummy"
69+
}
70+
})
71+
const text = res.content?.[0]?.text
72+
const obj = parseText<{
73+
supportedNetworks: string[]
74+
}>(text)
75+
expect(obj.supportedNetworks).toContain("bsc")
76+
expect(obj.supportedNetworks).toContain("bsc-testnet")
77+
expect(obj.supportedNetworks).toContain("opbnb")
78+
expect(obj.supportedNetworks).toContain("opbnb-testnet")
79+
})
80+
})

e2e/evm/nft.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { describe, expect, it } from "bun:test"
2+
3+
import { getClient, parseText } from "../util"
4+
5+
describe("EVM NFT Test", async () => {
6+
const client = await getClient()
7+
8+
// Binance Account Bound Token (BABT) on BSC
9+
const NFT_ADDRESS = "0x2b09d47d550061f995a3b5c6f0fd58005215d7c8"
10+
const TOKEN_ID = "1"
11+
12+
// erc1155 on BSC
13+
const ERC1155_ADDRESS = "0x06f352C604D36b703E04671827493c43F598dC1e"
14+
const ERC1155_TOKEN_ID = "1"
15+
16+
describe("ERC721 Tests", () => {
17+
it("get NFT info", async () => {
18+
const res = await client.callTool({
19+
name: "get_nft_info",
20+
arguments: {
21+
tokenAddress: NFT_ADDRESS,
22+
tokenId: TOKEN_ID,
23+
network: "bsc"
24+
}
25+
})
26+
const text = res.content?.[0]?.text
27+
const obj = parseText<{
28+
symbol: string
29+
}>(text)
30+
expect(obj.symbol).toEqual("BABT")
31+
})
32+
})
33+
34+
describe("ERC1155 Tests", () => {
35+
it("get ERC1155 token URI", async () => {
36+
const res = await client.callTool({
37+
name: "get_erc1155_token_uri",
38+
arguments: {
39+
tokenAddress: ERC1155_ADDRESS,
40+
tokenId: ERC1155_TOKEN_ID,
41+
network: "bsc"
42+
}
43+
})
44+
const text = res.content?.[0]?.text
45+
const obj = parseText<{
46+
tokenURI: string
47+
}>(text)
48+
expect(obj.tokenURI).toContain("://")
49+
})
50+
})
51+
})

e2e/evm/tokens.test.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { describe, expect, it } from "bun:test"
2+
3+
import { getClient, parseText } from "../util"
4+
5+
describe("EVM Tokens Test", async () => {
6+
const client = await getClient()
7+
8+
// BUSD contract on BSC
9+
const BUSD_ADDRESS = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"
10+
// Binance Hot Wallet
11+
const BINANCE_HOT_WALLET = "0x8894E0a0c962CB723c1976a4421c95949bE2D4E3"
12+
13+
it("get ERC20 token info", async () => {
14+
const res = await client.callTool({
15+
name: "get_erc20_token_info",
16+
arguments: {
17+
tokenAddress: BUSD_ADDRESS,
18+
network: "bsc"
19+
}
20+
})
21+
const text = res.content?.[0]?.text
22+
const obj = parseText<{
23+
name: string
24+
}>(text)
25+
expect(obj.name).toBe("BUSD Token")
26+
})
27+
28+
it("get native token balance", async () => {
29+
const res = await client.callTool({
30+
name: "get_native_balance",
31+
arguments: {
32+
address: BINANCE_HOT_WALLET,
33+
network: "bsc"
34+
}
35+
})
36+
const text = res.content?.[0]?.text
37+
const obj = parseText<{
38+
raw: string
39+
}>(text)
40+
expect(BigInt(obj.raw)).toBeTypeOf("bigint")
41+
})
42+
43+
it("get ERC20 token balance", async () => {
44+
const res = await client.callTool({
45+
name: "get_erc20_balance",
46+
arguments: {
47+
tokenAddress: BUSD_ADDRESS,
48+
address: BINANCE_HOT_WALLET,
49+
network: "bsc"
50+
}
51+
})
52+
const text = res.content?.[0]?.text
53+
const obj = parseText<{
54+
raw: string
55+
}>(text)
56+
expect(BigInt(obj.raw)).toBeTypeOf("bigint")
57+
})
58+
59+
// it("create ERC20 token", async () => {
60+
// const res = await client.callTool({
61+
// name: "create_erc20_token",
62+
// arguments: {
63+
// name: "Test USDT Token",
64+
// symbol: "vUSDT",
65+
// network: "bsc-testnet",
66+
// privateKey: process.env.PRIVATE_KEY as string,
67+
// totalSupply: "1000000000" // 1 billion
68+
// }
69+
// })
70+
// const text = res.content?.[0]?.text
71+
// const obj = parseText<{
72+
// hash: string
73+
// }>(text)
74+
// expect(obj.hash).toStartWith("0x")
75+
// })
76+
})

0 commit comments

Comments
 (0)