@hashgraphonline/hashinal-wc 1.0.86 → 1.0.88

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/README.md CHANGED
@@ -18,6 +18,10 @@ This SDK provides a simple interface for interacting with the Hedera Hashgraph u
18
18
  - Dissociate tokens from accounts
19
19
  - Update account properties
20
20
  - Approve token allowances
21
+ - Get transaction details by transaction ID or timestamp from the mirror node
22
+ - Get account NFTs with optional filtering by token ID
23
+ - Validate NFT ownership by serial number and token ID
24
+ - Make read-only calls to smart contracts on the mirror node
21
25
 
22
26
  ## Installation
23
27
 
@@ -518,6 +522,109 @@ const tokens = await sdk.getAccountTokens(accountId);
518
522
  console.log('Account tokens:', tokens);
519
523
  ```
520
524
 
525
+ ### `getTransaction(transactionId: string)`
526
+
527
+ Retrieves transaction details by transaction ID from the mirror node.
528
+
529
+ UMD Example:
530
+
531
+ ```javascript
532
+ const transactionId = "0.0.123456@1234567890.000000000";
533
+ const transaction = await window.HashinalsWalletConnectSDK.getTransaction(transactionId);
534
+ console.log(transaction);
535
+ ```
536
+
537
+ ESM Example:
538
+
539
+ ```javascript
540
+ const transaction = await sdk.getTransaction(transactionId);
541
+ ```
542
+
543
+ ### `getTransactionByTimestamp(timestamp: string)`
544
+
545
+ Retrieves transaction details by consensus timestamp from the mirror node.
546
+
547
+ UMD Example:
548
+
549
+ ```javascript
550
+ const timestamp = "1234567890.000000000";
551
+ const transaction = await window.HashinalsWalletConnectSDK.getTransactionByTimestamp(timestamp);
552
+ console.log(transaction);
553
+ ```
554
+
555
+ ESM Example:
556
+
557
+ ```javascript
558
+ const transaction = await sdk.getTransactionByTimestamp(timestamp);
559
+ ```
560
+
561
+ ### `getAccountNFTs(accountId: string, tokenId?: string)`
562
+
563
+ Retrieves all NFTs owned by an account, with optional filtering by token ID.
564
+
565
+ UMD Example:
566
+
567
+ ```javascript
568
+ const accountId = "0.0.123456";
569
+ const nfts = await window.HashinalsWalletConnectSDK.getAccountNFTs(accountId);
570
+ console.log(nfts);
571
+
572
+ // With token filter
573
+ const tokenId = "0.0.789012";
574
+ const filteredNfts = await window.HashinalsWalletConnectSDK.getAccountNFTs(accountId, tokenId);
575
+ ```
576
+
577
+ ESM Example:
578
+
579
+ ```javascript
580
+ const nfts = await sdk.getAccountNFTs(accountId);
581
+ const filteredNfts = await sdk.getAccountNFTs(accountId, tokenId);
582
+ ```
583
+
584
+ ### `validateNFTOwnership(serialNumber: string, accountId: string, tokenId: string)`
585
+
586
+ Validates if an account owns a specific NFT by serial number and token ID.
587
+
588
+ UMD Example:
589
+
590
+ ```javascript
591
+ const serialNumber = "1";
592
+ const accountId = "0.0.123456";
593
+ const tokenId = "0.0.789012";
594
+ const nft = await window.HashinalsWalletConnectSDK.validateNFTOwnership(serialNumber, accountId, tokenId);
595
+ console.log(nft ? "Account owns this NFT" : "Account does not own this NFT");
596
+ ```
597
+
598
+ ESM Example:
599
+
600
+ ```javascript
601
+ const nft = await sdk.validateNFTOwnership(serialNumber, accountId, tokenId);
602
+ ```
603
+
604
+ ### `readSmartContract(data: string, fromAccount: AccountId, contractId: ContractId, estimate?: boolean, value?: number)`
605
+
606
+ Makes a read-only call to a smart contract on the mirror node.
607
+
608
+ UMD Example:
609
+
610
+ ```javascript
611
+ const data = "0x..."; // Contract call data
612
+ const fromAccount = window.HashgraphSDK.AccountId.fromString("0.0.123456");
613
+ const contractId = window.HashgraphSDK.ContractId.fromString("0.0.789012");
614
+ const result = await window.HashinalsWalletConnectSDK.readSmartContract(data, fromAccount, contractId);
615
+ console.log(result);
616
+ ```
617
+
618
+ ESM Example:
619
+
620
+ ```javascript
621
+ import { AccountId, ContractId } from '@hashgraph/sdk';
622
+
623
+ const fromAccount = AccountId.fromString("0.0.123456");
624
+ const contractId = ContractId.fromString("0.0.789012");
625
+ const result = await sdk.readSmartContract(data, fromAccount, contractId);
626
+ ```
627
+
521
628
  ## Versions and Topic IDs
522
629
 
523
630
  Version 1.0.58 and onward correlate with the NPM Package version.
@@ -532,6 +639,8 @@ Version 1.0.58 and onward correlate with the NPM Package version.
532
639
  | v1.0.71 | 0.0.7337015 | UMD |
533
640
  | v1.0.79 | 0.0.7473819 | UMD |
534
641
  | v1.0.82 | 0.0.7522981 | UMD |
642
+ | v1.0.86 | 0.0.7770334 | UMD |
643
+ | v1.0.88 | 0.0.7797532 | UMD |
535
644
 
536
645
  ## Contributing
537
646
 
@@ -1810,13 +1810,15 @@ var Result = /* @__PURE__ */ ((Result2) => {
1810
1810
  return Result2;
1811
1811
  })(Result || {});
1812
1812
  class HashinalsWalletConnectSDK {
1813
- get dAppConnector() {
1814
- return HashinalsWalletConnectSDK.dAppConnectorInstance;
1815
- }
1816
1813
  constructor(logger, network) {
1814
+ this.extensionCheckInterval = null;
1815
+ this.hasCalledExtensionCallback = false;
1817
1816
  this.logger = logger || new DefaultLogger();
1818
1817
  this.network = network || LedgerId.MAINNET;
1819
1818
  }
1819
+ get dAppConnector() {
1820
+ return HashinalsWalletConnectSDK.dAppConnectorInstance;
1821
+ }
1820
1822
  static getInstance(logger, network) {
1821
1823
  let instance = HashinalsWalletConnectSDK == null ? void 0 : HashinalsWalletConnectSDK.instance;
1822
1824
  if (!instance) {
@@ -2235,12 +2237,13 @@ class HashinalsWalletConnectSDK {
2235
2237
  return false;
2236
2238
  }
2237
2239
  }
2238
- async initAccount(PROJECT_ID, APP_METADATA) {
2240
+ async initAccount(PROJECT_ID, APP_METADATA, networkOverride, onSessionIframeCreated = () => {
2241
+ }) {
2239
2242
  const { accountId: savedAccountId, network: savedNetwork } = this.loadConnectionInfo();
2240
2243
  if (savedAccountId && savedNetwork) {
2241
2244
  try {
2242
2245
  const network = savedNetwork === "mainnet" ? LedgerId.MAINNET : LedgerId.TESTNET;
2243
- await this.init(PROJECT_ID, APP_METADATA, network);
2246
+ await this.init(PROJECT_ID, APP_METADATA, network, onSessionIframeCreated);
2244
2247
  const balance = await this.getAccountBalance();
2245
2248
  return {
2246
2249
  accountId: savedAccountId,
@@ -2251,9 +2254,70 @@ class HashinalsWalletConnectSDK {
2251
2254
  this.saveConnectionInfo(void 0, void 0);
2252
2255
  return null;
2253
2256
  }
2257
+ } else if (networkOverride) {
2258
+ try {
2259
+ this.logger.info("initializing normally through override.", networkOverride);
2260
+ await this.init(PROJECT_ID, APP_METADATA, networkOverride, onSessionIframeCreated);
2261
+ this.logger.info("initialized", networkOverride);
2262
+ await this.connectViaDappBrowser();
2263
+ this.logger.info("connected via dapp browser");
2264
+ } catch (error) {
2265
+ this.logger.error("Failed to fallback connect:", error);
2266
+ this.saveConnectionInfo(void 0, void 0);
2267
+ return null;
2268
+ }
2254
2269
  }
2255
2270
  return null;
2256
2271
  }
2272
+ subscribeToExtensions(callback) {
2273
+ if (this.extensionCheckInterval) {
2274
+ clearInterval(this.extensionCheckInterval);
2275
+ }
2276
+ this.hasCalledExtensionCallback = false;
2277
+ this.extensionCheckInterval = setInterval(() => {
2278
+ var _a;
2279
+ const extensions = ((_a = this.dAppConnector) == null ? void 0 : _a.extensions) || [];
2280
+ const availableExtension = extensions.find((ext) => ext.availableInIframe);
2281
+ if (availableExtension && !this.hasCalledExtensionCallback) {
2282
+ this.hasCalledExtensionCallback = true;
2283
+ callback(availableExtension);
2284
+ if (this.extensionCheckInterval) {
2285
+ clearInterval(this.extensionCheckInterval);
2286
+ this.extensionCheckInterval = null;
2287
+ }
2288
+ }
2289
+ }, 1e3);
2290
+ return () => {
2291
+ if (this.extensionCheckInterval) {
2292
+ clearInterval(this.extensionCheckInterval);
2293
+ this.extensionCheckInterval = null;
2294
+ }
2295
+ this.hasCalledExtensionCallback = false;
2296
+ };
2297
+ }
2298
+ async connectViaDappBrowser() {
2299
+ const extensions = this.dAppConnector.extensions || [];
2300
+ const extension = extensions.find((ext) => {
2301
+ this.logger.info("Checking extension", ext);
2302
+ return ext.availableInIframe;
2303
+ });
2304
+ this.logger.info("extensions are", extensions, extension);
2305
+ if (extension) {
2306
+ await this.connectToExtension(extension);
2307
+ } else {
2308
+ this.subscribeToExtensions(async (newExtension) => {
2309
+ await this.connectToExtension(newExtension);
2310
+ });
2311
+ }
2312
+ }
2313
+ async connectToExtension(extension) {
2314
+ this.logger.info("found extension, connecting to iframe.", extension);
2315
+ const session = await this.dAppConnector.connectExtension(extension.id);
2316
+ const onSessionIframeCreated = this.dAppConnector.onSessionIframeCreated;
2317
+ if (onSessionIframeCreated) {
2318
+ onSessionIframeCreated(session);
2319
+ }
2320
+ }
2257
2321
  ensureInitialized() {
2258
2322
  if (!this.dAppConnector) {
2259
2323
  throw new Error("SDK not initialized. Call init() first.");
@@ -2371,6 +2435,126 @@ class HashinalsWalletConnectSDK {
2371
2435
  throw error;
2372
2436
  }
2373
2437
  }
2438
+ async getTransaction(transactionId) {
2439
+ try {
2440
+ const networkPrefix = this.getNetworkPrefix();
2441
+ const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions/${transactionId}`;
2442
+ this.logger.debug("Fetching transaction", url);
2443
+ const request = await fetchWithRetry()(url);
2444
+ if (!request.ok) {
2445
+ throw new Error(`Failed to fetch transaction: ${request.status}`);
2446
+ }
2447
+ return await request.json();
2448
+ } catch (e) {
2449
+ this.logger.error("Failed to get transaction", e);
2450
+ return null;
2451
+ }
2452
+ }
2453
+ async getTransactionByTimestamp(timestamp) {
2454
+ var _a;
2455
+ try {
2456
+ const networkPrefix = this.getNetworkPrefix();
2457
+ const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/transactions?timestamp=${timestamp}`;
2458
+ this.logger.debug("Fetching transaction by timestamp", url);
2459
+ const request = await fetchWithRetry()(url);
2460
+ if (!request.ok) {
2461
+ throw new Error(
2462
+ `Failed to fetch transaction by timestamp: ${request.status}`
2463
+ );
2464
+ }
2465
+ const response = await request.json();
2466
+ const transaction = (_a = response == null ? void 0 : response.transactions) == null ? void 0 : _a[0];
2467
+ if (transaction) {
2468
+ return await this.getTransaction(transaction.transaction_id);
2469
+ }
2470
+ return null;
2471
+ } catch (e) {
2472
+ this.logger.error("Failed to get transaction by timestamp", e);
2473
+ return null;
2474
+ }
2475
+ }
2476
+ async getAccountNFTs(accountId, tokenId) {
2477
+ var _a, _b, _c;
2478
+ try {
2479
+ const networkPrefix = this.getNetworkPrefix();
2480
+ const tokenQuery = tokenId ? `&token.id=${tokenId}` : "";
2481
+ const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/accounts/${accountId}/nfts?limit=200${tokenQuery}`;
2482
+ const request = await fetchWithRetry()(url);
2483
+ if (!request.ok) {
2484
+ throw new Error(`Failed to fetch NFTs for account: ${request.status}`);
2485
+ }
2486
+ const response = await request.json();
2487
+ let nextLink = ((_a = response == null ? void 0 : response.links) == null ? void 0 : _a.next) || null;
2488
+ let nfts = response.nfts;
2489
+ while (nextLink) {
2490
+ try {
2491
+ const nextRequest = await fetchWithRetry()(
2492
+ `https://${networkPrefix}.mirrornode.hedera.com${nextLink}`
2493
+ );
2494
+ if (!nextRequest.ok) {
2495
+ throw new Error(
2496
+ `Failed to fetch next page of NFTs: ${nextRequest.status}`
2497
+ );
2498
+ }
2499
+ const nextResponse = await nextRequest.json();
2500
+ nfts = [...nfts, ...(nextResponse == null ? void 0 : nextResponse.nfts) || []];
2501
+ nextLink = ((_b = nextResponse == null ? void 0 : nextResponse.links) == null ? void 0 : _b.next) && nextLink !== ((_c = nextResponse == null ? void 0 : nextResponse.links) == null ? void 0 : _c.next) ? nextResponse.links.next : null;
2502
+ } catch (e) {
2503
+ this.logger.error("Failed to fetch next page of NFTs", e);
2504
+ break;
2505
+ }
2506
+ }
2507
+ return nfts.map((nft) => {
2508
+ try {
2509
+ nft.token_uri = Buffer$1.from(nft.metadata, "base64").toString("ascii");
2510
+ } catch (e) {
2511
+ this.logger.error("Failed to decode NFT metadata", e);
2512
+ }
2513
+ return nft;
2514
+ });
2515
+ } catch (e) {
2516
+ this.logger.error("Failed to get account NFTs", e);
2517
+ return [];
2518
+ }
2519
+ }
2520
+ async validateNFTOwnership(serialNumber, accountId, tokenId) {
2521
+ const userNFTs = await this.getAccountNFTs(accountId, tokenId);
2522
+ return userNFTs.find(
2523
+ (nft) => nft.token_id === tokenId && nft.serial_number.toString() === serialNumber
2524
+ ) || null;
2525
+ }
2526
+ async readSmartContract(data, fromAccount, contractId, estimate = true, value = 0) {
2527
+ try {
2528
+ const networkPrefix = this.getNetworkPrefix();
2529
+ const body = {
2530
+ block: "latest",
2531
+ data,
2532
+ estimate,
2533
+ from: fromAccount.toSolidityAddress(),
2534
+ to: contractId.toSolidityAddress(),
2535
+ value
2536
+ };
2537
+ if (!estimate) {
2538
+ body.gas = 3e5;
2539
+ body.gasPrice = 1e8;
2540
+ }
2541
+ const url = `https://${networkPrefix}.mirrornode.hedera.com/api/v1/contracts/call`;
2542
+ const response = await fetchWithRetry()(url, {
2543
+ method: "POST",
2544
+ body: JSON.stringify(body),
2545
+ headers: {
2546
+ "Content-Type": "application/json"
2547
+ }
2548
+ });
2549
+ if (!response.ok) {
2550
+ throw new Error(`Failed to make contract call: ${response.status}`);
2551
+ }
2552
+ return await response.json();
2553
+ } catch (e) {
2554
+ this.logger.error("Failed to make contract call", e);
2555
+ return null;
2556
+ }
2557
+ }
2374
2558
  }
2375
2559
  export {
2376
2560
  HashgraphSDK,