@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 POP@AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# inscribe-mcp
|
|
2
|
+
|
|
3
|
+
> Verifiable inscription for AI agents - inscribe anything to blockchain
|
|
4
|
+
|
|
5
|
+
「刻む」という行為を、ブロックチェーンを意識せずに。
|
|
6
|
+
|
|
7
|
+
## What is inscribe?
|
|
8
|
+
|
|
9
|
+
**inscribe** = 残す・刻む・あとから消せない形で書く
|
|
10
|
+
|
|
11
|
+
- SNS投稿を刻む(削除される前に)
|
|
12
|
+
- ニュース記事をアーカイブ
|
|
13
|
+
- 予言・予測を証明
|
|
14
|
+
- AIの判断を記録
|
|
15
|
+
- 契約書にタイムスタンプ
|
|
16
|
+
|
|
17
|
+
すべて、**あとから検証できる**。改ざん不可能。
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### 1. インストール
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# npx で直接実行(推奨)
|
|
25
|
+
npx @proofofprotocol/inscribe-mcp init
|
|
26
|
+
|
|
27
|
+
# または npm でグローバルインストール
|
|
28
|
+
npm install -g @proofofprotocol/inscribe-mcp
|
|
29
|
+
inscribe-mcp init
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. 初期設定
|
|
33
|
+
|
|
34
|
+
`inscribe-mcp init` を実行すると対話形式で設定できます:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
? Select network: testnet
|
|
38
|
+
? Enter your Hedera Account ID: 0.0.XXXXXX
|
|
39
|
+
? Enter your Hedera Private Key: 302e...
|
|
40
|
+
|
|
41
|
+
Config saved to ~/.inscribe-mcp/config.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Hedera Testnet アカウントは [portal.hedera.com](https://portal.hedera.com) で無料作成。
|
|
45
|
+
|
|
46
|
+
### 3. Claude Desktop に接続
|
|
47
|
+
|
|
48
|
+
`claude_desktop_config.json`:
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"inscribe": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["@proofofprotocol/inscribe-mcp-server"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
設定は `~/.inscribe-mcp/config.json` から自動的に読み込まれます。
|
|
61
|
+
|
|
62
|
+
### 4. 使う
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
User: このツイートを刻んで
|
|
66
|
+
https://x.com/elonmusk/status/xxx
|
|
67
|
+
|
|
68
|
+
Claude: inscribe_url を使います
|
|
69
|
+
→ 投稿内容を自動取得: "Going to Mars in 2025"
|
|
70
|
+
→ inscription_id: "0.0.7503789-1703412000.123456789"
|
|
71
|
+
→ この投稿が存在した証拠を刻みました!
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Layer 1 API(推奨)
|
|
75
|
+
|
|
76
|
+
| ツール | 説明 |
|
|
77
|
+
|--------|------|
|
|
78
|
+
| `inscribe_url` | **URLを刻む**(SNS、記事、動画など)|
|
|
79
|
+
| `inscribe` | テキストを刻む |
|
|
80
|
+
| `verify` | 刻んだ内容を検証 |
|
|
81
|
+
| `history` | 履歴を取得 |
|
|
82
|
+
| `identity` | 信頼IDを作成(DID) |
|
|
83
|
+
|
|
84
|
+
### inscribe_url - キラーフィーチャー
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
// 自動取得
|
|
88
|
+
inscribe_url({ url: "https://x.com/user/status/xxx" })
|
|
89
|
+
|
|
90
|
+
// 目撃証言(自動取得できない場合)
|
|
91
|
+
inscribe_url({
|
|
92
|
+
url: "https://example.com/page",
|
|
93
|
+
content: "このページに〇〇と書いてあった",
|
|
94
|
+
note: "スクショも撮った"
|
|
95
|
+
})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**対応プラットフォーム:**
|
|
99
|
+
- ✅ X/Twitter (oEmbed)
|
|
100
|
+
- ✅ YouTube (oEmbed)
|
|
101
|
+
- 📝 その他(手動で content 指定)
|
|
102
|
+
|
|
103
|
+
### inscribe - テキストを刻む
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
inscribe({
|
|
107
|
+
content: "2025年にビットコインは10万ドルを超える",
|
|
108
|
+
type: "prediction",
|
|
109
|
+
author: "did:hedera:testnet:0.0.1234567"
|
|
110
|
+
})
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### verify - 検証
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
verify({
|
|
117
|
+
inscription_id: "0.0.7503789-1703412000.123456789",
|
|
118
|
+
content: "検証したい元テキスト" // オプション
|
|
119
|
+
})
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Layer 2 API(開発者向け)
|
|
123
|
+
|
|
124
|
+
通常は不要。デバッグや直接操作が必要な場合のみ。
|
|
125
|
+
|
|
126
|
+
| ツール | 説明 |
|
|
127
|
+
|--------|------|
|
|
128
|
+
| `hcs_create_topic` | HCS トピック作成 |
|
|
129
|
+
| `hcs_submit_message` | HCS メッセージ送信 |
|
|
130
|
+
| `hcs_get_messages` | HCS メッセージ取得 |
|
|
131
|
+
| `account_get_balance` | HBAR 残高確認 |
|
|
132
|
+
| `account_send_hbar` | HBAR 送金 |
|
|
133
|
+
| `account_get_info` | アカウント情報取得 |
|
|
134
|
+
|
|
135
|
+
## Philosophy
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
┌─────────────────────────────────────────────┐
|
|
139
|
+
│ あなたが呼ぶもの │
|
|
140
|
+
│ inscribe / verify / history / identity │
|
|
141
|
+
├─────────────────────────────────────────────┤
|
|
142
|
+
│ 内部で起きていること(見えない) │
|
|
143
|
+
│ Hedera Consensus Service │
|
|
144
|
+
│ Cryptographic Hashing │
|
|
145
|
+
│ DID / Decentralized Identity │
|
|
146
|
+
└─────────────────────────────────────────────┘
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**ブロックチェーンは手段。信頼が目的。**
|
|
150
|
+
|
|
151
|
+
## Use Cases
|
|
152
|
+
|
|
153
|
+
### SNS投稿の証拠保全
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
User: イーロン・マスクのこのツイートを刻んで
|
|
157
|
+
https://x.com/elonmusk/status/xxx
|
|
158
|
+
|
|
159
|
+
→ 後で削除されても「この時点で存在した」証明になる
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 予言・予測の証明
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
User: 「2025年末にHBARは$1を超える」と刻んで
|
|
166
|
+
|
|
167
|
+
→ 後から「俺は言ってた」と証明できる
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### AI判断の記録
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
User: この分析結果を刻んで
|
|
174
|
+
{"analysis": "...", "confidence": 0.95}
|
|
175
|
+
|
|
176
|
+
→ AIの判断過程を検証可能な形で記録
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## CLI Commands
|
|
180
|
+
|
|
181
|
+
観測・設定用のCLIツールを提供します(Read-Only、トランザクションは送信しません)。
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# 初期設定
|
|
185
|
+
inscribe-mcp init
|
|
186
|
+
|
|
187
|
+
# 設定確認
|
|
188
|
+
inscribe-mcp config
|
|
189
|
+
|
|
190
|
+
# 残高確認
|
|
191
|
+
inscribe-mcp balance
|
|
192
|
+
|
|
193
|
+
# ダッシュボード表示
|
|
194
|
+
inscribe-mcp show
|
|
195
|
+
|
|
196
|
+
# ログ表示
|
|
197
|
+
inscribe-mcp log # 最新10件
|
|
198
|
+
inscribe-mcp log --tail 20 # 最新20件
|
|
199
|
+
inscribe-mcp log --since 1h # 過去1時間
|
|
200
|
+
inscribe-mcp log --error # エラーのみ
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### ダッシュボード例
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
inscribe-mcp status (network: testnet)
|
|
207
|
+
════════════════════════════════════════════════════════════
|
|
208
|
+
Operator: 0.0.7455134
|
|
209
|
+
Balance: 985.63 HBAR
|
|
210
|
+
Topic: 0.0.7503789
|
|
211
|
+
|
|
212
|
+
MCP Activity (total)
|
|
213
|
+
────────────────────────────────────────────────────────────
|
|
214
|
+
Inscribe calls: 3 (success 2 / fail 1)
|
|
215
|
+
Verify calls: 1 (success 1 / fail 0)
|
|
216
|
+
History calls: 0 (success 0 / fail 0)
|
|
217
|
+
Avg latency: 1460 ms
|
|
218
|
+
|
|
219
|
+
Timeline
|
|
220
|
+
────────────────────────────────────────────────────────────
|
|
221
|
+
Last inscribe: 1m ago
|
|
222
|
+
Last verify: 8m ago
|
|
223
|
+
Last error: none
|
|
224
|
+
|
|
225
|
+
Links
|
|
226
|
+
────────────────────────────────────────────────────────────
|
|
227
|
+
Account: https://hashscan.io/testnet/account/0.0.7455134
|
|
228
|
+
Topic: https://hashscan.io/testnet/topic/0.0.7503789
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Configuration
|
|
232
|
+
|
|
233
|
+
設定は `~/.inscribe-mcp/config.json` に保存されます:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"network": "testnet",
|
|
238
|
+
"operatorAccountId": "0.0.XXXXXX",
|
|
239
|
+
"operatorPrivateKey": "302e...",
|
|
240
|
+
"defaultTopicId": "0.0.XXXXXX"
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
- `defaultTopicId` は初回 inscribe 時に自動作成されます
|
|
245
|
+
- 環境変数(`.env`)からのフォールバックもサポート
|
|
246
|
+
|
|
247
|
+
## Links
|
|
248
|
+
|
|
249
|
+
- [POP@AI](https://popatai.com) - Proof of Protocol for AI
|
|
250
|
+
- [Hedera](https://hedera.com) - The trust layer of the internet
|
|
251
|
+
- [HashScan](https://hashscan.io) - Hedera Explorer
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proofofprotocol/inscribe-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Verifiable inscription for AI agents - inscribe anything to blockchain with Hedera HCS",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/server.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"inscribe-mcp": "./src/cli/index.js",
|
|
9
|
+
"inscribe-mcp-server": "./src/server.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node src/server.js",
|
|
13
|
+
"start:sse": "node src/server-sse.js",
|
|
14
|
+
"cli": "node src/cli/index.js",
|
|
15
|
+
"test": "node src/test.js"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"model-context-protocol",
|
|
20
|
+
"hedera",
|
|
21
|
+
"hcs",
|
|
22
|
+
"inscription",
|
|
23
|
+
"verifiable",
|
|
24
|
+
"trust",
|
|
25
|
+
"blockchain",
|
|
26
|
+
"timestamp",
|
|
27
|
+
"proof",
|
|
28
|
+
"ai-agent",
|
|
29
|
+
"did",
|
|
30
|
+
"decentralized-identity"
|
|
31
|
+
],
|
|
32
|
+
"author": "POP@AI",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/proofofprotocol/inscribe-mcp.git"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/proofofprotocol/inscribe-mcp#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/proofofprotocol/inscribe-mcp/issues"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18.0.0"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"src/**/*",
|
|
47
|
+
"README.md",
|
|
48
|
+
"LICENSE"
|
|
49
|
+
],
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@hashgraph/sdk": "^2.51.0",
|
|
52
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
53
|
+
"commander": "^12.1.0",
|
|
54
|
+
"cors": "^2.8.5",
|
|
55
|
+
"dotenv": "^16.3.1",
|
|
56
|
+
"express": "^4.18.2"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* balance command
|
|
3
|
+
*
|
|
4
|
+
* Display current account balance via Mirror Node API.
|
|
5
|
+
* Read-Only: No transactions sent.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import { configExists, readConfig, validateConfig } from '../lib/config.js';
|
|
10
|
+
import { EXIT_CODES } from '../lib/exit-codes.js';
|
|
11
|
+
|
|
12
|
+
// ANSI colors
|
|
13
|
+
const colors = {
|
|
14
|
+
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
15
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
16
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
17
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
18
|
+
bold: (s) => `\x1b[1m${s}\x1b[0m`,
|
|
19
|
+
dim: (s) => `\x1b[2m${s}\x1b[0m`
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get Mirror Node URL for network
|
|
24
|
+
*/
|
|
25
|
+
function getMirrorUrl(network) {
|
|
26
|
+
return network === 'mainnet'
|
|
27
|
+
? 'https://mainnet.mirrornode.hedera.com'
|
|
28
|
+
: 'https://testnet.mirrornode.hedera.com';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Format tinybars to HBAR
|
|
33
|
+
*/
|
|
34
|
+
function formatHbar(tinybars) {
|
|
35
|
+
const hbar = tinybars / 100_000_000;
|
|
36
|
+
return hbar.toFixed(8) + ' HBAR';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Format tinybars to HBAR (short)
|
|
41
|
+
*/
|
|
42
|
+
function formatHbarShort(tinybars) {
|
|
43
|
+
const hbar = tinybars / 100_000_000;
|
|
44
|
+
if (hbar >= 1) {
|
|
45
|
+
return hbar.toFixed(2) + ' HBAR';
|
|
46
|
+
}
|
|
47
|
+
return hbar.toFixed(6) + ' HBAR';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const balanceCommand = new Command('balance')
|
|
51
|
+
.description('Display current account balance')
|
|
52
|
+
.option('--json', 'Output as JSON')
|
|
53
|
+
.action(async (options) => {
|
|
54
|
+
// Check if config exists
|
|
55
|
+
if (!configExists()) {
|
|
56
|
+
console.log('');
|
|
57
|
+
console.log(colors.red('Config not found.'));
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log('Run ' + colors.cyan('inscribe-mcp init') + ' to create configuration.');
|
|
60
|
+
console.log('');
|
|
61
|
+
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Validate config
|
|
65
|
+
const config = readConfig();
|
|
66
|
+
const validation = validateConfig(config);
|
|
67
|
+
|
|
68
|
+
if (!validation.valid) {
|
|
69
|
+
console.log('');
|
|
70
|
+
console.log(colors.red('Invalid configuration.'));
|
|
71
|
+
console.log('');
|
|
72
|
+
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { network, operatorAccountId } = config;
|
|
76
|
+
const mirrorUrl = getMirrorUrl(network);
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
// Fetch account info from Mirror Node
|
|
80
|
+
const response = await fetch(`${mirrorUrl}/api/v1/accounts/${operatorAccountId}`);
|
|
81
|
+
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
if (response.status === 404) {
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(colors.red('Account not found: ') + operatorAccountId);
|
|
86
|
+
console.log('');
|
|
87
|
+
console.log('Make sure the account exists on ' + network);
|
|
88
|
+
console.log('');
|
|
89
|
+
process.exit(EXIT_CODES.NETWORK_ERROR);
|
|
90
|
+
}
|
|
91
|
+
throw new Error(`HTTP ${response.status}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const data = await response.json();
|
|
95
|
+
const balance = data.balance?.balance || 0;
|
|
96
|
+
|
|
97
|
+
if (options.json) {
|
|
98
|
+
console.log(JSON.stringify({
|
|
99
|
+
network,
|
|
100
|
+
accountId: operatorAccountId,
|
|
101
|
+
balance: formatHbar(balance),
|
|
102
|
+
balanceTinybars: balance
|
|
103
|
+
}, null, 2));
|
|
104
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Pretty print
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log(colors.bold('Account Balance'));
|
|
110
|
+
console.log('─'.repeat(40));
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(` ${colors.dim('Network:')} ${colors.cyan(network)}`);
|
|
113
|
+
console.log(` ${colors.dim('Account:')} ${operatorAccountId}`);
|
|
114
|
+
console.log('');
|
|
115
|
+
console.log(` ${colors.dim('Balance:')} ${colors.green(colors.bold(formatHbarShort(balance)))}`);
|
|
116
|
+
console.log(` ${colors.dim('(' + balance.toLocaleString() + ' tinybars)')}`);
|
|
117
|
+
console.log('');
|
|
118
|
+
|
|
119
|
+
// Estimate inscriptions
|
|
120
|
+
const costPerInscribe = 0.0001; // ~$0.0001 per HCS message
|
|
121
|
+
const hbar = balance / 100_000_000;
|
|
122
|
+
const estimatedInscriptions = Math.floor(hbar / costPerInscribe);
|
|
123
|
+
|
|
124
|
+
console.log(` ${colors.dim('Estimated inscriptions:')} ~${estimatedInscriptions.toLocaleString()}`);
|
|
125
|
+
console.log('');
|
|
126
|
+
|
|
127
|
+
// Low balance warning
|
|
128
|
+
if (hbar < 0.1) {
|
|
129
|
+
console.log(colors.yellow('⚠ Low balance warning'));
|
|
130
|
+
console.log(' Consider adding more HBAR to continue inscribing.');
|
|
131
|
+
console.log('');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// HashScan link
|
|
135
|
+
const hashscanUrl = network === 'mainnet'
|
|
136
|
+
? `https://hashscan.io/mainnet/account/${operatorAccountId}`
|
|
137
|
+
: `https://hashscan.io/testnet/account/${operatorAccountId}`;
|
|
138
|
+
|
|
139
|
+
console.log(` ${colors.dim('HashScan:')} ${hashscanUrl}`);
|
|
140
|
+
console.log('');
|
|
141
|
+
|
|
142
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
143
|
+
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.log('');
|
|
146
|
+
console.log(colors.red('Failed to fetch balance:'));
|
|
147
|
+
console.log(' ' + error.message);
|
|
148
|
+
console.log('');
|
|
149
|
+
process.exit(EXIT_CODES.NETWORK_ERROR);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config command
|
|
3
|
+
*
|
|
4
|
+
* Display current configuration (with masked private key).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { configExists, getDisplayConfig, getConfigPath, validateConfig, readConfig } from '../lib/config.js';
|
|
9
|
+
import { EXIT_CODES } from '../lib/exit-codes.js';
|
|
10
|
+
|
|
11
|
+
// ANSI colors
|
|
12
|
+
const colors = {
|
|
13
|
+
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
14
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
15
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
16
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
17
|
+
bold: (s) => `\x1b[1m${s}\x1b[0m`,
|
|
18
|
+
dim: (s) => `\x1b[2m${s}\x1b[0m`
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const configCommand = new Command('config')
|
|
22
|
+
.description('Display current configuration')
|
|
23
|
+
.option('--json', 'Output as JSON (private key still masked)')
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
// Check if config exists
|
|
26
|
+
if (!configExists()) {
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log(colors.red('Config not found.'));
|
|
29
|
+
console.log('');
|
|
30
|
+
console.log('Run ' + colors.cyan('inscribe-mcp init') + ' to create configuration.');
|
|
31
|
+
console.log('');
|
|
32
|
+
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Validate config
|
|
36
|
+
const rawConfig = readConfig();
|
|
37
|
+
const validation = validateConfig(rawConfig);
|
|
38
|
+
|
|
39
|
+
if (!validation.valid) {
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(colors.red('Invalid configuration:'));
|
|
42
|
+
validation.errors.forEach(err => {
|
|
43
|
+
console.log(' • ' + err);
|
|
44
|
+
});
|
|
45
|
+
console.log('');
|
|
46
|
+
console.log('Run ' + colors.cyan('inscribe-mcp init --force') + ' to reconfigure.');
|
|
47
|
+
console.log('');
|
|
48
|
+
process.exit(EXIT_CODES.CONFIG_ERROR);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Get display config (masked)
|
|
52
|
+
const config = getDisplayConfig();
|
|
53
|
+
|
|
54
|
+
if (options.json) {
|
|
55
|
+
console.log(JSON.stringify(config, null, 2));
|
|
56
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Pretty print
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log(colors.bold('inscribe-mcp Configuration'));
|
|
62
|
+
console.log('─'.repeat(40));
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log(` ${colors.dim('File:')} ${getConfigPath()}`);
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log(` ${colors.dim('Network:')} ${colors.cyan(config.network)}`);
|
|
67
|
+
console.log(` ${colors.dim('Account:')} ${config.operatorAccountId}`);
|
|
68
|
+
console.log(` ${colors.dim('Key:')} ${config.operatorPrivateKey}`);
|
|
69
|
+
|
|
70
|
+
if (config.defaultTopicId) {
|
|
71
|
+
console.log(` ${colors.dim('Topic:')} ${config.defaultTopicId}`);
|
|
72
|
+
} else {
|
|
73
|
+
console.log(` ${colors.dim('Topic:')} ${colors.dim('(auto-create on first inscribe)')}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log('');
|
|
77
|
+
|
|
78
|
+
// HashScan link
|
|
79
|
+
const hashscanUrl = config.network === 'mainnet'
|
|
80
|
+
? `https://hashscan.io/mainnet/account/${config.operatorAccountId}`
|
|
81
|
+
: `https://hashscan.io/testnet/account/${config.operatorAccountId}`;
|
|
82
|
+
|
|
83
|
+
console.log(` ${colors.dim('HashScan:')} ${hashscanUrl}`);
|
|
84
|
+
console.log('');
|
|
85
|
+
|
|
86
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
87
|
+
});
|