@hashgraphonline/standards-sdk 0.0.157-canary.2 → 0.0.157-canary.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/hcs-10/base-client.d.ts +1 -1
- package/dist/cjs/hcs-10/base-client.d.ts.map +1 -1
- package/dist/cjs/hcs-10/sdk.d.ts +1 -1
- package/dist/cjs/hcs-10/sdk.d.ts.map +1 -1
- package/dist/cjs/hcs-11/agent-builder.d.ts +2 -0
- package/dist/cjs/hcs-11/agent-builder.d.ts.map +1 -1
- package/dist/cjs/hcs-11/client.d.ts +2 -0
- package/dist/cjs/hcs-11/client.d.ts.map +1 -1
- package/dist/cjs/hcs-11/types.d.ts +4 -2
- package/dist/cjs/hcs-11/types.d.ts.map +1 -1
- package/dist/cjs/hcs-15/index.d.ts +3 -0
- package/dist/cjs/hcs-15/index.d.ts.map +1 -0
- package/dist/cjs/hcs-15/petal-manager.d.ts +27 -0
- package/dist/cjs/hcs-15/petal-manager.d.ts.map +1 -0
- package/dist/cjs/hcs-15/types.d.ts +41 -0
- package/dist/cjs/hcs-15/types.d.ts.map +1 -0
- package/dist/cjs/hcs-16/flora-account-manager.d.ts.map +1 -1
- package/dist/cjs/hcs-16/types.d.ts +3 -5
- package/dist/cjs/hcs-16/types.d.ts.map +1 -1
- package/dist/cjs/hcs-18/discovery.d.ts +1 -0
- package/dist/cjs/hcs-18/discovery.d.ts.map +1 -1
- package/dist/cjs/hcs-18/types.d.ts +1 -0
- package/dist/cjs/hcs-18/types.d.ts.map +1 -1
- package/dist/cjs/hcs-20/sdk.d.ts.map +1 -1
- package/dist/cjs/hcs-7/evm-bridge.d.ts.map +1 -1
- package/dist/cjs/hcs-7/redis-cache.d.ts.map +1 -1
- package/dist/cjs/hcs-7/wasm-bridge.d.ts.map +1 -1
- package/dist/cjs/{index-xZmk-HBD.cjs → index-CJsmyij2.cjs} +12 -12
- package/dist/cjs/index-CJsmyij2.cjs.map +1 -0
- package/dist/cjs/{index-CyAbgH2f-Cv8mxAhS.cjs → index-CyAbgH2f-Dn5WQtPx.cjs} +2 -2
- package/dist/cjs/{index-CyAbgH2f-Cv8mxAhS.cjs.map → index-CyAbgH2f-Dn5WQtPx.cjs.map} +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/services/types.d.ts +1 -1
- package/dist/cjs/services/types.d.ts.map +1 -1
- package/dist/cjs/standards-sdk.cjs +1 -1
- package/dist/cjs/{standards-sdk.es45-BxAtDqsy-ELd4REyl.cjs → standards-sdk.es45-BxAtDqsy-CiMtsDbD.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es45-BxAtDqsy-ELd4REyl.cjs.map → standards-sdk.es45-BxAtDqsy-CiMtsDbD.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es46-BI8ACeLM-DRmcgoN0.cjs → standards-sdk.es46-BI8ACeLM-DFYgO-fP.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es46-BI8ACeLM-DRmcgoN0.cjs.map → standards-sdk.es46-BI8ACeLM-DFYgO-fP.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es47-DbkY3FlD-DfMpZygD.cjs → standards-sdk.es47-DbkY3FlD-2qTWs2BD.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es47-DbkY3FlD-DfMpZygD.cjs.map → standards-sdk.es47-DbkY3FlD-2qTWs2BD.cjs.map} +1 -1
- package/dist/cjs/{standards-sdk.es48-DzT9Qc3F-CmCkJl3x.cjs → standards-sdk.es48-DzT9Qc3F-Byz0fQnW.cjs} +2 -2
- package/dist/cjs/{standards-sdk.es48-DzT9Qc3F-CmCkJl3x.cjs.map → standards-sdk.es48-DzT9Qc3F-Byz0fQnW.cjs.map} +1 -1
- package/dist/cjs/utils/logger.d.ts.map +1 -1
- package/dist/es/hcs-10/base-client.d.ts +1 -1
- package/dist/es/hcs-10/base-client.d.ts.map +1 -1
- package/dist/es/hcs-10/sdk.d.ts +1 -1
- package/dist/es/hcs-10/sdk.d.ts.map +1 -1
- package/dist/es/hcs-11/agent-builder.d.ts +2 -0
- package/dist/es/hcs-11/agent-builder.d.ts.map +1 -1
- package/dist/es/hcs-11/client.d.ts +2 -0
- package/dist/es/hcs-11/client.d.ts.map +1 -1
- package/dist/es/hcs-11/types.d.ts +4 -2
- package/dist/es/hcs-11/types.d.ts.map +1 -1
- package/dist/es/hcs-15/index.d.ts +3 -0
- package/dist/es/hcs-15/index.d.ts.map +1 -0
- package/dist/es/hcs-15/petal-manager.d.ts +27 -0
- package/dist/es/hcs-15/petal-manager.d.ts.map +1 -0
- package/dist/es/hcs-15/types.d.ts +41 -0
- package/dist/es/hcs-15/types.d.ts.map +1 -0
- package/dist/es/hcs-16/flora-account-manager.d.ts.map +1 -1
- package/dist/es/hcs-16/types.d.ts +3 -5
- package/dist/es/hcs-16/types.d.ts.map +1 -1
- package/dist/es/hcs-18/discovery.d.ts +1 -0
- package/dist/es/hcs-18/discovery.d.ts.map +1 -1
- package/dist/es/hcs-18/types.d.ts +1 -0
- package/dist/es/hcs-18/types.d.ts.map +1 -1
- package/dist/es/hcs-20/sdk.d.ts.map +1 -1
- package/dist/es/hcs-7/evm-bridge.d.ts.map +1 -1
- package/dist/es/hcs-7/redis-cache.d.ts.map +1 -1
- package/dist/es/hcs-7/wasm-bridge.d.ts.map +1 -1
- package/dist/es/index.d.ts +1 -1
- package/dist/es/services/types.d.ts +1 -1
- package/dist/es/services/types.d.ts.map +1 -1
- package/dist/es/standards-sdk.es.js +19 -22
- package/dist/es/standards-sdk.es.js.map +1 -1
- package/dist/es/standards-sdk.es10.js +1 -1
- package/dist/es/standards-sdk.es11.js +10 -2
- package/dist/es/standards-sdk.es11.js.map +1 -1
- package/dist/es/standards-sdk.es12.js +1 -1
- package/dist/es/standards-sdk.es13.js +1 -1
- package/dist/es/standards-sdk.es13.js.map +1 -1
- package/dist/es/standards-sdk.es14.js +1 -1
- package/dist/es/standards-sdk.es15.js +39 -9
- package/dist/es/standards-sdk.es15.js.map +1 -1
- package/dist/es/standards-sdk.es16.js +1 -0
- package/dist/es/standards-sdk.es16.js.map +1 -1
- package/dist/es/standards-sdk.es18.js +1 -1
- package/dist/es/standards-sdk.es19.js +1 -1
- package/dist/es/standards-sdk.es2.js +1 -1
- package/dist/es/standards-sdk.es20.js +2 -2
- package/dist/es/standards-sdk.es23.js +2 -2
- package/dist/es/standards-sdk.es25.js +4 -2
- package/dist/es/standards-sdk.es25.js.map +1 -1
- package/dist/es/standards-sdk.es26.js +2 -2
- package/dist/es/standards-sdk.es27.js +152 -6
- package/dist/es/standards-sdk.es27.js.map +1 -1
- package/dist/es/standards-sdk.es28.js +26 -189
- package/dist/es/standards-sdk.es28.js.map +1 -1
- package/dist/es/standards-sdk.es29.js +446 -26
- package/dist/es/standards-sdk.es29.js.map +1 -1
- package/dist/es/standards-sdk.es3.js +1 -1
- package/dist/es/standards-sdk.es3.js.map +1 -1
- package/dist/es/standards-sdk.es30.js +6 -342
- package/dist/es/standards-sdk.es30.js.map +1 -1
- package/dist/es/standards-sdk.es31.js +202 -6
- package/dist/es/standards-sdk.es31.js.map +1 -1
- package/dist/es/standards-sdk.es32.js +34 -202
- package/dist/es/standards-sdk.es32.js.map +1 -1
- package/dist/es/standards-sdk.es33.js +529 -34
- package/dist/es/standards-sdk.es33.js.map +1 -1
- package/dist/es/standards-sdk.es34.js +87 -501
- package/dist/es/standards-sdk.es34.js.map +1 -1
- package/dist/es/standards-sdk.es35.js +19 -98
- package/dist/es/standards-sdk.es35.js.map +1 -1
- package/dist/es/standards-sdk.es36.js +156 -18
- package/dist/es/standards-sdk.es36.js.map +1 -1
- package/dist/es/standards-sdk.es37.js +146 -150
- package/dist/es/standards-sdk.es37.js.map +1 -1
- package/dist/es/standards-sdk.es38.js +561 -134
- package/dist/es/standards-sdk.es38.js.map +1 -1
- package/dist/es/standards-sdk.es39.js +562 -543
- package/dist/es/standards-sdk.es39.js.map +1 -1
- package/dist/es/standards-sdk.es4.js +6 -4
- package/dist/es/standards-sdk.es4.js.map +1 -1
- package/dist/es/standards-sdk.es40.js +4 -601
- package/dist/es/standards-sdk.es40.js.map +1 -1
- package/dist/es/standards-sdk.es41.js +415 -4
- package/dist/es/standards-sdk.es41.js.map +1 -1
- package/dist/es/standards-sdk.es42.js +1536 -389
- package/dist/es/standards-sdk.es42.js.map +1 -1
- package/dist/es/standards-sdk.es43.js +133 -1541
- package/dist/es/standards-sdk.es43.js.map +1 -1
- package/dist/es/standards-sdk.es44.js +7 -155
- package/dist/es/standards-sdk.es44.js.map +1 -1
- package/dist/es/standards-sdk.es45.js +2 -7
- package/dist/es/standards-sdk.es45.js.map +1 -1
- package/dist/es/standards-sdk.es46.js +5 -5
- package/dist/es/standards-sdk.es48.js +1 -1
- package/dist/es/standards-sdk.es49.js +1 -1
- package/dist/es/standards-sdk.es5.js +4 -6
- package/dist/es/standards-sdk.es5.js.map +1 -1
- package/dist/es/standards-sdk.es50.js +1 -1
- package/dist/es/standards-sdk.es51.js +1 -1
- package/dist/es/standards-sdk.es52.js +1 -1
- package/dist/es/standards-sdk.es54.js +7135 -2
- package/dist/es/standards-sdk.es54.js.map +1 -1
- package/dist/es/standards-sdk.es55.js +7134 -41
- package/dist/es/standards-sdk.es55.js.map +1 -1
- package/dist/es/standards-sdk.es56.js +37 -37
- package/dist/es/standards-sdk.es56.js.map +1 -1
- package/dist/es/standards-sdk.es57.js +37 -37
- package/dist/es/standards-sdk.es57.js.map +1 -1
- package/dist/es/standards-sdk.es58.js +78 -72
- package/dist/es/standards-sdk.es58.js.map +1 -1
- package/dist/es/standards-sdk.es59.js +41 -7134
- package/dist/es/standards-sdk.es59.js.map +1 -1
- package/dist/es/standards-sdk.es6.js.map +1 -1
- package/dist/es/standards-sdk.es7.js +28 -22
- package/dist/es/standards-sdk.es7.js.map +1 -1
- package/dist/es/standards-sdk.es8.js +5 -5
- package/dist/es/utils/logger.d.ts.map +1 -1
- package/package.json +37 -35
- package/dist/cjs/hcs-21/index.d.ts +0 -4
- package/dist/cjs/hcs-21/index.d.ts.map +0 -1
- package/dist/cjs/hcs-21/petal-account-manager.d.ts +0 -52
- package/dist/cjs/hcs-21/petal-account-manager.d.ts.map +0 -1
- package/dist/cjs/hcs-21/types.d.ts +0 -44
- package/dist/cjs/hcs-21/types.d.ts.map +0 -1
- package/dist/cjs/index-xZmk-HBD.cjs.map +0 -1
- package/dist/es/hcs-21/index.d.ts +0 -4
- package/dist/es/hcs-21/index.d.ts.map +0 -1
- package/dist/es/hcs-21/petal-account-manager.d.ts +0 -52
- package/dist/es/hcs-21/petal-account-manager.d.ts.map +0 -1
- package/dist/es/hcs-21/types.d.ts +0 -44
- package/dist/es/hcs-21/types.d.ts.map +0 -1
- package/dist/es/standards-sdk.es60.js +0 -7144
- package/dist/es/standards-sdk.es60.js.map +0 -1
|
@@ -1,207 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
concatenated += topic.topicId + topic.latestRunningHash;
|
|
24
|
-
}
|
|
25
|
-
const publicKeyString = typeof input.publicKey === "string" ? input.publicKey : input.publicKey.toString();
|
|
26
|
-
concatenated += publicKeyString;
|
|
27
|
-
const hash = createHash("sha384");
|
|
28
|
-
hash.update(concatenated);
|
|
29
|
-
const stateHash = hash.digest("hex");
|
|
30
|
-
this.logger.debug("Account state hash calculated", {
|
|
31
|
-
accountId: input.accountId,
|
|
32
|
-
stateHash
|
|
33
|
-
});
|
|
34
|
-
return {
|
|
35
|
-
stateHash,
|
|
36
|
-
accountId: input.accountId,
|
|
37
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
38
|
-
topicCount: input.topics.length
|
|
39
|
-
};
|
|
40
|
-
} catch (error) {
|
|
41
|
-
this.logger.error("Failed to calculate account state hash", error);
|
|
42
|
-
throw new StateHashError(
|
|
43
|
-
"Failed to calculate account state hash",
|
|
44
|
-
"CALCULATION_FAILED"
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Calculate composite state hash for Flora/Bloom
|
|
50
|
-
* CompositeStateHash = SHA384(
|
|
51
|
-
* Σ_sorted(accountId_i || StateHash_i) ||
|
|
52
|
-
* Σ_sorted(topicId_j || runningHash_j) ||
|
|
53
|
-
* composite_publicKeyFingerprint
|
|
54
|
-
* )
|
|
55
|
-
*/
|
|
56
|
-
calculateCompositeStateHash(input) {
|
|
57
|
-
try {
|
|
58
|
-
this.logger.debug("Calculating composite state hash", {
|
|
59
|
-
compositeAccountId: input.compositeAccountId,
|
|
60
|
-
memberCount: input.memberStates.length,
|
|
61
|
-
topicCount: input.compositeTopics.length
|
|
62
|
-
});
|
|
63
|
-
const sortedMembers = [...input.memberStates].sort(
|
|
64
|
-
(a, b) => a.accountId.localeCompare(b.accountId)
|
|
65
|
-
);
|
|
66
|
-
const sortedTopics = [...input.compositeTopics].sort(
|
|
67
|
-
(a, b) => a.topicId.localeCompare(b.topicId)
|
|
68
|
-
);
|
|
69
|
-
let concatenated = "";
|
|
70
|
-
for (const member of sortedMembers) {
|
|
71
|
-
concatenated += member.accountId + member.stateHash;
|
|
72
|
-
}
|
|
73
|
-
for (const topic of sortedTopics) {
|
|
74
|
-
concatenated += topic.topicId + topic.latestRunningHash;
|
|
75
|
-
}
|
|
76
|
-
concatenated += input.compositePublicKeyFingerprint;
|
|
77
|
-
const hash = createHash("sha384");
|
|
78
|
-
hash.update(concatenated);
|
|
79
|
-
const stateHash = hash.digest("hex");
|
|
80
|
-
this.logger.debug("Composite state hash calculated", {
|
|
81
|
-
compositeAccountId: input.compositeAccountId,
|
|
82
|
-
stateHash
|
|
83
|
-
});
|
|
84
|
-
return {
|
|
85
|
-
stateHash,
|
|
86
|
-
accountId: input.compositeAccountId,
|
|
87
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
88
|
-
topicCount: input.compositeTopics.length,
|
|
89
|
-
memberCount: input.memberStates.length,
|
|
90
|
-
compositeTopicCount: input.compositeTopics.length
|
|
91
|
-
};
|
|
92
|
-
} catch (error) {
|
|
93
|
-
this.logger.error("Failed to calculate composite state hash", error);
|
|
94
|
-
throw new StateHashError(
|
|
95
|
-
"Failed to calculate composite state hash",
|
|
96
|
-
"CALCULATION_FAILED"
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Calculate deterministic public key fingerprint for KeyList/Threshold keys
|
|
102
|
-
* Used for Flora/Bloom accounts
|
|
103
|
-
*/
|
|
104
|
-
calculateKeyFingerprint(keys, threshold) {
|
|
105
|
-
try {
|
|
106
|
-
const sortedKeys = [...keys].sort(
|
|
107
|
-
(a, b) => a.toString().localeCompare(b.toString())
|
|
108
|
-
);
|
|
109
|
-
const keyData = {
|
|
110
|
-
threshold,
|
|
111
|
-
keys: sortedKeys.map((k) => k.toString())
|
|
112
|
-
};
|
|
113
|
-
const hash = createHash("sha384");
|
|
114
|
-
hash.update(JSON.stringify(keyData));
|
|
115
|
-
return hash.digest("hex");
|
|
116
|
-
} catch (error) {
|
|
117
|
-
this.logger.error("Failed to calculate key fingerprint", error);
|
|
118
|
-
throw new StateHashError(
|
|
119
|
-
"Failed to calculate key fingerprint",
|
|
120
|
-
"FINGERPRINT_FAILED"
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Create HCS-17 state hash message
|
|
126
|
-
*/
|
|
127
|
-
createStateHashMessage(stateHash, accountId, topicIds, memo) {
|
|
128
|
-
return {
|
|
129
|
-
p: "hcs-17",
|
|
130
|
-
op: "state_hash",
|
|
131
|
-
state_hash: stateHash,
|
|
132
|
-
topics: topicIds,
|
|
133
|
-
account_id: accountId,
|
|
134
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
135
|
-
m: memo
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Verify state hash by recalculating
|
|
140
|
-
*/
|
|
141
|
-
async verifyStateHash(input, expectedHash) {
|
|
142
|
-
try {
|
|
143
|
-
let calculatedHash;
|
|
144
|
-
if ("publicKey" in input) {
|
|
145
|
-
const result = this.calculateAccountStateHash(input);
|
|
146
|
-
calculatedHash = result.stateHash;
|
|
147
|
-
} else {
|
|
148
|
-
const result = this.calculateCompositeStateHash(input);
|
|
149
|
-
calculatedHash = result.stateHash;
|
|
150
|
-
}
|
|
151
|
-
const isValid = calculatedHash === expectedHash;
|
|
152
|
-
const accountId = "accountId" in input ? input.accountId : input.compositeAccountId;
|
|
153
|
-
this.logger.debug("State hash verification", {
|
|
154
|
-
accountId,
|
|
155
|
-
isValid,
|
|
156
|
-
expected: expectedHash,
|
|
157
|
-
calculated: calculatedHash
|
|
158
|
-
});
|
|
159
|
-
return isValid;
|
|
160
|
-
} catch (error) {
|
|
161
|
-
this.logger.error("Failed to verify state hash", error);
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Get latest running hashes for topics (mock implementation)
|
|
167
|
-
* In production, this would query the actual Hedera network
|
|
168
|
-
*/
|
|
169
|
-
async getTopicRunningHashes(topicIds) {
|
|
170
|
-
return topicIds.map((topicId) => ({
|
|
171
|
-
topicId,
|
|
172
|
-
latestRunningHash: createHash("sha256").update(`mock-hash-${topicId}-${Date.now()}`).digest("hex").substring(0, 48)
|
|
173
|
-
}));
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Calculate and publish state hash to a topic
|
|
177
|
-
*/
|
|
178
|
-
async publishStateHash(stateHash, accountId, topicIds, publishTopicId, client) {
|
|
179
|
-
try {
|
|
180
|
-
const message = this.createStateHashMessage(
|
|
181
|
-
stateHash,
|
|
182
|
-
accountId,
|
|
183
|
-
topicIds,
|
|
184
|
-
"State synchronization"
|
|
185
|
-
);
|
|
186
|
-
const { TopicMessageSubmitTransaction } = await import("@hashgraph/sdk");
|
|
187
|
-
const transaction = new TopicMessageSubmitTransaction().setTopicId(publishTopicId).setMessage(JSON.stringify(message));
|
|
188
|
-
const response = await transaction.execute(client);
|
|
189
|
-
await response.getReceipt(client);
|
|
190
|
-
this.logger.info("State hash published", {
|
|
191
|
-
accountId,
|
|
192
|
-
topicId: publishTopicId,
|
|
193
|
-
stateHash
|
|
194
|
-
});
|
|
195
|
-
} catch (error) {
|
|
196
|
-
this.logger.error("Failed to publish state hash", error);
|
|
197
|
-
throw new StateHashError(
|
|
198
|
-
"Failed to publish state hash",
|
|
199
|
-
"PUBLISH_FAILED"
|
|
200
|
-
);
|
|
201
|
-
}
|
|
1
|
+
var DiscoveryOperation = /* @__PURE__ */ ((DiscoveryOperation2) => {
|
|
2
|
+
DiscoveryOperation2["ANNOUNCE"] = "announce";
|
|
3
|
+
DiscoveryOperation2["PROPOSE"] = "propose";
|
|
4
|
+
DiscoveryOperation2["RESPOND"] = "respond";
|
|
5
|
+
DiscoveryOperation2["COMPLETE"] = "complete";
|
|
6
|
+
DiscoveryOperation2["WITHDRAW"] = "withdraw";
|
|
7
|
+
return DiscoveryOperation2;
|
|
8
|
+
})(DiscoveryOperation || {});
|
|
9
|
+
var DiscoveryState = /* @__PURE__ */ ((DiscoveryState2) => {
|
|
10
|
+
DiscoveryState2["IDLE"] = "idle";
|
|
11
|
+
DiscoveryState2["ANNOUNCED"] = "announced";
|
|
12
|
+
DiscoveryState2["PROPOSING"] = "proposing";
|
|
13
|
+
DiscoveryState2["FORMING"] = "forming";
|
|
14
|
+
DiscoveryState2["ACTIVE"] = "active";
|
|
15
|
+
DiscoveryState2["WITHDRAWN"] = "withdrawn";
|
|
16
|
+
return DiscoveryState2;
|
|
17
|
+
})(DiscoveryState || {});
|
|
18
|
+
class DiscoveryError extends Error {
|
|
19
|
+
constructor(message, code) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.code = code;
|
|
22
|
+
this.name = "DiscoveryError";
|
|
202
23
|
}
|
|
203
24
|
}
|
|
25
|
+
const DiscoveryErrorCodes = {
|
|
26
|
+
INVALID_MESSAGE: "INVALID_MESSAGE",
|
|
27
|
+
TIMEOUT: "TIMEOUT",
|
|
28
|
+
INSUFFICIENT_PETALS: "INSUFFICIENT_PETALS",
|
|
29
|
+
FLORA_CREATION_FAILED: "FLORA_CREATION_FAILED",
|
|
30
|
+
ALREADY_IN_DISCOVERY: "ALREADY_IN_DISCOVERY",
|
|
31
|
+
INVALID_STATE: "INVALID_STATE"
|
|
32
|
+
};
|
|
204
33
|
export {
|
|
205
|
-
|
|
34
|
+
DiscoveryError,
|
|
35
|
+
DiscoveryErrorCodes,
|
|
36
|
+
DiscoveryOperation,
|
|
37
|
+
DiscoveryState
|
|
206
38
|
};
|
|
207
39
|
//# sourceMappingURL=standards-sdk.es32.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es32.js","sources":["../../src/hcs-17/state-hash-calculator.ts"],"sourcesContent":["import { createHash } from 'crypto';\nimport { PublicKey, KeyList, Key } from '@hashgraph/sdk';\nimport { Logger } from '../utils/logger';\nimport {\n AccountStateInput,\n CompositeStateInput,\n StateHashResult,\n CompositeStateHashResult,\n StateHashMessage,\n TopicState,\n StateHashError,\n} from './types';\n\n/**\n * HCS-17 State Hash Calculator\n * Calculates state hashes for accounts and composite accounts (Flora/Bloom)\n */\nexport class StateHashCalculator {\n private readonly logger: Logger;\n\n constructor(logger?: Logger) {\n this.logger = logger || new Logger({ module: 'StateHashCalculator' });\n }\n\n /**\n * Calculate state hash for a single account\n * StateHash = SHA384(topicId_1 || latestRunningHash_1 || ... || topicId_n || latestRunningHash_n || account_publicKey)\n */\n calculateAccountStateHash(input: AccountStateInput): StateHashResult {\n try {\n this.logger.debug('Calculating account state hash', {\n accountId: input.accountId,\n topicCount: input.topics.length,\n });\n\n const sortedTopics = [...input.topics].sort((a, b) =>\n a.topicId.localeCompare(b.topicId),\n );\n\n let concatenated = '';\n for (const topic of sortedTopics) {\n concatenated += topic.topicId + topic.latestRunningHash;\n }\n\n const publicKeyString =\n typeof input.publicKey === 'string'\n ? input.publicKey\n : input.publicKey.toString();\n concatenated += publicKeyString;\n const hash = createHash('sha384');\n hash.update(concatenated);\n const stateHash = hash.digest('hex');\n\n this.logger.debug('Account state hash calculated', {\n accountId: input.accountId,\n stateHash,\n });\n\n return {\n stateHash,\n accountId: input.accountId,\n timestamp: new Date(),\n topicCount: input.topics.length,\n };\n } catch (error) {\n this.logger.error('Failed to calculate account state hash', error);\n throw new StateHashError(\n 'Failed to calculate account state hash',\n 'CALCULATION_FAILED',\n );\n }\n }\n\n /**\n * Calculate composite state hash for Flora/Bloom\n * CompositeStateHash = SHA384(\n * Σ_sorted(accountId_i || StateHash_i) ||\n * Σ_sorted(topicId_j || runningHash_j) ||\n * composite_publicKeyFingerprint\n * )\n */\n calculateCompositeStateHash(\n input: CompositeStateInput,\n ): CompositeStateHashResult {\n try {\n this.logger.debug('Calculating composite state hash', {\n compositeAccountId: input.compositeAccountId,\n memberCount: input.memberStates.length,\n topicCount: input.compositeTopics.length,\n });\n\n const sortedMembers = [...input.memberStates].sort((a, b) =>\n a.accountId.localeCompare(b.accountId),\n );\n\n const sortedTopics = [...input.compositeTopics].sort((a, b) =>\n a.topicId.localeCompare(b.topicId),\n );\n\n let concatenated = '';\n for (const member of sortedMembers) {\n concatenated += member.accountId + member.stateHash;\n }\n\n for (const topic of sortedTopics) {\n concatenated += topic.topicId + topic.latestRunningHash;\n }\n\n concatenated += input.compositePublicKeyFingerprint;\n const hash = createHash('sha384');\n hash.update(concatenated);\n const stateHash = hash.digest('hex');\n\n this.logger.debug('Composite state hash calculated', {\n compositeAccountId: input.compositeAccountId,\n stateHash,\n });\n\n return {\n stateHash,\n accountId: input.compositeAccountId,\n timestamp: new Date(),\n topicCount: input.compositeTopics.length,\n memberCount: input.memberStates.length,\n compositeTopicCount: input.compositeTopics.length,\n };\n } catch (error) {\n this.logger.error('Failed to calculate composite state hash', error);\n throw new StateHashError(\n 'Failed to calculate composite state hash',\n 'CALCULATION_FAILED',\n );\n }\n }\n\n /**\n * Calculate deterministic public key fingerprint for KeyList/Threshold keys\n * Used for Flora/Bloom accounts\n */\n calculateKeyFingerprint(keys: PublicKey[], threshold: number): string {\n try {\n const sortedKeys = [...keys].sort((a, b) =>\n a.toString().localeCompare(b.toString()),\n );\n\n const keyData = {\n threshold,\n keys: sortedKeys.map(k => k.toString()),\n };\n const hash = createHash('sha384');\n hash.update(JSON.stringify(keyData));\n return hash.digest('hex');\n } catch (error) {\n this.logger.error('Failed to calculate key fingerprint', error);\n throw new StateHashError(\n 'Failed to calculate key fingerprint',\n 'FINGERPRINT_FAILED',\n );\n }\n }\n\n /**\n * Create HCS-17 state hash message\n */\n createStateHashMessage(\n stateHash: string,\n accountId: string,\n topicIds: string[],\n memo?: string,\n ): StateHashMessage {\n return {\n p: 'hcs-17',\n op: 'state_hash',\n state_hash: stateHash,\n topics: topicIds,\n account_id: accountId,\n timestamp: new Date().toISOString(),\n m: memo,\n };\n }\n\n /**\n * Verify state hash by recalculating\n */\n async verifyStateHash(\n input: AccountStateInput | CompositeStateInput,\n expectedHash: string,\n ): Promise<boolean> {\n try {\n let calculatedHash: string;\n\n if ('publicKey' in input) {\n const result = this.calculateAccountStateHash(input);\n calculatedHash = result.stateHash;\n } else {\n const result = this.calculateCompositeStateHash(input);\n calculatedHash = result.stateHash;\n }\n\n const isValid = calculatedHash === expectedHash;\n\n const accountId =\n 'accountId' in input ? input.accountId : input.compositeAccountId;\n this.logger.debug('State hash verification', {\n accountId,\n isValid,\n expected: expectedHash,\n calculated: calculatedHash,\n });\n\n return isValid;\n } catch (error) {\n this.logger.error('Failed to verify state hash', error);\n return false;\n }\n }\n\n /**\n * Get latest running hashes for topics (mock implementation)\n * In production, this would query the actual Hedera network\n */\n async getTopicRunningHashes(topicIds: string[]): Promise<TopicState[]> {\n return topicIds.map(topicId => ({\n topicId,\n latestRunningHash: createHash('sha256')\n .update(`mock-hash-${topicId}-${Date.now()}`)\n .digest('hex')\n .substring(0, 48),\n }));\n }\n\n /**\n * Calculate and publish state hash to a topic\n */\n async publishStateHash(\n stateHash: string,\n accountId: string,\n topicIds: string[],\n publishTopicId: string,\n client: any,\n ): Promise<void> {\n try {\n const message = this.createStateHashMessage(\n stateHash,\n accountId,\n topicIds,\n 'State synchronization',\n );\n\n const { TopicMessageSubmitTransaction } = await import('@hashgraph/sdk');\n\n const transaction = new TopicMessageSubmitTransaction()\n .setTopicId(publishTopicId)\n .setMessage(JSON.stringify(message));\n\n const response = await transaction.execute(client);\n await response.getReceipt(client);\n\n this.logger.info('State hash published', {\n accountId,\n topicId: publishTopicId,\n stateHash,\n });\n } catch (error) {\n this.logger.error('Failed to publish state hash', error);\n throw new StateHashError(\n 'Failed to publish state hash',\n 'PUBLISH_FAILED',\n );\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es32.js","sources":["../../src/hcs-18/types.ts"],"sourcesContent":["/**\n * HCS-18 Flora Discovery Protocol Types\n * Standard for Flora discovery and formation\n */\n\nimport { AccountId, TopicId, PublicKey } from '@hashgraph/sdk';\n\n/**\n * HCS-18 Operation types\n */\nexport enum DiscoveryOperation {\n ANNOUNCE = 'announce',\n PROPOSE = 'propose',\n RESPOND = 'respond',\n COMPLETE = 'complete',\n WITHDRAW = 'withdraw',\n}\n\n/**\n * Base HCS-18 message structure\n */\nexport interface DiscoveryMessage {\n p: 'hcs-18';\n op: DiscoveryOperation;\n data: any; // Operation-specific data\n}\n\n/**\n * Announce operation data\n */\nexport interface AnnounceData {\n account: string; // Account ID of the announcing Petal\n petal: {\n name: string;\n priority: number; // 0-1000, higher = preferred for Flora coordination\n };\n capabilities: {\n protocols: string[];\n resources?: {\n compute?: 'high' | 'medium' | 'low';\n storage?: 'high' | 'medium' | 'low';\n bandwidth?: 'high' | 'medium' | 'low';\n };\n group_preferences?: {\n sizes?: number[];\n threshold_ratios?: number[];\n };\n };\n valid_for?: number; // Number of HCS messages this announcement remains valid\n}\n\n/**\n * Propose operation data\n */\nexport interface ProposeData {\n proposer: string; // Account ID of the proposing Petal\n members: Array<{\n account: string;\n announce_seq?: number; // Required for new members\n priority: number;\n status?: 'existing' | 'proposed';\n }>;\n config: {\n name: string;\n threshold: number;\n purpose?: string;\n reason?: string; // For replacements\n };\n existing_flora?: string; // For member replacement\n}\n\n/**\n * Respond operation data\n */\nexport interface RespondData {\n responder: string; // Account ID of the responding Petal\n proposal_seq: number;\n decision: 'accept' | 'reject';\n reason?: string;\n accepted_seq?: number; // When rejecting due to conflict\n}\n\n/**\n * Complete operation data\n */\nexport interface CompleteData {\n proposer: string; // Account ID of the original proposer\n proposal_seq: number;\n flora_account: string;\n topics: {\n communication: string;\n transaction: string;\n state: string;\n };\n}\n\n/**\n * Withdraw operation data\n */\nexport interface WithdrawData {\n account: string; // Account ID of the withdrawing Petal\n announce_seq: number;\n reason?: string;\n}\n\n/**\n * Typed message operations\n */\nexport interface AnnounceMessage extends DiscoveryMessage {\n op: DiscoveryOperation.ANNOUNCE;\n data: AnnounceData;\n}\n\nexport interface ProposeMessage extends DiscoveryMessage {\n op: DiscoveryOperation.PROPOSE;\n data: ProposeData;\n}\n\nexport interface RespondMessage extends DiscoveryMessage {\n op: DiscoveryOperation.RESPOND;\n data: RespondData;\n}\n\nexport interface CompleteMessage extends DiscoveryMessage {\n op: DiscoveryOperation.COMPLETE;\n data: CompleteData;\n}\n\nexport interface WithdrawMessage extends DiscoveryMessage {\n op: DiscoveryOperation.WITHDRAW;\n data: WithdrawData;\n}\n\n/**\n * Discovery phase states\n */\nexport enum DiscoveryState {\n IDLE = 'idle',\n ANNOUNCED = 'announced',\n PROPOSING = 'proposing',\n FORMING = 'forming',\n ACTIVE = 'active',\n WITHDRAWN = 'withdrawn',\n}\n\n/**\n * Tracked announcement with HCS metadata\n */\nexport interface TrackedAnnouncement {\n account: string;\n sequenceNumber: number;\n consensusTimestamp: string;\n data: AnnounceData;\n}\n\n/**\n * Tracked proposal with HCS metadata\n */\nexport interface TrackedProposal {\n sequenceNumber: number;\n consensusTimestamp: string;\n proposer: string;\n data: ProposeData;\n responses: Map<string, RespondData>;\n}\n\n/**\n * Flora formation result\n */\nexport interface FloraFormation {\n proposalSeq: number;\n floraAccountId: string;\n topics: {\n communication: string;\n transaction: string;\n state: string;\n };\n members: Array<{\n account: string;\n priority: number;\n }>;\n threshold: number;\n createdAt: Date;\n}\n\n/**\n * Discovery event types for monitoring\n */\nexport interface DiscoveryEvent {\n type: 'announcement_received' | 'proposal_received' | 'response_received' | \n 'formation_complete' | 'withdrawal_received' | 'discovery_timeout';\n sequenceNumber?: number;\n timestamp: Date;\n data: any;\n}\n\n/**\n * Discovery configuration\n */\nexport interface DiscoveryConfig {\n discoveryTopicId: string | TopicId;\n accountId: string;\n petalName: string;\n priority: number;\n capabilities: {\n protocols: string[];\n resources?: AnnounceData['capabilities']['resources'];\n group_preferences?: AnnounceData['capabilities']['group_preferences'];\n };\n autoAcceptFilter?: (proposal: TrackedProposal) => boolean;\n onDiscoveryEvent?: (event: DiscoveryEvent) => void;\n memberPrivateKeys?: Map<string, string>; // Map of accountId -> privateKey for Flora creation\n}\n\n/**\n * HCS-18 Errors\n */\nexport class DiscoveryError extends Error {\n constructor(message: string, public readonly code: string) {\n super(message);\n this.name = 'DiscoveryError';\n }\n}\n\nexport const DiscoveryErrorCodes = {\n INVALID_MESSAGE: 'INVALID_MESSAGE',\n TIMEOUT: 'TIMEOUT',\n INSUFFICIENT_PETALS: 'INSUFFICIENT_PETALS',\n FLORA_CREATION_FAILED: 'FLORA_CREATION_FAILED',\n ALREADY_IN_DISCOVERY: 'ALREADY_IN_DISCOVERY',\n INVALID_STATE: 'INVALID_STATE',\n} as const;"],"names":["DiscoveryOperation","DiscoveryState"],"mappings":"AAUO,IAAK,uCAAAA,wBAAL;AACLA,sBAAA,UAAA,IAAW;AACXA,sBAAA,SAAA,IAAU;AACVA,sBAAA,SAAA,IAAU;AACVA,sBAAA,UAAA,IAAW;AACXA,sBAAA,UAAA,IAAW;AALD,SAAAA;AAAA,GAAA,sBAAA,CAAA,CAAA;AA8HL,IAAK,mCAAAC,oBAAL;AACLA,kBAAA,MAAA,IAAO;AACPA,kBAAA,WAAA,IAAY;AACZA,kBAAA,WAAA,IAAY;AACZA,kBAAA,SAAA,IAAU;AACVA,kBAAA,QAAA,IAAS;AACTA,kBAAA,WAAA,IAAY;AANF,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AAiFL,MAAM,uBAAuB,MAAM;AAAA,EACxC,YAAY,SAAiC,MAAc;AACzD,UAAM,OAAO;AAD8B,SAAA,OAAA;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAEO,MAAM,sBAAsB;AAAA,EACjC,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,eAAe;AACjB;"}
|