@claw-network/node 0.2.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 (190) hide show
  1. package/README.md +49 -0
  2. package/dist/api/api-key-store.d.ts +74 -0
  3. package/dist/api/api-key-store.d.ts.map +1 -0
  4. package/dist/api/api-key-store.js +170 -0
  5. package/dist/api/api-key-store.js.map +1 -0
  6. package/dist/api/auth.d.ts +30 -0
  7. package/dist/api/auth.d.ts.map +1 -0
  8. package/dist/api/auth.js +115 -0
  9. package/dist/api/auth.js.map +1 -0
  10. package/dist/api/legacy.d.ts +26 -0
  11. package/dist/api/legacy.d.ts.map +1 -0
  12. package/dist/api/legacy.js +281 -0
  13. package/dist/api/legacy.js.map +1 -0
  14. package/dist/api/middleware.d.ts +35 -0
  15. package/dist/api/middleware.d.ts.map +1 -0
  16. package/dist/api/middleware.js +75 -0
  17. package/dist/api/middleware.js.map +1 -0
  18. package/dist/api/response.d.ts +85 -0
  19. package/dist/api/response.d.ts.map +1 -0
  20. package/dist/api/response.js +185 -0
  21. package/dist/api/response.js.map +1 -0
  22. package/dist/api/router.d.ts +45 -0
  23. package/dist/api/router.d.ts.map +1 -0
  24. package/dist/api/router.js +183 -0
  25. package/dist/api/router.js.map +1 -0
  26. package/dist/api/routes/admin.d.ts +11 -0
  27. package/dist/api/routes/admin.d.ts.map +1 -0
  28. package/dist/api/routes/admin.js +124 -0
  29. package/dist/api/routes/admin.js.map +1 -0
  30. package/dist/api/routes/contracts.d.ts +7 -0
  31. package/dist/api/routes/contracts.d.ts.map +1 -0
  32. package/dist/api/routes/contracts.js +665 -0
  33. package/dist/api/routes/contracts.js.map +1 -0
  34. package/dist/api/routes/dao.d.ts +7 -0
  35. package/dist/api/routes/dao.d.ts.map +1 -0
  36. package/dist/api/routes/dao.js +549 -0
  37. package/dist/api/routes/dao.js.map +1 -0
  38. package/dist/api/routes/dev.d.ts +9 -0
  39. package/dist/api/routes/dev.d.ts.map +1 -0
  40. package/dist/api/routes/dev.js +273 -0
  41. package/dist/api/routes/dev.js.map +1 -0
  42. package/dist/api/routes/escrows.d.ts +7 -0
  43. package/dist/api/routes/escrows.d.ts.map +1 -0
  44. package/dist/api/routes/escrows.js +454 -0
  45. package/dist/api/routes/escrows.js.map +1 -0
  46. package/dist/api/routes/identities.d.ts +7 -0
  47. package/dist/api/routes/identities.d.ts.map +1 -0
  48. package/dist/api/routes/identities.js +245 -0
  49. package/dist/api/routes/identities.js.map +1 -0
  50. package/dist/api/routes/markets-capabilities.d.ts +7 -0
  51. package/dist/api/routes/markets-capabilities.d.ts.map +1 -0
  52. package/dist/api/routes/markets-capabilities.js +477 -0
  53. package/dist/api/routes/markets-capabilities.js.map +1 -0
  54. package/dist/api/routes/markets-disputes.d.ts +7 -0
  55. package/dist/api/routes/markets-disputes.d.ts.map +1 -0
  56. package/dist/api/routes/markets-disputes.js +102 -0
  57. package/dist/api/routes/markets-disputes.js.map +1 -0
  58. package/dist/api/routes/markets-info.d.ts +7 -0
  59. package/dist/api/routes/markets-info.d.ts.map +1 -0
  60. package/dist/api/routes/markets-info.js +523 -0
  61. package/dist/api/routes/markets-info.js.map +1 -0
  62. package/dist/api/routes/markets-search.d.ts +7 -0
  63. package/dist/api/routes/markets-search.d.ts.map +1 -0
  64. package/dist/api/routes/markets-search.js +38 -0
  65. package/dist/api/routes/markets-search.js.map +1 -0
  66. package/dist/api/routes/markets-tasks.d.ts +7 -0
  67. package/dist/api/routes/markets-tasks.d.ts.map +1 -0
  68. package/dist/api/routes/markets-tasks.js +539 -0
  69. package/dist/api/routes/markets-tasks.js.map +1 -0
  70. package/dist/api/routes/node.d.ts +7 -0
  71. package/dist/api/routes/node.d.ts.map +1 -0
  72. package/dist/api/routes/node.js +53 -0
  73. package/dist/api/routes/node.js.map +1 -0
  74. package/dist/api/routes/nonce.d.ts +10 -0
  75. package/dist/api/routes/nonce.d.ts.map +1 -0
  76. package/dist/api/routes/nonce.js +65 -0
  77. package/dist/api/routes/nonce.js.map +1 -0
  78. package/dist/api/routes/reputations.d.ts +7 -0
  79. package/dist/api/routes/reputations.d.ts.map +1 -0
  80. package/dist/api/routes/reputations.js +243 -0
  81. package/dist/api/routes/reputations.js.map +1 -0
  82. package/dist/api/routes/transfers.d.ts +7 -0
  83. package/dist/api/routes/transfers.d.ts.map +1 -0
  84. package/dist/api/routes/transfers.js +88 -0
  85. package/dist/api/routes/transfers.js.map +1 -0
  86. package/dist/api/routes/wallets.d.ts +7 -0
  87. package/dist/api/routes/wallets.d.ts.map +1 -0
  88. package/dist/api/routes/wallets.js +132 -0
  89. package/dist/api/routes/wallets.js.map +1 -0
  90. package/dist/api/schemas/common.d.ts +45 -0
  91. package/dist/api/schemas/common.d.ts.map +1 -0
  92. package/dist/api/schemas/common.js +30 -0
  93. package/dist/api/schemas/common.js.map +1 -0
  94. package/dist/api/schemas/contracts.d.ts +284 -0
  95. package/dist/api/schemas/contracts.d.ts.map +1 -0
  96. package/dist/api/schemas/contracts.js +79 -0
  97. package/dist/api/schemas/contracts.js.map +1 -0
  98. package/dist/api/schemas/dao.d.ts +271 -0
  99. package/dist/api/schemas/dao.d.ts.map +1 -0
  100. package/dist/api/schemas/dao.js +78 -0
  101. package/dist/api/schemas/dao.js.map +1 -0
  102. package/dist/api/schemas/identity.d.ts +75 -0
  103. package/dist/api/schemas/identity.d.ts.map +1 -0
  104. package/dist/api/schemas/identity.js +32 -0
  105. package/dist/api/schemas/identity.js.map +1 -0
  106. package/dist/api/schemas/markets.d.ts +822 -0
  107. package/dist/api/schemas/markets.d.ts.map +1 -0
  108. package/dist/api/schemas/markets.js +246 -0
  109. package/dist/api/schemas/markets.js.map +1 -0
  110. package/dist/api/schemas/wallet.d.ts +163 -0
  111. package/dist/api/schemas/wallet.d.ts.map +1 -0
  112. package/dist/api/schemas/wallet.js +54 -0
  113. package/dist/api/schemas/wallet.js.map +1 -0
  114. package/dist/api/server.d.ts +45 -0
  115. package/dist/api/server.d.ts.map +1 -0
  116. package/dist/api/server.js +131 -0
  117. package/dist/api/server.js.map +1 -0
  118. package/dist/api/types.d.ts +69 -0
  119. package/dist/api/types.d.ts.map +1 -0
  120. package/dist/api/types.js +196 -0
  121. package/dist/api/types.js.map +1 -0
  122. package/dist/daemon.d.ts +11 -0
  123. package/dist/daemon.d.ts.map +1 -0
  124. package/dist/daemon.js +248 -0
  125. package/dist/daemon.js.map +1 -0
  126. package/dist/index.d.ts +137 -0
  127. package/dist/index.d.ts.map +1 -0
  128. package/dist/index.js +795 -0
  129. package/dist/index.js.map +1 -0
  130. package/dist/indexer/index.d.ts +10 -0
  131. package/dist/indexer/index.d.ts.map +1 -0
  132. package/dist/indexer/index.js +7 -0
  133. package/dist/indexer/index.js.map +1 -0
  134. package/dist/indexer/indexer.d.ts +60 -0
  135. package/dist/indexer/indexer.d.ts.map +1 -0
  136. package/dist/indexer/indexer.js +408 -0
  137. package/dist/indexer/indexer.js.map +1 -0
  138. package/dist/indexer/query.d.ts +141 -0
  139. package/dist/indexer/query.d.ts.map +1 -0
  140. package/dist/indexer/query.js +244 -0
  141. package/dist/indexer/query.js.map +1 -0
  142. package/dist/indexer/store.d.ts +95 -0
  143. package/dist/indexer/store.d.ts.map +1 -0
  144. package/dist/indexer/store.js +250 -0
  145. package/dist/indexer/store.js.map +1 -0
  146. package/dist/logger.d.ts +13 -0
  147. package/dist/logger.d.ts.map +1 -0
  148. package/dist/logger.js +37 -0
  149. package/dist/logger.js.map +1 -0
  150. package/dist/p2p/sync.d.ts +105 -0
  151. package/dist/p2p/sync.d.ts.map +1 -0
  152. package/dist/p2p/sync.js +875 -0
  153. package/dist/p2p/sync.js.map +1 -0
  154. package/dist/policy/liquidity-policy.d.ts +17 -0
  155. package/dist/policy/liquidity-policy.d.ts.map +1 -0
  156. package/dist/policy/liquidity-policy.js +112 -0
  157. package/dist/policy/liquidity-policy.js.map +1 -0
  158. package/dist/services/chain-config.d.ts +226 -0
  159. package/dist/services/chain-config.d.ts.map +1 -0
  160. package/dist/services/chain-config.js +105 -0
  161. package/dist/services/chain-config.js.map +1 -0
  162. package/dist/services/contract-provider.d.ts +44 -0
  163. package/dist/services/contract-provider.d.ts.map +1 -0
  164. package/dist/services/contract-provider.js +167 -0
  165. package/dist/services/contract-provider.js.map +1 -0
  166. package/dist/services/contracts-service.d.ts +192 -0
  167. package/dist/services/contracts-service.d.ts.map +1 -0
  168. package/dist/services/contracts-service.js +336 -0
  169. package/dist/services/contracts-service.js.map +1 -0
  170. package/dist/services/dao-service.d.ts +245 -0
  171. package/dist/services/dao-service.d.ts.map +1 -0
  172. package/dist/services/dao-service.js +389 -0
  173. package/dist/services/dao-service.js.map +1 -0
  174. package/dist/services/identity-service.d.ts +150 -0
  175. package/dist/services/identity-service.d.ts.map +1 -0
  176. package/dist/services/identity-service.js +286 -0
  177. package/dist/services/identity-service.js.map +1 -0
  178. package/dist/services/index.d.ts +20 -0
  179. package/dist/services/index.d.ts.map +1 -0
  180. package/dist/services/index.js +15 -0
  181. package/dist/services/index.js.map +1 -0
  182. package/dist/services/reputation-service.d.ts +128 -0
  183. package/dist/services/reputation-service.d.ts.map +1 -0
  184. package/dist/services/reputation-service.js +204 -0
  185. package/dist/services/reputation-service.js.map +1 -0
  186. package/dist/services/wallet-service.d.ts +201 -0
  187. package/dist/services/wallet-service.d.ts.map +1 -0
  188. package/dist/services/wallet-service.js +402 -0
  189. package/dist/services/wallet-service.js.map +1 -0
  190. package/package.json +66 -0
@@ -0,0 +1,389 @@
1
+ /**
2
+ * DaoService — on-chain DAO governance operations for ClawDAO + ParamRegistry.
3
+ *
4
+ * Handles all DAO lifecycle operations that hit the chain. Route handlers
5
+ * delegate to it; it calls ClawDAO.sol and ParamRegistry.sol via
6
+ * ContractProvider and reads indexed proposal / vote data from IndexerQuery.
7
+ *
8
+ * Design decisions:
9
+ * - Proposal IDs are **uint256** on-chain (auto-incrementing `proposalCount`).
10
+ * REST-layer string IDs are NOT used for chain proposals — the chain
11
+ * returns the numeric ID from `propose()`.
12
+ * - `advanceProposal()` is an adapter that maps the REST `newStatus` string
13
+ * to the appropriate chain call: `queue()` or `execute()`.
14
+ * - Vote support values: 0 = Against, 1 = For, 2 = Abstain (Solidity uint8).
15
+ * - Delegation does NOT exist in ClawDAO.sol — delegation routes remain
16
+ * event-store-only (legacy fallback).
17
+ * - Treasury balance is read via `ClawToken.balanceOf(daoAddress)`.
18
+ * - Governance params are read via `ParamRegistry.getAllParams()`.
19
+ * - Token amounts are **integers** (ClawToken has 0 decimals).
20
+ */
21
+ import { keccak256, toUtf8Bytes } from 'ethers';
22
+ import { createLogger } from '../logger.js';
23
+ // ── Enums mirroring Solidity ──────────────────────────────────────────────
24
+ export var ProposalType;
25
+ (function (ProposalType) {
26
+ ProposalType[ProposalType["ParameterChange"] = 0] = "ParameterChange";
27
+ ProposalType[ProposalType["TreasurySpend"] = 1] = "TreasurySpend";
28
+ ProposalType[ProposalType["ProtocolUpgrade"] = 2] = "ProtocolUpgrade";
29
+ ProposalType[ProposalType["Emergency"] = 3] = "Emergency";
30
+ ProposalType[ProposalType["Signal"] = 4] = "Signal";
31
+ })(ProposalType || (ProposalType = {}));
32
+ export var ProposalStatus;
33
+ (function (ProposalStatus) {
34
+ ProposalStatus[ProposalStatus["Discussion"] = 0] = "Discussion";
35
+ ProposalStatus[ProposalStatus["Voting"] = 1] = "Voting";
36
+ ProposalStatus[ProposalStatus["Passed"] = 2] = "Passed";
37
+ ProposalStatus[ProposalStatus["Rejected"] = 3] = "Rejected";
38
+ ProposalStatus[ProposalStatus["Timelocked"] = 4] = "Timelocked";
39
+ ProposalStatus[ProposalStatus["Executed"] = 5] = "Executed";
40
+ ProposalStatus[ProposalStatus["Cancelled"] = 6] = "Cancelled";
41
+ ProposalStatus[ProposalStatus["Expired"] = 7] = "Expired";
42
+ })(ProposalStatus || (ProposalStatus = {}));
43
+ export var VoteSupport;
44
+ (function (VoteSupport) {
45
+ VoteSupport[VoteSupport["Against"] = 0] = "Against";
46
+ VoteSupport[VoteSupport["For"] = 1] = "For";
47
+ VoteSupport[VoteSupport["Abstain"] = 2] = "Abstain";
48
+ })(VoteSupport || (VoteSupport = {}));
49
+ // ── Mapping helpers ───────────────────────────────────────────────────────
50
+ const PROPOSAL_TYPE_MAP = {
51
+ parameter_change: ProposalType.ParameterChange,
52
+ treasury_spend: ProposalType.TreasurySpend,
53
+ protocol_upgrade: ProposalType.ProtocolUpgrade,
54
+ emergency: ProposalType.Emergency,
55
+ signal: ProposalType.Signal,
56
+ };
57
+ const VOTE_SUPPORT_MAP = {
58
+ for: VoteSupport.For,
59
+ against: VoteSupport.Against,
60
+ abstain: VoteSupport.Abstain,
61
+ };
62
+ /** Well-known ParamRegistry key names (matches Solidity constants). */
63
+ const PARAM_KEY_NAMES = {
64
+ [keccak256(toUtf8Bytes('MARKET_FEE_INFO'))]: 'MARKET_FEE_INFO',
65
+ [keccak256(toUtf8Bytes('MARKET_FEE_TASK'))]: 'MARKET_FEE_TASK',
66
+ [keccak256(toUtf8Bytes('MARKET_FEE_CAP'))]: 'MARKET_FEE_CAP',
67
+ [keccak256(toUtf8Bytes('MARKET_MIN_FEE'))]: 'MARKET_MIN_FEE',
68
+ [keccak256(toUtf8Bytes('MARKET_MAX_FEE'))]: 'MARKET_MAX_FEE',
69
+ [keccak256(toUtf8Bytes('ESCROW_BASE_RATE'))]: 'ESCROW_BASE_RATE',
70
+ [keccak256(toUtf8Bytes('ESCROW_HOLDING_RATE'))]: 'ESCROW_HOLDING_RATE',
71
+ [keccak256(toUtf8Bytes('ESCROW_MIN_FEE'))]: 'ESCROW_MIN_FEE',
72
+ [keccak256(toUtf8Bytes('MIN_TRANSFER_AMOUNT'))]: 'MIN_TRANSFER_AMOUNT',
73
+ [keccak256(toUtf8Bytes('MIN_ESCROW_AMOUNT'))]: 'MIN_ESCROW_AMOUNT',
74
+ [keccak256(toUtf8Bytes('MIN_NODE_STAKE'))]: 'MIN_NODE_STAKE',
75
+ [keccak256(toUtf8Bytes('UNSTAKE_COOLDOWN'))]: 'UNSTAKE_COOLDOWN',
76
+ [keccak256(toUtf8Bytes('VALIDATOR_REWARD_RATE'))]: 'VALIDATOR_REWARD_RATE',
77
+ [keccak256(toUtf8Bytes('SLASH_PER_VIOLATION'))]: 'SLASH_PER_VIOLATION',
78
+ [keccak256(toUtf8Bytes('TRUST_DECAY_RATE'))]: 'TRUST_DECAY_RATE',
79
+ [keccak256(toUtf8Bytes('EPOCH_DURATION'))]: 'EPOCH_DURATION',
80
+ [keccak256(toUtf8Bytes('PROPOSAL_THRESHOLD'))]: 'PROPOSAL_THRESHOLD',
81
+ [keccak256(toUtf8Bytes('VOTING_PERIOD'))]: 'VOTING_PERIOD',
82
+ [keccak256(toUtf8Bytes('TIMELOCK_DELAY'))]: 'TIMELOCK_DELAY',
83
+ [keccak256(toUtf8Bytes('QUORUM_BPS'))]: 'QUORUM_BPS',
84
+ };
85
+ // ---------------------------------------------------------------------------
86
+ // DaoService
87
+ // ---------------------------------------------------------------------------
88
+ export class DaoService {
89
+ contracts;
90
+ indexer;
91
+ log;
92
+ constructor(contracts, indexer, logger) {
93
+ this.contracts = contracts;
94
+ this.indexer = indexer;
95
+ this.log = logger ?? createLogger({ level: 'info' });
96
+ }
97
+ // ── Helpers ─────────────────────────────────────────────────────────
98
+ /** Hash a string to bytes32 (description hash, etc.) */
99
+ hash(value) {
100
+ return keccak256(toUtf8Bytes(value));
101
+ }
102
+ // =====================================================================
103
+ // READ operations
104
+ // =====================================================================
105
+ /**
106
+ * Fetch a single proposal from the chain via `getProposal()`.
107
+ */
108
+ async getProposal(proposalId) {
109
+ try {
110
+ const p = await this.contracts.dao.getProposal(proposalId);
111
+ return {
112
+ proposalId: Number(p.proposalId),
113
+ proposer: p.proposer,
114
+ pType: Number(p.pType),
115
+ status: Number(p.status),
116
+ descriptionHash: p.descriptionHash,
117
+ target: p.target,
118
+ snapshotBlock: Number(p.snapshotBlock),
119
+ createdAt: Number(p.createdAt),
120
+ discussionEndAt: Number(p.discussionEndAt),
121
+ votingEndAt: Number(p.votingEndAt),
122
+ timelockEndAt: Number(p.timelockEndAt),
123
+ forVotes: p.forVotes.toString(),
124
+ againstVotes: p.againstVotes.toString(),
125
+ abstainVotes: p.abstainVotes.toString(),
126
+ };
127
+ }
128
+ catch (err) {
129
+ this.log.warn('getProposal(%d) chain error: %s', proposalId, err.message);
130
+ return null;
131
+ }
132
+ }
133
+ /**
134
+ * List proposals from the indexer (paginated).
135
+ */
136
+ async listProposals(filter = {}) {
137
+ if (!this.indexer) {
138
+ return { proposals: [], total: 0, pagination: { limit: 20, offset: 0, hasMore: false } };
139
+ }
140
+ const result = this.indexer.getProposals(filter);
141
+ return {
142
+ proposals: result.items,
143
+ total: result.total,
144
+ pagination: {
145
+ limit: result.limit,
146
+ offset: result.offset,
147
+ hasMore: result.offset + result.items.length < result.total,
148
+ },
149
+ };
150
+ }
151
+ /**
152
+ * List votes from the indexer (paginated).
153
+ */
154
+ async listVotes(filter = {}) {
155
+ if (!this.indexer) {
156
+ return { votes: [], total: 0, pagination: { limit: 20, offset: 0, hasMore: false } };
157
+ }
158
+ const result = this.indexer.getVotes(filter);
159
+ return {
160
+ votes: result.items,
161
+ total: result.total,
162
+ pagination: {
163
+ limit: result.limit,
164
+ offset: result.offset,
165
+ hasMore: result.offset + result.items.length < result.total,
166
+ },
167
+ };
168
+ }
169
+ /**
170
+ * Get a voter's receipt for a specific proposal from the chain.
171
+ */
172
+ async getReceipt(proposalId, voter) {
173
+ const r = await this.contracts.dao.getReceipt(proposalId, voter);
174
+ return {
175
+ hasVoted: r.hasVoted,
176
+ support: Number(r.support),
177
+ weight: r.weight.toString(),
178
+ };
179
+ }
180
+ /**
181
+ * Get a voter's current voting power from the chain.
182
+ */
183
+ async getVotingPower(voter) {
184
+ const power = await this.contracts.dao.getVotingPower(voter);
185
+ return { voter, power: power.toString() };
186
+ }
187
+ /**
188
+ * Get the computed status of a proposal (auto-advances based on time).
189
+ */
190
+ async getComputedStatus(proposalId) {
191
+ const s = await this.contracts.dao.getStatus(proposalId);
192
+ return Number(s);
193
+ }
194
+ /**
195
+ * Check if a proposal has reached quorum.
196
+ */
197
+ async hasQuorum(proposalId) {
198
+ return this.contracts.dao.hasQuorum(proposalId);
199
+ }
200
+ /**
201
+ * Check if a proposal has passed (quorum + more for-votes than against).
202
+ */
203
+ async hasPassed(proposalId) {
204
+ return this.contracts.dao.hasPassed(proposalId);
205
+ }
206
+ // ── Treasury reads ──────────────────────────────────────────────────
207
+ /**
208
+ * Get the DAO treasury balance (ClawToken balance of the DAO contract).
209
+ */
210
+ async getTreasuryBalance() {
211
+ const daoAddress = (await this.contracts.dao.getAddress());
212
+ const balance = await this.contracts.token.balanceOf(daoAddress);
213
+ return {
214
+ balance: balance.toString(),
215
+ daoAddress,
216
+ };
217
+ }
218
+ // ── ParamRegistry reads ─────────────────────────────────────────────
219
+ /**
220
+ * Fetch all governance parameters from ParamRegistry on-chain.
221
+ */
222
+ async getAllParams() {
223
+ const [keys, values] = await this.contracts.paramRegistry.getAllParams();
224
+ const params = keys.map((keyHash, i) => ({
225
+ key: PARAM_KEY_NAMES[keyHash] ?? keyHash,
226
+ keyHash,
227
+ value: values[i].toString(),
228
+ }));
229
+ return { params, count: params.length };
230
+ }
231
+ /**
232
+ * Get a single governance parameter by name.
233
+ */
234
+ async getParam(name) {
235
+ const keyHash = this.hash(name);
236
+ const value = await this.contracts.paramRegistry.getParam(keyHash);
237
+ return { key: name, value: value.toString() };
238
+ }
239
+ // =====================================================================
240
+ // WRITE operations
241
+ // =====================================================================
242
+ /**
243
+ * Create a new proposal on-chain.
244
+ *
245
+ * @param pType Proposal type string (e.g. 'parameter_change').
246
+ * @param description Description text (hashed to bytes32).
247
+ * @param target Target contract address (or zero address for signal).
248
+ * @param callData Encoded call data (hex string, or '0x' for signal).
249
+ */
250
+ async propose(pType, description, target, callData) {
251
+ const typeEnum = PROPOSAL_TYPE_MAP[pType];
252
+ if (typeEnum === undefined) {
253
+ throw new Error(`Unknown proposal type: ${pType}`);
254
+ }
255
+ const descHash = this.hash(description);
256
+ this.log.info('propose(type=%s, target=%s)', pType, target);
257
+ const tx = await this.contracts.dao.propose(typeEnum, descHash, target, callData);
258
+ const receipt = await tx.wait();
259
+ const txHash = receipt.hash;
260
+ // Extract proposalId from ProposalCreated event.
261
+ const createdEvent = receipt.logs?.find((l) => l.fragment?.name === 'ProposalCreated');
262
+ const proposalId = createdEvent?.args?.[0]
263
+ ? Number(createdEvent.args[0])
264
+ : -1;
265
+ return {
266
+ txHash,
267
+ proposalId,
268
+ status: ProposalStatus[ProposalStatus.Discussion],
269
+ timestamp: Date.now(),
270
+ };
271
+ }
272
+ /**
273
+ * Cast a vote on-chain.
274
+ *
275
+ * @param proposalId Numeric proposal ID.
276
+ * @param option Vote option string: 'for', 'against', 'abstain'.
277
+ */
278
+ async vote(proposalId, option) {
279
+ const support = VOTE_SUPPORT_MAP[option];
280
+ if (support === undefined) {
281
+ throw new Error(`Unknown vote option: ${option}`);
282
+ }
283
+ this.log.info('vote(proposal=%d, support=%s)', proposalId, option);
284
+ const tx = await this.contracts.dao.vote(proposalId, support);
285
+ const receipt = await tx.wait();
286
+ return {
287
+ txHash: receipt.hash,
288
+ proposalId,
289
+ support,
290
+ timestamp: Date.now(),
291
+ };
292
+ }
293
+ /**
294
+ * Queue a passed proposal for timelock.
295
+ */
296
+ async queue(proposalId) {
297
+ this.log.info('queue(proposal=%d)', proposalId);
298
+ const tx = await this.contracts.dao.queue(proposalId);
299
+ const receipt = await tx.wait();
300
+ return {
301
+ txHash: receipt.hash,
302
+ proposalId,
303
+ status: ProposalStatus[ProposalStatus.Timelocked],
304
+ timestamp: Date.now(),
305
+ };
306
+ }
307
+ /**
308
+ * Execute a timelocked proposal.
309
+ */
310
+ async execute(proposalId) {
311
+ this.log.info('execute(proposal=%d)', proposalId);
312
+ const tx = await this.contracts.dao.execute(proposalId);
313
+ const receipt = await tx.wait();
314
+ return {
315
+ txHash: receipt.hash,
316
+ proposalId,
317
+ status: ProposalStatus[ProposalStatus.Executed],
318
+ timestamp: Date.now(),
319
+ };
320
+ }
321
+ /**
322
+ * Cancel a proposal (must be proposer or CANCELLER_ROLE).
323
+ */
324
+ async cancel(proposalId) {
325
+ this.log.info('cancel(proposal=%d)', proposalId);
326
+ const tx = await this.contracts.dao.cancel(proposalId);
327
+ const receipt = await tx.wait();
328
+ return {
329
+ txHash: receipt.hash,
330
+ proposalId,
331
+ status: ProposalStatus[ProposalStatus.Cancelled],
332
+ timestamp: Date.now(),
333
+ };
334
+ }
335
+ /**
336
+ * Advance a proposal to the next status.
337
+ *
338
+ * This is the REST-layer adapter: the `newStatus` string is mapped to
339
+ * the appropriate chain call (`queue` or `execute`).
340
+ *
341
+ * Mapping:
342
+ * - 'voting' → automatic (contract auto-advances after discussion period)
343
+ * - 'timelocked' / 'queued' → queue()
344
+ * - 'executed' → execute()
345
+ * - 'cancelled' → cancel()
346
+ *
347
+ * For statuses managed by on-chain time (Discussion→Voting, Voting→Passed),
348
+ * we call `getStatus()` which auto-advances, then return the current state.
349
+ */
350
+ async advanceProposal(proposalId, newStatus) {
351
+ const s = newStatus.toLowerCase();
352
+ if (s === 'timelocked' || s === 'queued') {
353
+ return this.queue(proposalId);
354
+ }
355
+ if (s === 'executed') {
356
+ return this.execute(proposalId);
357
+ }
358
+ if (s === 'cancelled') {
359
+ return this.cancel(proposalId);
360
+ }
361
+ // For time-based transitions, just read the computed status.
362
+ const currentStatus = await this.getComputedStatus(proposalId);
363
+ return {
364
+ txHash: '',
365
+ proposalId,
366
+ status: ProposalStatus[currentStatus],
367
+ timestamp: Date.now(),
368
+ };
369
+ }
370
+ // ── Treasury writes ─────────────────────────────────────────────────
371
+ /**
372
+ * Deposit Tokens into the DAO treasury.
373
+ *
374
+ * The caller must have approved the DAO contract to spend `amount` Tokens
375
+ * on ClawToken first. This service calls `ClawToken.transfer(daoAddress, amount)`.
376
+ */
377
+ async treasuryDeposit(amount) {
378
+ const daoAddress = (await this.contracts.dao.getAddress());
379
+ this.log.info('treasuryDeposit(amount=%d, to=%s)', amount, daoAddress);
380
+ const tx = await this.contracts.token.transfer(daoAddress, amount);
381
+ const receipt = await tx.wait();
382
+ return {
383
+ txHash: receipt.hash,
384
+ amount,
385
+ timestamp: Date.now(),
386
+ };
387
+ }
388
+ }
389
+ //# sourceMappingURL=dao-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dao-service.js","sourceRoot":"","sources":["../../src/services/dao-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * IdentityService — on-chain identity operations for ClawIdentity.
3
+ *
4
+ * This service is the single point of truth for all DID write/read
5
+ * operations that hit the chain. API route handlers delegate to it;
6
+ * it calls the ClawIdentity smart contract via ContractProvider and
7
+ * reads cached DID data from IndexerQuery when available.
8
+ *
9
+ * Design decisions:
10
+ * - DID string → bytes32 hash via `keccak256(toUtf8Bytes(did))`.
11
+ * - Ed25519 public keys are 32-byte `Uint8Array`/hex strings.
12
+ * - `rotationProof` is accepted but NOT verified on-chain in the
13
+ * current contract version (deferred to Phase 2 T-0.14).
14
+ * - Capability CRUD stays off-chain (P2P / event store); this
15
+ * service covers only registerDID / rotateKey / revokeDID /
16
+ * addPlatformLink and their view counterparts.
17
+ */
18
+ import { createLogger } from '../logger.js';
19
+ import type { ContractProvider } from './contract-provider.js';
20
+ import type { IndexerQuery } from '../indexer/query.js';
21
+ /**
22
+ * Derive a unique, deterministic EVM address for a DID.
23
+ *
24
+ * The address is a pseudo-address (no one holds its private key) used
25
+ * solely as a balance-holding account on the ERC-20 token contract.
26
+ * Token operations (mint / burn) are executed by the node signer which
27
+ * holds MINTER_ROLE and BURNER_ROLE.
28
+ *
29
+ * Formula: `'0x' + keccak256("clawnet:did-address:" + did)[last 20 bytes]`
30
+ */
31
+ export declare function deriveAddressForDid(did: string): string;
32
+ type Logger = ReturnType<typeof createLogger>;
33
+ /** Mirrors Solidity enum KeyPurpose. */
34
+ export type KeyPurpose = 'authentication' | 'assertion' | 'keyAgreement' | 'recovery';
35
+ export interface DIDRegistrationResult {
36
+ txHash: string;
37
+ did: string;
38
+ controller: string;
39
+ timestamp: number;
40
+ }
41
+ export interface KeyRotationResult {
42
+ txHash: string;
43
+ did: string;
44
+ oldKeyHash: string;
45
+ newKeyHash: string;
46
+ timestamp: number;
47
+ }
48
+ export interface DIDRevocationResult {
49
+ txHash: string;
50
+ did: string;
51
+ timestamp: number;
52
+ }
53
+ export interface PlatformLinkResult {
54
+ txHash: string;
55
+ did: string;
56
+ linkHash: string;
57
+ timestamp: number;
58
+ }
59
+ export interface DIDDocument {
60
+ did: string;
61
+ didHash: string;
62
+ controller: string;
63
+ publicKey: string;
64
+ keyPurpose: KeyPurpose;
65
+ isActive: boolean;
66
+ createdAt: number;
67
+ updatedAt: number;
68
+ platformLinks: string[];
69
+ }
70
+ export declare class IdentityService {
71
+ private readonly contracts;
72
+ private readonly indexer?;
73
+ private readonly log;
74
+ constructor(contracts: ContractProvider, indexer?: IndexerQuery | undefined, logger?: Logger);
75
+ /**
76
+ * Resolve a DID to its full on-chain document.
77
+ *
78
+ * Reads the DIDRecord + active KeyRecord + platform links from the
79
+ * ClawIdentity contract.
80
+ *
81
+ * @returns The DID document, or `null` if not registered.
82
+ */
83
+ resolve(did: string): Promise<DIDDocument | null>;
84
+ /**
85
+ * Get the controller EVM address for a DID.
86
+ *
87
+ * @returns The controller address, or `null` if not registered.
88
+ */
89
+ getController(did: string): Promise<string | null>;
90
+ /**
91
+ * Check if a DID is active on-chain.
92
+ */
93
+ isActive(did: string): Promise<boolean>;
94
+ /**
95
+ * Resolve a DID from the indexer cache (faster, eventually consistent).
96
+ *
97
+ * @returns Cached DID record or `null`.
98
+ */
99
+ getCachedDid(did: string): {
100
+ controller: string;
101
+ activeKey: string;
102
+ isActive: boolean;
103
+ updatedAt: number;
104
+ } | null;
105
+ /**
106
+ * Register a new DID on-chain.
107
+ *
108
+ * @param did Full DID string (`did:claw:z6Mk...`)
109
+ * @param publicKey Ed25519 public key (32 bytes, hex-encoded with `0x` prefix)
110
+ * @param purpose Key purpose (default: `authentication`)
111
+ * @param evmAddress EVM address for cross-reference (default: signer address)
112
+ */
113
+ registerDID(did: string, publicKey: string, purpose?: KeyPurpose, evmAddress?: string): Promise<DIDRegistrationResult>;
114
+ /**
115
+ * Rotate the active key for a DID.
116
+ *
117
+ * @param did Full DID string
118
+ * @param newPublicKey New Ed25519 public key (hex, 32 bytes)
119
+ * @param rotationProof Signature proof from old key (hex).
120
+ * Not verified on-chain in current contract version.
121
+ */
122
+ rotateKey(did: string, newPublicKey: string, rotationProof?: string): Promise<KeyRotationResult>;
123
+ /**
124
+ * Permanently revoke a DID. This cannot be undone.
125
+ */
126
+ revokeDID(did: string): Promise<DIDRevocationResult>;
127
+ /**
128
+ * Anchor a platform link hash to a DID on-chain.
129
+ */
130
+ addPlatformLink(did: string, linkHash: string): Promise<PlatformLinkResult>;
131
+ /**
132
+ * Ensure a DID is registered on-chain. If already registered, returns
133
+ * the existing controller. If not, auto-registers via `batchRegisterDID`
134
+ * (REGISTRAR_ROLE — no ECDSA signature needed) with a **unique derived
135
+ * address** as controller so each DID has its own balance slot.
136
+ *
137
+ * @param did Full DID string (`did:claw:z...`)
138
+ * @param publicKey Ed25519 public key (32 bytes, hex 0x-prefixed)
139
+ * @returns The controller (EVM) address (unique per DID).
140
+ */
141
+ ensureRegistered(did: string, publicKey: string): Promise<string>;
142
+ /**
143
+ * Hash a DID string to bytes32 for on-chain use.
144
+ *
145
+ * Uses keccak256(toUtf8Bytes(did)) — consistent with WalletService.
146
+ */
147
+ private hashDid;
148
+ }
149
+ export {};
150
+ //# sourceMappingURL=identity-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-service.d.ts","sourceRoot":"","sources":["../../src/services/identity-service.ts"],"names":[],"mappings":"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"}