@hashgraphonline/standards-sdk 0.1.137 → 0.1.138-feat-hcs-21-package-std.canary.4376298.35
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-21/base-client.d.ts +33 -0
- package/dist/cjs/hcs-21/base-client.d.ts.map +1 -0
- package/dist/cjs/hcs-21/browser.d.ts +20 -0
- package/dist/cjs/hcs-21/browser.d.ts.map +1 -0
- package/dist/cjs/hcs-21/errors.d.ts +6 -0
- package/dist/cjs/hcs-21/errors.d.ts.map +1 -0
- package/dist/cjs/hcs-21/index.d.ts +7 -0
- package/dist/cjs/hcs-21/index.d.ts.map +1 -0
- package/dist/cjs/hcs-21/sdk.d.ts +48 -0
- package/dist/cjs/hcs-21/sdk.d.ts.map +1 -0
- package/dist/cjs/hcs-21/tx.d.ts +20 -0
- package/dist/cjs/hcs-21/tx.d.ts.map +1 -0
- package/dist/cjs/hcs-21/types.d.ts +89 -0
- package/dist/cjs/hcs-21/types.d.ts.map +1 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/services/registry-broker/client.d.ts.map +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 +2 -2
- package/dist/cjs/standards-sdk.cjs.map +1 -1
- package/dist/es/hcs-21/base-client.d.ts +33 -0
- package/dist/es/hcs-21/base-client.d.ts.map +1 -0
- package/dist/es/hcs-21/browser.d.ts +20 -0
- package/dist/es/hcs-21/browser.d.ts.map +1 -0
- package/dist/es/hcs-21/errors.d.ts +6 -0
- package/dist/es/hcs-21/errors.d.ts.map +1 -0
- package/dist/es/hcs-21/index.d.ts +7 -0
- package/dist/es/hcs-21/index.d.ts.map +1 -0
- package/dist/es/hcs-21/sdk.d.ts +48 -0
- package/dist/es/hcs-21/sdk.d.ts.map +1 -0
- package/dist/es/hcs-21/tx.d.ts +20 -0
- package/dist/es/hcs-21/tx.d.ts.map +1 -0
- package/dist/es/hcs-21/types.d.ts +89 -0
- package/dist/es/hcs-21/types.d.ts.map +1 -0
- package/dist/es/index.d.ts +1 -0
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/services/registry-broker/client.d.ts.map +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 +67 -48
- package/dist/es/standards-sdk.es.js.map +1 -1
- package/dist/es/standards-sdk.es10.js +2 -2
- package/dist/es/standards-sdk.es100.js +231 -28
- package/dist/es/standards-sdk.es100.js.map +1 -1
- package/dist/es/standards-sdk.es101.js +109 -18
- package/dist/es/standards-sdk.es101.js.map +1 -1
- package/dist/es/standards-sdk.es102.js +32 -158
- package/dist/es/standards-sdk.es102.js.map +1 -1
- package/dist/es/standards-sdk.es103.js +80 -204
- package/dist/es/standards-sdk.es103.js.map +1 -1
- package/dist/es/standards-sdk.es104.js +21 -780
- package/dist/es/standards-sdk.es104.js.map +1 -1
- package/dist/es/standards-sdk.es105.js +140 -11
- package/dist/es/standards-sdk.es105.js.map +1 -1
- package/dist/es/standards-sdk.es106.js +29 -567
- package/dist/es/standards-sdk.es106.js.map +1 -1
- package/dist/es/standards-sdk.es107.js +17 -597
- package/dist/es/standards-sdk.es107.js.map +1 -1
- package/dist/es/standards-sdk.es108.js +159 -12
- package/dist/es/standards-sdk.es108.js.map +1 -1
- package/dist/es/standards-sdk.es109.js +208 -2
- package/dist/es/standards-sdk.es109.js.map +1 -1
- package/dist/es/standards-sdk.es110.js +774 -67
- package/dist/es/standards-sdk.es110.js.map +1 -1
- package/dist/es/standards-sdk.es111.js +11 -37
- package/dist/es/standards-sdk.es111.js.map +1 -1
- package/dist/es/standards-sdk.es112.js +567 -2
- package/dist/es/standards-sdk.es112.js.map +1 -1
- package/dist/es/standards-sdk.es113.js +576 -197
- package/dist/es/standards-sdk.es113.js.map +1 -1
- package/dist/es/standards-sdk.es114.js +12 -1139
- package/dist/es/standards-sdk.es114.js.map +1 -1
- package/dist/es/standards-sdk.es115.js +2 -306
- package/dist/es/standards-sdk.es115.js.map +1 -1
- package/dist/es/standards-sdk.es116.js +79 -418
- package/dist/es/standards-sdk.es116.js.map +1 -1
- package/dist/es/standards-sdk.es117.js +35 -351
- package/dist/es/standards-sdk.es117.js.map +1 -1
- package/dist/es/standards-sdk.es118.js +2 -761
- package/dist/es/standards-sdk.es118.js.map +1 -1
- package/dist/es/standards-sdk.es119.js +204 -185
- package/dist/es/standards-sdk.es119.js.map +1 -1
- package/dist/es/standards-sdk.es12.js +1 -1
- package/dist/es/standards-sdk.es120.js +1055 -1482
- package/dist/es/standards-sdk.es120.js.map +1 -1
- package/dist/es/standards-sdk.es121.js +265 -2024
- package/dist/es/standards-sdk.es121.js.map +1 -1
- package/dist/es/standards-sdk.es122.js +420 -50
- package/dist/es/standards-sdk.es122.js.map +1 -1
- package/dist/es/standards-sdk.es123.js +350 -82
- package/dist/es/standards-sdk.es123.js.map +1 -1
- package/dist/es/standards-sdk.es124.js +741 -139
- package/dist/es/standards-sdk.es124.js.map +1 -1
- package/dist/es/standards-sdk.es125.js +204 -7
- package/dist/es/standards-sdk.es125.js.map +1 -1
- package/dist/es/standards-sdk.es126.js +1533 -52
- package/dist/es/standards-sdk.es126.js.map +1 -1
- package/dist/es/standards-sdk.es127.js +2077 -59
- package/dist/es/standards-sdk.es127.js.map +1 -1
- package/dist/es/standards-sdk.es128.js +52 -28
- package/dist/es/standards-sdk.es128.js.map +1 -1
- package/dist/es/standards-sdk.es129.js +80 -131
- package/dist/es/standards-sdk.es129.js.map +1 -1
- package/dist/es/standards-sdk.es13.js +1 -1
- package/dist/es/standards-sdk.es130.js +152 -35
- package/dist/es/standards-sdk.es130.js.map +1 -1
- package/dist/es/standards-sdk.es131.js +7 -17
- package/dist/es/standards-sdk.es131.js.map +1 -1
- package/dist/es/standards-sdk.es132.js +53 -12241
- package/dist/es/standards-sdk.es132.js.map +1 -1
- package/dist/es/standards-sdk.es133.js +65 -694
- package/dist/es/standards-sdk.es133.js.map +1 -1
- package/dist/es/standards-sdk.es134.js +28 -172
- package/dist/es/standards-sdk.es134.js.map +1 -1
- package/dist/es/standards-sdk.es135.js +115 -299
- package/dist/es/standards-sdk.es135.js.map +1 -1
- package/dist/es/standards-sdk.es136.js +36 -340
- package/dist/es/standards-sdk.es136.js.map +1 -1
- package/dist/es/standards-sdk.es137.js +694 -453
- package/dist/es/standards-sdk.es137.js.map +1 -1
- package/dist/es/standards-sdk.es138.js +12210 -267
- package/dist/es/standards-sdk.es138.js.map +1 -1
- package/dist/es/standards-sdk.es139.js +15 -74
- package/dist/es/standards-sdk.es139.js.map +1 -1
- package/dist/es/standards-sdk.es14.js +1 -1
- package/dist/es/standards-sdk.es141.js +1 -1
- package/dist/es/standards-sdk.es142.js +175 -0
- package/dist/es/standards-sdk.es142.js.map +1 -0
- package/dist/es/standards-sdk.es143.js +325 -0
- package/dist/es/standards-sdk.es143.js.map +1 -0
- package/dist/es/standards-sdk.es144.js +349 -0
- package/dist/es/standards-sdk.es144.js.map +1 -0
- package/dist/es/standards-sdk.es145.js +456 -0
- package/dist/es/standards-sdk.es145.js.map +1 -0
- package/dist/es/standards-sdk.es146.js +334 -0
- package/dist/es/standards-sdk.es146.js.map +1 -0
- package/dist/es/standards-sdk.es147.js +79 -0
- package/dist/es/standards-sdk.es147.js.map +1 -0
- package/dist/es/standards-sdk.es15.js +1 -1
- package/dist/es/standards-sdk.es16.js +1 -1
- package/dist/es/standards-sdk.es17.js +5 -5
- package/dist/es/standards-sdk.es19.js +12 -12
- package/dist/es/standards-sdk.es20.js +9 -9
- package/dist/es/standards-sdk.es21.js +1 -1
- package/dist/es/standards-sdk.es22.js +1 -1
- package/dist/es/standards-sdk.es23.js +1 -1
- package/dist/es/standards-sdk.es24.js +1 -1
- package/dist/es/standards-sdk.es25.js +1 -1
- package/dist/es/standards-sdk.es26.js +1 -1
- package/dist/es/standards-sdk.es27.js +1 -1
- package/dist/es/standards-sdk.es28.js +12 -12
- package/dist/es/standards-sdk.es3.js +2 -2
- package/dist/es/standards-sdk.es31.js +2 -2
- package/dist/es/standards-sdk.es32.js +4 -4
- package/dist/es/standards-sdk.es33.js +1 -1
- package/dist/es/standards-sdk.es36.js +6 -6
- package/dist/es/standards-sdk.es37.js +4 -4
- package/dist/es/standards-sdk.es38.js +2 -2
- package/dist/es/standards-sdk.es39.js +2 -2
- package/dist/es/standards-sdk.es40.js +1 -1
- package/dist/es/standards-sdk.es41.js +1 -1
- package/dist/es/standards-sdk.es42.js +2 -2
- package/dist/es/standards-sdk.es47.js +1 -1
- package/dist/es/standards-sdk.es5.js +2 -2
- package/dist/es/standards-sdk.es52.js +1 -1
- package/dist/es/standards-sdk.es54.js +1 -1
- package/dist/es/standards-sdk.es57.js +1 -1
- package/dist/es/standards-sdk.es6.js +2 -2
- package/dist/es/standards-sdk.es61.js +7 -7
- package/dist/es/standards-sdk.es65.js +2 -2
- package/dist/es/standards-sdk.es66.js +3 -3
- package/dist/es/standards-sdk.es69.js +2 -2
- package/dist/es/standards-sdk.es7.js +2 -2
- package/dist/es/standards-sdk.es70.js +3 -3
- package/dist/es/standards-sdk.es71.js +2 -2
- package/dist/es/standards-sdk.es72.js +1 -1
- package/dist/es/standards-sdk.es75.js +2 -2
- package/dist/es/standards-sdk.es77.js +2 -2
- package/dist/es/standards-sdk.es78.js +4 -4
- package/dist/es/standards-sdk.es79.js +1 -1
- package/dist/es/standards-sdk.es8.js +1 -1
- package/dist/es/standards-sdk.es80.js +41 -27
- package/dist/es/standards-sdk.es80.js.map +1 -1
- package/dist/es/standards-sdk.es81.js +6 -78
- package/dist/es/standards-sdk.es81.js.map +1 -1
- package/dist/es/standards-sdk.es82.js +27 -64
- package/dist/es/standards-sdk.es82.js.map +1 -1
- package/dist/es/standards-sdk.es83.js +69 -23
- package/dist/es/standards-sdk.es83.js.map +1 -1
- package/dist/es/standards-sdk.es84.js +165 -23
- package/dist/es/standards-sdk.es84.js.map +1 -1
- package/dist/es/standards-sdk.es85.js +31 -166
- package/dist/es/standards-sdk.es85.js.map +1 -1
- package/dist/es/standards-sdk.es86.js +24 -127
- package/dist/es/standards-sdk.es86.js.map +1 -1
- package/dist/es/standards-sdk.es87.js +65 -142
- package/dist/es/standards-sdk.es87.js.map +1 -1
- package/dist/es/standards-sdk.es88.js +52 -127
- package/dist/es/standards-sdk.es88.js.map +1 -1
- package/dist/es/standards-sdk.es89.js +26 -41
- package/dist/es/standards-sdk.es89.js.map +1 -1
- package/dist/es/standards-sdk.es90.js +23 -261
- package/dist/es/standards-sdk.es90.js.map +1 -1
- package/dist/es/standards-sdk.es91.js +162 -93
- package/dist/es/standards-sdk.es91.js.map +1 -1
- package/dist/es/standards-sdk.es92.js +112 -83
- package/dist/es/standards-sdk.es92.js.map +1 -1
- package/dist/es/standards-sdk.es93.js +156 -28
- package/dist/es/standards-sdk.es93.js.map +1 -1
- package/dist/es/standards-sdk.es94.js +133 -225
- package/dist/es/standards-sdk.es94.js.map +1 -1
- package/dist/es/standards-sdk.es95.js +40 -108
- package/dist/es/standards-sdk.es95.js.map +1 -1
- package/dist/es/standards-sdk.es96.js +253 -24
- package/dist/es/standards-sdk.es96.js.map +1 -1
- package/dist/es/standards-sdk.es97.js +96 -80
- package/dist/es/standards-sdk.es97.js.map +1 -1
- package/dist/es/standards-sdk.es98.js +91 -21
- package/dist/es/standards-sdk.es98.js.map +1 -1
- package/dist/es/standards-sdk.es99.js +28 -141
- package/dist/es/standards-sdk.es99.js.map +1 -1
- package/package.json +62 -59
|
@@ -1,266 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
topics: params.topics,
|
|
22
|
-
account_id: params.accountId,
|
|
23
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24
|
-
m: params.memo
|
|
25
|
-
};
|
|
26
|
-
return msg;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Validate an HCS‑17 message against the schema.
|
|
30
|
-
*/
|
|
31
|
-
validateMessage(message) {
|
|
32
|
-
const res = hcs17MessageSchema.safeParse(message);
|
|
33
|
-
if (res.success) {
|
|
34
|
-
return { valid: true, errors: [] };
|
|
35
|
-
}
|
|
36
|
-
const errors = res.error.errors.map(
|
|
37
|
-
(e) => `${e.path.join(".")}: ${e.message}`
|
|
38
|
-
);
|
|
39
|
-
this.logger.debug(`HCS-17 message validation failed: ${errors.join(", ")}`);
|
|
40
|
-
return { valid: false, errors };
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Generate default HCS‑17 topic memo using numeric enum codes.
|
|
44
|
-
*/
|
|
45
|
-
generateTopicMemo(ttl) {
|
|
46
|
-
return generateHCS17Memo(ttl);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Validate that a topic is a valid HCS‑17 topic and return parsed info.
|
|
50
|
-
*/
|
|
51
|
-
async validateHCS17Topic(topicId) {
|
|
52
|
-
try {
|
|
53
|
-
const info = await this.mirrorNode.getTopicInfo(topicId);
|
|
54
|
-
const parsed = parseHCS17Memo(info.memo);
|
|
55
|
-
if (!parsed) {
|
|
56
|
-
return { valid: false, error: "Invalid HCS-17 memo format" };
|
|
57
|
-
}
|
|
58
|
-
if (parsed.type !== HCS17TopicType.STATE) {
|
|
59
|
-
return { valid: false, error: "Unsupported HCS-17 topic type" };
|
|
60
|
-
}
|
|
61
|
-
return { valid: true, type: parsed.type, ttl: parsed.ttl };
|
|
62
|
-
} catch (e) {
|
|
63
|
-
return { valid: false, error: String(e) };
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Fetch recent HCS‑17 messages from a topic via Mirror Node.
|
|
68
|
-
*/
|
|
69
|
-
async getRecentMessages(topicId, options) {
|
|
70
|
-
const limit = options?.limit ?? 25;
|
|
71
|
-
const order = options?.order ?? "desc";
|
|
72
|
-
const items = await this.mirrorNode.getTopicMessages(topicId, {
|
|
73
|
-
limit,
|
|
74
|
-
order
|
|
75
|
-
});
|
|
76
|
-
const results = [];
|
|
77
|
-
for (const m of items) {
|
|
78
|
-
try {
|
|
79
|
-
if (m.p !== "hcs-17" || m.op !== "state_hash") {
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
const envelope = m;
|
|
83
|
-
const { valid } = this.validateMessage(envelope);
|
|
84
|
-
if (!valid) {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
results.push({
|
|
88
|
-
message: {
|
|
89
|
-
p: "hcs-17",
|
|
90
|
-
op: "state_hash",
|
|
91
|
-
state_hash: envelope.state_hash,
|
|
92
|
-
topics: envelope.topics,
|
|
93
|
-
account_id: envelope.account_id,
|
|
94
|
-
timestamp: envelope.timestamp,
|
|
95
|
-
m: envelope.m
|
|
96
|
-
},
|
|
97
|
-
consensus_timestamp: envelope.consensus_timestamp,
|
|
98
|
-
sequence_number: Number(envelope.sequence_number),
|
|
99
|
-
payer: envelope.payer
|
|
100
|
-
});
|
|
101
|
-
} catch (err) {
|
|
102
|
-
this.logger.debug(`Failed to parse HCS-17 message: ${err}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return results;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Return the latest valid HCS‑17 message on a topic, if any.
|
|
109
|
-
*/
|
|
110
|
-
async getLatestMessage(topicId) {
|
|
111
|
-
const items = await this.getRecentMessages(topicId, {
|
|
112
|
-
limit: 1,
|
|
113
|
-
order: "desc"
|
|
114
|
-
});
|
|
115
|
-
if (!items.length) {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
const { message, consensus_timestamp, sequence_number } = items[0];
|
|
119
|
-
return Object.assign({}, message, { consensus_timestamp, sequence_number });
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Calculate state hash for a single account.
|
|
123
|
-
*/
|
|
124
|
-
calculateAccountStateHash(input) {
|
|
125
|
-
try {
|
|
126
|
-
this.logger.debug("Calculating account state hash", {
|
|
127
|
-
accountId: input.accountId,
|
|
128
|
-
topicCount: input.topics.length
|
|
129
|
-
});
|
|
130
|
-
const sortedTopics = [...input.topics].sort(
|
|
131
|
-
(a, b) => a.topicId.localeCompare(b.topicId)
|
|
132
|
-
);
|
|
133
|
-
let concatenated = "";
|
|
134
|
-
for (const topic of sortedTopics) {
|
|
135
|
-
concatenated += topic.topicId + topic.latestRunningHash;
|
|
136
|
-
}
|
|
137
|
-
let publicKeyString = "";
|
|
138
|
-
if (typeof input.publicKey === "string") {
|
|
139
|
-
publicKeyString = input.publicKey;
|
|
140
|
-
} else {
|
|
141
|
-
publicKeyString = input.publicKey.toString();
|
|
142
|
-
}
|
|
143
|
-
concatenated += publicKeyString;
|
|
144
|
-
const hash = createHash("sha384");
|
|
145
|
-
hash.update(concatenated);
|
|
146
|
-
const stateHash = hash.digest("hex");
|
|
147
|
-
this.logger.debug("Account state hash calculated", {
|
|
148
|
-
accountId: input.accountId,
|
|
149
|
-
stateHash
|
|
150
|
-
});
|
|
151
|
-
return {
|
|
152
|
-
stateHash,
|
|
153
|
-
accountId: input.accountId,
|
|
154
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
155
|
-
topicCount: input.topics.length
|
|
156
|
-
};
|
|
157
|
-
} catch (error) {
|
|
158
|
-
this.logger.error("Failed to calculate account state hash", error);
|
|
159
|
-
throw new Error("HCS-17 CALCULATION_FAILED");
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Calculate composite state hash for composite accounts (e.g., Flora/Bloom).
|
|
164
|
-
*/
|
|
165
|
-
calculateCompositeStateHash(input) {
|
|
166
|
-
try {
|
|
167
|
-
this.logger.debug("Calculating composite state hash", {
|
|
168
|
-
compositeAccountId: input.compositeAccountId,
|
|
169
|
-
memberCount: input.memberStates.length,
|
|
170
|
-
topicCount: input.compositeTopics.length
|
|
171
|
-
});
|
|
172
|
-
const sortedMembers = [...input.memberStates].sort(
|
|
173
|
-
(a, b) => a.accountId.localeCompare(b.accountId)
|
|
174
|
-
);
|
|
175
|
-
const sortedTopics = [...input.compositeTopics].sort(
|
|
176
|
-
(a, b) => a.topicId.localeCompare(b.topicId)
|
|
177
|
-
);
|
|
178
|
-
let concatenated = "";
|
|
179
|
-
for (const member of sortedMembers) {
|
|
180
|
-
concatenated += member.accountId + member.stateHash;
|
|
181
|
-
}
|
|
182
|
-
for (const topic of sortedTopics) {
|
|
183
|
-
concatenated += topic.topicId + topic.latestRunningHash;
|
|
184
|
-
}
|
|
185
|
-
concatenated += input.compositePublicKeyFingerprint;
|
|
186
|
-
const hash = createHash("sha384");
|
|
187
|
-
hash.update(concatenated);
|
|
188
|
-
const stateHash = hash.digest("hex");
|
|
189
|
-
this.logger.debug("Composite state hash calculated", {
|
|
190
|
-
compositeAccountId: input.compositeAccountId,
|
|
191
|
-
stateHash
|
|
192
|
-
});
|
|
193
|
-
return {
|
|
194
|
-
stateHash,
|
|
195
|
-
accountId: input.compositeAccountId,
|
|
196
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
197
|
-
topicCount: input.compositeTopics.length,
|
|
198
|
-
memberCount: input.memberStates.length,
|
|
199
|
-
compositeTopicCount: input.compositeTopics.length
|
|
200
|
-
};
|
|
201
|
-
} catch (error) {
|
|
202
|
-
this.logger.error("Failed to calculate composite state hash", error);
|
|
203
|
-
throw new Error("HCS-17 COMPOSITE_CALCULATION_FAILED");
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Calculate deterministic fingerprint for a threshold key from member public keys.
|
|
208
|
-
*/
|
|
209
|
-
calculateKeyFingerprint(keys, threshold) {
|
|
210
|
-
try {
|
|
211
|
-
const sortedKeys = [...keys].sort(
|
|
212
|
-
(a, b) => a.toString().localeCompare(b.toString())
|
|
213
|
-
);
|
|
214
|
-
const keyData = { threshold, keys: sortedKeys.map((k) => k.toString()) };
|
|
215
|
-
const hash = createHash("sha384");
|
|
216
|
-
hash.update(JSON.stringify(keyData));
|
|
217
|
-
return hash.digest("hex");
|
|
218
|
-
} catch (error) {
|
|
219
|
-
this.logger.error("Failed to calculate key fingerprint", error);
|
|
220
|
-
throw new Error("HCS-17 FINGERPRINT_FAILED");
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Build a valid HCS‑17 state hash message.
|
|
225
|
-
*/
|
|
226
|
-
createStateHashMessage(stateHash, accountId, topicIds, memo) {
|
|
227
|
-
return {
|
|
228
|
-
p: "hcs-17",
|
|
229
|
-
op: "state_hash",
|
|
230
|
-
state_hash: stateHash,
|
|
231
|
-
topics: topicIds,
|
|
232
|
-
account_id: accountId,
|
|
233
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
234
|
-
m: memo
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Recompute and verify a state hash input against an expected value.
|
|
239
|
-
*/
|
|
240
|
-
async verifyStateHash(input, expectedHash) {
|
|
241
|
-
try {
|
|
242
|
-
let calculatedHash;
|
|
243
|
-
if ("publicKey" in input) {
|
|
244
|
-
calculatedHash = this.calculateAccountStateHash(input).stateHash;
|
|
245
|
-
} else {
|
|
246
|
-
calculatedHash = this.calculateCompositeStateHash(input).stateHash;
|
|
247
|
-
}
|
|
248
|
-
const isValid = calculatedHash === expectedHash;
|
|
249
|
-
const accountId = "accountId" in input ? input.accountId : input.compositeAccountId;
|
|
250
|
-
this.logger.debug("State hash verification", {
|
|
251
|
-
accountId,
|
|
252
|
-
isValid,
|
|
253
|
-
expected: expectedHash,
|
|
254
|
-
calculated: calculatedHash
|
|
255
|
-
});
|
|
256
|
-
return isValid;
|
|
257
|
-
} catch (error) {
|
|
258
|
-
this.logger.error("Failed to verify state hash", error);
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
1
|
+
var FloraTopicType = /* @__PURE__ */ ((FloraTopicType2) => {
|
|
2
|
+
FloraTopicType2[FloraTopicType2["COMMUNICATION"] = 0] = "COMMUNICATION";
|
|
3
|
+
FloraTopicType2[FloraTopicType2["TRANSACTION"] = 1] = "TRANSACTION";
|
|
4
|
+
FloraTopicType2[FloraTopicType2["STATE"] = 2] = "STATE";
|
|
5
|
+
return FloraTopicType2;
|
|
6
|
+
})(FloraTopicType || {});
|
|
7
|
+
var FloraOperation = /* @__PURE__ */ ((FloraOperation2) => {
|
|
8
|
+
FloraOperation2["FLORA_CREATED"] = "flora_created";
|
|
9
|
+
FloraOperation2["TRANSACTION"] = "transaction";
|
|
10
|
+
FloraOperation2["STATE_UPDATE"] = "state_update";
|
|
11
|
+
FloraOperation2["FLORA_JOIN_REQUEST"] = "flora_join_request";
|
|
12
|
+
FloraOperation2["FLORA_JOIN_VOTE"] = "flora_join_vote";
|
|
13
|
+
FloraOperation2["FLORA_JOIN_ACCEPTED"] = "flora_join_accepted";
|
|
14
|
+
return FloraOperation2;
|
|
15
|
+
})(FloraOperation || {});
|
|
16
|
+
class FloraError extends Error {
|
|
17
|
+
constructor(message, code) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.name = "FloraError";
|
|
261
21
|
}
|
|
262
22
|
}
|
|
263
23
|
export {
|
|
264
|
-
|
|
24
|
+
FloraError,
|
|
25
|
+
FloraOperation,
|
|
26
|
+
FloraTopicType
|
|
265
27
|
};
|
|
266
28
|
//# sourceMappingURL=standards-sdk.es90.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es90.js","sources":["../../src/hcs-17/base-client.ts"],"sourcesContent":["import { HederaMirrorNode } from '../services/mirror-node';\nimport { Logger, ILogger } from '../utils/logger';\nimport { NetworkType } from '../utils/types';\nimport { createHash } from 'crypto';\nimport {\n hcs17MessageSchema,\n StateHashMessage,\n HCS17ClientConfig,\n parseHCS17Memo,\n generateHCS17Memo,\n HCS17TopicType,\n AccountStateInput,\n CompositeStateInput,\n StateHashResult,\n CompositeStateHashResult,\n} from './types';\nimport { PublicKey } from '@hashgraph/sdk';\n\n/**\n * Base client for HCS‑17 functionality, shared between Node and Browser clients.\n * Provides logging, mirror‑node access, message creation/validation,\n * topic memo helpers, and registry/message querying utilities.\n */\nexport class HCS17BaseClient {\n protected readonly network: NetworkType;\n protected readonly mirrorNode: HederaMirrorNode;\n protected readonly logger: ILogger;\n\n constructor(config: HCS17ClientConfig) {\n this.network = config.network;\n this.logger =\n config.logger ||\n new Logger({ level: config.logLevel || 'info', module: 'HCS-17' });\n this.mirrorNode = new HederaMirrorNode(this.network, this.logger, {\n customUrl: config.mirrorNodeUrl,\n });\n }\n\n /**\n * Create a valid HCS‑17 state hash message payload.\n */\n protected createMessage(params: {\n stateHash: string;\n accountId: string;\n topics: string[];\n memo?: string;\n }): StateHashMessage {\n const msg: StateHashMessage = {\n p: 'hcs-17',\n op: 'state_hash',\n state_hash: params.stateHash,\n topics: params.topics,\n account_id: params.accountId,\n timestamp: new Date().toISOString(),\n m: params.memo,\n };\n return msg;\n }\n\n /**\n * Validate an HCS‑17 message against the schema.\n */\n protected validateMessage(message: unknown): {\n valid: boolean;\n errors: string[];\n } {\n const res = hcs17MessageSchema.safeParse(message);\n if (res.success) {\n return { valid: true, errors: [] };\n }\n const errors = res.error.errors.map(\n e => `${e.path.join('.')}: ${e.message}`,\n );\n this.logger.debug(`HCS-17 message validation failed: ${errors.join(', ')}`);\n return { valid: false, errors };\n }\n\n /**\n * Generate default HCS‑17 topic memo using numeric enum codes.\n */\n protected generateTopicMemo(ttl: number): string {\n return generateHCS17Memo(ttl);\n }\n\n /**\n * Validate that a topic is a valid HCS‑17 topic and return parsed info.\n */\n async validateHCS17Topic(topicId: string): Promise<{\n valid: boolean;\n type?: HCS17TopicType;\n ttl?: number;\n error?: string;\n }> {\n try {\n const info = await this.mirrorNode.getTopicInfo(topicId);\n const parsed = parseHCS17Memo(info.memo);\n if (!parsed) {\n return { valid: false, error: 'Invalid HCS-17 memo format' };\n }\n if (parsed.type !== HCS17TopicType.STATE) {\n return { valid: false, error: 'Unsupported HCS-17 topic type' };\n }\n return { valid: true, type: parsed.type, ttl: parsed.ttl };\n } catch (e: unknown) {\n return { valid: false, error: String(e) };\n }\n }\n\n /**\n * Fetch recent HCS‑17 messages from a topic via Mirror Node.\n */\n async getRecentMessages(\n topicId: string,\n options?: { limit?: number; order?: 'asc' | 'desc' },\n ): Promise<\n Array<{\n message: StateHashMessage;\n consensus_timestamp?: string;\n sequence_number: number;\n payer?: string;\n }>\n > {\n const limit = options?.limit ?? 25;\n const order = options?.order ?? 'desc';\n const items = await this.mirrorNode.getTopicMessages(topicId, {\n limit,\n order,\n });\n type HCS17Envelope = StateHashMessage & {\n consensus_timestamp?: string;\n sequence_number: number;\n payer?: string;\n };\n const results: Array<{\n message: StateHashMessage;\n consensus_timestamp?: string;\n sequence_number: number;\n payer?: string;\n }> = [];\n for (const m of items) {\n try {\n if (m.p !== 'hcs-17' || m.op !== 'state_hash') {\n continue;\n }\n const envelope = m as unknown as HCS17Envelope;\n const { valid } = this.validateMessage(envelope);\n if (!valid) {\n continue;\n }\n results.push({\n message: {\n p: 'hcs-17',\n op: 'state_hash',\n state_hash: envelope.state_hash,\n topics: envelope.topics,\n account_id: envelope.account_id,\n timestamp: envelope.timestamp,\n m: envelope.m,\n },\n consensus_timestamp: envelope.consensus_timestamp,\n sequence_number: Number(envelope.sequence_number),\n payer: envelope.payer,\n });\n } catch (err) {\n this.logger.debug(`Failed to parse HCS-17 message: ${err}`);\n }\n }\n return results;\n }\n\n /**\n * Return the latest valid HCS‑17 message on a topic, if any.\n */\n async getLatestMessage(topicId: string): Promise<\n | (StateHashMessage & {\n consensus_timestamp?: string;\n sequence_number: number;\n })\n | null\n > {\n const items = await this.getRecentMessages(topicId, {\n limit: 1,\n order: 'desc',\n });\n if (!items.length) {\n return null;\n }\n const { message, consensus_timestamp, sequence_number } = items[0];\n return Object.assign({}, message, { consensus_timestamp, sequence_number });\n }\n\n /**\n * Calculate state hash for a single account.\n */\n public 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 let publicKeyString = '';\n if (typeof input.publicKey === 'string') {\n publicKeyString = input.publicKey;\n } else {\n publicKeyString = input.publicKey.toString();\n }\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 Error('HCS-17 CALCULATION_FAILED');\n }\n }\n\n /**\n * Calculate composite state hash for composite accounts (e.g., Flora/Bloom).\n */\n public 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 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 Error('HCS-17 COMPOSITE_CALCULATION_FAILED');\n }\n }\n\n /**\n * Calculate deterministic fingerprint for a threshold key from member public keys.\n */\n public calculateKeyFingerprint(keys: PublicKey[], threshold: number): string {\n try {\n const sortedKeys = [...keys].sort((a, b) =>\n a.toString().localeCompare(b.toString()),\n );\n const keyData = { threshold, keys: sortedKeys.map(k => k.toString()) };\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 Error('HCS-17 FINGERPRINT_FAILED');\n }\n }\n\n /**\n * Build a valid HCS‑17 state hash message.\n */\n public 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 * Recompute and verify a state hash input against an expected value.\n */\n public async verifyStateHash(\n input: AccountStateInput | CompositeStateInput,\n expectedHash: string,\n ): Promise<boolean> {\n try {\n let calculatedHash: string;\n if ('publicKey' in input) {\n calculatedHash = this.calculateAccountStateHash(input).stateHash;\n } else {\n calculatedHash = this.calculateCompositeStateHash(input).stateHash;\n }\n const isValid = calculatedHash === expectedHash;\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 return isValid;\n } catch (error) {\n this.logger.error('Failed to verify state hash', error);\n return false;\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es90.js","sources":["../../src/hcs-16/types.ts"],"sourcesContent":["import {\n AccountId,\n TopicId,\n PublicKey,\n Key,\n PrivateKey,\n KeyList,\n TokenId,\n} from '@hashgraph/sdk';\nimport { BaseProfile, SocialLink } from '../hcs-11/types';\n\n/**\n * HCS-16 Topic type enums\n */\nexport enum FloraTopicType {\n COMMUNICATION = 0,\n TRANSACTION = 1,\n STATE = 2,\n}\n\n/**\n * HCS-16 Flora member\n */\nexport interface FloraMember {\n accountId: string;\n publicKey?: PublicKey | string;\n privateKey?: string;\n weight?: number;\n}\n\n/**\n * HCS-16 Flora topics\n */\nexport interface FloraTopics {\n communication: TopicId;\n transaction: TopicId;\n state: TopicId;\n custom?: Array<{\n name: string;\n topicId: string;\n description?: string;\n }>;\n}\n\n/**\n * HCS-16 Flora configuration\n */\nexport interface FloraConfig {\n displayName: string;\n bio?: string;\n members: FloraMember[];\n threshold: number;\n initialBalance?: number;\n maxAutomaticTokenAssociations?: number;\n policies?: {\n membershipChange?: string;\n scheduleTxApproval?: string;\n };\n customFees?: {\n amount: number;\n feeCollectorAccountId: string;\n }[];\n metadata?: Record<string, any>;\n}\n\n/**\n * HCS-16 Flora creation result\n */\nexport interface FloraCreationResult {\n floraAccountId: AccountId;\n topics: FloraTopics;\n keyList: Key;\n transactionId: string;\n}\n\n/**\n * HCS-16 Message protocol operations\n */\nexport enum FloraOperation {\n FLORA_CREATED = 'flora_created',\n TRANSACTION = 'transaction',\n STATE_UPDATE = 'state_update',\n FLORA_JOIN_REQUEST = 'flora_join_request',\n FLORA_JOIN_VOTE = 'flora_join_vote',\n FLORA_JOIN_ACCEPTED = 'flora_join_accepted',\n}\n\n/**\n * HCS-16 Message envelope\n */\nexport interface FloraMessage {\n p: 'hcs-16';\n op: FloraOperation;\n operator_id: string;\n m?: string;\n [key: string]: unknown;\n}\n\n/**\n * HCS-16 Flora profile (extends HCS-11)\n */\nexport interface FloraProfile extends BaseProfile {\n version: string;\n type: 3;\n display_name: string;\n members: FloraMember[];\n threshold: number;\n topics: {\n communication: string;\n transaction: string;\n state: string;\n custom?: Array<{\n name: string;\n topicId: string;\n description?: string;\n }>;\n };\n alias?: string;\n bio?: string;\n socials?: SocialLink[];\n profileImage?: string;\n properties?: Record<string, unknown>;\n inboundTopicId: string;\n outboundTopicId: string;\n policies?: Record<string, string>;\n metadata?: Record<string, any>;\n}\n\n/**\n * HCS-16 errors\n */\nexport class FloraError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = 'FloraError';\n }\n}\n\n/**\n * Flora state update message\n */\nexport interface FloraStateUpdate {\n p: 'hcs-16';\n op: 'state_update';\n operator_id: string;\n hash: string;\n epoch?: number;\n members?: string[];\n timestamp: string;\n}\n\n/**\n * HIP-991 Custom fee configuration for transaction topics\n */\nexport interface TransactionTopicFee {\n amount: number;\n feeCollectorAccountId: string;\n denominatingTokenId?: string;\n}\n\n/**\n * Configuration for creating HCS-16 transaction topics with HIP-991 support\n */\nexport interface TransactionTopicConfig {\n memo: string;\n adminKey?: PrivateKey | KeyList;\n submitKey?: PrivateKey | KeyList;\n feeScheduleKey?: PrivateKey | KeyList;\n customFees?: TransactionTopicFee[];\n feeExemptKeys?: Key[];\n}\n\n/** credit_purchase not part of HCS-16 specification; no message type defined. */\n"],"names":["FloraTopicType","FloraOperation"],"mappings":"AAcO,IAAK,mCAAAA,oBAAL;AACLA,kBAAAA,gBAAA,mBAAgB,CAAA,IAAhB;AACAA,kBAAAA,gBAAA,iBAAc,CAAA,IAAd;AACAA,kBAAAA,gBAAA,WAAQ,CAAA,IAAR;AAHU,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AAgEL,IAAK,mCAAAC,oBAAL;AACLA,kBAAA,eAAA,IAAgB;AAChBA,kBAAA,aAAA,IAAc;AACdA,kBAAA,cAAA,IAAe;AACfA,kBAAA,oBAAA,IAAqB;AACrBA,kBAAA,iBAAA,IAAkB;AAClBA,kBAAA,qBAAA,IAAsB;AANZ,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AAqDL,MAAM,mBAAmB,MAAM;AAAA,EACpC,YACE,SACgB,MAChB;AACA,UAAM,OAAO;AAFG,SAAA,OAAA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;"}
|
|
@@ -1,103 +1,172 @@
|
|
|
1
|
-
import { AccountId,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { AccountId, TopicCreateTransaction, CustomFixedFee, TokenId, AccountCreateTransaction, Hbar, AccountUpdateTransaction, ScheduleCreateTransaction, TopicUpdateTransaction } from "@hashgraph/sdk";
|
|
2
|
+
import { buildTopicCreateTx, buildMessageTx } from "./standards-sdk.es136.js";
|
|
3
|
+
import { FloraOperation } from "./standards-sdk.es90.js";
|
|
4
|
+
function encodeHcs16FloraMemo(params) {
|
|
5
|
+
return `hcs-16:${params.floraAccountId}:${params.topicType}`;
|
|
6
|
+
}
|
|
7
|
+
function buildHcs16CreateFloraTopicTx(params) {
|
|
8
|
+
const memo = encodeHcs16FloraMemo({
|
|
9
|
+
floraAccountId: params.floraAccountId,
|
|
10
|
+
topicType: params.topicType
|
|
11
|
+
});
|
|
12
|
+
const tx = buildTopicCreateTx({
|
|
13
|
+
memo,
|
|
14
|
+
adminKey: params.adminKey,
|
|
15
|
+
submitKey: params.submitKey,
|
|
16
|
+
operatorPublicKey: params.operatorPublicKey
|
|
17
|
+
});
|
|
18
|
+
if (params.autoRenewAccountId) {
|
|
19
|
+
tx.setAutoRenewAccountId(AccountId.fromString(params.autoRenewAccountId));
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
return tx;
|
|
22
|
+
}
|
|
23
|
+
function buildHcs16CreateTransactionTopicTx(params) {
|
|
24
|
+
const tx = new TopicCreateTransaction().setTopicMemo(params.memo);
|
|
25
|
+
if (params.adminKey) {
|
|
26
|
+
tx.setAdminKey(params.adminKey);
|
|
22
27
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*/
|
|
26
|
-
async createStateTopic(options) {
|
|
27
|
-
const ttl = options?.ttl ?? 86400;
|
|
28
|
-
const tx = buildHcs17CreateTopicTx({
|
|
29
|
-
ttl,
|
|
30
|
-
adminKey: options?.adminKey,
|
|
31
|
-
submitKey: options?.submitKey,
|
|
32
|
-
operatorPublicKey: this.client.operatorPublicKey || void 0
|
|
33
|
-
});
|
|
34
|
-
const resp = await tx.execute(this.client);
|
|
35
|
-
const receipt = await resp.getReceipt(this.client);
|
|
36
|
-
if (!receipt.topicId) {
|
|
37
|
-
throw new Error("Failed to create topic: topicId empty");
|
|
38
|
-
}
|
|
39
|
-
const topicId = receipt.topicId.toString();
|
|
40
|
-
this.logger.info(`Created HCS-17 state topic ${topicId}`);
|
|
41
|
-
return topicId;
|
|
28
|
+
if (params.submitKey) {
|
|
29
|
+
tx.setSubmitKey(params.submitKey);
|
|
42
30
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
*/
|
|
46
|
-
async submitMessage(topicId, message) {
|
|
47
|
-
const { valid, errors } = this.validateMessage(message);
|
|
48
|
-
if (!valid) {
|
|
49
|
-
throw new Error(`Invalid HCS-17 message: ${errors.join(", ")}`);
|
|
50
|
-
}
|
|
51
|
-
const tx = buildHcs17MessageTx({
|
|
52
|
-
topicId,
|
|
53
|
-
stateHash: message.state_hash,
|
|
54
|
-
accountId: message.account_id,
|
|
55
|
-
topics: message.topics,
|
|
56
|
-
memo: message.m
|
|
57
|
-
});
|
|
58
|
-
const resp = await tx.execute(this.client);
|
|
59
|
-
const receipt = await resp.getReceipt(this.client);
|
|
60
|
-
return receipt;
|
|
31
|
+
if (params.feeScheduleKey) {
|
|
32
|
+
tx.setFeeScheduleKey(params.feeScheduleKey);
|
|
61
33
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
const latest = msgs[0];
|
|
73
|
-
const running = latest?.running_hash || "";
|
|
74
|
-
topicStates.push({ topicId: t, latestRunningHash: running });
|
|
75
|
-
}
|
|
76
|
-
const input = {
|
|
77
|
-
accountId: params.accountId,
|
|
78
|
-
publicKey: params.accountPublicKey,
|
|
79
|
-
topics: topicStates
|
|
80
|
-
};
|
|
81
|
-
const result = this.calculateAccountStateHash(input);
|
|
82
|
-
this.createStateHashMessage(
|
|
83
|
-
result.stateHash,
|
|
84
|
-
params.accountId,
|
|
85
|
-
params.topics,
|
|
86
|
-
params.memo
|
|
87
|
-
);
|
|
88
|
-
const tx = buildHcs17MessageTx({
|
|
89
|
-
topicId: params.publishTopicId,
|
|
90
|
-
stateHash: result.stateHash,
|
|
91
|
-
accountId: params.accountId,
|
|
92
|
-
topics: params.topics,
|
|
93
|
-
memo: params.memo
|
|
34
|
+
if (params.customFees && params.customFees.length > 0) {
|
|
35
|
+
const fees = params.customFees.map((fee) => {
|
|
36
|
+
const cf = new CustomFixedFee().setAmount(fee.amount).setFeeCollectorAccountId(
|
|
37
|
+
AccountId.fromString(fee.feeCollectorAccountId)
|
|
38
|
+
);
|
|
39
|
+
if (fee.denominatingTokenId) {
|
|
40
|
+
cf.setDenominatingTokenId(TokenId.fromString(fee.denominatingTokenId));
|
|
41
|
+
}
|
|
42
|
+
return cf;
|
|
94
43
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
44
|
+
tx.setCustomFees(fees);
|
|
45
|
+
}
|
|
46
|
+
if (params.feeExemptKeys && params.feeExemptKeys.length > 0) {
|
|
47
|
+
throw new Error("feeExemptKeys not supported by installed @hashgraph/sdk");
|
|
48
|
+
}
|
|
49
|
+
return tx;
|
|
50
|
+
}
|
|
51
|
+
function buildHcs16CreateAccountTx(params) {
|
|
52
|
+
const tx = new AccountCreateTransaction().setKey(params.keyList);
|
|
53
|
+
const initial = typeof params.initialBalanceHbar === "number" ? params.initialBalanceHbar : 1;
|
|
54
|
+
tx.setInitialBalance(new Hbar(initial));
|
|
55
|
+
const maxAssoc = typeof params.maxAutomaticTokenAssociations === "number" ? params.maxAutomaticTokenAssociations : -1;
|
|
56
|
+
tx.setMaxAutomaticTokenAssociations(maxAssoc);
|
|
57
|
+
return tx;
|
|
58
|
+
}
|
|
59
|
+
function buildHcs16ScheduleAccountKeyUpdateTx(params) {
|
|
60
|
+
const inner = new AccountUpdateTransaction().setAccountId(AccountId.fromString(params.floraAccountId)).setKey(params.newKeyList);
|
|
61
|
+
if (params.memo) {
|
|
62
|
+
inner.setTransactionMemo(params.memo);
|
|
63
|
+
}
|
|
64
|
+
return new ScheduleCreateTransaction().setScheduledTransaction(inner);
|
|
65
|
+
}
|
|
66
|
+
function buildHcs16ScheduleTopicKeyUpdateTx(params) {
|
|
67
|
+
const inner = new TopicUpdateTransaction().setTopicId(params.topicId);
|
|
68
|
+
if (params.adminKey) {
|
|
69
|
+
inner.setAdminKey(params.adminKey);
|
|
70
|
+
}
|
|
71
|
+
if (params.submitKey) {
|
|
72
|
+
inner.setSubmitKey(params.submitKey);
|
|
98
73
|
}
|
|
74
|
+
if (params.memo) {
|
|
75
|
+
inner.setTransactionMemo(params.memo);
|
|
76
|
+
}
|
|
77
|
+
return new ScheduleCreateTransaction().setScheduledTransaction(inner);
|
|
78
|
+
}
|
|
79
|
+
function buildHcs16MessageTx(params) {
|
|
80
|
+
const payload = {
|
|
81
|
+
p: "hcs-16",
|
|
82
|
+
op: params.op,
|
|
83
|
+
operator_id: params.operatorId,
|
|
84
|
+
...params.body || {}
|
|
85
|
+
};
|
|
86
|
+
return buildMessageTx({
|
|
87
|
+
topicId: params.topicId,
|
|
88
|
+
message: JSON.stringify(payload)
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function buildHcs16FloraCreatedTx(params) {
|
|
92
|
+
return buildHcs16MessageTx({
|
|
93
|
+
topicId: params.topicId,
|
|
94
|
+
operatorId: params.operatorId,
|
|
95
|
+
op: FloraOperation.FLORA_CREATED,
|
|
96
|
+
body: {
|
|
97
|
+
flora_account_id: params.floraAccountId,
|
|
98
|
+
topics: params.topics
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function buildHcs16TransactionTx(params) {
|
|
103
|
+
return buildHcs16MessageTx({
|
|
104
|
+
topicId: params.topicId,
|
|
105
|
+
operatorId: params.operatorId,
|
|
106
|
+
op: FloraOperation.TRANSACTION,
|
|
107
|
+
body: {
|
|
108
|
+
schedule_id: params.scheduleId,
|
|
109
|
+
data: params.data,
|
|
110
|
+
m: params.data
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function buildHcs16StateUpdateTx(params) {
|
|
115
|
+
return buildHcs16MessageTx({
|
|
116
|
+
topicId: params.topicId,
|
|
117
|
+
operatorId: params.operatorId,
|
|
118
|
+
op: FloraOperation.STATE_UPDATE,
|
|
119
|
+
body: {
|
|
120
|
+
hash: params.hash,
|
|
121
|
+
epoch: params.epoch,
|
|
122
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function buildHcs16FloraJoinRequestTx(params) {
|
|
127
|
+
return buildHcs16MessageTx({
|
|
128
|
+
topicId: params.topicId,
|
|
129
|
+
operatorId: params.operatorId,
|
|
130
|
+
op: FloraOperation.FLORA_JOIN_REQUEST,
|
|
131
|
+
body: {
|
|
132
|
+
candidate_account_id: params.candidateAccountId
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function buildHcs16FloraJoinVoteTx(params) {
|
|
137
|
+
return buildHcs16MessageTx({
|
|
138
|
+
topicId: params.topicId,
|
|
139
|
+
operatorId: params.operatorId,
|
|
140
|
+
op: FloraOperation.FLORA_JOIN_VOTE,
|
|
141
|
+
body: {
|
|
142
|
+
candidate_account_id: params.candidateAccountId,
|
|
143
|
+
approve: params.approve
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function buildHcs16FloraJoinAcceptedTx(params) {
|
|
148
|
+
return buildHcs16MessageTx({
|
|
149
|
+
topicId: params.topicId,
|
|
150
|
+
operatorId: params.operatorId,
|
|
151
|
+
op: FloraOperation.FLORA_JOIN_ACCEPTED,
|
|
152
|
+
body: {
|
|
153
|
+
members: params.members,
|
|
154
|
+
epoch: params.epoch
|
|
155
|
+
}
|
|
156
|
+
});
|
|
99
157
|
}
|
|
100
158
|
export {
|
|
101
|
-
|
|
159
|
+
buildHcs16CreateAccountTx,
|
|
160
|
+
buildHcs16CreateFloraTopicTx,
|
|
161
|
+
buildHcs16CreateTransactionTopicTx,
|
|
162
|
+
buildHcs16FloraCreatedTx,
|
|
163
|
+
buildHcs16FloraJoinAcceptedTx,
|
|
164
|
+
buildHcs16FloraJoinRequestTx,
|
|
165
|
+
buildHcs16FloraJoinVoteTx,
|
|
166
|
+
buildHcs16MessageTx,
|
|
167
|
+
buildHcs16ScheduleAccountKeyUpdateTx,
|
|
168
|
+
buildHcs16ScheduleTopicKeyUpdateTx,
|
|
169
|
+
buildHcs16StateUpdateTx,
|
|
170
|
+
buildHcs16TransactionTx
|
|
102
171
|
};
|
|
103
172
|
//# sourceMappingURL=standards-sdk.es91.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standards-sdk.es91.js","sources":["../../src/hcs-17/sdk.ts"],"sourcesContent":["import {\n Client,\n PublicKey,\n KeyList,\n TransactionReceipt,\n AccountId,\n} from '@hashgraph/sdk';\nimport { HCS17BaseClient } from './base-client';\nimport {\n SDKHCS17ClientConfig,\n StateHashMessage,\n TopicState,\n AccountStateInput,\n} from './types';\nimport { buildHcs17CreateTopicTx, buildHcs17MessageTx } from './tx';\nimport {\n createNodeOperatorContext,\n type NodeOperatorContext,\n} from '../common/node-operator-resolver';\n\n/**\n * Node SDK client for HCS‑17 operations.\n * Creates topics, submits messages, and can compute + publish state hashes.\n */\nexport class HCS17Client extends HCS17BaseClient {\n private client: Client;\n private operatorId: AccountId;\n private operatorCtx: NodeOperatorContext;\n\n constructor(config: SDKHCS17ClientConfig) {\n super(config);\n this.operatorId = AccountId.fromString(config.operatorId);\n this.operatorCtx = createNodeOperatorContext({\n network: this.network,\n operatorId: this.operatorId,\n operatorKey: config.operatorKey,\n keyType: config.keyType,\n mirrorNode: this.mirrorNode,\n logger: this.logger,\n client:\n config.network === 'mainnet'\n ? Client.forMainnet()\n : Client.forTestnet(),\n });\n this.client = this.operatorCtx.client;\n }\n\n public getKeyType(): 'ed25519' | 'ecdsa' {\n return this.operatorCtx.keyType;\n }\n\n /**\n * Create an HCS topic intended for HCS‑17 state messages.\n */\n async createStateTopic(options?: {\n ttl?: number;\n adminKey?: boolean | string | PublicKey | KeyList;\n submitKey?: boolean | string | PublicKey | KeyList;\n }): Promise<string> {\n const ttl = options?.ttl ?? 86400;\n const tx = buildHcs17CreateTopicTx({\n ttl,\n adminKey: options?.adminKey,\n submitKey: options?.submitKey,\n operatorPublicKey: this.client.operatorPublicKey || undefined,\n });\n const resp = await tx.execute(this.client);\n const receipt = await resp.getReceipt(this.client);\n if (!receipt.topicId) {\n throw new Error('Failed to create topic: topicId empty');\n }\n const topicId = receipt.topicId.toString();\n this.logger.info(`Created HCS-17 state topic ${topicId}`);\n return topicId;\n }\n\n /**\n * Submit a pre‑built HCS‑17 state hash message to a topic.\n */\n async submitMessage(\n topicId: string,\n message: StateHashMessage,\n ): Promise<TransactionReceipt> {\n const { valid, errors } = this.validateMessage(message);\n if (!valid) {\n throw new Error(`Invalid HCS-17 message: ${errors.join(', ')}`);\n }\n const tx = buildHcs17MessageTx({\n topicId,\n stateHash: message.state_hash,\n accountId: message.account_id,\n topics: message.topics,\n memo: message.m,\n });\n const resp = await tx.execute(this.client);\n const receipt = await resp.getReceipt(this.client);\n return receipt;\n }\n\n /**\n * Compute current account state hash from topic running hashes and publish it.\n */\n async computeAndPublish(params: {\n accountId: string;\n accountPublicKey: string | PublicKey;\n topics: string[];\n publishTopicId: string;\n memo?: string;\n }): Promise<{ stateHash: string; receipt: TransactionReceipt }> {\n const topicStates: TopicState[] = [];\n for (const t of params.topics) {\n const msgs = await this.mirrorNode.getTopicMessages(t, {\n limit: 1,\n order: 'desc',\n });\n const latest = msgs[0];\n const running = latest?.running_hash || '';\n topicStates.push({ topicId: t, latestRunningHash: running });\n }\n\n const input: AccountStateInput = {\n accountId: params.accountId,\n publicKey: params.accountPublicKey,\n topics: topicStates,\n };\n const result = this.calculateAccountStateHash(input);\n const message: StateHashMessage = this.createStateHashMessage(\n result.stateHash,\n params.accountId,\n params.topics,\n params.memo,\n );\n const tx = buildHcs17MessageTx({\n topicId: params.publishTopicId,\n stateHash: result.stateHash,\n accountId: params.accountId,\n topics: params.topics,\n memo: params.memo,\n });\n const resp = await tx.execute(this.client);\n const receipt = await resp.getReceipt(this.client);\n return { stateHash: result.stateHash, receipt };\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standards-sdk.es91.js","sources":["../../src/hcs-16/tx.ts"],"sourcesContent":["import {\n TopicCreateTransaction,\n TopicMessageSubmitTransaction,\n TopicUpdateTransaction,\n AccountCreateTransaction,\n AccountUpdateTransaction,\n ScheduleCreateTransaction,\n Hbar,\n PublicKey,\n KeyList,\n AccountId,\n CustomFixedFee,\n TokenId,\n} from '@hashgraph/sdk';\nimport {\n buildTopicCreateTx,\n buildMessageTx,\n type MaybeKey,\n} from '../common/tx/tx-utils';\nimport { FloraOperation, FloraTopicType, type FloraMessage } from './types';\n\nfunction encodeHcs16FloraMemo(params: {\n floraAccountId: string;\n topicType: FloraTopicType;\n}): string {\n return `hcs-16:${params.floraAccountId}:${params.topicType}`;\n}\n\n/**\n * Build a TopicCreateTransaction for HCS‑16 Flora topics (communication/transaction/state).\n */\nexport function buildHcs16CreateFloraTopicTx(params: {\n floraAccountId: string;\n topicType: FloraTopicType;\n adminKey?: MaybeKey;\n submitKey?: MaybeKey;\n operatorPublicKey?: PublicKey;\n autoRenewAccountId?: string;\n}): TopicCreateTransaction {\n const memo = encodeHcs16FloraMemo({\n floraAccountId: params.floraAccountId,\n topicType: params.topicType,\n });\n const tx = buildTopicCreateTx({\n memo,\n adminKey: params.adminKey,\n submitKey: params.submitKey,\n operatorPublicKey: params.operatorPublicKey,\n });\n if (params.autoRenewAccountId) {\n tx.setAutoRenewAccountId(AccountId.fromString(params.autoRenewAccountId));\n }\n return tx;\n}\n\n/**\n * Build a TopicCreateTransaction for a generic HCS‑16 transaction topic with HIP‑991 fees.\n */\nexport function buildHcs16CreateTransactionTopicTx(params: {\n memo: string;\n adminKey?: KeyList | PublicKey;\n submitKey?: KeyList | PublicKey;\n feeScheduleKey?: KeyList | PublicKey;\n customFees?: Array<{\n amount: number;\n feeCollectorAccountId: string;\n denominatingTokenId?: string;\n }>;\n feeExemptKeys?: PublicKey[];\n}): TopicCreateTransaction {\n const tx = new TopicCreateTransaction().setTopicMemo(params.memo);\n if (params.adminKey) {\n tx.setAdminKey(params.adminKey);\n }\n if (params.submitKey) {\n tx.setSubmitKey(params.submitKey);\n }\n if (params.feeScheduleKey) {\n tx.setFeeScheduleKey(params.feeScheduleKey);\n }\n if (params.customFees && params.customFees.length > 0) {\n const fees = params.customFees.map(fee => {\n const cf = new CustomFixedFee()\n .setAmount(fee.amount)\n .setFeeCollectorAccountId(\n AccountId.fromString(fee.feeCollectorAccountId),\n );\n if (fee.denominatingTokenId) {\n cf.setDenominatingTokenId(TokenId.fromString(fee.denominatingTokenId));\n }\n return cf;\n });\n tx.setCustomFees(fees);\n }\n if (params.feeExemptKeys && params.feeExemptKeys.length > 0) {\n throw new Error('feeExemptKeys not supported by installed @hashgraph/sdk');\n }\n return tx;\n}\n\n/**\n * Build an AccountCreateTransaction for a Flora account given a KeyList and optional params.\n */\nexport function buildHcs16CreateAccountTx(params: {\n keyList: KeyList;\n initialBalanceHbar?: number;\n maxAutomaticTokenAssociations?: number;\n}): AccountCreateTransaction {\n const tx = new AccountCreateTransaction().setKey(params.keyList);\n const initial =\n typeof params.initialBalanceHbar === 'number'\n ? params.initialBalanceHbar\n : 1;\n tx.setInitialBalance(new Hbar(initial));\n const maxAssoc =\n typeof params.maxAutomaticTokenAssociations === 'number'\n ? params.maxAutomaticTokenAssociations\n : -1;\n tx.setMaxAutomaticTokenAssociations(maxAssoc);\n return tx;\n}\n\n/**\n * Build a ScheduleCreateTransaction that wraps an AccountUpdateTransaction to rotate the Flora account KeyList.\n * Members will sign this scheduled transaction until threshold is reached and it executes.\n */\nexport function buildHcs16ScheduleAccountKeyUpdateTx(params: {\n floraAccountId: string;\n newKeyList: KeyList;\n memo?: string;\n}): ScheduleCreateTransaction {\n const inner = new AccountUpdateTransaction()\n .setAccountId(AccountId.fromString(params.floraAccountId))\n .setKey(params.newKeyList);\n if (params.memo) {\n inner.setTransactionMemo(params.memo);\n }\n return new ScheduleCreateTransaction().setScheduledTransaction(inner);\n}\n\n/**\n * Build a ScheduleCreateTransaction that wraps a TopicUpdateTransaction to rotate topic admin/submit keys.\n * Repeat for CTopic, TTopic, and STopic as needed for membership changes.\n */\nexport function buildHcs16ScheduleTopicKeyUpdateTx(params: {\n topicId: string;\n adminKey?: KeyList | PublicKey;\n submitKey?: KeyList | PublicKey;\n memo?: string;\n}): ScheduleCreateTransaction {\n const inner = new TopicUpdateTransaction().setTopicId(params.topicId);\n if (params.adminKey) {\n inner.setAdminKey(params.adminKey);\n }\n if (params.submitKey) {\n inner.setSubmitKey(params.submitKey);\n }\n if (params.memo) {\n inner.setTransactionMemo(params.memo);\n }\n return new ScheduleCreateTransaction().setScheduledTransaction(inner);\n}\n\n/**\n * Build a TopicMessageSubmitTransaction for generic HCS‑16 messages.\n * Body fields are merged into the envelope `{ p: 'hcs-16', op, operator_id }`.\n */\nexport function buildHcs16MessageTx(params: {\n topicId: string;\n operatorId: string;\n op: FloraOperation;\n body?: Record<string, unknown>;\n}): TopicMessageSubmitTransaction {\n const payload: FloraMessage = {\n p: 'hcs-16',\n op: params.op,\n operator_id: params.operatorId,\n ...(params.body || {}),\n } as FloraMessage;\n\n return buildMessageTx({\n topicId: params.topicId,\n message: JSON.stringify(payload),\n });\n}\n\n/**\n * Build HCS‑16 flora_created message.\n */\nexport function buildHcs16FloraCreatedTx(params: {\n topicId: string;\n operatorId: string;\n floraAccountId: string;\n topics: { communication: string; transaction: string; state: string };\n}): TopicMessageSubmitTransaction {\n return buildHcs16MessageTx({\n topicId: params.topicId,\n operatorId: params.operatorId,\n op: FloraOperation.FLORA_CREATED,\n body: {\n flora_account_id: params.floraAccountId,\n topics: params.topics,\n },\n });\n}\n\n/**\n * Build HCS‑16 transaction message.\n */\nexport function buildHcs16TransactionTx(params: {\n topicId: string;\n operatorId: string;\n scheduleId: string;\n data?: string;\n}): TopicMessageSubmitTransaction {\n return buildHcs16MessageTx({\n topicId: params.topicId,\n operatorId: params.operatorId,\n op: FloraOperation.TRANSACTION,\n body: {\n schedule_id: params.scheduleId,\n data: params.data,\n m: params.data,\n },\n });\n}\n\n/**\n * Build HCS‑16 state_update message.\n */\nexport function buildHcs16StateUpdateTx(params: {\n topicId: string;\n operatorId: string;\n hash: string;\n epoch?: number;\n}): TopicMessageSubmitTransaction {\n return buildHcs16MessageTx({\n topicId: params.topicId,\n operatorId: params.operatorId,\n op: FloraOperation.STATE_UPDATE,\n body: {\n hash: params.hash,\n epoch: params.epoch,\n timestamp: new Date().toISOString(),\n },\n });\n}\n\n/**\n * Build HCS‑16 flora_join_request message.\n */\nexport function buildHcs16FloraJoinRequestTx(params: {\n topicId: string;\n operatorId: string;\n candidateAccountId: string;\n}): TopicMessageSubmitTransaction {\n return buildHcs16MessageTx({\n topicId: params.topicId,\n operatorId: params.operatorId,\n op: FloraOperation.FLORA_JOIN_REQUEST,\n body: {\n candidate_account_id: params.candidateAccountId,\n },\n });\n}\n\n/**\n * Build HCS‑16 flora_join_vote message.\n */\nexport function buildHcs16FloraJoinVoteTx(params: {\n topicId: string;\n operatorId: string;\n candidateAccountId: string;\n approve: boolean;\n}): TopicMessageSubmitTransaction {\n return buildHcs16MessageTx({\n topicId: params.topicId,\n operatorId: params.operatorId,\n op: FloraOperation.FLORA_JOIN_VOTE,\n body: {\n candidate_account_id: params.candidateAccountId,\n approve: params.approve,\n },\n });\n}\n\n/**\n * Build HCS‑16 flora_join_accepted message.\n */\nexport function buildHcs16FloraJoinAcceptedTx(params: {\n topicId: string;\n operatorId: string;\n members: string[];\n epoch?: number;\n}): TopicMessageSubmitTransaction {\n return buildHcs16MessageTx({\n topicId: params.topicId,\n operatorId: params.operatorId,\n op: FloraOperation.FLORA_JOIN_ACCEPTED,\n body: {\n members: params.members,\n epoch: params.epoch,\n },\n });\n}\n"],"names":[],"mappings":"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"}
|