@abstraxn/signer-react 1.0.1 → 1.0.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.1] - 2026-01-28
9
+
10
+ ### Added
11
+ - Added `useEstimateGas` hook for estimating gas costs for transactions
package/README.md CHANGED
@@ -109,6 +109,10 @@ function HookConnectButton() {
109
109
  - **@abstraxn/signer-core** - Core SDK (dependency)
110
110
  - **@abstraxn/signer** - Backward compatible wrapper (deprecated)
111
111
 
112
+ ## 📋 Changelog
113
+
114
+ See [CHANGELOG.md](./CHANGELOG.md) for a list of changes and version history.
115
+
112
116
  ## 📝 License
113
117
 
114
118
  MIT
@@ -8366,14 +8366,14 @@ export declare function usePrepareRawTxn(provider: PublicClient): {
8366
8366
  prepareRawTxn: ({ from, to, value, data, abi, functionName, args, }: {
8367
8367
  from: Address;
8368
8368
  to: Address;
8369
- value?: string | number;
8369
+ value?: string | number | bigint;
8370
8370
  data?: `0x${string}`;
8371
8371
  abi?: Abi;
8372
8372
  functionName?: string;
8373
8373
  args?: any[];
8374
8374
  }) => Promise<{
8375
8375
  to: Address;
8376
- value: `0x${string}`;
8376
+ value: string | bigint;
8377
8377
  data: `0x${string}`;
8378
8378
  }>;
8379
8379
  };
@@ -8390,28 +8390,35 @@ export declare function usePrepareRawTxn(provider: PublicClient): {
8390
8390
  * const { signTxn } = useSignTxn(publicClient);
8391
8391
  *
8392
8392
  * // Prepare transaction
8393
- * const rawTx = await prepareRawTxn({
8394
- * from: address!,
8395
- * to: '0x...',
8396
- * value: '0.001',
8397
- * });
8398
- *
8399
- * // Sign transaction
8393
+ * const rawTx = await prepareRawTxn({ from: address!, to: '0x...', value: '0.001' });
8394
+ * const { estimateGas } = useEstimateGas(publicClient);
8395
+ * const gasEstimate = await estimateGas({ account: address!, to: rawTx.to, data: rawTx.data, value: rawTx.value });
8396
+ * // Sign (override required; no estimation in hook)
8400
8397
  * const signedTx = await signTxn({
8401
8398
  * from: address!,
8402
- * ...rawTx, // Spread to, value, data from prepareRawTxn
8399
+ * ...rawTx,
8400
+ * override: { gasLimit: gasEstimate.gasLimit, maxFeePerGas: gasEstimate.maxFeePerGas!, maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas! },
8403
8401
  * });
8404
8402
  * ```
8405
8403
  */
8406
8404
  export declare function useSignTxn(provider: PublicClient): {
8407
- signTxn: ({ from, to, value, data, chainId, }: {
8405
+ signTxn: ({ from, to, value, data, chainId, override, }: {
8408
8406
  from: Address;
8409
8407
  to: Address;
8410
- value: `0x${string}`;
8408
+ value: string | bigint;
8411
8409
  data: `0x${string}`;
8412
8410
  chainId?: number;
8411
+ /** Gas and fees (user must pass; no estimation in hook). EIP-1559 or legacy. Use useEstimateGas to get values. */
8412
+ override: {
8413
+ gasLimit: bigint;
8414
+ maxFeePerGas: bigint;
8415
+ maxPriorityFeePerGas: bigint;
8416
+ } | {
8417
+ gasLimit: bigint;
8418
+ gasPrice: bigint;
8419
+ };
8413
8420
  }) => Promise<{
8414
- unsignedTransaction: `0x02${string}`;
8421
+ unsignedTransaction: `0x02${string}` | import("viem").TransactionSerializedLegacy;
8415
8422
  signedTransaction: string;
8416
8423
  }>;
8417
8424
  isConnected: boolean;
@@ -8430,31 +8437,37 @@ export declare function useSignTxn(provider: PublicClient): {
8430
8437
  * const { signAndSendTxn } = useSignAndSendTxn(publicClient);
8431
8438
  *
8432
8439
  * // Prepare transaction
8433
- * const rawTx = await prepareRawTxn({
8434
- * from: address!,
8435
- * to: '0x...',
8436
- * value: '0.001',
8437
- * });
8438
- *
8439
- * // Sign and send transaction
8440
+ * const rawTx = await prepareRawTxn({ from: address!, to: '0x...', value: '0.001' });
8441
+ * const { estimateGas } = useEstimateGas(publicClient);
8442
+ * const gasEstimate = await estimateGas({ account: address!, to: rawTx.to, data: rawTx.data, value: rawTx.value });
8443
+ * // Sign and send (override required; no estimation in hook)
8440
8444
  * const result = await signAndSendTxn({
8441
8445
  * from: address!,
8442
- * ...rawTx, // Spread to, value, data from prepareRawTxn
8446
+ * ...rawTx,
8447
+ * override: { gasLimit: gasEstimate.gasLimit, maxFeePerGas: gasEstimate.maxFeePerGas!, maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas! },
8443
8448
  * });
8444
- *
8445
8449
  * console.log('Transaction hash:', result.hash);
8446
8450
  * ```
8447
8451
  */
8448
8452
  export declare function useSignAndSendTxn(provider: PublicClient): {
8449
- signAndSendTxn: ({ from, to, value, data, chainId, }: {
8453
+ signAndSendTxn: ({ from, to, value, data, chainId, override, }: {
8450
8454
  from: Address;
8451
8455
  to: Address;
8452
- value: `0x${string}`;
8456
+ value: string | bigint;
8453
8457
  data: `0x${string}`;
8454
8458
  chainId?: number;
8459
+ /** Gas and fees (user must pass; no estimation in hook). EIP-1559 or legacy. Use useEstimateGas to get values. */
8460
+ override: {
8461
+ gasLimit: bigint;
8462
+ maxFeePerGas: bigint;
8463
+ maxPriorityFeePerGas: bigint;
8464
+ } | {
8465
+ gasLimit: bigint;
8466
+ gasPrice: bigint;
8467
+ };
8455
8468
  }) => Promise<{
8456
8469
  hash: `0x${string}`;
8457
- unsignedTransaction: `0x02${string}`;
8470
+ unsignedTransaction: `0x02${string}` | import("viem").TransactionSerializedLegacy;
8458
8471
  signedTransaction: string;
8459
8472
  }>;
8460
8473
  isConnected: boolean;
@@ -8495,33 +8508,33 @@ export declare function useWaitForTxnReceipt(provider: PublicClient): {
8495
8508
  }) => Promise<TransactionReceipt>;
8496
8509
  };
8497
8510
  /**
8498
- * Hook to estimate gas price
8499
- * Estimates gas price and fees for transactions
8511
+ * Hook to estimate gas for a transaction
8512
+ * Returns gasLimit and fees to pass as override to useSignTxn / useSignAndSendTxn (no estimation inside those hooks).
8500
8513
  *
8501
8514
  * @param provider - PublicClient instance (can be created using usePublicClient hook)
8502
8515
  * @returns Object with estimateGas function
8503
8516
  *
8504
8517
  * @example
8505
8518
  * ```tsx
8506
- * const { publicClient } = usePublicClient(
8507
- * polygonAmoy,
8508
- * 'https://rpc-amoy.polygon.technology'
8509
- * );
8510
8519
  * const { estimateGas } = useEstimateGas(publicClient);
8511
- *
8512
- * // Estimate gas price
8513
- * const gasPrice = await estimateGas();
8514
- *
8515
- * // Returns:
8516
- * // {
8517
- * // gasPrice?: bigint, // Legacy gas price (for non-EIP-1559 chains)
8518
- * // maxFeePerGas?: bigint, // EIP-1559 max fee per gas
8519
- * // maxPriorityFeePerGas?: bigint // EIP-1559 max priority fee per gas
8520
- * // }
8520
+ * const result = await estimateGas({
8521
+ * account: address!,
8522
+ * to: rawTx.to,
8523
+ * data: rawTx.data,
8524
+ * value: rawTx.value,
8525
+ * });
8526
+ * // EIP-1559: override: { gasLimit: result.gasLimit, maxFeePerGas: result.maxFeePerGas!, maxPriorityFeePerGas: result.maxPriorityFeePerGas! }
8527
+ * // Legacy: override: { gasLimit: result.gasLimit, gasPrice: result.gasPrice! }
8521
8528
  * ```
8522
8529
  */
8523
8530
  export declare function useEstimateGas(provider: PublicClient): {
8524
- estimateGas: () => Promise<{
8531
+ estimateGas: ({ account, to, data, value, }: {
8532
+ account: Address;
8533
+ to: Address;
8534
+ data?: `0x${string}`;
8535
+ value?: string | bigint;
8536
+ }) => Promise<{
8537
+ gasLimit: bigint;
8525
8538
  gasPrice?: bigint;
8526
8539
  maxFeePerGas?: bigint;
8527
8540
  maxPriorityFeePerGas?: bigint;
package/dist/src/hooks.js CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { useState, useCallback, useEffect, useMemo } from 'react';
5
5
  import { useAbstraxnWallet } from './AbstraxnProvider';
6
- import { createPublicClient, createWalletClient, http, getContract, serializeTransaction, parseEther, encodeFunctionData } from 'viem';
6
+ import { createPublicClient, createWalletClient, http, getContract, serializeTransaction, encodeFunctionData } from 'viem';
7
7
  import { useWalletClient as useWagmiWalletClient, useAccount, useConfig, useChainId as useWagmiChainId, useSwitchChain as useWagmiSwitchChain, useSignMessage as useWagmiSignMessage } from 'wagmi';
8
8
  import { getWalletClient, switchChain } from '@wagmi/core';
9
9
  import { getConnectorMeta } from './connectors';
@@ -510,21 +510,11 @@ export function usePrepareRawTxn(provider) {
510
510
  // Determine if this is a native transfer
511
511
  const isNativeTransfer = !needsEncoding && !hasPreEncodedData;
512
512
  if (isNativeTransfer) {
513
- // Native transfer: convert value to wei and set data to '0x'
514
- if (!value || value === '0' || value === 0) {
513
+ // Native transfer: pass value through as-is (no hex conversion)
514
+ if (value === undefined || value === null || value === '' || value === '0' || value === 0) {
515
515
  throw new Error('Value is required for native transfer');
516
516
  }
517
- // Convert value to wei
518
- const valueStr = typeof value === 'string' ? value.trim() : String(value);
519
- let valueInWei;
520
- try {
521
- valueInWei = parseEther(valueStr);
522
- }
523
- catch (error) {
524
- throw new Error(`Invalid value format: "${valueStr}". Value must be a valid number string (e.g., "0.001").`);
525
- }
526
- // Convert to hex string
527
- finalValue = `0x${valueInWei.toString(16)}`;
517
+ finalValue = typeof value === 'bigint' ? value : (typeof value === 'string' ? value.trim() : String(value));
528
518
  finalData = '0x';
529
519
  }
530
520
  else {
@@ -537,36 +527,8 @@ export function usePrepareRawTxn(provider) {
537
527
  if (!functionName) {
538
528
  throw new Error('Function name is required for encoding function data');
539
529
  }
540
- // Process args to convert ETH amounts to wei for transfer functions
541
- const processedArgs = (args || []).map((arg, index) => {
542
- // Check if this is likely an amount parameter for transfer/transferFrom functions
543
- const isAmountParam = (functionName === 'transfer' || functionName === 'transferFrom') && index === 1;
544
- if (isAmountParam) {
545
- // If arg is a string or number that looks like ETH (has decimal point)
546
- if (typeof arg === 'string' && arg.includes('.')) {
547
- try {
548
- // Convert ETH to wei
549
- const weiAmount = parseEther(arg);
550
- return weiAmount.toString();
551
- }
552
- catch (error) {
553
- throw new Error(`Failed to convert amount "${arg}" to wei. Make sure it's a valid number string (e.g., "0.001").`);
554
- }
555
- }
556
- else if (typeof arg === 'number' && arg % 1 !== 0) {
557
- // Number with decimal places - convert to wei
558
- try {
559
- const weiAmount = parseEther(arg.toString());
560
- return weiAmount.toString();
561
- }
562
- catch (error) {
563
- throw new Error(`Failed to convert amount ${arg} to wei. Make sure it's a valid number.`);
564
- }
565
- }
566
- }
567
- // For other args, just return as-is
568
- return arg;
569
- });
530
+ // Pass args through as-is (no conversion); caller must pass amounts in wei / correct format
531
+ const processedArgs = args ?? [];
570
532
  try {
571
533
  finalData = encodeFunctionData({
572
534
  abi: abi,
@@ -588,18 +550,9 @@ export function usePrepareRawTxn(provider) {
588
550
  else {
589
551
  throw new Error('Either provide encoded data, or provide abi/functionName/args for encoding.');
590
552
  }
591
- // Handle value for contract calls
553
+ // Handle value for contract calls: pass through as-is (no hex conversion)
592
554
  if (value && value !== '0' && value !== 0) {
593
- // Convert value to wei if provided
594
- const valueStr = typeof value === 'string' ? value.trim() : String(value);
595
- let valueInWei;
596
- try {
597
- valueInWei = parseEther(valueStr);
598
- }
599
- catch (error) {
600
- throw new Error(`Invalid value format: "${valueStr}". Value must be a valid number string (e.g., "0.001").`);
601
- }
602
- finalValue = `0x${valueInWei.toString(16)}`;
555
+ finalValue = typeof value === 'bigint' ? value : (typeof value === 'string' ? value.trim() : String(value));
603
556
  }
604
557
  else {
605
558
  finalValue = '0x0';
@@ -626,22 +579,20 @@ export function usePrepareRawTxn(provider) {
626
579
  * const { signTxn } = useSignTxn(publicClient);
627
580
  *
628
581
  * // Prepare transaction
629
- * const rawTx = await prepareRawTxn({
630
- * from: address!,
631
- * to: '0x...',
632
- * value: '0.001',
633
- * });
634
- *
635
- * // Sign transaction
582
+ * const rawTx = await prepareRawTxn({ from: address!, to: '0x...', value: '0.001' });
583
+ * const { estimateGas } = useEstimateGas(publicClient);
584
+ * const gasEstimate = await estimateGas({ account: address!, to: rawTx.to, data: rawTx.data, value: rawTx.value });
585
+ * // Sign (override required; no estimation in hook)
636
586
  * const signedTx = await signTxn({
637
587
  * from: address!,
638
- * ...rawTx, // Spread to, value, data from prepareRawTxn
588
+ * ...rawTx,
589
+ * override: { gasLimit: gasEstimate.gasLimit, maxFeePerGas: gasEstimate.maxFeePerGas!, maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas! },
639
590
  * });
640
591
  * ```
641
592
  */
642
593
  export function useSignTxn(provider) {
643
594
  const { wallet, isConnected, address, signTransactionViaAPI } = useAbstraxnWallet();
644
- const signTxn = useCallback(async ({ from, to, value, data, chainId, }) => {
595
+ const signTxn = useCallback(async ({ from, to, value, data, chainId, override, }) => {
645
596
  if (!isConnected || !wallet) {
646
597
  throw new Error('Wallet is not connected');
647
598
  }
@@ -654,6 +605,16 @@ export function useSignTxn(provider) {
654
605
  if (!to) {
655
606
  throw new Error('To address is required');
656
607
  }
608
+ if (override.gasLimit === undefined) {
609
+ throw new Error('override.gasLimit is required. Use useEstimateGas to get values.');
610
+ }
611
+ const isLegacy = 'gasPrice' in override && override.gasPrice !== undefined;
612
+ if (!isLegacy) {
613
+ const o = override;
614
+ if (o.maxFeePerGas === undefined || o.maxPriorityFeePerGas === undefined) {
615
+ throw new Error('override.maxFeePerGas and maxPriorityFeePerGas are required for EIP-1559, or pass gasPrice for legacy.');
616
+ }
617
+ }
657
618
  // Get chain ID from provider or use provided one
658
619
  const targetChainId = chainId || provider.chain?.id;
659
620
  if (!targetChainId) {
@@ -661,32 +622,34 @@ export function useSignTxn(provider) {
661
622
  }
662
623
  // Get nonce
663
624
  const nonce = await provider.getTransactionCount({ address: from });
664
- // Convert hex value to bigint
665
- // Handle empty hex string "0x" by converting to "0x0"
666
- const normalizedValue = value === '0x' ? '0x0' : value;
667
- const valueInWei = BigInt(normalizedValue);
668
- // Estimate gas
669
- const gas = await provider.estimateGas({
670
- account: from,
671
- to,
672
- data,
673
- value: valueInWei,
674
- });
675
- // Estimate fees
676
- const fee = await provider.estimateFeesPerGas();
677
- // Create unsigned transaction
678
- const unsignedTx = {
679
- chainId: targetChainId,
680
- from,
681
- to,
682
- data,
683
- value: valueInWei,
684
- nonce,
685
- gas,
686
- maxFeePerGas: fee.maxFeePerGas,
687
- maxPriorityFeePerGas: fee.maxPriorityFeePerGas,
688
- type: 'eip1559',
689
- };
625
+ // Value in wei (pass-through from prepareRawTxn, no hex conversion)
626
+ const valueInWei = typeof value === 'bigint' ? value : BigInt(value === '0x' || value === '' ? '0' : value);
627
+ // Build unsigned tx from user override only (no estimateGas/estimateFeesPerGas)
628
+ const unsignedTx = isLegacy
629
+ ? {
630
+ chainId: targetChainId,
631
+ from,
632
+ to,
633
+ data,
634
+ value: valueInWei,
635
+ nonce,
636
+ gas: override.gasLimit,
637
+ gasPrice: override.gasPrice,
638
+ }
639
+ : (() => {
640
+ const o = override;
641
+ return {
642
+ chainId: targetChainId,
643
+ from,
644
+ to,
645
+ data,
646
+ value: valueInWei,
647
+ nonce,
648
+ gas: o.gasLimit,
649
+ maxFeePerGas: o.maxFeePerGas,
650
+ maxPriorityFeePerGas: o.maxPriorityFeePerGas,
651
+ };
652
+ })();
690
653
  // Serialize transaction
691
654
  const serializedTx = serializeTransaction(unsignedTx);
692
655
  // Sign transaction via Turnkey API
@@ -711,24 +674,21 @@ export function useSignTxn(provider) {
711
674
  * const { signAndSendTxn } = useSignAndSendTxn(publicClient);
712
675
  *
713
676
  * // Prepare transaction
714
- * const rawTx = await prepareRawTxn({
715
- * from: address!,
716
- * to: '0x...',
717
- * value: '0.001',
718
- * });
719
- *
720
- * // Sign and send transaction
677
+ * const rawTx = await prepareRawTxn({ from: address!, to: '0x...', value: '0.001' });
678
+ * const { estimateGas } = useEstimateGas(publicClient);
679
+ * const gasEstimate = await estimateGas({ account: address!, to: rawTx.to, data: rawTx.data, value: rawTx.value });
680
+ * // Sign and send (override required; no estimation in hook)
721
681
  * const result = await signAndSendTxn({
722
682
  * from: address!,
723
- * ...rawTx, // Spread to, value, data from prepareRawTxn
683
+ * ...rawTx,
684
+ * override: { gasLimit: gasEstimate.gasLimit, maxFeePerGas: gasEstimate.maxFeePerGas!, maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas! },
724
685
  * });
725
- *
726
686
  * console.log('Transaction hash:', result.hash);
727
687
  * ```
728
688
  */
729
689
  export function useSignAndSendTxn(provider) {
730
690
  const { wallet, isConnected, address, signTransactionViaAPI } = useAbstraxnWallet();
731
- const signAndSendTxn = useCallback(async ({ from, to, value, data, chainId, }) => {
691
+ const signAndSendTxn = useCallback(async ({ from, to, value, data, chainId, override, }) => {
732
692
  if (!isConnected || !wallet) {
733
693
  throw new Error('Wallet is not connected');
734
694
  }
@@ -741,6 +701,16 @@ export function useSignAndSendTxn(provider) {
741
701
  if (!to) {
742
702
  throw new Error('To address is required');
743
703
  }
704
+ if (override.gasLimit === undefined) {
705
+ throw new Error('override.gasLimit is required. Use useEstimateGas to get values.');
706
+ }
707
+ const isLegacy = 'gasPrice' in override && override.gasPrice !== undefined;
708
+ if (!isLegacy) {
709
+ const o = override;
710
+ if (o.maxFeePerGas === undefined || o.maxPriorityFeePerGas === undefined) {
711
+ throw new Error('override.maxFeePerGas and maxPriorityFeePerGas are required for EIP-1559, or pass gasPrice for legacy.');
712
+ }
713
+ }
744
714
  // Get chain ID from provider or use provided one
745
715
  const targetChainId = chainId || provider.chain?.id;
746
716
  if (!targetChainId) {
@@ -748,32 +718,34 @@ export function useSignAndSendTxn(provider) {
748
718
  }
749
719
  // Get nonce
750
720
  const nonce = await provider.getTransactionCount({ address: from });
751
- // Convert hex value to bigint
752
- // Handle empty hex string "0x" by converting to "0x0"
753
- const normalizedValue = value === '0x' ? '0x0' : value;
754
- const valueInWei = BigInt(normalizedValue);
755
- // Estimate gas
756
- const gas = await provider.estimateGas({
757
- account: from,
758
- to,
759
- data,
760
- value: valueInWei,
761
- });
762
- // Estimate fees
763
- const fee = await provider.estimateFeesPerGas();
764
- // Create unsigned transaction
765
- const unsignedTx = {
766
- chainId: targetChainId,
767
- from,
768
- to,
769
- data,
770
- value: valueInWei,
771
- nonce,
772
- gas,
773
- maxFeePerGas: fee.maxFeePerGas,
774
- maxPriorityFeePerGas: fee.maxPriorityFeePerGas,
775
- type: 'eip1559',
776
- };
721
+ // Value in wei (pass-through from prepareRawTxn, no hex conversion)
722
+ const valueInWei = typeof value === 'bigint' ? value : BigInt(value === '0x' || value === '' ? '0' : value);
723
+ // Build unsigned tx from user override only (no estimateGas/estimateFeesPerGas)
724
+ const unsignedTx = isLegacy
725
+ ? {
726
+ chainId: targetChainId,
727
+ from,
728
+ to,
729
+ data,
730
+ value: valueInWei,
731
+ nonce,
732
+ gas: override.gasLimit,
733
+ gasPrice: override.gasPrice,
734
+ }
735
+ : (() => {
736
+ const o = override;
737
+ return {
738
+ chainId: targetChainId,
739
+ from,
740
+ to,
741
+ data,
742
+ value: valueInWei,
743
+ nonce,
744
+ gas: o.gasLimit,
745
+ maxFeePerGas: o.maxFeePerGas,
746
+ maxPriorityFeePerGas: o.maxPriorityFeePerGas,
747
+ };
748
+ })();
777
749
  // Serialize transaction
778
750
  const serializedTx = serializeTransaction(unsignedTx);
779
751
  // Sign transaction via Turnkey API
@@ -844,59 +816,59 @@ export function useWaitForTxnReceipt(provider) {
844
816
  return { waitForTxnReceipt };
845
817
  }
846
818
  /**
847
- * Hook to estimate gas price
848
- * Estimates gas price and fees for transactions
819
+ * Hook to estimate gas for a transaction
820
+ * Returns gasLimit and fees to pass as override to useSignTxn / useSignAndSendTxn (no estimation inside those hooks).
849
821
  *
850
822
  * @param provider - PublicClient instance (can be created using usePublicClient hook)
851
823
  * @returns Object with estimateGas function
852
824
  *
853
825
  * @example
854
826
  * ```tsx
855
- * const { publicClient } = usePublicClient(
856
- * polygonAmoy,
857
- * 'https://rpc-amoy.polygon.technology'
858
- * );
859
827
  * const { estimateGas } = useEstimateGas(publicClient);
860
- *
861
- * // Estimate gas price
862
- * const gasPrice = await estimateGas();
863
- *
864
- * // Returns:
865
- * // {
866
- * // gasPrice?: bigint, // Legacy gas price (for non-EIP-1559 chains)
867
- * // maxFeePerGas?: bigint, // EIP-1559 max fee per gas
868
- * // maxPriorityFeePerGas?: bigint // EIP-1559 max priority fee per gas
869
- * // }
828
+ * const result = await estimateGas({
829
+ * account: address!,
830
+ * to: rawTx.to,
831
+ * data: rawTx.data,
832
+ * value: rawTx.value,
833
+ * });
834
+ * // EIP-1559: override: { gasLimit: result.gasLimit, maxFeePerGas: result.maxFeePerGas!, maxPriorityFeePerGas: result.maxPriorityFeePerGas! }
835
+ * // Legacy: override: { gasLimit: result.gasLimit, gasPrice: result.gasPrice! }
870
836
  * ```
871
837
  */
872
838
  export function useEstimateGas(provider) {
873
- const estimateGas = useCallback(async () => {
839
+ const estimateGas = useCallback(async ({ account, to, data = '0x', value = 0n, }) => {
874
840
  if (!provider) {
875
841
  throw new Error('Provider (publicClient) is required');
876
842
  }
843
+ if (!account) {
844
+ throw new Error('Account (from) is required');
845
+ }
846
+ if (!to) {
847
+ throw new Error('To address is required');
848
+ }
849
+ const valueInWei = typeof value === 'bigint' ? value : (value === undefined || value === '' || value === '0x' ? 0n : BigInt(value));
850
+ const gasLimit = await provider.estimateGas({
851
+ account,
852
+ to,
853
+ data: data ?? '0x',
854
+ value: valueInWei,
855
+ });
877
856
  try {
878
- // Try to get EIP-1559 fees first (for modern chains)
879
857
  const fees = await provider.estimateFeesPerGas();
880
858
  return {
859
+ gasLimit,
881
860
  maxFeePerGas: fees.maxFeePerGas,
882
861
  maxPriorityFeePerGas: fees.maxPriorityFeePerGas,
883
- // Also get legacy gas price as fallback
884
862
  gasPrice: fees.gasPrice,
885
863
  };
886
864
  }
887
865
  catch (error) {
888
- // If EIP-1559 fails, try legacy gas price
889
866
  try {
890
867
  const gasPrice = await provider.getGasPrice();
891
- return {
892
- gasPrice,
893
- };
868
+ return { gasLimit, gasPrice };
894
869
  }
895
870
  catch (legacyError) {
896
- if (error instanceof Error) {
897
- throw new Error(`Failed to estimate gas price: ${error.message}`);
898
- }
899
- throw error;
871
+ return { gasLimit };
900
872
  }
901
873
  }
902
874
  }, [provider]);