@exodus/solana-api 2.5.30 → 2.5.31-alpha.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 +2 -2
- package/src/api.js +3 -3
- package/src/tx-log/solana-monitor.js +55 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-api",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.31-alpha.0",
|
|
4
4
|
"description": "Exodus internal Solana asset API wrapper",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@exodus/assets-testing": "file:../../../__testing__"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "659340c999fa86c132293643a7fb96f33963e6cd"
|
|
38
38
|
}
|
package/src/api.js
CHANGED
|
@@ -52,7 +52,7 @@ export class Api {
|
|
|
52
52
|
|
|
53
53
|
request(path, contentType = 'application/json') {
|
|
54
54
|
return wretch(urljoin(this.rpcUrl, path)).headers({
|
|
55
|
-
'Content-
|
|
55
|
+
'Content-Type': contentType,
|
|
56
56
|
})
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -772,8 +772,8 @@ export class Api {
|
|
|
772
772
|
if (!stakingAddresses.length) return 0
|
|
773
773
|
|
|
774
774
|
// custom endpoint!
|
|
775
|
-
const rewards = await this.request(
|
|
776
|
-
.
|
|
775
|
+
const rewards = await this.request('rewards')
|
|
776
|
+
.post({ addresses: stakingAddresses })
|
|
777
777
|
.error(500, () => ({})) // addresses not found
|
|
778
778
|
.error(400, () => ({}))
|
|
779
779
|
.json()
|
|
@@ -10,14 +10,25 @@ const DEFAULT_REMOTE_CONFIG = {
|
|
|
10
10
|
staking: { enabled: true, pool: DEFAULT_POOL_ADDRESS },
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
const TICKS_BETWEEN_HISTORY_FETCHES = 10
|
|
14
|
+
const TICKS_BETWEEN_STAKE_FETCHES = 5
|
|
15
|
+
|
|
13
16
|
export class SolanaMonitor extends BaseMonitor {
|
|
14
|
-
constructor({
|
|
17
|
+
constructor({
|
|
18
|
+
api,
|
|
19
|
+
includeUnparsed = false,
|
|
20
|
+
ticksBetweenHistoryFetches = TICKS_BETWEEN_HISTORY_FETCHES,
|
|
21
|
+
ticksBetweenStakeFetches = TICKS_BETWEEN_STAKE_FETCHES,
|
|
22
|
+
...args
|
|
23
|
+
}) {
|
|
15
24
|
super(args)
|
|
16
25
|
assert(api, 'api is required')
|
|
17
26
|
this.api = api
|
|
18
27
|
this.cursors = {}
|
|
19
28
|
this.assets = {}
|
|
20
29
|
this.staking = DEFAULT_REMOTE_CONFIG.staking
|
|
30
|
+
this.ticksBetweenStakeFetches = ticksBetweenStakeFetches
|
|
31
|
+
this.ticksBetweenHistoryFetches = ticksBetweenHistoryFetches
|
|
21
32
|
this.includeUnparsed = includeUnparsed
|
|
22
33
|
this.addHook('before-stop', (...args) => this.beforeStop(...args))
|
|
23
34
|
}
|
|
@@ -92,6 +103,20 @@ export class SolanaMonitor extends BaseMonitor {
|
|
|
92
103
|
return _.uniq(_.flatten(stakingAddresses))
|
|
93
104
|
}
|
|
94
105
|
|
|
106
|
+
balanceChanged({ account, newAccount }) {
|
|
107
|
+
const solBalanceChanged = !account.balance || !account.balance.equals(newAccount.balance)
|
|
108
|
+
if (solBalanceChanged) return true
|
|
109
|
+
|
|
110
|
+
const tokenBalanceChanged =
|
|
111
|
+
!account.tokenBalances ||
|
|
112
|
+
Object.entries(newAccount.tokenBalances).some(
|
|
113
|
+
([token, balance]) =>
|
|
114
|
+
!account.tokenBalances[token] || !account.tokenBalances[token].equals(balance)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return tokenBalanceChanged
|
|
118
|
+
}
|
|
119
|
+
|
|
95
120
|
async tick({ walletAccount, refresh }) {
|
|
96
121
|
// Check for new wallet account
|
|
97
122
|
await this.initWalletAccount({ walletAccount })
|
|
@@ -104,28 +129,43 @@ export class SolanaMonitor extends BaseMonitor {
|
|
|
104
129
|
const address = await this.aci.getReceiveAddress({ assetName, walletAccount, useCache: true })
|
|
105
130
|
const stakingAddresses = await this.getStakingAddressesFromTxLog({ assetName, walletAccount })
|
|
106
131
|
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
const fetchStakingInfo = this.tickCount[walletAccount] % this.ticksBetweenStakeFetches === 0
|
|
133
|
+
const staking = fetchStakingInfo
|
|
134
|
+
? await this.getStakingInfo({ address, stakingAddresses })
|
|
135
|
+
: accountState.mem
|
|
136
|
+
|
|
137
|
+
const tokenAccounts = await this.api.getTokenAccountsByOwner(address)
|
|
138
|
+
const account = await this.getAccount({ address, staking, tokenAccounts })
|
|
113
139
|
|
|
114
|
-
const
|
|
140
|
+
const balanceChanged = this.balanceChanged({ account: accountState, newAccount: account })
|
|
115
141
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
refresh || cursorChanged
|
|
119
|
-
? await this.getStakingInfo({ address, stakingAddresses })
|
|
120
|
-
: accountState.mem
|
|
142
|
+
const isHistoryUpdateTick =
|
|
143
|
+
this.tickCount[walletAccount] % this.ticksBetweenHistoryFetches === 0
|
|
121
144
|
|
|
122
|
-
|
|
123
|
-
|
|
145
|
+
const shouldUpdateHistory = refresh || isHistoryUpdateTick || balanceChanged
|
|
146
|
+
const shouldUpdateOnlyBalance = balanceChanged && !shouldUpdateHistory
|
|
147
|
+
const shouldUpdateBalanceBeforeHistory = true
|
|
124
148
|
|
|
149
|
+
// getHistory is more likely to fail/be rate limited, so we want to update users balance only on a lot of ticks
|
|
150
|
+
if (shouldUpdateBalanceBeforeHistory || shouldUpdateOnlyBalance) {
|
|
125
151
|
// update all state at once
|
|
152
|
+
await this.updateState({ account, walletAccount, staking })
|
|
126
153
|
await this.emitUnknownTokensEvent({ tokenAccounts })
|
|
154
|
+
}
|
|
155
|
+
if (shouldUpdateHistory) {
|
|
156
|
+
const { logItemsByAsset, cursorState } = await this.getHistory({
|
|
157
|
+
address,
|
|
158
|
+
accountState,
|
|
159
|
+
walletAccount,
|
|
160
|
+
refresh,
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const cursorChanged = this.hasNewCursor({ walletAccount, cursorState })
|
|
164
|
+
|
|
165
|
+
// update all state at once
|
|
127
166
|
await this.updateTxLogByAsset({ walletAccount, logItemsByAsset, refresh })
|
|
128
167
|
await this.updateState({ account, cursorState, walletAccount, staking })
|
|
168
|
+
await this.emitUnknownTokensEvent({ tokenAccounts })
|
|
129
169
|
if (refresh || cursorChanged) {
|
|
130
170
|
this.cursors[walletAccount] = cursorState.cursor
|
|
131
171
|
}
|