@exodus/solana-api 3.11.1 → 3.11.3
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/README.md +1 -1
- package/package.json +4 -4
- package/src/api.js +10 -14
- package/src/get-stake-activation/delegation.js +153 -0
- package/src/get-stake-activation/index.js +63 -0
- package/src/index.js +0 -1
- package/src/tx-log/solana-auto-withdraw-monitor.js +2 -5
- package/src/tx-log/solana-monitor.js +5 -1
- package/src/tx-send.js +1 -1
- package/src/txs-utils.js +3 -8
- package/src/fee-monitor.js +0 -19
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
|
+
## [3.11.3](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.11.2...@exodus/solana-api@3.11.3) (2024-10-23)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* solana-api to use the right tokenAssetType ([#4331](https://github.com/ExodusMovement/assets/issues/4331)) ([d8f0be9](https://github.com/ExodusMovement/assets/commit/d8f0be9be29f286a75a6fdc2c112f004d7816842))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [3.11.2](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.11.1...@exodus/solana-api@3.11.2) (2024-10-10)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* SOL doc old references ([#4168](https://github.com/ExodusMovement/assets/issues/4168)) ([73e5516](https://github.com/ExodusMovement/assets/commit/73e5516109f9a3c2012198ef8aa68fc0a5032d5d))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
## [3.11.1](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.11.0...@exodus/solana-api@3.11.1) (2024-09-11)
|
|
7
25
|
|
|
8
26
|
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# Solana Api · [](https://www.npmjs.com/package/@exodus/solana-api)
|
|
2
2
|
|
|
3
|
-
- To get all transactions data from an address we gotta call 3 rpcs `
|
|
3
|
+
- To get all transactions data from an address we gotta call 3 rpcs `getSignaturesForAddress` (get txIds) -> `getTransaction` (get tx details) -> `getBlockTime` (get tx timestamp). Pretty annoying and resource-consuming backend-side. (https://github.com/solana-labs/solana/issues/12411)
|
|
4
4
|
- calling `getBlockTime` might results in an error if the slot/block requested is too old (https://github.com/solana-labs/solana/issues/12413), looks like some Solana validators can choose to not keep all the ledger blocks (fix in progress by solana team).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-api",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.3",
|
|
4
4
|
"description": "Exodus internal Solana asset API wrapper",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@exodus/models": "^12.0.1",
|
|
32
32
|
"@exodus/simple-retry": "^0.0.6",
|
|
33
33
|
"@exodus/solana-lib": "^3.6.0",
|
|
34
|
-
"@exodus/solana-meta": "^2.0.
|
|
34
|
+
"@exodus/solana-meta": "^2.0.2",
|
|
35
35
|
"@exodus/timer": "^1.1.1",
|
|
36
36
|
"bn.js": "^4.11.0",
|
|
37
37
|
"debug": "^4.1.1",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@exodus/assets-testing": "^1.0.0",
|
|
48
|
-
"@exodus/solana-web3.js": "^1.63.1-exodus.9-
|
|
48
|
+
"@exodus/solana-web3.js": "^1.63.1-exodus.9-rc3"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "f40ca3367fd84bc4c899c2dfea76004547fb111d",
|
|
51
51
|
"bugs": {
|
|
52
52
|
"url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-api"
|
|
53
53
|
},
|
package/src/api.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import createApiCJS from '@exodus/asset-json-rpc'
|
|
2
|
+
import { memoize } from '@exodus/basic-utils'
|
|
2
3
|
import { retry } from '@exodus/simple-retry'
|
|
3
4
|
import {
|
|
4
5
|
buildRawTransaction,
|
|
@@ -20,6 +21,7 @@ import urljoin from 'url-join'
|
|
|
20
21
|
import wretch from 'wretch'
|
|
21
22
|
|
|
22
23
|
import { Connection } from './connection.js'
|
|
24
|
+
import { getStakeActivation } from './get-stake-activation/index.js'
|
|
23
25
|
|
|
24
26
|
const createApi = createApiCJS.default || createApiCJS
|
|
25
27
|
|
|
@@ -31,17 +33,18 @@ const FORCE_HTTP = true // use https over ws
|
|
|
31
33
|
|
|
32
34
|
// Tokens + SOL api support
|
|
33
35
|
export class Api {
|
|
34
|
-
constructor({ rpcUrl, wsUrl, assets, txsLimit }) {
|
|
36
|
+
constructor({ rpcUrl, wsUrl, assets, txsLimit, tokenAssetType = 'SOLANA_TOKEN' }) {
|
|
35
37
|
this.setServer(rpcUrl)
|
|
36
38
|
this.setWsEndpoint(wsUrl)
|
|
37
39
|
this.setTokens(assets)
|
|
40
|
+
this.tokenAssetType = tokenAssetType
|
|
38
41
|
this.tokensToSkip = {}
|
|
39
42
|
this.txsLimit = txsLimit
|
|
40
43
|
this.connections = {}
|
|
41
|
-
this.getSupply =
|
|
44
|
+
this.getSupply = memoize(async (mintAddress) => {
|
|
42
45
|
// cached getSupply
|
|
43
46
|
const result = await this.rpcCall('getTokenSupply', [mintAddress])
|
|
44
|
-
return
|
|
47
|
+
return result?.value?.amount
|
|
45
48
|
})
|
|
46
49
|
}
|
|
47
50
|
|
|
@@ -55,7 +58,7 @@ export class Api {
|
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
setTokens(assets = {}) {
|
|
58
|
-
const solTokens = lodash.pickBy(assets, (asset) => asset.assetType ===
|
|
61
|
+
const solTokens = lodash.pickBy(assets, (asset) => asset.assetType === this.tokenAssetType)
|
|
59
62
|
this.tokens = new Map(Object.values(solTokens).map((v) => [v.mintAddress, v]))
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -126,9 +129,9 @@ export class Api {
|
|
|
126
129
|
return Number(epoch)
|
|
127
130
|
}
|
|
128
131
|
|
|
129
|
-
async getStakeActivation(
|
|
130
|
-
const {
|
|
131
|
-
return
|
|
132
|
+
async getStakeActivation(stakeAddress) {
|
|
133
|
+
const { status } = await getStakeActivation(this, stakeAddress)
|
|
134
|
+
return status
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
async getRecentBlockHash(commitment) {
|
|
@@ -148,13 +151,6 @@ export class Api {
|
|
|
148
151
|
])
|
|
149
152
|
}
|
|
150
153
|
|
|
151
|
-
async getFee() {
|
|
152
|
-
const result = await this.rpcCall('getRecentBlockhash', [
|
|
153
|
-
{ commitment: 'finalized', encoding: 'jsonParsed' },
|
|
154
|
-
])
|
|
155
|
-
return lodash.get(result, 'value.feeCalculator.lamportsPerSignature')
|
|
156
|
-
}
|
|
157
|
-
|
|
158
154
|
async getPriorityFee(transaction) {
|
|
159
155
|
// https://docs.helius.dev/solana-rpc-nodes/alpha-priority-fee-api
|
|
160
156
|
const result = await this.rpcCall('getPriorityFeeEstimate', [
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const WARMUP_COOLDOWN_RATE = 0.09
|
|
2
|
+
|
|
3
|
+
function getStakeHistoryEntry(epoch, stakeHistory) {
|
|
4
|
+
for (const entry of stakeHistory) {
|
|
5
|
+
if (entry.epoch === epoch) {
|
|
6
|
+
return entry
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getStakeAndActivating(
|
|
14
|
+
delegation, // Delegation
|
|
15
|
+
targetEpoch, // number
|
|
16
|
+
stakeHistory // StakeHistoryEntry[]
|
|
17
|
+
) {
|
|
18
|
+
if (delegation.activationEpoch === delegation.deactivationEpoch) {
|
|
19
|
+
// activated but instantly deactivated; no stake at all regardless of target_epoch
|
|
20
|
+
return {
|
|
21
|
+
effective: 0,
|
|
22
|
+
activating: 0,
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (targetEpoch === delegation.activationEpoch) {
|
|
27
|
+
// all is activating
|
|
28
|
+
return {
|
|
29
|
+
effective: 0,
|
|
30
|
+
activating: delegation.stake,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (targetEpoch < delegation.activationEpoch) {
|
|
35
|
+
// not yet enabled
|
|
36
|
+
return {
|
|
37
|
+
effective: 0,
|
|
38
|
+
activating: 0,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let currentEpoch = delegation.activationEpoch
|
|
43
|
+
let entry = getStakeHistoryEntry(currentEpoch, stakeHistory)
|
|
44
|
+
if (entry !== null) {
|
|
45
|
+
// target_epoch > self.activation_epoch
|
|
46
|
+
|
|
47
|
+
// loop from my activation epoch until the target epoch summing up my entitlement
|
|
48
|
+
// current effective stake is updated using its previous epoch's cluster stake
|
|
49
|
+
let currentEffectiveStake = 0
|
|
50
|
+
while (entry !== null) {
|
|
51
|
+
currentEpoch++
|
|
52
|
+
const remaining = delegation.stake - currentEffectiveStake
|
|
53
|
+
const weight = Number(remaining) / Number(entry.activating)
|
|
54
|
+
const newlyEffectiveClusterStake = Number(entry.effective) * WARMUP_COOLDOWN_RATE
|
|
55
|
+
const newlyEffectiveStake = Math.max(1, Math.round(weight * newlyEffectiveClusterStake))
|
|
56
|
+
|
|
57
|
+
currentEffectiveStake += newlyEffectiveStake
|
|
58
|
+
if (currentEffectiveStake >= delegation.stake) {
|
|
59
|
+
currentEffectiveStake = delegation.stake
|
|
60
|
+
break
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (currentEpoch >= targetEpoch || currentEpoch >= delegation.deactivationEpoch) {
|
|
64
|
+
break
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
entry = getStakeHistoryEntry(currentEpoch, stakeHistory)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
effective: currentEffectiveStake,
|
|
72
|
+
activating: delegation.stake - currentEffectiveStake,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// no history or I've dropped out of history, so assume fully effective
|
|
77
|
+
return {
|
|
78
|
+
effective: delegation.stake,
|
|
79
|
+
activating: 0,
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function getStakeActivatingAndDeactivating(delegation, targetEpoch, stakeHistory) {
|
|
84
|
+
const { effective, activating } = getStakeAndActivating(delegation, targetEpoch, stakeHistory)
|
|
85
|
+
|
|
86
|
+
// then de-activate some portion if necessary
|
|
87
|
+
if (targetEpoch < delegation.deactivationEpoch) {
|
|
88
|
+
return {
|
|
89
|
+
effective,
|
|
90
|
+
activating,
|
|
91
|
+
deactivating: 0,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (targetEpoch === delegation.deactivationEpoch) {
|
|
96
|
+
// can only deactivate what's activated
|
|
97
|
+
return {
|
|
98
|
+
effective,
|
|
99
|
+
activating: 0,
|
|
100
|
+
deactivating: effective,
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let currentEpoch = delegation.deactivationEpoch
|
|
105
|
+
let entry = getStakeHistoryEntry(currentEpoch, stakeHistory)
|
|
106
|
+
if (entry !== null) {
|
|
107
|
+
// target_epoch > self.activation_epoch
|
|
108
|
+
// loop from my deactivation epoch until the target epoch
|
|
109
|
+
// current effective stake is updated using its previous epoch's cluster stake
|
|
110
|
+
let currentEffectiveStake = effective
|
|
111
|
+
while (entry !== null) {
|
|
112
|
+
currentEpoch++
|
|
113
|
+
// if there is no deactivating stake at prev epoch, we should have been
|
|
114
|
+
// fully undelegated at this moment
|
|
115
|
+
if (entry.deactivating === 0) {
|
|
116
|
+
break
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// I'm trying to get to zero, how much of the deactivation in stake
|
|
120
|
+
// this account is entitled to take
|
|
121
|
+
const weight = Number(currentEffectiveStake) / Number(entry.deactivating)
|
|
122
|
+
|
|
123
|
+
// portion of newly not-effective cluster stake I'm entitled to at current epoch
|
|
124
|
+
const newlyNotEffectiveClusterStake = Number(entry.effective) * WARMUP_COOLDOWN_RATE
|
|
125
|
+
const newlyNotEffectiveStake = Math.max(1, Math.round(weight * newlyNotEffectiveClusterStake))
|
|
126
|
+
|
|
127
|
+
currentEffectiveStake -= newlyNotEffectiveStake
|
|
128
|
+
if (currentEffectiveStake <= 0) {
|
|
129
|
+
currentEffectiveStake = 0
|
|
130
|
+
break
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (currentEpoch >= targetEpoch) {
|
|
134
|
+
break
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
entry = getStakeHistoryEntry(currentEpoch, stakeHistory)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// deactivating stake should equal to all of currently remaining effective stake
|
|
141
|
+
return {
|
|
142
|
+
effective: currentEffectiveStake,
|
|
143
|
+
deactivating: currentEffectiveStake,
|
|
144
|
+
activating: 0,
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
effective: 0,
|
|
150
|
+
activating: 0,
|
|
151
|
+
deactivating: 0,
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { getStakeActivatingAndDeactivating } from './delegation.js'
|
|
2
|
+
|
|
3
|
+
const SYSVAR_STAKE_HISTORY_ADDRESS = 'SysvarStakeHistory1111111111111111111111111'
|
|
4
|
+
|
|
5
|
+
// Extracted from https://github.com/anza-xyz/solana-rpc-client-extensions/blob/main/js/src/rpc.ts
|
|
6
|
+
|
|
7
|
+
export async function getStakeActivation(api, stakeAddress) {
|
|
8
|
+
const [epoch, stakeAccount, stakeHistory] = await Promise.all([
|
|
9
|
+
api.getEpochInfo(),
|
|
10
|
+
(async () => {
|
|
11
|
+
const stakeAccount = await api.getAccountInfo(stakeAddress)
|
|
12
|
+
if (stakeAccount.data.discriminant === 0) {
|
|
13
|
+
throw new Error('data.discriminant is 0')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return stakeAccount
|
|
17
|
+
})(),
|
|
18
|
+
(async () => {
|
|
19
|
+
return api.getAccountInfo(SYSVAR_STAKE_HISTORY_ADDRESS)
|
|
20
|
+
})(),
|
|
21
|
+
])
|
|
22
|
+
|
|
23
|
+
const rentExemptReserve = stakeAccount.data.parsed.info.meta.rentExemptReserve
|
|
24
|
+
if (stakeAccount.data.parsed.discriminant === 1) {
|
|
25
|
+
return {
|
|
26
|
+
status: 'inactive',
|
|
27
|
+
active: 0,
|
|
28
|
+
inactive: stakeAccount.lamports - rentExemptReserve,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// THE HARD PART
|
|
33
|
+
const { effective, activating, deactivating } = stakeAccount.data.parsed.info.stake
|
|
34
|
+
? getStakeActivatingAndDeactivating(
|
|
35
|
+
stakeAccount.data.parsed.info.stake.delegation,
|
|
36
|
+
epoch,
|
|
37
|
+
stakeHistory.data.parsed.info
|
|
38
|
+
)
|
|
39
|
+
: {
|
|
40
|
+
effective: 0,
|
|
41
|
+
activating: 0,
|
|
42
|
+
deactivating: 0,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let status
|
|
46
|
+
if (deactivating > 0) {
|
|
47
|
+
status = 'deactivating'
|
|
48
|
+
} else if (activating > 0) {
|
|
49
|
+
status = 'activating'
|
|
50
|
+
} else if (effective > 0) {
|
|
51
|
+
status = 'active'
|
|
52
|
+
} else {
|
|
53
|
+
status = 'inactive'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const inactive = stakeAccount.lamports - effective - rentExemptReserve
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
status,
|
|
60
|
+
active: effective,
|
|
61
|
+
inactive,
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import assetsList from '@exodus/solana-meta'
|
|
|
4
4
|
|
|
5
5
|
import { Api } from './api.js'
|
|
6
6
|
|
|
7
|
-
export { default as SolanaFeeMonitor } from './fee-monitor.js'
|
|
8
7
|
export { SolanaMonitor, SolanaAutoWithdrawMonitor } from './tx-log/index.js'
|
|
9
8
|
export { createAccountState } from './account-state.js'
|
|
10
9
|
export { getSolStakedFee, getStakingInfo, getUnstakingFee } from './staking-utils.js'
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Timer } from '@exodus/timer'
|
|
2
|
-
import lodash from 'lodash'
|
|
3
2
|
import assert from 'minimalistic-assert'
|
|
4
3
|
import ms from 'ms'
|
|
5
4
|
|
|
6
|
-
const { get } = lodash
|
|
7
|
-
|
|
8
5
|
const INTERVAL = ms('30s')
|
|
9
6
|
|
|
10
7
|
export class SolanaAutoWithdrawMonitor {
|
|
@@ -53,9 +50,9 @@ export class SolanaAutoWithdrawMonitor {
|
|
|
53
50
|
async tryWithdraw({ accountState, walletAccount }) {
|
|
54
51
|
const stakingInfo = accountState.stakingInfo
|
|
55
52
|
const feeData = await this.aci.getFeeData({ assetName: this.assetName })
|
|
56
|
-
const fee =
|
|
53
|
+
const fee = feeData?.fee ?? this.asset.currency.ZERO
|
|
57
54
|
|
|
58
|
-
const solBalance =
|
|
55
|
+
const solBalance = accountState?.balance ?? this.asset.currency.ZERO
|
|
59
56
|
if (solBalance.lt(fee) || stakingInfo.withdrawable.isZero) return []
|
|
60
57
|
|
|
61
58
|
const promises = await this.createAndSendStake(
|
|
@@ -266,7 +266,11 @@ export class SolanaMonitor extends BaseMonitor {
|
|
|
266
266
|
item.data.meta = tx.data.meta
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
if (
|
|
269
|
+
if (
|
|
270
|
+
asset.assetType === this.api.tokenAssetType &&
|
|
271
|
+
item.feeAmount &&
|
|
272
|
+
item.feeAmount.isPositive
|
|
273
|
+
) {
|
|
270
274
|
const feeItem = {
|
|
271
275
|
..._.clone(item),
|
|
272
276
|
coinName: feeAsset.name,
|
package/src/tx-send.js
CHANGED
|
@@ -44,7 +44,7 @@ export const createAndBroadcastTXFactory =
|
|
|
44
44
|
walletAccount,
|
|
45
45
|
})
|
|
46
46
|
|
|
47
|
-
const isToken = asset.assetType ===
|
|
47
|
+
const isToken = asset.assetType === api.tokenAssetType
|
|
48
48
|
|
|
49
49
|
// Check if receiver has address active when sending tokens.
|
|
50
50
|
if (isToken) {
|
package/src/txs-utils.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import lodash from 'lodash'
|
|
2
|
-
|
|
3
|
-
const { get } = lodash
|
|
4
|
-
|
|
5
1
|
const isSolanaTx = (tx) => tx.coinName === 'solana'
|
|
6
2
|
export const isSolanaStaking = (tx) =>
|
|
7
|
-
isSolanaTx(tx) && ['createAccountWithSeed', 'delegate'].includes(
|
|
3
|
+
isSolanaTx(tx) && ['createAccountWithSeed', 'delegate'].includes(tx?.data?.staking?.method)
|
|
8
4
|
export const isSolanaUnstaking = (tx) =>
|
|
9
|
-
isSolanaTx(tx) &&
|
|
10
|
-
export const isSolanaWithdrawn = (tx) =>
|
|
11
|
-
isSolanaTx(tx) && get(tx, 'data.staking.method') === 'withdraw'
|
|
5
|
+
isSolanaTx(tx) && tx?.data?.staking?.method === 'undelegate'
|
|
6
|
+
export const isSolanaWithdrawn = (tx) => isSolanaTx(tx) && tx?.data?.staking?.method === 'withdraw'
|
|
12
7
|
export const isSolanaRewardsActivityTx = (tx) =>
|
|
13
8
|
[isSolanaStaking, isSolanaUnstaking, isSolanaWithdrawn].some((fn) => fn(tx))
|
package/src/fee-monitor.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { FeeMonitor } from '@exodus/asset-lib'
|
|
2
|
-
|
|
3
|
-
export default class SolanaFeeMonitor extends FeeMonitor {
|
|
4
|
-
#api
|
|
5
|
-
|
|
6
|
-
constructor({ updateFee, interval = '1m', assetName = 'solana', api }) {
|
|
7
|
-
super({ updateFee, interval, assetName })
|
|
8
|
-
this.#api = api
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async fetchFee() {
|
|
12
|
-
const fee = await this.#api.getFee()
|
|
13
|
-
if (fee === undefined) throw new Error('Failed to fetch fee')
|
|
14
|
-
|
|
15
|
-
return {
|
|
16
|
-
fee: `${fee} Lamports`,
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|