@exodus/ethereum-api 9.0.0-alpha.2 → 9.0.0
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 +2121 -0
- package/LICENSE +7 -0
- package/README.md +124 -0
- package/package.json +34 -33
- package/src/address-has-history.js +6 -2
- package/src/allowance/constants.js +4 -5
- package/src/allowance/index.js +159 -40
- package/src/check-tx/create-assess-transaction.js +23 -0
- package/src/check-tx/create-check-tx.js +104 -0
- package/src/check-tx/index.js +1 -0
- package/src/create-asset-plugin-factory.js +115 -0
- package/src/create-asset-utils.js +520 -0
- package/src/create-asset.js +272 -97
- package/src/create-token-factory.js +47 -17
- package/src/custom-fees.js +57 -0
- package/src/eip7702-whitelist.js +62 -0
- package/src/ens/index.js +12 -17
- package/src/error-wrapper.js +383 -0
- package/src/eth-like-util.js +172 -33
- package/src/exodus-eth-server/api-coin-nodes.js +27 -196
- package/src/exodus-eth-server/api.js +23 -14
- package/src/exodus-eth-server/clarity-v2.js +255 -0
- package/src/exodus-eth-server/clarity.js +67 -265
- package/src/exodus-eth-server/errors.js +40 -0
- package/src/exodus-eth-server/eth-like-server.js +385 -0
- package/src/exodus-eth-server/fetch-json.js +48 -0
- package/src/exodus-eth-server/index.js +77 -0
- package/src/exodus-eth-server/utils.js +31 -0
- package/src/exodus-eth-server/ws-gateway.js +306 -0
- package/src/exodus-eth-server/ws.js +1 -2
- package/src/fee-data/EthLikeFeeData.js +81 -0
- package/src/fee-data/index.js +54 -0
- package/src/fee-utils.js +229 -0
- package/src/gas-estimation.js +183 -66
- package/src/get-balance-for-address.js +1 -1
- package/src/get-balances.js +285 -27
- package/src/get-fee.js +92 -56
- package/src/get-historical-balance.js +58 -0
- package/src/hooks/index.js +1 -1
- package/src/hooks/monitor.js +182 -43
- package/src/hooks/staking-freshness.js +58 -0
- package/src/index.js +118 -12
- package/src/move-funds.js +153 -0
- package/src/multicall3/index.js +212 -0
- package/src/multisig-address.js +146 -0
- package/src/nft-utils.js +60 -0
- package/src/number-utils.js +34 -2
- package/src/optimism-gas/index.js +13 -5
- package/src/send-validations.js +58 -0
- package/src/server-based-fee-monitor.js +12 -19
- package/src/simulate-tx/fetch-tx-preview.js +0 -2
- package/src/simulate-tx/index.js +2 -2
- package/src/simulate-tx/simulate-eth-tx.js +24 -11
- package/src/simulation/common.js +34 -0
- package/src/simulation/create-simulate-message.js +49 -0
- package/src/simulation/create-simulate-transactions.js +108 -0
- package/src/simulation/estimate-fee.js +14 -0
- package/src/simulation/estimate-simple-transfer.js +15 -0
- package/src/simulation/get-message-type.js +18 -0
- package/src/simulation/simulate-message-api.js +68 -0
- package/src/simulation/simulate-transactions-api.js +266 -0
- package/src/simulation/simulate-transactions.js +16 -0
- package/src/simulation/transactions.js +52 -0
- package/src/simulation/try-estimating-changes-locally.js +26 -0
- package/src/staking/api/index.js +43 -0
- package/src/staking/cached-read.js +33 -0
- package/src/staking/ethereum/api.js +166 -34
- package/src/staking/ethereum/deps.js +37 -0
- package/src/staking/ethereum/everstake.js +113 -0
- package/src/staking/ethereum/index.js +4 -3
- package/src/staking/ethereum/service.js +682 -181
- package/src/staking/ethereum/staking-utils.js +275 -4
- package/src/staking/fantom-staking.js +9 -9
- package/src/staking/index.js +4 -4
- package/src/staking/matic/addresses.js +2 -0
- package/src/staking/matic/api.js +69 -49
- package/src/staking/matic/index.js +3 -3
- package/src/staking/matic/matic-staking-utils.js +243 -5
- package/src/staking/matic/matic-staking.md +53 -0
- package/src/staking/staking-provider-client.js +1 -1
- package/src/staking/utils/index.js +39 -0
- package/src/tx-create.js +666 -0
- package/src/tx-log/clarity-monitor.js +273 -103
- package/src/tx-log/clarity-truncated-history-monitor.js +109 -0
- package/src/tx-log/clarity-truncated-history-monitor.md +219 -0
- package/src/tx-log/clarity-utils/absolute.js +96 -0
- package/src/tx-log/clarity-utils/get-log-items-from-server-tx.js +94 -31
- package/src/tx-log/clarity-utils/get-names-of-tokens-transferred-by-server-tx.js +3 -2
- package/src/tx-log/clarity-utils/index.js +9 -3
- package/src/tx-log/clarity-utils/is-spam-pending-tx.js +13 -0
- package/src/tx-log/clarity-utils/normalize-transactions-response.js +65 -0
- package/src/tx-log/ethereum-monitor.js +93 -47
- package/src/tx-log/ethereum-no-history-monitor.js +52 -41
- package/src/tx-log/get-optimistic-txlog-effects.js +379 -0
- package/src/tx-log/index.js +5 -3
- package/src/tx-log/monitor-utils/check-pending-transactions.js +14 -5
- package/src/tx-log/monitor-utils/exclude-unchanged-token-balances.js +1 -1
- package/src/tx-log/monitor-utils/extract-balance-from-clarity-account-info.js +108 -0
- package/src/tx-log/monitor-utils/get-balance-updates.js +44 -0
- package/src/tx-log/monitor-utils/get-batched-rpc-balances.js +47 -0
- package/src/tx-log/monitor-utils/get-current-blacklist-status.js +38 -0
- package/src/tx-log/monitor-utils/get-current-eip7702-delegation.js +79 -0
- package/src/tx-log/monitor-utils/get-derive-transactions-to-check.js +10 -5
- package/src/tx-log/monitor-utils/get-fee-amount.js +1 -1
- package/src/tx-log/monitor-utils/get-history-from-server.js +1 -1
- package/src/tx-log/monitor-utils/get-log-items-from-server-tx.js +75 -33
- package/src/tx-log/monitor-utils/get-names-of-tokens-transferred-by-server-tx.js +3 -2
- package/src/tx-log/monitor-utils/get-raw-transfer-amount.js +29 -0
- package/src/tx-log/monitor-utils/get-transfers-by-token-name.js +3 -2
- package/src/tx-log/monitor-utils/get-value-of-transfers.js +10 -12
- package/src/tx-log/monitor-utils/index.js +12 -7
- package/src/tx-log/monitor-utils/is-unverifiable-pending-tx-expired.js +19 -0
- package/src/tx-log/monitor-utils/verify-pending-tx-status-rpc.js +90 -0
- package/src/tx-log-staking-processor/asset-staking-tx-data.js +82 -24
- package/src/tx-log-staking-processor/index.js +28 -14
- package/src/tx-log-staking-processor/utils.js +21 -20
- package/src/tx-send/broadcast-error-handler.js +63 -0
- package/src/tx-send/index.js +1 -2
- package/src/tx-send/nonce-utils.js +97 -0
- package/src/tx-send/tx-send.js +94 -288
- package/src/tx-sign/index.js +17 -0
- package/src/tx-type/index.js +280 -0
- package/src/watch-tx.js +36 -0
- package/src/web3/createSimulateMessage.js +3 -2
- package/src/web3/createSimulateTransactions.js +11 -0
- package/src/web3/index.js +3 -1
- package/src/etherscan/account.js +0 -49
- package/src/etherscan/index.js +0 -28
- package/src/etherscan/logs.js +0 -16
- package/src/etherscan/proxy.js +0 -47
- package/src/etherscan/request.js +0 -26
- package/src/etherscan/ws.js +0 -88
- package/src/exodus-eth-server/server-factory.js +0 -28
- package/src/exodus-eth-server/server-map.js +0 -21
- package/src/get-fee-async.js +0 -97
- package/src/staking/matic/service.js +0 -437
- package/src/staking-api.js +0 -5
- package/src/tx-log/clarity-utils/get-derive-data-needed-for-tick.js +0 -12
- package/src/tx-log-staking-processor/get-asset-tx-amount.js +0 -26
- package/src/tx-send/get-fee-info.js +0 -41
- package/src/websocket/index.android.js +0 -2
- package/src/websocket/index.ios.js +0 -2
- package/src/websocket/index.js +0 -21
package/src/get-fee-async.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import assert from 'minimalistic-assert'
|
|
2
|
-
import { fetchGasLimit } from './gas-estimation'
|
|
3
|
-
import { isForwarderContractCached } from './eth-like-util'
|
|
4
|
-
import { getFeeFactory } from './get-fee'
|
|
5
|
-
|
|
6
|
-
const FIXED_TRANSFER_GAS_LIMIT_ASSETS = new Set([
|
|
7
|
-
'amp',
|
|
8
|
-
'tetherusd',
|
|
9
|
-
'usdcoin',
|
|
10
|
-
'snx',
|
|
11
|
-
'geminidollar',
|
|
12
|
-
])
|
|
13
|
-
|
|
14
|
-
async function resolveExtraPercentage({ asset, toAddress }) {
|
|
15
|
-
const isToken = asset.name !== asset.baseAsset.name
|
|
16
|
-
// calling forwarder contracts with a bumped gas limit causes 'Out Of Gas' error on chain
|
|
17
|
-
const hasForwarderContract =
|
|
18
|
-
!isToken && toAddress ? await isForwarderContractCached({ asset, address: toAddress }) : false
|
|
19
|
-
|
|
20
|
-
return asset.baseAsset.estimateL1DataFee
|
|
21
|
-
? 100
|
|
22
|
-
: (isToken && FIXED_TRANSFER_GAS_LIMIT_ASSETS.has(asset.name)) || hasForwarderContract
|
|
23
|
-
? 0
|
|
24
|
-
: undefined
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const getFeeAsyncFactory = ({
|
|
28
|
-
assetClientInterface,
|
|
29
|
-
gasLimit: defaultGasLimit,
|
|
30
|
-
createUnsignedTx,
|
|
31
|
-
}) => {
|
|
32
|
-
assert(assetClientInterface, 'assetClientInterface is required')
|
|
33
|
-
assert(createUnsignedTx, 'createUnsignedTx is required')
|
|
34
|
-
const getFee = getFeeFactory({ gasLimit: defaultGasLimit })
|
|
35
|
-
return async ({
|
|
36
|
-
asset,
|
|
37
|
-
fromAddress = '0xffffffffffffffffffffffffffffffffffffffff', // sending from a random address
|
|
38
|
-
toAddress = '0xffffffffffffffffffffffffffffffffffffffff', // sending to a random address,
|
|
39
|
-
amount,
|
|
40
|
-
bip70,
|
|
41
|
-
txInput,
|
|
42
|
-
isExchange,
|
|
43
|
-
customFee,
|
|
44
|
-
calculateEffectiveFee,
|
|
45
|
-
isSendAll,
|
|
46
|
-
isRbfAllowed = true, // Destkop, isRbfAllowed=true when advanced panel is on
|
|
47
|
-
throwOnError = false,
|
|
48
|
-
}) => {
|
|
49
|
-
const extraPercentage = await resolveExtraPercentage({ asset, toAddress })
|
|
50
|
-
|
|
51
|
-
const gasLimit = await fetchGasLimit({
|
|
52
|
-
asset,
|
|
53
|
-
fromAddress,
|
|
54
|
-
toAddress,
|
|
55
|
-
txInput: txInput ?? '0x', // default value is '0x'
|
|
56
|
-
amount,
|
|
57
|
-
bip70,
|
|
58
|
-
throwOnError,
|
|
59
|
-
extraPercentage,
|
|
60
|
-
})
|
|
61
|
-
const feeData = await assetClientInterface.getFeeConfig({ assetName: asset.baseAsset.name })
|
|
62
|
-
|
|
63
|
-
const optimismL1DataFee = asset.baseAsset.estimateL1DataFee
|
|
64
|
-
? await asset.baseAsset.estimateL1DataFee({
|
|
65
|
-
unsignedTx: createUnsignedTx({
|
|
66
|
-
asset,
|
|
67
|
-
address: toAddress,
|
|
68
|
-
fromAddress,
|
|
69
|
-
amount,
|
|
70
|
-
nonce: 0,
|
|
71
|
-
txInput,
|
|
72
|
-
gasPrice: feeData.gasPrice,
|
|
73
|
-
gasLimit,
|
|
74
|
-
}),
|
|
75
|
-
})
|
|
76
|
-
: undefined
|
|
77
|
-
|
|
78
|
-
const { fee, ...rest } = getFee({
|
|
79
|
-
asset,
|
|
80
|
-
feeData,
|
|
81
|
-
gasLimit,
|
|
82
|
-
isExchange,
|
|
83
|
-
isSendAll,
|
|
84
|
-
amount,
|
|
85
|
-
isRbfAllowed,
|
|
86
|
-
calculateEffectiveFee, // BE
|
|
87
|
-
customFee, // BE
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
const l1DataFee = optimismL1DataFee
|
|
91
|
-
? asset.baseAsset.currency.baseUnit(optimismL1DataFee)
|
|
92
|
-
: asset.baseAsset.currency.ZERO
|
|
93
|
-
return { fee: fee.add(l1DataFee), optimismL1DataFee, gasLimit, ...rest }
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export default getFeeAsyncFactory
|
|
@@ -1,437 +0,0 @@
|
|
|
1
|
-
import BN from 'bn.js'
|
|
2
|
-
import { estimateGasLimit } from '../../gas-estimation'
|
|
3
|
-
import { MaticStakingApi } from './api'
|
|
4
|
-
import { stakingProviderClientFactory } from '../staking-provider-client'
|
|
5
|
-
import { isNumberUnit } from '@exodus/currency'
|
|
6
|
-
|
|
7
|
-
export function createPolygonStakingService({
|
|
8
|
-
assetClientInterface,
|
|
9
|
-
createAndBroadcastTX,
|
|
10
|
-
server,
|
|
11
|
-
}) {
|
|
12
|
-
const stakingApi = new MaticStakingApi()
|
|
13
|
-
const assetName = 'ethereum'
|
|
14
|
-
const stakingProvider = stakingProviderClientFactory()
|
|
15
|
-
|
|
16
|
-
async function getStakeAssets() {
|
|
17
|
-
const { polygon: asset, ethereum: feeAsset } = await assetClientInterface.getAssetsForNetwork({
|
|
18
|
-
baseAssetName: assetName,
|
|
19
|
-
})
|
|
20
|
-
return { asset, feeAsset }
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function amountToCurrency({ asset, amount }) {
|
|
24
|
-
return isNumberUnit(amount) ? amount : asset.currency.parse(amount)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async function delegate({ walletAccount, amount } = {}) {
|
|
28
|
-
const address = await assetClientInterface.getReceiveAddress({
|
|
29
|
-
assetName,
|
|
30
|
-
walletAccount,
|
|
31
|
-
})
|
|
32
|
-
const delegatorAddress = address.toLowerCase()
|
|
33
|
-
|
|
34
|
-
const { asset } = await getStakeAssets()
|
|
35
|
-
amount = amountToCurrency({ asset, amount })
|
|
36
|
-
|
|
37
|
-
const txApproveData = await stakingApi.approveStakeManager(amount)
|
|
38
|
-
let { gasPrice, gasLimit, fee } = await estimateTxFee(
|
|
39
|
-
delegatorAddress,
|
|
40
|
-
stakingApi.polygonContract.address,
|
|
41
|
-
txApproveData
|
|
42
|
-
)
|
|
43
|
-
await prepareAndSendTx({
|
|
44
|
-
walletAccount,
|
|
45
|
-
waitForConfirmation: true,
|
|
46
|
-
to: stakingApi.polygonContract.address,
|
|
47
|
-
txData: txApproveData,
|
|
48
|
-
gasPrice,
|
|
49
|
-
gasLimit,
|
|
50
|
-
fee,
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
const txDelegateData = await stakingApi.delegate({ amount })
|
|
54
|
-
;({ gasPrice, gasLimit, fee } = await estimateTxFee(
|
|
55
|
-
delegatorAddress,
|
|
56
|
-
stakingApi.validatorShareContract.address,
|
|
57
|
-
txDelegateData
|
|
58
|
-
))
|
|
59
|
-
|
|
60
|
-
const txId = await prepareAndSendTx({
|
|
61
|
-
walletAccount,
|
|
62
|
-
to: stakingApi.validatorShareContract.address,
|
|
63
|
-
txData: txDelegateData,
|
|
64
|
-
gasPrice,
|
|
65
|
-
gasLimit,
|
|
66
|
-
fee,
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
await stakingProvider.notifyStaking({
|
|
70
|
-
txId,
|
|
71
|
-
asset: asset.name,
|
|
72
|
-
delegator: delegatorAddress,
|
|
73
|
-
amount: amount.toBaseString(),
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
return txId
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async function undelegate({ walletAccount, amount } = {}) {
|
|
80
|
-
const address = await assetClientInterface.getReceiveAddress({
|
|
81
|
-
assetName,
|
|
82
|
-
walletAccount,
|
|
83
|
-
})
|
|
84
|
-
const delegatorAddress = address.toLowerCase()
|
|
85
|
-
|
|
86
|
-
const { asset } = await getStakeAssets()
|
|
87
|
-
amount = amountToCurrency({ asset, amount })
|
|
88
|
-
|
|
89
|
-
const txUndelegateData = await stakingApi.undelegate({ amount })
|
|
90
|
-
const { gasPrice, gasLimit, fee } = await estimateTxFee(
|
|
91
|
-
delegatorAddress.toLowerCase(),
|
|
92
|
-
stakingApi.validatorShareContract.address,
|
|
93
|
-
txUndelegateData
|
|
94
|
-
)
|
|
95
|
-
return prepareAndSendTx({
|
|
96
|
-
walletAccount,
|
|
97
|
-
to: stakingApi.validatorShareContract.address,
|
|
98
|
-
txData: txUndelegateData,
|
|
99
|
-
gasPrice,
|
|
100
|
-
gasLimit,
|
|
101
|
-
fee,
|
|
102
|
-
})
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function claimRewards({ walletAccount } = {}) {
|
|
106
|
-
const address = await assetClientInterface.getReceiveAddress({
|
|
107
|
-
assetName,
|
|
108
|
-
walletAccount,
|
|
109
|
-
})
|
|
110
|
-
const delegatorAddress = address.toLowerCase()
|
|
111
|
-
|
|
112
|
-
const txWithdrawRewardsData = await stakingApi.withdrawRewards()
|
|
113
|
-
const { gasPrice, gasLimit, fee } = await estimateTxFee(
|
|
114
|
-
delegatorAddress,
|
|
115
|
-
stakingApi.validatorShareContract.address,
|
|
116
|
-
txWithdrawRewardsData
|
|
117
|
-
)
|
|
118
|
-
return prepareAndSendTx({
|
|
119
|
-
walletAccount,
|
|
120
|
-
to: stakingApi.validatorShareContract.address,
|
|
121
|
-
txData: txWithdrawRewardsData,
|
|
122
|
-
gasPrice,
|
|
123
|
-
gasLimit,
|
|
124
|
-
fee,
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async function claimUndelegatedBalance({ walletAccount, unbondNonce } = {}) {
|
|
129
|
-
const address = await assetClientInterface.getReceiveAddress({
|
|
130
|
-
assetName,
|
|
131
|
-
walletAccount,
|
|
132
|
-
})
|
|
133
|
-
const delegatorAddress = address.toLowerCase()
|
|
134
|
-
|
|
135
|
-
const { asset } = await getStakeAssets()
|
|
136
|
-
const { currency } = asset
|
|
137
|
-
const unstakedClaimInfo = await fetchUnstakedClaimInfo({
|
|
138
|
-
stakingApi,
|
|
139
|
-
delegator: delegatorAddress,
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
const { unclaimedUndelegatedBalance } = await getUnstakedUnclaimedInfo({
|
|
143
|
-
stakingApi,
|
|
144
|
-
currency,
|
|
145
|
-
delegator: delegatorAddress,
|
|
146
|
-
...unstakedClaimInfo,
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
const txClaimUndelegatedData = await stakingApi.claimUndelegatedBalance({ unbondNonce })
|
|
150
|
-
const { gasPrice, gasLimit, fee } = await estimateTxFee(
|
|
151
|
-
delegatorAddress,
|
|
152
|
-
stakingApi.validatorShareContract.address,
|
|
153
|
-
txClaimUndelegatedData
|
|
154
|
-
)
|
|
155
|
-
const txId = await prepareAndSendTx({
|
|
156
|
-
walletAccount,
|
|
157
|
-
to: stakingApi.validatorShareContract.address,
|
|
158
|
-
txData: txClaimUndelegatedData,
|
|
159
|
-
gasPrice,
|
|
160
|
-
gasLimit,
|
|
161
|
-
fee,
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
await stakingProvider.notifyUnstaking({
|
|
165
|
-
txId,
|
|
166
|
-
asset: asset.name,
|
|
167
|
-
delegator: delegatorAddress,
|
|
168
|
-
amount: unclaimedUndelegatedBalance.toBaseString(),
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
return txId
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async function estimateDelegateOperation({ walletAccount, operation, args }) {
|
|
175
|
-
const delegateOperation = stakingApi[operation]
|
|
176
|
-
|
|
177
|
-
if (!delegateOperation) {
|
|
178
|
-
return
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const address = await assetClientInterface.getReceiveAddress({
|
|
182
|
-
assetName,
|
|
183
|
-
walletAccount,
|
|
184
|
-
})
|
|
185
|
-
const delegatorAddress = address.toLowerCase()
|
|
186
|
-
|
|
187
|
-
const { amount } = args
|
|
188
|
-
if (amount) {
|
|
189
|
-
const { asset } = await getStakeAssets()
|
|
190
|
-
args = { ...args, amount: amountToCurrency({ asset, amount }) }
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const operationTxData = await delegateOperation({ ...args, walletAccount })
|
|
194
|
-
const { fee } = await estimateTxFee(
|
|
195
|
-
delegatorAddress,
|
|
196
|
-
stakingApi.validatorShareContract.address,
|
|
197
|
-
operationTxData
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
return fee
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Estimating delegete tx using {estimateGasLimit} function does not work
|
|
205
|
-
* as the execution reverts (due to missing MATIC approval).
|
|
206
|
-
* Instead, a fixed gas limit is use, which is:
|
|
207
|
-
*
|
|
208
|
-
* delegateGasLimit = ERC20ApproveGas + delegateGas
|
|
209
|
-
*
|
|
210
|
-
* This is just for displaying purposes and it's just an aproximation of the delegate gas cost,
|
|
211
|
-
* NOT the real fee cost
|
|
212
|
-
*/
|
|
213
|
-
async function estimateDelegateTxFee() {
|
|
214
|
-
// approx gas limits
|
|
215
|
-
const { ethereum } = await assetClientInterface.getAssetsForNetwork({
|
|
216
|
-
baseAssetName: 'ethereum',
|
|
217
|
-
})
|
|
218
|
-
const erc20ApproveGas = 4900
|
|
219
|
-
const delegateGas = 240_000
|
|
220
|
-
const gasPrice = parseInt(await server.gasPrice(), 16)
|
|
221
|
-
const extraPercentage = 20
|
|
222
|
-
|
|
223
|
-
const gasLimit = erc20ApproveGas + delegateGas
|
|
224
|
-
const gasLimitWithBuffer = new BN(gasLimit)
|
|
225
|
-
.imuln(100 + extraPercentage)
|
|
226
|
-
.idivn(100)
|
|
227
|
-
.toString()
|
|
228
|
-
|
|
229
|
-
const fee = new BN(gasLimitWithBuffer).mul(new BN(gasPrice))
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
gasLimit: gasLimitWithBuffer,
|
|
233
|
-
gasPrice,
|
|
234
|
-
fee: ethereum.currency.baseUnit(fee.toString()),
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
async function estimateTxFee(from, to, txInput, gasPrice = '0x0') {
|
|
239
|
-
const { ethereum } = await assetClientInterface.getAssetsForNetwork({
|
|
240
|
-
baseAssetName: 'ethereum',
|
|
241
|
-
})
|
|
242
|
-
const amount = ethereum.currency.ZERO
|
|
243
|
-
const gasLimit = await estimateGasLimit(
|
|
244
|
-
ethereum,
|
|
245
|
-
from,
|
|
246
|
-
to,
|
|
247
|
-
amount, // staking contracts does not require ETH amount to interact with
|
|
248
|
-
txInput,
|
|
249
|
-
gasPrice
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
if (gasPrice === '0x0') {
|
|
253
|
-
gasPrice = await server.gasPrice()
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
gasPrice = parseInt(gasPrice, 16)
|
|
257
|
-
const fee = new BN(gasPrice).mul(new BN(gasLimit))
|
|
258
|
-
|
|
259
|
-
return {
|
|
260
|
-
gasLimit,
|
|
261
|
-
gasPrice: ethereum.currency.baseUnit(gasPrice),
|
|
262
|
-
fee: ethereum.currency.baseUnit(fee.toString()),
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
async function prepareAndSendTx({
|
|
267
|
-
walletAccount,
|
|
268
|
-
to,
|
|
269
|
-
txData: txInput,
|
|
270
|
-
gasPrice,
|
|
271
|
-
gasLimit,
|
|
272
|
-
fee,
|
|
273
|
-
waitForConfirmation = false,
|
|
274
|
-
} = {}) {
|
|
275
|
-
const { ethereum } = await assetClientInterface.getAssetsForNetwork({
|
|
276
|
-
baseAssetName: 'ethereum',
|
|
277
|
-
})
|
|
278
|
-
const sendTxArgs = {
|
|
279
|
-
asset: ethereum,
|
|
280
|
-
walletAccount,
|
|
281
|
-
address: to,
|
|
282
|
-
amount: ethereum.currency.ZERO,
|
|
283
|
-
options: {
|
|
284
|
-
shouldLog: true,
|
|
285
|
-
txInput,
|
|
286
|
-
gasPrice,
|
|
287
|
-
gasLimit,
|
|
288
|
-
feeAmount: fee,
|
|
289
|
-
},
|
|
290
|
-
waitForConfirmation,
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const { txId } = await createAndBroadcastTX(sendTxArgs)
|
|
294
|
-
|
|
295
|
-
return txId
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return {
|
|
299
|
-
delegate,
|
|
300
|
-
undelegate,
|
|
301
|
-
claimRewards,
|
|
302
|
-
claimUndelegatedBalance,
|
|
303
|
-
getPolygonStakingInfo,
|
|
304
|
-
estimateDelegateTxFee,
|
|
305
|
-
estimateDelegateOperation,
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
async function fetchUnstakedClaimInfo({ stakingApi, delegator }) {
|
|
310
|
-
const [unbondNonce, withdrawalDelay, currentEpoch, withdrawExchangeRate] = await Promise.all([
|
|
311
|
-
stakingApi.getCurrentUnbondNonce(delegator),
|
|
312
|
-
stakingApi.getWithdrawalDelay(),
|
|
313
|
-
stakingApi.getCurrentCheckpoint(),
|
|
314
|
-
stakingApi.getWithdrawExchangeRate(),
|
|
315
|
-
])
|
|
316
|
-
|
|
317
|
-
return {
|
|
318
|
-
unbondNonce,
|
|
319
|
-
withdrawalDelay,
|
|
320
|
-
currentEpoch,
|
|
321
|
-
withdrawExchangeRate,
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function calculateUnclaimedTokens({
|
|
326
|
-
currency,
|
|
327
|
-
exchangeRatePrecision,
|
|
328
|
-
withdrawExchangeRate,
|
|
329
|
-
shares,
|
|
330
|
-
canClaimUndelegatedBalance,
|
|
331
|
-
isUndelegateInProgress,
|
|
332
|
-
}) {
|
|
333
|
-
// see contract implementation
|
|
334
|
-
// https://github.com/maticnetwork/contracts/blob/1eb6960e511a967c15d4936904570a890d134fa6/contracts/staking/validatorShare/ValidatorShare.sol#L304
|
|
335
|
-
if (canClaimUndelegatedBalance || isUndelegateInProgress) {
|
|
336
|
-
const unclaimedTokens = withdrawExchangeRate
|
|
337
|
-
.mul(shares) // shares === validator tokens
|
|
338
|
-
.div(exchangeRatePrecision)
|
|
339
|
-
.toString()
|
|
340
|
-
|
|
341
|
-
return currency.baseUnit(unclaimedTokens)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
return currency.ZERO
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function canClaimUndelegatedBalance({ shares, withdrawEpoch, isUndelegateInProgress }) {
|
|
348
|
-
const undelegateNotStarted = shares.isZero() && withdrawEpoch.isZero()
|
|
349
|
-
return !(isUndelegateInProgress || undelegateNotStarted)
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
async function getUnstakedUnclaimedInfo({
|
|
353
|
-
stakingApi,
|
|
354
|
-
currency,
|
|
355
|
-
delegator,
|
|
356
|
-
unbondNonce,
|
|
357
|
-
currentEpoch,
|
|
358
|
-
withdrawalDelay,
|
|
359
|
-
withdrawExchangeRate,
|
|
360
|
-
}) {
|
|
361
|
-
const { withdrawEpoch, shares } = await stakingApi.getUnboundInfo(delegator, unbondNonce)
|
|
362
|
-
const exchangeRatePrecision = stakingApi.EXCHANGE_RATE_PRECISION
|
|
363
|
-
const isUndelegateInProgress =
|
|
364
|
-
!withdrawEpoch.isZero() && withdrawEpoch.add(withdrawalDelay).gte(currentEpoch)
|
|
365
|
-
const isUndelegatedBalanceClaimable = canClaimUndelegatedBalance({
|
|
366
|
-
shares,
|
|
367
|
-
withdrawEpoch,
|
|
368
|
-
isUndelegateInProgress,
|
|
369
|
-
})
|
|
370
|
-
const unclaimedUndelegatedBalance = calculateUnclaimedTokens({
|
|
371
|
-
currency,
|
|
372
|
-
exchangeRatePrecision,
|
|
373
|
-
withdrawExchangeRate,
|
|
374
|
-
shares,
|
|
375
|
-
canClaimUndelegatedBalance: isUndelegatedBalanceClaimable,
|
|
376
|
-
isUndelegateInProgress,
|
|
377
|
-
})
|
|
378
|
-
return {
|
|
379
|
-
isUndelegateInProgress,
|
|
380
|
-
canClaimUndelegatedBalance: isUndelegatedBalanceClaimable,
|
|
381
|
-
unclaimedUndelegatedBalance,
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
async function fetchRewardsInfo({ stakingApi, delegator, currency }) {
|
|
386
|
-
const [minRewardsToWithdraw, rewardsBalance] = await Promise.all([
|
|
387
|
-
stakingApi.getMinRewardsToWithdraw(),
|
|
388
|
-
stakingApi.getLiquidRewards(delegator),
|
|
389
|
-
])
|
|
390
|
-
const withdrawable = rewardsBalance.sub(minRewardsToWithdraw).gte(currency.ZERO)
|
|
391
|
-
? rewardsBalance
|
|
392
|
-
: currency.ZERO
|
|
393
|
-
|
|
394
|
-
return {
|
|
395
|
-
rewardsBalance,
|
|
396
|
-
minRewardsToWithdraw,
|
|
397
|
-
withdrawable,
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
export async function getPolygonStakingInfo({ address, asset, server }) {
|
|
402
|
-
const { currency } = asset
|
|
403
|
-
const stakingApi = new MaticStakingApi({ server })
|
|
404
|
-
const delegator = address.toLowerCase()
|
|
405
|
-
const [
|
|
406
|
-
delegatedBalance,
|
|
407
|
-
{ rewardsBalance, minRewardsToWithdraw, withdrawable },
|
|
408
|
-
{ unbondNonce, withdrawalDelay, currentEpoch, withdrawExchangeRate },
|
|
409
|
-
] = await Promise.all([
|
|
410
|
-
stakingApi.getTotalStake(delegator),
|
|
411
|
-
fetchRewardsInfo({ stakingApi, delegator, currency }),
|
|
412
|
-
fetchUnstakedClaimInfo({ stakingApi, delegator }),
|
|
413
|
-
])
|
|
414
|
-
const minDelegateAmount = currency.defaultUnit(1)
|
|
415
|
-
const isDelegating = !delegatedBalance.isZero
|
|
416
|
-
|
|
417
|
-
const unclaimedUndelegatedInfo = await getUnstakedUnclaimedInfo({
|
|
418
|
-
stakingApi,
|
|
419
|
-
currency,
|
|
420
|
-
delegator,
|
|
421
|
-
unbondNonce,
|
|
422
|
-
currentEpoch,
|
|
423
|
-
withdrawalDelay,
|
|
424
|
-
withdrawExchangeRate,
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
return {
|
|
428
|
-
rewardsBalance,
|
|
429
|
-
withdrawable,
|
|
430
|
-
unbondNonce,
|
|
431
|
-
isDelegating,
|
|
432
|
-
delegatedBalance,
|
|
433
|
-
minRewardsToWithdraw,
|
|
434
|
-
minDelegateAmount,
|
|
435
|
-
...unclaimedUndelegatedInfo,
|
|
436
|
-
}
|
|
437
|
-
}
|
package/src/staking-api.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// A super-selector that returns all the current data needed for a tick of the ETH monitor.
|
|
2
|
-
|
|
3
|
-
export default function getDeriveDataNeededForTick(aci) {
|
|
4
|
-
return async function ({ assetName, walletAccount }) {
|
|
5
|
-
const receiveAddress = await aci.getReceiveAddress({ assetName, walletAccount, useCache: true })
|
|
6
|
-
const currentAccountState = await aci.getAccountState({ assetName, walletAccount })
|
|
7
|
-
return {
|
|
8
|
-
ourWalletAddress: receiveAddress.toLowerCase(),
|
|
9
|
-
currentAccountState,
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { calculateTxAmountAndRewardFromStakeTx } from './utils.js'
|
|
2
|
-
|
|
3
|
-
const getPolygonTxAmount = ({ currency, tx, type, server }) => {
|
|
4
|
-
if ('delegate' in type) {
|
|
5
|
-
return calculateTxAmountAndRewardFromStakeTx({ tx, currency, server })
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return currency.ZERO
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const getEthereumTxAmount = ({ currency, tx, type }) => {
|
|
12
|
-
const isStakingTx = ['delegate', 'undelegatePending', 'undelegate', 'claimUndelegate'].some(
|
|
13
|
-
(stakingType) => type[stakingType]
|
|
14
|
-
)
|
|
15
|
-
if (isStakingTx) {
|
|
16
|
-
return currency.ZERO
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return tx.coinAmount
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const getStakeTxAmount = {
|
|
23
|
-
polygon: getPolygonTxAmount,
|
|
24
|
-
ethereum: getEthereumTxAmount,
|
|
25
|
-
ethereumholesky: getEthereumTxAmount,
|
|
26
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { fetchGasLimit } from '../gas-estimation'
|
|
2
|
-
|
|
3
|
-
const getFeeInfo = async function getFeeInfo({
|
|
4
|
-
assetClientInterface,
|
|
5
|
-
asset,
|
|
6
|
-
fromAddress,
|
|
7
|
-
toAddress,
|
|
8
|
-
amount,
|
|
9
|
-
isExchange,
|
|
10
|
-
txInput,
|
|
11
|
-
feeOpts = {},
|
|
12
|
-
}) {
|
|
13
|
-
const {
|
|
14
|
-
gasPrice: gasPrice_,
|
|
15
|
-
tipGasPrice: tipGasPrice_,
|
|
16
|
-
gasPriceEconomicalRate,
|
|
17
|
-
} = await assetClientInterface.getFeeData({
|
|
18
|
-
assetName: asset.name,
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
let { gasLimit, gasPrice = gasPrice_, tipGasPrice = tipGasPrice_ } = feeOpts
|
|
22
|
-
|
|
23
|
-
if (!gasLimit) {
|
|
24
|
-
gasLimit = await fetchGasLimit({
|
|
25
|
-
asset,
|
|
26
|
-
fromAddress,
|
|
27
|
-
toAddress,
|
|
28
|
-
amount,
|
|
29
|
-
txInput,
|
|
30
|
-
throwOnError: false,
|
|
31
|
-
isContract: feeOpts.isContract ?? undefined,
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const economicalFeeMultiplier = isExchange ? 1 : gasPriceEconomicalRate || 1
|
|
36
|
-
|
|
37
|
-
const fee = gasPrice.mul(economicalFeeMultiplier).mul(gasLimit)
|
|
38
|
-
return { gasPrice, gasLimit, fee, tipGasPrice }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export default getFeeInfo
|
package/src/websocket/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is a "light" version of @exodus/core resolution to select the native WebSocket on BE
|
|
3
|
-
* It's a workaround until https://github.com/ExodusMovement/assets/pull/72 is merged.
|
|
4
|
-
*
|
|
5
|
-
* Based on https://github.com/ExodusMovement/fetch/blob/master/core.js , note that chooses native on Desktop
|
|
6
|
-
*/
|
|
7
|
-
if (typeof process !== 'undefined' && (process.type === 'renderer' || process.type === 'worker')) {
|
|
8
|
-
// THIS IS FOR DESKTOP
|
|
9
|
-
if (process.env.EXODUS_DISABLE_WS) {
|
|
10
|
-
module.exports = globalThis.WebSocket
|
|
11
|
-
} else {
|
|
12
|
-
module.exports = require('ws')
|
|
13
|
-
}
|
|
14
|
-
// eslint-disable-next-line no-undef
|
|
15
|
-
} else if (typeof WebSocket === 'undefined') {
|
|
16
|
-
// THIS IS FOR UNIT TESTING.
|
|
17
|
-
module.exports = require('ws')
|
|
18
|
-
} else {
|
|
19
|
-
// THIS IS FOR BE
|
|
20
|
-
module.exports = globalThis.WebSocket
|
|
21
|
-
}
|