sorokeep 1.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/CONTRIBUTING.md +296 -0
- package/LICENSE +21 -0
- package/README.md +677 -0
- package/dist/alerts/alerts.d.ts +21 -0
- package/dist/alerts/alerts.d.ts.map +1 -0
- package/dist/alerts/alerts.js +18 -0
- package/dist/alerts/alerts.js.map +1 -0
- package/dist/alerts/discord.d.ts +3 -0
- package/dist/alerts/discord.d.ts.map +1 -0
- package/dist/alerts/discord.js +199 -0
- package/dist/alerts/discord.js.map +1 -0
- package/dist/alerts/dispatcher.d.ts +13 -0
- package/dist/alerts/dispatcher.d.ts.map +1 -0
- package/dist/alerts/dispatcher.js +91 -0
- package/dist/alerts/dispatcher.js.map +1 -0
- package/dist/alerts/keys.d.ts +24 -0
- package/dist/alerts/keys.d.ts.map +1 -0
- package/dist/alerts/keys.js +44 -0
- package/dist/alerts/keys.js.map +1 -0
- package/dist/alerts/pagerduty.d.ts +8 -0
- package/dist/alerts/pagerduty.d.ts.map +1 -0
- package/dist/alerts/pagerduty.js +164 -0
- package/dist/alerts/pagerduty.js.map +1 -0
- package/dist/alerts/resource.d.ts +23 -0
- package/dist/alerts/resource.d.ts.map +1 -0
- package/dist/alerts/resource.js +167 -0
- package/dist/alerts/resource.js.map +1 -0
- package/dist/alerts/slack.d.ts +7 -0
- package/dist/alerts/slack.d.ts.map +1 -0
- package/dist/alerts/slack.js +184 -0
- package/dist/alerts/slack.js.map +1 -0
- package/dist/alerts/telegram.d.ts +9 -0
- package/dist/alerts/telegram.d.ts.map +1 -0
- package/dist/alerts/telegram.js +133 -0
- package/dist/alerts/telegram.js.map +1 -0
- package/dist/alerts/templates.d.ts +109 -0
- package/dist/alerts/templates.d.ts.map +1 -0
- package/dist/alerts/templates.js +139 -0
- package/dist/alerts/templates.js.map +1 -0
- package/dist/alerts/types.d.ts +113 -0
- package/dist/alerts/types.d.ts.map +1 -0
- package/dist/alerts/types.js +87 -0
- package/dist/alerts/types.js.map +1 -0
- package/dist/alerts/webhook.d.ts +13 -0
- package/dist/alerts/webhook.d.ts.map +1 -0
- package/dist/alerts/webhook.js +56 -0
- package/dist/alerts/webhook.js.map +1 -0
- package/dist/cli/schemaFormatter.d.ts +11 -0
- package/dist/cli/schemaFormatter.d.ts.map +1 -0
- package/dist/cli/schemaFormatter.js +74 -0
- package/dist/cli/schemaFormatter.js.map +1 -0
- package/dist/commands/alerts.d.ts +3 -0
- package/dist/commands/alerts.d.ts.map +1 -0
- package/dist/commands/alerts.js +256 -0
- package/dist/commands/alerts.js.map +1 -0
- package/dist/commands/budget.d.ts +3 -0
- package/dist/commands/budget.d.ts.map +1 -0
- package/dist/commands/budget.js +47 -0
- package/dist/commands/budget.js.map +1 -0
- package/dist/commands/channels.d.ts +3 -0
- package/dist/commands/channels.d.ts.map +1 -0
- package/dist/commands/channels.js +84 -0
- package/dist/commands/channels.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +58 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/completion.d.ts +3 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +36 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/costs.d.ts +15 -0
- package/dist/commands/costs.d.ts.map +1 -0
- package/dist/commands/costs.js +280 -0
- package/dist/commands/costs.js.map +1 -0
- package/dist/commands/daemon.d.ts +3 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +93 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/db.d.ts +3 -0
- package/dist/commands/db.d.ts.map +1 -0
- package/dist/commands/db.js +140 -0
- package/dist/commands/db.js.map +1 -0
- package/dist/commands/guard.d.ts +3 -0
- package/dist/commands/guard.d.ts.map +1 -0
- package/dist/commands/guard.js +181 -0
- package/dist/commands/guard.js.map +1 -0
- package/dist/commands/history.d.ts +3 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +57 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/inspect.d.ts +3 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +82 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +20 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/pause.d.ts +3 -0
- package/dist/commands/pause.d.ts.map +1 -0
- package/dist/commands/pause.js +32 -0
- package/dist/commands/pause.js.map +1 -0
- package/dist/commands/resources.d.ts +3 -0
- package/dist/commands/resources.d.ts.map +1 -0
- package/dist/commands/resources.js +95 -0
- package/dist/commands/resources.js.map +1 -0
- package/dist/commands/restore.d.ts +3 -0
- package/dist/commands/restore.d.ts.map +1 -0
- package/dist/commands/restore.js +92 -0
- package/dist/commands/restore.js.map +1 -0
- package/dist/commands/resume.d.ts +3 -0
- package/dist/commands/resume.d.ts.map +1 -0
- package/dist/commands/resume.js +31 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +63 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/watch.d.ts +3 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +163 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/core/aws_secrets.d.ts +13 -0
- package/dist/core/aws_secrets.d.ts.map +1 -0
- package/dist/core/aws_secrets.js +34 -0
- package/dist/core/aws_secrets.js.map +1 -0
- package/dist/core/budget.d.ts +10 -0
- package/dist/core/budget.d.ts.map +1 -0
- package/dist/core/budget.js +31 -0
- package/dist/core/budget.js.map +1 -0
- package/dist/core/channels.d.ts +67 -0
- package/dist/core/channels.d.ts.map +1 -0
- package/dist/core/channels.js +136 -0
- package/dist/core/channels.js.map +1 -0
- package/dist/core/check.d.ts +25 -0
- package/dist/core/check.d.ts.map +1 -0
- package/dist/core/check.js +85 -0
- package/dist/core/check.js.map +1 -0
- package/dist/core/completion.d.ts +9 -0
- package/dist/core/completion.d.ts.map +1 -0
- package/dist/core/completion.js +68 -0
- package/dist/core/completion.js.map +1 -0
- package/dist/core/costs.d.ts +90 -0
- package/dist/core/costs.d.ts.map +1 -0
- package/dist/core/costs.js +147 -0
- package/dist/core/costs.js.map +1 -0
- package/dist/core/decoder.d.ts +7 -0
- package/dist/core/decoder.d.ts.map +1 -0
- package/dist/core/decoder.js +38 -0
- package/dist/core/decoder.js.map +1 -0
- package/dist/core/discovery.d.ts +38 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js +208 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/extension.d.ts +83 -0
- package/dist/core/extension.d.ts.map +1 -0
- package/dist/core/extension.js +429 -0
- package/dist/core/extension.js.map +1 -0
- package/dist/core/inspect.d.ts +62 -0
- package/dist/core/inspect.d.ts.map +1 -0
- package/dist/core/inspect.js +303 -0
- package/dist/core/inspect.js.map +1 -0
- package/dist/core/introspection.d.ts +8 -0
- package/dist/core/introspection.d.ts.map +1 -0
- package/dist/core/introspection.js +8 -0
- package/dist/core/introspection.js.map +1 -0
- package/dist/core/monitor.d.ts +42 -0
- package/dist/core/monitor.d.ts.map +1 -0
- package/dist/core/monitor.js +188 -0
- package/dist/core/monitor.js.map +1 -0
- package/dist/core/rent_projection.d.ts +153 -0
- package/dist/core/rent_projection.d.ts.map +1 -0
- package/dist/core/rent_projection.js +146 -0
- package/dist/core/rent_projection.js.map +1 -0
- package/dist/core/scvalTranslator.d.ts +11 -0
- package/dist/core/scvalTranslator.d.ts.map +1 -0
- package/dist/core/scvalTranslator.js +36 -0
- package/dist/core/scvalTranslator.js.map +1 -0
- package/dist/core/state_diff.d.ts +45 -0
- package/dist/core/state_diff.d.ts.map +1 -0
- package/dist/core/state_diff.js +112 -0
- package/dist/core/state_diff.js.map +1 -0
- package/dist/core/status.d.ts +24 -0
- package/dist/core/status.d.ts.map +1 -0
- package/dist/core/status.js +57 -0
- package/dist/core/status.js.map +1 -0
- package/dist/core/vault.d.ts +37 -0
- package/dist/core/vault.d.ts.map +1 -0
- package/dist/core/vault.js +179 -0
- package/dist/core/vault.js.map +1 -0
- package/dist/core/watch.d.ts +36 -0
- package/dist/core/watch.d.ts.map +1 -0
- package/dist/core/watch.js +176 -0
- package/dist/core/watch.js.map +1 -0
- package/dist/daemon/loop.d.ts +38 -0
- package/dist/daemon/loop.d.ts.map +1 -0
- package/dist/daemon/loop.js +169 -0
- package/dist/daemon/loop.js.map +1 -0
- package/dist/db/backup.d.ts +12 -0
- package/dist/db/backup.d.ts.map +1 -0
- package/dist/db/backup.js +132 -0
- package/dist/db/backup.js.map +1 -0
- package/dist/db/budget.d.ts +17 -0
- package/dist/db/budget.d.ts.map +1 -0
- package/dist/db/budget.js +31 -0
- package/dist/db/budget.js.map +1 -0
- package/dist/db/database.d.ts +6 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/database.js +134 -0
- package/dist/db/database.js.map +1 -0
- package/dist/db/migrations/.gitkeep +1 -0
- package/dist/db/migrations/001_resource_usage_logs.sql +28 -0
- package/dist/db/migrator.d.ts +28 -0
- package/dist/db/migrator.d.ts.map +1 -0
- package/dist/db/migrator.js +75 -0
- package/dist/db/migrator.js.map +1 -0
- package/dist/db/repositories.d.ts +474 -0
- package/dist/db/repositories.d.ts.map +1 -0
- package/dist/db/repositories.js +809 -0
- package/dist/db/repositories.js.map +1 -0
- package/dist/db/schema.sql +207 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +20 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +16 -0
- package/dist/lib.js.map +1 -0
- package/dist/logging/index.d.ts +22 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +34 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/logger.d.ts +14 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +135 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/types.d.ts +10 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +2 -0
- package/dist/logging/types.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +14 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +51 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/get-extension-costs.d.ts +4 -0
- package/dist/mcp/tools/get-extension-costs.d.ts.map +1 -0
- package/dist/mcp/tools/get-extension-costs.js +33 -0
- package/dist/mcp/tools/get-extension-costs.js.map +1 -0
- package/dist/mcp/tools/get_contract_status.d.ts +8 -0
- package/dist/mcp/tools/get_contract_status.d.ts.map +1 -0
- package/dist/mcp/tools/get_contract_status.js +33 -0
- package/dist/mcp/tools/get_contract_status.js.map +1 -0
- package/dist/rpc/client.d.ts +154 -0
- package/dist/rpc/client.d.ts.map +1 -0
- package/dist/rpc/client.js +766 -0
- package/dist/rpc/client.js.map +1 -0
- package/dist/utils/config.d.ts +51 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +86 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/formatting.d.ts +10 -0
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/utils/formatting.js +66 -0
- package/dist/utils/formatting.js.map +1 -0
- package/dist/utils/watch-config.d.ts +13 -0
- package/dist/utils/watch-config.d.ts.map +1 -0
- package/dist/utils/watch-config.js +32 -0
- package/dist/utils/watch-config.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { StellarRpcClient } from "../rpc/client.js";
|
|
2
|
+
import { getAllContracts, getContract, getEntriesForContract, getExtensionPolicy, getChannelAccounts, recordExtension, upsertEntry, updateLastCheckedLedger, getAverageResourceUsage, getBudget, addBudgetSpent, countExtensionsInLastHour, } from "../db/repositories.js";
|
|
3
|
+
import { ChannelAccountPool } from "./channels.js";
|
|
4
|
+
import { getLogger } from "../logging/index.js";
|
|
5
|
+
import { formatSecretKey } from "../utils/formatting.js";
|
|
6
|
+
import { VaultResolver } from "./vault.js";
|
|
7
|
+
import { loadConfig } from "../utils/config.js";
|
|
8
|
+
const logger = getLogger().child({ component: "Extension" });
|
|
9
|
+
// ─── Rate limiter ─────────────────────────────────────────────────────────────
|
|
10
|
+
/**
|
|
11
|
+
* Maximum number of auto-extension transactions allowed per contract per hour.
|
|
12
|
+
* Prevents runaway fee submissions under extreme network load (issue #142).
|
|
13
|
+
*/
|
|
14
|
+
export const HOURLY_RATE_LIMIT = 5;
|
|
15
|
+
/**
|
|
16
|
+
* Check whether the given contract has reached its hourly auto-extension rate limit.
|
|
17
|
+
*
|
|
18
|
+
* Queries `extension_history` for records within the last 60 minutes and
|
|
19
|
+
* compares the count against `limit` (default: HOURLY_RATE_LIMIT).
|
|
20
|
+
*
|
|
21
|
+
* @param db - The SQLite database connection.
|
|
22
|
+
* @param contractId - The contract to check.
|
|
23
|
+
* @param limit - Maximum allowed extensions per hour (defaults to HOURLY_RATE_LIMIT).
|
|
24
|
+
* @returns `true` when the contract is rate-limited; `false` otherwise.
|
|
25
|
+
*/
|
|
26
|
+
export function isRateLimited(db, contractId, limit = HOURLY_RATE_LIMIT) {
|
|
27
|
+
const count = countExtensionsInLastHour(db, contractId);
|
|
28
|
+
return count >= limit;
|
|
29
|
+
}
|
|
30
|
+
export async function simulateExtension(db, contractId, entryKeyXdrs, extendToLedgers, sourcePublicKey, rpcUrl) {
|
|
31
|
+
const contract = getContract(db, contractId);
|
|
32
|
+
if (!contract) {
|
|
33
|
+
return { success: false, contractId, entriesExtended: 0, error: "Contract not found" };
|
|
34
|
+
}
|
|
35
|
+
const client = new StellarRpcClient(contract.network, rpcUrl);
|
|
36
|
+
let sim;
|
|
37
|
+
try {
|
|
38
|
+
sim = await client.simulateExtension(entryKeyXdrs, extendToLedgers, sourcePublicKey);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
logger.warn(`Simulation warning for ${contractId}: ${err.message}`);
|
|
42
|
+
return {
|
|
43
|
+
success: false,
|
|
44
|
+
contractId,
|
|
45
|
+
entriesExtended: 0,
|
|
46
|
+
error: err.message,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
success: true,
|
|
51
|
+
contractId,
|
|
52
|
+
entriesExtended: entryKeyXdrs.length,
|
|
53
|
+
estimatedFee: sim.minResourceFee,
|
|
54
|
+
cpuInsns: sim.cpuInstructions,
|
|
55
|
+
memBytes: sim.memoryBytes,
|
|
56
|
+
readBytes: sim.readBytes,
|
|
57
|
+
writeBytes: sim.writeBytes,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export async function extendEntries(db, contractId, entryKeyXdrs, extendToLedgers, secretKey, rpcUrl, sponsorSecret) {
|
|
61
|
+
const contract = getContract(db, contractId);
|
|
62
|
+
if (!contract) {
|
|
63
|
+
return { success: false, contractId, entriesExtended: 0, error: "Contract not found" };
|
|
64
|
+
}
|
|
65
|
+
if (entryKeyXdrs.length === 0) {
|
|
66
|
+
return { success: false, contractId, entriesExtended: 0, error: "No entries to extend" };
|
|
67
|
+
}
|
|
68
|
+
const client = new StellarRpcClient(contract.network, rpcUrl);
|
|
69
|
+
logger.info(`Extending ${entryKeyXdrs.length} entries for ${contractId} to ${extendToLedgers} ledgers`);
|
|
70
|
+
const resolvedSponsorSecret = sponsorSecret ? await resolveSecretKey(sponsorSecret) : undefined;
|
|
71
|
+
if (sponsorSecret && !resolvedSponsorSecret) {
|
|
72
|
+
return {
|
|
73
|
+
success: false,
|
|
74
|
+
contractId,
|
|
75
|
+
entriesExtended: 0,
|
|
76
|
+
error: `Failed to resolve sponsor secret key from environment variable: ${sponsorSecret}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
let txResult;
|
|
80
|
+
try {
|
|
81
|
+
txResult = resolvedSponsorSecret
|
|
82
|
+
? await client.submitExtensionWithFeeBump(entryKeyXdrs, extendToLedgers, secretKey, resolvedSponsorSecret)
|
|
83
|
+
: await client.submitExtension(entryKeyXdrs, extendToLedgers, secretKey);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
logger.warn(`Simulation warning for ${contractId}: ${err.message}`);
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
contractId,
|
|
90
|
+
entriesExtended: 0,
|
|
91
|
+
error: err.message,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (!txResult.success) {
|
|
95
|
+
logger.error(`Extension failed for ${contractId}: ${txResult.error}`);
|
|
96
|
+
return {
|
|
97
|
+
success: false,
|
|
98
|
+
contractId,
|
|
99
|
+
entriesExtended: 0,
|
|
100
|
+
txHash: txResult.txHash || undefined,
|
|
101
|
+
error: txResult.error,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
let isAnomaly = false;
|
|
105
|
+
let anomalyDetails = undefined;
|
|
106
|
+
if (txResult.cpuInsns && txResult.memBytes) {
|
|
107
|
+
const baseline = getAverageResourceUsage(db, contractId, 10);
|
|
108
|
+
if (baseline && baseline.avg_cpu_insns > 0 && baseline.avg_mem_bytes > 0) {
|
|
109
|
+
const cpuRatio = txResult.cpuInsns / baseline.avg_cpu_insns;
|
|
110
|
+
const memRatio = txResult.memBytes / baseline.avg_mem_bytes;
|
|
111
|
+
if (cpuRatio >= 2.0 || memRatio >= 2.0) {
|
|
112
|
+
isAnomaly = true;
|
|
113
|
+
const details = [];
|
|
114
|
+
if (cpuRatio >= 2.0)
|
|
115
|
+
details.push(`CPU usage is ${cpuRatio.toFixed(2)}x baseline`);
|
|
116
|
+
if (memRatio >= 2.0)
|
|
117
|
+
details.push(`Memory usage is ${memRatio.toFixed(2)}x baseline`);
|
|
118
|
+
anomalyDetails = `Resource anomaly detected: ` + details.join(", ");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const freshTTLs = await client.getEntryTTLs(entryKeyXdrs);
|
|
123
|
+
const entries = getEntriesForContract(db, contractId);
|
|
124
|
+
const entryMap = new Map(entries.map(e => [e.entry_key_xdr, e]));
|
|
125
|
+
const updateDb = db.transaction(() => {
|
|
126
|
+
for (const freshEntry of freshTTLs.entries) {
|
|
127
|
+
const dbEntry = entryMap.get(freshEntry.entryKeyXdr);
|
|
128
|
+
if (!dbEntry)
|
|
129
|
+
continue;
|
|
130
|
+
const oldTTL = dbEntry.live_until_ledger
|
|
131
|
+
? dbEntry.live_until_ledger - freshTTLs.latestLedger
|
|
132
|
+
: 0;
|
|
133
|
+
recordExtension(db, {
|
|
134
|
+
contract_id: contractId,
|
|
135
|
+
contract_entry_id: dbEntry.id,
|
|
136
|
+
old_ttl_ledgers: Math.max(0, oldTTL),
|
|
137
|
+
new_ttl_ledgers: freshEntry.remainingTTL,
|
|
138
|
+
tx_hash: txResult.txHash,
|
|
139
|
+
cpu_insns: txResult.cpuInsns,
|
|
140
|
+
mem_bytes: txResult.memBytes,
|
|
141
|
+
is_anomaly: isAnomaly,
|
|
142
|
+
executed_at_ledger: freshTTLs.latestLedger,
|
|
143
|
+
});
|
|
144
|
+
upsertEntry(db, {
|
|
145
|
+
contract_id: contractId,
|
|
146
|
+
entry_key_xdr: freshEntry.entryKeyXdr,
|
|
147
|
+
entry_type: dbEntry.entry_type,
|
|
148
|
+
label: dbEntry.label ?? undefined,
|
|
149
|
+
live_until_ledger: freshEntry.liveUntilLedgerSeq,
|
|
150
|
+
last_modified_ledger: freshEntry.lastModifiedLedgerSeq,
|
|
151
|
+
discovery_source: dbEntry.discovery_source,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
updateLastCheckedLedger(db, contractId, freshTTLs.latestLedger);
|
|
155
|
+
});
|
|
156
|
+
updateDb();
|
|
157
|
+
return {
|
|
158
|
+
success: true,
|
|
159
|
+
contractId,
|
|
160
|
+
entriesExtended: entryKeyXdrs.length,
|
|
161
|
+
txHash: txResult.txHash,
|
|
162
|
+
ledger: txResult.ledger,
|
|
163
|
+
feeCharged: txResult.feeCharged,
|
|
164
|
+
cpuInsns: txResult.cpuInsns,
|
|
165
|
+
memBytes: txResult.memBytes,
|
|
166
|
+
isAnomaly,
|
|
167
|
+
anomalyDetails,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export async function runAutoExtensions(db, network, rpcUrl, sponsorSecret) {
|
|
171
|
+
const result = {
|
|
172
|
+
contractsChecked: 0,
|
|
173
|
+
contractsExtended: 0,
|
|
174
|
+
entriesExtended: 0,
|
|
175
|
+
errors: [],
|
|
176
|
+
extensions: [],
|
|
177
|
+
};
|
|
178
|
+
const contracts = getAllContracts(db).filter(c => c.network === network);
|
|
179
|
+
const eligibleContracts = contracts.filter(c => {
|
|
180
|
+
const p = getExtensionPolicy(db, c.id);
|
|
181
|
+
return p && p.enabled;
|
|
182
|
+
});
|
|
183
|
+
if (eligibleContracts.length === 0)
|
|
184
|
+
return result;
|
|
185
|
+
const client = new StellarRpcClient(network, rpcUrl);
|
|
186
|
+
const latestLedger = await client.getCurrentLedger();
|
|
187
|
+
const channelAccounts = getChannelAccounts(db, network);
|
|
188
|
+
const pool = channelAccounts.length > 0
|
|
189
|
+
? new ChannelAccountPool(db, network)
|
|
190
|
+
: null;
|
|
191
|
+
result.contractsChecked = eligibleContracts.length;
|
|
192
|
+
await Promise.all(eligibleContracts.map(async (contract) => {
|
|
193
|
+
const policy = getExtensionPolicy(db, contract.id);
|
|
194
|
+
try {
|
|
195
|
+
const entries = getEntriesForContract(db, contract.id);
|
|
196
|
+
const needsExtension = entries.filter(e => {
|
|
197
|
+
if (!e.live_until_ledger)
|
|
198
|
+
return false;
|
|
199
|
+
const remaining = e.live_until_ledger - latestLedger;
|
|
200
|
+
return remaining >= 0 && remaining < policy.extend_when_below_ledgers;
|
|
201
|
+
});
|
|
202
|
+
if (needsExtension.length === 0)
|
|
203
|
+
return;
|
|
204
|
+
// ── Rate limit check (issue #142) ────────────────────────────────
|
|
205
|
+
// Block auto-extension if the contract has already hit the maximum
|
|
206
|
+
// number of extension transactions allowed per hour.
|
|
207
|
+
if (isRateLimited(db, contract.id)) {
|
|
208
|
+
const count = countExtensionsInLastHour(db, contract.id);
|
|
209
|
+
const msg = `Contract ${contract.id}: rate limit reached — ${count}/${HOURLY_RATE_LIMIT} extensions in the last hour. Skipping.`;
|
|
210
|
+
logger.warn(msg);
|
|
211
|
+
result.errors.push(msg);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
// Resolve secret key: prefer channel pool, fall back to policy keypair
|
|
215
|
+
let secretKey = null;
|
|
216
|
+
let slot = null;
|
|
217
|
+
if (pool) {
|
|
218
|
+
slot = await pool.acquire();
|
|
219
|
+
secretKey = await resolveSecretKey(slot.keypairSource);
|
|
220
|
+
if (!secretKey) {
|
|
221
|
+
pool.release(slot.publicKey);
|
|
222
|
+
slot = null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!secretKey) {
|
|
226
|
+
secretKey = await resolveSecretKey(policy.keypair_source);
|
|
227
|
+
}
|
|
228
|
+
if (!secretKey) {
|
|
229
|
+
result.errors.push(`Contract ${contract.id}: Cannot resolve keypair from source "${pool ? "channel pool" : formatSecretKey(policy.keypair_source)}"`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const entryKeys = needsExtension.map(e => e.entry_key_xdr);
|
|
233
|
+
logger.info(`Auto-extending ${entryKeys.length} entries for ${contract.id} ` +
|
|
234
|
+
`(below ${policy.extend_when_below_ledgers}, target ${policy.target_ttl_ledgers})`);
|
|
235
|
+
try {
|
|
236
|
+
const billingCycle = new Date().toISOString().slice(0, 7);
|
|
237
|
+
const budget = getBudget(db, contract.id, billingCycle);
|
|
238
|
+
let estimatedFeeXlm = 0;
|
|
239
|
+
if (budget) {
|
|
240
|
+
const { Keypair } = await import("@stellar/stellar-sdk");
|
|
241
|
+
const pubKey = Keypair.fromSecret(secretKey).publicKey();
|
|
242
|
+
const simResult = await simulateExtension(db, contract.id, entryKeys, policy.target_ttl_ledgers, pubKey, rpcUrl);
|
|
243
|
+
if (!simResult.success) {
|
|
244
|
+
throw new Error(`Simulation failed: ${simResult.error}`);
|
|
245
|
+
}
|
|
246
|
+
estimatedFeeXlm = (simResult.estimatedFee || 0) / 10000000;
|
|
247
|
+
if (budget.spent_xlm + estimatedFeeXlm > budget.limit_xlm) {
|
|
248
|
+
throw new Error(`budget limit exceeded. Estimated cost: ${estimatedFeeXlm} XLM, Remaining: ${budget.limit_xlm - budget.spent_xlm} XLM`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const extResult = await extendEntries(db, contract.id, entryKeys, policy.target_ttl_ledgers, secretKey, rpcUrl, sponsorSecret);
|
|
252
|
+
if (extResult.success) {
|
|
253
|
+
if (budget && estimatedFeeXlm > 0) {
|
|
254
|
+
const actualFeeXlm = extResult.feeCharged !== undefined ? extResult.feeCharged / 10000000 : estimatedFeeXlm;
|
|
255
|
+
addBudgetSpent(db, contract.id, billingCycle, actualFeeXlm);
|
|
256
|
+
}
|
|
257
|
+
if (!extResult.txHash || extResult.ledger == null) {
|
|
258
|
+
result.errors.push(`Contract ${contract.id}: Extension succeeded but RPC returned no txHash or ledger`);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
result.contractsExtended++;
|
|
262
|
+
result.entriesExtended += extResult.entriesExtended;
|
|
263
|
+
result.extensions.push({
|
|
264
|
+
contractId: contract.id,
|
|
265
|
+
txHash: extResult.txHash,
|
|
266
|
+
entriesExtended: extResult.entriesExtended,
|
|
267
|
+
ledger: extResult.ledger,
|
|
268
|
+
isAnomaly: extResult.isAnomaly,
|
|
269
|
+
anomalyDetails: extResult.anomalyDetails,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
result.errors.push(`Contract ${contract.id}: Extension failed — ${extResult.error}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
finally {
|
|
278
|
+
if (slot && pool)
|
|
279
|
+
pool.release(slot.publicKey);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
284
|
+
result.errors.push(`Contract ${contract.id}: ${message}`);
|
|
285
|
+
logger.error(`Auto-extension error for ${contract.id}: ${message}`, err);
|
|
286
|
+
}
|
|
287
|
+
}));
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
export async function simulateRestore(db, contractId, entryKeyXdrs, sourcePublicKey, rpcUrl) {
|
|
291
|
+
const contract = getContract(db, contractId);
|
|
292
|
+
if (!contract) {
|
|
293
|
+
return { success: false, contractId, entriesRestored: 0, error: "Contract not found" };
|
|
294
|
+
}
|
|
295
|
+
const client = new StellarRpcClient(contract.network, rpcUrl);
|
|
296
|
+
const sim = await client.simulateRestore(entryKeyXdrs, sourcePublicKey);
|
|
297
|
+
if (!sim.success) {
|
|
298
|
+
return { success: false, contractId, entriesRestored: 0, error: sim.error };
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
success: true,
|
|
302
|
+
contractId,
|
|
303
|
+
entriesRestored: entryKeyXdrs.length,
|
|
304
|
+
estimatedFee: sim.minResourceFee,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
export async function restoreEntries(db, contractId, entryKeyXdrs, secretKey, rpcUrl) {
|
|
308
|
+
const contract = getContract(db, contractId);
|
|
309
|
+
if (!contract) {
|
|
310
|
+
return { success: false, contractId, entriesRestored: 0, error: "Contract not found" };
|
|
311
|
+
}
|
|
312
|
+
if (entryKeyXdrs.length === 0) {
|
|
313
|
+
return { success: false, contractId, entriesRestored: 0, error: "No entries to restore" };
|
|
314
|
+
}
|
|
315
|
+
const client = new StellarRpcClient(contract.network, rpcUrl);
|
|
316
|
+
logger.info(`Restoring ${entryKeyXdrs.length} entries for ${contractId}`);
|
|
317
|
+
let txResult;
|
|
318
|
+
try {
|
|
319
|
+
txResult = await client.submitRestore(entryKeyXdrs, secretKey);
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
logger.warn(`Simulation warning for ${contractId}: ${err.message}`);
|
|
323
|
+
return {
|
|
324
|
+
success: false,
|
|
325
|
+
contractId,
|
|
326
|
+
entriesRestored: 0,
|
|
327
|
+
error: err.message,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
if (!txResult.success) {
|
|
331
|
+
logger.error(`Restore failed for ${contractId}: ${txResult.error}`);
|
|
332
|
+
return {
|
|
333
|
+
success: false,
|
|
334
|
+
contractId,
|
|
335
|
+
entriesRestored: 0,
|
|
336
|
+
txHash: txResult.txHash || undefined,
|
|
337
|
+
error: txResult.error,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
const freshTTLs = await client.getEntryTTLs(entryKeyXdrs);
|
|
341
|
+
const entries = getEntriesForContract(db, contractId);
|
|
342
|
+
const entryMap = new Map(entries.map(e => [e.entry_key_xdr, e]));
|
|
343
|
+
let restored = 0;
|
|
344
|
+
const updateDb = db.transaction(() => {
|
|
345
|
+
for (const freshEntry of freshTTLs.entries) {
|
|
346
|
+
const dbEntry = entryMap.get(freshEntry.entryKeyXdr);
|
|
347
|
+
if (!dbEntry)
|
|
348
|
+
continue;
|
|
349
|
+
upsertEntry(db, {
|
|
350
|
+
contract_id: contractId,
|
|
351
|
+
entry_key_xdr: freshEntry.entryKeyXdr,
|
|
352
|
+
entry_type: dbEntry.entry_type,
|
|
353
|
+
label: dbEntry.label ?? undefined,
|
|
354
|
+
live_until_ledger: freshEntry.liveUntilLedgerSeq,
|
|
355
|
+
last_modified_ledger: freshEntry.lastModifiedLedgerSeq,
|
|
356
|
+
discovery_source: dbEntry.discovery_source,
|
|
357
|
+
});
|
|
358
|
+
restored++;
|
|
359
|
+
}
|
|
360
|
+
updateLastCheckedLedger(db, contractId, freshTTLs.latestLedger);
|
|
361
|
+
});
|
|
362
|
+
updateDb();
|
|
363
|
+
logger.info(`Restore successful for ${contractId}: tx=${txResult.txHash}, entries=${restored}`);
|
|
364
|
+
return {
|
|
365
|
+
success: true,
|
|
366
|
+
contractId,
|
|
367
|
+
entriesRestored: restored,
|
|
368
|
+
txHash: txResult.txHash,
|
|
369
|
+
ledger: txResult.ledger,
|
|
370
|
+
cpuInsns: txResult.cpuInsns,
|
|
371
|
+
memBytes: txResult.memBytes,
|
|
372
|
+
minResourceFee: txResult.minResourceFee,
|
|
373
|
+
feeCharged: txResult.feeCharged,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
// ─── Private helpers ──────────────────────────────────────────────────────────
|
|
377
|
+
/**
|
|
378
|
+
* Resolve a secret key from a keypair_source string.
|
|
379
|
+
* Supports:
|
|
380
|
+
* - "env:VAR_NAME" — reads from environment variable
|
|
381
|
+
* - "vault:<secret_path>" — reads from HashiCorp Vault (KV v1/v2)
|
|
382
|
+
* - Direct secret key string starting with "S" (56 chars)
|
|
383
|
+
*/
|
|
384
|
+
export async function resolveSecretKey(source) {
|
|
385
|
+
if (!source)
|
|
386
|
+
return null;
|
|
387
|
+
if (source.startsWith("env:")) {
|
|
388
|
+
const envVar = source.slice(4);
|
|
389
|
+
const value = process.env[envVar];
|
|
390
|
+
if (!value) {
|
|
391
|
+
logger.warn(`Environment variable ${envVar} not set`);
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
return value;
|
|
395
|
+
}
|
|
396
|
+
if (source.startsWith("vault:")) {
|
|
397
|
+
const vaultPath = source.slice(6);
|
|
398
|
+
if (!vaultPath) {
|
|
399
|
+
logger.warn("Vault keypair_source is empty");
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
try {
|
|
403
|
+
const config = loadConfig();
|
|
404
|
+
if (!config.vault?.url || !config.vault?.token) {
|
|
405
|
+
logger.error("Vault resolver requested but vault configuration missing in config.yaml (vault.url / vault.token)");
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
const resolver = new VaultResolver({
|
|
409
|
+
url: config.vault.url,
|
|
410
|
+
token: config.vault.token,
|
|
411
|
+
namespace: config.vault.namespace,
|
|
412
|
+
});
|
|
413
|
+
const secret = await resolver.getSecret(vaultPath);
|
|
414
|
+
return secret;
|
|
415
|
+
}
|
|
416
|
+
catch (err) {
|
|
417
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
418
|
+
logger.error(`Failed to resolve secret from Vault path "${vaultPath}": ${message}`);
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
// Direct secret key
|
|
423
|
+
if (source.startsWith("S") && source.length === 56) {
|
|
424
|
+
return source;
|
|
425
|
+
}
|
|
426
|
+
logger.warn(`Unknown keypair_source format: ${formatSecretKey(source)}`);
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
//# sourceMappingURL=extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../../src/core/extension.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { xdr } from "@stellar/stellar-sdk";
|
|
3
|
+
export interface InspectOptions {
|
|
4
|
+
entries?: string[];
|
|
5
|
+
network?: string;
|
|
6
|
+
rpcUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DecodedScVal {
|
|
9
|
+
type: string;
|
|
10
|
+
value: any;
|
|
11
|
+
}
|
|
12
|
+
export interface InspectEntryInfo {
|
|
13
|
+
inputEntry: string;
|
|
14
|
+
entryKeyXdr: string;
|
|
15
|
+
type: "balance" | "raw";
|
|
16
|
+
found: boolean;
|
|
17
|
+
remainingTTL?: number | null;
|
|
18
|
+
approximateTimeRemaining?: string | null;
|
|
19
|
+
status?: string;
|
|
20
|
+
balance?: {
|
|
21
|
+
amount: bigint;
|
|
22
|
+
authorized: boolean;
|
|
23
|
+
clawback: boolean;
|
|
24
|
+
};
|
|
25
|
+
formattedBalance?: string;
|
|
26
|
+
decodedValue?: DecodedScVal;
|
|
27
|
+
}
|
|
28
|
+
export interface InspectResult {
|
|
29
|
+
success: boolean;
|
|
30
|
+
contractId: string;
|
|
31
|
+
contractName?: string | null;
|
|
32
|
+
network?: string;
|
|
33
|
+
isSac?: boolean;
|
|
34
|
+
decimals?: number;
|
|
35
|
+
results?: InspectEntryInfo[];
|
|
36
|
+
error?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Format token balance in stroops/raw units to string representation with decimals.
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatTokenBalance(amount: bigint | number | string, decimals: number): string;
|
|
42
|
+
/**
|
|
43
|
+
* Custom parser for SAC balance map layout.
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseSacBalance(scVal: xdr.ScVal | string): {
|
|
46
|
+
amount: bigint;
|
|
47
|
+
authorized: boolean;
|
|
48
|
+
clawback: boolean;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Build storage key XDR for a SAC address balance entry.
|
|
52
|
+
*/
|
|
53
|
+
export declare function buildSacBalanceKeyXdr(contractId: string, address: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Inspect contract storage and token balances on SAC contracts.
|
|
56
|
+
*/
|
|
57
|
+
export declare function inspectContract(db: Database.Database, contractId: string, options?: InspectOptions): Promise<InspectResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Decode a base64 XDR ScVal string into a JSON-friendly structure.
|
|
60
|
+
*/
|
|
61
|
+
export declare function decodeScVal(scValBase64: string): DecodedScVal;
|
|
62
|
+
//# sourceMappingURL=inspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/core/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAkC,MAAM,sBAAsB,CAAC;AAQ3E,MAAM,WAAW,cAAc;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,OAAO,CAAC;QACpB,QAAQ,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiB7F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAgCrH;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAwBjF;AAED;;GAEG;AACH,wBAAsB,eAAe,CACjC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,cAAmB,GAC7B,OAAO,CAAC,aAAa,CAAC,CAuJxB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAO7D"}
|