@jinn-network/client 0.1.0-canary.adfd078d

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 (278) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/deployments/deployment-phase1a-l2-baseSepolia-fast.json +32 -0
  4. package/deployments/deployment-phase1a-token-baseSepolia-fast.json +27 -0
  5. package/deployments/deployment-phase1b-mech-baseSepolia-fast.json +26 -0
  6. package/deployments/deployment-stolas-l2-baseSepolia-fast.json +35 -0
  7. package/dist/adapters/adapter.d.ts +11 -0
  8. package/dist/adapters/adapter.js +2 -0
  9. package/dist/adapters/adapter.js.map +1 -0
  10. package/dist/adapters/local/adapter.d.ts +20 -0
  11. package/dist/adapters/local/adapter.js +146 -0
  12. package/dist/adapters/local/adapter.js.map +1 -0
  13. package/dist/adapters/mech/adapter.d.ts +29 -0
  14. package/dist/adapters/mech/adapter.js +332 -0
  15. package/dist/adapters/mech/adapter.js.map +1 -0
  16. package/dist/adapters/mech/claim-policy.d.ts +40 -0
  17. package/dist/adapters/mech/claim-policy.js +104 -0
  18. package/dist/adapters/mech/claim-policy.js.map +1 -0
  19. package/dist/adapters/mech/contracts.d.ts +44 -0
  20. package/dist/adapters/mech/contracts.js +323 -0
  21. package/dist/adapters/mech/contracts.js.map +1 -0
  22. package/dist/adapters/mech/ipfs.d.ts +43 -0
  23. package/dist/adapters/mech/ipfs.js +142 -0
  24. package/dist/adapters/mech/ipfs.js.map +1 -0
  25. package/dist/adapters/mech/safe.d.ts +15 -0
  26. package/dist/adapters/mech/safe.js +113 -0
  27. package/dist/adapters/mech/safe.js.map +1 -0
  28. package/dist/adapters/mech/types.d.ts +561 -0
  29. package/dist/adapters/mech/types.js +340 -0
  30. package/dist/adapters/mech/types.js.map +1 -0
  31. package/dist/api/balance-build.d.ts +22 -0
  32. package/dist/api/balance-build.js +37 -0
  33. package/dist/api/balance-build.js.map +1 -0
  34. package/dist/api/fleet-build.d.ts +62 -0
  35. package/dist/api/fleet-build.js +91 -0
  36. package/dist/api/fleet-build.js.map +1 -0
  37. package/dist/api/gather-status.d.ts +20 -0
  38. package/dist/api/gather-status.js +137 -0
  39. package/dist/api/gather-status.js.map +1 -0
  40. package/dist/api/history-build.d.ts +32 -0
  41. package/dist/api/history-build.js +48 -0
  42. package/dist/api/history-build.js.map +1 -0
  43. package/dist/api/peers.d.ts +27 -0
  44. package/dist/api/peers.js +94 -0
  45. package/dist/api/peers.js.map +1 -0
  46. package/dist/api/rewards-build.d.ts +20 -0
  47. package/dist/api/rewards-build.js +42 -0
  48. package/dist/api/rewards-build.js.map +1 -0
  49. package/dist/api/server.d.ts +34 -0
  50. package/dist/api/server.js +130 -0
  51. package/dist/api/server.js.map +1 -0
  52. package/dist/api/status-build.d.ts +92 -0
  53. package/dist/api/status-build.js +175 -0
  54. package/dist/api/status-build.js.map +1 -0
  55. package/dist/api/status-rollup-build.d.ts +36 -0
  56. package/dist/api/status-rollup-build.js +69 -0
  57. package/dist/api/status-rollup-build.js.map +1 -0
  58. package/dist/auth/erc8128.d.ts +43 -0
  59. package/dist/auth/erc8128.js +88 -0
  60. package/dist/auth/erc8128.js.map +1 -0
  61. package/dist/bin/jinn.d.ts +11 -0
  62. package/dist/bin/jinn.js +20 -0
  63. package/dist/bin/jinn.js.map +1 -0
  64. package/dist/build-meta.json +3 -0
  65. package/dist/chain-read-errors.d.ts +9 -0
  66. package/dist/chain-read-errors.js +43 -0
  67. package/dist/chain-read-errors.js.map +1 -0
  68. package/dist/cli/action.d.ts +26 -0
  69. package/dist/cli/action.js +56 -0
  70. package/dist/cli/action.js.map +1 -0
  71. package/dist/cli/command.d.ts +62 -0
  72. package/dist/cli/command.js +29 -0
  73. package/dist/cli/command.js.map +1 -0
  74. package/dist/cli/commands/balance.d.ts +3 -0
  75. package/dist/cli/commands/balance.js +46 -0
  76. package/dist/cli/commands/balance.js.map +1 -0
  77. package/dist/cli/commands/bootstrap.d.ts +3 -0
  78. package/dist/cli/commands/bootstrap.js +165 -0
  79. package/dist/cli/commands/bootstrap.js.map +1 -0
  80. package/dist/cli/commands/claim-rewards.d.ts +3 -0
  81. package/dist/cli/commands/claim-rewards.js +121 -0
  82. package/dist/cli/commands/claim-rewards.js.map +1 -0
  83. package/dist/cli/commands/doctor.d.ts +3 -0
  84. package/dist/cli/commands/doctor.js +151 -0
  85. package/dist/cli/commands/doctor.js.map +1 -0
  86. package/dist/cli/commands/fleet-scale.d.ts +3 -0
  87. package/dist/cli/commands/fleet-scale.js +449 -0
  88. package/dist/cli/commands/fleet-scale.js.map +1 -0
  89. package/dist/cli/commands/fleet.d.ts +3 -0
  90. package/dist/cli/commands/fleet.js +45 -0
  91. package/dist/cli/commands/fleet.js.map +1 -0
  92. package/dist/cli/commands/fund-requirements.d.ts +3 -0
  93. package/dist/cli/commands/fund-requirements.js +139 -0
  94. package/dist/cli/commands/fund-requirements.js.map +1 -0
  95. package/dist/cli/commands/history.d.ts +3 -0
  96. package/dist/cli/commands/history.js +61 -0
  97. package/dist/cli/commands/history.js.map +1 -0
  98. package/dist/cli/commands/init.d.ts +3 -0
  99. package/dist/cli/commands/init.js +91 -0
  100. package/dist/cli/commands/init.js.map +1 -0
  101. package/dist/cli/commands/keys-backup.d.ts +3 -0
  102. package/dist/cli/commands/keys-backup.js +107 -0
  103. package/dist/cli/commands/keys-backup.js.map +1 -0
  104. package/dist/cli/commands/logs.d.ts +3 -0
  105. package/dist/cli/commands/logs.js +69 -0
  106. package/dist/cli/commands/logs.js.map +1 -0
  107. package/dist/cli/commands/rewards.d.ts +3 -0
  108. package/dist/cli/commands/rewards.js +54 -0
  109. package/dist/cli/commands/rewards.js.map +1 -0
  110. package/dist/cli/commands/run.d.ts +3 -0
  111. package/dist/cli/commands/run.js +96 -0
  112. package/dist/cli/commands/run.js.map +1 -0
  113. package/dist/cli/commands/status.d.ts +3 -0
  114. package/dist/cli/commands/status.js +54 -0
  115. package/dist/cli/commands/status.js.map +1 -0
  116. package/dist/cli/commands/stop.d.ts +3 -0
  117. package/dist/cli/commands/stop.js +82 -0
  118. package/dist/cli/commands/stop.js.map +1 -0
  119. package/dist/cli/commands/submit-intent.d.ts +3 -0
  120. package/dist/cli/commands/submit-intent.js +169 -0
  121. package/dist/cli/commands/submit-intent.js.map +1 -0
  122. package/dist/cli/commands/version.d.ts +3 -0
  123. package/dist/cli/commands/version.js +114 -0
  124. package/dist/cli/commands/version.js.map +1 -0
  125. package/dist/cli/commands/withdraw.d.ts +3 -0
  126. package/dist/cli/commands/withdraw.js +181 -0
  127. package/dist/cli/commands/withdraw.js.map +1 -0
  128. package/dist/cli/deployment-digest.d.ts +10 -0
  129. package/dist/cli/deployment-digest.js +25 -0
  130. package/dist/cli/deployment-digest.js.map +1 -0
  131. package/dist/cli/execution-context.d.ts +50 -0
  132. package/dist/cli/execution-context.js +154 -0
  133. package/dist/cli/execution-context.js.map +1 -0
  134. package/dist/cli/help.d.ts +3 -0
  135. package/dist/cli/help.js +37 -0
  136. package/dist/cli/help.js.map +1 -0
  137. package/dist/cli/index.d.ts +17 -0
  138. package/dist/cli/index.js +132 -0
  139. package/dist/cli/index.js.map +1 -0
  140. package/dist/cli/introspection-context.d.ts +10 -0
  141. package/dist/cli/introspection-context.js +60 -0
  142. package/dist/cli/introspection-context.js.map +1 -0
  143. package/dist/cli/output.d.ts +36 -0
  144. package/dist/cli/output.js +35 -0
  145. package/dist/cli/output.js.map +1 -0
  146. package/dist/cli/password.d.ts +12 -0
  147. package/dist/cli/password.js +51 -0
  148. package/dist/cli/password.js.map +1 -0
  149. package/dist/config.d.ts +174 -0
  150. package/dist/config.js +252 -0
  151. package/dist/config.js.map +1 -0
  152. package/dist/daemon/creator.d.ts +24 -0
  153. package/dist/daemon/creator.js +80 -0
  154. package/dist/daemon/creator.js.map +1 -0
  155. package/dist/daemon/daemon.d.ts +60 -0
  156. package/dist/daemon/daemon.js +158 -0
  157. package/dist/daemon/daemon.js.map +1 -0
  158. package/dist/daemon/delivery-watcher.d.ts +10 -0
  159. package/dist/daemon/delivery-watcher.js +37 -0
  160. package/dist/daemon/delivery-watcher.js.map +1 -0
  161. package/dist/daemon/restorer.d.ts +19 -0
  162. package/dist/daemon/restorer.js +82 -0
  163. package/dist/daemon/restorer.js.map +1 -0
  164. package/dist/daemon/reward-claim-loop.d.ts +38 -0
  165. package/dist/daemon/reward-claim-loop.js +48 -0
  166. package/dist/daemon/reward-claim-loop.js.map +1 -0
  167. package/dist/discovery/registry.d.ts +43 -0
  168. package/dist/discovery/registry.js +104 -0
  169. package/dist/discovery/registry.js.map +1 -0
  170. package/dist/discovery/subgraph.d.ts +37 -0
  171. package/dist/discovery/subgraph.js +87 -0
  172. package/dist/discovery/subgraph.js.map +1 -0
  173. package/dist/earning/bootstrap.d.ts +79 -0
  174. package/dist/earning/bootstrap.js +989 -0
  175. package/dist/earning/bootstrap.js.map +1 -0
  176. package/dist/earning/contracts.d.ts +431 -0
  177. package/dist/earning/contracts.js +518 -0
  178. package/dist/earning/contracts.js.map +1 -0
  179. package/dist/earning/evidence-simhash.d.ts +59 -0
  180. package/dist/earning/evidence-simhash.js +87 -0
  181. package/dist/earning/evidence-simhash.js.map +1 -0
  182. package/dist/earning/fleet-display-index.d.ts +8 -0
  183. package/dist/earning/fleet-display-index.js +12 -0
  184. package/dist/earning/fleet-display-index.js.map +1 -0
  185. package/dist/earning/fleet-retire.d.ts +28 -0
  186. package/dist/earning/fleet-retire.js +75 -0
  187. package/dist/earning/fleet-retire.js.map +1 -0
  188. package/dist/earning/jinn-rewards.d.ts +62 -0
  189. package/dist/earning/jinn-rewards.js +81 -0
  190. package/dist/earning/jinn-rewards.js.map +1 -0
  191. package/dist/earning/next-service-index.d.ts +4 -0
  192. package/dist/earning/next-service-index.js +7 -0
  193. package/dist/earning/next-service-index.js.map +1 -0
  194. package/dist/earning/orphan-sweep.d.ts +33 -0
  195. package/dist/earning/orphan-sweep.js +157 -0
  196. package/dist/earning/orphan-sweep.js.map +1 -0
  197. package/dist/earning/reconcile.d.ts +37 -0
  198. package/dist/earning/reconcile.js +216 -0
  199. package/dist/earning/reconcile.js.map +1 -0
  200. package/dist/earning/safe-adapter.d.ts +70 -0
  201. package/dist/earning/safe-adapter.js +228 -0
  202. package/dist/earning/safe-adapter.js.map +1 -0
  203. package/dist/earning/stolas-claim.d.ts +47 -0
  204. package/dist/earning/stolas-claim.js +115 -0
  205. package/dist/earning/stolas-claim.js.map +1 -0
  206. package/dist/earning/store.d.ts +36 -0
  207. package/dist/earning/store.js +156 -0
  208. package/dist/earning/store.js.map +1 -0
  209. package/dist/earning/types.d.ts +123 -0
  210. package/dist/earning/types.js +64 -0
  211. package/dist/earning/types.js.map +1 -0
  212. package/dist/earning/viem-clients.d.ts +9 -0
  213. package/dist/earning/viem-clients.js +22 -0
  214. package/dist/earning/viem-clients.js.map +1 -0
  215. package/dist/earning/wallet.d.ts +20 -0
  216. package/dist/earning/wallet.js +103 -0
  217. package/dist/earning/wallet.js.map +1 -0
  218. package/dist/errors/envelope.d.ts +41 -0
  219. package/dist/errors/envelope.js +48 -0
  220. package/dist/errors/envelope.js.map +1 -0
  221. package/dist/index.d.ts +14 -0
  222. package/dist/index.js +17 -0
  223. package/dist/index.js.map +1 -0
  224. package/dist/main.d.ts +32 -0
  225. package/dist/main.js +281 -0
  226. package/dist/main.js.map +1 -0
  227. package/dist/mcp/server.d.ts +14 -0
  228. package/dist/mcp/server.js +205 -0
  229. package/dist/mcp/server.js.map +1 -0
  230. package/dist/operator-errors.d.ts +16 -0
  231. package/dist/operator-errors.js +88 -0
  232. package/dist/operator-errors.js.map +1 -0
  233. package/dist/preflight/claude-binary.d.ts +19 -0
  234. package/dist/preflight/claude-binary.js +44 -0
  235. package/dist/preflight/claude-binary.js.map +1 -0
  236. package/dist/preflight/claude-invocation-envelope.d.ts +11 -0
  237. package/dist/preflight/claude-invocation-envelope.js +67 -0
  238. package/dist/preflight/claude-invocation-envelope.js.map +1 -0
  239. package/dist/runner/claude.d.ts +15 -0
  240. package/dist/runner/claude.js +193 -0
  241. package/dist/runner/claude.js.map +1 -0
  242. package/dist/runner/runner.d.ts +11 -0
  243. package/dist/runner/runner.js +2 -0
  244. package/dist/runner/runner.js.map +1 -0
  245. package/dist/runner/simple.d.ts +8 -0
  246. package/dist/runner/simple.js +11 -0
  247. package/dist/runner/simple.js.map +1 -0
  248. package/dist/store/store.d.ts +74 -0
  249. package/dist/store/store.js +173 -0
  250. package/dist/store/store.js.map +1 -0
  251. package/dist/tx-retry.d.ts +55 -0
  252. package/dist/tx-retry.js +214 -0
  253. package/dist/tx-retry.js.map +1 -0
  254. package/dist/types/desired-state.d.ts +41 -0
  255. package/dist/types/desired-state.js +16 -0
  256. package/dist/types/desired-state.js.map +1 -0
  257. package/dist/types/errors.d.ts +8 -0
  258. package/dist/types/errors.js +17 -0
  259. package/dist/types/errors.js.map +1 -0
  260. package/dist/types/index.d.ts +2 -0
  261. package/dist/types/index.js +3 -0
  262. package/dist/types/index.js.map +1 -0
  263. package/dist/withdraw/args.d.ts +29 -0
  264. package/dist/withdraw/args.js +198 -0
  265. package/dist/withdraw/args.js.map +1 -0
  266. package/dist/withdraw/run-withdraw-plan.d.ts +21 -0
  267. package/dist/withdraw/run-withdraw-plan.js +257 -0
  268. package/dist/withdraw/run-withdraw-plan.js.map +1 -0
  269. package/dist/x402/acquire.d.ts +6 -0
  270. package/dist/x402/acquire.js +32 -0
  271. package/dist/x402/acquire.js.map +1 -0
  272. package/dist/x402/facilitator.d.ts +11 -0
  273. package/dist/x402/facilitator.js +52 -0
  274. package/dist/x402/facilitator.js.map +1 -0
  275. package/dist/x402/handler.d.ts +15 -0
  276. package/dist/x402/handler.js +40 -0
  277. package/dist/x402/handler.js.map +1 -0
  278. package/package.json +72 -0
@@ -0,0 +1,87 @@
1
+ /**
2
+ * evidence-simhash.ts — Compute SimHash of evidence checkpoints for anti-farming.
3
+ *
4
+ * SimHash produces a 256-bit fingerprint where similar inputs produce similar hashes
5
+ * (low Hamming distance). The on-chain activity checker (RestorationActivityCheckerV2)
6
+ * compares these hashes to detect farming — repeated submission of similar evidence.
7
+ *
8
+ * The algorithm:
9
+ * 1. Extract string features from the evidence checkpoint
10
+ * 2. Hash each feature to 256 bits via keccak256
11
+ * 3. For each bit position, tally +1 (bit set) or -1 (bit unset) across all features
12
+ * 4. The SimHash bit is 1 if the tally is non-negative, 0 otherwise
13
+ */
14
+ import { keccak256, toHex } from 'viem';
15
+ /**
16
+ * Extract string features from an evidence checkpoint.
17
+ * Each feature becomes one "vote" in the SimHash computation.
18
+ */
19
+ export function extractFeatures(checkpoint) {
20
+ const features = [];
21
+ features.push(`desired:${checkpoint.desiredStateHash}`);
22
+ for (const tc of checkpoint.toolCalls) {
23
+ features.push(`tool:${tc.name.toLowerCase().trim()}:${tc.argsHash}`);
24
+ }
25
+ for (const ei of checkpoint.externalInteractions) {
26
+ features.push(`ext:${ei.endpoint.toLowerCase().trim()}:${ei.method.toLowerCase().trim()}`);
27
+ }
28
+ features.push(`outcome:${checkpoint.outcome}`);
29
+ return features;
30
+ }
31
+ /**
32
+ * Compute a 256-bit SimHash from an array of string features.
33
+ *
34
+ * Each feature is hashed to 256 bits via keccak256. For each bit position,
35
+ * we tally +1 if the bit is set, -1 if not. The output bit is 1 if the
36
+ * tally is non-negative.
37
+ */
38
+ export function simhashFromFeatures(features) {
39
+ if (features.length === 0) {
40
+ return '0x0000000000000000000000000000000000000000000000000000000000000000';
41
+ }
42
+ // Hash each feature to 256 bits
43
+ const featureHashes = features.map((f) => BigInt(keccak256(toHex(f))));
44
+ // Vote on each bit position
45
+ const votes = new Int32Array(256);
46
+ for (const hash of featureHashes) {
47
+ for (let i = 0; i < 256; i++) {
48
+ if ((hash >> BigInt(i)) & 1n) {
49
+ votes[i] += 1;
50
+ }
51
+ else {
52
+ votes[i] -= 1;
53
+ }
54
+ }
55
+ }
56
+ // Construct SimHash from vote signs
57
+ let simhash = 0n;
58
+ for (let i = 0; i < 256; i++) {
59
+ if (votes[i] >= 0) {
60
+ simhash |= 1n << BigInt(i);
61
+ }
62
+ }
63
+ return ('0x' + simhash.toString(16).padStart(64, '0'));
64
+ }
65
+ /**
66
+ * Compute the SimHash of an evidence checkpoint.
67
+ * Returns a bytes32 hex string suitable for submission to the on-chain activity checker.
68
+ */
69
+ export function computeEvidenceSimHash(checkpoint) {
70
+ const features = extractFeatures(checkpoint);
71
+ return simhashFromFeatures(features);
72
+ }
73
+ /**
74
+ * Compute the Hamming distance between two bytes32 hex strings.
75
+ * Useful for client-side similarity checking before submitting on-chain.
76
+ */
77
+ export function hammingDistance(a, b) {
78
+ const xor = BigInt(a) ^ BigInt(b);
79
+ let count = 0;
80
+ let bits = xor;
81
+ while (bits > 0n) {
82
+ count += Number(bits & 1n);
83
+ bits >>= 1n;
84
+ }
85
+ return count;
86
+ }
87
+ //# sourceMappingURL=evidence-simhash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-simhash.js","sourceRoot":"","sources":["../../src/earning/evidence-simhash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Display index for operator-facing JSON (jinn fleet / balance / rewards).
3
+ * Persisted {@link ServiceState.index} is the HD derivation slot (typically 1-based).
4
+ */
5
+ import type { ServiceState } from './types.js';
6
+ /** Same value as `services[].index` in GET fleet v1 and related surfaces. */
7
+ export declare function displayFleetServiceIndex(svc: ServiceState): number;
8
+ export declare function findServiceByDisplayIndex(services: ServiceState[], displayIndex: number): ServiceState | undefined;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Display index for operator-facing JSON (jinn fleet / balance / rewards).
3
+ * Persisted {@link ServiceState.index} is the HD derivation slot (typically 1-based).
4
+ */
5
+ /** Same value as `services[].index` in GET fleet v1 and related surfaces. */
6
+ export function displayFleetServiceIndex(svc) {
7
+ return Math.max(0, svc.index - 1);
8
+ }
9
+ export function findServiceByDisplayIndex(services, displayIndex) {
10
+ return services.find(s => displayFleetServiceIndex(s) === displayIndex);
11
+ }
12
+ //# sourceMappingURL=fleet-display-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleet-display-index.js","sourceRoot":"","sources":["../../src/earning/fleet-display-index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,6EAA6E;AAC7E,MAAM,UAAU,wBAAwB,CAAC,GAAiB;IACxD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,QAAwB,EACxB,YAAoB;IAEpB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Retire one standard (distributor-managed) fleet service: distributor.unstakeAndWithdraw,
3
+ * then drop the row from local fleet JSON.
4
+ */
5
+ import type { PublicClient } from 'viem';
6
+ import type { WalletClient } from 'viem';
7
+ import type { FleetStateStore } from './store.js';
8
+ import type { FleetState, ServiceState } from './types.js';
9
+ export interface RetireFleetServiceParams {
10
+ publicClient: PublicClient;
11
+ masterWallet: WalletClient;
12
+ distributorAddress: string | undefined;
13
+ fleetStore: FleetStateStore;
14
+ chain: 'base' | 'base-sepolia';
15
+ serviceIndex: number;
16
+ }
17
+ export interface RetireFleetServiceResult {
18
+ ok: boolean;
19
+ txHash?: string;
20
+ message: string;
21
+ }
22
+ /**
23
+ * Unstake + terminate + unbond via ExternalStakingDistributor, then remove the service from disk.
24
+ * Self-bond mode is not supported here (return ok: false).
25
+ */
26
+ export declare function retireFleetServiceOnChain(params: RetireFleetServiceParams): Promise<RetireFleetServiceResult>;
27
+ /** Read-only: whether the service row exists in fleet JSON. */
28
+ export declare function findFleetService(state: FleetState, serviceIndex: number): ServiceState | undefined;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Retire one standard (distributor-managed) fleet service: distributor.unstakeAndWithdraw,
3
+ * then drop the row from local fleet JSON.
4
+ */
5
+ import { encodeFunctionData, getAddress, pad } from 'viem';
6
+ import { STOLAS_DISTRIBUTOR_ABI } from './contracts.js';
7
+ import { viemSendTransactionWithRetry, waitForTransactionReceiptWithRetry, } from '../tx-retry.js';
8
+ /**
9
+ * Unstake + terminate + unbond via ExternalStakingDistributor, then remove the service from disk.
10
+ * Self-bond mode is not supported here (return ok: false).
11
+ */
12
+ export async function retireFleetServiceOnChain(params) {
13
+ const { publicClient, masterWallet, distributorAddress, fleetStore, chain, serviceIndex } = params;
14
+ const state = await fleetStore.load(chain);
15
+ const stakingMode = state.staking_mode;
16
+ if (stakingMode !== 'standard') {
17
+ return {
18
+ ok: false,
19
+ message: `fleet retire is only implemented for staking_mode=standard (got ${stakingMode}).`,
20
+ };
21
+ }
22
+ if (!distributorAddress) {
23
+ return {
24
+ ok: false,
25
+ message: 'No distributor address in chain config; cannot call unstakeAndWithdraw.',
26
+ };
27
+ }
28
+ const svc = state.services.find(s => s.index === serviceIndex);
29
+ if (!svc) {
30
+ return { ok: true, message: `Service index ${serviceIndex} not in fleet state (already removed).` };
31
+ }
32
+ if (svc.service_id === null || !svc.staking_address) {
33
+ return {
34
+ ok: false,
35
+ message: `Service ${serviceIndex} is missing service_id or staking_address; cannot retire on-chain.`,
36
+ };
37
+ }
38
+ const stakingProxy = getAddress(svc.staking_address);
39
+ const operation = pad(stakingProxy, { size: 32 });
40
+ const data = encodeFunctionData({
41
+ abi: STOLAS_DISTRIBUTOR_ABI,
42
+ functionName: 'unstakeAndWithdraw',
43
+ args: [stakingProxy, BigInt(svc.service_id), operation],
44
+ });
45
+ try {
46
+ const txHash = await viemSendTransactionWithRetry(masterWallet, publicClient, {
47
+ account: masterWallet.account,
48
+ to: getAddress(distributorAddress),
49
+ data,
50
+ gas: 2500000n,
51
+ });
52
+ const receipt = await waitForTransactionReceiptWithRetry(publicClient, txHash);
53
+ if (receipt.status !== 'success') {
54
+ return {
55
+ ok: false,
56
+ message: `unstakeAndWithdraw tx failed or timed out (hash=${txHash}).`,
57
+ };
58
+ }
59
+ await fleetStore.removeService(serviceIndex);
60
+ return {
61
+ ok: true,
62
+ txHash,
63
+ message: `Retired service ${serviceIndex} (service_id=${svc.service_id}).`,
64
+ };
65
+ }
66
+ catch (e) {
67
+ const msg = e instanceof Error ? e.message : String(e);
68
+ return { ok: false, message: msg };
69
+ }
70
+ }
71
+ /** Read-only: whether the service row exists in fleet JSON. */
72
+ export function findFleetService(state, serviceIndex) {
73
+ return state.services.find(s => s.index === serviceIndex);
74
+ }
75
+ //# sourceMappingURL=fleet-retire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleet-retire.js","sourceRoot":"","sources":["../../src/earning/fleet-retire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * JINN reward claiming helper for the Phase 1a staking contract.
3
+ *
4
+ * The OLAS-style staking proxy exposes `calculateStakingReward()` plus
5
+ * owner-authorized `claim()` / `checkpointAndClaim()` entrypoints.
6
+ */
7
+ import type { PublicClient, WalletClient } from 'viem';
8
+ export declare const JINN_STAKING_ABI: readonly [{
9
+ readonly inputs: readonly [{
10
+ readonly name: "serviceId";
11
+ readonly type: "uint256";
12
+ }];
13
+ readonly name: "calculateStakingReward";
14
+ readonly outputs: readonly [{
15
+ readonly name: "amount";
16
+ readonly type: "uint256";
17
+ }];
18
+ readonly stateMutability: "view";
19
+ readonly type: "function";
20
+ }, {
21
+ readonly inputs: readonly [{
22
+ readonly name: "serviceId";
23
+ readonly type: "uint256";
24
+ }];
25
+ readonly name: "claim";
26
+ readonly outputs: readonly [{
27
+ readonly name: "amount";
28
+ readonly type: "uint256";
29
+ }];
30
+ readonly stateMutability: "nonpayable";
31
+ readonly type: "function";
32
+ }, {
33
+ readonly inputs: readonly [{
34
+ readonly name: "serviceId";
35
+ readonly type: "uint256";
36
+ }];
37
+ readonly name: "checkpointAndClaim";
38
+ readonly outputs: readonly [{
39
+ readonly name: "amount";
40
+ readonly type: "uint256";
41
+ }];
42
+ readonly stateMutability: "nonpayable";
43
+ readonly type: "function";
44
+ }];
45
+ /**
46
+ * Claim JINN rewards from the Phase 1a staking contract.
47
+ *
48
+ * Returns { claimed: false, amount: 0n } until the Phase 1a contract is
49
+ * deployed and the ABI is finalised. Wiring up is a matter of uncommenting
50
+ * the contract call below.
51
+ *
52
+ * @param publicClient — viem PublicClient for read calls
53
+ * @param walletClient — viem WalletClient for write calls
54
+ * @param stakingContractAddress — Phase 1a JINN staking contract address
55
+ * @param serviceId — OLAS service ID registered in the staking contract
56
+ */
57
+ export declare function claimJinnRewards(publicClient: PublicClient, walletClient: WalletClient, stakingContractAddress: `0x${string}`, serviceId: number, options?: {
58
+ checkpoint?: boolean;
59
+ }): Promise<{
60
+ claimed: boolean;
61
+ amount: bigint;
62
+ }>;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * JINN reward claiming helper for the Phase 1a staking contract.
3
+ *
4
+ * The OLAS-style staking proxy exposes `calculateStakingReward()` plus
5
+ * owner-authorized `claim()` / `checkpointAndClaim()` entrypoints.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // ABI fragment — only the functions we call
9
+ // ---------------------------------------------------------------------------
10
+ export const JINN_STAKING_ABI = [
11
+ {
12
+ inputs: [
13
+ { name: 'serviceId', type: 'uint256' },
14
+ ],
15
+ name: 'calculateStakingReward',
16
+ outputs: [{ name: 'amount', type: 'uint256' }],
17
+ stateMutability: 'view',
18
+ type: 'function',
19
+ },
20
+ {
21
+ inputs: [
22
+ { name: 'serviceId', type: 'uint256' },
23
+ ],
24
+ name: 'claim',
25
+ outputs: [{ name: 'amount', type: 'uint256' }],
26
+ stateMutability: 'nonpayable',
27
+ type: 'function',
28
+ },
29
+ {
30
+ inputs: [
31
+ { name: 'serviceId', type: 'uint256' },
32
+ ],
33
+ name: 'checkpointAndClaim',
34
+ outputs: [{ name: 'amount', type: 'uint256' }],
35
+ stateMutability: 'nonpayable',
36
+ type: 'function',
37
+ },
38
+ ];
39
+ // ---------------------------------------------------------------------------
40
+ // Claim function
41
+ // ---------------------------------------------------------------------------
42
+ /**
43
+ * Claim JINN rewards from the Phase 1a staking contract.
44
+ *
45
+ * Returns { claimed: false, amount: 0n } until the Phase 1a contract is
46
+ * deployed and the ABI is finalised. Wiring up is a matter of uncommenting
47
+ * the contract call below.
48
+ *
49
+ * @param publicClient — viem PublicClient for read calls
50
+ * @param walletClient — viem WalletClient for write calls
51
+ * @param stakingContractAddress — Phase 1a JINN staking contract address
52
+ * @param serviceId — OLAS service ID registered in the staking contract
53
+ */
54
+ export async function claimJinnRewards(publicClient, walletClient, stakingContractAddress, serviceId, options = {}) {
55
+ const pending = await publicClient.readContract({
56
+ address: stakingContractAddress,
57
+ abi: JINN_STAKING_ABI,
58
+ functionName: 'calculateStakingReward',
59
+ args: [BigInt(serviceId)],
60
+ });
61
+ if (pending === 0n) {
62
+ return { claimed: false, amount: 0n };
63
+ }
64
+ // Submit claim transaction
65
+ const [account] = await walletClient.getAddresses();
66
+ const hash = await walletClient.writeContract({
67
+ address: stakingContractAddress,
68
+ abi: JINN_STAKING_ABI,
69
+ functionName: options.checkpoint ? 'checkpointAndClaim' : 'claim',
70
+ args: [BigInt(serviceId)],
71
+ account,
72
+ chain: walletClient.chain ?? null,
73
+ });
74
+ // Wait for confirmation
75
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
76
+ if (receipt.status !== 'success') {
77
+ throw new Error(`JINN reward claim tx reverted: ${hash}`);
78
+ }
79
+ return { claimed: true, amount: pending };
80
+ }
81
+ //# sourceMappingURL=jinn-rewards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jinn-rewards.js","sourceRoot":"","sources":["../../src/earning/jinn-rewards.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,8EAA8E;AAC9E,4CAA4C;AAC5C,8EAA8E;AAE9E,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B;QACE,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE;SACvC;QACD,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC9C,eAAe,EAAE,MAAM;QACvB,IAAI,EAAE,UAAU;KACjB;IACD;QACE,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE;SACvC;QACD,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC9C,eAAe,EAAE,YAAY;QAC7B,IAAI,EAAE,UAAU;KACjB;IACD;QACE,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE;SACvC;QACD,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC9C,eAAe,EAAE,YAAY;QAC7B,IAAI,EAAE,UAAU;KACjB;CACO,CAAC;AAEX,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAA0B,EAC1B,YAA0B,EAC1B,sBAAqC,EACrC,SAAiB,EACjB,UAAoC,EAAE;IAEtC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC;QAC9C,OAAO,EAAE,sBAAsB;QAC/B,GAAG,EAAE,gBAAgB;QACrB,YAAY,EAAE,wBAAwB;QACtC,IAAI,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;KAC1B,CAAC,CAAC;IAEH,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxC,CAAC;IAED,2BAA2B;IAC3B,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,YAAY,CAAC,YAAY,EAAE,CAAC;IACpD,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC;QAC5C,OAAO,EAAE,sBAAsB;QAC/B,GAAG,EAAE,gBAAgB;QACrB,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO;QACjE,IAAI,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACzB,OAAO;QACP,KAAK,EAAE,YAAY,CAAC,KAAK,IAAI,IAAI;KAClC,CAAC,CAAC;IAEH,wBAAwB;IACxB,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,yBAAyB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Next HD service slot after existing rows (avoids reusing an index after a middle-row delete). */
2
+ export declare function nextFleetServiceIndex(services: Array<{
3
+ index: number;
4
+ }>): number;
@@ -0,0 +1,7 @@
1
+ /** Next HD service slot after existing rows (avoids reusing an index after a middle-row delete). */
2
+ export function nextFleetServiceIndex(services) {
3
+ if (services.length === 0)
4
+ return 1;
5
+ return Math.max(...services.map(s => s.index)) + 1;
6
+ }
7
+ //# sourceMappingURL=next-service-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-service-index.js","sourceRoot":"","sources":["../../src/earning/next-service-index.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,MAAM,UAAU,qBAAqB,CAAC,QAAkC;IACtE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Best-effort recovery of ETH from a service Safe / agent EOA when bootstrap abandons
3
+ * a persisted Safe (reconcile clear or stale standard-mode state).
4
+ *
5
+ * ERC-20 balances on the old Safe are not swept yet — see TODO below.
6
+ */
7
+ import { type Hex } from 'viem';
8
+ import type { ServiceState } from './types.js';
9
+ import { type JinnOnchainNetwork } from './viem-clients.js';
10
+ import { type PrivateKeyAccount } from 'viem/accounts';
11
+ import type { PublicClient } from 'viem';
12
+ /**
13
+ * If reconcile (or similar) will drop or replace `safe_address`, return the on-chain
14
+ * address that will no longer be tracked so we can sweep it first.
15
+ */
16
+ export declare function previousSafeBeingAbandoned(svc: ServiceState, patch: Partial<ServiceState>): string | null;
17
+ export interface SweepOrphanedServiceFundsParams {
18
+ rpcUrl: string;
19
+ network: JinnOnchainNetwork;
20
+ publicClient: PublicClient;
21
+ masterAddress: string;
22
+ masterAccount: PrivateKeyAccount;
23
+ serviceIndex: number;
24
+ agentPrivateKey: Hex;
25
+ agentAddress: string;
26
+ abandonedSafeAddress: string;
27
+ minAgentReserveWei: bigint;
28
+ }
29
+ /**
30
+ * Sweep ETH from an abandoned deployed Safe (via Safe.execTransaction) and excess
31
+ * agent EOA ETH to the master. Never throws; logs actionable errors on failure.
32
+ */
33
+ export declare function sweepOrphanedServiceFunds(params: SweepOrphanedServiceFundsParams): Promise<void>;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Best-effort recovery of ETH from a service Safe / agent EOA when bootstrap abandons
3
+ * a persisted Safe (reconcile clear or stale standard-mode state).
4
+ *
5
+ * ERC-20 balances on the old Safe are not swept yet — see TODO below.
6
+ */
7
+ import { formatEther, getAddress, zeroAddress } from 'viem';
8
+ import { executeSafeTxDirect } from './safe-adapter.js';
9
+ import { createJinnWalletClient } from './viem-clients.js';
10
+ import { privateKeyToAccount } from 'viem/accounts';
11
+ import { viemSendTransactionWithRetry, waitForTransactionReceiptWithRetry, } from '../tx-retry.js';
12
+ function isZeroishAddress(addr) {
13
+ if (!addr)
14
+ return true;
15
+ try {
16
+ return getAddress(addr) === getAddress(zeroAddress);
17
+ }
18
+ catch {
19
+ return true;
20
+ }
21
+ }
22
+ /**
23
+ * If reconcile (or similar) will drop or replace `safe_address`, return the on-chain
24
+ * address that will no longer be tracked so we can sweep it first.
25
+ */
26
+ export function previousSafeBeingAbandoned(svc, patch) {
27
+ const prev = svc.safe_address;
28
+ if (!prev || isZeroishAddress(prev))
29
+ return null;
30
+ let prevNorm;
31
+ try {
32
+ prevNorm = getAddress(prev);
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ if (patch.safe_address === null)
38
+ return prevNorm;
39
+ if (patch.safe_address !== undefined && patch.safe_address !== null) {
40
+ try {
41
+ const nextNorm = getAddress(patch.safe_address);
42
+ if (nextNorm !== prevNorm)
43
+ return prevNorm;
44
+ }
45
+ catch {
46
+ return prevNorm;
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ /**
52
+ * Sweep ETH from an abandoned deployed Safe (via Safe.execTransaction) and excess
53
+ * agent EOA ETH to the master. Never throws; logs actionable errors on failure.
54
+ */
55
+ export async function sweepOrphanedServiceFunds(params) {
56
+ const { serviceIndex, masterAddress } = params;
57
+ let masterNorm;
58
+ try {
59
+ masterNorm = getAddress(masterAddress);
60
+ }
61
+ catch {
62
+ console.error(`[jinn-earning] Service ${serviceIndex}: orphan sweep skipped — invalid master_address.`);
63
+ return;
64
+ }
65
+ try {
66
+ await runOrphanSweepBody({
67
+ ...params,
68
+ masterNorm,
69
+ });
70
+ }
71
+ catch (e) {
72
+ const msg = e instanceof Error ? e.message : String(e);
73
+ console.error(`[jinn-earning] Service ${serviceIndex}: orphan sweep aborted (${msg}). Fix RPC connectivity or retry bootstrap later.`);
74
+ }
75
+ }
76
+ async function runOrphanSweepBody(params) {
77
+ const { rpcUrl, network, publicClient, masterNorm, masterAccount, serviceIndex, agentPrivateKey, agentAddress, abandonedSafeAddress, minAgentReserveWei, } = params;
78
+ const code = await publicClient.getCode({ address: getAddress(abandonedSafeAddress) });
79
+ const safeBal = await publicClient.getBalance({ address: getAddress(abandonedSafeAddress) });
80
+ if (code !== undefined && code !== '0x' && safeBal > 0n) {
81
+ let agentBal = await publicClient.getBalance({ address: getAddress(agentAddress) });
82
+ if (agentBal < minAgentReserveWei) {
83
+ const need = minAgentReserveWei - agentBal;
84
+ const masterBal = await publicClient.getBalance({ address: masterNorm });
85
+ if (masterBal > need) {
86
+ try {
87
+ console.error(`[jinn-earning] Service ${serviceIndex}: funding agent ${agentAddress} with ${need} wei so the Safe owner can exec orphan sweep from ${abandonedSafeAddress}.`);
88
+ const masterWallet = createJinnWalletClient(rpcUrl, network, masterAccount);
89
+ const fundHash = await viemSendTransactionWithRetry(masterWallet, publicClient, {
90
+ account: masterAccount,
91
+ to: getAddress(agentAddress),
92
+ value: need,
93
+ });
94
+ await waitForTransactionReceiptWithRetry(publicClient, fundHash);
95
+ agentBal = await publicClient.getBalance({ address: getAddress(agentAddress) });
96
+ }
97
+ catch (e) {
98
+ const msg = e instanceof Error ? e.message : String(e);
99
+ console.error(`[jinn-earning] Service ${serviceIndex}: could not fund agent for orphan Safe sweep (${abandonedSafeAddress} holds ${safeBal} wei). ${msg} — send at least ${formatEther(need)} ETH to the agent EOA, then re-run bootstrap.`);
100
+ }
101
+ }
102
+ else {
103
+ console.error(`[jinn-earning] Service ${serviceIndex}: orphan Safe ${abandonedSafeAddress} holds ${safeBal} wei but master and agent lack gas to sweep. Fund master or agent, then re-run bootstrap.`);
104
+ }
105
+ }
106
+ agentBal = await publicClient.getBalance({ address: getAddress(agentAddress) });
107
+ if (agentBal >= minAgentReserveWei) {
108
+ try {
109
+ const { hash } = await executeSafeTxDirect({
110
+ rpcUrl,
111
+ signerKey: agentPrivateKey,
112
+ safeAddress: abandonedSafeAddress,
113
+ to: getAddress(masterNorm),
114
+ value: safeBal,
115
+ data: '0x',
116
+ });
117
+ const receipt = await waitForTransactionReceiptWithRetry(publicClient, hash);
118
+ if (receipt.status !== 'success') {
119
+ console.error(`[jinn-earning] Service ${serviceIndex}: orphan Safe sweep tx failed or timed out (safe=${abandonedSafeAddress}, tx=${hash}). Re-run bootstrap to retry.`);
120
+ }
121
+ else {
122
+ console.error(`[jinn-earning] Service ${serviceIndex}: swept ${safeBal} wei from orphan Safe ${abandonedSafeAddress} to master (tx: ${hash}).`);
123
+ }
124
+ }
125
+ catch (e) {
126
+ const msg = e instanceof Error ? e.message : String(e);
127
+ console.error(`[jinn-earning] Service ${serviceIndex}: orphan Safe sweep failed for ${abandonedSafeAddress} (${msg}). Ensure the agent EOA is still a Safe owner and re-run bootstrap, or move funds manually to master ${masterNorm}.`);
128
+ }
129
+ }
130
+ }
131
+ // TODO: sweep ERC-20 (e.g. OLAS) from abandoned Safe via Safe.execTransaction(transfer).
132
+ const agentAccount = privateKeyToAccount(agentPrivateKey);
133
+ const agentWallet = createJinnWalletClient(rpcUrl, network, agentAccount);
134
+ const finalAgentBal = await publicClient.getBalance({ address: getAddress(agentAddress) });
135
+ const transferable = finalAgentBal > minAgentReserveWei ? finalAgentBal - minAgentReserveWei : 0n;
136
+ if (transferable > 0n) {
137
+ try {
138
+ const txHash = await viemSendTransactionWithRetry(agentWallet, publicClient, {
139
+ account: agentAccount,
140
+ to: getAddress(masterNorm),
141
+ value: transferable,
142
+ });
143
+ const receipt = await waitForTransactionReceiptWithRetry(publicClient, txHash);
144
+ if (receipt.status !== 'success') {
145
+ console.error(`[jinn-earning] Service ${serviceIndex}: agent EOA sweep tx failed (tx=${txHash}). Re-run bootstrap to retry.`);
146
+ }
147
+ else {
148
+ console.error(`[jinn-earning] Service ${serviceIndex}: swept ${transferable} wei from agent ${agentAddress} to master (tx: ${txHash}).`);
149
+ }
150
+ }
151
+ catch (e) {
152
+ const msg = e instanceof Error ? e.message : String(e);
153
+ console.error(`[jinn-earning] Service ${serviceIndex}: agent EOA sweep failed (${msg}). Re-run bootstrap to retry or send manually to master ${masterNorm}.`);
154
+ }
155
+ }
156
+ }
157
+ //# sourceMappingURL=orphan-sweep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orphan-sweep.js","sourceRoot":"","sources":["../../src/earning/orphan-sweep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Pure reconciliation rules: persisted fleet service state vs on-chain signals.
3
+ * Used by FleetBootstrapper so operators need not hand-edit earning_state.json.
4
+ */
5
+ import type { ServiceState } from './types.js';
6
+ /** `revert` = call reverted (authoritative). `inconclusive` = RPC/transport — do not clear state. */
7
+ export type ChainReadFailure = 'revert' | 'missing' | 'inconclusive';
8
+ /** On-chain view gathered before applying rules (all reads best-effort). */
9
+ export interface ServiceChainSignals {
10
+ stakingState: number | ChainReadFailure;
11
+ /** Staking.getServiceInfo().multisig when readable */
12
+ stakingMultisig: string | null;
13
+ /** ServiceRegistry.getService().state when readable */
14
+ registryState: number | ChainReadFailure;
15
+ /** ServiceRegistry.getService().multisig when readable */
16
+ registryMultisig: string | null;
17
+ /** Whether bytecode exists at persisted safe_address */
18
+ safeDeployed: boolean | null;
19
+ }
20
+ export interface ReconcilePatch {
21
+ /** Operator-facing line (logged by bootstrap) */
22
+ message: string;
23
+ patch: Partial<ServiceState>;
24
+ }
25
+ /**
26
+ * Standard (distributor) mode: staking proxy is source of truth for stake/eviction.
27
+ */
28
+ export declare function reconcileStandardService(index: number, svc: ServiceState, chain: ServiceChainSignals, ctx: {
29
+ stakingContract: string;
30
+ }): ReconcilePatch | null;
31
+ /**
32
+ * Self-bond mode: registry + Safe bytecode + staking.
33
+ */
34
+ export declare function reconcileSelfBondService(index: number, svc: ServiceState, chain: ServiceChainSignals): ReconcilePatch | null;
35
+ export declare function reconcileServiceAgainstChain(stakingMode: 'standard' | 'self-bond', svc: ServiceState, chain: ServiceChainSignals, ctx: {
36
+ stakingContract: string;
37
+ }): ReconcilePatch | null;