@exodus/ethereum-api 4.0.2 → 4.0.3-alpha1
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 +3 -4
- package/src/exodus-eth-server/api-coin-nodes.js +191 -0
- package/src/exodus-eth-server/index.js +20 -7
- package/src/fee-monitor/index.js +1 -0
- package/src/fee-monitor/rootstock.js +14 -0
- package/src/gas-estimation.js +4 -1
- package/src/get-balances.js +5 -2
- package/src/tx-log/ethereum-no-history-monitor.js +193 -0
- package/src/tx-log/index.js +1 -0
- package/src/tx-log/monitor-utils/get-derive-transactions-to-check.js +1 -1
- package/LICENSE.md +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3-alpha1",
|
|
4
4
|
"description": "Ethereum Api",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@exodus/asset-lib": "^3.7.1",
|
|
18
18
|
"@exodus/crypto": "^1.0.0-rc.0",
|
|
19
|
-
"@exodus/ethereum-lib": "^2.26.
|
|
19
|
+
"@exodus/ethereum-lib": "^2.26.1-alpha2",
|
|
20
20
|
"@exodus/ethereumjs-util": "^7.1.0-exodus.6",
|
|
21
21
|
"@exodus/fetch": "^1.2.1",
|
|
22
22
|
"@exodus/simple-retry": "^0.0.6",
|
|
@@ -35,6 +35,5 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@exodus/models": "^8.10.4"
|
|
38
|
-
}
|
|
39
|
-
"gitHead": "d3498091de0e60d3593995c846acbe62cacecc1c"
|
|
38
|
+
}
|
|
40
39
|
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { bufferToHex } from '@exodus/ethereumjs-util'
|
|
2
|
+
import SolidityContract from '@exodus/solidity-contract'
|
|
3
|
+
import EventEmitter from 'events'
|
|
4
|
+
|
|
5
|
+
export default class ApiCoinNodesServer extends EventEmitter {
|
|
6
|
+
constructor({ uri }) {
|
|
7
|
+
super()
|
|
8
|
+
this.uri = uri
|
|
9
|
+
this.id = 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
setURI(uri) {
|
|
13
|
+
this.uri = uri
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async request(body) {
|
|
17
|
+
const options = {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: { 'Content-Type': 'application/json' },
|
|
20
|
+
body: JSON.stringify(body),
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const response = await fetch(this.uri, options)
|
|
24
|
+
const data = await response.json()
|
|
25
|
+
|
|
26
|
+
return data
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async sendBatchRequest(batch) {
|
|
30
|
+
const responses = await this.request(batch)
|
|
31
|
+
const isValid = responses.every((response) => {
|
|
32
|
+
return !isNaN(response?.id) && response?.result
|
|
33
|
+
})
|
|
34
|
+
if (responses.length !== batch.length || !isValid) {
|
|
35
|
+
throw new Error('Bad rpc batch response')
|
|
36
|
+
}
|
|
37
|
+
const keyed = responses.reduce((acc, response) => {
|
|
38
|
+
return { ...acc, [`${response.id}`]: response.result }
|
|
39
|
+
}, {})
|
|
40
|
+
return batch.map((request) => keyed[`${request.id}`])
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async sendRequest(request) {
|
|
44
|
+
const response = await this.request(request)
|
|
45
|
+
|
|
46
|
+
const result = response?.result
|
|
47
|
+
const error = response?.error
|
|
48
|
+
if (error || !result) {
|
|
49
|
+
const message = error?.message || error?.code || 'no result'
|
|
50
|
+
throw new Error(`Bad rpc response: ${message}`)
|
|
51
|
+
}
|
|
52
|
+
return result
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async isContract(address) {
|
|
56
|
+
const code = await this.getCode(address)
|
|
57
|
+
return code.length > 2
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
buildRequest({ method, params = [] }) {
|
|
61
|
+
return { jsonrpc: '2.0', id: this.id++, method, params }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
balanceOfRequest(address, tokenAddress, tag = 'latest') {
|
|
65
|
+
const contract = SolidityContract.simpleErc20(tokenAddress)
|
|
66
|
+
const callData = contract.balanceOf.build(address)
|
|
67
|
+
const data = {
|
|
68
|
+
data: bufferToHex(callData),
|
|
69
|
+
to: tokenAddress,
|
|
70
|
+
}
|
|
71
|
+
return this.ethCallRequest(data, tag)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getBalanceRequest(address, tag = 'latest') {
|
|
75
|
+
return this.buildRequest({ method: 'eth_getBalance', params: [address, tag] })
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
gasPriceRequest() {
|
|
79
|
+
return this.buildRequest({ method: 'eth_gasPrice' })
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
estimateGasRequest(data, tag = 'latest') {
|
|
83
|
+
return this.buildRequest({ method: 'eth_estimateGas', params: [data, tag] })
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
sendRawTransactionRequest(data) {
|
|
87
|
+
const hex = data.startsWith('0x') ? data : '0x' + data
|
|
88
|
+
return this.buildRequest({ method: 'eth_sendRawTransaction', params: [hex] })
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getCodeRequest(address, tag = 'latest') {
|
|
92
|
+
return this.buildRequest({ method: 'eth_getCode', params: [address, tag] })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getTransactionCountRequest(address, tag = 'latest') {
|
|
96
|
+
return this.buildRequest({ method: 'eth_getTransactionCount', params: [address, tag] })
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
getTransactionByHashRequest(hash) {
|
|
100
|
+
return this.buildRequest({ method: 'eth_getTransactionByHash', params: [hash] })
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getTransactionReceiptRequest(txhash) {
|
|
104
|
+
return this.buildRequest({ method: 'eth_getTransactionReceipt', params: [txhash] })
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
ethCallRequest(data, tag) {
|
|
108
|
+
return this.buildRequest({ method: 'eth_call', params: [data, tag] })
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
blockNumberRequest() {
|
|
112
|
+
return this.buildRequest({ method: 'eth_blockNumber' })
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
getBlockByNumberRequest(numberHex, isFullTxs = false) {
|
|
116
|
+
return this.buildRequest({ method: 'eth_getBlockByNumber', params: [numberHex, isFullTxs] })
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
simulateRawTransactionRequest(rawTx, applyPending = true) {
|
|
120
|
+
const replaced = rawTx.replace('0x', '')
|
|
121
|
+
return this.buildRequest({
|
|
122
|
+
method: 'debug_simulateRawTransaction',
|
|
123
|
+
params: [replaced, applyPending],
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async balanceOf(...params) {
|
|
128
|
+
const request = this.balanceOfRequest(...params)
|
|
129
|
+
return this.sendRequest(request)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async getBalance(...params) {
|
|
133
|
+
const request = this.getBalanceRequest(...params)
|
|
134
|
+
return this.sendRequest(request)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async gasPrice(...params) {
|
|
138
|
+
const request = this.gasPriceRequest(...params)
|
|
139
|
+
return this.sendRequest(request)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async estimateGas(...params) {
|
|
143
|
+
const request = this.estimateGasRequest(...params)
|
|
144
|
+
return this.sendRequest(request)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async sendRawTransaction(...params) {
|
|
148
|
+
const request = this.sendRawTransactionRequest(...params)
|
|
149
|
+
return this.sendRequest(request)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async getCode(...params) {
|
|
153
|
+
const request = this.getCodeRequest(...params)
|
|
154
|
+
return this.sendRequest(request)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async getTransactionCount(...params) {
|
|
158
|
+
const request = this.getTransactionCountRequest(...params)
|
|
159
|
+
return this.sendRequest(request)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async getTransactionByHash(...params) {
|
|
163
|
+
const request = this.getTransactionByHashRequest(...params)
|
|
164
|
+
return this.sendRequest(request)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async getTransactionReceipt(...params) {
|
|
168
|
+
const request = this.getTransactionReceiptRequest(...params)
|
|
169
|
+
return this.sendRequest(request)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async ethCall(...params) {
|
|
173
|
+
const request = this.ethCallRequest(...params)
|
|
174
|
+
return this.sendRequest(request)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async blockNumber(...params) {
|
|
178
|
+
const request = this.blockNumberRequest(...params)
|
|
179
|
+
return this.sendRequest(request)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async getBlockByNumber(...params) {
|
|
183
|
+
const request = this.getBlockByNumberRequest(...params)
|
|
184
|
+
return this.sendRequest(request)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async simulateRawTransaction(...params) {
|
|
188
|
+
const request = this.simulateRawTransactionRequest(...params)
|
|
189
|
+
return this.sendRequest(request)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_SERVER_URLS,
|
|
3
|
+
ETHEREUM_LIKE_ASSETS,
|
|
4
|
+
ETHEREUM_LIKE_MONITOR_TYPES,
|
|
5
|
+
} from '@exodus/ethereum-lib'
|
|
2
6
|
|
|
3
7
|
import { create } from './api'
|
|
4
8
|
import ClarityServer from './clarity'
|
|
9
|
+
import ApiCoinNodesServer from './api-coin-nodes'
|
|
10
|
+
|
|
11
|
+
function getAssetServer(assetName) {
|
|
12
|
+
switch (ETHEREUM_LIKE_MONITOR_TYPES[assetName]) {
|
|
13
|
+
case 'no-history':
|
|
14
|
+
return new ApiCoinNodesServer({ uri: DEFAULT_SERVER_URLS[assetName] })
|
|
15
|
+
case 'clarity':
|
|
16
|
+
return new ClarityServer({ baseAssetName: assetName, uri: DEFAULT_SERVER_URLS[assetName] })
|
|
17
|
+
case 'magnifier':
|
|
18
|
+
return create(DEFAULT_SERVER_URLS[assetName], assetName)
|
|
19
|
+
default:
|
|
20
|
+
throw new Error(`No server API found for ${assetName}`)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
5
23
|
|
|
6
24
|
const serverMap = Object.fromEntries(
|
|
7
|
-
ETHEREUM_LIKE_ASSETS.map((assetName) => [
|
|
8
|
-
assetName,
|
|
9
|
-
DEFAULT_SERVER_URLS[assetName].includes('clarity')
|
|
10
|
-
? new ClarityServer({ baseAssetName: assetName, uri: DEFAULT_SERVER_URLS[assetName] })
|
|
11
|
-
: create(DEFAULT_SERVER_URLS[assetName], assetName),
|
|
12
|
-
])
|
|
25
|
+
ETHEREUM_LIKE_ASSETS.map((assetName) => [assetName, getAssetServer(assetName)])
|
|
13
26
|
)
|
|
14
27
|
|
|
15
28
|
// allow self-signed certs
|
package/src/fee-monitor/index.js
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EthereumLikeFeeMonitor } from '@exodus/ethereum-lib'
|
|
2
|
+
import { getServerByName } from '../exodus-eth-server'
|
|
3
|
+
|
|
4
|
+
const assetName = 'rootstock'
|
|
5
|
+
|
|
6
|
+
export class RootstockFeeMonitor extends EthereumLikeFeeMonitor {
|
|
7
|
+
constructor({ updateFee }) {
|
|
8
|
+
super({
|
|
9
|
+
updateFee,
|
|
10
|
+
assetName,
|
|
11
|
+
getGasPrice: getServerByName(assetName).gasPrice,
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
}
|
package/src/gas-estimation.js
CHANGED
|
@@ -61,7 +61,10 @@ export async function fetchGasLimit({
|
|
|
61
61
|
|
|
62
62
|
const _isToken = isToken(asset)
|
|
63
63
|
if (_isToken) {
|
|
64
|
-
|
|
64
|
+
// only create tx-input only if not pass tx-input to a token asset
|
|
65
|
+
if (txInput === '0x') {
|
|
66
|
+
txInput = ethUtil.bufferToHex(asset.contract.transfer.build(toAddress, amount.toBaseString()))
|
|
67
|
+
}
|
|
65
68
|
amount = asset.baseAsset.currency.ZERO
|
|
66
69
|
toAddress = asset.contract.address
|
|
67
70
|
} else if (!isContract && !['ethereumarbone', 'ethereumarbnova'].includes(asset.name)) {
|
package/src/get-balances.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRpcBalanceAsset } from '@exodus/ethereum-lib'
|
|
1
|
+
import { ETHEREUM_LIKE_MONITOR_TYPES, isRpcBalanceAsset } from '@exodus/ethereum-lib'
|
|
2
2
|
|
|
3
3
|
const fixBalance = ({ txLog, balance }) => {
|
|
4
4
|
for (const tx of txLog) {
|
|
@@ -23,7 +23,10 @@ const fixBalance = ({ txLog, balance }) => {
|
|
|
23
23
|
* @returns {{balance}|null} an object with the balance or null if the balance is unknown/zero
|
|
24
24
|
*/
|
|
25
25
|
export const getBalances = ({ asset, txLog, accountState }) => {
|
|
26
|
-
if (
|
|
26
|
+
if (
|
|
27
|
+
isRpcBalanceAsset(asset) ||
|
|
28
|
+
ETHEREUM_LIKE_MONITOR_TYPES[asset.baseAsset.name] === 'no-history'
|
|
29
|
+
) {
|
|
27
30
|
const balance =
|
|
28
31
|
asset.baseAsset.name === asset.name
|
|
29
32
|
? accountState?.balance
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import BN from 'bn.js'
|
|
2
|
+
import { getServer } from '@exodus/ethereum-api'
|
|
3
|
+
import { Tx } from '@exodus/models'
|
|
4
|
+
|
|
5
|
+
import { getDeriveDataNeededForTick, getDeriveTransactionsToCheck } from './monitor-utils'
|
|
6
|
+
|
|
7
|
+
import { isEmpty, unionBy, zipObject } from 'lodash'
|
|
8
|
+
|
|
9
|
+
import { BaseMonitor } from '@exodus/asset-lib'
|
|
10
|
+
|
|
11
|
+
import { UNCONFIRMED_TX_LIMIT } from './monitor-utils/get-derive-transactions-to-check'
|
|
12
|
+
|
|
13
|
+
// The base ethereum monitor no history class handles listening for assets with no history
|
|
14
|
+
|
|
15
|
+
export class EthereumNoHistoryMonitor extends BaseMonitor {
|
|
16
|
+
constructor({ server, config, ...args }) {
|
|
17
|
+
super(args)
|
|
18
|
+
this.server = server || getServer(this.asset)
|
|
19
|
+
this.config = { ...config }
|
|
20
|
+
this.deriveDataNeededForTick = getDeriveDataNeededForTick(this.aci)
|
|
21
|
+
this.deriveTransactionsToCheck = getDeriveTransactionsToCheck({
|
|
22
|
+
getTxLog: (...args) => this.aci.getTxLog(...args),
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setServer(config) {
|
|
27
|
+
if (config.server === this.server?.uri) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
this.server.setURI(config.server)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async getBalances({ tokens, ourWalletAddress }) {
|
|
34
|
+
const batch = {}
|
|
35
|
+
const request = this.server.getBalanceRequest(ourWalletAddress)
|
|
36
|
+
batch[this.asset.name] = request
|
|
37
|
+
for (const token of tokens) {
|
|
38
|
+
const request = this.server.balanceOfRequest(ourWalletAddress, token.contract.address)
|
|
39
|
+
batch[token.name] = request
|
|
40
|
+
}
|
|
41
|
+
const pairs = Object.entries(batch)
|
|
42
|
+
if (!pairs.length) {
|
|
43
|
+
return {}
|
|
44
|
+
}
|
|
45
|
+
const requests = pairs.map((pair) => pair[1])
|
|
46
|
+
const responses = await this.server.sendBatchRequest(requests)
|
|
47
|
+
const entries = pairs.map((pair, idx) => {
|
|
48
|
+
const balanceHex = responses[idx]
|
|
49
|
+
const name = pair[0]
|
|
50
|
+
const hex = balanceHex.startsWith('0x') ? balanceHex.slice(2) : balanceHex
|
|
51
|
+
const balance = new BN(hex, 'hex').toString()
|
|
52
|
+
return [name, balance]
|
|
53
|
+
})
|
|
54
|
+
return Object.fromEntries(entries)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getNewAccountState({ tokens, ourWalletAddress }) {
|
|
58
|
+
const asset = this.asset
|
|
59
|
+
const newAccountState = {}
|
|
60
|
+
const balances = await this.getBalances({ tokens, ourWalletAddress })
|
|
61
|
+
const balance = balances[asset.name]
|
|
62
|
+
newAccountState.balance = asset.currency.baseUnit(balance)
|
|
63
|
+
const tokenBalancePairs = Object.entries(balances).filter((entry) => entry[0] !== asset.name)
|
|
64
|
+
const entries = tokenBalancePairs
|
|
65
|
+
.map((pair) => {
|
|
66
|
+
const token = tokens.find((token) => token.name === pair[0])
|
|
67
|
+
const value = token.currency.baseUnit(pair[1] || 0)
|
|
68
|
+
return value.isZero ? null : [token.name, value]
|
|
69
|
+
})
|
|
70
|
+
.filter((pair) => pair)
|
|
71
|
+
const tokenBalances = Object.fromEntries(entries)
|
|
72
|
+
if (!isEmpty(tokenBalances)) newAccountState.tokenBalances = tokenBalances
|
|
73
|
+
return newAccountState
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async deriveData({ assetSource, tokens }) {
|
|
77
|
+
const { assetName, walletAccount } = assetSource
|
|
78
|
+
|
|
79
|
+
const {
|
|
80
|
+
ourWalletAddress,
|
|
81
|
+
currentAccountState,
|
|
82
|
+
minimumConfirmations,
|
|
83
|
+
} = await this.deriveDataNeededForTick({ assetName, walletAccount })
|
|
84
|
+
const transactionsToCheck = await this.deriveTransactionsToCheck({
|
|
85
|
+
assetName,
|
|
86
|
+
walletAccount,
|
|
87
|
+
tokens,
|
|
88
|
+
ourWalletAddress,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
ourWalletAddress,
|
|
93
|
+
currentAccountState,
|
|
94
|
+
minimumConfirmations,
|
|
95
|
+
...transactionsToCheck,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async getTransactionsFromNode(transactions) {
|
|
100
|
+
const batch = []
|
|
101
|
+
for (const { tx } of transactions) {
|
|
102
|
+
const request = this.server.getTransactionByHashRequest(tx.txId)
|
|
103
|
+
batch.push(request)
|
|
104
|
+
}
|
|
105
|
+
const responses = await this.server.sendBatchRequest(batch)
|
|
106
|
+
const txIds = transactions.map(({ tx }) => tx.txId)
|
|
107
|
+
return zipObject(txIds, responses)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async checkPendingTransactions({
|
|
111
|
+
pendingTransactionsGroupedByAddressAndNonce,
|
|
112
|
+
pendingTransactionsToCheck,
|
|
113
|
+
walletAccount,
|
|
114
|
+
}) {
|
|
115
|
+
const txsToUpdate = []
|
|
116
|
+
const txsToRemove = []
|
|
117
|
+
const now = Date.now()
|
|
118
|
+
|
|
119
|
+
const pendingTransactions = unionBy(
|
|
120
|
+
Object.values(pendingTransactionsGroupedByAddressAndNonce),
|
|
121
|
+
Object.values(pendingTransactionsToCheck),
|
|
122
|
+
'tx.txId'
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if (isEmpty(pendingTransactions))
|
|
126
|
+
return {
|
|
127
|
+
txsToUpdate,
|
|
128
|
+
txsToRemove,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const txsFromNode = await this.getTransactionsFromNode(pendingTransactions)
|
|
132
|
+
|
|
133
|
+
for (const { tx, assetName } of pendingTransactions) {
|
|
134
|
+
const txFromNode = txsFromNode[tx.txId]
|
|
135
|
+
if (now - tx.date.getTime() > UNCONFIRMED_TX_LIMIT) {
|
|
136
|
+
txsToRemove.push({
|
|
137
|
+
tx,
|
|
138
|
+
assetSource: { asset: assetName, walletAccount },
|
|
139
|
+
})
|
|
140
|
+
} else if (txFromNode.blockHash !== null) {
|
|
141
|
+
txsToUpdate.push({
|
|
142
|
+
tx: { ...tx, confirmations: 1 },
|
|
143
|
+
assetSource: { asset: assetName, walletAccount },
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
txsToUpdate,
|
|
150
|
+
txsToRemove,
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async tick({ refresh, walletAccount }) {
|
|
155
|
+
const assets = await this.aci.getAssetsForNetwork({ baseAssetName: this.asset.name })
|
|
156
|
+
const tokens = Object.values(assets).filter((asset) => asset.baseAsset.name !== asset.name)
|
|
157
|
+
|
|
158
|
+
const assetSource = { assetName: this.asset.name, walletAccount }
|
|
159
|
+
|
|
160
|
+
const {
|
|
161
|
+
ourWalletAddress,
|
|
162
|
+
pendingTransactionsGroupedByAddressAndNonce,
|
|
163
|
+
pendingTransactionsToCheck,
|
|
164
|
+
} = await this.deriveData({
|
|
165
|
+
assetSource,
|
|
166
|
+
tokens,
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
const accountState = await this.getNewAccountState({
|
|
170
|
+
tokens,
|
|
171
|
+
ourWalletAddress,
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
const { txsToUpdate, txsToRemove } = await this.checkPendingTransactions({
|
|
175
|
+
pendingTransactionsGroupedByAddressAndNonce,
|
|
176
|
+
pendingTransactionsToCheck,
|
|
177
|
+
walletAccount,
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const logItemsByAsset = {}
|
|
181
|
+
|
|
182
|
+
txsToUpdate.forEach((txToUpdate) => {
|
|
183
|
+
logItemsByAsset[txToUpdate.assetSource.asset] =
|
|
184
|
+
logItemsByAsset[txToUpdate.assetSource.asset] || []
|
|
185
|
+
logItemsByAsset[txToUpdate.assetSource.asset].push(Tx.fromJSON(txToUpdate.tx))
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
await this.updateAccountState({ newData: { ...accountState }, walletAccount })
|
|
189
|
+
|
|
190
|
+
await this.removeFromTxLog(txsToRemove)
|
|
191
|
+
await this.updateTxLogByAsset({ logItemsByAsset, walletAccount, refresh })
|
|
192
|
+
}
|
|
193
|
+
}
|
package/src/tx-log/index.js
CHANGED
package/LICENSE.md
DELETED
|
File without changes
|