@exodus/ethereum-api 7.5.3 → 8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "7.5.3",
3
+ "version": "8.0.0",
4
4
  "description": "Ethereum Api",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -25,9 +25,9 @@
25
25
  "@exodus/bip44-constants": "^195.0.0",
26
26
  "@exodus/crypto": "^1.0.0-rc.0",
27
27
  "@exodus/currency": "^2.1.3",
28
- "@exodus/ethereum-lib": "^4.9.0",
29
- "@exodus/ethereum-meta": "^1.2.0",
30
- "@exodus/ethereumholesky-meta": "^1.0.1",
28
+ "@exodus/ethereum-lib": "^5.0.0",
29
+ "@exodus/ethereum-meta": "^1.5.1",
30
+ "@exodus/ethereumholesky-meta": "^1.0.3",
31
31
  "@exodus/ethereumjs-util": "^7.1.0-exodus.7",
32
32
  "@exodus/fetch": "^1.3.0",
33
33
  "@exodus/key-utils": "^3.1.0",
@@ -48,14 +48,14 @@
48
48
  "devDependencies": {
49
49
  "@exodus/assets": "^9.1.1",
50
50
  "@exodus/assets-testing": "^1.0.0",
51
- "@exodus/bsc-meta": "^1.1.2",
52
- "@exodus/ethereumarbone-meta": "^1.1.5",
53
- "@exodus/ethereumgoerli-meta": "^1.0.3",
54
- "@exodus/ethereumsepolia-meta": "^1.0.1",
55
- "@exodus/fantommainnet-meta": "^1.0.5",
56
- "@exodus/rootstock-meta": "^1.0.5",
51
+ "@exodus/bsc-meta": "^1.2.2",
52
+ "@exodus/ethereumarbone-meta": "^1.2.0",
53
+ "@exodus/ethereumgoerli-meta": "^1.0.5",
54
+ "@exodus/ethereumsepolia-meta": "^1.0.3",
55
+ "@exodus/fantommainnet-meta": "^1.1.2",
56
+ "@exodus/rootstock-meta": "^1.0.7",
57
57
  "cross-fetch": "^3.1.5",
58
58
  "delay": "4.0.1"
59
59
  },
60
- "gitHead": "9322a03c6b00b6dc765356309b3e8f1e1f27df41"
60
+ "gitHead": "a5992c8a158d486d6e95c03b17136b67ee06459c"
61
61
  }
@@ -6,26 +6,24 @@ import { ClarityMonitor } from './tx-log/clarity-monitor'
6
6
  import { EthereumNoHistoryMonitor } from './tx-log/ethereum-no-history-monitor'
7
7
  import { EthereumMonitor } from './tx-log/ethereum-monitor'
8
8
 
9
- import { getServer } from './exodus-eth-server'
9
+ import { createEvmServer } from './exodus-eth-server'
10
10
 
11
11
  import {
12
- CONFIRMATIONS_NUMBER,
13
12
  createEthereumLikeAccountState,
14
13
  createGetKeyIdentifier as defaultCreateGetKeyIdentifier,
15
- createUnsignedTx,
16
14
  encodePrivate,
17
- encodePublic,
15
+ encodePublicFactory,
18
16
  hasChecksum,
19
17
  parseUnsignedTx,
20
18
  signUnsignedTx,
21
19
  signUnsignedTxWithSigner,
22
- validate,
23
20
  signMessage,
24
21
  signMessageWithSigner,
25
22
  signHardwareFactory,
26
23
  DEFAULT_FEE_MONITOR_INTERVAL,
24
+ validateFactory,
25
+ createUnsignedTxFactory,
27
26
  } from '@exodus/ethereum-lib'
28
- import { ETHEREUM_LIKE_MONITOR_TYPES } from '@exodus/ethereum-lib/src/constants'
29
27
  import assert from 'minimalistic-assert'
30
28
  import ms from 'ms'
31
29
 
@@ -35,7 +33,7 @@ import { getEffectiveGasPrice, getFeeFactory } from './get-fee'
35
33
  import { createEthereumHooks } from './hooks'
36
34
  import { createStakingApi } from './staking-api'
37
35
  import { txSendFactory } from './tx-send'
38
- import { serverBasedFeeMonitorFactoryFactory } from './fee-monitor'
36
+ import { serverBasedFeeMonitorFactoryFactory } from './server-based-fee-monitor'
39
37
  import { createGetBalanceForAddress } from './get-balance-for-address'
40
38
  import { estimateL1DataFeeFactory, getL1GetFeeFactory } from './optimism-gas'
41
39
  import { mapValues } from 'lodash'
@@ -55,15 +53,25 @@ export const createAssetFactory = ({
55
53
  customBip44,
56
54
  customCreateGetKeyIdentifier,
57
55
  feeMonitorInterval,
58
- l1GasOracleAddress, // l1 extra fee for base and opto
56
+ l1GasOracleAddress, // l1 extra fee for base and optostakingConfiguration = {},
57
+ serverUrl,
58
+ confirmationsNumber,
59
+ monitorType = 'magnifier',
60
+ tokenType,
61
+ confirmationNumber,
59
62
  stakingConfiguration = {},
60
63
  }) => {
61
64
  assert(assetsList, 'assetsList is required')
62
65
  assert(feeData, 'feeData is required')
66
+ assert(serverUrl, 'serverUrl is required')
67
+ assert(confirmationsNumber, 'confirmationsNumber is required')
63
68
 
64
69
  const base = assetsList.find((asset) => asset.name === asset.baseAssetName)
65
70
  assert(base, 'base is required')
66
71
 
72
+ const chainId = base.chainId
73
+ assert(chainId, 'chainId is required')
74
+
67
75
  const createGetKeyIdentifier = customCreateGetKeyIdentifier || defaultCreateGetKeyIdentifier
68
76
 
69
77
  return (
@@ -82,16 +90,14 @@ export const createAssetFactory = ({
82
90
 
83
91
  const asset = assets[base.name]
84
92
 
85
- const server = getServer(asset)
93
+ const server = createEvmServer({ assetName: asset.name, serverUrl, monitorType })
86
94
 
87
95
  const gasLimit = 21e3 // 21 KGas, enough only for sending ether to normal address
88
96
 
89
97
  const contractGasLimit = 1e6 // used when estimateGas fail
90
98
 
91
99
  const address = {
92
- validate: useEip1191ChainIdChecksum
93
- ? (address) => validate(address, { baseAssetName: asset.name })
94
- : validate,
100
+ validate: validateFactory({ chainId, useEip1191ChainIdChecksum }),
95
101
  hasChecksum,
96
102
  isContract: server.isContract,
97
103
  }
@@ -100,25 +106,20 @@ export const createAssetFactory = ({
100
106
 
101
107
  const keys = {
102
108
  encodePrivate,
103
- encodePublic: useEip1191ChainIdChecksum
104
- ? (pubKey) => encodePublic(pubKey, { baseAssetName: asset.name })
105
- : encodePublic,
109
+ encodePublic: encodePublicFactory({ chainId, useEip1191ChainIdChecksum }),
106
110
  }
107
111
 
108
112
  const { createToken, getTokens } = createTokenFactory({ address, bip44, keys }, assets)
109
113
 
110
114
  const addressHasHistory = addressHasHistoryFactory({ server })
111
115
 
112
- const monitorType = ETHEREUM_LIKE_MONITOR_TYPES[asset.name]
113
-
114
- assert(monitorType, `ETHEREUM_LIKE_MONITOR_TYPES for asset ${asset.name} is not defined`)
115
-
116
116
  const feeMonitor = monitorType === 'no-history'
117
117
 
118
118
  const createFeeMonitor = serverBasedFeeMonitorFactoryFactory({
119
119
  assetName: base.name,
120
120
  interval: config.feeMonitorInterval || feeMonitorInterval || DEFAULT_FEE_MONITOR_INTERVAL,
121
121
  eip1559Enabled: feeData.eip1559Enabled, // this is not updated via remote config. Should it be?
122
+ server,
122
123
  })
123
124
 
124
125
  const features = {
@@ -135,8 +136,6 @@ export const createAssetFactory = ({
135
136
  ...(supportsStaking && { staking: {} }),
136
137
  }
137
138
 
138
- const confirmationNumber = CONFIRMATIONS_NUMBER[asset.name] || 1
139
-
140
139
  const stakingAssetNames = Object.keys(stakingConfiguration)
141
140
 
142
141
  const extraData =
@@ -177,6 +176,7 @@ export const createAssetFactory = ({
177
176
  assetClientInterface,
178
177
  assetName: asset.name,
179
178
  stakingAssetNames,
179
+ server,
180
180
  })['after-tick']
181
181
  monitor.addHook('after-tick', afterTickHook)
182
182
  }
@@ -186,7 +186,12 @@ export const createAssetFactory = ({
186
186
 
187
187
  const defaultAddressPath = 'm/0/0'
188
188
 
189
- const sendTx = txSendFactory({ assetClientInterface })
189
+ const createUnsignedTx = createUnsignedTxFactory({ chainId })
190
+
191
+ const sendTx = txSendFactory({
192
+ assetClientInterface,
193
+ createUnsignedTx,
194
+ })
190
195
 
191
196
  const estimateL1DataFee = l1GasOracleAddress
192
197
  ? estimateL1DataFeeFactory({ l1GasOracleAddress, server })
@@ -245,6 +250,8 @@ export const createAssetFactory = ({
245
250
  keys,
246
251
  address,
247
252
  api,
253
+ chainId,
254
+ monitorType,
248
255
  estimateL1DataFee,
249
256
  server,
250
257
  ...(erc20FuelBuffer && { erc20FuelBuffer }),
@@ -7,22 +7,31 @@ import {
7
7
  import { create } from './api'
8
8
  import ClarityServer from './clarity'
9
9
  import ApiCoinNodesServer from './api-coin-nodes'
10
+ import assert from 'minimalistic-assert'
10
11
 
11
- function getAssetServer(assetName) {
12
- switch (ETHEREUM_LIKE_MONITOR_TYPES[assetName]) {
12
+ export function createEvmServer({ assetName, serverUrl, monitorType }) {
13
+ assert(assetName, 'assetName is required')
14
+ assert(serverUrl, 'serverUrl is required')
15
+ assert(monitorType, 'monitorType is required')
16
+ switch (monitorType) {
13
17
  case 'no-history':
14
- return new ApiCoinNodesServer({ uri: DEFAULT_SERVER_URLS[assetName] })
18
+ return new ApiCoinNodesServer({ uri: serverUrl })
15
19
  case 'clarity':
16
- return new ClarityServer({ baseAssetName: assetName, uri: DEFAULT_SERVER_URLS[assetName] })
20
+ return new ClarityServer({ baseAssetName: assetName, uri: serverUrl })
17
21
  case 'magnifier':
18
- return create(DEFAULT_SERVER_URLS[assetName], assetName)
22
+ return create(serverUrl, assetName)
19
23
  default:
20
- throw new Error(`No server API found for ${assetName}`)
24
+ throw new Error(`No server API found for ${assetName} and type ${monitorType}`)
21
25
  }
22
26
  }
23
27
 
28
+ // @Deprecated
24
29
  const serverMap = Object.fromEntries(
25
- ETHEREUM_LIKE_ASSETS.map((assetName) => [assetName, getAssetServer(assetName)])
30
+ ETHEREUM_LIKE_ASSETS.map((assetName) => {
31
+ const monitorType = ETHEREUM_LIKE_MONITOR_TYPES[assetName]
32
+ const serverUrl = DEFAULT_SERVER_URLS[assetName]
33
+ return [assetName, createEvmServer({ assetName, serverUrl, monitorType })]
34
+ })
26
35
  )
27
36
 
28
37
  // allow self-signed certs
@@ -43,11 +52,20 @@ export const ftm = serverMap['fantommainnet']
43
52
  export const harmony = serverMap['harmonymainnet']
44
53
 
45
54
  export function getServer(asset) {
55
+ const server = asset.baseAsset.server
56
+ if (server) {
57
+ return server
58
+ }
59
+
60
+ // legacy way using the global serverMap
46
61
  return getServerByName(asset.baseAsset.name)
47
62
  }
48
63
 
49
64
  export function getServerByName(baseAssetName) {
65
+ console.warn(
66
+ `Asking ${baseAssetName} server by name, please use asset.baseAsset.server or getServer(asset)`
67
+ )
50
68
  const server = serverMap[baseAssetName]
51
- if (!server) throw new Error(`unsupported base asset ${baseAssetName}`)
69
+ if (!server) throw new Error(`Unsupported base asset ${baseAssetName}`)
52
70
  return server
53
71
  }
@@ -1,7 +1,16 @@
1
1
  import { getEthereumStakingInfo, getPolygonStakingInfo } from '../staking'
2
2
  import processTxLog from '../tx-log-staking-processor'
3
+ import assert from 'minimalistic-assert'
3
4
 
4
- export const createEthereumHooks = ({ assetClientInterface, assetName, stakingAssetNames }) => {
5
+ export const createEthereumHooks = ({
6
+ assetClientInterface,
7
+ assetName,
8
+ stakingAssetNames,
9
+ server,
10
+ }) => {
11
+ assert(assetClientInterface, 'assetClientInterface is required')
12
+ assert(server, 'server is required')
13
+ assert(assetName, 'assetName is required')
5
14
  const afterTickHook = async ({ walletAccount }) => {
6
15
  // args passed from monitor tick method ({ monitor, error })
7
16
  const assets = await assetClientInterface.getAssetsForNetwork({
@@ -24,6 +33,7 @@ export const createEthereumHooks = ({ assetClientInterface, assetName, stakingAs
24
33
  const assetStakingInfo = await getStakingInfo({
25
34
  address: userAddress.toString(),
26
35
  asset: assets[stakingAssetName],
36
+ server,
27
37
  })
28
38
  stakingInfo.staking[stakingAssetName] = assetStakingInfo
29
39
  }
package/src/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
  // If the client is importing one module specifically,
3
3
  // it's breaking the encapsulation
4
4
  export * from './eth-like-util'
5
- export * from './fee-monitor'
6
5
  export * from './gas-estimation'
7
6
  export * from './exodus-eth-server'
8
7
  export * from './tx-log'
@@ -1,7 +1,5 @@
1
1
  import * as ethUtil from '@exodus/ethereumjs-util'
2
2
  import { createEthereumJsTx, createContract } from '@exodus/ethereum-lib'
3
- import { getServerByName } from '../exodus-eth-server'
4
- import { GAS_ORACLE_ADDRESS } from './addresses'
5
3
  import { fromHexToBigInt } from '../number-utils'
6
4
  import assert from 'minimalistic-assert'
7
5
 
@@ -36,15 +34,3 @@ export const getL1GetFeeFactory = ({ asset, originalGetFee }) => {
36
34
  return { fee: fee.add(l1DataFee), ...rest }
37
35
  }
38
36
  }
39
-
40
- /**
41
- * Back-compatibility
42
- *
43
- * @deprecated use eth-asset.estimateL1DataFee
44
- * @param unsignedTx
45
- * @returns {Promise<string>}
46
- */
47
- export const estimateOptimismL1DataFee = estimateL1DataFeeFactory({
48
- server: getServerByName('optimism'),
49
- l1GasOracleAddress: GAS_ORACLE_ADDRESS,
50
- })
@@ -1,8 +1,7 @@
1
1
  import { FeeMonitor } from '@exodus/asset-lib'
2
2
  import assert from 'minimalistic-assert'
3
- import { getServerByName } from '../exodus-eth-server'
4
3
  import { DEFAULT_FEE_MONITOR_INTERVAL } from '@exodus/ethereum-lib'
5
- import { fromHexToString } from '../number-utils'
4
+ import { fromHexToString } from './number-utils'
6
5
 
7
6
  /**
8
7
  * Generic eth server based fee monitor.
@@ -13,7 +12,7 @@ import { fromHexToString } from '../number-utils'
13
12
  *
14
13
  * const api = {
15
14
  * ...
16
- * createFeeMonitor: serverBasedFeeMonitorFactoryFactory({ interval: '50s', assetName: base.name }),
15
+ * createFeeMonitor: serverBasedFeeMonitorFactoryFactory({ interval: '50s', server, assetName: base.name }),
17
16
  * ...
18
17
  * }
19
18
  */
@@ -22,12 +21,10 @@ export const serverBasedFeeMonitorFactoryFactory = ({
22
21
  assetName,
23
22
  interval = DEFAULT_FEE_MONITOR_INTERVAL,
24
23
  eip1559Enabled,
24
+ server,
25
25
  }) => {
26
26
  assert(assetName, 'assetName is required')
27
- // NOTE: Using getServerByName for simplicity now but
28
- // remove getServerByName and convert server to a param instead.
29
- // This is to avoid global references, static creation, remove the chain specific map and allow IOC
30
- const server = getServerByName(assetName)
27
+ assert(server, 'server is required')
31
28
 
32
29
  const FeeMonitorClass = class ServerBaseEthereumFeeMonitor extends FeeMonitor {
33
30
  constructor({ updateFee }) {
@@ -31,7 +31,8 @@ export class EthereumStaking {
31
31
 
32
32
  constructor(
33
33
  asset, // ethereum or ethereumholesky for testnet
34
- minAmount = MIN_AMOUNT
34
+ minAmount = MIN_AMOUNT,
35
+ server
35
36
  ) {
36
37
  this.asset = asset
37
38
  const accountingAddress =
@@ -43,6 +44,7 @@ export class EthereumStaking {
43
44
  this.accountingAddress = accountingAddress
44
45
  this.poolAddress = poolAddress
45
46
  this.minAmount = asset.currency.defaultUnit(minAmount)
47
+ this.server = server
46
48
  }
47
49
 
48
50
  buildTxData = (contract, method, ...args) => {
@@ -57,7 +59,7 @@ export class EthereumStaking {
57
59
  tag: 'latest',
58
60
  }
59
61
 
60
- const eth = getServerByName(this.asset.name)
62
+ const eth = this.server || getServerByName(this.asset.name)
61
63
  return retry(eth.ethCall, { delayTimesMs: RETRY_DELAYS })(data)
62
64
  }
63
65
 
@@ -288,10 +288,10 @@ export function createEthereumStakingService({
288
288
  }
289
289
  }
290
290
 
291
- export async function getEthereumStakingInfo({ address, asset }) {
291
+ export async function getEthereumStakingInfo({ address, asset, server }) {
292
292
  const { currency } = asset
293
293
  const delegator = address.toLowerCase()
294
- const staking = new EthereumStaking(asset)
294
+ const staking = new EthereumStaking(asset, undefined, server)
295
295
 
296
296
  const [
297
297
  activeStakedBalance,
@@ -14,7 +14,8 @@ export class MaticStakingApi {
14
14
 
15
15
  constructor(
16
16
  validatorId = MaticStakingApi.EVERSTAKE_VALIDATOR_CONTRACT_ADDR,
17
- stakeManagerAddr = MaticStakingApi.STAKING_MANAGER_ADDR
17
+ stakeManagerAddr = MaticStakingApi.STAKING_MANAGER_ADDR,
18
+ server
18
19
  ) {
19
20
  // harcoded exchange rate from the validtor share contract
20
21
  // in order to calculate claim unstake amount off-chain
@@ -22,6 +23,7 @@ export class MaticStakingApi {
22
23
  this.validatorShareContract = createContract(validatorId, 'maticValidatorShare')
23
24
  this.stakingManagerContract = createContract(stakeManagerAddr, 'maticStakingManager')
24
25
  this.polygonContract = createContract(polygonEthToken.contract.current, 'polygon')
26
+ this.server = server
25
27
  }
26
28
 
27
29
  buildTxData = (contract, method, ...args) => {
@@ -36,7 +38,7 @@ export class MaticStakingApi {
36
38
  tag: 'latest',
37
39
  }
38
40
 
39
- const eth = getServerByName('ethereum')
41
+ const eth = this.server || getServerByName('ethereum')
40
42
  return retry(eth.ethCall, { delayTimesMs: RETRY_DELAYS })(data)
41
43
  }
42
44
 
@@ -1,7 +1,7 @@
1
-
2
1
  ## Staking in Polygon (MATIC)
3
2
 
4
3
  ## How it works?
4
+
5
5
  Polygon Staking happens in the **Ethereum network**, it is implemented by a set of smart contracts deployed on the ETH mainnet.
6
6
  Staking is made by delegating the `ERC20 MATIC` token to those smart contracts which handle the `(un)staking/rewards` process and it shouldn't be confused with the Native asset in **Polygon network** (`MATIC NATIVE`).
7
7
 
@@ -10,41 +10,47 @@ Stakers are divided into `validators`, `delegators`, and watchers (for fraud rep
10
10
  ## Contracts
11
11
 
12
12
  ### StakeManager contract
13
+
13
14
  `StakeManager` is the main contract for handling validator related activities like checkPoint signature verification, reward distribution, and stake management. Since the contract is using NFT ID as a source of ownership, change of ownership and signer won't affect anything in the system. [see](https://wiki.polygon.technology/docs/pos/contracts/stakingmanager).
14
15
 
15
16
  ### ValidatorShare contract
17
+
16
18
  For delegation staking each validator has its own deployed **contract**, this contract has the logic to `stake/unstake` as delegators, but it also acts as an `ERC20`, this `ERC20` token is what we know as the shares token. Shares token are calculated based on the total amount staked in the contract, varying from time to time
17
- When delegators stake matic, they call `buyVoucher()` , the contract receives the MATIC tokens to stake (approval is needed on Matic token contract) and it calculates and mints the number of token shares that correspond to that staked amount. [see](https://wiki.polygon.technology/docs/pos/contracts/delegation).
19
+ When delegators stake matic, they call `buyVoucher()` , the contract receives the MATIC tokens to stake (approval is needed on Matic token contract) and it calculates and mints the number of token shares that correspond to that staked amount. [see](https://wiki.polygon.technology/docs/pos/contracts/delegation).
18
20
 
19
21
  ### Staking Anatomy
22
+
20
23
  Example taken from the docs:
21
24
 
22
- *Polygon supports delegation via validator shares. By using this design, it is easier to distribute rewards and slash with scale (thousands of delegators) on Ethereum contracts without much computation.
23
- Delegators delegate by purchasing shares of a finite pool from validators. Each validator will have their own validator share token. Let's call these fungible tokens `VATIC` for a validator `A`. As soon as a user delegates to a validator `A`, they will be issued `VATIC` based on an exchange rate of `MATIC/VATIC` pair. As users accrue value the exchange rate indicates that they can now withdraw more `MATIC` for each `VATIC` and when users get slashed, users withdraw less `MATIC` for their `VATIC`.
24
- Note that `MATIC` is a staking token. A delegator needs to have `MATIC` tokens to participate in the delegation.
25
- Initially, a delegator `D` buys tokens from validator `A` specific pool when `1 MATIC per 1 VATIC`.
26
- When a validator gets rewarded with more `MATIC` tokens, new tokens are added to the pool. Let's say with the current pool of `100 MATIC` tokens, `10 MATIC` rewards are added to the pool. But since the total supply of `VATIC` tokens didn't change due to rewards, the exchange rate becomes `1 MATIC per 0.9 VATIC`. Now, delegator `D` gets more `MATIC` for the same shares.
27
- `VATIC`: Validator specific minted validator share tokens (ERC20 tokens)*
25
+ _Polygon supports delegation via validator shares. By using this design, it is easier to distribute rewards and slash with scale (thousands of delegators) on Ethereum contracts without much computation.
26
+ Delegators delegate by purchasing shares of a finite pool from validators. Each validator will have their own validator share token. Let's call these fungible tokens `VATIC` for a validator `A`. As soon as a user delegates to a validator `A`, they will be issued `VATIC` based on an exchange rate of `MATIC/VATIC` pair. As users accrue value the exchange rate indicates that they can now withdraw more `MATIC` for each `VATIC` and when users get slashed, users withdraw less `MATIC` for their `VATIC`.
27
+ Note that `MATIC` is a staking token. A delegator needs to have `MATIC` tokens to participate in the delegation.
28
+ Initially, a delegator `D` buys tokens from validator `A` specific pool when `1 MATIC per 1 VATIC`.
29
+ When a validator gets rewarded with more `MATIC` tokens, new tokens are added to the pool. Let's say with the current pool of `100 MATIC` tokens, `10 MATIC` rewards are added to the pool. But since the total supply of `VATIC` tokens didn't change due to rewards, the exchange rate becomes `1 MATIC per 0.9 VATIC`. Now, delegator `D` gets more `MATIC` for the same shares.
30
+ `VATIC`: Validator specific minted validator share tokens (ERC20 tokens)_
28
31
 
29
32
  #### Rewards
33
+
30
34
  Delegators can do with their rewards the following:
31
35
  withdraw via `withdrawRewards()` or
32
36
  `restake` (earned rewards are put as stake in the contract via `restake()`)
33
37
 
34
38
  #### Unstaking
39
+
35
40
  For delegators to unstake, there are two steps:
41
+
36
42
  1. `sellVoucher_new()`
37
43
  2. `unstakeClaimTokens()`
38
44
 
39
45
  **Note**: there are some methods in the validator share contract with the suffix `_new`, for instance:
40
- `sellVoucher()` and `sellVoucher_new()` this is because the recent changes on the smart contract to support the new exit API (**unstake** and **claim** tokens)*
46
+ `sellVoucher()` and `sellVoucher_new()` this is because the recent changes on the smart contract to support the new exit API (**unstake** and **claim** tokens)\*
41
47
 
42
- **sellVoucher** method calculates the token shares that correspond to the staked MATIC at that time, and burns those share tokens, it also transfers the rewards, and makes changes in the contract to update the total stake held in the contract .
48
+ **sellVoucher** method calculates the token shares that correspond to the staked MATIC at that time, and burns those share tokens, it also transfers the rewards, and makes changes in the contract to update the total stake held in the contract .
43
49
  Basically it prepares the contract to let delegators withdraw their staked MATIC in a second step once the **withdrawal delay** it's ben fulfilled.
44
50
 
45
51
  #### Unstake Claim Tokens
46
- **unstakeClaimTokens** makes the actual withdraw of the staked tokens, sellVoucher does not transfer the staked MATIC back to the delegator, we need to call this function after the withdrawal delay has been fulfilled, so that delegators can get their stake amount back to their wallet.
47
52
 
53
+ **unstakeClaimTokens** makes the actual withdraw of the staked tokens, sellVoucher does not transfer the staked MATIC back to the delegator, we need to call this function after the withdrawal delay has been fulfilled, so that delegators can get their stake amount back to their wallet.
48
54
 
49
55
  ### Staking Bussines Rules
50
56
 
@@ -55,8 +61,7 @@ All of these rules can be queried from the smart contracts, except `minimum amou
55
61
  - **Withdrawal delay**: The amount of time delegators must wait before claiming their staked amount. Varies depending on the contract governance
56
62
  - **Withdrawal exchange rate**: The exchange rate used to convert tokens to shares and vice-versa. Varies depending on the number of MATIC in the withdraw pool share (affected by the earned rewards).
57
63
  - **Unstaking period**: immediately, but staked MATIC tokens are not available to be withdrawn before withdrawal delay
58
- - **Claim unstaked tokens**: after 3-4 days has passed since unstaked was called, the unstaked tokens can be claimed by the delegator.
59
-
64
+ - **Claim unstaked tokens**: after 3-4 days has passed since unstaked was called, the unstaked tokens can be claimed by the delegator.
60
65
 
61
66
  Useful resources:
62
67
 
@@ -64,4 +69,3 @@ Useful resources:
64
69
  [Polygon Staking](https://wiki.polygon.technology/docs/pos/contracts/delegation)
65
70
  [StakeManager contract](https://github.com/maticnetwork/contracts/blob/main/contracts/staking/stakeManager/StakeManager.sol)
66
71
  [Validator share contract](https://github.com/maticnetwork/contracts/blob/main/contracts/staking/stakeManager/StakeManager.sol)
67
-
@@ -399,9 +399,9 @@ async function fetchRewardsInfo({ stakingApi, delegator, currency }) {
399
399
  }
400
400
  }
401
401
 
402
- export async function getPolygonStakingInfo({ address, asset }) {
402
+ export async function getPolygonStakingInfo({ address, asset, server }) {
403
403
  const { currency } = asset
404
- const stakingApi = new MaticStakingApi()
404
+ const stakingApi = new MaticStakingApi(undefined, undefined, server)
405
405
  const delegator = address.toLowerCase()
406
406
  const [
407
407
  delegatedBalance,
@@ -2,7 +2,6 @@
2
2
 
3
3
  import { getNonce, transactionExists } from '../eth-like-util'
4
4
  import {
5
- createUnsignedTx,
6
5
  calculateBumpedGasPrice,
7
6
  isToken as checkIsToken,
8
7
  normalizeTxId,
@@ -10,8 +9,9 @@ import {
10
9
  import assert from 'minimalistic-assert'
11
10
  import getFeeInfo from './get-fee-info'
12
11
 
13
- const txSendFactory = ({ assetClientInterface }) => {
12
+ const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
14
13
  assert(assetClientInterface, 'assetClientInterface is required')
14
+ assert(createUnsignedTx, 'createUnsignedTx is required')
15
15
  return async ({
16
16
  asset,
17
17
  walletAccount,
@@ -113,6 +113,7 @@ const txSendFactory = ({ assetClientInterface }) => {
113
113
  keepTxInput,
114
114
  isSendAll,
115
115
  isExchange,
116
+ createUnsignedTx,
116
117
  }
117
118
  let { txId, rawTx, nonce, gasLimit, tipGasPrice } = await createTx(createTxParams)
118
119
 
@@ -219,6 +220,7 @@ const createTx = async ({
219
220
  isExchange,
220
221
  fromAddress,
221
222
  feeOpts,
223
+ createUnsignedTx,
222
224
  }) => {
223
225
  const isToken = checkIsToken(asset)
224
226
 
@@ -1,17 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'avalanchec'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class AvalancheFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- })
16
- }
17
- }
@@ -1,17 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'bsc'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class BscFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- })
16
- }
17
- }
@@ -1,18 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'ethereum'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class EthereumFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee, interval }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- interval,
16
- })
17
- }
18
- }
@@ -1,19 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'ethereumarbnova'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class EthereumArbnovaFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee, interval }) {
9
- super({
10
- updateFee,
11
- assetName,
12
- getGasPrice: async () => {
13
- const fee = await getServerByName(assetName).getFee()
14
- return fee?.gasPrice
15
- },
16
- interval,
17
- })
18
- }
19
- }
@@ -1,19 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'ethereumarbone'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class EthereumArboneFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee, interval }) {
9
- super({
10
- updateFee,
11
- assetName,
12
- getGasPrice: async () => {
13
- const fee = await getServerByName(assetName).getFee()
14
- return fee?.gasPrice
15
- },
16
- interval,
17
- })
18
- }
19
- }
@@ -1,17 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'ethereumclassic'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class EthereumClassicFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- })
16
- }
17
- }
@@ -1,18 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'ethereumgoerli'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class EthereumGoerliFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee, interval }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- interval,
16
- })
17
- }
18
- }
@@ -1,18 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'ethereumholesky'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class EthereumHoleskyFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee, interval }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- interval,
16
- })
17
- }
18
- }
@@ -1,18 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'ethereumsepolia'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class EthereumSepoliaFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee, interval }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- interval,
16
- })
17
- }
18
- }
@@ -1,17 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'fantommainnet'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class FantomFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- })
16
- }
17
- }
@@ -1,17 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'harmonymainnet'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class HarmonyFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- })
16
- }
17
- }
@@ -1,16 +0,0 @@
1
- export * from './server-based-fee-monitor'
2
-
3
- export * from './ethereum'
4
- export * from './ethereumclassic'
5
- export * from './ethereumgoerli'
6
- export * from './ethereumholesky'
7
- export * from './ethereumsepolia'
8
- export * from './bsc'
9
- export * from './polygon'
10
- export * from './avalanchec'
11
- export * from './fantom'
12
- export * from './harmony'
13
- export * from './ethereumarbnova'
14
- export * from './ethereumarbone'
15
- export * from './rootstock'
16
- export * from './optimism'
@@ -1,19 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'optimism'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class OptimismFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee, interval }) {
9
- super({
10
- updateFee,
11
- assetName,
12
- getGasPrice: async () => {
13
- const fee = await getServerByName(assetName).getFee()
14
- return fee?.gasPrice
15
- },
16
- interval,
17
- })
18
- }
19
- }
@@ -1,17 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'matic'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class PolygonFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- })
16
- }
17
- }
@@ -1,17 +0,0 @@
1
- import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
2
- import { getServerByName } from '../exodus-eth-server'
3
-
4
- const assetName = 'rootstock'
5
-
6
- // @deprecated use ./server-based-fee-monitor.js
7
- export class RootstockFeeMonitor extends EthereumLikeFeeMonitor {
8
- constructor({ updateFee }) {
9
- const server = getServerByName(assetName)
10
- const getGasPrice = (...args) => server.gasPrice(...args)
11
- super({
12
- updateFee,
13
- assetName,
14
- getGasPrice,
15
- })
16
- }
17
- }