@hashgraphonline/standards-sdk 0.0.69 → 0.0.72

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 (236) hide show
  1. package/README.md +13 -0
  2. package/dist/es/fees/fee-config-builder.d.ts +93 -45
  3. package/dist/es/fees/fee-config-builder.d.ts.map +1 -1
  4. package/dist/es/fees/types.d.ts +14 -12
  5. package/dist/es/fees/types.d.ts.map +1 -1
  6. package/dist/es/hcs-10/base-client.d.ts +53 -1
  7. package/dist/es/hcs-10/base-client.d.ts.map +1 -1
  8. package/dist/es/hcs-10/browser.d.ts +0 -1
  9. package/dist/es/hcs-10/browser.d.ts.map +1 -1
  10. package/dist/es/hcs-10/sdk.d.ts +9 -2
  11. package/dist/es/hcs-10/sdk.d.ts.map +1 -1
  12. package/dist/es/services/mirror-node.d.ts +74 -1
  13. package/dist/es/services/mirror-node.d.ts.map +1 -1
  14. package/dist/es/services/types.d.ts +29 -0
  15. package/dist/es/services/types.d.ts.map +1 -1
  16. package/dist/es/standards-sdk.es.js +2 -0
  17. package/dist/es/standards-sdk.es.js.map +1 -1
  18. package/dist/es/standards-sdk.es100.js +13 -4
  19. package/dist/es/standards-sdk.es100.js.map +1 -1
  20. package/dist/es/standards-sdk.es101.js +13 -4
  21. package/dist/es/standards-sdk.es101.js.map +1 -1
  22. package/dist/es/standards-sdk.es102.js +1 -1
  23. package/dist/es/standards-sdk.es104.js +3 -3
  24. package/dist/es/standards-sdk.es105.js +8 -8
  25. package/dist/es/standards-sdk.es106.js +3 -3
  26. package/dist/es/standards-sdk.es108.js +2282 -3
  27. package/dist/es/standards-sdk.es108.js.map +1 -1
  28. package/dist/es/standards-sdk.es109.js +34 -2
  29. package/dist/es/standards-sdk.es109.js.map +1 -1
  30. package/dist/es/standards-sdk.es110.js +33 -2
  31. package/dist/es/standards-sdk.es110.js.map +1 -1
  32. package/dist/es/standards-sdk.es111.js +9 -34
  33. package/dist/es/standards-sdk.es111.js.map +1 -1
  34. package/dist/es/standards-sdk.es112.js +32 -31
  35. package/dist/es/standards-sdk.es112.js.map +1 -1
  36. package/dist/es/standards-sdk.es113.js +3 -9
  37. package/dist/es/standards-sdk.es113.js.map +1 -1
  38. package/dist/es/standards-sdk.es114.js +2 -34
  39. package/dist/es/standards-sdk.es114.js.map +1 -1
  40. package/dist/es/standards-sdk.es115.js +5 -0
  41. package/dist/es/standards-sdk.es115.js.map +1 -0
  42. package/dist/es/standards-sdk.es12.js +1 -1
  43. package/dist/es/standards-sdk.es14.js +1 -1
  44. package/dist/es/standards-sdk.es17.js +1 -1
  45. package/dist/es/standards-sdk.es18.js +93 -5
  46. package/dist/es/standards-sdk.es18.js.map +1 -1
  47. package/dist/es/standards-sdk.es19.js +127 -67
  48. package/dist/es/standards-sdk.es19.js.map +1 -1
  49. package/dist/es/standards-sdk.es20.js +7 -1041
  50. package/dist/es/standards-sdk.es20.js.map +1 -1
  51. package/dist/es/standards-sdk.es22.js +6627 -36
  52. package/dist/es/standards-sdk.es22.js.map +1 -1
  53. package/dist/es/standards-sdk.es23.js +1039 -46
  54. package/dist/es/standards-sdk.es23.js.map +1 -1
  55. package/dist/es/standards-sdk.es24.js +36 -6627
  56. package/dist/es/standards-sdk.es24.js.map +1 -1
  57. package/dist/es/standards-sdk.es25.js +48 -3
  58. package/dist/es/standards-sdk.es25.js.map +1 -1
  59. package/dist/es/standards-sdk.es26.js +3 -2
  60. package/dist/es/standards-sdk.es26.js.map +1 -1
  61. package/dist/es/standards-sdk.es27.js +2 -5
  62. package/dist/es/standards-sdk.es27.js.map +1 -1
  63. package/dist/es/standards-sdk.es29.js +5 -419
  64. package/dist/es/standards-sdk.es29.js.map +1 -1
  65. package/dist/es/standards-sdk.es30.js +419 -2
  66. package/dist/es/standards-sdk.es30.js.map +1 -1
  67. package/dist/es/standards-sdk.es31.js +2 -120
  68. package/dist/es/standards-sdk.es31.js.map +1 -1
  69. package/dist/es/standards-sdk.es32.js +120 -3
  70. package/dist/es/standards-sdk.es32.js.map +1 -1
  71. package/dist/es/standards-sdk.es33.js +3 -164
  72. package/dist/es/standards-sdk.es33.js.map +1 -1
  73. package/dist/es/standards-sdk.es34.js +164 -2
  74. package/dist/es/standards-sdk.es34.js.map +1 -1
  75. package/dist/es/standards-sdk.es35.js +3 -194
  76. package/dist/es/standards-sdk.es35.js.map +1 -1
  77. package/dist/es/standards-sdk.es36.js +2 -438
  78. package/dist/es/standards-sdk.es36.js.map +1 -1
  79. package/dist/es/standards-sdk.es37.js +358 -19
  80. package/dist/es/standards-sdk.es37.js.map +1 -1
  81. package/dist/es/standards-sdk.es38.js +5 -138
  82. package/dist/es/standards-sdk.es38.js.map +1 -1
  83. package/dist/es/standards-sdk.es39.js +174 -13
  84. package/dist/es/standards-sdk.es39.js.map +1 -1
  85. package/dist/es/standards-sdk.es4.js +1 -1
  86. package/dist/es/standards-sdk.es40.js +75 -23
  87. package/dist/es/standards-sdk.es40.js.map +1 -1
  88. package/dist/es/standards-sdk.es41.js +111 -26
  89. package/dist/es/standards-sdk.es41.js.map +1 -1
  90. package/dist/es/standards-sdk.es42.js +47 -16
  91. package/dist/es/standards-sdk.es42.js.map +1 -1
  92. package/dist/es/standards-sdk.es43.js +9 -43
  93. package/dist/es/standards-sdk.es43.js.map +1 -1
  94. package/dist/es/standards-sdk.es44.js +92 -13
  95. package/dist/es/standards-sdk.es44.js.map +1 -1
  96. package/dist/es/standards-sdk.es45.js +3 -60
  97. package/dist/es/standards-sdk.es45.js.map +1 -1
  98. package/dist/es/standards-sdk.es46.js +2 -1289
  99. package/dist/es/standards-sdk.es46.js.map +1 -1
  100. package/dist/es/standards-sdk.es47.js +98 -133
  101. package/dist/es/standards-sdk.es47.js.map +1 -1
  102. package/dist/es/standards-sdk.es48.js +69 -86
  103. package/dist/es/standards-sdk.es48.js.map +1 -1
  104. package/dist/es/standards-sdk.es49.js +5 -83
  105. package/dist/es/standards-sdk.es49.js.map +1 -1
  106. package/dist/es/standards-sdk.es5.js +128 -2
  107. package/dist/es/standards-sdk.es5.js.map +1 -1
  108. package/dist/es/standards-sdk.es50.js +4 -31
  109. package/dist/es/standards-sdk.es50.js.map +1 -1
  110. package/dist/es/standards-sdk.es51.js +220 -5
  111. package/dist/es/standards-sdk.es51.js.map +1 -1
  112. package/dist/es/standards-sdk.es52.js +53 -154
  113. package/dist/es/standards-sdk.es52.js.map +1 -1
  114. package/dist/es/standards-sdk.es53.js +68 -22
  115. package/dist/es/standards-sdk.es53.js.map +1 -1
  116. package/dist/es/standards-sdk.es54.js +19 -789
  117. package/dist/es/standards-sdk.es54.js.map +1 -1
  118. package/dist/es/standards-sdk.es55.js +3 -3
  119. package/dist/es/standards-sdk.es56.js +78 -130
  120. package/dist/es/standards-sdk.es56.js.map +1 -1
  121. package/dist/es/standards-sdk.es57.js +194 -3
  122. package/dist/es/standards-sdk.es57.js.map +1 -1
  123. package/dist/es/standards-sdk.es58.js +430 -13
  124. package/dist/es/standards-sdk.es58.js.map +1 -1
  125. package/dist/es/standards-sdk.es59.js +23 -25
  126. package/dist/es/standards-sdk.es59.js.map +1 -1
  127. package/dist/es/standards-sdk.es60.js +136 -23
  128. package/dist/es/standards-sdk.es60.js.map +1 -1
  129. package/dist/es/standards-sdk.es61.js +16 -36
  130. package/dist/es/standards-sdk.es61.js.map +1 -1
  131. package/dist/es/standards-sdk.es62.js +21 -356
  132. package/dist/es/standards-sdk.es62.js.map +1 -1
  133. package/dist/es/standards-sdk.es63.js +28 -5
  134. package/dist/es/standards-sdk.es63.js.map +1 -1
  135. package/dist/es/standards-sdk.es64.js +15 -173
  136. package/dist/es/standards-sdk.es64.js.map +1 -1
  137. package/dist/es/standards-sdk.es65.js +37 -74
  138. package/dist/es/standards-sdk.es65.js.map +1 -1
  139. package/dist/es/standards-sdk.es66.js +16 -112
  140. package/dist/es/standards-sdk.es66.js.map +1 -1
  141. package/dist/es/standards-sdk.es67.js +56 -47
  142. package/dist/es/standards-sdk.es67.js.map +1 -1
  143. package/dist/es/standards-sdk.es68.js +1288 -9
  144. package/dist/es/standards-sdk.es68.js.map +1 -1
  145. package/dist/es/standards-sdk.es69.js +134 -83
  146. package/dist/es/standards-sdk.es69.js.map +1 -1
  147. package/dist/es/standards-sdk.es7.js +95 -81
  148. package/dist/es/standards-sdk.es7.js.map +1 -1
  149. package/dist/es/standards-sdk.es70.js +83 -3
  150. package/dist/es/standards-sdk.es70.js.map +1 -1
  151. package/dist/es/standards-sdk.es71.js +32 -2
  152. package/dist/es/standards-sdk.es71.js.map +1 -1
  153. package/dist/es/standards-sdk.es72.js +5 -112
  154. package/dist/es/standards-sdk.es72.js.map +1 -1
  155. package/dist/es/standards-sdk.es73.js +154 -69
  156. package/dist/es/standards-sdk.es73.js.map +1 -1
  157. package/dist/es/standards-sdk.es74.js +792 -5
  158. package/dist/es/standards-sdk.es74.js.map +1 -1
  159. package/dist/es/standards-sdk.es75.js +142 -4
  160. package/dist/es/standards-sdk.es75.js.map +1 -1
  161. package/dist/es/standards-sdk.es76.js +26 -215
  162. package/dist/es/standards-sdk.es76.js.map +1 -1
  163. package/dist/es/standards-sdk.es77.js +60 -55
  164. package/dist/es/standards-sdk.es77.js.map +1 -1
  165. package/dist/es/standards-sdk.es78.js +50 -69
  166. package/dist/es/standards-sdk.es78.js.map +1 -1
  167. package/dist/es/standards-sdk.es79.js +9 -100
  168. package/dist/es/standards-sdk.es79.js.map +1 -1
  169. package/dist/es/standards-sdk.es8.js +2 -47
  170. package/dist/es/standards-sdk.es8.js.map +1 -1
  171. package/dist/es/standards-sdk.es80.js +65 -2
  172. package/dist/es/standards-sdk.es80.js.map +1 -1
  173. package/dist/es/standards-sdk.es81.js +6 -16
  174. package/dist/es/standards-sdk.es81.js.map +1 -1
  175. package/dist/es/standards-sdk.es82.js +13 -407
  176. package/dist/es/standards-sdk.es82.js.map +1 -1
  177. package/dist/es/standards-sdk.es83.js +7 -32
  178. package/dist/es/standards-sdk.es83.js.map +1 -1
  179. package/dist/es/standards-sdk.es84.js +43 -61
  180. package/dist/es/standards-sdk.es84.js.map +1 -1
  181. package/dist/es/standards-sdk.es85.js +2 -50
  182. package/dist/es/standards-sdk.es85.js.map +1 -1
  183. package/dist/es/standards-sdk.es86.js +136 -10
  184. package/dist/es/standards-sdk.es86.js.map +1 -1
  185. package/dist/es/standards-sdk.es87.js +164 -57
  186. package/dist/es/standards-sdk.es87.js.map +1 -1
  187. package/dist/es/standards-sdk.es88.js +27 -6
  188. package/dist/es/standards-sdk.es88.js.map +1 -1
  189. package/dist/es/standards-sdk.es89.js +25 -14
  190. package/dist/es/standards-sdk.es89.js.map +1 -1
  191. package/dist/es/standards-sdk.es9.js +1 -1
  192. package/dist/es/standards-sdk.es90.js +38 -7
  193. package/dist/es/standards-sdk.es90.js.map +1 -1
  194. package/dist/es/standards-sdk.es91.js +21 -45
  195. package/dist/es/standards-sdk.es91.js.map +1 -1
  196. package/dist/es/standards-sdk.es92.js +101 -2
  197. package/dist/es/standards-sdk.es92.js.map +1 -1
  198. package/dist/es/standards-sdk.es93.js +2 -136
  199. package/dist/es/standards-sdk.es93.js.map +1 -1
  200. package/dist/es/standards-sdk.es94.js +16 -172
  201. package/dist/es/standards-sdk.es94.js.map +1 -1
  202. package/dist/es/standards-sdk.es95.js +409 -2282
  203. package/dist/es/standards-sdk.es95.js.map +1 -1
  204. package/dist/es/standards-sdk.es96.js +31 -12
  205. package/dist/es/standards-sdk.es96.js.map +1 -1
  206. package/dist/es/standards-sdk.es97.js +15 -13
  207. package/dist/es/standards-sdk.es97.js.map +1 -1
  208. package/dist/es/standards-sdk.es98.js +3 -31
  209. package/dist/es/standards-sdk.es98.js.map +1 -1
  210. package/dist/es/standards-sdk.es99.js +3 -14
  211. package/dist/es/standards-sdk.es99.js.map +1 -1
  212. package/dist/es/utils/index.d.ts +1 -0
  213. package/dist/es/utils/index.d.ts.map +1 -1
  214. package/dist/es/utils/types.d.ts +3 -0
  215. package/dist/es/utils/types.d.ts.map +1 -1
  216. package/dist/umd/fees/fee-config-builder.d.ts +93 -45
  217. package/dist/umd/fees/fee-config-builder.d.ts.map +1 -1
  218. package/dist/umd/fees/types.d.ts +14 -12
  219. package/dist/umd/fees/types.d.ts.map +1 -1
  220. package/dist/umd/hcs-10/base-client.d.ts +53 -1
  221. package/dist/umd/hcs-10/base-client.d.ts.map +1 -1
  222. package/dist/umd/hcs-10/browser.d.ts +0 -1
  223. package/dist/umd/hcs-10/browser.d.ts.map +1 -1
  224. package/dist/umd/hcs-10/sdk.d.ts +9 -2
  225. package/dist/umd/hcs-10/sdk.d.ts.map +1 -1
  226. package/dist/umd/services/mirror-node.d.ts +74 -1
  227. package/dist/umd/services/mirror-node.d.ts.map +1 -1
  228. package/dist/umd/services/types.d.ts +29 -0
  229. package/dist/umd/services/types.d.ts.map +1 -1
  230. package/dist/umd/standards-sdk.umd.js +1 -1
  231. package/dist/umd/standards-sdk.umd.js.map +1 -1
  232. package/dist/umd/utils/index.d.ts +1 -0
  233. package/dist/umd/utils/index.d.ts.map +1 -1
  234. package/dist/umd/utils/types.d.ts +3 -0
  235. package/dist/umd/utils/types.d.ts.map +1 -1
  236. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"standards-sdk.es18.js","sources":["../../src/services/mirror-node.ts"],"sourcesContent":["import { PublicKey, Timestamp } from '@hashgraph/sdk';\nimport axios from 'axios';\nimport { Logger } from '../utils/logger';\nimport { HCSMessage } from '../hcs-10/base-client';\nimport { proto } from '@hashgraph/proto';\nimport {\n AccountResponse,\n CustomFees,\n HBARPrice,\n TopicMessagesResponse,\n TopicResponse,\n} from './types';\nimport { NetworkType } from '../utils/types';\nexport class HederaMirrorNode {\n private network: NetworkType;\n private baseUrl: string;\n private logger: Logger;\n private isServerEnvironment: boolean;\n\n constructor(network: NetworkType, logger: Logger) {\n this.network = network;\n this.baseUrl = this.getMirrorNodeUrl();\n this.logger = logger;\n this.isServerEnvironment = typeof window === 'undefined';\n }\n\n private getMirrorNodeUrl(): string {\n return this.network === 'mainnet'\n ? 'https://mainnet-public.mirrornode.hedera.com'\n : 'https://testnet.mirrornode.hedera.com';\n }\n\n getBaseUrl(): string {\n return this.baseUrl;\n }\n\n async getPublicKey(accountId: string): Promise<PublicKey> {\n this.logger.info(`Getting public key for account ${accountId}`);\n\n const accountInfo = await this.requestAccount(accountId);\n\n try {\n if (!accountInfo || !accountInfo.key) {\n throw new Error(\n `Failed to retrieve public key for account ID: ${accountId}`\n );\n }\n\n return PublicKey.fromString(accountInfo.key.key);\n } catch (error: any) {\n throw new Error(\n `Error fetching public key from Mirror Node: ${error.message}`\n );\n }\n }\n\n async getAccountMemo(accountId: string): Promise<string | null> {\n const maxRetries = 3;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n const accountInfoUrl = `${this.baseUrl}/api/v1/accounts/${accountId}`;\n\n const response = await axios.get(accountInfoUrl);\n const accountInfo = response.data;\n\n if (accountInfo && accountInfo.memo) {\n return accountInfo.memo;\n }\n\n this.logger.error(`No memo found for account ${accountId}`);\n\n if (attempt < maxRetries - 1) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n } catch (error: any) {\n this.logger.error(\n `Error getting account memo (attempt ${attempt + 1}): ${\n error.message\n }`\n );\n\n if (attempt < maxRetries - 1) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n }\n\n return null;\n }\n\n async getTopicInfo(topicId: string): Promise<TopicResponse> {\n try {\n const topicInfoUrl = `${this.baseUrl}/api/v1/topics/${topicId}`;\n const response = await axios.get(topicInfoUrl);\n return response.data;\n } catch (error: any) {\n this.logger.error(`Error retrieving topic information: ${error.message}`);\n throw new Error(`Failed to retrieve topic information: ${error.message}`);\n }\n }\n\n async getTopicFees(topicId: string): Promise<CustomFees | null> {\n try {\n const topicInfo = await this.getTopicInfo(topicId);\n return topicInfo.custom_fees;\n } catch (error: any) {\n this.logger.error(`Error retrieving topic fees: ${error.message}`);\n return null;\n }\n }\n\n async getHBARPrice(date: Date): Promise<number | null> {\n try {\n const timestamp = Timestamp.fromDate(date).toString();\n\n const request = await fetch(\n `https://mainnet-public.mirrornode.hedera.com/api/v1/network/exchangerate?timestamp=${timestamp}`\n );\n const response = (await request.json()) as HBARPrice;\n\n const usdPrice =\n Number(response?.current_rate?.cent_equivalent) /\n Number(response?.current_rate?.hbar_equivalent) /\n 100;\n\n return usdPrice;\n } catch (e) {\n return null;\n }\n }\n\n async getTopicMessages(topicId: string): Promise<HCSMessage[]> {\n this.logger.trace(`Querying messages for topic ${topicId}`);\n\n let nextUrl = `${this.baseUrl}/api/v1/topics/${topicId}/messages`;\n const messages: HCSMessage[] = [];\n\n while (nextUrl) {\n try {\n const response = await axios.get<TopicMessagesResponse>(nextUrl);\n const data = response.data;\n\n if (data.messages && data.messages.length > 0) {\n for (const message of data.messages) {\n try {\n if (!message.message) {\n continue;\n }\n\n let messageContent: string;\n try {\n if (this.isServerEnvironment) {\n messageContent = Buffer.from(\n message.message,\n 'base64'\n ).toString('utf-8');\n } else {\n messageContent = new TextDecoder().decode(\n Uint8Array.from(atob(message.message), (c) =>\n c.charCodeAt(0)\n )\n );\n }\n } catch (error) {\n this.logger.error(`Error decoding message: ${error}`);\n continue;\n }\n\n let messageJson;\n try {\n messageJson = JSON.parse(messageContent);\n } catch (error) {\n this.logger.error(\n `Invalid JSON message content: ${messageContent}`\n );\n return;\n }\n\n messageJson.sequence_number = message.sequence_number;\n messages.push({\n ...messageJson,\n consensus_timestamp: message.consensus_timestamp,\n sequence_number: message.sequence_number,\n created: new Date(\n Number(message.consensus_timestamp) * 1000\n ),\n });\n } catch (error: any) {\n this.logger.error(`Error processing message: ${error.message}`);\n }\n }\n }\n\n nextUrl = data.links?.next ? `${this.baseUrl}${data.links.next}` : '';\n } catch (error: any) {\n this.logger.error(`Error querying topic messages: ${error.message}`);\n throw new Error(`Failed to query topic messages: ${error.message}`);\n }\n }\n\n return messages;\n }\n\n async requestAccount(accountId: string): Promise<AccountResponse> {\n try {\n const accountInfoUrl = `${this.baseUrl}/api/v1/accounts/${accountId}`;\n const response = await axios.get(accountInfoUrl);\n if (!response.data) {\n throw new Error(\n `Failed to make request to mirror node for account: ${accountId}`\n );\n }\n return response.data;\n } catch (error: any) {\n this.logger.error(`Failed to fetch account: ${error.message}`);\n throw new Error(`Failed to fetch account: ${error.message}`);\n }\n }\n\n async checkKeyListAccess(\n keyBytes: Buffer,\n userPublicKey: PublicKey\n ): Promise<boolean> {\n try {\n const key = proto.Key.decode(keyBytes);\n return this.evaluateKeyAccess(key, userPublicKey);\n } catch (error) {\n this.logger.error(\n `Error decoding protobuf key: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n return false;\n }\n }\n\n private async evaluateKeyAccess(\n key: proto.IKey,\n userPublicKey: PublicKey\n ): Promise<boolean> {\n if (key.ed25519) {\n return this.compareEd25519Key(key.ed25519, userPublicKey);\n }\n\n if (key.keyList) {\n return this.evaluateKeyList(key.keyList, userPublicKey);\n }\n\n if (key.thresholdKey && key.thresholdKey.keys) {\n return this.evaluateKeyList(key.thresholdKey.keys, userPublicKey);\n }\n\n return false;\n }\n\n private async evaluateKeyList(\n keyList: proto.IKeyList,\n userPublicKey: PublicKey\n ): Promise<boolean> {\n const keys = keyList.keys || [];\n\n for (const listKey of keys) {\n if (!listKey) continue;\n\n if (listKey.ed25519) {\n if (this.compareEd25519Key(listKey.ed25519, userPublicKey)) {\n return true;\n }\n } else if (listKey.keyList || listKey.thresholdKey) {\n try {\n const nestedKeyBytes = proto.Key.encode({\n ...(listKey.keyList ? { keyList: listKey.keyList } : {}),\n ...(listKey.thresholdKey\n ? { thresholdKey: listKey.thresholdKey }\n : {}),\n }).finish();\n\n const hasNestedAccess = await this.checkKeyListAccess(\n Buffer.from(nestedKeyBytes),\n userPublicKey\n );\n\n if (hasNestedAccess) {\n return true;\n }\n } catch (err) {\n this.logger.debug(\n `Error in nested key: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n }\n\n return false;\n }\n\n private compareEd25519Key(\n keyData: Uint8Array,\n userPublicKey: PublicKey\n ): boolean {\n try {\n const decodedKey = PublicKey.fromBytes(Buffer.from(keyData));\n return decodedKey.toString() === userPublicKey.toString();\n } catch (err) {\n return false;\n }\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"standards-sdk.es18.js","sources":["../../src/services/mirror-node.ts"],"sourcesContent":["import { PublicKey, Timestamp } from '@hashgraph/sdk';\nimport axios from 'axios';\nimport { Logger } from '../utils/logger';\nimport { HCSMessage } from '../hcs-10/base-client';\nimport { proto } from '@hashgraph/proto';\nimport {\n AccountResponse,\n CustomFees,\n HBARPrice,\n TokenInfoResponse,\n TopicMessagesResponse,\n TopicResponse,\n} from './types';\nimport { NetworkType } from '../utils/types';\nexport class HederaMirrorNode {\n private network: NetworkType;\n private baseUrl: string;\n private logger: Logger;\n private isServerEnvironment: boolean;\n\n constructor(network: NetworkType, logger: Logger) {\n this.network = network;\n this.baseUrl = this.getMirrorNodeUrl();\n this.logger = logger;\n this.isServerEnvironment = typeof window === 'undefined';\n }\n\n private getMirrorNodeUrl(): string {\n return this.network === 'mainnet'\n ? 'https://mainnet-public.mirrornode.hedera.com'\n : 'https://testnet.mirrornode.hedera.com';\n }\n\n getBaseUrl(): string {\n return this.baseUrl;\n }\n\n /**\n * Retrieves the public key for a given account ID from the mirror node.\n * @param accountId The ID of the account to retrieve the public key for.\n * @returns A promise that resolves to the public key for the given account.\n * @throws An error if the account ID is invalid or the public key cannot be retrieved.\n */\n async getPublicKey(accountId: string): Promise<PublicKey> {\n this.logger.info(`Getting public key for account ${accountId}`);\n\n const accountInfo = await this.requestAccount(accountId);\n\n try {\n if (!accountInfo || !accountInfo.key) {\n throw new Error(\n `Failed to retrieve public key for account ID: ${accountId}`\n );\n }\n\n return PublicKey.fromString(accountInfo.key.key);\n } catch (error: any) {\n throw new Error(\n `Error fetching public key from Mirror Node: ${error.message}`\n );\n }\n }\n\n /**\n * Retrieves the memo for a given account ID from the mirror node.\n * @param accountId The ID of the account to retrieve the memo for.\n * @returns A promise that resolves to the memo for the given account.\n * @throws An error if the account ID is invalid or the memo cannot be retrieved.\n */\n async getAccountMemo(accountId: string): Promise<string | null> {\n const maxRetries = 3;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n const accountInfoUrl = `${this.baseUrl}/api/v1/accounts/${accountId}`;\n\n const response = await axios.get(accountInfoUrl);\n const accountInfo = response.data;\n\n if (accountInfo && accountInfo.memo) {\n return accountInfo.memo;\n }\n\n this.logger.error(`No memo found for account ${accountId}`);\n\n if (attempt < maxRetries - 1) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n } catch (error: any) {\n this.logger.error(\n `Error getting account memo (attempt ${attempt + 1}): ${\n error.message\n }`\n );\n\n if (attempt < maxRetries - 1) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n }\n\n return null;\n }\n\n /**\n * Retrieves topic information for a given topic ID from the mirror node.\n * @param topicId The ID of the topic to retrieve information for.\n * @returns A promise that resolves to the topic information.\n * @throws An error if the topic ID is invalid or the information cannot be retrieved.\n */\n async getTopicInfo(topicId: string): Promise<TopicResponse> {\n try {\n const topicInfoUrl = `${this.baseUrl}/api/v1/topics/${topicId}`;\n const response = await axios.get(topicInfoUrl);\n return response.data;\n } catch (error: any) {\n this.logger.error(`Error retrieving topic information: ${error.message}`);\n throw new Error(`Failed to retrieve topic information: ${error.message}`);\n }\n }\n\n /**\n * Retrieves custom fees for a given topic ID from the mirror node.\n * @param topicId The ID of the topic to retrieve custom fees for.\n * @returns A promise that resolves to the custom fees for the given topic.\n * @throws An error if the topic ID is invalid or the custom fees cannot be retrieved.\n */\n async getTopicFees(topicId: string): Promise<CustomFees | null> {\n try {\n const topicInfo = await this.getTopicInfo(topicId);\n return topicInfo.custom_fees;\n } catch (error: any) {\n this.logger.error(`Error retrieving topic fees: ${error.message}`);\n return null;\n }\n }\n\n /**\n * Retrieves the current HBAR price from the mirror node.\n * @param date The date to retrieve the HBAR price for.\n * @returns A promise that resolves to the HBAR price for the given date.\n * @throws An error if the date is invalid or the price cannot be retrieved.\n */\n async getHBARPrice(date: Date): Promise<number | null> {\n try {\n const timestamp = Timestamp.fromDate(date).toString();\n\n const request = await fetch(\n `https://mainnet-public.mirrornode.hedera.com/api/v1/network/exchangerate?timestamp=${timestamp}`\n );\n const response = (await request.json()) as HBARPrice;\n\n const usdPrice =\n Number(response?.current_rate?.cent_equivalent) /\n Number(response?.current_rate?.hbar_equivalent) /\n 100;\n\n return usdPrice;\n } catch (e) {\n return null;\n }\n }\n\n /**\n * Retrieves token information for a given token ID from the mirror node.\n * @param tokenId The ID of the token to retrieve information for.\n * @returns A promise that resolves to the token information.\n * @throws An error if the token ID is invalid or the information cannot be retrieved.\n */\n async getTokenInfo(tokenId: string): Promise<TokenInfoResponse | null> {\n this.logger.debug(`Fetching token info for ${tokenId}`);\n try {\n const tokenInfoUrl = `${this.baseUrl}/api/v1/tokens/${tokenId}`;\n const response = await axios.get<TokenInfoResponse>(tokenInfoUrl);\n if (response.data) {\n this.logger.trace(`Token info found for ${tokenId}:`, response.data);\n return response.data;\n }\n this.logger.warn(`No token info found for ${tokenId}`);\n return null;\n } catch (error: any) {\n this.logger.error(\n `Error fetching token info for ${tokenId}: ${error.message}`\n );\n\n return null;\n }\n }\n\n /**\n * Retrieves messages for a given topic ID from the mirror node.\n * @param topicId The ID of the topic to retrieve messages for.\n * @returns A promise that resolves to the messages for the given topic.\n * @throws An error if the topic ID is invalid or the messages cannot be retrieved.\n */\n async getTopicMessages(topicId: string): Promise<HCSMessage[]> {\n this.logger.trace(`Querying messages for topic ${topicId}`);\n\n let nextUrl = `${this.baseUrl}/api/v1/topics/${topicId}/messages`;\n const messages: HCSMessage[] = [];\n\n while (nextUrl) {\n try {\n const response = await axios.get<TopicMessagesResponse>(nextUrl);\n const data = response.data;\n\n if (data.messages && data.messages.length > 0) {\n for (const message of data.messages) {\n try {\n if (!message.message) {\n continue;\n }\n\n let messageContent: string;\n try {\n if (this.isServerEnvironment) {\n messageContent = Buffer.from(\n message.message,\n 'base64'\n ).toString('utf-8');\n } else {\n messageContent = new TextDecoder().decode(\n Uint8Array.from(atob(message.message), (c) =>\n c.charCodeAt(0)\n )\n );\n }\n } catch (error) {\n this.logger.error(`Error decoding message: ${error}`);\n continue;\n }\n\n let messageJson;\n try {\n messageJson = JSON.parse(messageContent);\n } catch (error) {\n this.logger.error(\n `Invalid JSON message content: ${messageContent}`\n );\n return;\n }\n\n messageJson.sequence_number = message.sequence_number;\n messages.push({\n ...messageJson,\n consensus_timestamp: message.consensus_timestamp,\n sequence_number: message.sequence_number,\n created: new Date(Number(message.consensus_timestamp) * 1000),\n });\n } catch (error: any) {\n this.logger.error(`Error processing message: ${error.message}`);\n }\n }\n }\n\n nextUrl = data.links?.next ? `${this.baseUrl}${data.links.next}` : '';\n } catch (error: any) {\n this.logger.error(`Error querying topic messages: ${error.message}`);\n throw new Error(`Failed to query topic messages: ${error.message}`);\n }\n }\n\n return messages;\n }\n\n /**\n * Requests account information for a given account ID from the mirror node.\n * @param accountId The ID of the account to retrieve information for.\n * @returns A promise that resolves to the account information.\n * @throws An error if the account ID is invalid or the information cannot be retrieved.\n */\n async requestAccount(accountId: string): Promise<AccountResponse> {\n try {\n const accountInfoUrl = `${this.baseUrl}/api/v1/accounts/${accountId}`;\n const response = await axios.get(accountInfoUrl);\n if (!response.data) {\n throw new Error(\n `Failed to make request to mirror node for account: ${accountId}`\n );\n }\n return response.data;\n } catch (error: any) {\n this.logger.error(`Failed to fetch account: ${error.message}`);\n throw new Error(`Failed to fetch account: ${error.message}`);\n }\n }\n\n /**\n * Checks if a user has access to a given key list.\n * @param keyBytes The key list to check access for.\n * @param userPublicKey The public key of the user to check access for.\n * @returns A promise that resolves to true if the user has access, false otherwise.\n */\n async checkKeyListAccess(\n keyBytes: Buffer,\n userPublicKey: PublicKey\n ): Promise<boolean> {\n try {\n const key = proto.Key.decode(keyBytes);\n return this.evaluateKeyAccess(key, userPublicKey);\n } catch (error) {\n this.logger.error(\n `Error decoding protobuf key: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n return false;\n }\n }\n\n /**\n * Evaluates the access of a given key to a user's public key.\n * @param key The key to evaluate access for.\n * @param userPublicKey The public key of the user to evaluate access for.\n * @returns A promise that resolves to true if the key has access, false otherwise.\n */\n private async evaluateKeyAccess(\n key: proto.IKey,\n userPublicKey: PublicKey\n ): Promise<boolean> {\n if (key.ed25519) {\n return this.compareEd25519Key(key.ed25519, userPublicKey);\n }\n\n if (key.keyList) {\n return this.evaluateKeyList(key.keyList, userPublicKey);\n }\n\n if (key.thresholdKey && key.thresholdKey.keys) {\n return this.evaluateKeyList(key.thresholdKey.keys, userPublicKey);\n }\n\n return false;\n }\n\n /**\n * Evaluates the access of a given key list to a user's public key.\n * @param keyList The key list to evaluate access for.\n * @param userPublicKey The public key of the user to evaluate access for.\n * @returns A promise that resolves to true if the key list has access, false otherwise.\n */\n private async evaluateKeyList(\n keyList: proto.IKeyList,\n userPublicKey: PublicKey\n ): Promise<boolean> {\n const keys = keyList.keys || [];\n\n for (const listKey of keys) {\n if (!listKey) continue;\n\n if (listKey.ed25519) {\n if (this.compareEd25519Key(listKey.ed25519, userPublicKey)) {\n return true;\n }\n } else if (listKey.keyList || listKey.thresholdKey) {\n try {\n const nestedKeyBytes = proto.Key.encode({\n ...(listKey.keyList ? { keyList: listKey.keyList } : {}),\n ...(listKey.thresholdKey\n ? { thresholdKey: listKey.thresholdKey }\n : {}),\n }).finish();\n\n const hasNestedAccess = await this.checkKeyListAccess(\n Buffer.from(nestedKeyBytes),\n userPublicKey\n );\n\n if (hasNestedAccess) {\n return true;\n }\n } catch (err) {\n this.logger.debug(\n `Error in nested key: ${\n err instanceof Error ? err.message : String(err)\n }`\n );\n }\n }\n }\n\n return false;\n }\n\n /**\n * Compares an Ed25519 key with a user's public key.\n * @param keyData The Ed25519 key data to compare.\n * @param userPublicKey The public key of the user to compare with.\n * @returns A boolean indicating whether the key matches the user's public key.\n */\n private compareEd25519Key(\n keyData: Uint8Array,\n userPublicKey: PublicKey\n ): boolean {\n try {\n const decodedKey = PublicKey.fromBytes(Buffer.from(keyData));\n return decodedKey.toString() === userPublicKey.toString();\n } catch (err) {\n return false;\n }\n }\n}\n"],"names":[],"mappings":";;;;;AAcO,MAAM,iBAAiB;AAAA,EAM5B,YAAY,SAAsB,QAAgB;AAChD,SAAK,UAAU;AACV,SAAA,UAAU,KAAK,iBAAiB;AACrC,SAAK,SAAS;AACT,SAAA,sBAAsB,OAAO,WAAW;AAAA,EAAA;AAAA,EAGvC,mBAA2B;AAC1B,WAAA,KAAK,YAAY,YACpB,iDACA;AAAA,EAAA;AAAA,EAGN,aAAqB;AACnB,WAAO,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASd,MAAM,aAAa,WAAuC;AACxD,SAAK,OAAO,KAAK,kCAAkC,SAAS,EAAE;AAE9D,UAAM,cAAc,MAAM,KAAK,eAAe,SAAS;AAEnD,QAAA;AACF,UAAI,CAAC,eAAe,CAAC,YAAY,KAAK;AACpC,cAAM,IAAI;AAAA,UACR,iDAAiD,SAAS;AAAA,QAC5D;AAAA,MAAA;AAGF,aAAO,UAAU,WAAW,YAAY,IAAI,GAAG;AAAA,aACxC,OAAY;AACnB,YAAM,IAAI;AAAA,QACR,+CAA+C,MAAM,OAAO;AAAA,MAC9D;AAAA,IAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAM,eAAe,WAA2C;AAC9D,UAAM,aAAa;AAEnB,aAAS,UAAU,GAAG,UAAU,YAAY,WAAW;AACjD,UAAA;AACF,cAAM,iBAAiB,GAAG,KAAK,OAAO,oBAAoB,SAAS;AAEnE,cAAM,WAAW,MAAM,MAAM,IAAI,cAAc;AAC/C,cAAM,cAAc,SAAS;AAEzB,YAAA,eAAe,YAAY,MAAM;AACnC,iBAAO,YAAY;AAAA,QAAA;AAGrB,aAAK,OAAO,MAAM,6BAA6B,SAAS,EAAE;AAEtD,YAAA,UAAU,aAAa,GAAG;AAC5B,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAI,CAAC;AAAA,QAAA;AAAA,eAEnD,OAAY;AACnB,aAAK,OAAO;AAAA,UACV,uCAAuC,UAAU,CAAC,MAChD,MAAM,OACR;AAAA,QACF;AAEI,YAAA,UAAU,aAAa,GAAG;AAC5B,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAI,CAAC;AAAA,QAAA;AAAA,MAC1D;AAAA,IACF;AAGK,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,MAAM,aAAa,SAAyC;AACtD,QAAA;AACF,YAAM,eAAe,GAAG,KAAK,OAAO,kBAAkB,OAAO;AAC7D,YAAM,WAAW,MAAM,MAAM,IAAI,YAAY;AAC7C,aAAO,SAAS;AAAA,aACT,OAAY;AACnB,WAAK,OAAO,MAAM,uCAAuC,MAAM,OAAO,EAAE;AACxE,YAAM,IAAI,MAAM,yCAAyC,MAAM,OAAO,EAAE;AAAA,IAAA;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAM,aAAa,SAA6C;AAC1D,QAAA;AACF,YAAM,YAAY,MAAM,KAAK,aAAa,OAAO;AACjD,aAAO,UAAU;AAAA,aACV,OAAY;AACnB,WAAK,OAAO,MAAM,gCAAgC,MAAM,OAAO,EAAE;AAC1D,aAAA;AAAA,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAM,aAAa,MAAoC;AACjD,QAAA;AACF,YAAM,YAAY,UAAU,SAAS,IAAI,EAAE,SAAS;AAEpD,YAAM,UAAU,MAAM;AAAA,QACpB,sFAAsF,SAAS;AAAA,MACjG;AACM,YAAA,WAAY,MAAM,QAAQ,KAAK;AAE/B,YAAA,WACJ,OAAO,UAAU,cAAc,eAAe,IAC9C,OAAO,UAAU,cAAc,eAAe,IAC9C;AAEK,aAAA;AAAA,aACA,GAAG;AACH,aAAA;AAAA,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAM,aAAa,SAAoD;AACrE,SAAK,OAAO,MAAM,2BAA2B,OAAO,EAAE;AAClD,QAAA;AACF,YAAM,eAAe,GAAG,KAAK,OAAO,kBAAkB,OAAO;AAC7D,YAAM,WAAW,MAAM,MAAM,IAAuB,YAAY;AAChE,UAAI,SAAS,MAAM;AACjB,aAAK,OAAO,MAAM,wBAAwB,OAAO,KAAK,SAAS,IAAI;AACnE,eAAO,SAAS;AAAA,MAAA;AAElB,WAAK,OAAO,KAAK,2BAA2B,OAAO,EAAE;AAC9C,aAAA;AAAA,aACA,OAAY;AACnB,WAAK,OAAO;AAAA,QACV,iCAAiC,OAAO,KAAK,MAAM,OAAO;AAAA,MAC5D;AAEO,aAAA;AAAA,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAM,iBAAiB,SAAwC;AAC7D,SAAK,OAAO,MAAM,+BAA+B,OAAO,EAAE;AAE1D,QAAI,UAAU,GAAG,KAAK,OAAO,kBAAkB,OAAO;AACtD,UAAM,WAAyB,CAAC;AAEhC,WAAO,SAAS;AACV,UAAA;AACF,cAAM,WAAW,MAAM,MAAM,IAA2B,OAAO;AAC/D,cAAM,OAAO,SAAS;AAEtB,YAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAClC,qBAAA,WAAW,KAAK,UAAU;AAC/B,gBAAA;AACE,kBAAA,CAAC,QAAQ,SAAS;AACpB;AAAA,cAAA;AAGE,kBAAA;AACA,kBAAA;AACF,oBAAI,KAAK,qBAAqB;AAC5B,mCAAiB,OAAO;AAAA,oBACtB,QAAQ;AAAA,oBACR;AAAA,kBAAA,EACA,SAAS,OAAO;AAAA,gBAAA,OACb;AACY,mCAAA,IAAI,cAAc;AAAA,oBACjC,WAAW;AAAA,sBAAK,KAAK,QAAQ,OAAO;AAAA,sBAAG,CAAC,MACtC,EAAE,WAAW,CAAC;AAAA,oBAAA;AAAA,kBAElB;AAAA,gBAAA;AAAA,uBAEK,OAAO;AACd,qBAAK,OAAO,MAAM,2BAA2B,KAAK,EAAE;AACpD;AAAA,cAAA;AAGE,kBAAA;AACA,kBAAA;AACY,8BAAA,KAAK,MAAM,cAAc;AAAA,uBAChC,OAAO;AACd,qBAAK,OAAO;AAAA,kBACV,iCAAiC,cAAc;AAAA,gBACjD;AACA;AAAA,cAAA;AAGF,0BAAY,kBAAkB,QAAQ;AACtC,uBAAS,KAAK;AAAA,gBACZ,GAAG;AAAA,gBACH,qBAAqB,QAAQ;AAAA,gBAC7B,iBAAiB,QAAQ;AAAA,gBACzB,SAAS,IAAI,KAAK,OAAO,QAAQ,mBAAmB,IAAI,GAAI;AAAA,cAAA,CAC7D;AAAA,qBACM,OAAY;AACnB,mBAAK,OAAO,MAAM,6BAA6B,MAAM,OAAO,EAAE;AAAA,YAAA;AAAA,UAChE;AAAA,QACF;AAGQ,kBAAA,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,GAAG,KAAK,MAAM,IAAI,KAAK;AAAA,eAC5D,OAAY;AACnB,aAAK,OAAO,MAAM,kCAAkC,MAAM,OAAO,EAAE;AACnE,cAAM,IAAI,MAAM,mCAAmC,MAAM,OAAO,EAAE;AAAA,MAAA;AAAA,IACpE;AAGK,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,MAAM,eAAe,WAA6C;AAC5D,QAAA;AACF,YAAM,iBAAiB,GAAG,KAAK,OAAO,oBAAoB,SAAS;AACnE,YAAM,WAAW,MAAM,MAAM,IAAI,cAAc;AAC3C,UAAA,CAAC,SAAS,MAAM;AAClB,cAAM,IAAI;AAAA,UACR,sDAAsD,SAAS;AAAA,QACjE;AAAA,MAAA;AAEF,aAAO,SAAS;AAAA,aACT,OAAY;AACnB,WAAK,OAAO,MAAM,4BAA4B,MAAM,OAAO,EAAE;AAC7D,YAAM,IAAI,MAAM,4BAA4B,MAAM,OAAO,EAAE;AAAA,IAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAM,mBACJ,UACA,eACkB;AACd,QAAA;AACF,YAAM,MAAM,MAAM,IAAI,OAAO,QAAQ;AAC9B,aAAA,KAAK,kBAAkB,KAAK,aAAa;AAAA,aACzC,OAAO;AACd,WAAK,OAAO;AAAA,QACV,gCACE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,MACF;AACO,aAAA;AAAA,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAc,kBACZ,KACA,eACkB;AAClB,QAAI,IAAI,SAAS;AACf,aAAO,KAAK,kBAAkB,IAAI,SAAS,aAAa;AAAA,IAAA;AAG1D,QAAI,IAAI,SAAS;AACf,aAAO,KAAK,gBAAgB,IAAI,SAAS,aAAa;AAAA,IAAA;AAGxD,QAAI,IAAI,gBAAgB,IAAI,aAAa,MAAM;AAC7C,aAAO,KAAK,gBAAgB,IAAI,aAAa,MAAM,aAAa;AAAA,IAAA;AAG3D,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,MAAc,gBACZ,SACA,eACkB;AACZ,UAAA,OAAO,QAAQ,QAAQ,CAAC;AAE9B,eAAW,WAAW,MAAM;AAC1B,UAAI,CAAC,QAAS;AAEd,UAAI,QAAQ,SAAS;AACnB,YAAI,KAAK,kBAAkB,QAAQ,SAAS,aAAa,GAAG;AACnD,iBAAA;AAAA,QAAA;AAAA,MAEA,WAAA,QAAQ,WAAW,QAAQ,cAAc;AAC9C,YAAA;AACI,gBAAA,iBAAiB,MAAM,IAAI,OAAO;AAAA,YACtC,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAA,IAAY,CAAC;AAAA,YACtD,GAAI,QAAQ,eACR,EAAE,cAAc,QAAQ,aAAA,IACxB,CAAA;AAAA,UACL,CAAA,EAAE,OAAO;AAEJ,gBAAA,kBAAkB,MAAM,KAAK;AAAA,YACjC,OAAO,KAAK,cAAc;AAAA,YAC1B;AAAA,UACF;AAEA,cAAI,iBAAiB;AACZ,mBAAA;AAAA,UAAA;AAAA,iBAEF,KAAK;AACZ,eAAK,OAAO;AAAA,YACV,wBACE,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CACjD;AAAA,UACF;AAAA,QAAA;AAAA,MACF;AAAA,IACF;AAGK,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASD,kBACN,SACA,eACS;AACL,QAAA;AACF,YAAM,aAAa,UAAU,UAAU,OAAO,KAAK,OAAO,CAAC;AAC3D,aAAO,WAAW,eAAe,cAAc,SAAS;AAAA,aACjD,KAAK;AACL,aAAA;AAAA,IAAA;AAAA,EACT;AAEJ;"}
@@ -1,94 +1,154 @@
1
+ import { CustomFeeType } from "./standards-sdk.es20.js";
2
+ import { HederaMirrorNode } from "./standards-sdk.es18.js";
1
3
  class FeeConfigBuilder {
2
- constructor() {
3
- this.feeAmount = 0;
4
- this.decimals = 0;
5
- this.feeCollectorAccountId = "";
6
- this.exemptAccountIds = [];
4
+ constructor(options) {
5
+ this.customFees = [];
6
+ this.logger = options.logger;
7
+ this.mirrorNode = new HederaMirrorNode(options.network, options.logger);
8
+ this.defaultCollectorAccountId = options.defaultCollectorAccountId || "";
7
9
  }
8
10
  /**
9
- * Static factory method to create a fee config with HBAR amount in one line
10
- * @param hbarAmount Amount in HBAR
11
- * @param collectorAccountId Account that will receive the fees
12
- * @param exemptAccounts Optional array of exempt account IDs
13
- * @returns A configured FeeConfigBuilder
11
+ * Static factory method to create a FeeConfigBuilder with a single HBAR fee.
12
+ * @param hbarAmount Amount in HBAR.
13
+ * @param collectorAccountId Optional account ID to collect the fee. If omitted or undefined, defaults to the agent's own account ID during topic creation.
14
+ * @param network Network type ('mainnet' or 'testnet').
15
+ * @param logger Logger instance.
16
+ * @param exemptAccounts Optional array of account IDs exempt from this fee.
17
+ * @returns A configured FeeConfigBuilder instance.
14
18
  */
15
- static forHbar(hbarAmount, collectorAccountId, exemptAccounts = []) {
16
- return new FeeConfigBuilder().setHbarAmount(hbarAmount).setFeeCollector(collectorAccountId).addExemptAccounts(exemptAccounts);
19
+ static forHbar(hbarAmount, collectorAccountId, network, logger, exemptAccounts = []) {
20
+ const builder = new FeeConfigBuilder({
21
+ network,
22
+ logger,
23
+ defaultCollectorAccountId: collectorAccountId
24
+ });
25
+ return builder.addHbarFee(hbarAmount, collectorAccountId, exemptAccounts);
17
26
  }
18
27
  /**
19
- * Sets the fee amount in HBAR (convenient method)
20
- * @param hbarAmount The amount in HBAR (e.g., 5 for 5 HBAR)
21
- * @returns This builder instance for method chaining
28
+ * Static factory method to create a FeeConfigBuilder with a single token fee.
29
+ * Automatically fetches token decimals if not provided.
30
+ * @param tokenAmount Amount of tokens.
31
+ * @param feeTokenId Token ID for the fee.
32
+ * @param collectorAccountId Optional account ID to collect the fee. If omitted or undefined, defaults to the agent's own account ID during topic creation.
33
+ * @param network Network type ('mainnet' or 'testnet').
34
+ * @param logger Logger instance.
35
+ * @param exemptAccounts Optional array of account IDs exempt from this fee.
36
+ * @param decimals Optional decimals for the token (fetched if omitted).
37
+ * @returns A Promise resolving to a configured FeeConfigBuilder instance.
22
38
  */
23
- setHbarAmount(hbarAmount) {
24
- if (hbarAmount <= 0) {
25
- throw new Error("HBAR amount must be greater than zero");
26
- }
27
- this.feeAmount = hbarAmount * 1e8;
28
- this.decimals = 0;
29
- return this;
30
- }
31
- /**
32
- * Sets the amount of the fee to be collected for topic submissions
33
- * @param amount The fee amount (in tinybars or token units)
34
- * @param decimals Decimal places for fixed point representation (default: 0)
35
- * @returns This builder instance for method chaining
36
- */
37
- setFeeAmount(amount, decimals = 0) {
38
- this.feeAmount = amount;
39
- this.decimals = decimals;
40
- return this;
41
- }
42
- /**
43
- * Sets the Hedera account ID that will collect the fees
44
- * @param accountId The fee collector's account ID (e.g., '0.0.12345')
45
- * @returns This builder instance for method chaining
46
- */
47
- setFeeCollector(accountId) {
48
- this.feeCollectorAccountId = accountId;
49
- return this;
39
+ static async forToken(tokenAmount, feeTokenId, collectorAccountId, network, logger, exemptAccounts = [], decimals) {
40
+ const builder = new FeeConfigBuilder({
41
+ network,
42
+ logger,
43
+ defaultCollectorAccountId: collectorAccountId
44
+ });
45
+ await builder.addTokenFee(
46
+ tokenAmount,
47
+ feeTokenId,
48
+ collectorAccountId,
49
+ decimals,
50
+ exemptAccounts
51
+ );
52
+ return builder;
50
53
  }
51
54
  /**
52
- * Adds an account ID to the list of accounts exempt from paying fees
53
- * @param accountId The account ID to exempt from fees
54
- * @returns This builder instance for method chaining
55
+ * Adds an HBAR fee configuration to the builder.
56
+ * Allows chaining multiple fee additions.
57
+ * @param hbarAmount The amount in HBAR (e.g., 0.5).
58
+ * @param collectorAccountId Optional. The account ID to collect this fee. If omitted, defaults to the agent's own account ID during topic creation.
59
+ * @param exemptAccountIds Optional. Accounts specifically exempt from *this* HBAR fee.
60
+ * @returns This FeeConfigBuilder instance for chaining.
55
61
  */
56
- addExemptAccount(accountId) {
57
- if (!this.exemptAccountIds.includes(accountId)) {
58
- this.exemptAccountIds.push(accountId);
62
+ addHbarFee(hbarAmount, collectorAccountId, exemptAccountIds = []) {
63
+ if (hbarAmount <= 0) {
64
+ throw new Error("HBAR amount must be greater than zero");
59
65
  }
66
+ this.customFees.push({
67
+ feeAmount: {
68
+ amount: hbarAmount * 1e8,
69
+ decimals: 0
70
+ },
71
+ feeCollectorAccountId: collectorAccountId || "",
72
+ feeTokenId: void 0,
73
+ exemptAccounts: [...exemptAccountIds],
74
+ type: CustomFeeType.FIXED_FEE
75
+ });
60
76
  return this;
61
77
  }
62
78
  /**
63
- * Adds multiple account IDs to the list of accounts exempt from paying fees
64
- * @param accountIds Array of account IDs to exempt from fees
65
- * @returns This builder instance for method chaining
79
+ * Adds a token fee configuration to the builder.
80
+ * Allows chaining multiple fee additions.
81
+ * Fetches token decimals automatically if not provided.
82
+ * @param tokenAmount The amount of the specified token.
83
+ * @param feeTokenId The ID of the token to charge the fee in.
84
+ * @param collectorAccountId Optional. The account ID to collect this fee. If omitted, defaults to the agent's own account ID during topic creation.
85
+ * @param decimals Optional. The number of decimals for the token. If omitted, it will be fetched from the mirror node.
86
+ * @param exemptAccountIds Optional. Accounts specifically exempt from *this* token fee.
87
+ * @returns A Promise resolving to this FeeConfigBuilder instance for chaining.
66
88
  */
67
- addExemptAccounts(accountIds) {
68
- for (const accountId of accountIds) {
69
- this.addExemptAccount(accountId);
89
+ async addTokenFee(tokenAmount, feeTokenId, collectorAccountId, decimals, exemptAccountIds = []) {
90
+ if (tokenAmount <= 0) {
91
+ throw new Error("Token amount must be greater than zero");
92
+ }
93
+ if (!feeTokenId) {
94
+ throw new Error("Fee token ID is required when adding a token fee");
70
95
  }
96
+ let finalDecimals = decimals;
97
+ if (finalDecimals === void 0) {
98
+ try {
99
+ const tokenInfo = await this.mirrorNode.getTokenInfo(feeTokenId);
100
+ if (tokenInfo?.decimals) {
101
+ finalDecimals = parseInt(tokenInfo.decimals, 10);
102
+ this.logger.info(
103
+ `Fetched decimals for ${feeTokenId}: ${finalDecimals}`
104
+ );
105
+ } else {
106
+ this.logger.warn(
107
+ `Could not fetch decimals for ${feeTokenId}, defaulting to 0.`
108
+ );
109
+ finalDecimals = 0;
110
+ }
111
+ } catch (error) {
112
+ this.logger.error(
113
+ `Error fetching decimals for ${feeTokenId}, defaulting to 0: ${error}`
114
+ );
115
+ finalDecimals = 0;
116
+ }
117
+ }
118
+ this.customFees.push({
119
+ feeAmount: {
120
+ amount: tokenAmount * 10 ** finalDecimals,
121
+ decimals: finalDecimals
122
+ },
123
+ feeCollectorAccountId: collectorAccountId || "",
124
+ feeTokenId,
125
+ exemptAccounts: [...exemptAccountIds],
126
+ type: CustomFeeType.FIXED_FEE
127
+ });
71
128
  return this;
72
129
  }
73
130
  /**
74
- * Builds and returns the final fee configuration object
75
- * @throws Error if fee collector account ID is not set or if fee amount is not positive
76
- * @returns A complete TopicFeeConfig object
131
+ * Builds the final TopicFeeConfig object.
132
+ * @returns The TopicFeeConfig containing all added custom fees and a consolidated list of unique exempt accounts.
133
+ * @throws Error if no fees have been added.
134
+ * @throws Error if more than 10 fees have been added.
77
135
  */
78
136
  build() {
79
- if (!this.feeCollectorAccountId) {
80
- throw new Error("Fee collector account ID is required");
137
+ if (this.customFees.length === 0) {
138
+ throw new Error(
139
+ "At least one fee must be added using addHbarFee/addTokenFee or created using forHbar/forToken"
140
+ );
81
141
  }
82
- if (this.feeAmount <= 0) {
83
- throw new Error("Fee amount must be greater than zero");
142
+ if (this.customFees.length > 10) {
143
+ throw new Error("Maximum of 10 custom fees per topic allowed");
84
144
  }
145
+ const allExemptAccounts = /* @__PURE__ */ new Set();
146
+ this.customFees.forEach((fee) => {
147
+ fee.exemptAccounts.forEach((account) => allExemptAccounts.add(account));
148
+ });
85
149
  return {
86
- feeAmount: {
87
- amount: this.feeAmount,
88
- decimals: this.decimals
89
- },
90
- feeCollectorAccountId: this.feeCollectorAccountId,
91
- exemptAccounts: this.exemptAccountIds
150
+ customFees: this.customFees,
151
+ exemptAccounts: Array.from(allExemptAccounts)
92
152
  };
93
153
  }
94
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"standards-sdk.es19.js","sources":["../../src/fees/fee-config-builder.ts"],"sourcesContent":["import { FeeConfigBuilderInterface, TopicFeeConfig } from './types';\n\n/**\n * FeeConfigBuilder provides a fluent interface for creating fee configurations\n * for HCS-10 topics. This makes it easy to configure fees without dealing with\n * the complexity of the underlying fee structure.\n *\n * Example usage:\n * ```typescript\n * const feeConfig = new FeeConfigBuilder()\n * .setHbarAmount(1) // 1 HBAR\n * .setFeeCollector('0.0.12345')\n * .addExemptAccount('0.0.67890')\n * .build();\n * ```\n */\nexport class FeeConfigBuilder implements FeeConfigBuilderInterface {\n private feeAmount: number = 0;\n private decimals: number = 0;\n private feeCollectorAccountId: string = '';\n private exemptAccountIds: string[] = [];\n\n /**\n * Static factory method to create a fee config with HBAR amount in one line\n * @param hbarAmount Amount in HBAR\n * @param collectorAccountId Account that will receive the fees\n * @param exemptAccounts Optional array of exempt account IDs\n * @returns A configured FeeConfigBuilder\n */\n static forHbar(\n hbarAmount: number,\n collectorAccountId: string,\n exemptAccounts: string[] = []\n ): FeeConfigBuilder {\n return new FeeConfigBuilder()\n .setHbarAmount(hbarAmount)\n .setFeeCollector(collectorAccountId)\n .addExemptAccounts(exemptAccounts);\n }\n\n /**\n * Sets the fee amount in HBAR (convenient method)\n * @param hbarAmount The amount in HBAR (e.g., 5 for 5 HBAR)\n * @returns This builder instance for method chaining\n */\n setHbarAmount(hbarAmount: number): FeeConfigBuilder {\n if (hbarAmount <= 0) {\n throw new Error('HBAR amount must be greater than zero');\n }\n\n // Convert HBAR to tinybars (1 HBAR = 100,000,000 tinybars)\n this.feeAmount = hbarAmount * 100_000_000;\n this.decimals = 0;\n return this;\n }\n\n /**\n * Sets the amount of the fee to be collected for topic submissions\n * @param amount The fee amount (in tinybars or token units)\n * @param decimals Decimal places for fixed point representation (default: 0)\n * @returns This builder instance for method chaining\n */\n setFeeAmount(amount: number, decimals: number = 0): FeeConfigBuilder {\n this.feeAmount = amount;\n this.decimals = decimals;\n return this;\n }\n\n /**\n * Sets the Hedera account ID that will collect the fees\n * @param accountId The fee collector's account ID (e.g., '0.0.12345')\n * @returns This builder instance for method chaining\n */\n setFeeCollector(accountId: string): FeeConfigBuilder {\n this.feeCollectorAccountId = accountId;\n return this;\n }\n\n /**\n * Adds an account ID to the list of accounts exempt from paying fees\n * @param accountId The account ID to exempt from fees\n * @returns This builder instance for method chaining\n */\n addExemptAccount(accountId: string): FeeConfigBuilder {\n if (!this.exemptAccountIds.includes(accountId)) {\n this.exemptAccountIds.push(accountId);\n }\n return this;\n }\n\n /**\n * Adds multiple account IDs to the list of accounts exempt from paying fees\n * @param accountIds Array of account IDs to exempt from fees\n * @returns This builder instance for method chaining\n */\n addExemptAccounts(accountIds: string[]): FeeConfigBuilder {\n for (const accountId of accountIds) {\n this.addExemptAccount(accountId);\n }\n return this;\n }\n\n /**\n * Builds and returns the final fee configuration object\n * @throws Error if fee collector account ID is not set or if fee amount is not positive\n * @returns A complete TopicFeeConfig object\n */\n build(): TopicFeeConfig {\n if (!this.feeCollectorAccountId) {\n throw new Error('Fee collector account ID is required');\n }\n\n if (this.feeAmount <= 0) {\n throw new Error('Fee amount must be greater than zero');\n }\n\n return {\n feeAmount: {\n amount: this.feeAmount,\n decimals: this.decimals,\n },\n feeCollectorAccountId: this.feeCollectorAccountId,\n exemptAccounts: this.exemptAccountIds,\n };\n }\n}\n\n/* Example usage:\n\n// Super simple one-liner with the factory method\nconst simpleFeeConfig = FeeConfigBuilder.forHbar(5, '0.0.12345');\n\n// With Agent Builder\nconst agent = new AgentBuilder()\n .setName('Fee Collector Agent')\n .setDescription('An agent that collects fees')\n .setInboundTopicType(InboundTopicType.FEE_BASED)\n .setFeeConfig(FeeConfigBuilder.forHbar(1, '0.0.12345', ['0.0.67890']))\n .setNetwork('testnet')\n .build();\n\n// Directly with client\nconst client = new HCS10Client(config);\nconst connectionFeeConfig = new FeeConfigBuilder()\n .setHbarAmount(0.5) // 0.5 HBAR (simple!)\n .setFeeCollector(client.getAccountAndSigner().accountId)\n .addExemptAccount(requestingAccountId);\n\nconst result = await client.handleConnectionRequest(\n inboundTopicId,\n requestingAccountId,\n connectionRequestId,\n connectionFeeConfig\n);\n\n*/\n"],"names":[],"mappings":"AAgBO,MAAM,iBAAsD;AAAA,EAA5D,cAAA;AACL,SAAQ,YAAoB;AAC5B,SAAQ,WAAmB;AAC3B,SAAQ,wBAAgC;AACxC,SAAQ,mBAA6B,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStC,OAAO,QACL,YACA,oBACA,iBAA2B,CAAA,GACT;AACX,WAAA,IAAI,mBACR,cAAc,UAAU,EACxB,gBAAgB,kBAAkB,EAClC,kBAAkB,cAAc;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrC,cAAc,YAAsC;AAClD,QAAI,cAAc,GAAG;AACb,YAAA,IAAI,MAAM,uCAAuC;AAAA,IAAA;AAIzD,SAAK,YAAY,aAAa;AAC9B,SAAK,WAAW;AACT,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,aAAa,QAAgB,WAAmB,GAAqB;AACnE,SAAK,YAAY;AACjB,SAAK,WAAW;AACT,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,gBAAgB,WAAqC;AACnD,SAAK,wBAAwB;AACtB,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,iBAAiB,WAAqC;AACpD,QAAI,CAAC,KAAK,iBAAiB,SAAS,SAAS,GAAG;AACzC,WAAA,iBAAiB,KAAK,SAAS;AAAA,IAAA;AAE/B,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,kBAAkB,YAAwC;AACxD,eAAW,aAAa,YAAY;AAClC,WAAK,iBAAiB,SAAS;AAAA,IAAA;AAE1B,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,QAAwB;AAClB,QAAA,CAAC,KAAK,uBAAuB;AACzB,YAAA,IAAI,MAAM,sCAAsC;AAAA,IAAA;AAGpD,QAAA,KAAK,aAAa,GAAG;AACjB,YAAA,IAAI,MAAM,sCAAsC;AAAA,IAAA;AAGjD,WAAA;AAAA,MACL,WAAW;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,MACjB;AAAA,MACA,uBAAuB,KAAK;AAAA,MAC5B,gBAAgB,KAAK;AAAA,IACvB;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"standards-sdk.es19.js","sources":["../../src/fees/fee-config-builder.ts"],"sourcesContent":["import {\n FeeConfigBuilderInterface,\n TokenFeeConfig,\n TopicFeeConfig,\n CustomFeeType,\n} from './types';\nimport { HederaMirrorNode } from '../services/mirror-node';\nimport { Logger } from '../utils/logger';\nimport { NetworkType } from '../utils/types';\n\n/**\n * FeeConfigBuilder provides a fluent interface for creating fee configurations\n * for HCS-10 topics. This makes it easy to configure fees without dealing with\n * the complexity of the underlying fee structure.\n *\n * Example usage:\n *\n * // Super simple one-liner with the factory method\n * const simpleFeeConfig = FeeConfigBuilder.forHbar(5, '0.0.12345', NetworkType.TESTNET, new Logger(), ['0.0.67890']);\n *\n * // With multiple fees:\n * const multipleFeeConfig = new FeeConfigBuilder({\n * network: NetworkType.TESTNET,\n * logger: new Logger(),\n * defaultCollectorAccountId: '0.0.12345',\n * defaultExemptAccountIds: ['0.0.67890']\n * })\n * .withHbarFee(1) // 1 HBAR fee\n * .withTokenFee(10, '0.0.54321') // 10 units of token 0.0.54321\n * .build();\n *\n * With Agent Builder\n * const agent = new AgentBuilder()\n * .setName('Fee Collector Agent')\n * .setDescription('An agent that collects fees')\n * .setInboundTopicType(InboundTopicType.FEE_BASED)\n * .setFeeConfig(FeeConfigBuilder.forHbar(1, '0.0.12345', NetworkType.TESTNET, new Logger(), ['0.0.67890']))\n * .setNetwork('testnet')\n .build();\n\n * Directly with client\n * const client = new HCS10Client(config);\n * const connectionFeeConfig = new FeeConfigBuilder({\n * network: NetworkType.TESTNET,\n * logger: new Logger(),\n * defaultCollectorAccountId: client.getAccountAndSigner().accountId,\n * defaultExemptAccountIds: ['0.0.67890']\n * })\n * .withHbarFee(0.5) // 0.5 HBAR (simple!)\n * .build();\n\n * const result = await client.handleConnectionRequest(\n * inboundTopicId,\n * requestingAccountId,\n * connectionRequestId,\n * connectionFeeConfig\n * );\n*/\nexport interface FeeConfigBuilderOptions {\n network: NetworkType;\n logger: Logger;\n defaultCollectorAccountId?: string;\n}\n\nexport class FeeConfigBuilder implements FeeConfigBuilderInterface {\n private customFees: TokenFeeConfig[] = [];\n private mirrorNode: HederaMirrorNode;\n private logger: Logger;\n private defaultCollectorAccountId: string;\n\n constructor(options: FeeConfigBuilderOptions) {\n this.logger = options.logger;\n this.mirrorNode = new HederaMirrorNode(options.network, options.logger);\n this.defaultCollectorAccountId = options.defaultCollectorAccountId || '';\n }\n\n /**\n * Static factory method to create a FeeConfigBuilder with a single HBAR fee.\n * @param hbarAmount Amount in HBAR.\n * @param collectorAccountId Optional account ID to collect the fee. If omitted or undefined, defaults to the agent's own account ID during topic creation.\n * @param network Network type ('mainnet' or 'testnet').\n * @param logger Logger instance.\n * @param exemptAccounts Optional array of account IDs exempt from this fee.\n * @returns A configured FeeConfigBuilder instance.\n */\n static forHbar(\n hbarAmount: number,\n collectorAccountId: string | undefined,\n network: NetworkType,\n logger: Logger,\n exemptAccounts: string[] = []\n ): FeeConfigBuilder {\n const builder = new FeeConfigBuilder({\n network,\n logger,\n defaultCollectorAccountId: collectorAccountId,\n });\n return builder.addHbarFee(hbarAmount, collectorAccountId, exemptAccounts);\n }\n\n /**\n * Static factory method to create a FeeConfigBuilder with a single token fee.\n * Automatically fetches token decimals if not provided.\n * @param tokenAmount Amount of tokens.\n * @param feeTokenId Token ID for the fee.\n * @param collectorAccountId Optional account ID to collect the fee. If omitted or undefined, defaults to the agent's own account ID during topic creation.\n * @param network Network type ('mainnet' or 'testnet').\n * @param logger Logger instance.\n * @param exemptAccounts Optional array of account IDs exempt from this fee.\n * @param decimals Optional decimals for the token (fetched if omitted).\n * @returns A Promise resolving to a configured FeeConfigBuilder instance.\n */\n static async forToken(\n tokenAmount: number,\n feeTokenId: string,\n collectorAccountId: string | undefined,\n network: NetworkType,\n logger: Logger,\n exemptAccounts: string[] = [],\n decimals?: number\n ): Promise<FeeConfigBuilder> {\n const builder = new FeeConfigBuilder({\n network,\n logger,\n defaultCollectorAccountId: collectorAccountId,\n });\n await builder.addTokenFee(\n tokenAmount,\n feeTokenId,\n collectorAccountId,\n decimals,\n exemptAccounts\n );\n return builder;\n }\n\n /**\n * Adds an HBAR fee configuration to the builder.\n * Allows chaining multiple fee additions.\n * @param hbarAmount The amount in HBAR (e.g., 0.5).\n * @param collectorAccountId Optional. The account ID to collect this fee. If omitted, defaults to the agent's own account ID during topic creation.\n * @param exemptAccountIds Optional. Accounts specifically exempt from *this* HBAR fee.\n * @returns This FeeConfigBuilder instance for chaining.\n */\n addHbarFee(\n hbarAmount: number,\n collectorAccountId?: string,\n exemptAccountIds: string[] = []\n ): FeeConfigBuilder {\n if (hbarAmount <= 0) {\n throw new Error('HBAR amount must be greater than zero');\n }\n\n this.customFees.push({\n feeAmount: {\n amount: hbarAmount * 100_000_000,\n decimals: 0,\n },\n feeCollectorAccountId: collectorAccountId || '',\n feeTokenId: undefined,\n exemptAccounts: [...exemptAccountIds],\n type: CustomFeeType.FIXED_FEE,\n });\n\n return this;\n }\n\n /**\n * Adds a token fee configuration to the builder.\n * Allows chaining multiple fee additions.\n * Fetches token decimals automatically if not provided.\n * @param tokenAmount The amount of the specified token.\n * @param feeTokenId The ID of the token to charge the fee in.\n * @param collectorAccountId Optional. The account ID to collect this fee. If omitted, defaults to the agent's own account ID during topic creation.\n * @param decimals Optional. The number of decimals for the token. If omitted, it will be fetched from the mirror node.\n * @param exemptAccountIds Optional. Accounts specifically exempt from *this* token fee.\n * @returns A Promise resolving to this FeeConfigBuilder instance for chaining.\n */\n async addTokenFee(\n tokenAmount: number,\n feeTokenId: string,\n collectorAccountId?: string,\n decimals?: number,\n exemptAccountIds: string[] = []\n ): Promise<FeeConfigBuilder> {\n if (tokenAmount <= 0) {\n throw new Error('Token amount must be greater than zero');\n }\n if (!feeTokenId) {\n throw new Error('Fee token ID is required when adding a token fee');\n }\n\n let finalDecimals = decimals;\n if (finalDecimals === undefined) {\n try {\n const tokenInfo = await this.mirrorNode.getTokenInfo(feeTokenId);\n if (tokenInfo?.decimals) {\n finalDecimals = parseInt(tokenInfo.decimals, 10);\n this.logger.info(\n `Fetched decimals for ${feeTokenId}: ${finalDecimals}`\n );\n } else {\n this.logger.warn(\n `Could not fetch decimals for ${feeTokenId}, defaulting to 0.`\n );\n finalDecimals = 0;\n }\n } catch (error) {\n this.logger.error(\n `Error fetching decimals for ${feeTokenId}, defaulting to 0: ${error}`\n );\n finalDecimals = 0;\n }\n }\n\n this.customFees.push({\n feeAmount: {\n amount: tokenAmount * 10 ** finalDecimals,\n decimals: finalDecimals,\n },\n feeCollectorAccountId: collectorAccountId || '',\n feeTokenId: feeTokenId,\n exemptAccounts: [...exemptAccountIds],\n type: CustomFeeType.FIXED_FEE,\n });\n\n return this;\n }\n\n /**\n * Builds the final TopicFeeConfig object.\n * @returns The TopicFeeConfig containing all added custom fees and a consolidated list of unique exempt accounts.\n * @throws Error if no fees have been added.\n * @throws Error if more than 10 fees have been added.\n */\n build(): TopicFeeConfig {\n if (this.customFees.length === 0) {\n throw new Error(\n 'At least one fee must be added using addHbarFee/addTokenFee or created using forHbar/forToken'\n );\n }\n\n if (this.customFees.length > 10) {\n throw new Error('Maximum of 10 custom fees per topic allowed');\n }\n\n const allExemptAccounts = new Set<string>();\n this.customFees.forEach((fee) => {\n fee.exemptAccounts.forEach((account) => allExemptAccounts.add(account));\n });\n\n return {\n customFees: this.customFees,\n exemptAccounts: Array.from(allExemptAccounts),\n };\n }\n}\n"],"names":[],"mappings":"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"}