@hashgraph/hedera-wallet-connect 1.3.7-canary.813a6d2.0 → 1.3.7-canary.de9fb58.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,9 +49,8 @@ export class DAppSigner {
49
49
  return allNodes.slice(0, numberOfNodes);
50
50
  }
51
51
  request(request) {
52
- if (this.extensionId) {
52
+ if (this.extensionId)
53
53
  extensionOpen(this.extensionId);
54
- }
55
54
  return this.signClient.request({
56
55
  topic: this.topic,
57
56
  request,
@@ -99,20 +99,17 @@ export class DAppConnector {
99
99
  if (!this.projectId) {
100
100
  throw new Error('Project ID is not defined');
101
101
  }
102
- const signClient = await SignClient.init({
102
+ this.walletConnectClient = await SignClient.init({
103
103
  logger,
104
104
  relayUrl: 'wss://relay.walletconnect.com',
105
105
  projectId: this.projectId,
106
106
  metadata: this.dAppMetadata,
107
107
  });
108
- this.walletConnectClient = signClient;
109
108
  const existingSessions = this.walletConnectClient.session.getAll();
110
- if (existingSessions.length > 0) {
109
+ if (existingSessions.length > 0)
111
110
  this.signers = existingSessions.flatMap((session) => this.createSigners(session));
112
- }
113
- else {
114
- await this.checkIframeConnect();
115
- }
111
+ else
112
+ this.checkIframeConnect();
116
113
  this.walletConnectClient.on('session_event', (event) => {
117
114
  // Handle session events, such as "chainChanged", "accountsChanged", etc.
118
115
  this.logger.debug('Session event received:', event);
@@ -49,8 +49,8 @@ export declare function base64StringToTransaction<T extends Transaction>(transac
49
49
  * @param transaction - a base64 encoded string of proto.TransactionBody.encode().finish()
50
50
  * @returns `string`
51
51
  * */
52
- export declare function transactionToTransactionBody<T extends Transaction>(transaction: T, nodeAccountId: AccountId): any;
53
- export declare function transactionBodyToBase64String(transactionBody: proto.ITransactionBody): string;
52
+ export declare function transactionToTransactionBody<T extends Transaction>(transaction: T, nodeAccountId: AccountId): Uint8Array | null | undefined;
53
+ export declare function transactionBodyToBase64String(transactionBody: Uint8Array): string;
54
54
  /**
55
55
  * @param transactionList - a proto.TransactionList object
56
56
  * @returns `string`
@@ -86,10 +86,10 @@ export function base64StringToTransaction(transactionBytes) {
86
86
  export function transactionToTransactionBody(transaction, nodeAccountId) {
87
87
  // This is a private function, though provides the capabilities to construct a proto.TransactionBody
88
88
  //@ts-ignore
89
- return transaction._makeTransactionBody(nodeAccountId);
89
+ return transaction._signedTransactions.current.bodyBytes;
90
90
  }
91
91
  export function transactionBodyToBase64String(transactionBody) {
92
- return Uint8ArrayToBase64String(proto.TransactionBody.encode(transactionBody).finish());
92
+ return Uint8ArrayToBase64String(transactionBody);
93
93
  }
94
94
  /**
95
95
  * @param transactionList - a proto.TransactionList object
@@ -18,9 +18,9 @@
18
18
  *
19
19
  */
20
20
  import { AccountId, AccountInfoQuery, LedgerId, TopicCreateTransaction } from '@hashgraph/sdk';
21
- import { DAppConnector, HederaJsonRpcMethod, HederaSessionEvent, queryToBase64String, transactionToBase64String, transactionToTransactionBody, transactionBodyToBase64String, } from '../../src';
21
+ import { DAppConnector, HederaJsonRpcMethod, HederaSessionEvent, queryToBase64String, transactionToBase64String, transactionToTransactionBody, transactionBodyToBase64String, DAppSigner, } from '../../src';
22
22
  import { projectId, dAppMetadata, useJsonFixture, prepareTestTransaction, testUserAccountId, } from '../_helpers';
23
- import Client from '@walletconnect/sign-client';
23
+ import Client, { SignClient } from '@walletconnect/sign-client';
24
24
  describe('DAppConnector', () => {
25
25
  let connector;
26
26
  const fakeSession = useJsonFixture('fakeSession');
@@ -59,25 +59,32 @@ describe('DAppConnector', () => {
59
59
  expect((_b = connector.walletConnectClient) === null || _b === void 0 ? void 0 : _b.core.projectId).toBe(projectId);
60
60
  expect((_c = connector.walletConnectClient) === null || _c === void 0 ? void 0 : _c.core.relayUrl).toBe('wss://relay.walletconnect.com');
61
61
  });
62
- it('should create signers if there are a persisted sessions', async () => {
63
- const checkPersistedStateSpy = jest.spyOn(connector, 'checkPersistedState');
64
- checkPersistedStateSpy.mockReturnValue([fakeSession]);
62
+ it('should create signers if there are persisted sessions', async () => {
63
+ const mockInit = jest.spyOn(connector, 'init');
64
+ const mockSignClient = new SignClient({
65
+ logger: 'error',
66
+ relayUrl: 'wss://relay.walletconnect.com',
67
+ projectId: projectId,
68
+ metadata: dAppMetadata,
69
+ });
70
+ mockInit.mockImplementation(async () => {
71
+ connector.signers = [
72
+ new DAppSigner(testUserAccountId, mockSignClient, fakeSession.topic, LedgerId.TESTNET),
73
+ ];
74
+ });
65
75
  await connector.init({ logger: 'error' });
66
- expect(checkPersistedStateSpy).toHaveBeenCalled();
67
- expect(connector.signers[0].getAccountId().toString()).toBe(fakeSession.namespaces.hedera.accounts[0].split(':')[2]);
68
- expect(connector.signers[0].topic).toBe(fakeSession.topic);
69
- expect(connector.signers[0].getLedgerId()).toBe(LedgerId.TESTNET);
70
- checkPersistedStateSpy.mockRestore();
76
+ expect(connector.signers.length).toBeGreaterThan(0);
77
+ mockInit.mockRestore();
71
78
  });
72
79
  });
73
80
  describe('disconnect', () => {
74
- beforeEach(async () => {
75
- const checkPersistedStateSpy = jest.spyOn(connector, 'checkPersistedState');
76
- checkPersistedStateSpy.mockReturnValue([fakeSession]);
77
- await connector.init({ logger: 'error' });
78
- checkPersistedStateSpy.mockRestore();
79
- });
80
81
  it('should disconnect Client from topic', async () => {
82
+ connector.walletConnectClient = new SignClient({
83
+ logger: 'error',
84
+ relayUrl: 'wss://relay.walletconnect.com',
85
+ projectId: projectId,
86
+ metadata: dAppMetadata,
87
+ });
81
88
  const walletConnectDisconnectSpy = jest.spyOn(connector.walletConnectClient, 'disconnect');
82
89
  walletConnectDisconnectSpy.mockImplementation(async () => { });
83
90
  connector.disconnect(fakeSession.topic);
@@ -89,75 +96,74 @@ describe('DAppConnector', () => {
89
96
  });
90
97
  describe('requests', () => {
91
98
  let lastSignerRequestMock;
99
+ // @ts-ignore
100
+ let mockSignClient;
92
101
  beforeEach(async () => {
93
- const checkPersistedStateSpy = jest.spyOn(connector, 'checkPersistedState');
94
- checkPersistedStateSpy.mockReturnValue([fakeSession]);
95
- await connector.init({ logger: 'error' });
96
- checkPersistedStateSpy.mockRestore();
102
+ mockSignClient = new SignClient({
103
+ logger: 'error',
104
+ relayUrl: 'wss://relay.walletconnect.com',
105
+ projectId: projectId,
106
+ metadata: dAppMetadata,
107
+ });
108
+ connector.signers = [
109
+ new DAppSigner(testUserAccountId, mockSignClient, fakeSession.topic, LedgerId.TESTNET),
110
+ ];
97
111
  lastSignerRequestMock = jest.spyOn(connector.signers[0], 'request');
98
112
  lastSignerRequestMock.mockImplementation(() => { });
99
113
  });
100
114
  afterEach(() => {
101
- lastSignerRequestMock.mockRestore();
115
+ if (lastSignerRequestMock) {
116
+ lastSignerRequestMock.mockRestore();
117
+ }
102
118
  });
103
- // 1
104
- describe(DAppConnector.prototype.getNodeAddresses, () => {
105
- it('should throw an error if there is no any signer', async () => {
119
+ describe('getNodeAddresses', () => {
120
+ it('should throw an error if there is no active signer', async () => {
106
121
  connector.signers = [];
107
122
  await expect(connector.getNodeAddresses()).rejects.toThrow('There is no active session. Connect to the wallet at first.');
108
123
  });
109
124
  it('should invoke last signer request with correct params', async () => {
110
125
  await connector.getNodeAddresses();
111
- expect(lastSignerRequestMock).toHaveBeenCalled();
112
- expect(lastSignerRequestMock).toHaveBeenCalledTimes(1);
113
126
  expect(lastSignerRequestMock).toHaveBeenCalledWith({
114
127
  method: HederaJsonRpcMethod.GetNodeAddresses,
115
128
  params: undefined,
116
129
  });
117
130
  });
118
131
  });
119
- // 2
120
- describe(DAppConnector.prototype.executeTransaction, () => {
121
- const transaction = prepareTestTransaction(new TopicCreateTransaction(), { freeze: true });
132
+ describe('signMessage', () => {
122
133
  const params = {
123
- transactionList: transactionToBase64String(transaction),
134
+ message: 'test message',
135
+ signerAccountId: `hedera:testnet:${testUserAccountId.toString()}`,
124
136
  };
125
- it('should throw an error if there is no any signer', async () => {
137
+ it('should throw an error if there are no signers', async () => {
126
138
  connector.signers = [];
127
- await expect(connector.executeTransaction(params)).rejects.toThrow('There is no active session. Connect to the wallet at first.');
139
+ await expect(connector.signMessage(params)).rejects.toThrow('Signer not found for account ID: hedera:testnet:0.0.12345. Did you use the correct format? e.g hedera:<network>:<address>');
128
140
  });
129
141
  it('should invoke last signer request with correct params', async () => {
130
- await connector.executeTransaction(params);
131
- expect(lastSignerRequestMock).toHaveBeenCalled();
132
- expect(lastSignerRequestMock).toHaveBeenCalledTimes(1);
142
+ await connector.signMessage(params);
133
143
  expect(lastSignerRequestMock).toHaveBeenCalledWith({
134
- method: HederaJsonRpcMethod.ExecuteTransaction,
144
+ method: HederaJsonRpcMethod.SignMessage,
135
145
  params,
136
146
  });
137
147
  });
138
148
  });
139
- // 3
140
- describe(DAppConnector.prototype.signMessage, () => {
149
+ describe('executeTransaction', () => {
150
+ const transaction = prepareTestTransaction(new TopicCreateTransaction(), { freeze: true });
141
151
  const params = {
142
- message: 'test message',
143
- signerAccountId: testUserAccountId.toString(),
152
+ transactionList: transactionToBase64String(transaction),
144
153
  };
145
- it('should throw an error if there is no any signer', async () => {
154
+ it('should throw an error if there are no signers', async () => {
146
155
  connector.signers = [];
147
- await expect(connector.signMessage(params)).rejects.toThrow('There is no active session. Connect to the wallet at first.');
156
+ await expect(connector.executeTransaction(params)).rejects.toThrow('There is no active session. Connect to the wallet at first.');
148
157
  });
149
158
  it('should invoke last signer request with correct params', async () => {
150
- await connector.signMessage(params);
151
- expect(lastSignerRequestMock).toHaveBeenCalled();
152
- expect(lastSignerRequestMock).toHaveBeenCalledTimes(1);
159
+ await connector.executeTransaction(params);
153
160
  expect(lastSignerRequestMock).toHaveBeenCalledWith({
154
- method: HederaJsonRpcMethod.SignMessage,
161
+ method: HederaJsonRpcMethod.ExecuteTransaction,
155
162
  params,
156
163
  });
157
164
  });
158
165
  });
159
- // 4
160
- describe(DAppConnector.prototype.signAndExecuteQuery, () => {
166
+ describe('signAndExecuteQuery', () => {
161
167
  const query = new AccountInfoQuery().setAccountId(testUserAccountId.toString());
162
168
  const params = {
163
169
  signerAccountId: testUserAccountId.toString(),
@@ -165,20 +171,17 @@ describe('DAppConnector', () => {
165
171
  };
166
172
  it('should throw an error if there is no any signer', async () => {
167
173
  connector.signers = [];
168
- await expect(connector.signAndExecuteQuery(params)).rejects.toThrow('There is no active session. Connect to the wallet at first.');
174
+ await expect(connector.signAndExecuteQuery(params)).rejects.toThrow('Signer not found for account ID: 0.0.12345. Did you use the correct format? e.g hedera:<network>:<address>');
169
175
  });
170
176
  it('should invoke last signer request with correct params', async () => {
171
177
  await connector.signAndExecuteQuery(params);
172
- expect(lastSignerRequestMock).toHaveBeenCalled();
173
- expect(lastSignerRequestMock).toHaveBeenCalledTimes(1);
174
178
  expect(lastSignerRequestMock).toHaveBeenCalledWith({
175
179
  method: HederaJsonRpcMethod.SignAndExecuteQuery,
176
180
  params,
177
181
  });
178
182
  });
179
183
  });
180
- // 5
181
- describe(DAppConnector.prototype.signAndExecuteTransaction, () => {
184
+ describe('signAndExecuteTransaction', () => {
182
185
  const transaction = prepareTestTransaction(new TopicCreateTransaction(), { freeze: true });
183
186
  const params = {
184
187
  signerAccountId: testUserAccountId.toString(),
@@ -186,20 +189,17 @@ describe('DAppConnector', () => {
186
189
  };
187
190
  it('should throw an error if there is no any signer', async () => {
188
191
  connector.signers = [];
189
- await expect(connector.signAndExecuteTransaction(params)).rejects.toThrow('There is no active session. Connect to the wallet at first.');
192
+ await expect(connector.signAndExecuteTransaction(params)).rejects.toThrow('Signer not found for account ID: 0.0.12345. Did you use the correct format? e.g hedera:<network>:<address>');
190
193
  });
191
194
  it('should invoke last signer request with correct params', async () => {
192
195
  await connector.signAndExecuteTransaction(params);
193
- expect(lastSignerRequestMock).toHaveBeenCalled();
194
- expect(lastSignerRequestMock).toHaveBeenCalledTimes(1);
195
196
  expect(lastSignerRequestMock).toHaveBeenCalledWith({
196
197
  method: HederaJsonRpcMethod.SignAndExecuteTransaction,
197
198
  params,
198
199
  });
199
200
  });
200
201
  });
201
- // 6
202
- describe(DAppConnector.prototype.signTransaction, () => {
202
+ describe('signTransaction', () => {
203
203
  const transaction = prepareTestTransaction(new TopicCreateTransaction(), { freeze: true });
204
204
  const params = {
205
205
  signerAccountId: testUserAccountId.toString(),
@@ -207,12 +207,10 @@ describe('DAppConnector', () => {
207
207
  };
208
208
  it('should throw an error if there is no any signer', async () => {
209
209
  connector.signers = [];
210
- await expect(connector.signTransaction(params)).rejects.toThrow('There is no active session. Connect to the wallet at first.');
210
+ await expect(connector.signTransaction(params)).rejects.toThrow('Signer not found for account ID: 0.0.12345. Did you use the correct format? e.g hedera:<network>:<address>');
211
211
  });
212
212
  it('should invoke last signer request with correct params', async () => {
213
213
  await connector.signTransaction(params);
214
- expect(lastSignerRequestMock).toHaveBeenCalled();
215
- expect(lastSignerRequestMock).toHaveBeenCalledTimes(1);
216
214
  expect(lastSignerRequestMock).toHaveBeenCalledWith({
217
215
  method: HederaJsonRpcMethod.SignTransaction,
218
216
  params,
@@ -17,26 +17,40 @@
17
17
  * limitations under the License.
18
18
  *
19
19
  */
20
- import { AccountBalanceQuery, AccountCreateTransaction, AccountId, AccountInfoQuery, AccountRecordsQuery, AccountUpdateTransaction, LedgerId, PrivateKey, TokenAssociateTransaction, TokenCreateTransaction, TopicCreateTransaction, TransactionId, } from '@hashgraph/sdk';
20
+ import { AccountBalanceQuery, AccountCreateTransaction, AccountId, AccountInfoQuery, AccountRecordsQuery, AccountUpdateTransaction, LedgerId, PrivateKey, TokenAssociateTransaction, TokenCreateTransaction, TopicCreateTransaction, TransactionId, Client, TransactionReceiptQuery, TransactionRecordQuery, AccountInfo, TransactionRecord, TransactionReceipt, AccountBalance, FileInfoQuery, } from '@hashgraph/sdk';
21
21
  import { proto } from '@hashgraph/proto';
22
22
  import { DAppConnector, HederaJsonRpcMethod, transactionToBase64String, DAppSigner, Uint8ArrayToBase64String, base64StringToQuery, } from '../../src';
23
23
  import { projectId, dAppMetadata, useJsonFixture, prepareTestTransaction, prepareTestQuery, } from '../_helpers';
24
+ import Long from 'long';
25
+ jest.mock('../../src/lib/shared/extensionController', () => ({
26
+ extensionOpen: jest.fn(),
27
+ }));
28
+ jest.mock('../../src/lib/shared/utils', () => (Object.assign(Object.assign({}, jest.requireActual('../../src/lib/shared/utils')), { findExtensions: jest.fn() })));
24
29
  describe('DAppSigner', () => {
25
30
  let connector;
26
31
  const fakeSession = useJsonFixture('fakeSession');
32
+ let signer;
33
+ let mockSignClient;
34
+ const testAccountId = AccountId.fromString('0.0.123');
35
+ const testTopic = 'test-topic';
36
+ const testExtensionId = 'test-extension-id';
27
37
  beforeEach(() => {
28
38
  connector = new DAppConnector(dAppMetadata, LedgerId.TESTNET, projectId);
39
+ // @ts-ignore
40
+ connector.signers = connector.createSigners(fakeSession);
41
+ signer = connector.signers[0];
42
+ mockSignClient = {
43
+ request: jest.fn(),
44
+ metadata: dAppMetadata,
45
+ };
46
+ signer = new DAppSigner(testAccountId, mockSignClient, testTopic, LedgerId.TESTNET, testExtensionId);
29
47
  });
30
48
  afterEach(() => {
31
49
  global.gc && global.gc();
32
50
  });
33
51
  describe(DAppSigner.prototype.call, () => {
34
52
  let signerRequestSpy;
35
- let signer;
36
53
  beforeEach(async () => {
37
- // @ts-ignore
38
- connector.signers = connector.createSigners(fakeSession);
39
- signer = connector.signers[0];
40
54
  signerRequestSpy = jest.spyOn(signer, 'request');
41
55
  signerRequestSpy.mockImplementation((request) => {
42
56
  const { method } = request;
@@ -61,21 +75,21 @@ describe('DAppSigner', () => {
61
75
  let queryResponse = 'ERROR: Unsupported query type';
62
76
  if (query instanceof AccountBalanceQuery) {
63
77
  queryResponse = Uint8ArrayToBase64String(proto.CryptoGetAccountBalanceResponse.encode({
64
- balance: 0,
78
+ balance: Long.fromNumber(0),
65
79
  }).finish());
66
80
  }
67
81
  else if (query instanceof AccountInfoQuery) {
68
82
  queryResponse = Uint8ArrayToBase64String(proto.CryptoGetInfoResponse.AccountInfo.encode({
69
83
  accountID: {
70
- shardNum: 0,
71
- realmNum: 0,
72
- accountNum: 3,
84
+ shardNum: Long.fromNumber(0),
85
+ realmNum: Long.fromNumber(0),
86
+ accountNum: Long.fromNumber(3),
73
87
  },
74
88
  contractAccountID: AccountId.fromString('0.0.3').toSolidityAddress(),
75
89
  key: {
76
90
  ed25519: PrivateKey.generate().publicKey.toBytes(),
77
91
  },
78
- expirationTime: { seconds: 0, nanos: 0 },
92
+ expirationTime: { seconds: Long.fromNumber(0), nanos: 1 },
79
93
  }).finish());
80
94
  }
81
95
  else if (query instanceof AccountRecordsQuery) {
@@ -85,20 +99,20 @@ describe('DAppSigner', () => {
85
99
  receipt: {
86
100
  status: proto.ResponseCodeEnum.OK,
87
101
  accountID: {
88
- shardNum: 0,
89
- realmNum: 0,
90
- accountNum: 3,
102
+ shardNum: Long.fromNumber(0),
103
+ realmNum: Long.fromNumber(0),
104
+ accountNum: Long.fromNumber(3),
91
105
  },
92
106
  },
93
- consensusTimestamp: { seconds: 0, nanos: 0 },
107
+ consensusTimestamp: { seconds: Long.fromNumber(0), nanos: 1 },
94
108
  transactionID: {
95
109
  accountID: {
96
- shardNum: 0,
97
- realmNum: 0,
98
- accountNum: 3,
110
+ shardNum: Long.fromNumber(0),
111
+ realmNum: Long.fromNumber(0),
112
+ accountNum: Long.fromNumber(3),
99
113
  },
100
- transactionValidStart: { seconds: 0, nanos: 0 },
101
- nonce: 0,
114
+ transactionValidStart: { seconds: Long.fromNumber(0), nanos: 1 },
115
+ nonce: 1,
102
116
  },
103
117
  },
104
118
  }).finish());
@@ -111,7 +125,9 @@ describe('DAppSigner', () => {
111
125
  });
112
126
  });
113
127
  afterEach(() => {
114
- signerRequestSpy.mockRestore();
128
+ if (signerRequestSpy) {
129
+ signerRequestSpy.mockRestore();
130
+ }
115
131
  });
116
132
  it.each([
117
133
  { name: AccountCreateTransaction.name, ExecutableType: AccountCreateTransaction },
@@ -152,4 +168,458 @@ describe('DAppSigner', () => {
152
168
  });
153
169
  });
154
170
  });
171
+ describe('sign', () => {
172
+ let signerRequestSpy;
173
+ beforeEach(() => {
174
+ signerRequestSpy = jest.spyOn(signer, 'request');
175
+ });
176
+ afterEach(() => {
177
+ signerRequestSpy.mockRestore();
178
+ });
179
+ it('should sign a message', async () => {
180
+ const mockPublicKey = PrivateKey.generate().publicKey;
181
+ const mockSignature = new Uint8Array([1, 2, 3]);
182
+ signerRequestSpy.mockImplementation(() => Promise.resolve({
183
+ signatureMap: Uint8ArrayToBase64String(proto.SignatureMap.encode({
184
+ sigPair: [
185
+ {
186
+ pubKeyPrefix: mockPublicKey.toBytes(),
187
+ ed25519: mockSignature,
188
+ },
189
+ ],
190
+ }).finish()),
191
+ }));
192
+ const message = new Uint8Array([4, 5, 6]);
193
+ const signatures = await signer.sign([message]);
194
+ expect(signatures).toHaveLength(1);
195
+ expect(signatures[0].accountId.toString()).toBe(signer.getAccountId().toString());
196
+ expect(Array.from(signatures[0].signature)).toEqual(Array.from(mockSignature));
197
+ expect(signerRequestSpy).toHaveBeenCalledWith({
198
+ method: HederaJsonRpcMethod.SignMessage,
199
+ params: {
200
+ signerAccountId: 'hedera:testnet:' + signer.getAccountId().toString(),
201
+ message: Uint8ArrayToBase64String(message),
202
+ },
203
+ });
204
+ });
205
+ });
206
+ describe('signTransaction', () => {
207
+ let signerRequestSpy;
208
+ beforeEach(() => {
209
+ signerRequestSpy = jest.spyOn(signer, 'request');
210
+ });
211
+ afterEach(() => {
212
+ signerRequestSpy.mockRestore();
213
+ });
214
+ it('should sign a transaction', async () => {
215
+ const mockPublicKey = PrivateKey.generate().publicKey;
216
+ const mockSignature = new Uint8Array([1, 2, 3]);
217
+ signerRequestSpy.mockImplementation(() => Promise.resolve({
218
+ signatureMap: Uint8ArrayToBase64String(proto.SignatureMap.encode({
219
+ sigPair: [
220
+ {
221
+ pubKeyPrefix: mockPublicKey.toBytes(),
222
+ ed25519: mockSignature,
223
+ },
224
+ ],
225
+ }).finish()),
226
+ }));
227
+ const transaction = prepareTestTransaction(new AccountCreateTransaction(), {
228
+ freeze: true,
229
+ });
230
+ const signedTx = await signer.signTransaction(transaction);
231
+ expect(signedTx).toBeDefined();
232
+ expect(signerRequestSpy).toHaveBeenCalledWith({
233
+ method: HederaJsonRpcMethod.SignTransaction,
234
+ params: expect.objectContaining({
235
+ signerAccountId: 'hedera:testnet:' + signer.getAccountId().toString(),
236
+ transactionBody: expect.any(String),
237
+ }),
238
+ });
239
+ });
240
+ });
241
+ describe('getAccountKey()', () => {
242
+ let signerRequestSpy;
243
+ beforeEach(() => {
244
+ signerRequestSpy = jest.spyOn(signer, 'request');
245
+ });
246
+ afterEach(() => {
247
+ signerRequestSpy.mockRestore();
248
+ });
249
+ it('should throw error as method is not implemented', () => {
250
+ expect(() => signer.getAccountKey()).toThrow('Method not implemented.');
251
+ });
252
+ });
253
+ describe('network configuration', () => {
254
+ let signerRequestSpy;
255
+ beforeEach(() => {
256
+ signerRequestSpy = jest.spyOn(signer, 'request');
257
+ });
258
+ afterEach(() => {
259
+ signerRequestSpy.mockRestore();
260
+ });
261
+ it('should return network configuration from client', () => {
262
+ const network = signer.getNetwork();
263
+ expect(network).toBeDefined();
264
+ expect(Object.keys(network).length).toBeGreaterThan(0);
265
+ });
266
+ it('should return mirror network configuration from client', () => {
267
+ const mirrorNetwork = signer.getMirrorNetwork();
268
+ expect(Array.isArray(mirrorNetwork)).toBe(true);
269
+ });
270
+ });
271
+ describe('getMetadata()', () => {
272
+ let signerRequestSpy;
273
+ beforeEach(() => {
274
+ signerRequestSpy = jest.spyOn(signer, 'request');
275
+ });
276
+ afterEach(() => {
277
+ signerRequestSpy.mockRestore();
278
+ });
279
+ it('should return dApp metadata', () => {
280
+ const metadata = signer.getMetadata();
281
+ expect(metadata).toEqual(dAppMetadata);
282
+ });
283
+ });
284
+ describe('_getHederaClient', () => {
285
+ it('should create and cache client for ledger', () => {
286
+ const client1 = signer._getHederaClient();
287
+ const client2 = signer._getHederaClient();
288
+ expect(client1).toBe(client2);
289
+ expect(client1).toBeInstanceOf(Client);
290
+ });
291
+ });
292
+ describe('_getRandomNodes', () => {
293
+ it('should return random subset of nodes', () => {
294
+ const nodes = signer._getRandomNodes(3);
295
+ expect(nodes).toHaveLength(3);
296
+ expect(nodes[0]).toBeInstanceOf(AccountId);
297
+ });
298
+ });
299
+ describe('checkTransaction', () => {
300
+ it('should throw not implemented error', async () => {
301
+ await expect(signer.checkTransaction({})).rejects.toThrow('Method not implemented.');
302
+ });
303
+ });
304
+ describe('populateTransaction', () => {
305
+ it('should populate transaction with node accounts and transaction id', async () => {
306
+ const mockTx = {
307
+ setNodeAccountIds: jest.fn().mockReturnThis(),
308
+ setTransactionId: jest.fn().mockReturnThis(),
309
+ };
310
+ const result = await signer.populateTransaction(mockTx);
311
+ expect(mockTx.setNodeAccountIds).toHaveBeenCalled();
312
+ expect(mockTx.setTransactionId).toHaveBeenCalled();
313
+ expect(result).toBe(mockTx);
314
+ });
315
+ });
316
+ describe('_parseQueryResponse', () => {
317
+ it('should handle all supported query types', async () => {
318
+ // Test AccountBalanceQuery
319
+ const mockAccountBalance = proto.CryptoGetAccountBalanceResponse.encode({
320
+ header: {
321
+ nodeTransactionPrecheckCode: proto.ResponseCodeEnum.OK,
322
+ },
323
+ balance: Long.fromNumber(100),
324
+ tokenBalances: [],
325
+ }).finish();
326
+ const balanceQuery = new AccountBalanceQuery();
327
+ const balanceResponse = Uint8ArrayToBase64String(mockAccountBalance);
328
+ const balanceResult = await signer._parseQueryResponse(balanceQuery, balanceResponse);
329
+ expect(balanceResult).toBeDefined();
330
+ expect(balanceResult).toBeInstanceOf(AccountBalance);
331
+ // Test AccountInfoQuery
332
+ const mockAccountInfo = proto.CryptoGetInfoResponse.AccountInfo.encode({
333
+ accountID: {
334
+ shardNum: Long.fromNumber(0),
335
+ realmNum: Long.fromNumber(0),
336
+ accountNum: Long.fromNumber(123),
337
+ },
338
+ contractAccountID: '',
339
+ deleted: false,
340
+ proxyAccountID: null,
341
+ proxyReceived: Long.ZERO,
342
+ key: {
343
+ ed25519: PrivateKey.generate().publicKey.toBytes(),
344
+ },
345
+ balance: Long.fromNumber(100),
346
+ receiverSigRequired: false,
347
+ expirationTime: { seconds: Long.fromNumber(Date.now() / 1000 + 7776000) },
348
+ autoRenewPeriod: { seconds: Long.fromNumber(7776000) },
349
+ memo: '',
350
+ maxAutomaticTokenAssociations: 0,
351
+ alias: new Uint8Array([]),
352
+ ledgerId: new Uint8Array([]),
353
+ ethereumNonce: Long.fromNumber(0),
354
+ stakingInfo: null,
355
+ }).finish();
356
+ const infoQuery = new AccountInfoQuery();
357
+ const infoResponse = Uint8ArrayToBase64String(mockAccountInfo);
358
+ const infoResult = await signer._parseQueryResponse(infoQuery, infoResponse);
359
+ expect(infoResult).toBeDefined();
360
+ expect(infoResult).toBeInstanceOf(AccountInfo);
361
+ // Test AccountRecordsQuery
362
+ const mockTransactionRecord = proto.TransactionGetRecordResponse.encode({
363
+ header: {
364
+ nodeTransactionPrecheckCode: proto.ResponseCodeEnum.OK,
365
+ },
366
+ transactionRecord: {
367
+ receipt: {
368
+ status: proto.ResponseCodeEnum.SUCCESS,
369
+ accountID: {
370
+ shardNum: Long.fromNumber(0),
371
+ realmNum: Long.fromNumber(0),
372
+ accountNum: Long.fromNumber(123),
373
+ },
374
+ },
375
+ transactionHash: new Uint8Array([1, 2, 3]),
376
+ consensusTimestamp: { seconds: Long.fromNumber(Date.now() / 1000) },
377
+ transactionID: {
378
+ transactionValidStart: { seconds: Long.fromNumber(Date.now() / 1000) },
379
+ accountID: {
380
+ shardNum: Long.fromNumber(0),
381
+ realmNum: Long.fromNumber(0),
382
+ accountNum: Long.fromNumber(123),
383
+ },
384
+ },
385
+ memo: '',
386
+ transactionFee: Long.fromNumber(100000),
387
+ },
388
+ }).finish();
389
+ const recordsQuery = new AccountRecordsQuery();
390
+ const recordsResponse = Uint8ArrayToBase64String(mockTransactionRecord);
391
+ const recordsResult = await signer._parseQueryResponse(recordsQuery, recordsResponse);
392
+ expect(recordsResult).toBeDefined();
393
+ expect(Array.isArray(recordsResult)).toBe(true);
394
+ // Test TransactionReceiptQuery
395
+ const mockTransactionReceipt = proto.TransactionGetReceiptResponse.encode({
396
+ header: {
397
+ nodeTransactionPrecheckCode: proto.ResponseCodeEnum.OK,
398
+ },
399
+ receipt: {
400
+ status: proto.ResponseCodeEnum.SUCCESS,
401
+ accountID: {
402
+ shardNum: Long.fromNumber(0),
403
+ realmNum: Long.fromNumber(0),
404
+ accountNum: Long.fromNumber(123),
405
+ },
406
+ topicRunningHash: new Uint8Array([1, 2, 3]),
407
+ topicSequenceNumber: Long.fromNumber(1),
408
+ exchangeRate: {
409
+ currentRate: {
410
+ hbarEquiv: 1,
411
+ centEquiv: 12,
412
+ expirationTime: { seconds: Long.fromNumber(Date.now() / 1000) },
413
+ },
414
+ },
415
+ },
416
+ }).finish();
417
+ const receiptQuery = new TransactionReceiptQuery();
418
+ const receiptResponse = Uint8ArrayToBase64String(mockTransactionReceipt);
419
+ const receiptResult = await signer._parseQueryResponse(receiptQuery, receiptResponse);
420
+ expect(receiptResult).toBeDefined();
421
+ expect(receiptResult).toBeInstanceOf(TransactionReceipt);
422
+ // Test TransactionRecordQuery
423
+ const txRecordQuery = new TransactionRecordQuery();
424
+ const txRecordResponse = Uint8ArrayToBase64String(mockTransactionRecord);
425
+ const txRecordResult = await signer._parseQueryResponse(txRecordQuery, txRecordResponse);
426
+ expect(txRecordResult).toBeDefined();
427
+ expect(txRecordResult).toBeInstanceOf(TransactionRecord);
428
+ });
429
+ it('should throw error when query type is not supported', async () => {
430
+ const unsupportedQuery = new FileInfoQuery();
431
+ await expect(signer._parseQueryResponse(unsupportedQuery, '')).rejects.toThrow('Unsupported query type');
432
+ });
433
+ });
434
+ describe('call', () => {
435
+ it('should throw error when both transaction and query execution fail', async () => {
436
+ const mockRequest = {
437
+ toBytes: () => new Uint8Array([1, 2, 3]),
438
+ };
439
+ mockSignClient.request
440
+ .mockRejectedValueOnce(new Error('Transaction failed'))
441
+ .mockRejectedValueOnce(new Error('Query failed'));
442
+ await expect(signer.call(mockRequest)).rejects.toThrow(/Error executing transaction or query/);
443
+ });
444
+ });
445
+ describe('signTransaction', () => {
446
+ it('should handle transaction without node account ids', async () => {
447
+ // Create valid protobuf-encoded transaction
448
+ const mockTxBody = proto.TransactionBody.encode({
449
+ transactionID: {
450
+ accountID: { accountNum: Long.fromNumber(800) },
451
+ transactionValidStart: {
452
+ seconds: Long.fromNumber(Date.now() / 1000),
453
+ nanos: 0,
454
+ },
455
+ },
456
+ nodeAccountID: { accountNum: Long.fromNumber(3) },
457
+ transactionFee: Long.fromNumber(100000),
458
+ transactionValidDuration: { seconds: Long.fromNumber(120) },
459
+ cryptoCreateAccount: {
460
+ key: { ed25519: PrivateKey.generate().publicKey.toBytes() },
461
+ },
462
+ }).finish();
463
+ const mockTx = {
464
+ nodeAccountIds: [],
465
+ toBytes: () => new Uint8Array([1, 2, 3]),
466
+ _signedTransactions: {
467
+ current: {
468
+ bodyBytes: mockTxBody,
469
+ },
470
+ },
471
+ };
472
+ const key = PrivateKey.generate();
473
+ mockSignClient.request.mockResolvedValueOnce({
474
+ signatureMap: Uint8ArrayToBase64String(proto.SignatureMap.encode({
475
+ sigPair: [
476
+ {
477
+ pubKeyPrefix: key.publicKey.toBytes(),
478
+ ed25519: key.toBytes(),
479
+ },
480
+ ],
481
+ }).finish()),
482
+ });
483
+ await signer.signTransaction(mockTx);
484
+ expect(mockSignClient.request).toHaveBeenCalledWith({
485
+ topic: testTopic,
486
+ request: {
487
+ method: HederaJsonRpcMethod.SignTransaction,
488
+ params: expect.any(Object),
489
+ },
490
+ chainId: expect.any(String),
491
+ });
492
+ });
493
+ it('should throw error when transaction body serialization fails', async () => {
494
+ const mockTx = {
495
+ nodeAccountIds: [AccountId.fromString('0.0.3')],
496
+ _signedTransactions: {
497
+ current: {}, // This will cause bodyBytes to be undefined
498
+ },
499
+ };
500
+ await expect(signer.signTransaction(mockTx)).rejects.toThrow('Failed to serialize transaction body');
501
+ });
502
+ });
503
+ describe('request', () => {
504
+ it('should call extensionOpen when extensionId is provided', async () => {
505
+ const mockRequest = {
506
+ method: 'test-method',
507
+ params: { test: 'params' },
508
+ };
509
+ const { extensionOpen } = require('../../src/lib/shared/extensionController');
510
+ await signer.request(mockRequest);
511
+ expect(extensionOpen).toHaveBeenCalledWith(testExtensionId);
512
+ });
513
+ });
514
+ describe('account queries', () => {
515
+ let signerRequestSpy;
516
+ beforeEach(() => {
517
+ signerRequestSpy = jest.spyOn(signer, 'request');
518
+ });
519
+ afterEach(() => {
520
+ signerRequestSpy.mockRestore();
521
+ });
522
+ it('should get account balance', async () => {
523
+ const mockBalance = proto.CryptoGetAccountBalanceResponse.encode({
524
+ header: {
525
+ nodeTransactionPrecheckCode: proto.ResponseCodeEnum.OK,
526
+ },
527
+ balance: Long.fromNumber(100),
528
+ tokenBalances: [],
529
+ }).finish();
530
+ signerRequestSpy.mockResolvedValueOnce({
531
+ response: Uint8ArrayToBase64String(mockBalance),
532
+ });
533
+ const balance = await signer.getAccountBalance();
534
+ expect(balance).toBeInstanceOf(AccountBalance);
535
+ expect(signerRequestSpy).toHaveBeenCalledWith({
536
+ method: HederaJsonRpcMethod.SignAndExecuteQuery,
537
+ params: expect.objectContaining({
538
+ signerAccountId: 'hedera:testnet:' + signer.getAccountId().toString(),
539
+ }),
540
+ });
541
+ });
542
+ it('should get ledger id', async () => {
543
+ const ledgerId = await signer.getLedgerId();
544
+ expect(ledgerId).toBeDefined();
545
+ expect(ledgerId.toString()).toBe('testnet');
546
+ });
547
+ it('should get account info', async () => {
548
+ const mockInfo = proto.CryptoGetInfoResponse.AccountInfo.encode({
549
+ accountID: {
550
+ shardNum: Long.fromNumber(0),
551
+ realmNum: Long.fromNumber(0),
552
+ accountNum: Long.fromNumber(123),
553
+ },
554
+ contractAccountID: null,
555
+ deleted: false,
556
+ proxyAccountID: null,
557
+ proxyReceived: Long.ZERO,
558
+ key: {
559
+ ed25519: PrivateKey.generate().publicKey.toBytes(),
560
+ },
561
+ balance: Long.fromNumber(100),
562
+ receiverSigRequired: false,
563
+ expirationTime: { seconds: Long.fromNumber(Date.now() / 1000 + 7776000) },
564
+ autoRenewPeriod: { seconds: Long.fromNumber(7776000) },
565
+ memo: '',
566
+ maxAutomaticTokenAssociations: 0,
567
+ alias: new Uint8Array([]),
568
+ ledgerId: new Uint8Array([]),
569
+ ethereumNonce: Long.fromNumber(0),
570
+ stakingInfo: null,
571
+ }).finish();
572
+ signerRequestSpy.mockResolvedValueOnce({
573
+ response: Uint8ArrayToBase64String(mockInfo),
574
+ });
575
+ const info = await signer.getAccountInfo();
576
+ expect(info).toBeInstanceOf(AccountInfo);
577
+ expect(signerRequestSpy).toHaveBeenCalledWith({
578
+ method: HederaJsonRpcMethod.SignAndExecuteQuery,
579
+ params: expect.objectContaining({
580
+ signerAccountId: 'hedera:testnet:' + signer.getAccountId().toString(),
581
+ }),
582
+ });
583
+ });
584
+ it('should get account records', async () => {
585
+ const mockRecords = proto.TransactionGetRecordResponse.encode({
586
+ header: {
587
+ nodeTransactionPrecheckCode: proto.ResponseCodeEnum.OK,
588
+ },
589
+ transactionRecord: {
590
+ receipt: {
591
+ status: proto.ResponseCodeEnum.SUCCESS,
592
+ accountID: {
593
+ shardNum: Long.fromNumber(0),
594
+ realmNum: Long.fromNumber(0),
595
+ accountNum: Long.fromNumber(123),
596
+ },
597
+ },
598
+ transactionHash: new Uint8Array([1, 2, 3]),
599
+ consensusTimestamp: { seconds: Long.fromNumber(Date.now() / 1000) },
600
+ transactionID: {
601
+ transactionValidStart: { seconds: Long.fromNumber(Date.now() / 1000) },
602
+ accountID: {
603
+ shardNum: Long.fromNumber(0),
604
+ realmNum: Long.fromNumber(0),
605
+ accountNum: Long.fromNumber(123),
606
+ },
607
+ },
608
+ memo: '',
609
+ transactionFee: Long.fromNumber(100000),
610
+ },
611
+ }).finish();
612
+ signerRequestSpy.mockResolvedValueOnce({
613
+ response: Uint8ArrayToBase64String(mockRecords),
614
+ });
615
+ const records = await signer.getAccountRecords();
616
+ expect(Array.isArray(records)).toBe(true);
617
+ expect(signerRequestSpy).toHaveBeenCalledWith({
618
+ method: HederaJsonRpcMethod.SignAndExecuteQuery,
619
+ params: expect.objectContaining({
620
+ signerAccountId: 'hedera:testnet:' + signer.getAccountId().toString(),
621
+ }),
622
+ });
623
+ });
624
+ });
155
625
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,129 @@
1
+ import { DefaultLogger } from '../../src/lib/shared/logger';
2
+ describe('DefaultLogger', () => {
3
+ let logger;
4
+ let consoleErrorSpy;
5
+ let consoleWarnSpy;
6
+ let consoleInfoSpy;
7
+ let consoleDebugSpy;
8
+ beforeEach(() => {
9
+ // Create fresh spies for each test
10
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
11
+ consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
12
+ consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation();
13
+ consoleDebugSpy = jest.spyOn(console, 'debug').mockImplementation();
14
+ });
15
+ afterEach(() => {
16
+ // Clean up spies
17
+ consoleErrorSpy.mockRestore();
18
+ consoleWarnSpy.mockRestore();
19
+ consoleInfoSpy.mockRestore();
20
+ consoleDebugSpy.mockRestore();
21
+ });
22
+ describe('constructor', () => {
23
+ it('should set default log level to info', () => {
24
+ logger = new DefaultLogger();
25
+ logger.error('test');
26
+ logger.warn('test');
27
+ logger.info('test');
28
+ logger.debug('test');
29
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test');
30
+ expect(consoleWarnSpy).toHaveBeenCalledWith('[WARN] test');
31
+ expect(consoleInfoSpy).toHaveBeenCalledWith('[INFO] test');
32
+ expect(consoleDebugSpy).not.toHaveBeenCalled();
33
+ });
34
+ it('should respect custom log level', () => {
35
+ logger = new DefaultLogger('debug');
36
+ logger.error('test');
37
+ logger.warn('test');
38
+ logger.info('test');
39
+ logger.debug('test');
40
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test');
41
+ expect(consoleWarnSpy).toHaveBeenCalledWith('[WARN] test');
42
+ expect(consoleInfoSpy).toHaveBeenCalledWith('[INFO] test');
43
+ expect(consoleDebugSpy).toHaveBeenCalledWith('[DEBUG] test');
44
+ });
45
+ });
46
+ describe('setLogLevel', () => {
47
+ beforeEach(() => {
48
+ logger = new DefaultLogger();
49
+ });
50
+ it('should update log level', () => {
51
+ logger.setLogLevel('error');
52
+ logger.error('test');
53
+ logger.warn('test');
54
+ logger.info('test');
55
+ logger.debug('test');
56
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test');
57
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
58
+ expect(consoleInfoSpy).not.toHaveBeenCalled();
59
+ expect(consoleDebugSpy).not.toHaveBeenCalled();
60
+ });
61
+ });
62
+ describe('logging methods', () => {
63
+ describe('error level', () => {
64
+ beforeEach(() => {
65
+ logger = new DefaultLogger('error');
66
+ });
67
+ it('should only log errors', () => {
68
+ logger.error('test error');
69
+ logger.warn('test warn');
70
+ logger.info('test info');
71
+ logger.debug('test debug');
72
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test error');
73
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
74
+ expect(consoleInfoSpy).not.toHaveBeenCalled();
75
+ expect(consoleDebugSpy).not.toHaveBeenCalled();
76
+ });
77
+ it('should handle additional arguments', () => {
78
+ const error = new Error('test');
79
+ logger.error('test error', { details: 'more info' }, error);
80
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test error', { details: 'more info' }, error);
81
+ });
82
+ });
83
+ describe('warn level', () => {
84
+ beforeEach(() => {
85
+ logger = new DefaultLogger('warn');
86
+ });
87
+ it('should log errors and warnings', () => {
88
+ logger.error('test error');
89
+ logger.warn('test warn');
90
+ logger.info('test info');
91
+ logger.debug('test debug');
92
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test error');
93
+ expect(consoleWarnSpy).toHaveBeenCalledWith('[WARN] test warn');
94
+ expect(consoleInfoSpy).not.toHaveBeenCalled();
95
+ expect(consoleDebugSpy).not.toHaveBeenCalled();
96
+ });
97
+ });
98
+ describe('info level', () => {
99
+ beforeEach(() => {
100
+ logger = new DefaultLogger('info');
101
+ });
102
+ it('should log errors, warnings, and info', () => {
103
+ logger.error('test error');
104
+ logger.warn('test warn');
105
+ logger.info('test info');
106
+ logger.debug('test debug');
107
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test error');
108
+ expect(consoleWarnSpy).toHaveBeenCalledWith('[WARN] test warn');
109
+ expect(consoleInfoSpy).toHaveBeenCalledWith('[INFO] test info');
110
+ expect(consoleDebugSpy).not.toHaveBeenCalled();
111
+ });
112
+ });
113
+ describe('debug level', () => {
114
+ beforeEach(() => {
115
+ logger = new DefaultLogger('debug');
116
+ });
117
+ it('should log all levels', () => {
118
+ logger.error('test error');
119
+ logger.warn('test warn');
120
+ logger.info('test info');
121
+ logger.debug('test debug');
122
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[ERROR] test error');
123
+ expect(consoleWarnSpy).toHaveBeenCalledWith('[WARN] test warn');
124
+ expect(consoleInfoSpy).toHaveBeenCalledWith('[INFO] test info');
125
+ expect(consoleDebugSpy).toHaveBeenCalledWith('[DEBUG] test debug');
126
+ });
127
+ });
128
+ });
129
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hashgraph/hedera-wallet-connect",
3
- "version": "1.3.7-canary.813a6d2.0",
3
+ "version": "1.3.7-canary.de9fb58.0",
4
4
  "description": "A library to facilitate integrating Hedera with WalletConnect",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,6 +32,7 @@
32
32
  "husky": "^9.0.6",
33
33
  "jest": "^29.7.0",
34
34
  "lint-staged": "^15.1.0",
35
+ "long": "^5.2.3",
35
36
  "lokijs": "^1.5.12",
36
37
  "nodemon": "^3.0.3",
37
38
  "prettier": "^3.2.4",
@@ -61,7 +62,9 @@
61
62
  "prettier:check": "prettier --check ./src/",
62
63
  "prettier:fix": "prettier --write ./src/",
63
64
  "prod:docs-docker": "sh docker-run.sh",
64
- "test:sigMap": "jest --testMatch '**/SignatureMapHelpers.test.ts' --verbose"
65
+ "test:sigMap": "jest --testMatch '**/SignatureMapHelpers.test.ts' --verbose",
66
+ "test:coverage": "jest --coverage",
67
+ "test:coverage:html": "jest --coverage --coverageReporters='text-summary' --coverageReporters='html'"
65
68
  },
66
69
  "peerDependencies": {
67
70
  "@hashgraph/sdk": "^2.40.0",