@goplausible/openclaw-algorand-plugin 1.9.5 → 2.0.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/index.ts +74 -529
- package/lib/mcporter.ts +75 -0
- package/lib/workspace.ts +216 -0
- package/openclaw.plugin.json +25 -2
- package/package.json +12 -3
- package/setup.ts +7 -23
- package/scripts/backup-keyring.js +0 -117
- package/scripts/setup-keyring.sh +0 -428
package/scripts/setup-keyring.sh
DELETED
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -e
|
|
3
|
-
|
|
4
|
-
MODE="${1:---detect}"
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
-
PLUGIN_DIR="$(dirname "$SCRIPT_DIR")"
|
|
7
|
-
NODE_MODULES="$PLUGIN_DIR/node_modules"
|
|
8
|
-
BACKUP_SCRIPT="$SCRIPT_DIR/backup-keyring.js"
|
|
9
|
-
WALLET_DB="$HOME/.algorand-mcp/wallet.db"
|
|
10
|
-
|
|
11
|
-
# ═══════════════════════════════════════════════════════════
|
|
12
|
-
# 1. OS Detection
|
|
13
|
-
# ═══════════════════════════════════════════════════════════
|
|
14
|
-
if [[ "$(uname -s)" != "Linux" ]]; then
|
|
15
|
-
case "$(uname -s)" in
|
|
16
|
-
Darwin) BACKEND="macOS Keychain" ;;
|
|
17
|
-
*) BACKEND="OS Keychain" ;;
|
|
18
|
-
esac
|
|
19
|
-
if [ "$MODE" = "--detect" ]; then
|
|
20
|
-
echo "PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')"
|
|
21
|
-
echo "BACKEND=$BACKEND"
|
|
22
|
-
echo "PERSISTENT=true"
|
|
23
|
-
echo "HEADLESS=false"
|
|
24
|
-
else
|
|
25
|
-
echo ""
|
|
26
|
-
echo " ✅ $BACKEND — persistent by default. No setup needed."
|
|
27
|
-
echo ""
|
|
28
|
-
fi
|
|
29
|
-
exit 0
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
# ═══════════════════════════════════════════════════════════
|
|
33
|
-
# 2. Linux Environment Detection
|
|
34
|
-
# ═══════════════════════════════════════════════════════════
|
|
35
|
-
|
|
36
|
-
PLATFORM="linux"
|
|
37
|
-
KEYRING_DIR="$HOME/.local/share/keyrings"
|
|
38
|
-
|
|
39
|
-
# Display (headless?)
|
|
40
|
-
HAS_DISPLAY=false
|
|
41
|
-
[[ -n "${DISPLAY:-}" || -n "${WAYLAND_DISPLAY:-}" ]] && HAS_DISPLAY=true
|
|
42
|
-
|
|
43
|
-
# D-Bus session
|
|
44
|
-
HAS_DBUS=false
|
|
45
|
-
[[ -n "${DBUS_SESSION_BUS_ADDRESS:-}" ]] && HAS_DBUS=true
|
|
46
|
-
|
|
47
|
-
# GNOME Keyring daemon running
|
|
48
|
-
KEYRING_RUNNING=false
|
|
49
|
-
pgrep -u "$USER" gnome-keyring-daemon >/dev/null 2>&1 && KEYRING_RUNNING=true
|
|
50
|
-
|
|
51
|
-
# Keyring files on disk
|
|
52
|
-
KEYRING_FILES=false
|
|
53
|
-
[[ -d "$KEYRING_DIR" && "$(ls -A "$KEYRING_DIR" 2>/dev/null)" ]] && KEYRING_FILES=true
|
|
54
|
-
|
|
55
|
-
# Wallet DB exists and account count (via Node.js)
|
|
56
|
-
WALLET_DB_EXISTS=false
|
|
57
|
-
WALLET_DB_COUNT=0
|
|
58
|
-
[[ -f "$WALLET_DB" ]] && WALLET_DB_EXISTS=true
|
|
59
|
-
if [[ "$WALLET_DB_EXISTS" == "true" && -f "$BACKUP_SCRIPT" ]]; then
|
|
60
|
-
WALLET_DB_COUNT=$(NODE_PATH="$NODE_MODULES" node "$BACKUP_SCRIPT" count 2>/dev/null || echo "0")
|
|
61
|
-
fi
|
|
62
|
-
|
|
63
|
-
# Package manager
|
|
64
|
-
PKG=""
|
|
65
|
-
if command -v apt >/dev/null 2>&1; then
|
|
66
|
-
PKG="apt"
|
|
67
|
-
elif command -v dnf >/dev/null 2>&1; then
|
|
68
|
-
PKG="dnf"
|
|
69
|
-
elif command -v yum >/dev/null 2>&1; then
|
|
70
|
-
PKG="yum"
|
|
71
|
-
elif command -v pacman >/dev/null 2>&1; then
|
|
72
|
-
PKG="pacman"
|
|
73
|
-
elif command -v apk >/dev/null 2>&1; then
|
|
74
|
-
PKG="apk"
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
# Container detection
|
|
78
|
-
IN_CONTAINER=false
|
|
79
|
-
[[ -f /.dockerenv ]] && IN_CONTAINER=true
|
|
80
|
-
grep -q 'docker\|lxc\|containerd' /proc/1/cgroup 2>/dev/null && IN_CONTAINER=true
|
|
81
|
-
|
|
82
|
-
# Persistence verdict
|
|
83
|
-
HEADLESS=false
|
|
84
|
-
if [[ "$HAS_DBUS" == "true" && "$KEYRING_RUNNING" == "true" && "$KEYRING_FILES" == "true" ]]; then
|
|
85
|
-
PERSISTENT="true"
|
|
86
|
-
BACKEND="GNOME Keyring (persistent)"
|
|
87
|
-
elif [[ "$HAS_DISPLAY" == "true" ]]; then
|
|
88
|
-
PERSISTENT="true"
|
|
89
|
-
BACKEND="Desktop Keyring (persistent)"
|
|
90
|
-
else
|
|
91
|
-
PERSISTENT="false"
|
|
92
|
-
BACKEND="In-memory (volatile)"
|
|
93
|
-
HEADLESS=true
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
# ═══════════════════════════════════════════════════════════
|
|
97
|
-
# 3. Detect-only mode
|
|
98
|
-
# ═══════════════════════════════════════════════════════════
|
|
99
|
-
if [ "$MODE" = "--detect" ]; then
|
|
100
|
-
echo "PLATFORM=$PLATFORM"
|
|
101
|
-
echo "BACKEND=$BACKEND"
|
|
102
|
-
echo "PERSISTENT=$PERSISTENT"
|
|
103
|
-
echo "HEADLESS=$HEADLESS"
|
|
104
|
-
echo "HAS_DISPLAY=$HAS_DISPLAY"
|
|
105
|
-
echo "HAS_DBUS=$HAS_DBUS"
|
|
106
|
-
echo "KEYRING_RUNNING=$KEYRING_RUNNING"
|
|
107
|
-
echo "KEYRING_FILES=$KEYRING_FILES"
|
|
108
|
-
echo "WALLET_DB_EXISTS=$WALLET_DB_EXISTS"
|
|
109
|
-
echo "WALLET_DB_COUNT=$WALLET_DB_COUNT"
|
|
110
|
-
echo "PKG_MANAGER=$PKG"
|
|
111
|
-
echo "IN_CONTAINER=$IN_CONTAINER"
|
|
112
|
-
exit 0
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
# ═══════════════════════════════════════════════════════════
|
|
116
|
-
# 4. Setup mode
|
|
117
|
-
# ═══════════════════════════════════════════════════════════
|
|
118
|
-
|
|
119
|
-
echo ""
|
|
120
|
-
echo " ── Algorand MCP Keyring Persistence Setup ──"
|
|
121
|
-
echo ""
|
|
122
|
-
|
|
123
|
-
# ─── 4a. Status display ───
|
|
124
|
-
echo " Platform: Linux"
|
|
125
|
-
echo " Display: $( [[ "$HAS_DISPLAY" == "true" ]] && echo "✅ Yes" || echo "❌ No (headless)" )"
|
|
126
|
-
echo " D-Bus session: $( [[ "$HAS_DBUS" == "true" ]] && echo "✅ Active" || echo "❌ Not found" )"
|
|
127
|
-
echo " Keyring daemon: $( [[ "$KEYRING_RUNNING" == "true" ]] && echo "✅ Running" || echo "❌ Not running" )"
|
|
128
|
-
echo " Keyring files: $( [[ "$KEYRING_FILES" == "true" ]] && echo "✅ Found in $KEYRING_DIR" || echo "❌ None (in-memory only)" )"
|
|
129
|
-
echo " Wallet DB: $( [[ "$WALLET_DB_EXISTS" == "true" ]] && echo "✅ $WALLET_DB ($WALLET_DB_COUNT account(s))" || echo "— Not found (fresh install)" )"
|
|
130
|
-
echo " Package manager: ${PKG:-unknown}"
|
|
131
|
-
echo " Container: $( [[ "$IN_CONTAINER" == "true" ]] && echo "Yes" || echo "No" )"
|
|
132
|
-
echo ""
|
|
133
|
-
|
|
134
|
-
# Already persistent with keyring files on disk?
|
|
135
|
-
if [[ "$PERSISTENT" == "true" && "$KEYRING_FILES" == "true" ]]; then
|
|
136
|
-
echo " ✅ Keyring is persistent and will survive reboots."
|
|
137
|
-
echo ""
|
|
138
|
-
exit 0
|
|
139
|
-
fi
|
|
140
|
-
|
|
141
|
-
# ─── 4b. Backup existing wallet mnemonics (UPDATE scenario only) ───
|
|
142
|
-
BACKUP_FILE=""
|
|
143
|
-
if [[ "$WALLET_DB_COUNT" -gt 0 && "$KEYRING_RUNNING" == "true" && -f "$BACKUP_SCRIPT" ]]; then
|
|
144
|
-
echo " ── Step 1: Backup wallet mnemonics from current keyring ──"
|
|
145
|
-
echo ""
|
|
146
|
-
echo " Found $WALLET_DB_COUNT account(s) in wallet.db."
|
|
147
|
-
echo " Reading mnemonics from current keyring before setup..."
|
|
148
|
-
echo ""
|
|
149
|
-
|
|
150
|
-
BACKUP_FILE=$(mktemp /tmp/algorand-mcp-keyring-backup.XXXXXX)
|
|
151
|
-
chmod 600 "$BACKUP_FILE"
|
|
152
|
-
|
|
153
|
-
BACKUP_RESULT=$(NODE_PATH="$NODE_MODULES" node "$BACKUP_SCRIPT" backup "$BACKUP_FILE" 2>&1)
|
|
154
|
-
echo " $BACKUP_RESULT"
|
|
155
|
-
|
|
156
|
-
# Check if backup actually has content
|
|
157
|
-
if [[ ! -s "$BACKUP_FILE" ]]; then
|
|
158
|
-
rm -f "$BACKUP_FILE"
|
|
159
|
-
BACKUP_FILE=""
|
|
160
|
-
echo " ℹ️ No mnemonics to backup (keyring may be empty after a reboot)."
|
|
161
|
-
fi
|
|
162
|
-
echo ""
|
|
163
|
-
elif [[ "$WALLET_DB_COUNT" -gt 0 && "$KEYRING_RUNNING" != "true" ]]; then
|
|
164
|
-
echo " ── Step 1: Backup ──"
|
|
165
|
-
echo ""
|
|
166
|
-
echo " ⚠️ Keyring daemon not running — cannot backup existing mnemonics."
|
|
167
|
-
echo " If the system was rebooted, in-memory mnemonics are already lost."
|
|
168
|
-
echo ""
|
|
169
|
-
fi
|
|
170
|
-
|
|
171
|
-
# ─── 4c. Install keyring packages ───
|
|
172
|
-
echo " ── Step 2: Install keyring packages ──"
|
|
173
|
-
echo ""
|
|
174
|
-
|
|
175
|
-
if [[ -z "$PKG" ]]; then
|
|
176
|
-
echo " Could not detect package manager. Install manually:"
|
|
177
|
-
echo " gnome-keyring, libsecret-tools, dbus-user-session (or equivalent)"
|
|
178
|
-
echo ""
|
|
179
|
-
else
|
|
180
|
-
case "$PKG" in
|
|
181
|
-
apt)
|
|
182
|
-
INSTALL_CMD="sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt update && sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt install -y gnome-keyring libsecret-tools dbus-user-session"
|
|
183
|
-
;;
|
|
184
|
-
dnf)
|
|
185
|
-
INSTALL_CMD="sudo dnf install -y gnome-keyring libsecret libsecret-tools"
|
|
186
|
-
;;
|
|
187
|
-
yum)
|
|
188
|
-
INSTALL_CMD="sudo yum install -y gnome-keyring libsecret libsecret-tools"
|
|
189
|
-
;;
|
|
190
|
-
pacman)
|
|
191
|
-
INSTALL_CMD="sudo pacman -Sy --noconfirm gnome-keyring libsecret"
|
|
192
|
-
;;
|
|
193
|
-
apk)
|
|
194
|
-
INSTALL_CMD="sudo apk add gnome-keyring libsecret dbus secret-tool"
|
|
195
|
-
;;
|
|
196
|
-
esac
|
|
197
|
-
|
|
198
|
-
echo " Run:"
|
|
199
|
-
echo " $INSTALL_CMD"
|
|
200
|
-
echo ""
|
|
201
|
-
read -r -p " Install now? [y/N] " REPLY
|
|
202
|
-
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
|
|
203
|
-
echo ""
|
|
204
|
-
eval "$INSTALL_CMD"
|
|
205
|
-
echo ""
|
|
206
|
-
echo " ✅ Packages installed."
|
|
207
|
-
else
|
|
208
|
-
echo " Skipped. Install later with the command above."
|
|
209
|
-
fi
|
|
210
|
-
echo ""
|
|
211
|
-
fi
|
|
212
|
-
|
|
213
|
-
# ─── 4d. Enable lingering user session ───
|
|
214
|
-
echo " ── Step 3: Enable user session lingering ──"
|
|
215
|
-
echo ""
|
|
216
|
-
echo " This keeps D-Bus and keyring daemon alive after SSH logout."
|
|
217
|
-
echo ""
|
|
218
|
-
|
|
219
|
-
if loginctl show-user "$USER" 2>/dev/null | grep -q "Linger=yes"; then
|
|
220
|
-
echo " ✅ Lingering already enabled for $USER"
|
|
221
|
-
else
|
|
222
|
-
read -r -p " Enable lingering for $USER? [y/N] " REPLY
|
|
223
|
-
if [[ "$REPLY" =~ ^[Yy]$ ]]; then
|
|
224
|
-
loginctl enable-linger "$USER"
|
|
225
|
-
echo " ✅ Lingering enabled."
|
|
226
|
-
else
|
|
227
|
-
echo " Skipped."
|
|
228
|
-
fi
|
|
229
|
-
fi
|
|
230
|
-
echo ""
|
|
231
|
-
|
|
232
|
-
# ─── 4e. Start D-Bus and keyring daemon ───
|
|
233
|
-
echo " ── Step 4: Start D-Bus session and keyring daemon ──"
|
|
234
|
-
echo ""
|
|
235
|
-
|
|
236
|
-
# Ensure D-Bus is available
|
|
237
|
-
if [[ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]]; then
|
|
238
|
-
echo " Starting D-Bus session..."
|
|
239
|
-
eval $(dbus-launch --sh-syntax)
|
|
240
|
-
echo " ✅ D-Bus session started."
|
|
241
|
-
else
|
|
242
|
-
echo " ✅ D-Bus session already active."
|
|
243
|
-
fi
|
|
244
|
-
|
|
245
|
-
# Kill stale keyring daemons (leftover --unlock processes, etc.)
|
|
246
|
-
STALE_COUNT=$(pgrep -u "$USER" gnome-keyring-daemon 2>/dev/null | wc -l)
|
|
247
|
-
if [[ "$STALE_COUNT" -gt 1 ]]; then
|
|
248
|
-
echo " Cleaning up $STALE_COUNT stale keyring daemon processes..."
|
|
249
|
-
pkill -9 -u "$USER" gnome-keyring-daemon 2>/dev/null || true
|
|
250
|
-
sleep 2
|
|
251
|
-
fi
|
|
252
|
-
|
|
253
|
-
# Start the daemon via --start (D-Bus activated, stays resident)
|
|
254
|
-
# Note: on headless, the daemon may be D-Bus activated on demand rather than
|
|
255
|
-
# staying resident. This is normal — secret-tool and @napi-rs/keyring will
|
|
256
|
-
# trigger D-Bus activation automatically when they query the Secret Service.
|
|
257
|
-
echo " Starting gnome-keyring-daemon..."
|
|
258
|
-
eval $(gnome-keyring-daemon --start --components=secrets 2>&1 | grep -v '^\*\*') || true
|
|
259
|
-
sleep 1
|
|
260
|
-
|
|
261
|
-
if pgrep -u "$USER" gnome-keyring-daemon >/dev/null 2>&1; then
|
|
262
|
-
echo " ✅ Keyring daemon running."
|
|
263
|
-
else
|
|
264
|
-
# On D-Bus activated systems, the daemon starts on demand — verify by querying
|
|
265
|
-
if command -v secret-tool >/dev/null 2>&1; then
|
|
266
|
-
secret-tool search --all service algorand-mcp 2>/dev/null && echo " ✅ Keyring daemon available (D-Bus activated)." || true
|
|
267
|
-
fi
|
|
268
|
-
echo " ℹ️ Daemon is D-Bus activated (starts on demand when queried)."
|
|
269
|
-
fi
|
|
270
|
-
echo ""
|
|
271
|
-
|
|
272
|
-
# ─── 4f. Create persistent login keyring collection ───
|
|
273
|
-
KEYRING_FILE="$KEYRING_DIR/login.keyring"
|
|
274
|
-
mkdir -p "$KEYRING_DIR"
|
|
275
|
-
|
|
276
|
-
echo " ── Step 5: Create persistent keyring ──"
|
|
277
|
-
echo ""
|
|
278
|
-
|
|
279
|
-
if [[ -f "$KEYRING_FILE" ]]; then
|
|
280
|
-
echo " ✅ Keyring already exists at $KEYRING_FILE"
|
|
281
|
-
else
|
|
282
|
-
# On headless Linux, gnome-keyring-daemon refuses to create a collection
|
|
283
|
-
# via normal prompts (no GUI). We use the D-Bus internal interface
|
|
284
|
-
# CreateWithMasterPassword to create the "login" collection with an
|
|
285
|
-
# empty master password — making it auto-unlocked and persistent on disk.
|
|
286
|
-
echo " Creating login keyring collection via D-Bus..."
|
|
287
|
-
|
|
288
|
-
python3 << 'PYEOF'
|
|
289
|
-
import sys
|
|
290
|
-
try:
|
|
291
|
-
from jeepney import new_method_call, DBusAddress
|
|
292
|
-
from jeepney.io.blocking import open_dbus_connection
|
|
293
|
-
|
|
294
|
-
conn = open_dbus_connection(bus='SESSION')
|
|
295
|
-
|
|
296
|
-
# Open a plain-text session with the Secret Service
|
|
297
|
-
msg = new_method_call(
|
|
298
|
-
DBusAddress('/org/freedesktop/secrets',
|
|
299
|
-
bus_name='org.freedesktop.secrets',
|
|
300
|
-
interface='org.freedesktop.Secret.Service'),
|
|
301
|
-
'OpenSession',
|
|
302
|
-
'sv',
|
|
303
|
-
('plain', ('s', ''))
|
|
304
|
-
)
|
|
305
|
-
reply = conn.send_and_get_reply(msg)
|
|
306
|
-
session_path = reply.body[1]
|
|
307
|
-
|
|
308
|
-
# Create the "login" collection with empty master password
|
|
309
|
-
# Uses the internal gnome-keyring interface (bypasses GUI prompt)
|
|
310
|
-
props = {
|
|
311
|
-
'org.freedesktop.Secret.Collection.Label': ('s', 'login')
|
|
312
|
-
}
|
|
313
|
-
master_password = (session_path, b'', b'', 'text/plain')
|
|
314
|
-
|
|
315
|
-
msg = new_method_call(
|
|
316
|
-
DBusAddress('/org/freedesktop/secrets',
|
|
317
|
-
bus_name='org.gnome.keyring',
|
|
318
|
-
interface='org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface'),
|
|
319
|
-
'CreateWithMasterPassword',
|
|
320
|
-
'a{sv}(oayays)',
|
|
321
|
-
(props, master_password)
|
|
322
|
-
)
|
|
323
|
-
reply = conn.send_and_get_reply(msg)
|
|
324
|
-
print(f" Collection created: {reply.body[0]}")
|
|
325
|
-
conn.close()
|
|
326
|
-
except Exception as e:
|
|
327
|
-
print(f" Error: {e}", file=sys.stderr)
|
|
328
|
-
sys.exit(1)
|
|
329
|
-
PYEOF
|
|
330
|
-
|
|
331
|
-
if [[ $? -eq 0 && -f "$KEYRING_FILE" ]]; then
|
|
332
|
-
echo " ✅ Persistent keyring created at $KEYRING_FILE"
|
|
333
|
-
else
|
|
334
|
-
FOUND_FILE=$(ls "$KEYRING_DIR"/*.keyring 2>/dev/null | head -1 || true)
|
|
335
|
-
if [[ -n "$FOUND_FILE" ]]; then
|
|
336
|
-
echo " ✅ Persistent keyring created at $FOUND_FILE"
|
|
337
|
-
else
|
|
338
|
-
echo " ⚠️ Keyring file not created. Ensure python3 and jeepney are installed."
|
|
339
|
-
echo " Install with: pip3 install jeepney"
|
|
340
|
-
fi
|
|
341
|
-
fi
|
|
342
|
-
fi
|
|
343
|
-
echo ""
|
|
344
|
-
|
|
345
|
-
# ─── 4g. Restore backed-up wallet mnemonics (UPDATE scenario only) ───
|
|
346
|
-
if [[ -n "$BACKUP_FILE" && -f "$BACKUP_FILE" && -s "$BACKUP_FILE" ]]; then
|
|
347
|
-
echo " ── Step 6: Restore wallet mnemonics ──"
|
|
348
|
-
echo ""
|
|
349
|
-
|
|
350
|
-
RESTORE_RESULT=$(NODE_PATH="$NODE_MODULES" node "$BACKUP_SCRIPT" restore "$BACKUP_FILE" 2>&1)
|
|
351
|
-
echo " $RESTORE_RESULT"
|
|
352
|
-
|
|
353
|
-
# Securely delete backup
|
|
354
|
-
shred -u "$BACKUP_FILE" 2>/dev/null || rm -f "$BACKUP_FILE"
|
|
355
|
-
echo " ✅ Temporary backup securely deleted."
|
|
356
|
-
echo ""
|
|
357
|
-
fi
|
|
358
|
-
|
|
359
|
-
# ─── 4h. Docker-specific guidance ───
|
|
360
|
-
if [[ "$IN_CONTAINER" == "true" ]]; then
|
|
361
|
-
echo " ── Docker / Container Notes ──"
|
|
362
|
-
echo ""
|
|
363
|
-
echo " Add to your Dockerfile:"
|
|
364
|
-
echo " RUN apt-get update && apt-get install -y \\"
|
|
365
|
-
echo " gnome-keyring libsecret-tools dbus-user-session \\"
|
|
366
|
-
echo " && rm -rf /var/lib/apt/lists/*"
|
|
367
|
-
echo ""
|
|
368
|
-
echo " Entrypoint wrapper (entrypoint.sh):"
|
|
369
|
-
echo ' #!/bin/bash'
|
|
370
|
-
echo ' export $(dbus-launch)'
|
|
371
|
-
echo ' eval $(gnome-keyring-daemon --start --components=secrets)'
|
|
372
|
-
echo ' # Create login collection if not exists (headless — no GUI prompt)'
|
|
373
|
-
echo ' if [ ! -f ~/.local/share/keyrings/login.keyring ]; then'
|
|
374
|
-
echo ' python3 -c "'
|
|
375
|
-
echo ' from jeepney import new_method_call, DBusAddress'
|
|
376
|
-
echo ' from jeepney.io.blocking import open_dbus_connection'
|
|
377
|
-
echo ' conn = open_dbus_connection(bus=\"SESSION\")'
|
|
378
|
-
echo ' r = conn.send_and_get_reply(new_method_call(DBusAddress(\"/org/freedesktop/secrets\",bus_name=\"org.freedesktop.secrets\",interface=\"org.freedesktop.Secret.Service\"),\"OpenSession\",\"sv\",(\"plain\",(\"s\",\"\"))))'
|
|
379
|
-
echo ' s = r.body[1]'
|
|
380
|
-
echo ' conn.send_and_get_reply(new_method_call(DBusAddress(\"/org/freedesktop/secrets\",bus_name=\"org.gnome.keyring\",interface=\"org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface\"),\"CreateWithMasterPassword\",\"a{sv}(oayays)\",({\"org.freedesktop.Secret.Collection.Label\":(\"s\",\"login\")},(s,b\"\",b\"\",\"text/plain\"))))'
|
|
381
|
-
echo ' conn.close()'
|
|
382
|
-
echo ' "'
|
|
383
|
-
echo ' fi'
|
|
384
|
-
echo ' exec "$@"'
|
|
385
|
-
echo ""
|
|
386
|
-
echo " Persist keyring + wallet data (docker-compose.yml):"
|
|
387
|
-
echo " volumes:"
|
|
388
|
-
echo " - keyring-data:/home/user/.local/share/keyrings"
|
|
389
|
-
echo " - wallet-data:/home/user/.algorand-mcp"
|
|
390
|
-
echo ""
|
|
391
|
-
fi
|
|
392
|
-
|
|
393
|
-
# ─── 4i. Final verification ───
|
|
394
|
-
echo " ── Results ──"
|
|
395
|
-
echo ""
|
|
396
|
-
|
|
397
|
-
# Re-check
|
|
398
|
-
VERIFY_RUNNING=false
|
|
399
|
-
pgrep -u "$USER" gnome-keyring-daemon >/dev/null 2>&1 && VERIFY_RUNNING=true
|
|
400
|
-
|
|
401
|
-
VERIFY_FILES=false
|
|
402
|
-
[[ -d "$KEYRING_DIR" && "$(ls -A "$KEYRING_DIR" 2>/dev/null)" ]] && VERIFY_FILES=true
|
|
403
|
-
|
|
404
|
-
if [[ "$VERIFY_RUNNING" == "true" ]]; then
|
|
405
|
-
echo " ✅ Daemon: Running"
|
|
406
|
-
else
|
|
407
|
-
echo " ✅ Daemon: D-Bus activated (starts on demand)"
|
|
408
|
-
fi
|
|
409
|
-
|
|
410
|
-
if [[ "$VERIFY_FILES" == "true" ]]; then
|
|
411
|
-
echo " ✅ Persistent: Yes (files at $KEYRING_DIR)"
|
|
412
|
-
else
|
|
413
|
-
echo " ⚠️ Persistent: No keyring files yet"
|
|
414
|
-
fi
|
|
415
|
-
|
|
416
|
-
# Verify wallet mnemonics via Node.js
|
|
417
|
-
if [[ -f "$BACKUP_SCRIPT" && "$WALLET_DB_EXISTS" == "true" ]]; then
|
|
418
|
-
VERIFY_RESULT=$(NODE_PATH="$NODE_MODULES" node "$BACKUP_SCRIPT" verify 2>/dev/null | tail -1)
|
|
419
|
-
echo " ✅ Wallets: $VERIFY_RESULT"
|
|
420
|
-
fi
|
|
421
|
-
|
|
422
|
-
echo ""
|
|
423
|
-
echo " Behavior after setup:"
|
|
424
|
-
echo " • Keyring stored on disk, auto-unlocked on boot via D-Bus activation"
|
|
425
|
-
echo " • loginctl linger keeps D-Bus session alive between SSH sessions"
|
|
426
|
-
echo " • Wallet keys persist across reboots — no user interaction needed"
|
|
427
|
-
echo " • Keep agent wallet funds minimal — use QR code top-ups as needed"
|
|
428
|
-
echo ""
|