Browse Source

Merge pull request #521 from gre/custom-network

add a custom network that will retry / timeout / remap errors
master
Gaëtan Renaudeau 7 years ago
committed by GitHub
parent
commit
ee81a48e5a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      package.json
  2. 46
      src/api/Ethereum.js
  3. 6
      src/api/Fees.js
  4. 22
      src/api/network.js
  5. 3
      src/config/constants.js
  6. 5
      src/helpers/promise.js
  7. 3
      src/helpers/withLibcore.js
  8. 6
      yarn.lock

2
package.json

@ -41,7 +41,7 @@
"@ledgerhq/hw-app-xrp": "^4.13.0",
"@ledgerhq/hw-transport": "^4.13.0",
"@ledgerhq/hw-transport-node-hid": "^4.13.0",
"@ledgerhq/ledger-core": "1.4.5",
"@ledgerhq/ledger-core": "1.6.0",
"@ledgerhq/live-common": "2.29.0",
"async": "^2.6.1",
"axios": "^0.18.0",

46
src/api/Ethereum.js

@ -1,8 +1,7 @@
// @flow
import axios from 'axios'
import { retry } from 'helpers/promise'
import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types'
import { blockchainBaseURL, userFriendlyError } from './Ledger'
import network from './network'
import { blockchainBaseURL } from './Ledger'
export type Block = { height: number } // TODO more fields actually
export type Tx = {
@ -47,37 +46,40 @@ export const apiForCurrency = (currency: CryptoCurrency): API => {
}
return {
async getTransactions(address, blockHash) {
const { data } = await userFriendlyError(
retry(
() =>
axios.get(`${baseURL}/addresses/${address}/transactions`, {
params: { blockHash, noToken: 1 },
}),
{ maxRetry: 3 },
),
)
const { data } = await network({
method: 'GET',
url: `${baseURL}/addresses/${address}/transactions`,
params: { blockHash, noToken: 1 },
})
return data
},
async getCurrentBlock() {
const { data } = await userFriendlyError(
retry(() => axios.get(`${baseURL}/blocks/current`), { maxRetry: 3 }),
)
const { data } = await network({
method: 'GET',
url: `${baseURL}/blocks/current`,
})
return data
},
async getAccountNonce(address) {
const { data } = await userFriendlyError(
retry(() => axios.get(`${baseURL}/addresses/${address}/nonce`), { maxRetry: 3 }),
)
const { data } = await network({
method: 'GET',
url: `${baseURL}/addresses/${address}/nonce`,
})
return data[0].nonce
},
async broadcastTransaction(tx) {
const { data } = await userFriendlyError(axios.post(`${baseURL}/transactions/send`, { tx }))
const { data } = await network({
method: 'POST',
url: `${baseURL}/transactions/send`,
data: { tx },
})
return data.result
},
async getAccountBalance(address) {
const { data } = await userFriendlyError(
retry(() => axios.get(`${baseURL}/addresses/${address}/balance`), { maxRetry: 3 }),
)
const { data } = await network({
method: 'GET',
url: `${baseURL}/addresses/${address}/balance`,
})
return data[0].balance
},
}

6
src/api/Fees.js

@ -1,8 +1,8 @@
// @flow
import invariant from 'invariant'
import axios from 'axios'
import type { Currency } from '@ledgerhq/live-common/lib/types'
import { blockchainBaseURL, userFriendlyError } from './Ledger'
import { blockchainBaseURL } from './Ledger'
import network from './network'
export type Fees = {
[_: string]: number,
@ -11,7 +11,7 @@ export type Fees = {
export const getEstimatedFees = async (currency: Currency): Promise<Fees> => {
const baseURL = blockchainBaseURL(currency)
invariant(baseURL, `Fees for ${currency.id} are not supported`)
const { data, status } = await userFriendlyError(axios.get(`${baseURL}/fees`))
const { data, status } = await network({ method: 'GET', url: `${baseURL}/fees` })
if (data) {
return data
}

22
src/api/network.js

@ -0,0 +1,22 @@
// @flow
import axios from 'axios'
import { GET_CALLS_RETRY, GET_CALLS_TIMEOUT } from 'config/constants'
import { userFriendlyError } from 'api/Ledger'
import { retry } from 'helpers/promise'
const doRequest = axios // TODO later introduce a way to run it in renderer based on a env, we will diverge this implementation
export default (arg: Object) => {
let promise
if (arg.method === 'GET') {
if (!('timeout' in arg)) {
arg.timeout = GET_CALLS_TIMEOUT
}
promise = retry(() => doRequest(arg), {
maxRetry: GET_CALLS_RETRY,
})
} else {
promise = doRequest(arg)
}
return userFriendlyError(promise)
}

3
src/config/constants.js

@ -6,6 +6,9 @@ const intFromEnv = (key: string, def: number) => {
return def
}
export const GET_CALLS_TIMEOUT = intFromEnv('GET_CALLS_TIMEOUT', 30 * 1000)
export const GET_CALLS_RETRY = intFromEnv('GET_CALLS_RETRY', 2)
export const SYNC_MAX_CONCURRENT = intFromEnv('LEDGER_SYNC_MAX_CONCURRENT', 2)
export const SYNC_BOOT_DELAY = 2 * 1000
export const SYNC_ALL_INTERVAL = 60 * 1000

5
src/helpers/promise.js

@ -1,7 +1,8 @@
// @flow
import logger from 'logger'
// small utilities for Promises
import logger from 'logger'
export const delay = (ms: number): Promise<void> => new Promise(f => setTimeout(f, ms))
const defaults = {
@ -21,7 +22,7 @@ export function retry<A>(f: () => Promise<A>, options?: $Shape<typeof defaults>)
}
// In case of failure, wait the interval, retry the action
return result.catch(e => {
logger.warn('Promise#retry', e)
logger.warn('retry failed', e.message)
return delay(interval).then(() => rec(remainingTry - 1, interval * intervalMultiplicator))
})
}

3
src/helpers/withLibcore.js

@ -1,9 +1,12 @@
// @flow
import invariant from 'invariant'
import network from 'api/network'
const core = require('@ledgerhq/ledger-core')
core.setHttpQueryImplementation(network)
let walletPoolInstance: ?Object = null
// TODO: `core` and `NJSWalletPool` should be typed

6
yarn.lock

@ -1502,9 +1502,9 @@
dependencies:
events "^2.0.0"
"@ledgerhq/ledger-core@1.4.5":
version "1.4.5"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-1.4.5.tgz#d3cf00ac07307d419b09e4cc1de8a8764ef16338"
"@ledgerhq/ledger-core@1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-1.6.0.tgz#885184cfc14598487894de2b9893c4a08798b074"
dependencies:
"@ledgerhq/hw-app-btc" "^4.7.3"
"@ledgerhq/hw-transport-node-hid" "^4.7.6"

Loading…
Cancel
Save