indelible-mcp 5.8.1 → 5.8.2
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 +1 -1
- package/package.json +1 -1
- package/src/index.js +60 -10
package/LICENSE
CHANGED
|
@@ -15,7 +15,7 @@ Additional Use Grant: You may make use of the Licensed Work for personal,
|
|
|
15
15
|
commercial blockchain storage, session saving, or
|
|
16
16
|
encrypted vault service without written permission
|
|
17
17
|
from the Licensor.
|
|
18
|
-
Change Date: August
|
|
18
|
+
Change Date: August 19, 2030
|
|
19
19
|
Change License: MIT License
|
|
20
20
|
|
|
21
21
|
Terms
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1025,7 +1025,8 @@ function claimRefusalMessage(claim2) {
|
|
|
1025
1025
|
if (r === "WALLET_VIEW_DEGRADED") {
|
|
1026
1026
|
const seen = Number.isFinite(claim2.visibleSats) ? `${claim2.visibleSats} sats` : "the coins known locally";
|
|
1027
1027
|
const needs = Number.isFinite(claim2.need) ? ` (needs about ${claim2.need} sats)` : "";
|
|
1028
|
-
|
|
1028
|
+
const opener = claim2.operator_reason === "INDEX_PARTIAL" ? "The network's view of your wallet is temporarily incomplete (the index is catching up)." : "Cannot reach the network to see your full wallet right now.";
|
|
1029
|
+
return `${opener} The currently-visible coins (${seen}) cannot fund this save${needs}, but your wallet may hold more that is not visible yet. Nothing was spent. Retry in a few minutes \u2014 do not add funds based on this message.`;
|
|
1029
1030
|
}
|
|
1030
1031
|
if (r === "NO_COINS") return "No UTXOs available. Fund your wallet.";
|
|
1031
1032
|
return "No UTXOs available. Fund your wallet.";
|
|
@@ -1100,11 +1101,13 @@ async function claimSpendableUtxos(address, bridgeFallback, opts = {}) {
|
|
|
1100
1101
|
}
|
|
1101
1102
|
}
|
|
1102
1103
|
let _bridgeDegraded = false;
|
|
1104
|
+
let _bridgePartial = null;
|
|
1103
1105
|
const bridgeView = async () => {
|
|
1104
1106
|
if (!bridgeFallback) return [];
|
|
1105
1107
|
try {
|
|
1106
1108
|
const v = await bridgeFallback(address);
|
|
1107
1109
|
_bridgeDegraded = false;
|
|
1110
|
+
_bridgePartial = v?.coverage?.known && v.coverage.partial ? v.coverage : null;
|
|
1108
1111
|
return v;
|
|
1109
1112
|
} catch {
|
|
1110
1113
|
_bridgeDegraded = true;
|
|
@@ -1121,6 +1124,17 @@ async function claimSpendableUtxos(address, bridgeFallback, opts = {}) {
|
|
|
1121
1124
|
} else {
|
|
1122
1125
|
candidates = unionCandidates(address, await bridgeView());
|
|
1123
1126
|
}
|
|
1127
|
+
if (_phase === "union" && candidates.length === 0 && (_bridgeDegraded || _bridgePartial)) {
|
|
1128
|
+
return {
|
|
1129
|
+
refused: true,
|
|
1130
|
+
reason: "WALLET_VIEW_DEGRADED",
|
|
1131
|
+
operator_reason: _bridgeDegraded ? "BRIDGE_UNREACHABLE" : "INDEX_PARTIAL",
|
|
1132
|
+
..._bridgePartial ? { index_holes: _bridgePartial.holes, index_source: _bridgePartial.source } : {},
|
|
1133
|
+
underlying: "NO_COINS",
|
|
1134
|
+
visibleSats: 0,
|
|
1135
|
+
reservedSats: 0
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1124
1138
|
const claimed = await withFileLock(LOCK_PATH, async () => {
|
|
1125
1139
|
const store = readReservations();
|
|
1126
1140
|
releaseDeadPreSign(store, now);
|
|
@@ -1137,8 +1151,17 @@ async function claimSpendableUtxos(address, bridgeFallback, opts = {}) {
|
|
|
1137
1151
|
if (wholeWallet.ok) return { busy: true };
|
|
1138
1152
|
const { ok: _ok, ...evidence } = selected;
|
|
1139
1153
|
const reservedSats = (candidates || []).filter((u) => reserved.has(inputKey(u))).reduce((s, u) => s + (u?.value || 0), 0);
|
|
1140
|
-
if (_bridgeDegraded && evidence.reason !== "TX_TOO_LARGE") {
|
|
1141
|
-
return {
|
|
1154
|
+
if ((_bridgeDegraded || _bridgePartial) && evidence.reason !== "TX_TOO_LARGE") {
|
|
1155
|
+
return {
|
|
1156
|
+
refused: true,
|
|
1157
|
+
reason: "WALLET_VIEW_DEGRADED",
|
|
1158
|
+
operator_reason: _bridgeDegraded ? "BRIDGE_UNREACHABLE" : "INDEX_PARTIAL",
|
|
1159
|
+
..._bridgePartial ? { index_holes: _bridgePartial.holes, index_source: _bridgePartial.source } : {},
|
|
1160
|
+
underlying: evidence.reason,
|
|
1161
|
+
need: evidence.need,
|
|
1162
|
+
visibleSats: evidence.available,
|
|
1163
|
+
reservedSats
|
|
1164
|
+
};
|
|
1142
1165
|
}
|
|
1143
1166
|
return { refused: true, ...evidence, reservedSats };
|
|
1144
1167
|
}
|
|
@@ -1597,14 +1620,27 @@ async function checkHealth() {
|
|
|
1597
1620
|
return false;
|
|
1598
1621
|
}
|
|
1599
1622
|
}
|
|
1623
|
+
function coverageFromHeaders(headers) {
|
|
1624
|
+
try {
|
|
1625
|
+
const src = headers?.get?.("x-utxo-source") || null;
|
|
1626
|
+
const holesRaw = headers?.get?.("x-utxo-holes");
|
|
1627
|
+
if (src === null && (holesRaw === null || holesRaw === void 0)) return { known: false, partial: false, source: null, holes: 0 };
|
|
1628
|
+
const holes = Number.parseInt(holesRaw || "0", 10) || 0;
|
|
1629
|
+
const partial = holes > 0 || /partial/i.test(src || "");
|
|
1630
|
+
return { known: true, partial, source: src, holes };
|
|
1631
|
+
} catch {
|
|
1632
|
+
return { known: false, partial: false, source: null, holes: 0 };
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1600
1635
|
async function getUtxos(address) {
|
|
1601
1636
|
const path = `/api/address/${address}/unspent`;
|
|
1602
1637
|
const res = await spvFetch(path);
|
|
1603
1638
|
const first = await res.json();
|
|
1639
|
+
const firstCoverage = coverageFromHeaders(res.headers);
|
|
1604
1640
|
if (Array.isArray(first) && first.length > 0) {
|
|
1605
1641
|
process.stderr.write(`[MCP] UTXOs from bridge: ${first.length}
|
|
1606
1642
|
`);
|
|
1607
|
-
return first;
|
|
1643
|
+
return withCoverage(first, firstCoverage);
|
|
1608
1644
|
}
|
|
1609
1645
|
let reached = 0;
|
|
1610
1646
|
try {
|
|
@@ -1615,8 +1651,9 @@ async function getUtxos(address) {
|
|
|
1615
1651
|
headers: { "X-API-Key": bridge.apiKey }
|
|
1616
1652
|
});
|
|
1617
1653
|
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
1618
|
-
return { name: bridge.name, utxos: await r.json() };
|
|
1654
|
+
return { name: bridge.name, utxos: await r.json(), coverage: coverageFromHeaders(r.headers) };
|
|
1619
1655
|
}));
|
|
1656
|
+
let anyPartial = null;
|
|
1620
1657
|
for (const s of settled) {
|
|
1621
1658
|
if (s.status !== "fulfilled") continue;
|
|
1622
1659
|
reached++;
|
|
@@ -1624,8 +1661,14 @@ async function getUtxos(address) {
|
|
|
1624
1661
|
if (Array.isArray(u) && u.length > 0) {
|
|
1625
1662
|
process.stderr.write(`[MCP] UTXOs recovered via fan-out from ${s.value.name}: ${u.length}
|
|
1626
1663
|
`);
|
|
1627
|
-
return u;
|
|
1664
|
+
return withCoverage(u, s.value.coverage);
|
|
1628
1665
|
}
|
|
1666
|
+
if (s.value.coverage?.known && s.value.coverage.partial) anyPartial = s.value.coverage;
|
|
1667
|
+
}
|
|
1668
|
+
if (anyPartial) {
|
|
1669
|
+
process.stderr.write(`[MCP] UTXOs: 0 across ${reached} bridge(s), but a bridge reports a PARTIAL index (holes=${anyPartial.holes})
|
|
1670
|
+
`);
|
|
1671
|
+
return withCoverage([], anyPartial);
|
|
1629
1672
|
}
|
|
1630
1673
|
} catch (e) {
|
|
1631
1674
|
process.stderr.write(`[MCP] UTXO fan-out error: ${e.message}
|
|
@@ -1633,7 +1676,7 @@ async function getUtxos(address) {
|
|
|
1633
1676
|
}
|
|
1634
1677
|
process.stderr.write(`[MCP] UTXOs: 0 across ${reached} bridge(s)
|
|
1635
1678
|
`);
|
|
1636
|
-
return Array.isArray(first) ? first : [];
|
|
1679
|
+
return withCoverage(Array.isArray(first) ? first : [], firstCoverage);
|
|
1637
1680
|
}
|
|
1638
1681
|
async function getAddressHistory(address) {
|
|
1639
1682
|
const res = await spvFetch(`/api/address/${address}/history`);
|
|
@@ -2169,7 +2212,7 @@ function extractEncryptedFromTx(tx) {
|
|
|
2169
2212
|
const match = str.match(/([A-Za-z0-9+/=]{12,}):([A-Za-z0-9+/=]{20,}):([A-Za-z0-9+/=]{20,})/);
|
|
2170
2213
|
return match ? match[0] : null;
|
|
2171
2214
|
}
|
|
2172
|
-
var SEED_BRIDGES, OLD_BRIDGE_IPS, bridgeHealth, HEALTH_CHECK_INTERVAL, MAX_FAILURES, migrationDone, SOURCE_FETCH_CONCURRENCY, ARC_NETWORK_STATUSES, StoredError, _stickyBridge, STICKY_WINDOW_MS;
|
|
2215
|
+
var SEED_BRIDGES, OLD_BRIDGE_IPS, bridgeHealth, HEALTH_CHECK_INTERVAL, MAX_FAILURES, migrationDone, withCoverage, SOURCE_FETCH_CONCURRENCY, ARC_NETWORK_STATUSES, StoredError, _stickyBridge, STICKY_WINDOW_MS;
|
|
2173
2216
|
var init_spv = __esm({
|
|
2174
2217
|
"mcp-server/lib/spv.js"() {
|
|
2175
2218
|
init_config_customer();
|
|
@@ -2196,6 +2239,13 @@ var init_spv = __esm({
|
|
|
2196
2239
|
HEALTH_CHECK_INTERVAL = 6e4;
|
|
2197
2240
|
MAX_FAILURES = 3;
|
|
2198
2241
|
migrationDone = false;
|
|
2242
|
+
withCoverage = (utxos, coverage) => {
|
|
2243
|
+
try {
|
|
2244
|
+
Object.defineProperty(utxos, "coverage", { value: coverage, enumerable: false });
|
|
2245
|
+
} catch {
|
|
2246
|
+
}
|
|
2247
|
+
return utxos;
|
|
2248
|
+
};
|
|
2199
2249
|
SOURCE_FETCH_CONCURRENCY = 8;
|
|
2200
2250
|
ARC_NETWORK_STATUSES = /* @__PURE__ */ new Set([
|
|
2201
2251
|
// Tightened 2026-06-17 to match the relay-federation bridge: a node must have
|
|
@@ -17454,7 +17504,7 @@ Answer THAT message and nothing else \u2014 the wire also carries unrelated conv
|
|
|
17454
17504
|
}
|
|
17455
17505
|
function printHelp() {
|
|
17456
17506
|
console.log(`
|
|
17457
|
-
Indelible MCP \u2014 Blockchain memory for Claude Code (v5.8.
|
|
17507
|
+
Indelible MCP \u2014 Blockchain memory for Claude Code (v5.8.2)
|
|
17458
17508
|
|
|
17459
17509
|
Setup:
|
|
17460
17510
|
indelible-mcp Set up interactively (recommended \u2014 your key is never written to shell history)
|
|
@@ -17783,7 +17833,7 @@ function readStdin() {
|
|
|
17783
17833
|
}
|
|
17784
17834
|
var SERVER_INFO = {
|
|
17785
17835
|
name: "indelible",
|
|
17786
|
-
version: "5.8.
|
|
17836
|
+
version: "5.8.2",
|
|
17787
17837
|
description: "Blockchain-backed memory and code storage for Claude Code"
|
|
17788
17838
|
};
|
|
17789
17839
|
var TOOLS = [
|