@octaflowlabs/onchain-sdk 1.0.0-test10 → 1.0.0-test11
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/blockchain/buildUnsignedTransferTx.d.ts +2 -1
- package/dist/blockchain/buildUnsignedTransferTx.js +36 -1
- package/dist/cjs/blockchain/buildUnsignedTransferTx.d.ts +2 -1
- package/dist/cjs/blockchain/buildUnsignedTransferTx.js +37 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/types/common.d.ts +16 -0
- package/dist/cjs/utils/formatAmount.d.ts +6 -0
- package/dist/cjs/utils/formatAmount.js +55 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/types/common.d.ts +16 -0
- package/dist/utils/formatAmount.d.ts +6 -0
- package/dist/utils/formatAmount.js +50 -0
- package/package.json +1 -1
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { BuildUnsignedTransferTxOptions, UnsignedTransferTxResponse } from '../types/common';
|
|
1
|
+
import { BuildMaxNativeTransferTxOptions, BuildMaxNativeTransferTxResponse, BuildUnsignedTransferTxOptions, UnsignedTransferTxResponse } from '../types/common';
|
|
2
2
|
export declare const buildUnsignedTransferTx: (options: BuildUnsignedTransferTxOptions) => Promise<UnsignedTransferTxResponse>;
|
|
3
|
+
export declare const buildMaxNativeTransferTx: (options: BuildMaxNativeTransferTxOptions) => Promise<BuildMaxNativeTransferTxResponse>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** npm imports */
|
|
2
|
-
import { Interface, parseUnits } from 'ethers';
|
|
2
|
+
import { Interface, formatUnits, parseUnits } from 'ethers';
|
|
3
3
|
/** local imports */
|
|
4
4
|
import { getProvider } from './getProvider';
|
|
5
5
|
import { estimateGasLimitFromProvider } from './estimateGasLimitFromProvider';
|
|
@@ -60,6 +60,11 @@ export const buildUnsignedTransferTx = async (options) => {
|
|
|
60
60
|
};
|
|
61
61
|
if (estimateGas.feeData.gasPrice)
|
|
62
62
|
unsignedTxToReturn.gasPrice = estimateGas.feeData.gasPrice.toString();
|
|
63
|
+
const gasReserve = estimateGas.feeData.maxFeePerGas
|
|
64
|
+
? estimateGas.gasLimit * estimateGas.feeData.maxFeePerGas
|
|
65
|
+
: estimateGas.feeData.gasPrice
|
|
66
|
+
? estimateGas.gasLimit * estimateGas.feeData.gasPrice
|
|
67
|
+
: undefined;
|
|
63
68
|
try {
|
|
64
69
|
await provider.call({
|
|
65
70
|
from: options.fromAddress,
|
|
@@ -78,6 +83,7 @@ export const buildUnsignedTransferTx = async (options) => {
|
|
|
78
83
|
nonce,
|
|
79
84
|
gasEstimated: estimateGas.gasEstimated.toString(),
|
|
80
85
|
gasLimit: estimateGas.gasLimit.toString(),
|
|
86
|
+
gasReserve: gasReserve?.toString(),
|
|
81
87
|
bufferPercentage: estimateGas.bufferPercentage,
|
|
82
88
|
feeData: {
|
|
83
89
|
maxFeePerGas: estimateGas.feeData.maxFeePerGas?.toString(),
|
|
@@ -93,3 +99,32 @@ export const buildUnsignedTransferTx = async (options) => {
|
|
|
93
99
|
throw error;
|
|
94
100
|
}
|
|
95
101
|
};
|
|
102
|
+
export const buildMaxNativeTransferTx = async (options) => {
|
|
103
|
+
const isNativeToken = !options.tokenAddress ||
|
|
104
|
+
options.tokenAddress?.toLowerCase() === '0x0000000000000000000000000000000000000000' ||
|
|
105
|
+
options.tokenAddress?.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
|
|
106
|
+
if (!isNativeToken)
|
|
107
|
+
throw new Error('Max native transfer requires a native token address');
|
|
108
|
+
const provisionalTx = await buildUnsignedTransferTx({
|
|
109
|
+
...options,
|
|
110
|
+
value: options.balance,
|
|
111
|
+
tokenAddress: options.tokenAddress,
|
|
112
|
+
});
|
|
113
|
+
if (!provisionalTx.gasReserve)
|
|
114
|
+
throw new Error('Could not determine gas reserve for max send');
|
|
115
|
+
const balanceWei = parseUnits(options.balance, 18);
|
|
116
|
+
const gasReserveWei = BigInt(provisionalTx.gasReserve);
|
|
117
|
+
const sendableWei = balanceWei - gasReserveWei;
|
|
118
|
+
if (sendableWei <= 0n)
|
|
119
|
+
throw new Error('Insufficient balance to cover gas reserve');
|
|
120
|
+
const sendableValue = formatUnits(sendableWei, 18);
|
|
121
|
+
const finalTx = await buildUnsignedTransferTx({
|
|
122
|
+
...options,
|
|
123
|
+
value: sendableValue,
|
|
124
|
+
tokenAddress: options.tokenAddress,
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
...finalTx,
|
|
128
|
+
sendableValue,
|
|
129
|
+
};
|
|
130
|
+
};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { BuildUnsignedTransferTxOptions, UnsignedTransferTxResponse } from '../types/common';
|
|
1
|
+
import { BuildMaxNativeTransferTxOptions, BuildMaxNativeTransferTxResponse, BuildUnsignedTransferTxOptions, UnsignedTransferTxResponse } from '../types/common';
|
|
2
2
|
export declare const buildUnsignedTransferTx: (options: BuildUnsignedTransferTxOptions) => Promise<UnsignedTransferTxResponse>;
|
|
3
|
+
export declare const buildMaxNativeTransferTx: (options: BuildMaxNativeTransferTxOptions) => Promise<BuildMaxNativeTransferTxResponse>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildUnsignedTransferTx = void 0;
|
|
3
|
+
exports.buildMaxNativeTransferTx = exports.buildUnsignedTransferTx = void 0;
|
|
4
4
|
/** npm imports */
|
|
5
5
|
const ethers_1 = require("ethers");
|
|
6
6
|
/** local imports */
|
|
@@ -63,6 +63,11 @@ const buildUnsignedTransferTx = async (options) => {
|
|
|
63
63
|
};
|
|
64
64
|
if (estimateGas.feeData.gasPrice)
|
|
65
65
|
unsignedTxToReturn.gasPrice = estimateGas.feeData.gasPrice.toString();
|
|
66
|
+
const gasReserve = estimateGas.feeData.maxFeePerGas
|
|
67
|
+
? estimateGas.gasLimit * estimateGas.feeData.maxFeePerGas
|
|
68
|
+
: estimateGas.feeData.gasPrice
|
|
69
|
+
? estimateGas.gasLimit * estimateGas.feeData.gasPrice
|
|
70
|
+
: undefined;
|
|
66
71
|
try {
|
|
67
72
|
await provider.call({
|
|
68
73
|
from: options.fromAddress,
|
|
@@ -81,6 +86,7 @@ const buildUnsignedTransferTx = async (options) => {
|
|
|
81
86
|
nonce,
|
|
82
87
|
gasEstimated: estimateGas.gasEstimated.toString(),
|
|
83
88
|
gasLimit: estimateGas.gasLimit.toString(),
|
|
89
|
+
gasReserve: gasReserve?.toString(),
|
|
84
90
|
bufferPercentage: estimateGas.bufferPercentage,
|
|
85
91
|
feeData: {
|
|
86
92
|
maxFeePerGas: estimateGas.feeData.maxFeePerGas?.toString(),
|
|
@@ -97,3 +103,33 @@ const buildUnsignedTransferTx = async (options) => {
|
|
|
97
103
|
}
|
|
98
104
|
};
|
|
99
105
|
exports.buildUnsignedTransferTx = buildUnsignedTransferTx;
|
|
106
|
+
const buildMaxNativeTransferTx = async (options) => {
|
|
107
|
+
const isNativeToken = !options.tokenAddress ||
|
|
108
|
+
options.tokenAddress?.toLowerCase() === '0x0000000000000000000000000000000000000000' ||
|
|
109
|
+
options.tokenAddress?.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
|
|
110
|
+
if (!isNativeToken)
|
|
111
|
+
throw new Error('Max native transfer requires a native token address');
|
|
112
|
+
const provisionalTx = await (0, exports.buildUnsignedTransferTx)({
|
|
113
|
+
...options,
|
|
114
|
+
value: options.balance,
|
|
115
|
+
tokenAddress: options.tokenAddress,
|
|
116
|
+
});
|
|
117
|
+
if (!provisionalTx.gasReserve)
|
|
118
|
+
throw new Error('Could not determine gas reserve for max send');
|
|
119
|
+
const balanceWei = (0, ethers_1.parseUnits)(options.balance, 18);
|
|
120
|
+
const gasReserveWei = BigInt(provisionalTx.gasReserve);
|
|
121
|
+
const sendableWei = balanceWei - gasReserveWei;
|
|
122
|
+
if (sendableWei <= 0n)
|
|
123
|
+
throw new Error('Insufficient balance to cover gas reserve');
|
|
124
|
+
const sendableValue = (0, ethers_1.formatUnits)(sendableWei, 18);
|
|
125
|
+
const finalTx = await (0, exports.buildUnsignedTransferTx)({
|
|
126
|
+
...options,
|
|
127
|
+
value: sendableValue,
|
|
128
|
+
tokenAddress: options.tokenAddress,
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
...finalTx,
|
|
132
|
+
sendableValue,
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
exports.buildMaxNativeTransferTx = buildMaxNativeTransferTx;
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { ERC20_TOKEN_CONTRACT_ABI };
|
|
|
4
4
|
/** constants exports */
|
|
5
5
|
export { GAS_LIMIT_PER_TX_TYPE } from './constants/constants';
|
|
6
6
|
/** basic blockchain exports */
|
|
7
|
-
export { buildUnsignedTransferTx } from './blockchain/buildUnsignedTransferTx';
|
|
7
|
+
export { buildMaxNativeTransferTx, buildUnsignedTransferTx } from './blockchain/buildUnsignedTransferTx';
|
|
8
8
|
export { broadcastTransaction } from './blockchain/broadcastTransaction';
|
|
9
9
|
export { estimateGasLimitFromProvider } from './blockchain/estimateGasLimitFromProvider';
|
|
10
10
|
export { getProvider } from './blockchain/getProvider';
|
|
@@ -15,4 +15,4 @@ export { transformBigInt } from './utils/transformBigInt';
|
|
|
15
15
|
import NATIVE_TOKENS from './utils/tokens';
|
|
16
16
|
export { NATIVE_TOKENS };
|
|
17
17
|
/** types exports */
|
|
18
|
-
export { BroadcastTransactionOptions, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, TxStatusResponse, UnsignedTransferTxResponse, } from './types/common';
|
|
18
|
+
export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildMaxNativeTransferTxResponse, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, TxStatusResponse, UnsignedTransferTxResponse, FormatAmountOptions, } 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.NATIVE_TOKENS = exports.transformBigInt = exports.getShortenTransactionHash = exports.txStatus = exports.getProvider = exports.estimateGasLimitFromProvider = exports.broadcastTransaction = exports.buildUnsignedTransferTx = exports.GAS_LIMIT_PER_TX_TYPE = exports.ERC20_TOKEN_CONTRACT_ABI = void 0;
|
|
6
|
+
exports.NATIVE_TOKENS = exports.transformBigInt = exports.getShortenTransactionHash = exports.txStatus = exports.getProvider = exports.estimateGasLimitFromProvider = exports.broadcastTransaction = exports.buildUnsignedTransferTx = exports.buildMaxNativeTransferTx = 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;
|
|
@@ -12,6 +12,7 @@ var constants_1 = require("./constants/constants");
|
|
|
12
12
|
Object.defineProperty(exports, "GAS_LIMIT_PER_TX_TYPE", { enumerable: true, get: function () { return constants_1.GAS_LIMIT_PER_TX_TYPE; } });
|
|
13
13
|
/** basic blockchain exports */
|
|
14
14
|
var buildUnsignedTransferTx_1 = require("./blockchain/buildUnsignedTransferTx");
|
|
15
|
+
Object.defineProperty(exports, "buildMaxNativeTransferTx", { enumerable: true, get: function () { return buildUnsignedTransferTx_1.buildMaxNativeTransferTx; } });
|
|
15
16
|
Object.defineProperty(exports, "buildUnsignedTransferTx", { enumerable: true, get: function () { return buildUnsignedTransferTx_1.buildUnsignedTransferTx; } });
|
|
16
17
|
var broadcastTransaction_1 = require("./blockchain/broadcastTransaction");
|
|
17
18
|
Object.defineProperty(exports, "broadcastTransaction", { enumerable: true, get: function () { return broadcastTransaction_1.broadcastTransaction; } });
|
|
@@ -33,6 +33,7 @@ export interface UnsignedTransferTxResponse {
|
|
|
33
33
|
nonce: number;
|
|
34
34
|
gasEstimated: string;
|
|
35
35
|
gasLimit: string;
|
|
36
|
+
gasReserve?: string;
|
|
36
37
|
bufferPercentage: number;
|
|
37
38
|
feeData: {
|
|
38
39
|
maxFeePerGas?: string;
|
|
@@ -40,6 +41,13 @@ export interface UnsignedTransferTxResponse {
|
|
|
40
41
|
gasPrice?: string;
|
|
41
42
|
};
|
|
42
43
|
}
|
|
44
|
+
export interface BuildMaxNativeTransferTxOptions extends Omit<BuildUnsignedTransferTxOptions, 'value' | 'tokenAddress' | 'tokenDecimals'> {
|
|
45
|
+
balance: string;
|
|
46
|
+
tokenAddress?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface BuildMaxNativeTransferTxResponse extends UnsignedTransferTxResponse {
|
|
49
|
+
sendableValue: string;
|
|
50
|
+
}
|
|
43
51
|
export interface BroadcastTransactionOptions {
|
|
44
52
|
signedTx: string;
|
|
45
53
|
rpcUrl: string;
|
|
@@ -55,3 +63,11 @@ export interface TxStatusResponse {
|
|
|
55
63
|
success: boolean;
|
|
56
64
|
receipt: TransactionReceipt | null;
|
|
57
65
|
}
|
|
66
|
+
export interface FormatAmountOptions {
|
|
67
|
+
decimalsToShow?: number;
|
|
68
|
+
useGroupSeparator?: boolean;
|
|
69
|
+
locale?: string;
|
|
70
|
+
minimumFractionDigits?: number;
|
|
71
|
+
minDisplayDecimals?: number;
|
|
72
|
+
maxDisplayDigits?: number;
|
|
73
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** npm imports */
|
|
2
|
+
import { BigNumberish } from 'ethers';
|
|
3
|
+
/** local imports */
|
|
4
|
+
import { FormatAmountOptions } from '../types/common';
|
|
5
|
+
export declare const formattedAmountForDisplay: (amount: BigNumberish, decimals: number, options?: FormatAmountOptions) => string;
|
|
6
|
+
export declare const parsedAmount: (amount: string, decimals: number) => bigint;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parsedAmount = exports.formattedAmountForDisplay = void 0;
|
|
4
|
+
/** npm imports */
|
|
5
|
+
const ethers_1 = require("ethers");
|
|
6
|
+
const formattedAmountForDisplay = (amount, decimals, options = {}) => {
|
|
7
|
+
const { decimalsToShow = 0, useGroupSeparator = true, locale = 'en-US', minimumFractionDigits, minDisplayDecimals = 9, maxDisplayDigits = 16, } = options;
|
|
8
|
+
const formattedAmount = (0, ethers_1.formatUnits)(amount, decimals);
|
|
9
|
+
if (formattedAmount.startsWith('-')) {
|
|
10
|
+
throw new Error('Negative balances are not supported');
|
|
11
|
+
}
|
|
12
|
+
const [wholePart = '0', fractionPart = ''] = formattedAmount.split('.');
|
|
13
|
+
if (wholePart.length >= maxDisplayDigits) {
|
|
14
|
+
const mantissaWhole = wholePart[0] ?? '0';
|
|
15
|
+
const mantissaFraction = (wholePart.slice(1) + fractionPart).slice(0, decimalsToShow);
|
|
16
|
+
const exponent = wholePart.length - 1;
|
|
17
|
+
const rawMantissa = mantissaFraction ? `${mantissaWhole}.${mantissaFraction}` : mantissaWhole;
|
|
18
|
+
const trimmedMantissa = rawMantissa.replace(/\.0+$|(?<=\.[0-9]*?)0+$/g, '').replace(/\.$/, '');
|
|
19
|
+
return `${trimmedMantissa}e${exponent}`;
|
|
20
|
+
}
|
|
21
|
+
const firstNonZeroIndex = fractionPart.split('').findIndex((digit) => digit !== '0');
|
|
22
|
+
const hasNonZeroFraction = firstNonZeroIndex !== -1;
|
|
23
|
+
if (hasNonZeroFraction && wholePart === '0' && firstNonZeroIndex >= minDisplayDecimals) {
|
|
24
|
+
const sample = new Intl.NumberFormat(locale).format(1000.1);
|
|
25
|
+
const decimalSeparator = sample.replace(/\d/g, '').slice(-1) ?? '.';
|
|
26
|
+
const minValue = `0${decimalSeparator}${'0'.repeat(Math.max(0, minDisplayDecimals - 1))}1`;
|
|
27
|
+
return `< ${minValue}`;
|
|
28
|
+
}
|
|
29
|
+
if (!hasNonZeroFraction) {
|
|
30
|
+
const sample = new Intl.NumberFormat(locale).format(1000.1);
|
|
31
|
+
const groupSeparator = sample.replace(/\d/g, '')[0] ?? ',';
|
|
32
|
+
const groupedWhole = useGroupSeparator
|
|
33
|
+
? (wholePart || '0').replace(/\B(?=(\d{3})+(?!\d))/g, groupSeparator)
|
|
34
|
+
: wholePart;
|
|
35
|
+
return groupedWhole;
|
|
36
|
+
}
|
|
37
|
+
const maxDecimals = decimalsToShow ?? fractionPart.length;
|
|
38
|
+
let trimmedFraction = fractionPart.slice(0, Math.max(0, maxDecimals));
|
|
39
|
+
const minDecimals = minimumFractionDigits ?? 0;
|
|
40
|
+
if (trimmedFraction.length < minDecimals) {
|
|
41
|
+
trimmedFraction = trimmedFraction.padEnd(minDecimals, '0');
|
|
42
|
+
}
|
|
43
|
+
const sample = new Intl.NumberFormat(locale).format(1000.1);
|
|
44
|
+
const groupSeparator = sample.replace(/\d/g, '')[0] ?? ',';
|
|
45
|
+
const decimalSeparator = sample.replace(/\d/g, '').slice(-1) ?? '.';
|
|
46
|
+
const groupedWhole = useGroupSeparator
|
|
47
|
+
? (wholePart || '0').replace(/\B(?=(\d{3})+(?!\d))/g, groupSeparator)
|
|
48
|
+
: wholePart;
|
|
49
|
+
if (!trimmedFraction)
|
|
50
|
+
return groupedWhole;
|
|
51
|
+
return `${groupedWhole}${decimalSeparator}${trimmedFraction}`;
|
|
52
|
+
};
|
|
53
|
+
exports.formattedAmountForDisplay = formattedAmountForDisplay;
|
|
54
|
+
const parsedAmount = (amount, decimals) => (0, ethers_1.parseUnits)(amount, decimals);
|
|
55
|
+
exports.parsedAmount = parsedAmount;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { ERC20_TOKEN_CONTRACT_ABI };
|
|
|
4
4
|
/** constants exports */
|
|
5
5
|
export { GAS_LIMIT_PER_TX_TYPE } from './constants/constants';
|
|
6
6
|
/** basic blockchain exports */
|
|
7
|
-
export { buildUnsignedTransferTx } from './blockchain/buildUnsignedTransferTx';
|
|
7
|
+
export { buildMaxNativeTransferTx, buildUnsignedTransferTx } from './blockchain/buildUnsignedTransferTx';
|
|
8
8
|
export { broadcastTransaction } from './blockchain/broadcastTransaction';
|
|
9
9
|
export { estimateGasLimitFromProvider } from './blockchain/estimateGasLimitFromProvider';
|
|
10
10
|
export { getProvider } from './blockchain/getProvider';
|
|
@@ -15,4 +15,4 @@ export { transformBigInt } from './utils/transformBigInt';
|
|
|
15
15
|
import NATIVE_TOKENS from './utils/tokens';
|
|
16
16
|
export { NATIVE_TOKENS };
|
|
17
17
|
/** types exports */
|
|
18
|
-
export { BroadcastTransactionOptions, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, TxStatusResponse, UnsignedTransferTxResponse, } from './types/common';
|
|
18
|
+
export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildMaxNativeTransferTxResponse, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, TxStatusResponse, UnsignedTransferTxResponse, FormatAmountOptions, } from './types/common';
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export { ERC20_TOKEN_CONTRACT_ABI };
|
|
|
4
4
|
/** constants exports */
|
|
5
5
|
export { GAS_LIMIT_PER_TX_TYPE } from './constants/constants';
|
|
6
6
|
/** basic blockchain exports */
|
|
7
|
-
export { buildUnsignedTransferTx } from './blockchain/buildUnsignedTransferTx';
|
|
7
|
+
export { buildMaxNativeTransferTx, buildUnsignedTransferTx } from './blockchain/buildUnsignedTransferTx';
|
|
8
8
|
export { broadcastTransaction } from './blockchain/broadcastTransaction';
|
|
9
9
|
export { estimateGasLimitFromProvider } from './blockchain/estimateGasLimitFromProvider';
|
|
10
10
|
export { getProvider } from './blockchain/getProvider';
|
package/dist/types/common.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export interface UnsignedTransferTxResponse {
|
|
|
33
33
|
nonce: number;
|
|
34
34
|
gasEstimated: string;
|
|
35
35
|
gasLimit: string;
|
|
36
|
+
gasReserve?: string;
|
|
36
37
|
bufferPercentage: number;
|
|
37
38
|
feeData: {
|
|
38
39
|
maxFeePerGas?: string;
|
|
@@ -40,6 +41,13 @@ export interface UnsignedTransferTxResponse {
|
|
|
40
41
|
gasPrice?: string;
|
|
41
42
|
};
|
|
42
43
|
}
|
|
44
|
+
export interface BuildMaxNativeTransferTxOptions extends Omit<BuildUnsignedTransferTxOptions, 'value' | 'tokenAddress' | 'tokenDecimals'> {
|
|
45
|
+
balance: string;
|
|
46
|
+
tokenAddress?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface BuildMaxNativeTransferTxResponse extends UnsignedTransferTxResponse {
|
|
49
|
+
sendableValue: string;
|
|
50
|
+
}
|
|
43
51
|
export interface BroadcastTransactionOptions {
|
|
44
52
|
signedTx: string;
|
|
45
53
|
rpcUrl: string;
|
|
@@ -55,3 +63,11 @@ export interface TxStatusResponse {
|
|
|
55
63
|
success: boolean;
|
|
56
64
|
receipt: TransactionReceipt | null;
|
|
57
65
|
}
|
|
66
|
+
export interface FormatAmountOptions {
|
|
67
|
+
decimalsToShow?: number;
|
|
68
|
+
useGroupSeparator?: boolean;
|
|
69
|
+
locale?: string;
|
|
70
|
+
minimumFractionDigits?: number;
|
|
71
|
+
minDisplayDecimals?: number;
|
|
72
|
+
maxDisplayDigits?: number;
|
|
73
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** npm imports */
|
|
2
|
+
import { BigNumberish } from 'ethers';
|
|
3
|
+
/** local imports */
|
|
4
|
+
import { FormatAmountOptions } from '../types/common';
|
|
5
|
+
export declare const formattedAmountForDisplay: (amount: BigNumberish, decimals: number, options?: FormatAmountOptions) => string;
|
|
6
|
+
export declare const parsedAmount: (amount: string, decimals: number) => bigint;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** npm imports */
|
|
2
|
+
import { formatUnits, parseUnits } from 'ethers';
|
|
3
|
+
export const formattedAmountForDisplay = (amount, decimals, options = {}) => {
|
|
4
|
+
const { decimalsToShow = 0, useGroupSeparator = true, locale = 'en-US', minimumFractionDigits, minDisplayDecimals = 9, maxDisplayDigits = 16, } = options;
|
|
5
|
+
const formattedAmount = formatUnits(amount, decimals);
|
|
6
|
+
if (formattedAmount.startsWith('-')) {
|
|
7
|
+
throw new Error('Negative balances are not supported');
|
|
8
|
+
}
|
|
9
|
+
const [wholePart = '0', fractionPart = ''] = formattedAmount.split('.');
|
|
10
|
+
if (wholePart.length >= maxDisplayDigits) {
|
|
11
|
+
const mantissaWhole = wholePart[0] ?? '0';
|
|
12
|
+
const mantissaFraction = (wholePart.slice(1) + fractionPart).slice(0, decimalsToShow);
|
|
13
|
+
const exponent = wholePart.length - 1;
|
|
14
|
+
const rawMantissa = mantissaFraction ? `${mantissaWhole}.${mantissaFraction}` : mantissaWhole;
|
|
15
|
+
const trimmedMantissa = rawMantissa.replace(/\.0+$|(?<=\.[0-9]*?)0+$/g, '').replace(/\.$/, '');
|
|
16
|
+
return `${trimmedMantissa}e${exponent}`;
|
|
17
|
+
}
|
|
18
|
+
const firstNonZeroIndex = fractionPart.split('').findIndex((digit) => digit !== '0');
|
|
19
|
+
const hasNonZeroFraction = firstNonZeroIndex !== -1;
|
|
20
|
+
if (hasNonZeroFraction && wholePart === '0' && firstNonZeroIndex >= minDisplayDecimals) {
|
|
21
|
+
const sample = new Intl.NumberFormat(locale).format(1000.1);
|
|
22
|
+
const decimalSeparator = sample.replace(/\d/g, '').slice(-1) ?? '.';
|
|
23
|
+
const minValue = `0${decimalSeparator}${'0'.repeat(Math.max(0, minDisplayDecimals - 1))}1`;
|
|
24
|
+
return `< ${minValue}`;
|
|
25
|
+
}
|
|
26
|
+
if (!hasNonZeroFraction) {
|
|
27
|
+
const sample = new Intl.NumberFormat(locale).format(1000.1);
|
|
28
|
+
const groupSeparator = sample.replace(/\d/g, '')[0] ?? ',';
|
|
29
|
+
const groupedWhole = useGroupSeparator
|
|
30
|
+
? (wholePart || '0').replace(/\B(?=(\d{3})+(?!\d))/g, groupSeparator)
|
|
31
|
+
: wholePart;
|
|
32
|
+
return groupedWhole;
|
|
33
|
+
}
|
|
34
|
+
const maxDecimals = decimalsToShow ?? fractionPart.length;
|
|
35
|
+
let trimmedFraction = fractionPart.slice(0, Math.max(0, maxDecimals));
|
|
36
|
+
const minDecimals = minimumFractionDigits ?? 0;
|
|
37
|
+
if (trimmedFraction.length < minDecimals) {
|
|
38
|
+
trimmedFraction = trimmedFraction.padEnd(minDecimals, '0');
|
|
39
|
+
}
|
|
40
|
+
const sample = new Intl.NumberFormat(locale).format(1000.1);
|
|
41
|
+
const groupSeparator = sample.replace(/\d/g, '')[0] ?? ',';
|
|
42
|
+
const decimalSeparator = sample.replace(/\d/g, '').slice(-1) ?? '.';
|
|
43
|
+
const groupedWhole = useGroupSeparator
|
|
44
|
+
? (wholePart || '0').replace(/\B(?=(\d{3})+(?!\d))/g, groupSeparator)
|
|
45
|
+
: wholePart;
|
|
46
|
+
if (!trimmedFraction)
|
|
47
|
+
return groupedWhole;
|
|
48
|
+
return `${groupedWhole}${decimalSeparator}${trimmedFraction}`;
|
|
49
|
+
};
|
|
50
|
+
export const parsedAmount = (amount, decimals) => parseUnits(amount, decimals);
|