@exodus/ethereum-api 8.53.6 → 8.54.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.
- package/CHANGELOG.md +18 -0
- package/package.json +3 -3
- package/src/staking/matic/api.js +26 -0
- package/src/staking/matic/service.js +6 -5
- package/src/tx-type/index.js +29 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [8.54.1](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.54.0...@exodus/ethereum-api@8.54.1) (2025-10-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @exodus/ethereum-api
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [8.54.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.53.6...@exodus/ethereum-api@8.54.0) (2025-10-23)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
* feat: enable contract deployment via evm asset api (#6742)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
## [8.53.6](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.53.5...@exodus/ethereum-api@8.53.6) (2025-10-23)
|
|
7
25
|
|
|
8
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.54.1",
|
|
4
4
|
"description": "Transaction monitors, fee monitors, RPC with the blockchain node, and other networking code for Ethereum and EVM-based blockchains",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@exodus/bip44-constants": "^195.0.0",
|
|
30
30
|
"@exodus/crypto": "^1.0.0-rc.26",
|
|
31
31
|
"@exodus/currency": "^6.0.1",
|
|
32
|
-
"@exodus/ethereum-lib": "^5.18.
|
|
32
|
+
"@exodus/ethereum-lib": "^5.18.3",
|
|
33
33
|
"@exodus/ethereum-meta": "^2.9.1",
|
|
34
34
|
"@exodus/ethereumholesky-meta": "^2.0.5",
|
|
35
35
|
"@exodus/ethereumjs": "^1.8.0",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"type": "git",
|
|
68
68
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "9d2c245deb27cf3ce56eef0d7ad5c0ab8bd4bc02"
|
|
71
71
|
}
|
package/src/staking/matic/api.js
CHANGED
|
@@ -7,6 +7,8 @@ import BN from 'bn.js'
|
|
|
7
7
|
import { getServerByName } from '../../exodus-eth-server/index.js'
|
|
8
8
|
import { fromHexToBN, fromHexToString, splitIn32BytesArray } from '../../number-utils.js'
|
|
9
9
|
|
|
10
|
+
const EVERSTAKE_API_URL = 'https://polygon-clarity.a.exodus.io/everstake-rewards'
|
|
11
|
+
|
|
10
12
|
const polygonEthToken = ethAssets.find(({ name: tokenName }) => tokenName === 'polygon')
|
|
11
13
|
|
|
12
14
|
const RETRY_DELAYS = ['10s']
|
|
@@ -109,6 +111,7 @@ export class MaticStakingApi {
|
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
getLiquidRewards = async (address) => {
|
|
114
|
+
// latest accrued rewards
|
|
112
115
|
const liquidRewards = await this.#callReadFunctionContract(
|
|
113
116
|
this.validatorShareContract,
|
|
114
117
|
'getLiquidRewards',
|
|
@@ -117,6 +120,29 @@ export class MaticStakingApi {
|
|
|
117
120
|
return polygonEthToken.currency.baseUnit(liquidRewards)
|
|
118
121
|
}
|
|
119
122
|
|
|
123
|
+
getTotalRewards = async (address) => {
|
|
124
|
+
// use external everstake API to get total rewards
|
|
125
|
+
const url = new URL(EVERSTAKE_API_URL)
|
|
126
|
+
|
|
127
|
+
const options = {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers: { 'Content-Type': 'application/json' },
|
|
130
|
+
body: JSON.stringify({
|
|
131
|
+
address,
|
|
132
|
+
}),
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const response = await fetch(url.toString(), options)
|
|
137
|
+
const res = await response.json()
|
|
138
|
+
if (res === 'address' || !res?.rewards) return polygonEthToken.currency.ZERO // address not found
|
|
139
|
+
return polygonEthToken.currency.baseUnit(res.rewards)
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.warn('Error fetching Polygon total rewards:', error)
|
|
142
|
+
return polygonEthToken.currency.ZERO
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
120
146
|
getTotalStake = async (address) => {
|
|
121
147
|
const stakeInfo = await this.#callReadFunctionContract(
|
|
122
148
|
this.validatorShareContract,
|
|
@@ -482,18 +482,19 @@ async function getUnstakedUnclaimedInfo({
|
|
|
482
482
|
}
|
|
483
483
|
|
|
484
484
|
async function fetchRewardsInfo({ stakingApi, delegator, currency }) {
|
|
485
|
-
const [minRewardsToWithdraw, rewardsBalance] = await Promise.all([
|
|
485
|
+
const [minRewardsToWithdraw, lastRewards, rewardsBalance] = await Promise.all([
|
|
486
486
|
stakingApi.getMinRewardsToWithdraw(),
|
|
487
487
|
stakingApi.getLiquidRewards(delegator),
|
|
488
|
+
stakingApi.getTotalRewards(delegator),
|
|
488
489
|
])
|
|
489
|
-
const withdrawable =
|
|
490
|
-
?
|
|
490
|
+
const withdrawable = lastRewards.sub(minRewardsToWithdraw).gte(currency.ZERO)
|
|
491
|
+
? lastRewards
|
|
491
492
|
: currency.ZERO
|
|
492
493
|
|
|
493
494
|
return {
|
|
494
|
-
rewardsBalance,
|
|
495
|
+
rewardsBalance: rewardsBalance.add(lastRewards), // all time accrued rewards
|
|
495
496
|
minRewardsToWithdraw,
|
|
496
|
-
withdrawable,
|
|
497
|
+
withdrawable, // unclaimed rewards
|
|
497
498
|
}
|
|
498
499
|
}
|
|
499
500
|
|
package/src/tx-type/index.js
CHANGED
|
@@ -6,8 +6,9 @@ import assert from 'minimalistic-assert'
|
|
|
6
6
|
import { isContractAddressCached } from '../eth-like-util.js'
|
|
7
7
|
|
|
8
8
|
export const TX_TYPE_TRANSFER = 'transfer'
|
|
9
|
+
export const TX_TYPE_CREATE_CONTRACT = 'create-contract'
|
|
9
10
|
|
|
10
|
-
const VALID_TX_TYPES = new Set([TX_TYPE_TRANSFER])
|
|
11
|
+
const VALID_TX_TYPES = new Set([TX_TYPE_TRANSFER, TX_TYPE_CREATE_CONTRACT])
|
|
11
12
|
|
|
12
13
|
export const isValidTxType = (txType) => VALID_TX_TYPES.has(txType)
|
|
13
14
|
|
|
@@ -33,14 +34,21 @@ export const assertCriticalTxAttributes = (criticalTxAttributes) => {
|
|
|
33
34
|
const { amount, toAddress, txInput, txToAddress, txType, txValue } = criticalTxAttributes
|
|
34
35
|
|
|
35
36
|
assert(amount instanceof NumberUnit, 'expected NumberUnit amount')
|
|
36
|
-
assert(typeof toAddress === 'string', 'expected string toAddress')
|
|
37
37
|
assert(
|
|
38
38
|
typeof txInput === 'string' && txInput.startsWith('0x', 'expected hexadecimal string txInput')
|
|
39
39
|
)
|
|
40
|
-
assert(typeof txToAddress === 'string', 'expected string txToAddress')
|
|
41
40
|
assert(isValidTxType(txType), 'expected valid txType')
|
|
42
41
|
assert(txValue instanceof NumberUnit, 'expected NumberUnit txValue')
|
|
43
42
|
|
|
43
|
+
if (txType === TX_TYPE_CREATE_CONTRACT) {
|
|
44
|
+
assert(toAddress === null, 'expected null toAddress')
|
|
45
|
+
assert(txToAddress === null, 'expected null txToAddress')
|
|
46
|
+
assert(txInput !== '0x', 'expected non-empty txInput for contract creation')
|
|
47
|
+
} else {
|
|
48
|
+
assert(typeof toAddress === 'string', 'expected string toAddress')
|
|
49
|
+
assert(typeof txToAddress === 'string', 'expected string txToAddress')
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
return criticalTxAttributes
|
|
45
53
|
}
|
|
46
54
|
|
|
@@ -91,7 +99,8 @@ const createResolvedTxAttributes = async ({
|
|
|
91
99
|
txToAddress,
|
|
92
100
|
txValue,
|
|
93
101
|
txType,
|
|
94
|
-
isContractTxToAddress:
|
|
102
|
+
isContractTxToAddress:
|
|
103
|
+
Boolean(txToAddress) && (await isContractAddressCached({ asset, address: txToAddress })),
|
|
95
104
|
})
|
|
96
105
|
|
|
97
106
|
export const resolveTxFromAddress = async ({
|
|
@@ -147,6 +156,22 @@ export const resolveCriticalTxAttributes = ({
|
|
|
147
156
|
|
|
148
157
|
const amount = providedAmount ?? asset.currency.ZERO
|
|
149
158
|
assert(amount instanceof NumberUnit, 'expected providedAmount')
|
|
159
|
+
|
|
160
|
+
if (txType === TX_TYPE_CREATE_CONTRACT) {
|
|
161
|
+
assert(asset.name === asset.baseAsset.name, 'must use baseAsset for contract deployments')
|
|
162
|
+
assert(!providedToAddress, 'toAddress must be falsy when creating a contract')
|
|
163
|
+
assert(!providedTxToAddress, 'txToAddress must be falsy when creating a contract')
|
|
164
|
+
|
|
165
|
+
return assertCriticalTxAttributes({
|
|
166
|
+
amount,
|
|
167
|
+
toAddress: null,
|
|
168
|
+
txInput: providedTxInput,
|
|
169
|
+
txToAddress: null,
|
|
170
|
+
txType,
|
|
171
|
+
txValue: amount,
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
150
175
|
assert(txType === TX_TYPE_TRANSFER, 'expected TX_TYPE_TRANSFER')
|
|
151
176
|
|
|
152
177
|
// HACK: If a `toAddress` hasn't been defined, then we
|