@hashgraphonline/standards-sdk 0.0.17 → 0.0.18

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.
@@ -1,7 +1,25 @@
1
- import { InboundTopicType, NetworkType, AgentConfiguration, FeeAmount } from './types.d';
1
+ import { InboundTopicType, NetworkType, FeeConfigBuilderInterface, AgentConfiguration } from './types.d';
2
2
  import { AIAgentCapability } from '../hcs-11';
3
3
  import { AgentMetadata } from './sdk';
4
4
  type SocialPlatform = 'twitter' | 'discord' | 'github' | 'website' | 'x' | 'linkedin' | 'youtube' | 'telegram';
5
+ /**
6
+ * AgentBuilder is a builder class for creating agent configurations.
7
+ * It provides a fluent interface for setting various properties of the agent.
8
+ *
9
+ * Example usage:
10
+ * ```typescript
11
+ * const agentBuilder = new AgentBuilder();
12
+ * agentBuilder.setName('My Agent');
13
+ * agentBuilder.setDescription('This is my agent');
14
+ * agentBuilder.setCapabilities([AIAgentCapability.CREATE_CONTENT]);
15
+ * agentBuilder.setModel('gpt-4o');
16
+ * agentBuilder.setCreator('John Doe');
17
+ * agentBuilder.addSocial('twitter', 'JohnDoe');
18
+ * agentBuilder.addProperty('key', 'value');
19
+ * const agentConfig = agentBuilder.build();
20
+ * ```
21
+ *
22
+ */
5
23
  export declare class AgentBuilder {
6
24
  private config;
7
25
  setName(name: string): AgentBuilder;
@@ -16,8 +34,8 @@ export declare class AgentBuilder {
16
34
  setProfilePicture(pfpBuffer: Buffer, pfpFileName: string): AgentBuilder;
17
35
  setNetwork(network: NetworkType): AgentBuilder;
18
36
  setInboundTopicType(inboundTopicType: InboundTopicType): AgentBuilder;
19
- setFeeConfig(feeAmount: FeeAmount, feeCollectorAccountId: string, exemptAccounts?: string[]): AgentBuilder;
20
- setConnectionFeeConfig(feeAmount: FeeAmount, feeCollectorAccountId: string, exemptAccounts?: string[]): AgentBuilder;
37
+ setFeeConfig(feeConfigBuilder: FeeConfigBuilderInterface): AgentBuilder;
38
+ setConnectionFeeConfig(feeConfigBuilder: FeeConfigBuilderInterface): AgentBuilder;
21
39
  setExistingAccount(accountId: string, privateKey: string): AgentBuilder;
22
40
  build(): AgentConfiguration;
23
41
  }
@@ -1,6 +1,6 @@
1
1
  import { Logger, LogLevel } from '../utils/logger';
2
2
  import { Registration } from './registrations';
3
- import { HederaMirrorNode, TopicInfo, AccountResponse } from '../utils/mirror-node-utils';
3
+ import { HederaMirrorNode, TopicInfo, AccountResponse } from '../services/mirror-node';
4
4
  export interface HCS10Config {
5
5
  network: 'mainnet' | 'testnet';
6
6
  logLevel?: LogLevel;
@@ -42,8 +42,7 @@ export declare abstract class HCS10BaseClient extends Registration {
42
42
  getAccountMemo(accountId: string): Promise<string | null>;
43
43
  protected getTopicInfoFromMemo(memo: string): Promise<TopicInfo | null>;
44
44
  getTopicInfo(accountId: string): Promise<TopicInfo | null>;
45
- retrieveOutboundConnectTopic(accountId: string): Promise<string | null>;
46
- retrieveOutboundConnectTopicFromNetwork(accountId: string): Promise<TopicInfo>;
45
+ retrieveOutboundConnectTopic(accountId: string): Promise<TopicInfo>;
47
46
  retrieveOutboundMessages(agentAccountId: string): Promise<HCSMessage[]>;
48
47
  hasConnectionCreated(agentAccountId: string, connectionId: number): Promise<boolean>;
49
48
  clearCache(): void;
@@ -0,0 +1,66 @@
1
+ import { FeeConfigBuilderInterface, TopicFeeConfig } from './types.d';
2
+ /**
3
+ * FeeConfigBuilder provides a fluent interface for creating fee configurations
4
+ * for HCS-10 topics. This makes it easy to configure fees without dealing with
5
+ * the complexity of the underlying fee structure.
6
+ *
7
+ * Example usage:
8
+ * ```typescript
9
+ * const feeConfig = new FeeConfigBuilder()
10
+ * .setHbarAmount(1) // 1 HBAR
11
+ * .setFeeCollector('0.0.12345')
12
+ * .addExemptAccount('0.0.67890')
13
+ * .build();
14
+ * ```
15
+ */
16
+ export declare class FeeConfigBuilder implements FeeConfigBuilderInterface {
17
+ private feeAmount;
18
+ private decimals;
19
+ private feeCollectorAccountId;
20
+ private exemptAccountIds;
21
+ /**
22
+ * Static factory method to create a fee config with HBAR amount in one line
23
+ * @param hbarAmount Amount in HBAR
24
+ * @param collectorAccountId Account that will receive the fees
25
+ * @param exemptAccounts Optional array of exempt account IDs
26
+ * @returns A configured FeeConfigBuilder
27
+ */
28
+ static forHbar(hbarAmount: number, collectorAccountId: string, exemptAccounts?: string[]): FeeConfigBuilder;
29
+ /**
30
+ * Sets the fee amount in HBAR (convenient method)
31
+ * @param hbarAmount The amount in HBAR (e.g., 5 for 5 HBAR)
32
+ * @returns This builder instance for method chaining
33
+ */
34
+ setHbarAmount(hbarAmount: number): FeeConfigBuilder;
35
+ /**
36
+ * Sets the amount of the fee to be collected for topic submissions
37
+ * @param amount The fee amount (in tinybars or token units)
38
+ * @param decimals Decimal places for fixed point representation (default: 0)
39
+ * @returns This builder instance for method chaining
40
+ */
41
+ setFeeAmount(amount: number, decimals?: number): FeeConfigBuilder;
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: string): FeeConfigBuilder;
48
+ /**
49
+ * Adds an account ID to the list of accounts exempt from paying fees
50
+ * @param accountId The account ID to exempt from fees
51
+ * @returns This builder instance for method chaining
52
+ */
53
+ addExemptAccount(accountId: string): FeeConfigBuilder;
54
+ /**
55
+ * Adds multiple account IDs to the list of accounts exempt from paying fees
56
+ * @param accountIds Array of account IDs to exempt from fees
57
+ * @returns This builder instance for method chaining
58
+ */
59
+ addExemptAccounts(accountIds: string[]): FeeConfigBuilder;
60
+ /**
61
+ * Builds and returns the final fee configuration object
62
+ * @throws Error if fee collector account ID is not set or if fee amount is not positive
63
+ * @returns A complete TopicFeeConfig object
64
+ */
65
+ build(): TopicFeeConfig;
66
+ }
@@ -2,9 +2,10 @@ import { Client, PrivateKey, KeyList, TransactionReceipt, PublicKey } from '@has
2
2
  import { RetrievedInscriptionResult } from '@kiloscribe/inscription-sdk';
3
3
  import { Logger } from '../utils/logger';
4
4
  import { HCS10BaseClient } from './base-client';
5
- import { HCSClientConfig, AgentConfig, CreateAccountResponse, CreateAgentResponse, InscribePfpResponse, StoreHCS11ProfileResponse, AgentRegistrationResult, HandleConnectionRequestResponse, WaitForConnectionConfirmationResponse, GetAccountAndSignerResponse, InboundTopicType, TopicFeeConfig } from './types.d';
5
+ import { HCSClientConfig, AgentConfig, CreateAccountResponse, CreateAgentResponse, InscribePfpResponse, StoreHCS11ProfileResponse, AgentRegistrationResult, HandleConnectionRequestResponse, WaitForConnectionConfirmationResponse, GetAccountAndSignerResponse, InboundTopicType, TopicFeeConfig, FeeConfigBuilderInterface } from './types.d';
6
6
  import { AgentBuilder } from './agent-builder';
7
7
  export { InboundTopicType } from './types.d';
8
+ export { FeeConfigBuilder } from './fee-config-builder';
8
9
  export interface AgentMetadata {
9
10
  type: 'autonomous' | 'manual';
10
11
  model?: string;
@@ -43,7 +44,7 @@ export declare class HCS10Client extends HCS10BaseClient {
43
44
  * @param feeConfig Optional fee configuration for fee-based topics
44
45
  * @returns The topic ID of the created inbound topic
45
46
  */
46
- createInboundTopic(accountId: string, topicType: InboundTopicType, feeConfig?: TopicFeeConfig): Promise<string>;
47
+ createInboundTopic(accountId: string, topicType: InboundTopicType, feeConfig?: FeeConfigBuilderInterface): Promise<string>;
47
48
  /**
48
49
  * Creates a new agent with inbound and outbound topics
49
50
  * @param builder The agent builder object
@@ -79,7 +80,7 @@ export declare class HCS10Client extends HCS10BaseClient {
79
80
  * @param connectionFeeConfig Optional fee configuration for the connection topic
80
81
  * @returns Response with connection details
81
82
  */
82
- handleConnectionRequest(inboundTopicId: string, requestingAccountId: string, connectionRequestId: number, connectionFeeConfig?: TopicFeeConfig): Promise<HandleConnectionRequestResponse>;
83
+ handleConnectionRequest(inboundTopicId: string, requestingAccountId: string, connectionRequestId: number, connectionFeeConfig?: FeeConfigBuilderInterface): Promise<HandleConnectionRequestResponse>;
83
84
  confirmConnection(inboundTopicId: string, connectionTopicId: string, connectedAccountId: string, connectionId: number, operatorId: string, memo: string, submitKey?: PrivateKey): Promise<number>;
84
85
  sendMessage(connectionTopicId: string, operatorId: string, data: string, memo?: string, submitKey?: PrivateKey): Promise<void>;
85
86
  createTopic(memo: string, adminKey?: boolean | PublicKey | KeyList, submitKey?: boolean | PublicKey | KeyList, feeConfig?: TopicFeeConfig): Promise<string>;
@@ -105,6 +106,12 @@ export declare class HCS10Client extends HCS10BaseClient {
105
106
  */
106
107
  waitForConnectionConfirmation(inboundTopicId: string, connectionRequestId: number, maxAttempts?: number, delayMs?: number): Promise<WaitForConnectionConfirmationResponse>;
107
108
  getAccountAndSigner(): GetAccountAndSignerResponse;
109
+ /**
110
+ * Checks if a user can submit to a topic and determines if a fee is required
111
+ * @param topicId The topic ID to check
112
+ * @param userAccountId The account ID of the user attempting to submit
113
+ * @returns Object with canSubmit, requiresFee, and optional reason
114
+ */
108
115
  canSubmitToInboundTopic(topicId: string, userAccountId: string): Promise<{
109
116
  canSubmit: boolean;
110
117
  requiresFee: boolean;
@@ -4,3 +4,4 @@ export * from './hcs-10';
4
4
  export * from './hcs-11';
5
5
  export * from './utils';
6
6
  export * from './inscribe';
7
+ export * from './services';
@@ -0,0 +1 @@
1
+ export * from './mirror-node';
@@ -1,5 +1,5 @@
1
1
  import { PublicKey } from '@hashgraph/sdk';
2
- import { Logger } from './logger';
2
+ import { Logger } from '../utils/logger';
3
3
  import { HCSMessage } from '../hcs-10/base-client';
4
4
  export interface Balance {
5
5
  balance: number;
@@ -99,20 +99,20 @@ export interface TopicMessagesResponse {
99
99
  };
100
100
  }
101
101
  export interface TopicResponse {
102
- admin_key: AdminKey;
102
+ admin_key: Key;
103
103
  auto_renew_account: string;
104
104
  auto_renew_period: number;
105
105
  created_timestamp: string;
106
106
  custom_fees: CustomFees;
107
107
  deleted: boolean;
108
- fee_exempt_key_list: AdminKey[];
109
- fee_schedule_key: AdminKey;
108
+ fee_exempt_key_list: Key[];
109
+ fee_schedule_key: Key;
110
110
  memo: string;
111
- submit_key: AdminKey;
111
+ submit_key: Key;
112
112
  timestamp: Timestamp;
113
113
  topic_id: string;
114
114
  }
115
- export interface AdminKey {
115
+ export interface Key {
116
116
  _type: string;
117
117
  key: string;
118
118
  }
@@ -142,5 +142,8 @@ export declare class HederaMirrorNode {
142
142
  getTopicFees(topicId: string): Promise<CustomFees | null>;
143
143
  getTopicMessages(topicId: string): Promise<HCSMessage[]>;
144
144
  requestAccount(accountId: string): Promise<AccountResponse>;
145
- getAccountInfo(accountId: string): Promise<AccountResponse>;
145
+ checkKeyListAccess(keyBytes: Buffer, userPublicKey: PublicKey): Promise<boolean>;
146
+ private evaluateKeyAccess;
147
+ private evaluateKeyList;
148
+ private compareEd25519Key;
146
149
  }
@@ -19,6 +19,7 @@ var __privateWrapper = (obj, member, setter, getter) => ({
19
19
  });
20
20
  var _names, _data, _dataLength, _Writer_instances, writeData_fn, _data2, _offset, _bytesRead, _parent, _maxInflation, _Reader_instances, incrementBytesRead_fn, peekBytes_fn, _options, _offset2, _tokens, _TokenString_instances, subTokenString_fn, _ParamType_instances, walkAsync_fn, _AbiCoder_instances, getCoder_fn, _errors, _events, _functions, _abiCoder, _Interface_instances, getFunction_fn, getEvent_fn;
21
21
  import { ContractId, AccountId, Client, PrivateKey, Transaction, PublicKey, Status, AccountUpdateTransaction, AccountCreateTransaction, Hbar, CustomFixedFee, KeyList, TopicCreateTransaction, TopicMessageSubmitTransaction, TopicId } from "@hashgraph/sdk";
22
+ import { proto } from "@hashgraph/proto";
22
23
  let Logger$1 = class Logger {
23
24
  constructor(options = {}) {
24
25
  this.level = options.level || "info";
@@ -6223,11 +6224,11 @@ ieee754$1.write = function(buffer2, value, offset, isLE2, mLen, nBytes) {
6223
6224
  function typedArraySupport() {
6224
6225
  try {
6225
6226
  const arr = new GlobalUint8Array(1);
6226
- const proto = { foo: function() {
6227
+ const proto2 = { foo: function() {
6227
6228
  return 42;
6228
6229
  } };
6229
- Object.setPrototypeOf(proto, GlobalUint8Array.prototype);
6230
- Object.setPrototypeOf(arr, proto);
6230
+ Object.setPrototypeOf(proto2, GlobalUint8Array.prototype);
6231
+ Object.setPrototypeOf(arr, proto2);
6231
6232
  return arr.foo() === 42;
6232
6233
  } catch (e) {
6233
6234
  return false;
@@ -8017,11 +8018,11 @@ ieee754.write = function(buffer2, value, offset, isLE2, mLen, nBytes) {
8017
8018
  function typedArraySupport() {
8018
8019
  try {
8019
8020
  const arr = new GlobalUint8Array(1);
8020
- const proto = { foo: function() {
8021
+ const proto2 = { foo: function() {
8021
8022
  return 42;
8022
8023
  } };
8023
- Object.setPrototypeOf(proto, GlobalUint8Array.prototype);
8024
- Object.setPrototypeOf(arr, proto);
8024
+ Object.setPrototypeOf(proto2, GlobalUint8Array.prototype);
8025
+ Object.setPrototypeOf(arr, proto2);
8025
8026
  return arr.foo() === 42;
8026
8027
  } catch (e) {
8027
8028
  return false;
@@ -15496,10 +15497,8 @@ class HederaMirrorNode {
15496
15497
  if (this.logger) {
15497
15498
  this.logger.info(`Getting public key for account ${accountId}`);
15498
15499
  }
15499
- const accountInfoUrl = `${this.baseUrl}/api/v1/accounts/${accountId}`;
15500
+ const accountInfo = await this.requestAccount(accountId);
15500
15501
  try {
15501
- const response = await axios.get(accountInfoUrl);
15502
- const accountInfo = response.data;
15503
15502
  if (!accountInfo || !accountInfo.key) {
15504
15503
  throw new Error(
15505
15504
  `Failed to retrieve public key for account ID: ${accountId}`
@@ -15514,11 +15513,9 @@ class HederaMirrorNode {
15514
15513
  }
15515
15514
  async getAccountMemo(accountId) {
15516
15515
  try {
15517
- const response = await axios.get(
15518
- `${this.baseUrl}/api/v1/accounts/${accountId}`
15519
- );
15520
- if (response.data && response.data.memo) {
15521
- return response.data.memo;
15516
+ const accountInfo = await this.requestAccount(accountId);
15517
+ if (accountInfo && accountInfo.memo) {
15518
+ return accountInfo.memo;
15522
15519
  }
15523
15520
  return null;
15524
15521
  } catch (error) {
@@ -15611,20 +15608,65 @@ class HederaMirrorNode {
15611
15608
  throw new Error(`Failed to fetch account: ${error.message}`);
15612
15609
  }
15613
15610
  }
15614
- async getAccountInfo(accountId) {
15611
+ async checkKeyListAccess(keyBytes, userPublicKey) {
15615
15612
  try {
15616
- const accountInfoUrl = `${this.baseUrl}/api/v1/accounts/${accountId}`;
15617
- const response = await axios.get(accountInfoUrl);
15618
- return response.data;
15613
+ const key = proto.Key.decode(keyBytes);
15614
+ return this.evaluateKeyAccess(key, userPublicKey);
15619
15615
  } catch (error) {
15620
15616
  if (this.logger) {
15621
- this.logger.error(
15622
- `Error retrieving account information: ${error.message}`
15623
- );
15617
+ this.logger.error(`Error decoding protobuf key: ${error instanceof Error ? error.message : String(error)}`);
15624
15618
  }
15625
- throw new Error(
15626
- `Failed to retrieve account information: ${error.message}`
15627
- );
15619
+ return false;
15620
+ }
15621
+ }
15622
+ async evaluateKeyAccess(key, userPublicKey) {
15623
+ if (key.ed25519) {
15624
+ return this.compareEd25519Key(key.ed25519, userPublicKey);
15625
+ }
15626
+ if (key.keyList) {
15627
+ return this.evaluateKeyList(key.keyList, userPublicKey);
15628
+ }
15629
+ if (key.thresholdKey && key.thresholdKey.keys) {
15630
+ return this.evaluateKeyList(key.thresholdKey.keys, userPublicKey);
15631
+ }
15632
+ return false;
15633
+ }
15634
+ async evaluateKeyList(keyList, userPublicKey) {
15635
+ const keys = keyList.keys || [];
15636
+ for (const listKey of keys) {
15637
+ if (!listKey) continue;
15638
+ if (listKey.ed25519) {
15639
+ if (this.compareEd25519Key(listKey.ed25519, userPublicKey)) {
15640
+ return true;
15641
+ }
15642
+ } else if (listKey.keyList || listKey.thresholdKey) {
15643
+ try {
15644
+ const nestedKeyBytes = proto.Key.encode({
15645
+ ...listKey.keyList ? { keyList: listKey.keyList } : {},
15646
+ ...listKey.thresholdKey ? { thresholdKey: listKey.thresholdKey } : {}
15647
+ }).finish();
15648
+ const hasNestedAccess = await this.checkKeyListAccess(
15649
+ Buffer2.from(nestedKeyBytes),
15650
+ userPublicKey
15651
+ );
15652
+ if (hasNestedAccess) {
15653
+ return true;
15654
+ }
15655
+ } catch (err) {
15656
+ if (this.logger) {
15657
+ this.logger.debug(`Error in nested key: ${err instanceof Error ? err.message : String(err)}`);
15658
+ }
15659
+ }
15660
+ }
15661
+ }
15662
+ return false;
15663
+ }
15664
+ compareEd25519Key(keyData, userPublicKey) {
15665
+ try {
15666
+ const decodedKey = PublicKey.fromBytes(Buffer2.from(keyData));
15667
+ return decodedKey.toString() === userPublicKey.toString();
15668
+ } catch (err) {
15669
+ return false;
15628
15670
  }
15629
15671
  }
15630
15672
  }
@@ -15705,10 +15747,6 @@ class HCS10BaseClient extends Registration {
15705
15747
  return topicInfo;
15706
15748
  }
15707
15749
  async retrieveOutboundConnectTopic(accountId) {
15708
- const topicInfo = await this.getTopicInfo(accountId);
15709
- return (topicInfo == null ? void 0 : topicInfo.outboundTopic) ?? null;
15710
- }
15711
- async retrieveOutboundConnectTopicFromNetwork(accountId) {
15712
15750
  this.logger.info(`Retrieving topics for account: ${accountId}`);
15713
15751
  const cachedInfo = await this.getTopicInfo(accountId);
15714
15752
  if (cachedInfo) return cachedInfo;
@@ -15759,7 +15797,7 @@ class HCS10BaseClient extends Registration {
15759
15797
  }
15760
15798
  async retrieveOutboundMessages(agentAccountId) {
15761
15799
  try {
15762
- const topicInfo = await this.retrieveOutboundConnectTopicFromNetwork(
15800
+ const topicInfo = await this.retrieveOutboundConnectTopic(
15763
15801
  agentAccountId
15764
15802
  );
15765
15803
  if (!topicInfo) {
@@ -15779,7 +15817,7 @@ class HCS10BaseClient extends Registration {
15779
15817
  }
15780
15818
  async hasConnectionCreated(agentAccountId, connectionId) {
15781
15819
  try {
15782
- const outBoundTopic = await this.retrieveOutboundConnectTopicFromNetwork(
15820
+ const outBoundTopic = await this.retrieveOutboundConnectTopic(
15783
15821
  agentAccountId
15784
15822
  );
15785
15823
  const messages = await this.retrieveOutboundMessages(
@@ -31894,6 +31932,100 @@ async function accountIdsToExemptKeys(accountIds, network, logger) {
31894
31932
  }
31895
31933
  return exemptKeys;
31896
31934
  }
31935
+ class FeeConfigBuilder {
31936
+ constructor() {
31937
+ this.feeAmount = 0;
31938
+ this.decimals = 0;
31939
+ this.feeCollectorAccountId = "";
31940
+ this.exemptAccountIds = [];
31941
+ }
31942
+ /**
31943
+ * Static factory method to create a fee config with HBAR amount in one line
31944
+ * @param hbarAmount Amount in HBAR
31945
+ * @param collectorAccountId Account that will receive the fees
31946
+ * @param exemptAccounts Optional array of exempt account IDs
31947
+ * @returns A configured FeeConfigBuilder
31948
+ */
31949
+ static forHbar(hbarAmount, collectorAccountId, exemptAccounts = []) {
31950
+ return new FeeConfigBuilder().setHbarAmount(hbarAmount).setFeeCollector(collectorAccountId).addExemptAccounts(exemptAccounts);
31951
+ }
31952
+ /**
31953
+ * Sets the fee amount in HBAR (convenient method)
31954
+ * @param hbarAmount The amount in HBAR (e.g., 5 for 5 HBAR)
31955
+ * @returns This builder instance for method chaining
31956
+ */
31957
+ setHbarAmount(hbarAmount) {
31958
+ if (hbarAmount <= 0) {
31959
+ throw new Error("HBAR amount must be greater than zero");
31960
+ }
31961
+ this.feeAmount = hbarAmount * 1e8;
31962
+ this.decimals = 0;
31963
+ return this;
31964
+ }
31965
+ /**
31966
+ * Sets the amount of the fee to be collected for topic submissions
31967
+ * @param amount The fee amount (in tinybars or token units)
31968
+ * @param decimals Decimal places for fixed point representation (default: 0)
31969
+ * @returns This builder instance for method chaining
31970
+ */
31971
+ setFeeAmount(amount, decimals = 0) {
31972
+ this.feeAmount = amount;
31973
+ this.decimals = decimals;
31974
+ return this;
31975
+ }
31976
+ /**
31977
+ * Sets the Hedera account ID that will collect the fees
31978
+ * @param accountId The fee collector's account ID (e.g., '0.0.12345')
31979
+ * @returns This builder instance for method chaining
31980
+ */
31981
+ setFeeCollector(accountId) {
31982
+ this.feeCollectorAccountId = accountId;
31983
+ return this;
31984
+ }
31985
+ /**
31986
+ * Adds an account ID to the list of accounts exempt from paying fees
31987
+ * @param accountId The account ID to exempt from fees
31988
+ * @returns This builder instance for method chaining
31989
+ */
31990
+ addExemptAccount(accountId) {
31991
+ if (!this.exemptAccountIds.includes(accountId)) {
31992
+ this.exemptAccountIds.push(accountId);
31993
+ }
31994
+ return this;
31995
+ }
31996
+ /**
31997
+ * Adds multiple account IDs to the list of accounts exempt from paying fees
31998
+ * @param accountIds Array of account IDs to exempt from fees
31999
+ * @returns This builder instance for method chaining
32000
+ */
32001
+ addExemptAccounts(accountIds) {
32002
+ for (const accountId of accountIds) {
32003
+ this.addExemptAccount(accountId);
32004
+ }
32005
+ return this;
32006
+ }
32007
+ /**
32008
+ * Builds and returns the final fee configuration object
32009
+ * @throws Error if fee collector account ID is not set or if fee amount is not positive
32010
+ * @returns A complete TopicFeeConfig object
32011
+ */
32012
+ build() {
32013
+ if (!this.feeCollectorAccountId) {
32014
+ throw new Error("Fee collector account ID is required");
32015
+ }
32016
+ if (this.feeAmount <= 0) {
32017
+ throw new Error("Fee amount must be greater than zero");
32018
+ }
32019
+ return {
32020
+ feeAmount: {
32021
+ amount: this.feeAmount,
32022
+ decimals: this.decimals
32023
+ },
32024
+ feeCollectorAccountId: this.feeCollectorAccountId,
32025
+ exemptAccounts: this.exemptAccountIds
32026
+ };
32027
+ }
32028
+ }
31897
32029
  class HCS10Client extends HCS10BaseClient {
31898
32030
  constructor(config) {
31899
32031
  super({
@@ -31970,7 +32102,7 @@ class HCS10Client extends HCS10BaseClient {
31970
32102
  if (!feeConfig) {
31971
32103
  throw new Error("Fee configuration is required for fee-based topics");
31972
32104
  }
31973
- return this.createTopic(memo, true, true, feeConfig);
32105
+ return this.createTopic(memo, true, true, feeConfig.build());
31974
32106
  default:
31975
32107
  throw new Error(`Unsupported inbound topic type: ${topicType}`);
31976
32108
  }
@@ -32147,6 +32279,7 @@ class HCS10Client extends HCS10BaseClient {
32147
32279
  ...feeConfig.exemptAccounts || [],
32148
32280
  ...additionalExemptAccounts
32149
32281
  ];
32282
+ console.log("exemptAccountIds", exemptAccountIds);
32150
32283
  if (exemptAccountIds.length > 0) {
32151
32284
  const uniqueExemptAccountIds = Array.from(new Set(exemptAccountIds));
32152
32285
  const filteredExemptAccounts = uniqueExemptAccountIds.filter(
@@ -32202,13 +32335,10 @@ class HCS10Client extends HCS10BaseClient {
32202
32335
  let connectionTopicId;
32203
32336
  try {
32204
32337
  if (connectionFeeConfig) {
32205
- const additionalExemptAccounts = [requestingAccountId];
32338
+ const feeConfig = connectionFeeConfig.build();
32206
32339
  const modifiedFeeConfig = {
32207
- ...connectionFeeConfig,
32208
- exemptAccounts: [
32209
- ...connectionFeeConfig.exemptAccounts || [],
32210
- ...additionalExemptAccounts
32211
- ]
32340
+ ...feeConfig,
32341
+ exemptAccounts: [...feeConfig.exemptAccounts || []]
32212
32342
  };
32213
32343
  connectionTopicId = await this.createTopic(
32214
32344
  memo,
@@ -32391,7 +32521,7 @@ class HCS10Client extends HCS10BaseClient {
32391
32521
  this.logger.info(
32392
32522
  `Submitted connection request to topic ID: ${inboundTopicId}`
32393
32523
  );
32394
- const outboundTopic = await this.retrieveOutboundConnectTopicFromNetwork(
32524
+ const outboundTopic = await this.retrieveOutboundConnectTopic(
32395
32525
  requestingAccountId
32396
32526
  );
32397
32527
  const responseSequenceNumber = (_a = response.topicSequenceNumber) == null ? void 0 : _a.toNumber();
@@ -32493,27 +32623,15 @@ class HCS10Client extends HCS10BaseClient {
32493
32623
  `Attempt ${attempt + 1}/${maxAttempts} to find connection confirmation`
32494
32624
  );
32495
32625
  const messages = await this.mirrorNode.getTopicMessages(inboundTopicId);
32496
- this.logger.info(
32497
- `Retrieved ${messages.length} messages from topic ${inboundTopicId}`
32498
- );
32499
- messages.forEach((msg, index) => {
32500
- this.logger.info(`Message ${index}: ${JSON.stringify(msg)}`);
32501
- });
32502
32626
  const connectionCreatedMessages = messages.filter(
32503
32627
  (m) => m.op === "connection_created"
32504
32628
  );
32505
32629
  this.logger.info(
32506
32630
  `Found ${connectionCreatedMessages.length} connection_created messages`
32507
32631
  );
32508
- connectionCreatedMessages.forEach((msg, index) => {
32509
- this.logger.info(`Connection message ${index}: ${JSON.stringify(msg)}`);
32510
- });
32511
32632
  if (connectionCreatedMessages.length > 0) {
32512
32633
  for (const message of connectionCreatedMessages) {
32513
- this.logger.info(
32514
- `Checking if message connection_id (${message.connection_id}) matches request ID (${connectionRequestId})`
32515
- );
32516
- if (message.connection_id === connectionRequestId) {
32634
+ if (Number(message.connection_id) === Number(connectionRequestId)) {
32517
32635
  this.logger.info("Connection confirmation found");
32518
32636
  return {
32519
32637
  connectionTopicId: message.connection_topic_id,
@@ -32541,7 +32659,14 @@ class HCS10Client extends HCS10BaseClient {
32541
32659
  signer: this.operatorPrivateKey
32542
32660
  };
32543
32661
  }
32662
+ /**
32663
+ * Checks if a user can submit to a topic and determines if a fee is required
32664
+ * @param topicId The topic ID to check
32665
+ * @param userAccountId The account ID of the user attempting to submit
32666
+ * @returns Object with canSubmit, requiresFee, and optional reason
32667
+ */
32544
32668
  async canSubmitToInboundTopic(topicId, userAccountId) {
32669
+ var _a, _b, _c, _d;
32545
32670
  try {
32546
32671
  const topicInfo = await this.mirrorNode.getTopicInfo(topicId);
32547
32672
  if (!topicInfo) {
@@ -32551,29 +32676,37 @@ class HCS10Client extends HCS10BaseClient {
32551
32676
  reason: "Topic does not exist"
32552
32677
  };
32553
32678
  }
32554
- const hasSubmitKey = topicInfo.submit_key && topicInfo.submit_key.key;
32555
- if (!hasSubmitKey) {
32679
+ if (!((_a = topicInfo.submit_key) == null ? void 0 : _a.key)) {
32556
32680
  return { canSubmit: true, requiresFee: false };
32557
32681
  }
32558
32682
  try {
32559
32683
  const userPublicKey = await this.mirrorNode.getPublicKey(userAccountId);
32560
- const topicSubmitKey = PublicKey.fromString(topicInfo.submit_key.key);
32561
- if (userPublicKey.toString() === topicSubmitKey.toString()) {
32562
- return { canSubmit: true, requiresFee: false };
32684
+ if (topicInfo.submit_key._type === "ProtobufEncoded") {
32685
+ const keyBytes = Buffer2.from(topicInfo.submit_key.key, "hex");
32686
+ const hasAccess = await this.mirrorNode.checkKeyListAccess(
32687
+ keyBytes,
32688
+ userPublicKey
32689
+ );
32690
+ if (hasAccess) {
32691
+ return { canSubmit: true, requiresFee: false };
32692
+ }
32693
+ } else {
32694
+ const topicSubmitKey = PublicKey.fromString(topicInfo.submit_key.key);
32695
+ if (userPublicKey.toString() === topicSubmitKey.toString()) {
32696
+ return { canSubmit: true, requiresFee: false };
32697
+ }
32563
32698
  }
32564
32699
  } catch (error) {
32565
- this.logger.error(`Error comparing keys: ${error}`);
32700
+ this.logger.error(
32701
+ `Key validation error: ${error instanceof Error ? error.message : String(error)}`
32702
+ );
32566
32703
  }
32567
- const hasFeeScheduleKey = topicInfo.fee_schedule_key && topicInfo.fee_schedule_key.key;
32568
- if (hasFeeScheduleKey && topicInfo.custom_fees) {
32569
- const customFees = topicInfo.custom_fees;
32570
- if (customFees && customFees.fixed_fees && customFees.fixed_fees.length > 0) {
32571
- return {
32572
- canSubmit: true,
32573
- requiresFee: true,
32574
- reason: "Requires fee payment via HIP-991"
32575
- };
32576
- }
32704
+ if (((_b = topicInfo.fee_schedule_key) == null ? void 0 : _b.key) && ((_d = (_c = topicInfo.custom_fees) == null ? void 0 : _c.fixed_fees) == null ? void 0 : _d.length) > 0) {
32705
+ return {
32706
+ canSubmit: true,
32707
+ requiresFee: true,
32708
+ reason: "Requires fee payment via HIP-991"
32709
+ };
32577
32710
  }
32578
32711
  return {
32579
32712
  canSubmit: false,
@@ -32581,11 +32714,12 @@ class HCS10Client extends HCS10BaseClient {
32581
32714
  reason: "User does not have submit permission for this topic"
32582
32715
  };
32583
32716
  } catch (error) {
32584
- this.logger.error(`Error validating topic submission: ${error.message}`);
32717
+ const errorMessage = error instanceof Error ? error.message : String(error);
32718
+ this.logger.error(`Topic submission validation error: ${errorMessage}`);
32585
32719
  return {
32586
32720
  canSubmit: false,
32587
32721
  requiresFee: false,
32588
- reason: `Error: ${error.message}`
32722
+ reason: `Error: ${errorMessage}`
32589
32723
  };
32590
32724
  }
32591
32725
  }
@@ -32808,20 +32942,12 @@ class AgentBuilder {
32808
32942
  this.config.inboundTopicType = inboundTopicType;
32809
32943
  return this;
32810
32944
  }
32811
- setFeeConfig(feeAmount, feeCollectorAccountId, exemptAccounts) {
32812
- this.config.feeConfig = {
32813
- feeAmount,
32814
- feeCollectorAccountId,
32815
- exemptAccounts
32816
- };
32945
+ setFeeConfig(feeConfigBuilder) {
32946
+ this.config.feeConfig = feeConfigBuilder;
32817
32947
  return this;
32818
32948
  }
32819
- setConnectionFeeConfig(feeAmount, feeCollectorAccountId, exemptAccounts) {
32820
- this.config.connectionFeeConfig = {
32821
- feeAmount,
32822
- feeCollectorAccountId,
32823
- exemptAccounts
32824
- };
32949
+ setConnectionFeeConfig(feeConfigBuilder) {
32950
+ this.config.connectionFeeConfig = feeConfigBuilder;
32825
32951
  return this;
32826
32952
  }
32827
32953
  setExistingAccount(accountId, privateKey) {
@@ -32864,6 +32990,7 @@ export {
32864
32990
  ConnectionConfirmationError,
32865
32991
  EVMBridge,
32866
32992
  EndpointType,
32993
+ FeeConfigBuilder,
32867
32994
  HCS,
32868
32995
  HCS10BaseClient,
32869
32996
  HCS10Cache,