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.
Files changed (275) hide show
  1. package/CONTRIBUTING.md +296 -0
  2. package/LICENSE +21 -0
  3. package/README.md +677 -0
  4. package/dist/alerts/alerts.d.ts +21 -0
  5. package/dist/alerts/alerts.d.ts.map +1 -0
  6. package/dist/alerts/alerts.js +18 -0
  7. package/dist/alerts/alerts.js.map +1 -0
  8. package/dist/alerts/discord.d.ts +3 -0
  9. package/dist/alerts/discord.d.ts.map +1 -0
  10. package/dist/alerts/discord.js +199 -0
  11. package/dist/alerts/discord.js.map +1 -0
  12. package/dist/alerts/dispatcher.d.ts +13 -0
  13. package/dist/alerts/dispatcher.d.ts.map +1 -0
  14. package/dist/alerts/dispatcher.js +91 -0
  15. package/dist/alerts/dispatcher.js.map +1 -0
  16. package/dist/alerts/keys.d.ts +24 -0
  17. package/dist/alerts/keys.d.ts.map +1 -0
  18. package/dist/alerts/keys.js +44 -0
  19. package/dist/alerts/keys.js.map +1 -0
  20. package/dist/alerts/pagerduty.d.ts +8 -0
  21. package/dist/alerts/pagerduty.d.ts.map +1 -0
  22. package/dist/alerts/pagerduty.js +164 -0
  23. package/dist/alerts/pagerduty.js.map +1 -0
  24. package/dist/alerts/resource.d.ts +23 -0
  25. package/dist/alerts/resource.d.ts.map +1 -0
  26. package/dist/alerts/resource.js +167 -0
  27. package/dist/alerts/resource.js.map +1 -0
  28. package/dist/alerts/slack.d.ts +7 -0
  29. package/dist/alerts/slack.d.ts.map +1 -0
  30. package/dist/alerts/slack.js +184 -0
  31. package/dist/alerts/slack.js.map +1 -0
  32. package/dist/alerts/telegram.d.ts +9 -0
  33. package/dist/alerts/telegram.d.ts.map +1 -0
  34. package/dist/alerts/telegram.js +133 -0
  35. package/dist/alerts/telegram.js.map +1 -0
  36. package/dist/alerts/templates.d.ts +109 -0
  37. package/dist/alerts/templates.d.ts.map +1 -0
  38. package/dist/alerts/templates.js +139 -0
  39. package/dist/alerts/templates.js.map +1 -0
  40. package/dist/alerts/types.d.ts +113 -0
  41. package/dist/alerts/types.d.ts.map +1 -0
  42. package/dist/alerts/types.js +87 -0
  43. package/dist/alerts/types.js.map +1 -0
  44. package/dist/alerts/webhook.d.ts +13 -0
  45. package/dist/alerts/webhook.d.ts.map +1 -0
  46. package/dist/alerts/webhook.js +56 -0
  47. package/dist/alerts/webhook.js.map +1 -0
  48. package/dist/cli/schemaFormatter.d.ts +11 -0
  49. package/dist/cli/schemaFormatter.d.ts.map +1 -0
  50. package/dist/cli/schemaFormatter.js +74 -0
  51. package/dist/cli/schemaFormatter.js.map +1 -0
  52. package/dist/commands/alerts.d.ts +3 -0
  53. package/dist/commands/alerts.d.ts.map +1 -0
  54. package/dist/commands/alerts.js +256 -0
  55. package/dist/commands/alerts.js.map +1 -0
  56. package/dist/commands/budget.d.ts +3 -0
  57. package/dist/commands/budget.d.ts.map +1 -0
  58. package/dist/commands/budget.js +47 -0
  59. package/dist/commands/budget.js.map +1 -0
  60. package/dist/commands/channels.d.ts +3 -0
  61. package/dist/commands/channels.d.ts.map +1 -0
  62. package/dist/commands/channels.js +84 -0
  63. package/dist/commands/channels.js.map +1 -0
  64. package/dist/commands/check.d.ts +3 -0
  65. package/dist/commands/check.d.ts.map +1 -0
  66. package/dist/commands/check.js +58 -0
  67. package/dist/commands/check.js.map +1 -0
  68. package/dist/commands/completion.d.ts +3 -0
  69. package/dist/commands/completion.d.ts.map +1 -0
  70. package/dist/commands/completion.js +36 -0
  71. package/dist/commands/completion.js.map +1 -0
  72. package/dist/commands/costs.d.ts +15 -0
  73. package/dist/commands/costs.d.ts.map +1 -0
  74. package/dist/commands/costs.js +280 -0
  75. package/dist/commands/costs.js.map +1 -0
  76. package/dist/commands/daemon.d.ts +3 -0
  77. package/dist/commands/daemon.d.ts.map +1 -0
  78. package/dist/commands/daemon.js +93 -0
  79. package/dist/commands/daemon.js.map +1 -0
  80. package/dist/commands/db.d.ts +3 -0
  81. package/dist/commands/db.d.ts.map +1 -0
  82. package/dist/commands/db.js +140 -0
  83. package/dist/commands/db.js.map +1 -0
  84. package/dist/commands/guard.d.ts +3 -0
  85. package/dist/commands/guard.d.ts.map +1 -0
  86. package/dist/commands/guard.js +181 -0
  87. package/dist/commands/guard.js.map +1 -0
  88. package/dist/commands/history.d.ts +3 -0
  89. package/dist/commands/history.d.ts.map +1 -0
  90. package/dist/commands/history.js +57 -0
  91. package/dist/commands/history.js.map +1 -0
  92. package/dist/commands/inspect.d.ts +3 -0
  93. package/dist/commands/inspect.d.ts.map +1 -0
  94. package/dist/commands/inspect.js +82 -0
  95. package/dist/commands/inspect.js.map +1 -0
  96. package/dist/commands/mcp.d.ts +3 -0
  97. package/dist/commands/mcp.d.ts.map +1 -0
  98. package/dist/commands/mcp.js +20 -0
  99. package/dist/commands/mcp.js.map +1 -0
  100. package/dist/commands/pause.d.ts +3 -0
  101. package/dist/commands/pause.d.ts.map +1 -0
  102. package/dist/commands/pause.js +32 -0
  103. package/dist/commands/pause.js.map +1 -0
  104. package/dist/commands/resources.d.ts +3 -0
  105. package/dist/commands/resources.d.ts.map +1 -0
  106. package/dist/commands/resources.js +95 -0
  107. package/dist/commands/resources.js.map +1 -0
  108. package/dist/commands/restore.d.ts +3 -0
  109. package/dist/commands/restore.d.ts.map +1 -0
  110. package/dist/commands/restore.js +92 -0
  111. package/dist/commands/restore.js.map +1 -0
  112. package/dist/commands/resume.d.ts +3 -0
  113. package/dist/commands/resume.d.ts.map +1 -0
  114. package/dist/commands/resume.js +31 -0
  115. package/dist/commands/resume.js.map +1 -0
  116. package/dist/commands/status.d.ts +3 -0
  117. package/dist/commands/status.d.ts.map +1 -0
  118. package/dist/commands/status.js +63 -0
  119. package/dist/commands/status.js.map +1 -0
  120. package/dist/commands/watch.d.ts +3 -0
  121. package/dist/commands/watch.d.ts.map +1 -0
  122. package/dist/commands/watch.js +163 -0
  123. package/dist/commands/watch.js.map +1 -0
  124. package/dist/core/aws_secrets.d.ts +13 -0
  125. package/dist/core/aws_secrets.d.ts.map +1 -0
  126. package/dist/core/aws_secrets.js +34 -0
  127. package/dist/core/aws_secrets.js.map +1 -0
  128. package/dist/core/budget.d.ts +10 -0
  129. package/dist/core/budget.d.ts.map +1 -0
  130. package/dist/core/budget.js +31 -0
  131. package/dist/core/budget.js.map +1 -0
  132. package/dist/core/channels.d.ts +67 -0
  133. package/dist/core/channels.d.ts.map +1 -0
  134. package/dist/core/channels.js +136 -0
  135. package/dist/core/channels.js.map +1 -0
  136. package/dist/core/check.d.ts +25 -0
  137. package/dist/core/check.d.ts.map +1 -0
  138. package/dist/core/check.js +85 -0
  139. package/dist/core/check.js.map +1 -0
  140. package/dist/core/completion.d.ts +9 -0
  141. package/dist/core/completion.d.ts.map +1 -0
  142. package/dist/core/completion.js +68 -0
  143. package/dist/core/completion.js.map +1 -0
  144. package/dist/core/costs.d.ts +90 -0
  145. package/dist/core/costs.d.ts.map +1 -0
  146. package/dist/core/costs.js +147 -0
  147. package/dist/core/costs.js.map +1 -0
  148. package/dist/core/decoder.d.ts +7 -0
  149. package/dist/core/decoder.d.ts.map +1 -0
  150. package/dist/core/decoder.js +38 -0
  151. package/dist/core/decoder.js.map +1 -0
  152. package/dist/core/discovery.d.ts +38 -0
  153. package/dist/core/discovery.d.ts.map +1 -0
  154. package/dist/core/discovery.js +208 -0
  155. package/dist/core/discovery.js.map +1 -0
  156. package/dist/core/extension.d.ts +83 -0
  157. package/dist/core/extension.d.ts.map +1 -0
  158. package/dist/core/extension.js +429 -0
  159. package/dist/core/extension.js.map +1 -0
  160. package/dist/core/inspect.d.ts +62 -0
  161. package/dist/core/inspect.d.ts.map +1 -0
  162. package/dist/core/inspect.js +303 -0
  163. package/dist/core/inspect.js.map +1 -0
  164. package/dist/core/introspection.d.ts +8 -0
  165. package/dist/core/introspection.d.ts.map +1 -0
  166. package/dist/core/introspection.js +8 -0
  167. package/dist/core/introspection.js.map +1 -0
  168. package/dist/core/monitor.d.ts +42 -0
  169. package/dist/core/monitor.d.ts.map +1 -0
  170. package/dist/core/monitor.js +188 -0
  171. package/dist/core/monitor.js.map +1 -0
  172. package/dist/core/rent_projection.d.ts +153 -0
  173. package/dist/core/rent_projection.d.ts.map +1 -0
  174. package/dist/core/rent_projection.js +146 -0
  175. package/dist/core/rent_projection.js.map +1 -0
  176. package/dist/core/scvalTranslator.d.ts +11 -0
  177. package/dist/core/scvalTranslator.d.ts.map +1 -0
  178. package/dist/core/scvalTranslator.js +36 -0
  179. package/dist/core/scvalTranslator.js.map +1 -0
  180. package/dist/core/state_diff.d.ts +45 -0
  181. package/dist/core/state_diff.d.ts.map +1 -0
  182. package/dist/core/state_diff.js +112 -0
  183. package/dist/core/state_diff.js.map +1 -0
  184. package/dist/core/status.d.ts +24 -0
  185. package/dist/core/status.d.ts.map +1 -0
  186. package/dist/core/status.js +57 -0
  187. package/dist/core/status.js.map +1 -0
  188. package/dist/core/vault.d.ts +37 -0
  189. package/dist/core/vault.d.ts.map +1 -0
  190. package/dist/core/vault.js +179 -0
  191. package/dist/core/vault.js.map +1 -0
  192. package/dist/core/watch.d.ts +36 -0
  193. package/dist/core/watch.d.ts.map +1 -0
  194. package/dist/core/watch.js +176 -0
  195. package/dist/core/watch.js.map +1 -0
  196. package/dist/daemon/loop.d.ts +38 -0
  197. package/dist/daemon/loop.d.ts.map +1 -0
  198. package/dist/daemon/loop.js +169 -0
  199. package/dist/daemon/loop.js.map +1 -0
  200. package/dist/db/backup.d.ts +12 -0
  201. package/dist/db/backup.d.ts.map +1 -0
  202. package/dist/db/backup.js +132 -0
  203. package/dist/db/backup.js.map +1 -0
  204. package/dist/db/budget.d.ts +17 -0
  205. package/dist/db/budget.d.ts.map +1 -0
  206. package/dist/db/budget.js +31 -0
  207. package/dist/db/budget.js.map +1 -0
  208. package/dist/db/database.d.ts +6 -0
  209. package/dist/db/database.d.ts.map +1 -0
  210. package/dist/db/database.js +134 -0
  211. package/dist/db/database.js.map +1 -0
  212. package/dist/db/migrations/.gitkeep +1 -0
  213. package/dist/db/migrations/001_resource_usage_logs.sql +28 -0
  214. package/dist/db/migrator.d.ts +28 -0
  215. package/dist/db/migrator.d.ts.map +1 -0
  216. package/dist/db/migrator.js +75 -0
  217. package/dist/db/migrator.js.map +1 -0
  218. package/dist/db/repositories.d.ts +474 -0
  219. package/dist/db/repositories.d.ts.map +1 -0
  220. package/dist/db/repositories.js +809 -0
  221. package/dist/db/repositories.js.map +1 -0
  222. package/dist/db/schema.sql +207 -0
  223. package/dist/index.d.ts +3 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +47 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/lib.d.ts +20 -0
  228. package/dist/lib.d.ts.map +1 -0
  229. package/dist/lib.js +16 -0
  230. package/dist/lib.js.map +1 -0
  231. package/dist/logging/index.d.ts +22 -0
  232. package/dist/logging/index.d.ts.map +1 -0
  233. package/dist/logging/index.js +34 -0
  234. package/dist/logging/index.js.map +1 -0
  235. package/dist/logging/logger.d.ts +14 -0
  236. package/dist/logging/logger.d.ts.map +1 -0
  237. package/dist/logging/logger.js +135 -0
  238. package/dist/logging/logger.js.map +1 -0
  239. package/dist/logging/types.d.ts +10 -0
  240. package/dist/logging/types.d.ts.map +1 -0
  241. package/dist/logging/types.js +2 -0
  242. package/dist/logging/types.js.map +1 -0
  243. package/dist/mcp/index.d.ts +3 -0
  244. package/dist/mcp/index.d.ts.map +1 -0
  245. package/dist/mcp/index.js +14 -0
  246. package/dist/mcp/index.js.map +1 -0
  247. package/dist/mcp/server.d.ts +10 -0
  248. package/dist/mcp/server.d.ts.map +1 -0
  249. package/dist/mcp/server.js +51 -0
  250. package/dist/mcp/server.js.map +1 -0
  251. package/dist/mcp/tools/get-extension-costs.d.ts +4 -0
  252. package/dist/mcp/tools/get-extension-costs.d.ts.map +1 -0
  253. package/dist/mcp/tools/get-extension-costs.js +33 -0
  254. package/dist/mcp/tools/get-extension-costs.js.map +1 -0
  255. package/dist/mcp/tools/get_contract_status.d.ts +8 -0
  256. package/dist/mcp/tools/get_contract_status.d.ts.map +1 -0
  257. package/dist/mcp/tools/get_contract_status.js +33 -0
  258. package/dist/mcp/tools/get_contract_status.js.map +1 -0
  259. package/dist/rpc/client.d.ts +154 -0
  260. package/dist/rpc/client.d.ts.map +1 -0
  261. package/dist/rpc/client.js +766 -0
  262. package/dist/rpc/client.js.map +1 -0
  263. package/dist/utils/config.d.ts +51 -0
  264. package/dist/utils/config.d.ts.map +1 -0
  265. package/dist/utils/config.js +86 -0
  266. package/dist/utils/config.js.map +1 -0
  267. package/dist/utils/formatting.d.ts +10 -0
  268. package/dist/utils/formatting.d.ts.map +1 -0
  269. package/dist/utils/formatting.js +66 -0
  270. package/dist/utils/formatting.js.map +1 -0
  271. package/dist/utils/watch-config.d.ts +13 -0
  272. package/dist/utils/watch-config.d.ts.map +1 -0
  273. package/dist/utils/watch-config.js +32 -0
  274. package/dist/utils/watch-config.js.map +1 -0
  275. package/package.json +73 -0
@@ -0,0 +1,136 @@
1
+ import { StellarRpcClient } from "../rpc/client.js";
2
+ import { getChannelAccounts, updateChannelBalance, insertChannelAccount, markChannelFunded, } from "../db/repositories.js";
3
+ import { getLogger } from "../logging/index.js";
4
+ const logger = getLogger().child({ component: "ChannelAccountPool" });
5
+ /**
6
+ * Pool of channel accounts for concurrent TTL extensions.
7
+ *
8
+ * Each account tracks its own sequence number on Stellar, so concurrent
9
+ * transactions submitted through different accounts avoid sequence conflicts.
10
+ * acquire() hands out a slot in round-robin order, blocking callers until
11
+ * a slot is free. release() returns the slot and unblocks the next waiter.
12
+ */
13
+ export class ChannelAccountPool {
14
+ db;
15
+ network;
16
+ accounts;
17
+ /** Tracks which publicKeys are currently in use. */
18
+ inUse = new Set();
19
+ /** Queue of resolve callbacks waiting for the next free slot. */
20
+ waiters = [];
21
+ /** Round-robin cursor. */
22
+ cursor = 0;
23
+ constructor(db, network) {
24
+ this.db = db;
25
+ this.network = network;
26
+ this.accounts = getChannelAccounts(db, network);
27
+ }
28
+ /** Number of registered channel accounts. */
29
+ size() {
30
+ return this.accounts.length;
31
+ }
32
+ /**
33
+ * Acquire an available channel account slot.
34
+ * If all slots are in use, waits until one is released.
35
+ */
36
+ acquire() {
37
+ const slot = this.nextFreeSlot();
38
+ if (slot) {
39
+ this.inUse.add(slot.publicKey);
40
+ return Promise.resolve(slot);
41
+ }
42
+ // All slots busy — queue the caller
43
+ return new Promise(resolve => {
44
+ this.waiters.push(resolve);
45
+ });
46
+ }
47
+ /**
48
+ * Release a slot back to the pool.
49
+ * Unblocks the oldest waiting acquire() call if any.
50
+ */
51
+ release(publicKey) {
52
+ this.inUse.delete(publicKey);
53
+ if (this.waiters.length > 0) {
54
+ const slot = this.nextFreeSlot();
55
+ if (slot) {
56
+ this.inUse.add(slot.publicKey);
57
+ this.waiters.shift()(slot);
58
+ }
59
+ }
60
+ }
61
+ /**
62
+ * Returns current balance information for all accounts in the pool.
63
+ * Reads from the DB — does not call the RPC.
64
+ */
65
+ getBalances() {
66
+ return getChannelAccounts(this.db, this.network).map(a => ({
67
+ publicKey: a.public_key,
68
+ balanceXlm: a.balance_xlm,
69
+ balanceCheckedAt: a.balance_checked_at,
70
+ }));
71
+ }
72
+ /**
73
+ * Fetch native XLM balances for all accounts from the RPC and persist them.
74
+ * Errors per-account are logged and swallowed — does not throw.
75
+ */
76
+ async refreshBalances(rpcUrl) {
77
+ if (this.accounts.length === 0)
78
+ return;
79
+ const client = new StellarRpcClient(this.network, rpcUrl);
80
+ await Promise.all(this.accounts.map(async (account) => {
81
+ try {
82
+ const response = await client.getAccount(account.public_key);
83
+ const nativeBalance = response.balances?.find((b) => b.asset_type === "native");
84
+ const xlm = nativeBalance ? parseFloat(nativeBalance.balance) : 0;
85
+ updateChannelBalance(this.db, account.public_key, xlm);
86
+ }
87
+ catch (err) {
88
+ const msg = err instanceof Error ? err.message : String(err);
89
+ logger.warn(`Failed to refresh balance for ${account.public_key}: ${msg}`);
90
+ }
91
+ }));
92
+ }
93
+ // ─── Private ─────────────────────────────────────────────────────────────
94
+ /**
95
+ * Find the next free account in round-robin order.
96
+ * Returns undefined if all accounts are in use.
97
+ */
98
+ nextFreeSlot() {
99
+ const n = this.accounts.length;
100
+ for (let i = 0; i < n; i++) {
101
+ const idx = (this.cursor + i) % n;
102
+ const account = this.accounts[idx];
103
+ if (!this.inUse.has(account.public_key)) {
104
+ this.cursor = (idx + 1) % n;
105
+ return { publicKey: account.public_key, keypairSource: account.keypair_source };
106
+ }
107
+ }
108
+ return undefined;
109
+ }
110
+ }
111
+ export function addChannel(db, publicKey, network, label) {
112
+ insertChannelAccount(db, { public_key: publicKey, network, label });
113
+ }
114
+ export function listChannels(db, network) {
115
+ return getChannelAccounts(db, network);
116
+ }
117
+ export async function fundChannels(db, masterSecretKey, amountXlm, network, rpcUrl) {
118
+ const accounts = getChannelAccounts(db, network);
119
+ if (accounts.length === 0) {
120
+ return { funded: 0, txHash: "", errors: [] };
121
+ }
122
+ const client = new StellarRpcClient(network, rpcUrl);
123
+ const destinations = accounts.map((a) => ({
124
+ publicKey: a.public_key,
125
+ amountXlm,
126
+ }));
127
+ const result = await client.sendPayments(destinations, masterSecretKey);
128
+ if (!result.success) {
129
+ return { funded: 0, txHash: result.txHash, errors: [result.error ?? "Transaction failed"] };
130
+ }
131
+ for (const account of accounts) {
132
+ markChannelFunded(db, account.public_key);
133
+ }
134
+ return { funded: accounts.length, txHash: result.txHash, errors: [] };
135
+ }
136
+ //# sourceMappingURL=channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.js","sourceRoot":"","sources":["../../src/core/channels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface CheckEntry {
2
+ entryKeyXdr: string;
3
+ entryType: "instance" | "wasm";
4
+ liveUntilLedger: number;
5
+ remainingTTL: number;
6
+ }
7
+ export interface CheckResult {
8
+ contractId: string;
9
+ network: string;
10
+ threshold: number;
11
+ latestLedger: number;
12
+ minimumTTL: number;
13
+ passed: boolean;
14
+ entries: CheckEntry[];
15
+ error?: string;
16
+ }
17
+ /**
18
+ * One-shot, stateless TTL check for a Soroban contract.
19
+ *
20
+ * Queries the Stellar RPC directly — no local DB required.
21
+ * Checks both the contract instance and its WASM code entry (when present).
22
+ * Returns `passed: true` when minimumTTL >= threshold.
23
+ */
24
+ export declare function checkContractTTL(contractId: string, network: string, threshold: number, rpcUrl?: string): Promise<CheckResult>;
25
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/core/check.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,UAAU,GAAG,MAAM,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAgFtB"}
@@ -0,0 +1,85 @@
1
+ import { StellarRpcClient } from "../rpc/client.js";
2
+ import { getLogger } from "../logging/index.js";
3
+ const logger = getLogger().child({ component: "CheckCommand" });
4
+ /**
5
+ * One-shot, stateless TTL check for a Soroban contract.
6
+ *
7
+ * Queries the Stellar RPC directly — no local DB required.
8
+ * Checks both the contract instance and its WASM code entry (when present).
9
+ * Returns `passed: true` when minimumTTL >= threshold.
10
+ */
11
+ export async function checkContractTTL(contractId, network, threshold, rpcUrl) {
12
+ const client = new StellarRpcClient(network, rpcUrl);
13
+ const entries = [];
14
+ try {
15
+ const instanceEntry = await client.getContractInstanceEntry(contractId);
16
+ if (!instanceEntry) {
17
+ return {
18
+ contractId,
19
+ network,
20
+ threshold,
21
+ latestLedger: 0,
22
+ minimumTTL: 0,
23
+ passed: false,
24
+ entries: [],
25
+ error: `Contract ${contractId} not found on ${network}`,
26
+ };
27
+ }
28
+ entries.push({
29
+ entryKeyXdr: instanceEntry.entryKeyXdr,
30
+ entryType: "instance",
31
+ liveUntilLedger: instanceEntry.liveUntilLedgerSeq,
32
+ remainingTTL: instanceEntry.remainingTTL,
33
+ });
34
+ if (instanceEntry.wasmHash) {
35
+ const wasmEntry = await client.getWasmCodeEntry(instanceEntry.wasmHash);
36
+ if (wasmEntry) {
37
+ entries.push({
38
+ entryKeyXdr: wasmEntry.entryKeyXdr,
39
+ entryType: "wasm",
40
+ liveUntilLedger: wasmEntry.liveUntilLedgerSeq,
41
+ remainingTTL: wasmEntry.remainingTTL,
42
+ });
43
+ }
44
+ else {
45
+ return {
46
+ contractId,
47
+ network,
48
+ threshold,
49
+ latestLedger: instanceEntry.latestLedger,
50
+ minimumTTL: 0,
51
+ passed: false,
52
+ entries,
53
+ error: `WASM code entry (hash: ${instanceEntry.wasmHash.substring(0, 10)}...) not found`,
54
+ };
55
+ }
56
+ }
57
+ const minimumTTL = Math.min(...entries.map(e => e.remainingTTL));
58
+ const passed = minimumTTL >= threshold;
59
+ logger.debug(`TTL check — contract: ${contractId}, minimumTTL: ${minimumTTL}, threshold: ${threshold}, passed: ${passed}`);
60
+ return {
61
+ contractId,
62
+ network,
63
+ threshold,
64
+ latestLedger: instanceEntry.latestLedger,
65
+ minimumTTL,
66
+ passed,
67
+ entries,
68
+ };
69
+ }
70
+ catch (error) {
71
+ const message = error instanceof Error ? error.message : String(error);
72
+ logger.error(`TTL check failed for ${contractId}: ${message}`);
73
+ return {
74
+ contractId,
75
+ network,
76
+ threshold,
77
+ latestLedger: 0,
78
+ minimumTTL: 0,
79
+ passed: false,
80
+ entries: [],
81
+ error: message,
82
+ };
83
+ }
84
+ }
85
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/core/check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type Database from "better-sqlite3";
2
+ export declare const TOP_LEVEL_COMMANDS: string[];
3
+ export declare const ALERTS_SUBCOMMANDS: string[];
4
+ export declare const CHANNELS_SUBCOMMANDS: string[];
5
+ export declare const STATUS_CONTRACT_COMMANDS: string[];
6
+ export declare function getCompletionSuggestions(db: Database.Database, words: string[], cursorIndex: number): string[];
7
+ export declare function renderBashCompletionScript(): string;
8
+ export declare function renderZshCompletionScript(): string;
9
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/core/completion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,eAAO,MAAM,kBAAkB,UAY9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAA+C,CAAC;AAC/E,eAAO,MAAM,oBAAoB,UAA0B,CAAC;AAC5D,eAAO,MAAM,wBAAwB,UAAgE,CAAC;AAEtG,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CAsBV;AAED,wBAAgB,0BAA0B,IAAI,MAAM,CAYnD;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAgBlD"}
@@ -0,0 +1,68 @@
1
+ import { getAllContracts } from "../db/repositories.js";
2
+ export const TOP_LEVEL_COMMANDS = [
3
+ "watch",
4
+ "status",
5
+ "check",
6
+ "daemon",
7
+ "alerts",
8
+ "guard",
9
+ "costs",
10
+ "resources",
11
+ "restore",
12
+ "channels",
13
+ "completion",
14
+ ];
15
+ export const ALERTS_SUBCOMMANDS = ["add", "list", "remove", "test", "history"];
16
+ export const CHANNELS_SUBCOMMANDS = ["add", "list", "fund"];
17
+ export const STATUS_CONTRACT_COMMANDS = ["status", "check", "resources", "costs", "guard", "restore"];
18
+ export function getCompletionSuggestions(db, words, cursorIndex) {
19
+ if (words.length <= 1 || cursorIndex <= 1) {
20
+ return TOP_LEVEL_COMMANDS;
21
+ }
22
+ const normalizedWords = words.slice(1, cursorIndex + 1);
23
+ const firstCommand = normalizedWords[0];
24
+ if (firstCommand === "alerts") {
25
+ if (cursorIndex === 2) {
26
+ return ALERTS_SUBCOMMANDS;
27
+ }
28
+ return [];
29
+ }
30
+ if (firstCommand && STATUS_CONTRACT_COMMANDS.includes(firstCommand) && cursorIndex === 2) {
31
+ const contracts = getAllContracts(db)
32
+ .map((contract) => contract.id)
33
+ .filter((id) => typeof id === "string");
34
+ return contracts;
35
+ }
36
+ return TOP_LEVEL_COMMANDS.filter((cmd) => cmd.startsWith(normalizedWords[0] ?? ""));
37
+ }
38
+ export function renderBashCompletionScript() {
39
+ return `#!/usr/bin/env bash
40
+ _sorokeep_complete() {
41
+ local cur prev words cword
42
+ _init_completion -n : || return
43
+
44
+ local suggestions
45
+ suggestions=$(sorokeep completion --query --cursor "$cword" "\${words[@]}" 2>/dev/null)
46
+ COMPREPLY=( $(compgen -W "$suggestions" -- "$cur") )
47
+ }
48
+ complete -F _sorokeep_complete sorokeep
49
+ `;
50
+ }
51
+ export function renderZshCompletionScript() {
52
+ return [
53
+ "#compdef sorokeep",
54
+ "",
55
+ "_sorokeep() {",
56
+ " local -a suggestions",
57
+ " local -a words",
58
+ "",
59
+ ' local current_word=${words[CURRENT]}',
60
+ ' suggestions=( ${(f)"$(sorokeep completion --query --cursor "$CURRENT" "${words[@]}")"} )',
61
+ " _describe 'values' suggestions",
62
+ "}",
63
+ "",
64
+ "compdef _sorokeep sorokeep",
65
+ "",
66
+ ].join("\n");
67
+ }
68
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/core/completion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,WAAW;IACX,SAAS;IACT,UAAU;IACV,YAAY;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAEtG,MAAM,UAAU,wBAAwB,CACtC,EAAqB,EACrB,KAAe,EACf,WAAmB;IAEnB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACH,MAAM,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAExC,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,kBAAkB,CAAC;QAC5B,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAEF,IAAI,YAAY,IAAI,wBAAwB,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACxF,MAAM,SAAS,GAAG,eAAe,CAAC,EAAE,CAAC;aAClC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;aAC9B,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC;QACxD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO;;;;;;;;;;CAUR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,OAAO;QACL,mBAAmB;QACnB,EAAE;QACF,eAAe;QACf,wBAAwB;QACxB,kBAAkB;QAClB,EAAE;QACF,wCAAwC;QACxC,4FAA4F;QAC5F,kCAAkC;QAClC,GAAG;QACH,EAAE;QACF,4BAA4B;QAC5B,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,90 @@
1
+ import type Database from "better-sqlite3";
2
+ import type { FeeStatsResult } from "../rpc/client.js";
3
+ export interface EntryTypeCostBreakdown {
4
+ count: number;
5
+ costXlm: number;
6
+ }
7
+ export interface ExtensionCostDetail {
8
+ executedAt: string;
9
+ entryLabel: string;
10
+ entryType: string;
11
+ oldTtlLedgers: number;
12
+ newTtlLedgers: number;
13
+ oldTtlFormatted: string;
14
+ newTtlFormatted: string;
15
+ costXlm: number | null;
16
+ txHash: string;
17
+ executedAtLedger: number;
18
+ }
19
+ export interface CostProjection {
20
+ estimated30DayCostXlm: number;
21
+ basisDays: number;
22
+ formula: string;
23
+ }
24
+ export interface ExtensionCostsResult {
25
+ contract: {
26
+ id: string;
27
+ name: string | null;
28
+ network: string;
29
+ };
30
+ period: {
31
+ days: number | null;
32
+ label: string;
33
+ };
34
+ summary: {
35
+ totalExtensions: number;
36
+ totalCostXlm: number;
37
+ };
38
+ byEntryType: Record<string, EntryTypeCostBreakdown>;
39
+ recentExtensions: ExtensionCostDetail[];
40
+ projection?: CostProjection;
41
+ message?: string;
42
+ }
43
+ export type GetExtensionCostsError = {
44
+ success: false;
45
+ error: "contract_not_found";
46
+ contractId: string;
47
+ } | {
48
+ success: false;
49
+ error: "invalid_period";
50
+ period: number;
51
+ };
52
+ export type GetExtensionCostsResponse = {
53
+ success: true;
54
+ data: ExtensionCostsResult;
55
+ } | GetExtensionCostsError;
56
+ export declare function getExtensionCosts(db: Database.Database, contractId: string, options?: {
57
+ period?: number;
58
+ all?: boolean;
59
+ }): GetExtensionCostsResponse;
60
+ export interface PeriodCostSummary {
61
+ days: number;
62
+ totalExtensions: number;
63
+ totalCostXlm: number;
64
+ }
65
+ export interface MultiPeriodCostsData {
66
+ contract: {
67
+ id: string;
68
+ name: string | null;
69
+ network: string;
70
+ };
71
+ periods: PeriodCostSummary[];
72
+ projection: FeeAdjustedProjection;
73
+ }
74
+ export type GetMultiPeriodCostsResponse = {
75
+ success: true;
76
+ data: MultiPeriodCostsData;
77
+ } | {
78
+ success: false;
79
+ error: "contract_not_found";
80
+ contractId: string;
81
+ };
82
+ export declare function getMultiPeriodCosts(db: Database.Database, contractId: string, feeStats?: Pick<FeeStatsResult, "baseFeeStroops" | "surgePricingMultiplier">): GetMultiPeriodCostsResponse;
83
+ export interface FeeAdjustedProjection {
84
+ baseProjectedCostXlm: number;
85
+ adjustedProjectedCostXlm: number;
86
+ baseFeeMultiplier: number;
87
+ surgePricingMultiplier: number;
88
+ }
89
+ export declare function calculateFeeAdjustedProjection(totalCostXlm: number, periodDays: number, feeStats?: Pick<FeeStatsResult, "baseFeeStroops" | "surgePricingMultiplier">): FeeAdjustedProjection;
90
+ //# sourceMappingURL=costs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"costs.d.ts","sourceRoot":"","sources":["../../src/core/costs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import { getContract, getEntriesForContract, getExtensionHistory, } from "../db/repositories.js";
2
+ import { formatTimeToCloseLedger } from "../utils/formatting.js";
3
+ const DEFAULT_PERIOD_DAYS = 30;
4
+ export function getExtensionCosts(db, contractId, options) {
5
+ const contract = getContract(db, contractId);
6
+ if (!contract) {
7
+ return {
8
+ success: false,
9
+ error: "contract_not_found",
10
+ contractId,
11
+ };
12
+ }
13
+ const allTime = options?.all === true;
14
+ const period = allTime ? undefined : (options?.period ?? DEFAULT_PERIOD_DAYS);
15
+ if (period !== undefined && (!Number.isInteger(period) || period <= 0)) {
16
+ return {
17
+ success: false,
18
+ error: "invalid_period",
19
+ period,
20
+ };
21
+ }
22
+ const history = getExtensionHistory(db, contractId, period);
23
+ const periodLabel = allTime ? "all time" : `last ${period} days`;
24
+ if (history.length === 0) {
25
+ return {
26
+ success: true,
27
+ data: {
28
+ contract: {
29
+ id: contract.id,
30
+ name: contract.name,
31
+ network: contract.network,
32
+ },
33
+ period: {
34
+ days: period ?? null,
35
+ label: periodLabel,
36
+ },
37
+ summary: {
38
+ totalExtensions: 0,
39
+ totalCostXlm: 0,
40
+ },
41
+ byEntryType: {},
42
+ recentExtensions: [],
43
+ message: "No extensions recorded for this period.",
44
+ },
45
+ };
46
+ }
47
+ const entries = getEntriesForContract(db, contractId);
48
+ const entryMap = new Map(entries.map((entry) => [entry.id, entry]));
49
+ let totalCostXlm = 0;
50
+ const byEntryType = {};
51
+ for (const record of history) {
52
+ const cost = record.cost_xlm ?? 0;
53
+ totalCostXlm += cost;
54
+ const entry = entryMap.get(record.contract_entry_id);
55
+ const entryType = entry?.entry_type ?? "unknown";
56
+ if (!byEntryType[entryType]) {
57
+ byEntryType[entryType] = { count: 0, costXlm: 0 };
58
+ }
59
+ byEntryType[entryType].count++;
60
+ byEntryType[entryType].costXlm += cost;
61
+ }
62
+ const recentExtensions = history.map((record) => {
63
+ const entry = entryMap.get(record.contract_entry_id);
64
+ const entryLabel = entry?.label ?? entry?.entry_type ?? "unknown";
65
+ const entryType = entry?.entry_type ?? "unknown";
66
+ return {
67
+ executedAt: record.executed_at,
68
+ entryLabel,
69
+ entryType,
70
+ oldTtlLedgers: record.old_ttl_ledgers,
71
+ newTtlLedgers: record.new_ttl_ledgers,
72
+ oldTtlFormatted: formatTimeToCloseLedger(record.old_ttl_ledgers),
73
+ newTtlFormatted: formatTimeToCloseLedger(record.new_ttl_ledgers),
74
+ costXlm: record.cost_xlm,
75
+ txHash: record.tx_hash,
76
+ executedAtLedger: record.executed_at_ledger,
77
+ };
78
+ });
79
+ return {
80
+ success: true,
81
+ data: {
82
+ contract: {
83
+ id: contract.id,
84
+ name: contract.name,
85
+ network: contract.network,
86
+ },
87
+ period: {
88
+ days: period ?? null,
89
+ label: periodLabel,
90
+ },
91
+ summary: {
92
+ totalExtensions: history.length,
93
+ totalCostXlm,
94
+ },
95
+ byEntryType,
96
+ recentExtensions,
97
+ ...(period !== undefined
98
+ ? {
99
+ projection: {
100
+ estimated30DayCostXlm: (totalCostXlm / period) * 30,
101
+ basisDays: period,
102
+ formula: "linear extrapolation from period average",
103
+ },
104
+ }
105
+ : {}),
106
+ },
107
+ };
108
+ }
109
+ const MULTI_PERIOD_WINDOWS = [7, 30, 90];
110
+ export function getMultiPeriodCosts(db, contractId, feeStats) {
111
+ const contract = getContract(db, contractId);
112
+ if (!contract) {
113
+ return { success: false, error: "contract_not_found", contractId };
114
+ }
115
+ const periods = MULTI_PERIOD_WINDOWS.map((days) => {
116
+ const history = getExtensionHistory(db, contractId, days);
117
+ let totalCostXlm = 0;
118
+ for (const record of history) {
119
+ totalCostXlm += record.cost_xlm ?? 0;
120
+ }
121
+ return { days, totalExtensions: history.length, totalCostXlm };
122
+ });
123
+ const thirtyDay = periods.find((p) => p.days === 30);
124
+ const projection = calculateFeeAdjustedProjection(thirtyDay.totalCostXlm, 30, feeStats);
125
+ return {
126
+ success: true,
127
+ data: {
128
+ contract: { id: contract.id, name: contract.name, network: contract.network },
129
+ periods,
130
+ projection,
131
+ },
132
+ };
133
+ }
134
+ const DEFAULT_BASE_FEE_STROOPS = 100;
135
+ export function calculateFeeAdjustedProjection(totalCostXlm, periodDays, feeStats) {
136
+ const baseProjectedCostXlm = (totalCostXlm / periodDays) * 30;
137
+ const liveBaseFee = feeStats?.baseFeeStroops ?? DEFAULT_BASE_FEE_STROOPS;
138
+ const baseFeeMultiplier = Math.max(liveBaseFee / DEFAULT_BASE_FEE_STROOPS, 0);
139
+ const surgePricingMultiplier = Math.max(feeStats?.surgePricingMultiplier ?? 1, 1);
140
+ return {
141
+ baseProjectedCostXlm,
142
+ adjustedProjectedCostXlm: baseProjectedCostXlm * baseFeeMultiplier * surgePricingMultiplier,
143
+ baseFeeMultiplier,
144
+ surgePricingMultiplier,
145
+ };
146
+ }
147
+ //# sourceMappingURL=costs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"costs.js","sourceRoot":"","sources":["../../src/core/costs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface DecodedLedgerKey {
2
+ contractId: string;
3
+ symbol: any;
4
+ durability: string;
5
+ }
6
+ export declare function decodeLedgerKey(base64Key: string): DecodedLedgerKey;
7
+ //# sourceMappingURL=decoder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../src/core/decoder.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAqCnE"}
@@ -0,0 +1,38 @@
1
+ import { xdr, Address, scValToNative } from '@stellar/stellar-sdk';
2
+ export function decodeLedgerKey(base64Key) {
3
+ const buf = Buffer.from(base64Key, 'base64');
4
+ const key = xdr.LedgerKey.fromXDR(buf);
5
+ if (key.switch() !== xdr.LedgerEntryType.contractData()) {
6
+ throw new Error('Unsupported ledger entry type');
7
+ }
8
+ const contractData = key.contractData();
9
+ const contractAddress = Address.fromScAddress(contractData.contract());
10
+ const contractId = contractAddress.toString();
11
+ const scValKey = contractData.key();
12
+ let symbol;
13
+ if (scValKey.switch() === xdr.ScValType.scvLedgerKeyContractInstance()) {
14
+ symbol = 'ContractInstance';
15
+ }
16
+ else {
17
+ try {
18
+ symbol = scValToNative(scValKey);
19
+ }
20
+ catch {
21
+ symbol = 'Unknown';
22
+ }
23
+ }
24
+ const durabilityType = contractData.durability();
25
+ let durability = 'Unknown';
26
+ if (durabilityType.value === xdr.ContractDataDurability.persistent().value) {
27
+ durability = 'Persistent';
28
+ }
29
+ else if (durabilityType.value === xdr.ContractDataDurability.temporary().value) {
30
+ durability = 'Temporary';
31
+ }
32
+ return {
33
+ contractId,
34
+ symbol,
35
+ durability
36
+ };
37
+ }
38
+ //# sourceMappingURL=decoder.js.map