Skip to content

Commit

Permalink
feat(Swap): deposit failure endpoint added for swap
Browse files Browse the repository at this point in the history
  • Loading branch information
tony-blockchain committed Feb 13, 2019
1 parent 0ceda8c commit a585456
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 68 deletions.
Expand Up @@ -83,6 +83,7 @@ export default ({ api, coreSagas, networks }) => {
calculateEffectiveBalanceMemo,
getDefaultAccount,
createPayment,
updateLatestEthTrade,
validateXlm,
validateXlmCreateAccount,
validateXlmAccountExists
Expand Down Expand Up @@ -633,52 +634,50 @@ export default ({ api, coreSagas, networks }) => {
if (!txError) yield put(A.setStep(EXCHANGE_STEPS.CONFIRM))
}

const confirm = function*() {
let password
let scrambleKey
let connection
// Ask for second password or lockbox transport
const getDepositCredentials = function*(source) {
if (source.type !== ADDRESS_TYPES.LOCKBOX) {
const password = yield call(promptForSecondPassword)
return { password }
}
const deviceR = yield select(
selectors.core.kvStore.lockbox.getDeviceFromCoinAddrs,
prop('coin', source),
[prop('address', source)]
)
const device = deviceR.getOrFail(MISSING_DEVICE_ERROR)
const coin = prop('coin', source)
const deviceType = prop('device_type', device)
yield call(promptForLockbox, coin, deviceType)
const scrambleKey = Lockbox.utils.getScrambleKey(coin, deviceType)
const connection = yield select(
selectors.components.lockbox.getCurrentConnection
)
return { scrambleKey, connection }
}

const createTrade = function*(source, target, pair) {
const quote = (yield select(
selectors.modules.rates.getPairQuote(pair)
)).getOrFail(NO_ADVICE_ERROR)
const refundAddress = yield call(selectReceiveAddress, source, networks)
const destinationAddress = yield call(
selectReceiveAddress,
target,
networks
)
// Execute trade
return yield call(
api.executeTrade,
quote,
refundAddress,
destinationAddress
)
}

const depositFunds = function*(trade, source, depositCredentials) {
let txId = null
try {
// Get form data
yield put(actions.form.clearSubmitErrors(CONFIRM_FORM))
yield put(actions.form.startSubmit(CONFIRM_FORM))
const form = yield select(formValueSelector)
const source = prop('source', form)
const target = prop('target', form)
const pair = getCurrentPair(form)
const quote = (yield select(
selectors.modules.rates.getPairQuote(pair)
)).getOrFail(NO_ADVICE_ERROR)
const refundAddress = yield call(selectReceiveAddress, source, networks)
const destinationAddress = yield call(
selectReceiveAddress,
target,
networks
)
// Ask for second password or lockbox transport
if (source.type !== ADDRESS_TYPES.LOCKBOX) {
password = yield call(promptForSecondPassword)
} else {
const deviceR = yield select(
selectors.core.kvStore.lockbox.getDeviceFromCoinAddrs,
prop('coin', source),
[prop('address', source)]
)
const device = deviceR.getOrFail(MISSING_DEVICE_ERROR)
const coin = prop('coin', source)
const deviceType = prop('device_type', device)
yield call(promptForLockbox, coin, deviceType)
scrambleKey = Lockbox.utils.getScrambleKey(coin, deviceType)
connection = yield select(
selectors.components.lockbox.getCurrentConnection
)
}
// Execute trade
const trade = yield call(
api.executeTrade,
quote,
refundAddress,
destinationAddress
)
const {
depositAddress,
depositMemo,
Expand All @@ -695,42 +694,62 @@ export default ({ api, coreSagas, networks }) => {
)
// Sign transaction
if (source.type !== ADDRESS_TYPES.LOCKBOX) {
payment = yield (yield payment.sign(password)).publish()
const { password } = depositCredentials
payment = yield payment.sign(password)
txId = payment.value().txId
payment = yield payment.publish()
} else {
payment = yield (yield payment.sign(
const { connection, scrambleKey } = depositCredentials
payment = yield payment.sign(
null,
prop('transport', connection),
scrambleKey
)).publish()
)
txId = payment.value().txId
payment = yield payment.publish()
yield put(actions.components.lockbox.setConnectionSuccess())
yield delay(4000)
yield put(actions.modals.closeAllModals())
}
// Update metadat
if (prop('coin', source) === 'ETH') {
const { txId } = payment.value()
yield put(
actions.core.kvStore.ethereum.setLatestTxTimestampEthereum(Date.now())
)
yield take(
actionTypes.core.kvStore.ethereum.FETCH_METADATA_ETHEREUM_SUCCESS
)
yield put(actions.core.kvStore.ethereum.setLatestTxEthereum(txId))
}

if (prop('coin', source) === 'ETH')
yield spawn(updateLatestEthTrade, txId)
} catch (err) {
yield call(api.failTrade, trade.id, err, txId)
throw err
}
}

const showConfirmationError = function*(err) {
yield put(actions.modals.closeAllModals())
yield put(actions.form.stopSubmit(CONFIRM_FORM, { _error: err }))
yield put(
actions.logs.logErrorMessage(logLocation, 'confirm', JSON.stringify(err))
)
}

const confirm = function*() {
// Get form data
yield put(actions.form.clearSubmitErrors(CONFIRM_FORM))
yield put(actions.form.startSubmit(CONFIRM_FORM))
const form = yield select(formValueSelector)
const source = prop('source', form)
const target = prop('target', form)
const pair = getCurrentPair(form)
let trade, depositCredentials
try {
depositCredentials = yield call(getDepositCredentials, source)
trade = yield call(createTrade, source, target, pair)
yield call(depositFunds, trade, source, depositCredentials)
yield put(actions.form.stopSubmit(CONFIRM_FORM))
yield put(actions.router.push('/swap/history'))
yield put(A.setStep(EXCHANGE_STEPS.EXCHANGE_FORM))
yield put(
actions.modals.showModal(RESULTS_MODAL, formatExchangeTrade(trade))
)
yield put(actions.components.refresh.refreshClicked())
} catch (e) {
yield put(actions.modals.closeAllModals())
yield put(actions.form.stopSubmit(CONFIRM_FORM, { _error: e }))
yield put(
actions.logs.logErrorMessage(logLocation, 'confirm', JSON.stringify(e))
)
} catch (err) {
return yield call(showConfirmationError, err)
}
}

Expand Down
@@ -1,8 +1,8 @@
import { call, cancel, fork, join, put, select } from 'redux-saga/effects'
import { call, cancel, fork, join, put, select, take } from 'redux-saga/effects'
import { always, contains, equals, head, prop, toLower } from 'ramda'
import BigNumber from 'bignumber.js'

import { selectors, actions } from 'data'
import { selectors, actions, actionTypes } from 'data'
import * as S from './selectors'
import { convertStandardToBase } from './services'
import { CREATE_ACCOUNT_ERROR, NO_ACCOUNT_ERROR, RESERVE_ERROR } from './model'
Expand Down Expand Up @@ -301,12 +301,24 @@ export default ({ coreSagas, networks }) => {
throw CREATE_ACCOUNT_ERROR
}

const updateLatestEthTrade = function*(txId) {
// Update metadata
yield put(
actions.core.kvStore.ethereum.setLatestTxTimestampEthereum(Date.now())
)
yield take(
actionTypes.core.kvStore.ethereum.FETCH_METADATA_ETHEREUM_SUCCESS
)
yield put(actions.core.kvStore.ethereum.setLatestTxEthereum(txId))
}

return {
calculatePaymentMemo,
calculateProvisionalPayment,
calculateEffectiveBalanceMemo,
createPayment,
getDefaultAccount,
updateLatestEthTrade,
validateXlm,
validateXlmAccountExists,
validateXlmCreateAccount
Expand Down
19 changes: 18 additions & 1 deletion packages/blockchain-wallet-v4/src/network/api/trades/index.js
@@ -1,4 +1,6 @@
export default ({ nabuUrl, post, get }) => {
import isObject from 'isobject'

export default ({ nabuUrl, post, put, get }) => {
const executeTrade = (quote, refundAddress, destinationAddress) =>
post({
url: nabuUrl,
Expand Down Expand Up @@ -47,8 +49,23 @@ export default ({ nabuUrl, post, get }) => {
ignoreQueryParams: true
})

const failTrade = (tradeId, err, txHash = null) => {
let failureReason = null
if (typeof err === 'string') failureReason = { message: err }
if (isObject(err)) failureReason = err
put({
url: nabuUrl,
endPoint: `trades/${tradeId}/failure-reason`,
data: {
txHash,
failureReason
}
})
}

return {
executeTrade,
failTrade,
fetchLimits,
fetchTrade,
fetchTrades,
Expand Down

0 comments on commit a585456

Please sign in to comment.