diff --git a/app/browser/api/ledger.js b/app/browser/api/ledger.js index 5e0009dac1b..3f85a138783 100644 --- a/app/browser/api/ledger.js +++ b/app/browser/api/ledger.js @@ -1881,15 +1881,33 @@ const onWalletProperties = (state, body) => { state = ledgerState.setInfoProp(state, 'currentRate', rate) } + // Grants + let probi = parseFloat(body.get('probi')) + let userFunded = null + if (!isNaN(probi)) { + userFunded = probi + let grants = body.get('grants') || Immutable.List() + if (!grants.isEmpty()) { + let grantTotal = 0 + grants = grants.map(grant => { + grantTotal += parseFloat(grant.get('probi')) + return { + amount: new BigNumber(grant.get('probi').toString()).dividedBy('1e18').toNumber(), + expirationDate: grant.get('expiryTime') + } + }) + state = ledgerState.setInfoProp(state, 'grants', grants) + userFunded = probi - grantTotal + } + + state = ledgerState.setInfoProp(state, 'userFunded', new BigNumber(userFunded.toString()).dividedBy('1e18').toNumber()) + } + // Probi - const probi = parseFloat(body.get('probi')) if (probi >= 0) { state = ledgerState.setInfoProp(state, 'probi', probi) - - const amount = info.get('balance') - - if (amount != null && rate) { - const bigProbi = new BigNumber(probi.toString()).dividedBy('1e18') + if (userFunded != null && rate) { + const bigProbi = new BigNumber(userFunded.toString()).dividedBy('1e18') const bigRate = new BigNumber(rate.toString()) const converted = bigProbi.times(bigRate).toNumber() diff --git a/app/common/lib/ledgerUtil.js b/app/common/lib/ledgerUtil.js index 5227e010de7..a7190f923ec 100644 --- a/app/common/lib/ledgerUtil.js +++ b/app/common/lib/ledgerUtil.js @@ -64,16 +64,16 @@ const batToCurrencyString = (bat, ledgerData) => { return `${converted} ${currency}` } -const formatCurrentBalance = (ledgerData) => { +const formatCurrentBalance = (ledgerData, amount, showAlt = true) => { let currency = 'USD' let balance = 0 let converted = 0 let hasRate = false if (ledgerData != null) { - balance = Number(ledgerData.get('balance') || 0) + balance = Number(amount || 0) converted = Number.parseFloat(ledgerData.get('converted')) || 0 - hasRate = ledgerData.has('currentRate') && ledgerData.hasIn(['rates', 'BTC']) + hasRate = showAlt ? ledgerData.has('currentRate') && ledgerData.hasIn(['rates', 'BTC']) : false } balance = balance.toFixed(2) diff --git a/app/extensions/brave/locales/en-US/preferences.properties b/app/extensions/brave/locales/en-US/preferences.properties index 27a62137df4..b9df0b685bf 100644 --- a/app/extensions/brave/locales/en-US/preferences.properties +++ b/app/extensions/brave/locales/en-US/preferences.properties @@ -138,6 +138,7 @@ engineGoKey=Engine Go Key (Type First) engineGoKey=Engine Go Key (type first) enpass=Enpass® (requires application) extensions=Extensions +expires=expires flash=Run Adobe Flash Player flashAllowAlways=Allow until {{time}} flashTroubleshooting=Flash not working? Try the troubleshooting tips on our @@ -383,6 +384,7 @@ tabsSettings=Tabs Settings termsOfService=Terms of Service timeSpent=Time Spent toolbarUserInterfaceScale=Toolbar and UI elements scale +total=total totalAmount=Total Amount update=Update updateToPreviewReleases=Update to preview releases * diff --git a/app/renderer/components/preferences/payment/enabledContent.js b/app/renderer/components/preferences/payment/enabledContent.js index bcf4c2f8997..22afad14e79 100644 --- a/app/renderer/components/preferences/payment/enabledContent.js +++ b/app/renderer/components/preferences/payment/enabledContent.js @@ -10,7 +10,6 @@ const Immutable = require('immutable') // Components const ImmutableComponent = require('../../immutableComponent') const BrowserButton = require('../../common/browserButton') -const {FormTextbox} = require('../../common/textbox') const {PanelDropdown} = require('../../common/dropdown') const LedgerTable = require('./ledgerTable') const Captcha = require('./captcha') @@ -143,19 +142,28 @@ class EnabledContent extends ImmutableComponent { fundsAmount () { const ledgerData = this.props.ledgerData - const val = formatCurrentBalance(ledgerData) || '' - const big = val.length > 23 + if (!ledgerData) { + return + } - return
- - -
+ const total = formatCurrentBalance(ledgerData, ledgerData.get('balance'), false) || '' + const userFunded = formatCurrentBalance(ledgerData, ledgerData.get('userFunded')) || '' + const grants = ledgerData.get('grants') || Immutable.List() + + return
+
{userFunded}
+ { + grants.map(grant => { + return
+ {formatCurrentBalance(ledgerData, grant.get('amount'), false)} + ( {new Date(grant.get('expirationDate') * 1000).toLocaleDateString()}) +
+ }) + } +
+ {total} () +
+
} lastReconcileMessage () { @@ -183,8 +191,12 @@ class EnabledContent extends ImmutableComponent { } return
-
-
+ { + prevReconcileDateValue + ? + : null + } +
} @@ -224,8 +236,7 @@ class EnabledContent extends ImmutableComponent { } return
-
-
+
} @@ -422,7 +433,7 @@ class EnabledContent extends ImmutableComponent { } -
+
{ ledgerData.get('error') && ledgerData.get('error').get('caller') === 'getWalletProperties' ?
@@ -434,8 +445,6 @@ class EnabledContent extends ImmutableComponent {
{this.lastReconcileMessage()} -
-
{ ledgerData.get('error') && ledgerData.get('error').get('caller') === 'getWalletProperties' ?
@@ -510,6 +519,10 @@ const gridStyles = StyleSheet.create({ row3col3: { gridRow: 3, gridColumn: 3 + }, + + mergeRow23Col2: { + gridRow: '2 / span 2' } }) @@ -541,10 +554,6 @@ const styles = StyleSheet.create({ alignItems: 'center' }, - width_input: { - width: '195px' - }, - balance__iconLink: { color: globalStyles.color.mediumGray, fontSize: globalStyles.payments.fontSize.regular, @@ -661,6 +670,23 @@ const styles = StyleSheet.create({ ':hover': { textDecoration: 'underline' } + }, + + fundsAmount__item: { + marginBottom: '4px', + width: '215px', + fontSize: '14.5px' + }, + + fundsAmount__total: { + marginTop: '10px', + paddingTop: '12px', + borderTop: '1px solid #999', + fontSize: '15px' + }, + + lastContribution: { + paddingRight: '4px' } }) diff --git a/app/renderer/components/preferences/paymentsTab.js b/app/renderer/components/preferences/paymentsTab.js index 799dcbd2d35..1ad5c832856 100644 --- a/app/renderer/components/preferences/paymentsTab.js +++ b/app/renderer/components/preferences/paymentsTab.js @@ -82,7 +82,7 @@ class PaymentsTab extends ImmutableComponent { const addresses = ledgerData.get('addresses') || Immutable.List() const walletQR = ledgerData.get('walletQR') || Immutable.List() const wizardData = ledgerData.get('wizardData') || Immutable.Map() - const funds = formatCurrentBalance(ledgerData) + const funds = formatCurrentBalance(ledgerData, ledgerData.get('balance')) const budget = ledgerState.getContributionAmount(null, ledgerData.get('contributionAmount'), this.props.settings) const minAmount = batToCurrencyString(budget, ledgerData) @@ -110,7 +110,7 @@ class PaymentsTab extends ImmutableComponent { get getOverlayFunds () { const ledgerData = this.props.ledgerData || Immutable.Map() - return formatCurrentBalance(ledgerData) + return formatCurrentBalance(ledgerData, ledgerData.get('balance')) } get deletedSitesFooter () { diff --git a/docs/state.md b/docs/state.md index 897568596b2..e843318f314 100644 --- a/docs/state.md +++ b/docs/state.md @@ -211,6 +211,10 @@ AppStore created, boolean, // wallet is created creating: boolean, // wallet is being created currentRate: number, + grants: [{ + amount: number, + expirationDate: number + }] hasBitcoinHandler: boolean, // brave browser has a `bitcoin:` URI handler monthlyAmounts: Array // list of all monthly amounts for the contribution passphrase: string, // the BAT wallet passphrase @@ -244,6 +248,7 @@ AppStore viewingId: string, // UUIDv4 for this contribution }], unconfirmed: string, // unconfirmed balance in BAT.toFixed(2) + userFunded: number, // amount funded by the user userHasFunded: boolean // permanently true once user funds wallet }, locations: { diff --git a/test/unit/app/browser/api/ledgerTest.js b/test/unit/app/browser/api/ledgerTest.js index 4bbbeaaecdc..8bc2315b2a1 100644 --- a/test/unit/app/browser/api/ledgerTest.js +++ b/test/unit/app/browser/api/ledgerTest.js @@ -1504,19 +1504,18 @@ describe('ledger api unit tests', function () { const expectedState = state .setIn(['ledger', 'info', 'probi'], probi) .setIn(['ledger', 'info', 'balance'], 25) + .setIn(['ledger', 'info', 'userFunded'], 25) .setIn(['ledger', 'info', 'userHasFunded'], true) assert.deepEqual(result.toJS(), expectedState.toJS()) }) it('amount is null', function () { const result = ledgerApi.onWalletProperties(state, Immutable.fromJS({ - probi: probi, rates: rates })) const expectedState = state .setIn(['ledger', 'info', 'rates'], Immutable.fromJS(rates)) .setIn(['ledger', 'info', 'currentRate'], rate) - .setIn(['ledger', 'info', 'probi'], probi) assert.deepEqual(result.toJS(), expectedState.toJS()) }) @@ -1531,13 +1530,14 @@ describe('ledger api unit tests', function () { .setIn(['ledger', 'info', 'currentRate'], rate) .setIn(['ledger', 'info', 'converted'], 3.5836474125) .setIn(['ledger', 'info', 'balance'], 25) + .setIn(['ledger', 'info', 'userFunded'], 25) .setIn(['ledger', 'info', 'probi'], probi) .setIn(['ledger', 'info', 'userHasFunded'], true) assert.deepEqual(result.toJS(), expectedState.toJS()) }) it('big probi', function () { - const bigProbi = '7.309622404968674704085e+21' + const bigProbi = 7.309622404968674704085e+21 const result = ledgerApi.onWalletProperties(state, Immutable.fromJS({ probi: bigProbi, balance: '7309.6224', @@ -1548,6 +1548,7 @@ describe('ledger api unit tests', function () { .setIn(['ledger', 'info', 'currentRate'], rate) .setIn(['ledger', 'info', 'converted'], 1047.8043767167208) .setIn(['ledger', 'info', 'balance'], 7309.6224) + .setIn(['ledger', 'info', 'userFunded'], 7309.622404968675) .setIn(['ledger', 'info', 'probi'], bigProbi) .setIn(['ledger', 'info', 'userHasFunded'], true) assert.deepEqual(result.toJS(), expectedState.toJS()) @@ -1642,6 +1643,55 @@ describe('ledger api unit tests', function () { contributionAmount = 10 }) }) + + describe('grants', function () { + const probi = 25000000000000000000 + + it('probi is missing', function () { + const expectedState = state + .setIn(['ledger', 'info', 'balance'], 25) + .setIn(['ledger', 'info', 'userHasFunded'], true) + const result = ledgerApi.onWalletProperties(state, Immutable.fromJS({ + balance: 25 + })) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + + it('is missing', function () { + const expectedState = state + .setIn(['ledger', 'info', 'balance'], 25) + .setIn(['ledger', 'info', 'userHasFunded'], true) + .setIn(['ledger', 'info', 'probi'], probi) + .setIn(['ledger', 'info', 'userFunded'], 25) + const result = ledgerApi.onWalletProperties(state, Immutable.fromJS({ + probi, + balance: 25 + })) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + + it('grant is saved', function () { + const expectedState = state + .setIn(['ledger', 'info', 'balance'], 25) + .setIn(['ledger', 'info', 'userHasFunded'], true) + .setIn(['ledger', 'info', 'probi'], probi) + .setIn(['ledger', 'info', 'userFunded'], 15) + .setIn(['ledger', 'info', 'grants'], Immutable.fromJS([{ + expirationDate: 2130600234, + amount: 10 + }])) + const result = ledgerApi.onWalletProperties(state, Immutable.fromJS({ + probi, + balance: 25, + grants: [{ + altcurrency: 'BAT', + expiryTime: 2130600234, + probi: 10000000000000000000 + }] + })) + assert.deepEqual(result.toJS(), expectedState.toJS()) + }) + }) }) describe('claimPromotion', function () { diff --git a/test/unit/app/common/lib/ledgerUtilTest.js b/test/unit/app/common/lib/ledgerUtilTest.js index 2f54ef62322..e1a332fbe74 100644 --- a/test/unit/app/common/lib/ledgerUtilTest.js +++ b/test/unit/app/common/lib/ledgerUtilTest.js @@ -223,12 +223,12 @@ describe('ledgerUtil unit test', function () { it('defaults to 0 as balance when rate is not present', function () { const data = ledgerData.delete('rates') - const result = ledgerUtil.formatCurrentBalance(data) + const result = ledgerUtil.formatCurrentBalance(data, ledgerData.get('balance')) assert.equal(result, '5.00 BAT') }) it('formats `balance` and `converted` values to two decimal places', function () { - const result = ledgerUtil.formatCurrentBalance(ledgerData) + const result = ledgerUtil.formatCurrentBalance(ledgerData, ledgerData.get('balance')) assert.equal(result, '5.00 BAT (1.12 USD)') }) @@ -238,24 +238,29 @@ describe('ledgerUtil unit test', function () { }) it('defaults `converted` to 0 if not found', function () { - const result = ledgerUtil.formatCurrentBalance(ledgerData.delete('converted')) + const result = ledgerUtil.formatCurrentBalance(ledgerData.delete('converted'), ledgerData.get('balance')) assert.equal(result, '5.00 BAT (0.00 USD)') }) it('handles `balance` being a string', function () { - const result = ledgerUtil.formatCurrentBalance(ledgerData.set('balance', '5')) + const result = ledgerUtil.formatCurrentBalance(ledgerData, 5) assert.equal(result, '5.00 BAT (1.12 USD)') }) it('handles `converted` being a string', function () { - const result = ledgerUtil.formatCurrentBalance(ledgerData.set('converted', '1.1234')) + const result = ledgerUtil.formatCurrentBalance(ledgerData.set('converted', '1.1234'), ledgerData.get('balance')) assert.equal(result, '5.00 BAT (1.12 USD)') }) it('custom format for amount lower then 0.01', function () { - const result = ledgerUtil.formatCurrentBalance(ledgerData.set('converted', '0.004')) + const result = ledgerUtil.formatCurrentBalance(ledgerData.set('converted', '0.004'), ledgerData.get('balance')) assert.equal(result, '5.00 BAT (< 0.01 USD)') }) + + it('formats only `balance` when alt is excluded', function () { + const result = ledgerUtil.formatCurrentBalance(ledgerData, ledgerData.get('balance'), false) + assert.equal(result, '5.00 BAT') + }) }) describe('formattedTimeFromNow', function () { diff --git a/test/unit/app/renderer/components/preferences/paymentsTabTest.js b/test/unit/app/renderer/components/preferences/paymentsTabTest.js index a3da767f129..6fb3d63b8f8 100644 --- a/test/unit/app/renderer/components/preferences/paymentsTabTest.js +++ b/test/unit/app/renderer/components/preferences/paymentsTabTest.js @@ -9,10 +9,9 @@ const assert = require('assert') const Immutable = require('immutable') const fakeElectron = require('../../../../lib/fakeElectron') const fakeSettings = require('../../../../lib/fakeSettings') -const {batToCurrencyString} = require('../../../../../../app/common/lib/ledgerUtil') const {advancedSettingsDialog} = require('../../../../../lib/selectors') -let PaymentsTab, EnabledContent +let PaymentsTab require('../../../../braveUnit') describe('PaymentsTab component', function () { @@ -71,7 +70,6 @@ describe('PaymentsTab component', function () { fakeSettings.mockReturnValue = false window.chrome = fakeElectron PaymentsTab = require('../../../../../../app/renderer/components/preferences/paymentsTab') - EnabledContent = require('../../../../../../app/renderer/components/preferences/payment/enabledContent') }) after(function () { mockery.disable() @@ -178,53 +176,6 @@ describe('PaymentsTab component', function () { }) }) - describe('fundsamount functionality', function () { - it('does not display if wallet not created', function () { - fakeSettings.mockReturnValue = true - const wrapper = mount( - - ) - const inst = wrapper.instance() - assert.equal(inst.fundsAmount, null) - }) - - it('handles expected balance', function () { - fakeSettings.mockReturnValue = true - const wrapper = mount( - - ) - assert.equal(wrapper.find('[data-test-id="fundsAmount"]').length, 1) - }) - - it.skip('renders full balance correctly', function () { - fakeSettings.mockReturnValue = true - const wrapper = mount( - - ) - const inst = wrapper.instance() - assert.equal(batToCurrencyString(10, inst.props.ledgerData), '10.00 USD') - }) - - it.skip('renders partial balance correctly', function () { - fakeSettings.mockReturnValue = true - const wrapper = mount( - - ) - const inst = wrapper.instance() - assert.equal(batToCurrencyString(10, inst.props.ledgerData), '2.00 USD') - }) - }) - describe('advanced ledger settings content', function () { it('defaults to an 8 second minimum visit duration', function () { fakeSettings.mockReturnValue = true