@octaflowlabs/onchain-sdk 1.3.8 → 1.4.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.
@@ -8,6 +8,7 @@ export interface NetworkField {
8
8
  iconUrl: string;
9
9
  symbol: string;
10
10
  failoverRpcUrl?: string;
11
+ blockTime?: number;
11
12
  }
12
13
  export interface NetworkRegistry {
13
14
  category: string;
@@ -15,6 +15,7 @@ exports.NETWORKS_REGISTRY = [
15
15
  iconUrl: 'https://assets.coingecko.com/coins/images/279/large/ethereum.png',
16
16
  symbol: 'ETH',
17
17
  failoverRpcUrl: 'https://eth.llamarpc.com',
18
+ blockTime: 12,
18
19
  },
19
20
  {
20
21
  id: 'bnb-smart-chain',
@@ -22,10 +23,11 @@ exports.NETWORKS_REGISTRY = [
22
23
  nameForDisplay: 'BNB Smart Chain',
23
24
  chainId: 56,
24
25
  rpcUrl: 'https://bsc-dataseed.bnbchain.org',
25
- explorerUrl: 'https://bscscan.com/',
26
+ explorerUrl: 'https://bscscan.com',
26
27
  iconUrl: 'https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png',
27
28
  symbol: 'BNB',
28
29
  failoverRpcUrl: 'https://bsc.llamarpc.com',
30
+ blockTime: 3,
29
31
  },
30
32
  {
31
33
  id: 'polygon-mainnet',
@@ -37,6 +39,7 @@ exports.NETWORKS_REGISTRY = [
37
39
  explorerUrl: 'https://polygonscan.com',
38
40
  symbol: 'POL',
39
41
  failoverRpcUrl: 'https://polygon.llamarpc.com',
42
+ blockTime: 2,
40
43
  },
41
44
  {
42
45
  id: 'arbitrum-mainnet',
@@ -48,6 +51,7 @@ exports.NETWORKS_REGISTRY = [
48
51
  iconUrl: 'https://assets.coingecko.com/coins/images/16547/large/photo_2023-03-29_21.47.00.jpeg',
49
52
  symbol: 'ARB',
50
53
  failoverRpcUrl: 'https://arb.llamarpc.com',
54
+ blockTime: 1,
51
55
  },
52
56
  ],
53
57
  },
@@ -64,6 +68,7 @@ exports.NETWORKS_REGISTRY = [
64
68
  iconUrl: 'https://assets.coingecko.com/coins/images/279/large/ethereum.png',
65
69
  symbol: 'ETH',
66
70
  failoverRpcUrl: 'https://eth-sepolia.llamarpc.com',
71
+ blockTime: 12,
67
72
  },
68
73
  ],
69
74
  },
@@ -3,7 +3,7 @@ import ERC20_TOKEN_CONTRACT_ABI from './ABIs/ERC20_TOKEN_CONTRACT_ABI';
3
3
  export { ERC20_TOKEN_CONTRACT_ABI };
4
4
  /** constants exports */
5
5
  export { GAS_LIMIT_PER_TX_TYPE, MULTICALL3_ADDRESS } from './constants/constants';
6
- export { NetworkField, NetworkRegistry, NETWORKS_REGISTRY, } from './constants/NETWORKS_REGISTRY';
6
+ export { NetworkField, NetworkRegistry, NETWORKS_REGISTRY } from './constants/NETWORKS_REGISTRY';
7
7
  export { BASIC_TOKENS_BY_CHAIN, BasicTokenData, BasicTokenSymbol, ChainTokenDataMap, } from './constants/BASIC_TOKENS_REGISTRY';
8
8
  /** basic blockchain exports */
9
9
  export { buildBaseUnsignedTransferTx, buildMaxNativeTransferTx, buildUnsignedTransferTx, } from './blockchain/buildUnsignedTransferTx';
@@ -26,5 +26,7 @@ export { NATIVE_TOKENS };
26
26
  export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
27
27
  export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
28
28
  export { normalizeAddress } from './utils/normalizeAddress';
29
+ export { toGwei, tryParseGweiToWei, parseGasLimit } from './utils/parseGasFees';
30
+ export { getFeePresets, calcReserve, estimateSeconds, getBlockTime, BLOCK_TIME_BY_CHAIN, } from './utils/feePresets';
29
31
  /** types exports */
30
- export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, BuildBaseUnsignedTransferTxParams, TxStatusResponse, EstimateTransactionOptions, EstimateTransactionResult, PrepareTransactionParams, PrepareTransactionResult, FormatAmountOptions, TransactionRequest, GetBalanceParams, GetBalancesParams, GetBalancesChainRequest, GetBalanceResult, ChainBalances, TokenBalance, ChainGroup, } from './types/common';
32
+ export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, BuildBaseUnsignedTransferTxParams, TxStatusResponse, EstimateTransactionOptions, EstimateTransactionResult, PrepareTransactionParams, PrepareTransactionResult, FormatAmountOptions, TransactionRequest, GetBalanceParams, GetBalancesParams, GetBalancesChainRequest, GetBalanceResult, ChainBalances, TokenBalance, ChainGroup, FeePreset, FeePresetLabel, FeeEstimateSeconds, ResolvedFees, EIP1559Fees, LegacyFees, FeeModel, FeeHistoryData, FeeDataInput, } from './types/common';
package/dist/cjs/index.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.normalizeAddress = exports.errorMessagesForGasLimitEstimation = exports.errorMessagesForBroadcast = exports.handleErrorMessages = exports.parsedAmount = exports.formattedAmountForDisplay = exports.NATIVE_TOKENS = exports.transformBigInt = exports.getShortenData = exports.getShortenTransactionHashOrAddress = exports.signTransaction = exports.signMessage = exports.createWallet = exports.EvmWalletService = exports.prepareTransaction = exports.estimateTransaction = exports.getBalances = exports.getBalance = exports.txStatus = exports.getProvider = exports.estimateGasLimitFromProvider = exports.broadcastTransaction = exports.buildUnsignedTransferTx = exports.buildMaxNativeTransferTx = exports.buildBaseUnsignedTransferTx = exports.BASIC_TOKENS_BY_CHAIN = exports.NETWORKS_REGISTRY = exports.MULTICALL3_ADDRESS = exports.GAS_LIMIT_PER_TX_TYPE = exports.ERC20_TOKEN_CONTRACT_ABI = void 0;
6
+ exports.BLOCK_TIME_BY_CHAIN = exports.getBlockTime = exports.estimateSeconds = exports.calcReserve = exports.getFeePresets = exports.parseGasLimit = exports.tryParseGweiToWei = exports.toGwei = exports.normalizeAddress = exports.errorMessagesForGasLimitEstimation = exports.errorMessagesForBroadcast = exports.handleErrorMessages = exports.parsedAmount = exports.formattedAmountForDisplay = exports.NATIVE_TOKENS = exports.transformBigInt = exports.getShortenData = exports.getShortenTransactionHashOrAddress = exports.signTransaction = exports.signMessage = exports.createWallet = exports.EvmWalletService = exports.prepareTransaction = exports.estimateTransaction = exports.getBalances = exports.getBalance = exports.txStatus = exports.getProvider = exports.estimateGasLimitFromProvider = exports.broadcastTransaction = exports.buildUnsignedTransferTx = exports.buildMaxNativeTransferTx = exports.buildBaseUnsignedTransferTx = exports.BASIC_TOKENS_BY_CHAIN = exports.NETWORKS_REGISTRY = exports.MULTICALL3_ADDRESS = exports.GAS_LIMIT_PER_TX_TYPE = exports.ERC20_TOKEN_CONTRACT_ABI = void 0;
7
7
  /** ABIs exports */
8
8
  const ERC20_TOKEN_CONTRACT_ABI_1 = __importDefault(require("./ABIs/ERC20_TOKEN_CONTRACT_ABI"));
9
9
  exports.ERC20_TOKEN_CONTRACT_ABI = ERC20_TOKEN_CONTRACT_ABI_1.default;
@@ -59,3 +59,13 @@ Object.defineProperty(exports, "errorMessagesForBroadcast", { enumerable: true,
59
59
  Object.defineProperty(exports, "errorMessagesForGasLimitEstimation", { enumerable: true, get: function () { return handleErrorMessages_1.errorMessagesForGasLimitEstimation; } });
60
60
  var normalizeAddress_1 = require("./utils/normalizeAddress");
61
61
  Object.defineProperty(exports, "normalizeAddress", { enumerable: true, get: function () { return normalizeAddress_1.normalizeAddress; } });
62
+ var parseGasFees_1 = require("./utils/parseGasFees");
63
+ Object.defineProperty(exports, "toGwei", { enumerable: true, get: function () { return parseGasFees_1.toGwei; } });
64
+ Object.defineProperty(exports, "tryParseGweiToWei", { enumerable: true, get: function () { return parseGasFees_1.tryParseGweiToWei; } });
65
+ Object.defineProperty(exports, "parseGasLimit", { enumerable: true, get: function () { return parseGasFees_1.parseGasLimit; } });
66
+ var feePresets_1 = require("./utils/feePresets");
67
+ Object.defineProperty(exports, "getFeePresets", { enumerable: true, get: function () { return feePresets_1.getFeePresets; } });
68
+ Object.defineProperty(exports, "calcReserve", { enumerable: true, get: function () { return feePresets_1.calcReserve; } });
69
+ Object.defineProperty(exports, "estimateSeconds", { enumerable: true, get: function () { return feePresets_1.estimateSeconds; } });
70
+ Object.defineProperty(exports, "getBlockTime", { enumerable: true, get: function () { return feePresets_1.getBlockTime; } });
71
+ Object.defineProperty(exports, "BLOCK_TIME_BY_CHAIN", { enumerable: true, get: function () { return feePresets_1.BLOCK_TIME_BY_CHAIN; } });
@@ -130,3 +130,46 @@ export interface ChainGroup {
130
130
  nativeBalanceRequests: GetBalanceParams[];
131
131
  tokenBalanceRequests: GetBalanceParams[];
132
132
  }
133
+ export type EIP1559Fees = {
134
+ mode: 'eip1559';
135
+ maxFeePerGas: bigint;
136
+ maxPriorityFeePerGas: bigint;
137
+ gasLimit: bigint;
138
+ };
139
+ export type LegacyFees = {
140
+ mode: 'legacy';
141
+ gasPrice: bigint;
142
+ gasLimit: bigint;
143
+ };
144
+ export type ResolvedFees = EIP1559Fees | LegacyFees;
145
+ export type FeeModel = 'eip1559' | 'legacy';
146
+ export type FeePresetLabel = 'Low' | 'Standard' | 'High';
147
+ export type FeeEstimateSeconds = {
148
+ min: number;
149
+ max: number;
150
+ };
151
+ export type FeePreset = {
152
+ label: FeePresetLabel;
153
+ fees: ResolvedFees;
154
+ humanReadableGasReserve: string;
155
+ humanReadableEstimatedCost: string;
156
+ estimatedSeconds?: FeeEstimateSeconds;
157
+ };
158
+ export type FeeHistoryData = {
159
+ currentBaseFee: string;
160
+ range12h: {
161
+ minBaseFee: string;
162
+ maxBaseFee: string;
163
+ minPriorityFee: string;
164
+ maxPriorityFee: string;
165
+ };
166
+ };
167
+ export type FeeDataInput = {
168
+ chainId?: number;
169
+ gasLimit?: bigint | string | number;
170
+ feeData?: {
171
+ maxFeePerGas?: bigint | string;
172
+ maxPriorityFeePerGas?: bigint | string;
173
+ gasPrice?: bigint | string;
174
+ };
175
+ };
@@ -0,0 +1,6 @@
1
+ import { FeeDataInput, FeeEstimateSeconds, FeePreset } from '../types/common';
2
+ export declare const BLOCK_TIME_BY_CHAIN: Record<number, number>;
3
+ export declare function getBlockTime(chainId: number): number;
4
+ export declare function calcReserve(gasLimit: bigint, pricePerGas: bigint): string;
5
+ export declare function estimateSeconds(presetPriority: bigint, standardPriority: bigint, blockTime: number): FeeEstimateSeconds;
6
+ export declare function getFeePresets(tx: FeeDataInput): FeePreset[];
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BLOCK_TIME_BY_CHAIN = void 0;
4
+ exports.getBlockTime = getBlockTime;
5
+ exports.calcReserve = calcReserve;
6
+ exports.estimateSeconds = estimateSeconds;
7
+ exports.getFeePresets = getFeePresets;
8
+ const NETWORKS_REGISTRY_1 = require("../constants/NETWORKS_REGISTRY");
9
+ const formatAmount_1 = require("./formatAmount");
10
+ const DEFAULT_BLOCK_TIME = 12;
11
+ const FORMAT_OPTS = { useGroupSeparator: false, decimalsToShow: 18 };
12
+ exports.BLOCK_TIME_BY_CHAIN = Object.fromEntries(NETWORKS_REGISTRY_1.NETWORKS_REGISTRY.flatMap((r) => r.networks)
13
+ .filter((n) => n.blockTime != null)
14
+ .map((n) => [n.chainId, n.blockTime]));
15
+ function getBlockTime(chainId) {
16
+ return exports.BLOCK_TIME_BY_CHAIN[chainId] ?? DEFAULT_BLOCK_TIME;
17
+ }
18
+ function calcReserve(gasLimit, pricePerGas) {
19
+ return (0, formatAmount_1.formattedAmountForDisplay)(gasLimit * pricePerGas, 18, FORMAT_OPTS);
20
+ }
21
+ function estimateSeconds(presetPriority, standardPriority, blockTime) {
22
+ if (standardPriority === 0n) {
23
+ return { min: blockTime, max: blockTime * 4 };
24
+ }
25
+ const ratio = Number((presetPriority * 1000n) / standardPriority) / 1000;
26
+ if (ratio >= 1.4)
27
+ return { min: blockTime, max: blockTime * 2 };
28
+ if (ratio >= 0.9)
29
+ return { min: blockTime, max: blockTime * 3 };
30
+ return { min: blockTime, max: blockTime * 4 };
31
+ }
32
+ function getFeePresets(tx) {
33
+ const builtTx = tx;
34
+ const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = builtTx.feeData ?? {};
35
+ const gasLimit = builtTx.gasLimit
36
+ ? BigInt(builtTx.gasLimit)
37
+ : BigInt(builtTx.unsignedTx?.gasLimit ?? 21000);
38
+ // EIP-1559
39
+ if (maxFeePerGas != null && maxPriorityFeePerGas != null) {
40
+ const priority = BigInt(maxPriorityFeePerGas);
41
+ const baseFee = BigInt(maxFeePerGas) - BigInt(maxPriorityFeePerGas);
42
+ const estimatedCostPerGas = (priority) => baseFee + priority;
43
+ const chainId = builtTx.unsignedTx?.chainId ?? 1;
44
+ const blockTime = getBlockTime(chainId);
45
+ const lowPriority = (priority * 75n) / 100n;
46
+ const highPriority = (priority * 150n) / 100n;
47
+ const build = (label, priority, seconds) => {
48
+ const presetMaxFeePerGas = baseFee + priority;
49
+ return {
50
+ label,
51
+ fees: {
52
+ mode: 'eip1559',
53
+ maxFeePerGas: presetMaxFeePerGas,
54
+ maxPriorityFeePerGas: priority,
55
+ gasLimit,
56
+ },
57
+ humanReadableGasReserve: calcReserve(gasLimit, presetMaxFeePerGas),
58
+ humanReadableEstimatedCost: calcReserve(gasLimit, estimatedCostPerGas(priority)),
59
+ estimatedSeconds: seconds,
60
+ };
61
+ };
62
+ return [
63
+ build('Low', lowPriority, estimateSeconds(lowPriority, priority, blockTime)),
64
+ build('Standard', priority, estimateSeconds(priority, priority, blockTime)),
65
+ build('High', highPriority, estimateSeconds(highPriority, priority, blockTime)),
66
+ ];
67
+ }
68
+ // Legacy
69
+ if (gasPrice != null) {
70
+ const price = BigInt(gasPrice);
71
+ const build = (label, price, estimatedSeconds) => ({
72
+ label,
73
+ fees: { mode: 'legacy', gasPrice: price, gasLimit },
74
+ humanReadableGasReserve: calcReserve(gasLimit, price),
75
+ humanReadableEstimatedCost: calcReserve(gasLimit, price),
76
+ estimatedSeconds,
77
+ });
78
+ return [
79
+ build('Low', (price * 90n) / 100n, { min: 180, max: 180 }),
80
+ build('Standard', price, { min: 60, max: 60 }),
81
+ build('High', (price * 115n) / 100n, { min: 20, max: 20 }),
82
+ ];
83
+ }
84
+ throw new Error('feeData missing from unsignedTx');
85
+ }
@@ -0,0 +1,3 @@
1
+ export declare function toGwei(wei: bigint): string;
2
+ export declare function tryParseGweiToWei(input: string): bigint | null;
3
+ export declare function parseGasLimit(input: string): bigint | null;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toGwei = toGwei;
4
+ exports.tryParseGweiToWei = tryParseGweiToWei;
5
+ exports.parseGasLimit = parseGasLimit;
6
+ const __1 = require("..");
7
+ const DECIMAL_PATTERN = /^\d*(\.\d*)?$/;
8
+ const UINT_PATTERN = /^\d+$/;
9
+ function toGwei(wei) {
10
+ return (0, __1.formattedAmountForDisplay)(wei, 9, {
11
+ useGroupSeparator: false,
12
+ decimalsToShow: 9,
13
+ });
14
+ }
15
+ function tryParseGweiToWei(input) {
16
+ const valueNormalized = input.trim().replace(/,/g, '.');
17
+ if (!valueNormalized || valueNormalized === '.')
18
+ return null;
19
+ if (!DECIMAL_PATTERN.test(valueNormalized))
20
+ return null;
21
+ try {
22
+ return (0, __1.parsedAmount)(valueNormalized, 9);
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ function parseGasLimit(input) {
29
+ const trimmed = input.trim().replace(/\s/g, '');
30
+ if (!UINT_PATTERN.test(trimmed))
31
+ return null;
32
+ const value = BigInt(trimmed);
33
+ // 21000 is the minimum - protcol-enforced floor for any tx
34
+ if (value < 21000n)
35
+ return null;
36
+ return value;
37
+ }
@@ -8,6 +8,7 @@ export interface NetworkField {
8
8
  iconUrl: string;
9
9
  symbol: string;
10
10
  failoverRpcUrl?: string;
11
+ blockTime?: number;
11
12
  }
12
13
  export interface NetworkRegistry {
13
14
  category: string;
@@ -12,6 +12,7 @@ export const NETWORKS_REGISTRY = [
12
12
  iconUrl: 'https://assets.coingecko.com/coins/images/279/large/ethereum.png',
13
13
  symbol: 'ETH',
14
14
  failoverRpcUrl: 'https://eth.llamarpc.com',
15
+ blockTime: 12,
15
16
  },
16
17
  {
17
18
  id: 'bnb-smart-chain',
@@ -19,10 +20,11 @@ export const NETWORKS_REGISTRY = [
19
20
  nameForDisplay: 'BNB Smart Chain',
20
21
  chainId: 56,
21
22
  rpcUrl: 'https://bsc-dataseed.bnbchain.org',
22
- explorerUrl: 'https://bscscan.com/',
23
+ explorerUrl: 'https://bscscan.com',
23
24
  iconUrl: 'https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png',
24
25
  symbol: 'BNB',
25
26
  failoverRpcUrl: 'https://bsc.llamarpc.com',
27
+ blockTime: 3,
26
28
  },
27
29
  {
28
30
  id: 'polygon-mainnet',
@@ -34,6 +36,7 @@ export const NETWORKS_REGISTRY = [
34
36
  explorerUrl: 'https://polygonscan.com',
35
37
  symbol: 'POL',
36
38
  failoverRpcUrl: 'https://polygon.llamarpc.com',
39
+ blockTime: 2,
37
40
  },
38
41
  {
39
42
  id: 'arbitrum-mainnet',
@@ -45,6 +48,7 @@ export const NETWORKS_REGISTRY = [
45
48
  iconUrl: 'https://assets.coingecko.com/coins/images/16547/large/photo_2023-03-29_21.47.00.jpeg',
46
49
  symbol: 'ARB',
47
50
  failoverRpcUrl: 'https://arb.llamarpc.com',
51
+ blockTime: 1,
48
52
  },
49
53
  ],
50
54
  },
@@ -61,6 +65,7 @@ export const NETWORKS_REGISTRY = [
61
65
  iconUrl: 'https://assets.coingecko.com/coins/images/279/large/ethereum.png',
62
66
  symbol: 'ETH',
63
67
  failoverRpcUrl: 'https://eth-sepolia.llamarpc.com',
68
+ blockTime: 12,
64
69
  },
65
70
  ],
66
71
  },
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import ERC20_TOKEN_CONTRACT_ABI from './ABIs/ERC20_TOKEN_CONTRACT_ABI';
3
3
  export { ERC20_TOKEN_CONTRACT_ABI };
4
4
  /** constants exports */
5
5
  export { GAS_LIMIT_PER_TX_TYPE, MULTICALL3_ADDRESS } from './constants/constants';
6
- export { NetworkField, NetworkRegistry, NETWORKS_REGISTRY, } from './constants/NETWORKS_REGISTRY';
6
+ export { NetworkField, NetworkRegistry, NETWORKS_REGISTRY } from './constants/NETWORKS_REGISTRY';
7
7
  export { BASIC_TOKENS_BY_CHAIN, BasicTokenData, BasicTokenSymbol, ChainTokenDataMap, } from './constants/BASIC_TOKENS_REGISTRY';
8
8
  /** basic blockchain exports */
9
9
  export { buildBaseUnsignedTransferTx, buildMaxNativeTransferTx, buildUnsignedTransferTx, } from './blockchain/buildUnsignedTransferTx';
@@ -26,5 +26,7 @@ export { NATIVE_TOKENS };
26
26
  export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
27
27
  export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
28
28
  export { normalizeAddress } from './utils/normalizeAddress';
29
+ export { toGwei, tryParseGweiToWei, parseGasLimit } from './utils/parseGasFees';
30
+ export { getFeePresets, calcReserve, estimateSeconds, getBlockTime, BLOCK_TIME_BY_CHAIN, } from './utils/feePresets';
29
31
  /** types exports */
30
- export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, BuildBaseUnsignedTransferTxParams, TxStatusResponse, EstimateTransactionOptions, EstimateTransactionResult, PrepareTransactionParams, PrepareTransactionResult, FormatAmountOptions, TransactionRequest, GetBalanceParams, GetBalancesParams, GetBalancesChainRequest, GetBalanceResult, ChainBalances, TokenBalance, ChainGroup, } from './types/common';
32
+ export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, BuildBaseUnsignedTransferTxParams, TxStatusResponse, EstimateTransactionOptions, EstimateTransactionResult, PrepareTransactionParams, PrepareTransactionResult, FormatAmountOptions, TransactionRequest, GetBalanceParams, GetBalancesParams, GetBalancesChainRequest, GetBalanceResult, ChainBalances, TokenBalance, ChainGroup, FeePreset, FeePresetLabel, FeeEstimateSeconds, ResolvedFees, EIP1559Fees, LegacyFees, FeeModel, FeeHistoryData, FeeDataInput, } from './types/common';
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import ERC20_TOKEN_CONTRACT_ABI from './ABIs/ERC20_TOKEN_CONTRACT_ABI';
3
3
  export { ERC20_TOKEN_CONTRACT_ABI };
4
4
  /** constants exports */
5
5
  export { GAS_LIMIT_PER_TX_TYPE, MULTICALL3_ADDRESS } from './constants/constants';
6
- export { NETWORKS_REGISTRY, } from './constants/NETWORKS_REGISTRY';
6
+ export { NETWORKS_REGISTRY } from './constants/NETWORKS_REGISTRY';
7
7
  export { BASIC_TOKENS_BY_CHAIN, } from './constants/BASIC_TOKENS_REGISTRY';
8
8
  /** basic blockchain exports */
9
9
  export { buildBaseUnsignedTransferTx, buildMaxNativeTransferTx, buildUnsignedTransferTx, } from './blockchain/buildUnsignedTransferTx';
@@ -25,3 +25,5 @@ export { NATIVE_TOKENS };
25
25
  export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
26
26
  export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
27
27
  export { normalizeAddress } from './utils/normalizeAddress';
28
+ export { toGwei, tryParseGweiToWei, parseGasLimit } from './utils/parseGasFees';
29
+ export { getFeePresets, calcReserve, estimateSeconds, getBlockTime, BLOCK_TIME_BY_CHAIN, } from './utils/feePresets';
@@ -130,3 +130,46 @@ export interface ChainGroup {
130
130
  nativeBalanceRequests: GetBalanceParams[];
131
131
  tokenBalanceRequests: GetBalanceParams[];
132
132
  }
133
+ export type EIP1559Fees = {
134
+ mode: 'eip1559';
135
+ maxFeePerGas: bigint;
136
+ maxPriorityFeePerGas: bigint;
137
+ gasLimit: bigint;
138
+ };
139
+ export type LegacyFees = {
140
+ mode: 'legacy';
141
+ gasPrice: bigint;
142
+ gasLimit: bigint;
143
+ };
144
+ export type ResolvedFees = EIP1559Fees | LegacyFees;
145
+ export type FeeModel = 'eip1559' | 'legacy';
146
+ export type FeePresetLabel = 'Low' | 'Standard' | 'High';
147
+ export type FeeEstimateSeconds = {
148
+ min: number;
149
+ max: number;
150
+ };
151
+ export type FeePreset = {
152
+ label: FeePresetLabel;
153
+ fees: ResolvedFees;
154
+ humanReadableGasReserve: string;
155
+ humanReadableEstimatedCost: string;
156
+ estimatedSeconds?: FeeEstimateSeconds;
157
+ };
158
+ export type FeeHistoryData = {
159
+ currentBaseFee: string;
160
+ range12h: {
161
+ minBaseFee: string;
162
+ maxBaseFee: string;
163
+ minPriorityFee: string;
164
+ maxPriorityFee: string;
165
+ };
166
+ };
167
+ export type FeeDataInput = {
168
+ chainId?: number;
169
+ gasLimit?: bigint | string | number;
170
+ feeData?: {
171
+ maxFeePerGas?: bigint | string;
172
+ maxPriorityFeePerGas?: bigint | string;
173
+ gasPrice?: bigint | string;
174
+ };
175
+ };
@@ -0,0 +1,6 @@
1
+ import { FeeDataInput, FeeEstimateSeconds, FeePreset } from '../types/common';
2
+ export declare const BLOCK_TIME_BY_CHAIN: Record<number, number>;
3
+ export declare function getBlockTime(chainId: number): number;
4
+ export declare function calcReserve(gasLimit: bigint, pricePerGas: bigint): string;
5
+ export declare function estimateSeconds(presetPriority: bigint, standardPriority: bigint, blockTime: number): FeeEstimateSeconds;
6
+ export declare function getFeePresets(tx: FeeDataInput): FeePreset[];
@@ -0,0 +1,78 @@
1
+ import { NETWORKS_REGISTRY } from '../constants/NETWORKS_REGISTRY';
2
+ import { formattedAmountForDisplay } from './formatAmount';
3
+ const DEFAULT_BLOCK_TIME = 12;
4
+ const FORMAT_OPTS = { useGroupSeparator: false, decimalsToShow: 18 };
5
+ export const BLOCK_TIME_BY_CHAIN = Object.fromEntries(NETWORKS_REGISTRY.flatMap((r) => r.networks)
6
+ .filter((n) => n.blockTime != null)
7
+ .map((n) => [n.chainId, n.blockTime]));
8
+ export function getBlockTime(chainId) {
9
+ return BLOCK_TIME_BY_CHAIN[chainId] ?? DEFAULT_BLOCK_TIME;
10
+ }
11
+ export function calcReserve(gasLimit, pricePerGas) {
12
+ return formattedAmountForDisplay(gasLimit * pricePerGas, 18, FORMAT_OPTS);
13
+ }
14
+ export function estimateSeconds(presetPriority, standardPriority, blockTime) {
15
+ if (standardPriority === 0n) {
16
+ return { min: blockTime, max: blockTime * 4 };
17
+ }
18
+ const ratio = Number((presetPriority * 1000n) / standardPriority) / 1000;
19
+ if (ratio >= 1.4)
20
+ return { min: blockTime, max: blockTime * 2 };
21
+ if (ratio >= 0.9)
22
+ return { min: blockTime, max: blockTime * 3 };
23
+ return { min: blockTime, max: blockTime * 4 };
24
+ }
25
+ export function getFeePresets(tx) {
26
+ const builtTx = tx;
27
+ const { maxFeePerGas, maxPriorityFeePerGas, gasPrice } = builtTx.feeData ?? {};
28
+ const gasLimit = builtTx.gasLimit
29
+ ? BigInt(builtTx.gasLimit)
30
+ : BigInt(builtTx.unsignedTx?.gasLimit ?? 21000);
31
+ // EIP-1559
32
+ if (maxFeePerGas != null && maxPriorityFeePerGas != null) {
33
+ const priority = BigInt(maxPriorityFeePerGas);
34
+ const baseFee = BigInt(maxFeePerGas) - BigInt(maxPriorityFeePerGas);
35
+ const estimatedCostPerGas = (priority) => baseFee + priority;
36
+ const chainId = builtTx.unsignedTx?.chainId ?? 1;
37
+ const blockTime = getBlockTime(chainId);
38
+ const lowPriority = (priority * 75n) / 100n;
39
+ const highPriority = (priority * 150n) / 100n;
40
+ const build = (label, priority, seconds) => {
41
+ const presetMaxFeePerGas = baseFee + priority;
42
+ return {
43
+ label,
44
+ fees: {
45
+ mode: 'eip1559',
46
+ maxFeePerGas: presetMaxFeePerGas,
47
+ maxPriorityFeePerGas: priority,
48
+ gasLimit,
49
+ },
50
+ humanReadableGasReserve: calcReserve(gasLimit, presetMaxFeePerGas),
51
+ humanReadableEstimatedCost: calcReserve(gasLimit, estimatedCostPerGas(priority)),
52
+ estimatedSeconds: seconds,
53
+ };
54
+ };
55
+ return [
56
+ build('Low', lowPriority, estimateSeconds(lowPriority, priority, blockTime)),
57
+ build('Standard', priority, estimateSeconds(priority, priority, blockTime)),
58
+ build('High', highPriority, estimateSeconds(highPriority, priority, blockTime)),
59
+ ];
60
+ }
61
+ // Legacy
62
+ if (gasPrice != null) {
63
+ const price = BigInt(gasPrice);
64
+ const build = (label, price, estimatedSeconds) => ({
65
+ label,
66
+ fees: { mode: 'legacy', gasPrice: price, gasLimit },
67
+ humanReadableGasReserve: calcReserve(gasLimit, price),
68
+ humanReadableEstimatedCost: calcReserve(gasLimit, price),
69
+ estimatedSeconds,
70
+ });
71
+ return [
72
+ build('Low', (price * 90n) / 100n, { min: 180, max: 180 }),
73
+ build('Standard', price, { min: 60, max: 60 }),
74
+ build('High', (price * 115n) / 100n, { min: 20, max: 20 }),
75
+ ];
76
+ }
77
+ throw new Error('feeData missing from unsignedTx');
78
+ }
@@ -0,0 +1,3 @@
1
+ export declare function toGwei(wei: bigint): string;
2
+ export declare function tryParseGweiToWei(input: string): bigint | null;
3
+ export declare function parseGasLimit(input: string): bigint | null;
@@ -0,0 +1,32 @@
1
+ import { formattedAmountForDisplay, parsedAmount } from '..';
2
+ const DECIMAL_PATTERN = /^\d*(\.\d*)?$/;
3
+ const UINT_PATTERN = /^\d+$/;
4
+ export function toGwei(wei) {
5
+ return formattedAmountForDisplay(wei, 9, {
6
+ useGroupSeparator: false,
7
+ decimalsToShow: 9,
8
+ });
9
+ }
10
+ export function tryParseGweiToWei(input) {
11
+ const valueNormalized = input.trim().replace(/,/g, '.');
12
+ if (!valueNormalized || valueNormalized === '.')
13
+ return null;
14
+ if (!DECIMAL_PATTERN.test(valueNormalized))
15
+ return null;
16
+ try {
17
+ return parsedAmount(valueNormalized, 9);
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ export function parseGasLimit(input) {
24
+ const trimmed = input.trim().replace(/\s/g, '');
25
+ if (!UINT_PATTERN.test(trimmed))
26
+ return null;
27
+ const value = BigInt(trimmed);
28
+ // 21000 is the minimum - protcol-enforced floor for any tx
29
+ if (value < 21000n)
30
+ return null;
31
+ return value;
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@octaflowlabs/onchain-sdk",
3
- "version": "1.3.8",
3
+ "version": "1.4.1",
4
4
  "description": "onchain methods for web3",
5
5
  "repository": "https://github.com/crisramb665/onchain-sdk.git",
6
6
  "license": "MIT",