@hashgraphonline/hashinal-wc 1.0.117-canary.0 → 1.0.118-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js DELETED
@@ -1,771 +0,0 @@
1
- function ensureGlobalHTMLElement() {
2
- if (typeof globalThis === 'undefined') {
3
- return;
4
- }
5
- if (typeof globalThis.HTMLElement === 'undefined') {
6
- globalThis.HTMLElement = class {
7
- };
8
- }
9
- }
10
- ensureGlobalHTMLElement();
11
- import { Buffer } from 'buffer';
12
- import { TransferTransaction, TopicMessageSubmitTransaction, ContractExecuteTransaction, Hbar, TransactionId, AccountId, TopicId, ContractId, LedgerId, TokenCreateTransaction, TokenType, TokenSupplyType, TokenMintTransaction, TopicCreateTransaction, PrivateKey, AccountCreateTransaction, TokenAssociateTransaction, TokenDissociateTransaction, AccountUpdateTransaction, AccountAllowanceApproveTransaction, TokenId, } from '@hashgraph/sdk';
13
- import * as HashgraphSDK from '@hashgraph/sdk';
14
- import { HederaSessionEvent, HederaJsonRpcMethod, DAppConnector, HederaChainId, } from '@hashgraph/hedera-wallet-connect';
15
- import { Logger } from './logger';
16
- import { fetchWithRetry } from './utils/retry';
17
- class HashinalsWalletConnectSDK {
18
- get dAppConnector() {
19
- return HashinalsWalletConnectSDK.dAppConnectorInstance;
20
- }
21
- constructor(logger, network) {
22
- this.extensionCheckInterval = null;
23
- this.hasCalledExtensionCallback = false;
24
- this.logger = logger || new Logger();
25
- this.network = network || LedgerId.MAINNET;
26
- }
27
- static getInstance(logger, network) {
28
- let instance = HashinalsWalletConnectSDK?.instance;
29
- if (!instance) {
30
- HashinalsWalletConnectSDK.instance = new HashinalsWalletConnectSDK(logger, network);
31
- instance = HashinalsWalletConnectSDK.instance;
32
- }
33
- if (network) {
34
- instance.setNetwork(network);
35
- }
36
- return instance;
37
- }
38
- setLogger(logger) {
39
- this.logger = logger;
40
- }
41
- setNetwork(network) {
42
- this.network = network;
43
- }
44
- getNetwork() {
45
- return this.network;
46
- }
47
- setLogLevel(level) {
48
- if (this.logger instanceof Logger) {
49
- this.logger.setLogLevel(level);
50
- }
51
- }
52
- async init(projectId, metadata, network, onSessionIframeCreated) {
53
- const chosenNetwork = network || this.network;
54
- const isMainnet = chosenNetwork.toString() === 'mainnet';
55
- if (HashinalsWalletConnectSDK.dAppConnectorInstance) {
56
- return HashinalsWalletConnectSDK.dAppConnectorInstance;
57
- }
58
- HashinalsWalletConnectSDK.dAppConnectorInstance = new DAppConnector(metadata, chosenNetwork, projectId, Object.values(HederaJsonRpcMethod), [HederaSessionEvent.ChainChanged, HederaSessionEvent.AccountsChanged], [isMainnet ? HederaChainId.Mainnet : HederaChainId.Testnet], 'debug');
59
- await HashinalsWalletConnectSDK.dAppConnectorInstance.init({
60
- logger: 'error',
61
- });
62
- HashinalsWalletConnectSDK.dAppConnectorInstance.onSessionIframeCreated = (session) => {
63
- this.logger.info('new session from from iframe', session);
64
- this.handleNewSession(session);
65
- if (onSessionIframeCreated) {
66
- onSessionIframeCreated(session);
67
- }
68
- };
69
- this.logger.info(`Hedera Wallet Connect SDK initialized on ${chosenNetwork}`);
70
- return HashinalsWalletConnectSDK.dAppConnectorInstance;
71
- }
72
- async connect() {
73
- this.ensureInitialized();
74
- const session = await this.dAppConnector.openModal();
75
- this.handleNewSession(session);
76
- return session;
77
- }
78
- async disconnect() {
79
- try {
80
- this.ensureInitialized();
81
- const accountInfo = this.getAccountInfo();
82
- const accountId = accountInfo?.accountId;
83
- const network = accountInfo?.network;
84
- const signer = this?.dAppConnector?.signers.find((signer_) => signer_.getAccountId().toString() === accountId);
85
- await this.dAppConnector?.disconnect(signer?.topic);
86
- this.logger.info(`Disconnected from ${accountId} on ${network}`);
87
- return true;
88
- }
89
- catch (e) {
90
- this.logger.error('Failed to disconnect', e);
91
- return false;
92
- }
93
- }
94
- async disconnectAll() {
95
- try {
96
- this.ensureInitialized();
97
- await this.dAppConnector?.disconnectAll();
98
- this.logger.info(`Disconnected from all wallets`);
99
- return true;
100
- }
101
- catch (e) {
102
- this.logger.error('Failed to disconnect', e);
103
- return false;
104
- }
105
- }
106
- async executeTransaction(tx, disableSigner = false) {
107
- this.ensureInitialized();
108
- const accountInfo = this.getAccountInfo();
109
- const accountId = accountInfo?.accountId;
110
- const signer = this.dAppConnector.signers.find((signer_) => signer_.getAccountId().toString() === accountId);
111
- if (!disableSigner) {
112
- const signedTx = await tx.freezeWithSigner(signer);
113
- const executedTx = await signedTx.executeWithSigner(signer);
114
- return await executedTx.getReceiptWithSigner(signer);
115
- }
116
- else {
117
- const executedTx = await tx.executeWithSigner(signer);
118
- return await executedTx.getReceiptWithSigner(signer);
119
- }
120
- }
121
- async executeTransactionWithErrorHandling(tx, disableSigner) {
122
- try {
123
- const result = await this.executeTransaction(tx, disableSigner);
124
- return {
125
- result,
126
- error: undefined,
127
- };
128
- }
129
- catch (e) {
130
- const error = e;
131
- const message = error.message?.toLowerCase();
132
- this.logger.error('Failed to execute transaction', e);
133
- this.logger.error('Failure reason for transaction is', message);
134
- if (message.includes('insufficient payer balance')) {
135
- return {
136
- result: undefined,
137
- error: 'Insufficient balance to complete the transaction.',
138
- };
139
- }
140
- else if (message.includes('reject')) {
141
- return {
142
- result: undefined,
143
- error: 'You rejected the transaction',
144
- };
145
- }
146
- else if (message.includes('invalid signature')) {
147
- return {
148
- result: undefined,
149
- error: 'Invalid signature. Please check your account and try again.',
150
- };
151
- }
152
- else if (message.includes('transaction expired')) {
153
- return {
154
- result: undefined,
155
- error: 'Transaction expired. Please try again.',
156
- };
157
- }
158
- else if (message.includes('account not found')) {
159
- return {
160
- result: undefined,
161
- error: 'Account not found. Please check the account ID and try again.',
162
- };
163
- }
164
- else if (message.includes('unauthorized')) {
165
- return {
166
- result: undefined,
167
- error: 'Unauthorized. You may not have the necessary permissions for this action.',
168
- };
169
- }
170
- else if (message.includes('busy')) {
171
- return {
172
- result: undefined,
173
- error: 'The network is busy. Please try again later.',
174
- };
175
- }
176
- else if (message.includes('invalid transaction')) {
177
- return {
178
- result: undefined,
179
- error: 'Invalid transaction. Please check your inputs and try again.',
180
- };
181
- }
182
- }
183
- }
184
- async submitMessageToTopic(topicId, message, submitKey) {
185
- this.ensureInitialized();
186
- let transaction = new TopicMessageSubmitTransaction()
187
- .setTopicId(TopicId.fromString(topicId))
188
- .setMessage(message);
189
- if (submitKey) {
190
- transaction = await transaction.sign(submitKey);
191
- }
192
- return this.executeTransaction(transaction);
193
- }
194
- async transferHbar(fromAccountId, toAccountId, amount) {
195
- this.ensureInitialized();
196
- const transaction = new TransferTransaction()
197
- .setTransactionId(TransactionId.generate(fromAccountId))
198
- .addHbarTransfer(AccountId.fromString(fromAccountId), new Hbar(-amount))
199
- .addHbarTransfer(AccountId.fromString(toAccountId), new Hbar(amount));
200
- return this.executeTransaction(transaction);
201
- }
202
- async executeSmartContract(contractId, functionName, parameters, gas = 100000) {
203
- this.ensureInitialized();
204
- const transaction = new ContractExecuteTransaction()
205
- .setContractId(ContractId.fromString(contractId))
206
- .setGas(gas)
207
- .setFunction(functionName, parameters);
208
- return this.executeTransaction(transaction);
209
- }
210
- handleNewSession(session) {
211
- const sessionAccount = session.namespaces?.hedera?.accounts?.[0];
212
- const sessionParts = sessionAccount?.split(':');
213
- const accountId = sessionParts.pop();
214
- const network = sessionParts.pop();
215
- this.logger.info('sessionAccount is', accountId, network);
216
- if (!accountId) {
217
- this.logger.error('No account id found in the session');
218
- return;
219
- }
220
- else {
221
- this.saveConnectionInfo(accountId, network);
222
- }
223
- }
224
- getNetworkPrefix() {
225
- const accountInfo = this.getAccountInfo();
226
- const network = accountInfo?.network;
227
- if (!network) {
228
- this.logger.warn('Network is not set on SDK, defaulting.');
229
- const cachedNetwork = localStorage.getItem('connectedNetwork');
230
- if (cachedNetwork) {
231
- return cachedNetwork;
232
- }
233
- return 'mainnet-public';
234
- }
235
- if (network !== this.network) {
236
- this.logger.warn('Detected network mismatch, reverting to signer network', network);
237
- this.network = network;
238
- }
239
- return network.isMainnet() ? 'mainnet-public' : 'testnet';
240
- }
241
- async requestAccount(account) {
242
- try {
243
- const networkPrefix = this.getNetworkPrefix();
244
- const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/accounts/${account}`;
245
- const response = await fetchWithRetry()(url);
246
- if (!response.ok) {
247
- throw new Error(`Failed to make request to mirror node for account: ${response.status}`);
248
- }
249
- return await response.json();
250
- }
251
- catch (e) {
252
- this.logger.error('Failed to fetch account', e);
253
- throw e;
254
- }
255
- }
256
- async getAccountBalance() {
257
- this.ensureInitialized();
258
- const accountInfo = this.getAccountInfo();
259
- const account = accountInfo?.accountId;
260
- if (!account) {
261
- return null;
262
- }
263
- const accountResponse = await this.requestAccount(account);
264
- if (!accountResponse) {
265
- throw new Error('Failed to fetch account. Try again or check if the Account ID is valid.');
266
- }
267
- const balance = accountResponse.balance.balance / 10 ** 8;
268
- return Number(balance).toLocaleString('en-US');
269
- }
270
- getAccountInfo() {
271
- const { accountId: cachedAccountId } = this.loadConnectionInfo();
272
- if (!cachedAccountId) {
273
- return null;
274
- }
275
- const signers = this?.dAppConnector?.signers;
276
- if (!signers?.length) {
277
- return null;
278
- }
279
- const cachedSigner = this.dAppConnector.signers.find((signer_) => signer_.getAccountId().toString() === cachedAccountId);
280
- if (!cachedSigner) {
281
- return null;
282
- }
283
- const accountId = cachedSigner?.getAccountId()?.toString();
284
- if (!accountId) {
285
- return null;
286
- }
287
- const network = cachedSigner.getLedgerId();
288
- return {
289
- accountId,
290
- network,
291
- };
292
- }
293
- async createTopic(memo, adminKey, submitKey) {
294
- this.ensureInitialized();
295
- let transaction = new TopicCreateTransaction().setTopicMemo(memo || '');
296
- if (adminKey) {
297
- const adminWithPrivateKey = PrivateKey.fromString(adminKey);
298
- transaction.setAdminKey(adminWithPrivateKey.publicKey);
299
- transaction = await transaction.sign(adminWithPrivateKey);
300
- }
301
- if (submitKey) {
302
- transaction.setSubmitKey(PrivateKey.fromString(submitKey).publicKey);
303
- }
304
- const receipt = await this.executeTransaction(transaction);
305
- return receipt.topicId.toString();
306
- }
307
- async createToken(name, symbol, initialSupply, decimals, treasuryAccountId, adminKey, supplyKey) {
308
- this.ensureInitialized();
309
- let transaction = new TokenCreateTransaction()
310
- .setTokenName(name)
311
- .setTokenSymbol(symbol)
312
- .setDecimals(decimals)
313
- .setInitialSupply(initialSupply)
314
- .setTreasuryAccountId(AccountId.fromString(treasuryAccountId))
315
- .setTokenType(TokenType.NonFungibleUnique)
316
- .setSupplyType(TokenSupplyType.Finite);
317
- if (supplyKey) {
318
- transaction = transaction.setSupplyKey(PrivateKey.fromString(supplyKey));
319
- }
320
- if (adminKey) {
321
- transaction = transaction.setAdminKey(PrivateKey.fromString(adminKey));
322
- transaction = await transaction.sign(PrivateKey.fromString(adminKey));
323
- }
324
- const receipt = await this.executeTransaction(transaction);
325
- return receipt.tokenId.toString();
326
- }
327
- async mintNFT(tokenId, metadata, supplyKey) {
328
- this.ensureInitialized();
329
- let transaction = await new TokenMintTransaction()
330
- .setTokenId(tokenId)
331
- .setMetadata([Buffer.from(metadata, 'utf-8')])
332
- .sign(supplyKey);
333
- return this.executeTransaction(transaction);
334
- }
335
- async getMessages(topicId, lastTimestamp, disableTimestampFilter = false, network) {
336
- const networkPrefix = network || this.getNetworkPrefix();
337
- const baseUrl = `https://${networkPrefix}.mirrornode.hedera.com`;
338
- const timestampQuery = Number(lastTimestamp) > 0 && !disableTimestampFilter
339
- ? `&timestamp=gt:${lastTimestamp}`
340
- : '';
341
- const url = `${baseUrl}/api/v1/topics/${topicId}/messages?limit=200${timestampQuery}`;
342
- try {
343
- const response = await fetchWithRetry()(url);
344
- if (!response.ok) {
345
- throw new Error(`Failed to make request to mirror node: ${response.status}`);
346
- }
347
- const data = await response.json();
348
- const messages = data?.messages || [];
349
- const nextLink = data?.links?.next;
350
- const collectedMessages = messages.map((msg) => {
351
- const parsedMessage = JSON.parse(atob(msg.message));
352
- return {
353
- ...parsedMessage,
354
- payer: msg.payer_account_id,
355
- created: new Date(Number(msg.consensus_timestamp) * 1000),
356
- consensus_timestamp: msg.consensus_timestamp,
357
- sequence_number: msg.sequence_number,
358
- };
359
- });
360
- if (nextLink) {
361
- const nextResult = await this.getMessages(topicId, Number(collectedMessages[collectedMessages.length - 1]?.consensus_timestamp), disableTimestampFilter);
362
- collectedMessages.push(...nextResult.messages);
363
- }
364
- return {
365
- messages: collectedMessages.sort((a, b) => a.sequence_number - b.sequence_number),
366
- error: '',
367
- };
368
- }
369
- catch (error) {
370
- this.logger.error('Error fetching topic data:', error);
371
- return {
372
- messages: [],
373
- error: error.toString(),
374
- };
375
- }
376
- }
377
- async signMessage(message) {
378
- const dAppConnector = this.dAppConnector;
379
- if (!dAppConnector) {
380
- throw new Error('No active connection or signer');
381
- }
382
- const accountInfo = this.getAccountInfo();
383
- const accountId = accountInfo?.accountId;
384
- const params = {
385
- signerAccountId: `hedera:${this.network}:${accountId}`,
386
- message,
387
- };
388
- const result = (await dAppConnector.signMessage(params));
389
- // @ts-ignore
390
- return { userSignature: result.signatureMap };
391
- }
392
- saveConnectionInfo(accountId, connectedNetwork) {
393
- if (!accountId) {
394
- localStorage.removeItem('connectedAccountId');
395
- localStorage.removeItem('connectedNetwork');
396
- }
397
- else {
398
- const cleanNetwork = connectedNetwork?.replace(/['"]+/g, '');
399
- localStorage.setItem('connectedNetwork', cleanNetwork);
400
- localStorage.setItem('connectedAccountId', accountId);
401
- }
402
- }
403
- loadConnectionInfo() {
404
- return {
405
- accountId: localStorage.getItem('connectedAccountId'),
406
- network: localStorage.getItem('connectedNetwork'),
407
- };
408
- }
409
- async connectWallet(PROJECT_ID, APP_METADATA, network) {
410
- try {
411
- await this.init(PROJECT_ID, APP_METADATA, network);
412
- const session = await this.connect();
413
- const accountInfo = this.getAccountInfo();
414
- const accountId = accountInfo?.accountId;
415
- const balance = await this.getAccountBalance();
416
- const networkPrefix = this.getNetworkPrefix();
417
- this.saveConnectionInfo(accountId, networkPrefix);
418
- return {
419
- accountId,
420
- balance,
421
- session,
422
- };
423
- }
424
- catch (error) {
425
- this.logger.error('Failed to connect wallet:', error);
426
- throw error;
427
- }
428
- }
429
- async disconnectWallet(clearStorage = true) {
430
- try {
431
- const success = await this.disconnect();
432
- if (success && clearStorage) {
433
- localStorage.clear();
434
- }
435
- this.saveConnectionInfo(undefined);
436
- return success;
437
- }
438
- catch (error) {
439
- this.logger.error('Failed to disconnect wallet:', error);
440
- return false;
441
- }
442
- }
443
- async initAccount(PROJECT_ID, APP_METADATA, networkOverride, onSessionIframeCreated = () => { }) {
444
- const { accountId: savedAccountId, network: savedNetwork } = this.loadConnectionInfo();
445
- if (savedAccountId && savedNetwork) {
446
- try {
447
- const defaultNetwork = savedNetwork === 'mainnet' ? LedgerId.MAINNET : LedgerId.TESTNET;
448
- const network = networkOverride || defaultNetwork;
449
- await this.init(PROJECT_ID, APP_METADATA, network, onSessionIframeCreated);
450
- const balance = await this.getAccountBalance();
451
- return {
452
- accountId: savedAccountId,
453
- balance,
454
- };
455
- }
456
- catch (error) {
457
- this.logger.error('Failed to reconnect:', error);
458
- this.saveConnectionInfo(undefined, undefined);
459
- return null;
460
- }
461
- }
462
- else if (networkOverride) {
463
- try {
464
- this.logger.info('initializing normally through override.', networkOverride);
465
- await this.init(PROJECT_ID, APP_METADATA, networkOverride, onSessionIframeCreated);
466
- this.logger.info('initialized', networkOverride);
467
- await this.connectViaDappBrowser();
468
- this.logger.info('connected via dapp browser');
469
- }
470
- catch (error) {
471
- this.logger.error('Failed to fallback connect:', error);
472
- this.saveConnectionInfo(undefined, undefined);
473
- return null;
474
- }
475
- }
476
- return null;
477
- }
478
- subscribeToExtensions(callback) {
479
- // Clear any existing interval and reset flag
480
- if (this.extensionCheckInterval) {
481
- clearInterval(this.extensionCheckInterval);
482
- }
483
- this.hasCalledExtensionCallback = false;
484
- // Set up polling to check for extensions
485
- this.extensionCheckInterval = setInterval(() => {
486
- const extensions = this.dAppConnector?.extensions || [];
487
- const availableExtension = extensions.find((ext) => ext.availableInIframe);
488
- if (availableExtension && !this.hasCalledExtensionCallback) {
489
- this.hasCalledExtensionCallback = true;
490
- callback(availableExtension);
491
- // Clear the interval once we find an available extension
492
- if (this.extensionCheckInterval) {
493
- clearInterval(this.extensionCheckInterval);
494
- this.extensionCheckInterval = null;
495
- }
496
- }
497
- }, 1000); // Check every second
498
- // Return cleanup function
499
- return () => {
500
- if (this.extensionCheckInterval) {
501
- clearInterval(this.extensionCheckInterval);
502
- this.extensionCheckInterval = null;
503
- }
504
- this.hasCalledExtensionCallback = false;
505
- };
506
- }
507
- async connectViaDappBrowser() {
508
- const extensions = this.dAppConnector.extensions || [];
509
- const extension = extensions.find((ext) => {
510
- this.logger.info('Checking extension', ext);
511
- return ext.availableInIframe;
512
- });
513
- this.logger.info('extensions are', extensions, extension);
514
- if (extension) {
515
- await this.connectToExtension(extension);
516
- }
517
- else {
518
- // If no extension is immediately available, subscribe to changes
519
- this.subscribeToExtensions(async (newExtension) => {
520
- await this.connectToExtension(newExtension);
521
- });
522
- }
523
- }
524
- async connectToExtension(extension) {
525
- this.logger.info('found extension, connecting to iframe.', extension);
526
- const session = await this.dAppConnector.connectExtension(extension.id);
527
- const onSessionIframeCreated = this.dAppConnector.onSessionIframeCreated;
528
- if (onSessionIframeCreated) {
529
- onSessionIframeCreated(session);
530
- }
531
- }
532
- ensureInitialized() {
533
- if (!this.dAppConnector) {
534
- throw new Error('SDK not initialized. Call init() first.');
535
- }
536
- }
537
- static run() {
538
- try {
539
- if (typeof window !== 'undefined') {
540
- window.HashinalsWalletConnectSDK =
541
- HashinalsWalletConnectSDK.getInstance();
542
- window.HashgraphSDK = HashgraphSDK;
543
- }
544
- }
545
- catch (e) {
546
- console.error('[ERROR]: failed setting sdk on window');
547
- }
548
- }
549
- async transferToken(tokenId, fromAccountId, toAccountId, amount) {
550
- this.ensureInitialized();
551
- const transaction = new TransferTransaction()
552
- .setTransactionId(TransactionId.generate(fromAccountId))
553
- .addTokenTransfer(TokenId.fromString(tokenId), AccountId.fromString(fromAccountId), -amount)
554
- .addTokenTransfer(TokenId.fromString(tokenId), AccountId.fromString(toAccountId), amount);
555
- return this.executeTransaction(transaction);
556
- }
557
- async createAccount(initialBalance) {
558
- this.ensureInitialized();
559
- const transaction = new AccountCreateTransaction().setInitialBalance(new Hbar(initialBalance));
560
- return this.executeTransaction(transaction);
561
- }
562
- async associateTokenToAccount(accountId, tokenId) {
563
- this.ensureInitialized();
564
- const transaction = new TokenAssociateTransaction()
565
- .setAccountId(AccountId.fromString(accountId))
566
- .setTokenIds([TokenId.fromString(tokenId)]);
567
- return this.executeTransaction(transaction);
568
- }
569
- async dissociateTokenFromAccount(accountId, tokenId) {
570
- this.ensureInitialized();
571
- const transaction = new TokenDissociateTransaction()
572
- .setAccountId(AccountId.fromString(accountId))
573
- .setTokenIds([TokenId.fromString(tokenId)]);
574
- return this.executeTransaction(transaction);
575
- }
576
- async updateAccount(accountId, maxAutomaticTokenAssociations) {
577
- this.ensureInitialized();
578
- const transaction = new AccountUpdateTransaction()
579
- .setAccountId(AccountId.fromString(accountId))
580
- .setMaxAutomaticTokenAssociations(maxAutomaticTokenAssociations);
581
- return this.executeTransaction(transaction);
582
- }
583
- async approveAllowance(spenderAccountId, tokenId, amount, ownerAccountId) {
584
- this.ensureInitialized();
585
- const transaction = new AccountAllowanceApproveTransaction().approveTokenAllowance(TokenId.fromString(tokenId), AccountId.fromString(ownerAccountId), AccountId.fromString(spenderAccountId), amount);
586
- return this.executeTransaction(transaction);
587
- }
588
- async getAccountTokens(accountId) {
589
- this.ensureInitialized();
590
- const networkPrefix = this.getNetworkPrefix();
591
- const baseUrl = `https://${networkPrefix}.mirrornode.hedera.com`;
592
- const url = `${baseUrl}/api/v1/accounts/${accountId}/tokens?limit=200`;
593
- try {
594
- const response = await fetchWithRetry()(url);
595
- if (!response.ok) {
596
- throw new Error(`Failed to make request to mirror node for account tokens: ${response.status}`);
597
- }
598
- const data = await response.json();
599
- const tokens = [];
600
- for (const token of data.tokens) {
601
- if (token.token_id) {
602
- tokens.push({
603
- tokenId: token.token_id,
604
- balance: token.balance,
605
- decimals: token.decimals,
606
- formatted_balance: (token.balance /
607
- 10 ** token.decimals).toLocaleString('en-US'),
608
- created_timestamp: new Date(Number(token.created_timestamp) * 1000),
609
- });
610
- }
611
- }
612
- let nextLink = data.links?.next;
613
- while (nextLink) {
614
- const nextUrl = `${baseUrl}${nextLink}`;
615
- const nextResponse = await fetchWithRetry()(nextUrl);
616
- if (!nextResponse.ok) {
617
- throw new Error(`Failed to make request to mirror node for account tokens: ${nextResponse.status}, page: ${nextUrl}`);
618
- }
619
- const nextData = await nextResponse.json();
620
- for (const token of nextData.tokens) {
621
- if (token.token_id) {
622
- tokens.push({
623
- tokenId: token.token_id,
624
- balance: token.balance,
625
- decimals: token.decimals,
626
- formatted_balance: (token.balance /
627
- 10 ** token.decimals).toLocaleString('en-US'),
628
- created_timestamp: new Date(Number(token.created_timestamp) * 1000),
629
- });
630
- }
631
- }
632
- nextLink = nextData.links?.next;
633
- }
634
- return { tokens };
635
- }
636
- catch (error) {
637
- this.logger.error('Error fetching account tokens:', error);
638
- throw error;
639
- }
640
- }
641
- async getTransaction(transactionId) {
642
- try {
643
- const networkPrefix = this.getNetworkPrefix();
644
- const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions/${transactionId}`;
645
- this.logger.debug('Fetching transaction', url);
646
- const request = await fetchWithRetry()(url);
647
- if (!request.ok) {
648
- throw new Error(`Failed to fetch transaction: ${request.status}`);
649
- }
650
- return await request.json();
651
- }
652
- catch (e) {
653
- this.logger.error('Failed to get transaction', e);
654
- return null;
655
- }
656
- }
657
- async getTransactionByTimestamp(timestamp) {
658
- try {
659
- const networkPrefix = this.getNetworkPrefix();
660
- const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions?timestamp=${timestamp}`;
661
- this.logger.debug('Fetching transaction by timestamp', url);
662
- const request = await fetchWithRetry()(url);
663
- if (!request.ok) {
664
- throw new Error(`Failed to fetch transaction by timestamp: ${request.status}`);
665
- }
666
- const response = (await request.json());
667
- const transaction = response?.transactions?.[0];
668
- if (transaction) {
669
- return await this.getTransaction(transaction.transaction_id);
670
- }
671
- return null;
672
- }
673
- catch (e) {
674
- this.logger.error('Failed to get transaction by timestamp', e);
675
- return null;
676
- }
677
- }
678
- async getAccountNFTs(accountId, tokenId) {
679
- try {
680
- const networkPrefix = this.getNetworkPrefix();
681
- const tokenQuery = tokenId ? `&token.id=${tokenId}` : '';
682
- const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/accounts/${accountId}/nfts?limit=200${tokenQuery}`;
683
- const request = await fetchWithRetry()(url);
684
- if (!request.ok) {
685
- throw new Error(`Failed to fetch NFTs for account: ${request.status}`);
686
- }
687
- const response = (await request.json());
688
- let nextLink = response?.links?.next || null;
689
- let nfts = (response.nfts || []);
690
- while (nextLink) {
691
- try {
692
- const nextRequest = await fetchWithRetry()(`https://${networkPrefix}.mirrornode.hedera.com${nextLink}`);
693
- if (!nextRequest.ok) {
694
- throw new Error(`Failed to fetch next page of NFTs: ${nextRequest.status}`);
695
- }
696
- const nextResponse = (await nextRequest.json());
697
- const nextNfts = (nextResponse?.nfts || []);
698
- nfts = [...nfts, ...nextNfts];
699
- nextLink =
700
- nextResponse?.links?.next && nextLink !== nextResponse?.links?.next
701
- ? nextResponse.links.next
702
- : null;
703
- }
704
- catch (e) {
705
- this.logger.error('Failed to fetch next page of NFTs', e);
706
- break;
707
- }
708
- }
709
- return nfts.map((nft) => {
710
- try {
711
- nft.token_uri = Buffer.from(nft.metadata, 'base64').toString('ascii');
712
- }
713
- catch (e) {
714
- this.logger.error('Failed to decode NFT metadata', e);
715
- }
716
- return nft;
717
- });
718
- }
719
- catch (e) {
720
- this.logger.error('Failed to get account NFTs', e);
721
- return [];
722
- }
723
- }
724
- async validateNFTOwnership(serialNumber, accountId, tokenId) {
725
- const userNFTs = await this.getAccountNFTs(accountId, tokenId);
726
- return (userNFTs.find((nft) => nft.token_id === tokenId &&
727
- nft.serial_number.toString() === serialNumber) || null);
728
- }
729
- async readSmartContract(data, fromAccount, contractId, estimate = true, value = 0) {
730
- try {
731
- const networkPrefix = this.getNetworkPrefix();
732
- const body = {
733
- block: 'latest',
734
- data: data,
735
- estimate: estimate,
736
- from: fromAccount.toSolidityAddress(),
737
- to: contractId.toSolidityAddress(),
738
- value,
739
- };
740
- if (!estimate) {
741
- body.gas = 300000;
742
- body.gasPrice = 100000000;
743
- }
744
- const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/contracts/call`;
745
- const response = await fetchWithRetry()(url, {
746
- method: 'POST',
747
- body: JSON.stringify(body),
748
- headers: {
749
- 'Content-Type': 'application/json',
750
- },
751
- });
752
- if (!response.ok) {
753
- throw new Error(`Failed to make contract call: ${response.status}`);
754
- }
755
- return await response.json();
756
- }
757
- catch (e) {
758
- this.logger.error('Failed to make contract call', e);
759
- return null;
760
- }
761
- }
762
- }
763
- // This variable is replaced at build time.
764
- // @ts-ignore
765
- if ('VITE_BUILD_FORMAT' === 'umd') {
766
- HashinalsWalletConnectSDK.run();
767
- }
768
- export * from './types';
769
- export * from './sign';
770
- export { HashinalsWalletConnectSDK, HashgraphSDK };
771
- //# sourceMappingURL=index.js.map