@proofofprotocol/inscribe-mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +255 -0
- package/package.json +58 -0
- package/src/cli/commands/balance.js +151 -0
- package/src/cli/commands/config.js +87 -0
- package/src/cli/commands/init.js +186 -0
- package/src/cli/commands/log.js +193 -0
- package/src/cli/commands/show.js +249 -0
- package/src/cli/index.js +44 -0
- package/src/cli/lib/config.js +126 -0
- package/src/cli/lib/exit-codes.js +19 -0
- package/src/lib/did.js +64 -0
- package/src/lib/hedera.js +221 -0
- package/src/lib/logger.js +200 -0
- package/src/server-sse.js +239 -0
- package/src/server.js +102 -0
- package/src/test.js +107 -0
- package/src/tools/layer1/history.js +174 -0
- package/src/tools/layer1/identity.js +120 -0
- package/src/tools/layer1/inscribe.js +132 -0
- package/src/tools/layer1/inscribe_url.js +193 -0
- package/src/tools/layer1/verify.js +177 -0
- package/src/tools/layer2/account.js +155 -0
- package/src/tools/layer2/hcs.js +163 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 2: Account Operations
|
|
3
|
+
*
|
|
4
|
+
* Advanced tools for direct account manipulation.
|
|
5
|
+
* Usually not needed - use Layer 1 tools instead.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Hbar, TransferTransaction } from '@hashgraph/sdk';
|
|
9
|
+
import { getHederaClient, getOperatorId, getMirrorNodeUrl } from '../../lib/hedera.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get HBAR Balance
|
|
13
|
+
*/
|
|
14
|
+
export const getBalanceTool = {
|
|
15
|
+
name: 'account_get_balance',
|
|
16
|
+
description: '[Advanced] HBAR 残高を確認する',
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
account_id: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'アカウントID(省略時は運営アカウント)'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
handler: async ({ account_id }) => {
|
|
28
|
+
const targetId = account_id || process.env.HEDERA_OPERATOR_ID;
|
|
29
|
+
const mirrorUrl = getMirrorNodeUrl();
|
|
30
|
+
|
|
31
|
+
const response = await fetch(`${mirrorUrl}/api/v1/accounts/${targetId}`);
|
|
32
|
+
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
return {
|
|
35
|
+
success: false,
|
|
36
|
+
error: `アカウント ${targetId} が見つかりません`,
|
|
37
|
+
account_id: targetId
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const data = await response.json();
|
|
42
|
+
const balanceTinybars = data.balance?.balance || 0;
|
|
43
|
+
const balanceHbar = balanceTinybars / 100_000_000;
|
|
44
|
+
|
|
45
|
+
const network = process.env.HEDERA_NETWORK || 'testnet';
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
account_id: targetId,
|
|
50
|
+
balance_hbar: balanceHbar.toFixed(8),
|
|
51
|
+
balance_tinybars: balanceTinybars,
|
|
52
|
+
hashscan_url: `https://hashscan.io/${network}/account/${targetId}`
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Send HBAR
|
|
59
|
+
*/
|
|
60
|
+
export const sendHbarTool = {
|
|
61
|
+
name: 'account_send_hbar',
|
|
62
|
+
description: '[Advanced] HBAR を送金する',
|
|
63
|
+
inputSchema: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
to_account_id: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: '送金先アカウントID'
|
|
69
|
+
},
|
|
70
|
+
amount: {
|
|
71
|
+
type: 'number',
|
|
72
|
+
description: '送金額(HBAR)'
|
|
73
|
+
},
|
|
74
|
+
memo: {
|
|
75
|
+
type: 'string',
|
|
76
|
+
description: 'トランザクションメモ(オプション)'
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
required: ['to_account_id', 'amount']
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
handler: async ({ to_account_id, amount, memo }) => {
|
|
83
|
+
const client = getHederaClient();
|
|
84
|
+
const operatorId = getOperatorId();
|
|
85
|
+
|
|
86
|
+
const tx = new TransferTransaction()
|
|
87
|
+
.addHbarTransfer(operatorId, new Hbar(-amount))
|
|
88
|
+
.addHbarTransfer(to_account_id, new Hbar(amount));
|
|
89
|
+
|
|
90
|
+
if (memo) {
|
|
91
|
+
tx.setTransactionMemo(memo);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const response = await tx.execute(client);
|
|
95
|
+
const receipt = await response.getReceipt(client);
|
|
96
|
+
|
|
97
|
+
const network = process.env.HEDERA_NETWORK || 'testnet';
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
from: operatorId.toString(),
|
|
102
|
+
to: to_account_id,
|
|
103
|
+
amount_hbar: amount,
|
|
104
|
+
transaction_id: response.transactionId.toString(),
|
|
105
|
+
status: receipt.status.toString(),
|
|
106
|
+
hashscan_url: `https://hashscan.io/${network}/transaction/${response.transactionId.toString()}`
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get Account Info
|
|
113
|
+
*/
|
|
114
|
+
export const getAccountInfoTool = {
|
|
115
|
+
name: 'account_get_info',
|
|
116
|
+
description: '[Advanced] アカウント情報を取得する',
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {
|
|
120
|
+
account_id: {
|
|
121
|
+
type: 'string',
|
|
122
|
+
description: 'アカウントID'
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
required: ['account_id']
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
handler: async ({ account_id }) => {
|
|
129
|
+
const mirrorUrl = getMirrorNodeUrl();
|
|
130
|
+
|
|
131
|
+
const response = await fetch(`${mirrorUrl}/api/v1/accounts/${account_id}`);
|
|
132
|
+
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
return {
|
|
135
|
+
success: false,
|
|
136
|
+
error: `アカウント ${account_id} が見つかりません`,
|
|
137
|
+
account_id
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const data = await response.json();
|
|
142
|
+
const network = process.env.HEDERA_NETWORK || 'testnet';
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
success: true,
|
|
146
|
+
account_id,
|
|
147
|
+
evm_address: data.evm_address,
|
|
148
|
+
key: data.key,
|
|
149
|
+
balance_hbar: (data.balance?.balance || 0) / 100_000_000,
|
|
150
|
+
created_timestamp: data.created_timestamp,
|
|
151
|
+
memo: data.memo,
|
|
152
|
+
hashscan_url: `https://hashscan.io/${network}/account/${account_id}`
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 2: HCS Direct Operations
|
|
3
|
+
*
|
|
4
|
+
* Advanced tools for direct HCS manipulation.
|
|
5
|
+
* Usually not needed - use Layer 1 tools instead.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { TopicCreateTransaction, TopicMessageSubmitTransaction, TopicId } from '@hashgraph/sdk';
|
|
9
|
+
import { getHederaClient, getMirrorNodeUrl } from '../../lib/hedera.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create HCS Topic
|
|
13
|
+
*/
|
|
14
|
+
export const createTopicTool = {
|
|
15
|
+
name: 'hcs_create_topic',
|
|
16
|
+
description: '[Advanced] HCS トピックを直接作成する',
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
memo: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'トピックのメモ(説明)'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
handler: async ({ memo }) => {
|
|
28
|
+
const client = getHederaClient();
|
|
29
|
+
|
|
30
|
+
const tx = new TopicCreateTransaction();
|
|
31
|
+
if (memo) {
|
|
32
|
+
tx.setTopicMemo(memo);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const response = await tx.execute(client);
|
|
36
|
+
const receipt = await response.getReceipt(client);
|
|
37
|
+
|
|
38
|
+
const network = process.env.HEDERA_NETWORK || 'testnet';
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
topic_id: receipt.topicId.toString(),
|
|
43
|
+
memo: memo || null,
|
|
44
|
+
hashscan_url: `https://hashscan.io/${network}/topic/${receipt.topicId.toString()}`
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Submit HCS Message
|
|
51
|
+
*/
|
|
52
|
+
export const submitMessageTool = {
|
|
53
|
+
name: 'hcs_submit_message',
|
|
54
|
+
description: '[Advanced] HCS にメッセージを直接送信する',
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
topic_id: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description: 'トピックID (例: 0.0.7503789)'
|
|
61
|
+
},
|
|
62
|
+
message: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'メッセージ内容'
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
required: ['topic_id', 'message']
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
handler: async ({ topic_id, message }) => {
|
|
71
|
+
const client = getHederaClient();
|
|
72
|
+
|
|
73
|
+
const tx = new TopicMessageSubmitTransaction()
|
|
74
|
+
.setTopicId(TopicId.fromString(topic_id))
|
|
75
|
+
.setMessage(message);
|
|
76
|
+
|
|
77
|
+
const response = await tx.execute(client);
|
|
78
|
+
const record = await response.getRecord(client);
|
|
79
|
+
|
|
80
|
+
const network = process.env.HEDERA_NETWORK || 'testnet';
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
topic_id,
|
|
85
|
+
timestamp: record.consensusTimestamp.toString(),
|
|
86
|
+
message_preview: message.substring(0, 100) + (message.length > 100 ? '...' : ''),
|
|
87
|
+
hashscan_url: `https://hashscan.io/${network}/transaction/${response.transactionId.toString()}`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get HCS Messages
|
|
94
|
+
*/
|
|
95
|
+
export const getMessagesTool = {
|
|
96
|
+
name: 'hcs_get_messages',
|
|
97
|
+
description: '[Advanced] HCS メッセージを取得する',
|
|
98
|
+
inputSchema: {
|
|
99
|
+
type: 'object',
|
|
100
|
+
properties: {
|
|
101
|
+
topic_id: {
|
|
102
|
+
type: 'string',
|
|
103
|
+
description: 'トピックID'
|
|
104
|
+
},
|
|
105
|
+
limit: {
|
|
106
|
+
type: 'number',
|
|
107
|
+
description: '取得件数(デフォルト: 10)',
|
|
108
|
+
default: 10
|
|
109
|
+
},
|
|
110
|
+
order: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
description: '並び順(asc / desc)',
|
|
113
|
+
default: 'desc'
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
required: ['topic_id']
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
handler: async ({ topic_id, limit = 10, order = 'desc' }) => {
|
|
120
|
+
const mirrorUrl = getMirrorNodeUrl();
|
|
121
|
+
const apiUrl = `${mirrorUrl}/api/v1/topics/${topic_id}/messages?limit=${limit}&order=${order}`;
|
|
122
|
+
|
|
123
|
+
const response = await fetch(apiUrl);
|
|
124
|
+
if (!response.ok) {
|
|
125
|
+
return {
|
|
126
|
+
success: false,
|
|
127
|
+
error: `トピック ${topic_id} が見つかりません`,
|
|
128
|
+
topic_id,
|
|
129
|
+
messages: []
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const data = await response.json();
|
|
134
|
+
|
|
135
|
+
const messages = (data.messages || []).map(m => {
|
|
136
|
+
let content;
|
|
137
|
+
try {
|
|
138
|
+
content = Buffer.from(m.message, 'base64').toString('utf-8');
|
|
139
|
+
// Try to parse as JSON
|
|
140
|
+
const parsed = JSON.parse(content);
|
|
141
|
+
content = parsed;
|
|
142
|
+
} catch {
|
|
143
|
+
// Keep as string if not JSON
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
timestamp: m.consensus_timestamp,
|
|
148
|
+
sequence_number: m.sequence_number,
|
|
149
|
+
content
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const network = process.env.HEDERA_NETWORK || 'testnet';
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
success: true,
|
|
157
|
+
topic_id,
|
|
158
|
+
count: messages.length,
|
|
159
|
+
messages,
|
|
160
|
+
hashscan_url: `https://hashscan.io/${network}/topic/${topic_id}`
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
};
|