From 7d736f00c719bed4f20104ba34fefddb0c3eca4f Mon Sep 17 00:00:00 2001 From: Timo Uhlmann Date: Sat, 30 Jun 2018 10:21:50 -0700 Subject: [PATCH 1/2] Payment state: CREATED --- src/actions/__tests__/payments.js | 37 ++++++++++++++++--------------- src/actions/payments.js | 36 +++++++++++++++++++++--------- src/reducers/payments/payment.js | 1 + src/sagas/__tests__/payments.js | 1 + 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/actions/__tests__/payments.js b/src/actions/__tests__/payments.js index 2b447d0..15e2139 100644 --- a/src/actions/__tests__/payments.js +++ b/src/actions/__tests__/payments.js @@ -22,6 +22,25 @@ describe('Payment Actions', () => { }) }) + describe('createPayment', () => { + it('creates an action', () => { + expect(actions.createPayment( + 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', { + fiatCurrency: 'EUR' + }, createdAt) + ).toEqual({ + type: types.CREATE_PAYMENT, + payload: { + id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', + state: 'CREATED', + fiatCurrency: 'EUR', + createdAt: '2017-06-17T17:30:00.000Z', + updatedAt: '2017-06-17T17:30:00.000Z' + } + }) + }) + }) + describe('setAmount', () => { it('creates an action', () => { expect(actions.setAmount('29.95', 'Receipt')).toEqual({ @@ -55,24 +74,6 @@ describe('Payment Actions', () => { }) }) - describe('createPayment', () => { - it('creates an action', () => { - expect(actions.createPayment( - 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', { - fiatCurrency: 'EUR' - }, createdAt) - ).toEqual({ - type: types.CREATE_PAYMENT, - payload: { - id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - fiatCurrency: 'EUR', - createdAt: '2017-06-17T17:30:00.000Z', - updatedAt: '2017-06-17T17:30:00.000Z' - } - }) - }) - }) - describe('updatePayment', () => { it('creates an action', () => { expect( diff --git a/src/actions/payments.js b/src/actions/payments.js index 736baf0..2adf83a 100644 --- a/src/actions/payments.js +++ b/src/actions/payments.js @@ -1,5 +1,12 @@ import * as types from './constants/payments' +const now = () => new Date().toISOString() + +/** + * Setup a new payment + * @param {Function} resolve Success callback + * @param {Function} reject Error callback + */ export const requestPayment = (resolve, reject) => ({ type: types.REQUEST_PAYMENT, payload: { @@ -8,6 +15,23 @@ export const requestPayment = (resolve, reject) => ({ } }) +/** + * + * @param {String} id Payment identifier + * @param {Object} payment Payment properties + * @param {Date} timestamp The payment's creation date + */ +export const createPayment = (id, payment, timestamp = now) => ({ + type: types.CREATE_PAYMENT, + payload: Object.assign({}, payment, { id }, + { + state: 'CREATED', + createdAt: timestamp(), + updatedAt: timestamp() + } + ) +}) + export const setAmount = (requestedAmount, receipt = null) => ({ type: types.SET_AMOUNT, payload: { @@ -30,17 +54,7 @@ export const cancelPayment = () => ({ type: types.CANCEL_PAYMENT }) -export const createPayment = (id, payment, timestamp = () => new Date().toISOString()) => ({ - type: types.CREATE_PAYMENT, - payload: Object.assign({}, payment, { id }, - { - createdAt: timestamp(), - updatedAt: timestamp() - } - ) -}) - -export const updatePayment = (id, payment, timestamp = () => new Date().toISOString()) => ({ +export const updatePayment = (id, payment, timestamp = () => now) => ({ type: types.UPDATE_PAYMENT, payload: Object.assign({}, payment, { id }, { diff --git a/src/reducers/payments/payment.js b/src/reducers/payments/payment.js index dddf084..c7878f8 100644 --- a/src/reducers/payments/payment.js +++ b/src/reducers/payments/payment.js @@ -5,6 +5,7 @@ import { const PAYMENT_KEYS = [ 'id', + 'state', 'createdAt', 'fiatCurrency', 'exchange', diff --git a/src/sagas/__tests__/payments.js b/src/sagas/__tests__/payments.js index cb1b1b4..101c89c 100644 --- a/src/sagas/__tests__/payments.js +++ b/src/sagas/__tests__/payments.js @@ -171,6 +171,7 @@ describe('processPayment', () => { payload: { id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', fiatCurrency: 'EUR', + state: 'CREATED', createdAt: creationTime, updatedAt: creationTime } From 8c2b0ddfd4207cc8ae5b67f3d965b21a4bd38da5 Mon Sep 17 00:00:00 2001 From: Timo Uhlmann Date: Sat, 6 Oct 2018 15:59:31 +0200 Subject: [PATCH 2/2] Refactored payment actions & specs. Payment states. --- src/actions/__tests__/payments.js | 236 ++++++++++++++++-------------- src/actions/payments.js | 101 ++++++++++++- src/sagas/__tests__/payments.js | 13 +- src/sagas/payments.js | 21 ++- src/views/payments/send.js | 1 + 5 files changed, 245 insertions(+), 127 deletions(-) diff --git a/src/actions/__tests__/payments.js b/src/actions/__tests__/payments.js index 15e2139..937d1c1 100644 --- a/src/actions/__tests__/payments.js +++ b/src/actions/__tests__/payments.js @@ -9,127 +9,144 @@ const creationTime = '2017-06-17T17:30:00.000Z' const createdAt = () => creationTime describe('Payment Actions', () => { - describe('requestPayment', () => { - it('creates an action', () => { - expect(actions.requestPayment(noop, noop, 3000)) - .toEqual({ - type: types.REQUEST_PAYMENT, + describe('User Input', () => { + describe('requestPayment', () => { + it('allows the seller to trigger a new payment workflow', () => { + expect(actions.requestPayment(noop, noop, 3000)) + .toEqual({ + type: types.REQUEST_PAYMENT, + payload: { + resolve: noop, + reject: noop + } + }) + }) + }) + + describe('setAmount', () => { + it('allows the seller to set amount and receipt', () => { + expect(actions.setAmount('29.95', 'Receipt')).toEqual({ + type: types.SET_AMOUNT, payload: { - resolve: noop, - reject: noop + requestedAmount: '29.95', + receipt: 'Receipt' } }) - }) - }) + }) - describe('createPayment', () => { - it('creates an action', () => { - expect(actions.createPayment( - 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', { - fiatCurrency: 'EUR' - }, createdAt) - ).toEqual({ - type: types.CREATE_PAYMENT, - payload: { - id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - state: 'CREATED', - fiatCurrency: 'EUR', - createdAt: '2017-06-17T17:30:00.000Z', - updatedAt: '2017-06-17T17:30:00.000Z' - } + it('accepts an empty receipt', () => { + expect(actions.setAmount('29.95')).toEqual({ + type: types.SET_AMOUNT, + payload: { + requestedAmount: '29.95', + receipt: null + } + }) }) }) - }) - describe('setAmount', () => { - it('creates an action', () => { - expect(actions.setAmount('29.95', 'Receipt')).toEqual({ - type: types.SET_AMOUNT, - payload: { - requestedAmount: '29.95', - receipt: 'Receipt' - } + describe('setTip', () => { + it('allows buyer to set a tip', () => { + expect(actions.setTip('0.015814568844')).toEqual({ + type: types.SET_TIP, + payload: { + tip: '0.015814568844' + } + }) }) }) - it('accepts empty receipt', () => { - expect(actions.setAmount('29.95')).toEqual({ - type: types.SET_AMOUNT, - payload: { - requestedAmount: '29.95', - receipt: null - } + describe('cancelPayment', () => { + it('cancels a running payment request', () => { + expect(actions.cancelPayment()).toEqual({ + type: types.CANCEL_PAYMENT + }) }) }) }) - describe('setTip', () => { - it('creates an action', () => { - expect(actions.setTip('3.00')).toEqual({ - type: types.SET_TIP, - payload: { - tip: 3 - } + describe('Saga Actions', () => { + describe('createPayment', () => { + it('creates a new payment model', () => { + expect(actions.createPayment( + 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', { + fiatCurrency: 'EUR' + }, createdAt) + ).toEqual({ + type: types.CREATE_PAYMENT, + payload: { + id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', + state: 'CREATED', + fiatCurrency: 'EUR', + createdAt: '2017-06-17T17:30:00.000Z', + updatedAt: '2017-06-17T17:30:00.000Z' + } + }) }) }) - }) - describe('updatePayment', () => { - it('creates an action', () => { - expect( - actions.updatePayment('a2f8d724-5c7a-43e9-bbac-b0295b059e82', { - address: '9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6', - height: '1057120', - paymentId: '6b1887e13bbd81db', - rate: '315.84800377' - }, createdAt) - ).toEqual({ - type: types.UPDATE_PAYMENT, - payload: { - id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - address: '9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6', - height: '1057120', - paymentId: '6b1887e13bbd81db', - rate: '315.84800377' - // updatedAt: creationTime - } + describe('networkInput', () => { + it('sets required network info', () => { + expect(actions.networkInput( + 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', + '9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6', + 'A3Brqw9sVmwLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMVqg62UVmnbzRji2SB9', + '1057120', + '6b1887e13bbd81db', + '315.84800377' + )).toEqual({ + type: types.UPDATE_PAYMENT, + payload: { + id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', + address: '9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6', + integratedAddress: 'A3Brqw9sVmwLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMVqg62UVmnbzRji2SB9', + height: '1057120', + paymentId: '6b1887e13bbd81db', + rate: '315.84800377', + state: 'NETWORK_INPUT' + // updatedAt: creationTime + } + }) }) + }) - expect( - actions.updatePayment('a2f8d724-5c7a-43e9-bbac-b0295b059e82', { - requestedAmount: '49.95', - convertedAmount: '0.158145688444', - receipt: 'Receipt #12' - }, createdAt) - ).toEqual({ - type: types.UPDATE_PAYMENT, - payload: { - id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - requestedAmount: '49.95', - convertedAmount: '0.158145688444', - receipt: 'Receipt #12' - // updatedAt: creationTime - } + describe('sellerInput', () => { + it('sets required seller info', () => { + expect( + actions.sellerInput('a2f8d724-5c7a-43e9-bbac-b0295b059e82', + '49.95', + '0.158145688444' + ) + ).toEqual({ + type: types.UPDATE_PAYMENT, + payload: { + id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', + requestedAmount: '49.95', + convertedAmount: '0.158145688444', + state: 'SELLER_INPUT' + // updatedAt: creationTime + } + }) }) + }) - expect( - actions.updatePayment('a2f8d724-5c7a-43e9-bbac-b0295b059e82', { - uri: 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.158145688444&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312' - }, createdAt) - ).toEqual({ - type: types.UPDATE_PAYMENT, - payload: { - id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - uri: 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.158145688444&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312' - // updatedAt: creationTime - } + describe('setUri', () => { + it('updates the uri for the QR code', () => { + expect( + actions.setUri('a2f8d724-5c7a-43e9-bbac-b0295b059e82', 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.158145688444&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312') + ).toEqual({ + type: types.UPDATE_PAYMENT, + payload: { + id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', + uri: 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.158145688444&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312', + tip: null + // updatedAt: creationTime + } + }) }) expect( - actions.updatePayment('a2f8d724-5c7a-43e9-bbac-b0295b059e82', { - uri: 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.173960257288&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312', - tip: '0.015814568844' - }, createdAt) + actions.setUri('a2f8d724-5c7a-43e9-bbac-b0295b059e82', 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.173960257288&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312', '0.015814568844') ).toEqual({ type: types.UPDATE_PAYMENT, payload: { @@ -139,18 +156,21 @@ describe('Payment Actions', () => { // updatedAt: creationTime } }) + }) - expect( - actions.updatePayment('a2f8d724-5c7a-43e9-bbac-b0295b059e82', { - receivedAmount: '0.158145688444' - }, createdAt) - ).toEqual({ - type: types.UPDATE_PAYMENT, - payload: { - id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - receivedAmount: '0.158145688444' - // updatedAt: creationTime - } + describe('receivePayment', () => { + it('finalizes the payment', () => { + expect( + actions.receivePayment('a2f8d724-5c7a-43e9-bbac-b0295b059e82', '0.158145688444') + ).toEqual({ + type: types.UPDATE_PAYMENT, + payload: { + id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', + receivedAmount: '0.158145688444', + state: 'PAYMENT_RECEIVED' + // updatedAt: creationTime + } + }) }) }) }) diff --git a/src/actions/payments.js b/src/actions/payments.js index 2adf83a..f93fb15 100644 --- a/src/actions/payments.js +++ b/src/actions/payments.js @@ -4,6 +4,10 @@ const now = () => new Date().toISOString() /** * Setup a new payment + * + * Called from dashboard, this triggers a new `processPayment` saga. + * + * @see processPayment * @param {Function} resolve Success callback * @param {Function} reject Error callback */ @@ -16,6 +20,9 @@ export const requestPayment = (resolve, reject) => ({ }) /** + * Create a new payment model. + * + * Called by saga after creating new uuid. * * @param {String} id Payment identifier * @param {Object} payment Payment properties @@ -32,6 +39,18 @@ export const createPayment = (id, payment, timestamp = now) => ({ ) }) +/** + * Set requested amount and an optional receipt reference. + * + * The amount is as requested by the seller. If a fiat currency is + * configured in the settings, this value will be multiplied by + * `exchangeRate` + * + * Called from create payment screen. + * + * @param {Big} requestedAmount Amount due, as requested by seller + * @param {String} receipt An optional reference to a payment receipt + */ export const setAmount = (requestedAmount, receipt = null) => ({ type: types.SET_AMOUNT, payload: { @@ -39,22 +58,98 @@ export const setAmount = (requestedAmount, receipt = null) => ({ receipt } }) - +/** + * Set the tip amount. This is calculated by a percentage, + * which can be configured in the settings. + * + * Called from send payment screen. + * + * @param {Big} tip Tip amount in XMR, as set by the buyer + */ export const setTip = (tip) => { tip = Math.max(0, Number.parseFloat(tip) || 0) return { type: types.SET_TIP, payload: { - tip + tip: `${tip}` } } } +/** + * Set required network information in the model. + * + * Called by saga after polling Monero wallet and exchange rate. + * + * @param {String} id The payment id + * @param {String} address Monero address + * @param {String} integratedAddress Monero integrated address + * @param {String} height Monero block height at beginning of payment process + * @param {String} paymentId Monero payment id + * @param {Big} rate fiat/XMR exchange rate + */ +export const networkInput = (id, address, integratedAddress, height, paymentId, rate) => + updatePayment(id, { + address, + integratedAddress, + height, + paymentId, + rate, + state: 'NETWORK_INPUT' + }) + +/** + * Set requested and converted amount in payment model. + * + * Called by saga after conversion is done. + * + * @param {String} id The payment id + * @param {Big} requestedAmount Amount due, as requested by the seller + * @param {Big} convertedAmount Amount due, converted + */ +export const sellerInput = (id, requestedAmount, convertedAmount) => + // TODO requestedAmount, receipt? + updatePayment(id, { + requestedAmount, + convertedAmount, + state: 'SELLER_INPUT' + }) + +/** + * Sets the URI to be encoded in a QR Code. + * + * Called by saga after buyer enters tip. + * + * @param {String} id The payment id + * @param {String} uri The `monero:` payment uri for displaying a QR code + */ +export const setUri = (id, uri, tip = null) => + updatePayment(id, { uri, tip }) + +/** + * Sets the amount received. + * + * Called by saga after polling wallet for incoming payments. + * + * @param {String} id The payment id + * @param {Big} receivedAmount The amount received + */ +export const receivePayment = (id, receivedAmount) => + updatePayment(id, { + receivedAmount, + state: 'PAYMENT_RECEIVED' + }) + +/** + * Cancel a pending payment request. + * + * Called from send payment screen. + */ export const cancelPayment = () => ({ type: types.CANCEL_PAYMENT }) -export const updatePayment = (id, payment, timestamp = () => now) => ({ +const updatePayment = (id, payment, timestamp = now) => ({ type: types.UPDATE_PAYMENT, payload: Object.assign({}, payment, { id }, { diff --git a/src/sagas/__tests__/payments.js b/src/sagas/__tests__/payments.js index 101c89c..6df503d 100644 --- a/src/sagas/__tests__/payments.js +++ b/src/sagas/__tests__/payments.js @@ -184,7 +184,8 @@ describe('processPayment', () => { integratedAddress: 'A3Brqw9sVmwLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMVqg62UVmnbzRji2SB9', paymentId: '6b1887e13bbd81db', height: 1057120, - rate: 315.84800377 + rate: 315.84800377, + state: 'NETWORK_INPUT' } }) .put({ @@ -193,14 +194,15 @@ describe('processPayment', () => { id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', requestedAmount: '49.95', convertedAmount: '0.158145688444', - receipt: 'Receipt #12' + state: 'SELLER_INPUT' } }) .put({ type: types.UPDATE_PAYMENT, payload: { id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - uri: 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.158145688444&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312' + uri: 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.158145688444&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312', + tip: null } }) .put({ @@ -208,14 +210,15 @@ describe('processPayment', () => { payload: { id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', uri: 'monero:9sVBq8LNtWRLyWS8EWeUw1VqpqfwnDHTkG7Pb4NJ3RmZWeeMZhGMe2ZXz4bSk7BbtEYF5981nLxkDYQ6B46tX5DMLRHQFh6?tx_payment_id=6b1887e13bbd81db&tx_amount=0.173960257288&recipient_name=Barolo%20Beach%20Cafe&tx_description=Receipt%20%2312', - tip: 0.015814568844 + tip: '0.015814568844' } }) .put({ type: types.UPDATE_PAYMENT, payload: { id: 'a2f8d724-5c7a-43e9-bbac-b0295b059e82', - receivedAmount: '0.158145688444' + receivedAmount: '0.158145688444', + state: 'PAYMENT_RECEIVED' } }) .dispatch(setAmount('49.95', 'Receipt #12')) diff --git a/src/sagas/payments.js b/src/sagas/payments.js index 22d6745..996fc81 100644 --- a/src/sagas/payments.js +++ b/src/sagas/payments.js @@ -20,7 +20,10 @@ import { import { createPayment, - updatePayment + networkInput, + sellerInput, + setUri, + receivePayment } from '../actions/payments' import * as types from '../actions/constants/payments' @@ -31,7 +34,7 @@ function * listenForTip (id, paymentRequest, name, receipt) { const { tip } = setTip.payload const convertedTip = parseInt(new Big(tip).times(1e12).round(), 10) const { uri } = yield call([paymentRequest, 'makeUri'], convertedTip, name, receipt) - yield put(updatePayment(id, { tip, uri })) + yield put(setUri(id, uri, tip)) } } @@ -80,32 +83,28 @@ export function * processPayment (action) { paymentId } = paymentRequest - yield put(updatePayment(id, { address, integratedAddress, height, paymentId, rate })) + yield put(networkInput(id, address, integratedAddress, height, paymentId, rate)) const setAmount = yield take(types.SET_AMOUNT) const { requestedAmount, receipt } = setAmount.payload const convertedAmount = new Big(requestedAmount).times(1e12).div(rate).round() - yield put(updatePayment(id, { - requestedAmount, - convertedAmount: convertedAmount.div(1e12).toFixed(12), - receipt - })) + yield put(sellerInput(id, requestedAmount, convertedAmount.div(1e12).toFixed(12))) paymentRequest.setAmount(parseInt(convertedAmount, 10)) const { uri } = yield call([paymentRequest, 'makeUri'], 0, merchantName, receipt) - yield put(updatePayment(id, { uri })) + yield put(setUri(id, uri)) const tipSaga = yield fork(listenForTip, id, paymentRequest, merchantName, receipt) try { const onFulfilled = yield call(awaitPayment, paymentRequest, pollingInterval) - yield put(updatePayment(id, { receivedAmount: new Big(onFulfilled.amountReceived).div(1e12).toFixed(12) })) + yield put(receivePayment(id, new Big(onFulfilled.amountReceived).div(1e12).toFixed(12))) } catch (e) { - console.warn('Error', e) + console.warn(e) paymentRequest.cancel() } finally { tipSaga.cancel() diff --git a/src/views/payments/send.js b/src/views/payments/send.js index aacbd44..75baa70 100644 --- a/src/views/payments/send.js +++ b/src/views/payments/send.js @@ -87,6 +87,7 @@ export default class SendPayment extends Component { onClick={(e) => { const isResetting = tipIndex === key e.preventDefault() + // TODO Use Big setTip(isResetting ? 0 : tipRate * convertedAmount) this.setState({ tipIndex: isResetting ? null : key