Skip to content

Commit

Permalink
added wallet cooldown code
Browse files Browse the repository at this point in the history
  • Loading branch information
maikelmclauflin committed Mar 30, 2019
1 parent 696cef7 commit 9c79d78
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 8 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -30,6 +30,7 @@ env:
- "TESTING_COHORTS=test"
- "TOKEN_LIST=foobarfoobar"
- "UPHOLD_DONOR_CARD_ID=6654ecb0-6079-4f6c-ba58-791cc890a561"
- "WALLET_COOLDOWN_HRS=0"
- "VOTING_COHORTS=control,grant,test,ads,safetynet"
- secure: "JQ9WipBrcCPtXFwv/fmzhv8LPz/tx/jCPpeTK0KmSZr4Yqs5kMG0YGH3QeT1YDpiRakW9X5us9tsnsfHuslvZ8Z565lc0wIK7b7CUcEzVuBts6cfVQtOpqKKYjw6jyq5TraTYawYGUfeaCkP+35oM/1fs4vPy6MbH5Plzg6f9iMfB+BFysRT20JYKXcW0LfihHRKStaAJYKDD2mpdY4kStu7vYB66LgR6Solw1IUwgJzfKst/dM6PJspfmNkFaHCoBNMEYcUJmeJPqmLCnfIA+eRCrSMfHOChjzCV6JbmcD11FOydISEhdt67X+5TDArePYVssrj7NygVlrn8TOvk6InXuul6n+oIpS0vz5e5QdxrReLLwb+WJPK7xKWD56Ko2gfTwtEUdevLzQhKfPMs5wW5ujjlcjAqi5PmC87Q+bxCjet19EdJ4j09y2NSKRo1LMzu1WIM6o1mIatha0vJEHa05XAUsuD9lCGrt/aG4DLYh5Q5gJP/SYDoMl+wJku254KJN+WesxaSREhgdqtV13GFnMofI9r/vq4wKrlcbsMh3UD337NZlNVZzONINeJ4afN3TRK+LS8bHGsss/ZpLcnfT0uYMXzneQQhkKmKWkss8VOLEZ2ccLRG0LNWsOJXznBE/SqXaxSK4NkgXQDyfVUuAj7GPyIDX6hygsguyA="
- secure: "be8ASUNkGT1MpO/wfwVQKuo0Absf5xQAnjXRmsrM105n+vGXdq1c/fl13wow7d/PQtR27tNlJ5UmoeROUCBLlOKm+bWWZ7wFThsxOQtHk3yJoaVtIApo5cwEQcMi/92zWQKDwO7ZuK+xY9oLiYng2yayfuxBUEzWlNxS0cMsmq6Xnf1qG8USVCqvo8gQp/X8hliscFWRbCJ+lzggmlIsoTe6RElF9N3yXngvWRJY/GDjOe3FD2wJNDoE8wYwHcxKvfcdL0c8dWhHl5KC366ZSiBMJHrwv2aVjUgwQ2Azsdehxy1bsqyiH2bS/ifH8FUosjMA/g8qRB89EgaLCS5NndIVl1q0miuRv20kMaF6syTOH3HyDi/o2L9tg1Z/XSuNSVI2o+A8yJfKiY1AwjCR8aQ+uyKj9kOg7nTlBElHrOcAOaiC0Rg13TZ2230IbFanQFIqDL0B8xQx1EAxsArgWIrebqSd1QbVYKEHE5+2dWXExPX+7e217rFvEz5Ltxq1U9IdHHnmcTxUrylr800ub2PtOyZvRNbBFXq5tDpENLl/lV8yf0Qm2q+8jUvqXZIG0akIqC5b0cpHEtxJcAGvfqFx8vZUV1WW4TVbxApmndSGFw2bF6psx6SJUDrdFfl87u1Rb7wWtesDXAMrfIphlr0AcH2P7XDqxAjifuQgtdk="
Expand Down
1 change: 1 addition & 0 deletions base.yml
Expand Up @@ -70,4 +70,5 @@ services:
- UPHOLD_DONOR_CARD_ID
- UPHOLD_ENVIRONMENT
- VOTING_COHORTS
- WALLET_COOLDOWN_HRS
- YOUTUBE_API_KEY
6 changes: 6 additions & 0 deletions bat-utils/lib/extras-utils.js
Expand Up @@ -20,6 +20,7 @@ module.exports = {
isYoutubeChannelId,
normalizeChannel,
justDate,
hexTime,
BigNumber
}

Expand Down Expand Up @@ -48,6 +49,11 @@ function documentOlderThan (olderThanDays, anchorTime, _id) {
return createdTimestamp(_id) < (anchorTime - (DAY_MS * olderThanDays))
}

function hexTime (now = new Date()) {
const offsetSeconds = Math.floor(now / 1000)
return offsetSeconds.toString(16) + '0000000000000000'
}

function createdTimestamp (id) {
return new Date(parseInt(id.toHexString().substring(0, 8), 16) * 1000).getTime()
}
Expand Down
12 changes: 6 additions & 6 deletions bat-utils/lib/extras-utils.test.js
Expand Up @@ -4,6 +4,7 @@ import {
ObjectID
} from 'mongodb'
import {
hexTime,
surveyorChoices,
createdTimestamp,
timeout,
Expand All @@ -18,13 +19,11 @@ dotenv.config()
const objectId = ObjectID('5b11685dd28b11258d50c1f4')
const objectDate = (new Date('2018-06-01T15:38:05.000Z')).getTime()
test('createdTimestamp', (t) => {
t.plan(1)
const fromId = createdTimestamp(objectId)
t.is(fromId, objectDate)
})

test('timeout', (t) => {
t.plan(1)
let bool = false
timeout(495).then(() => {
bool = true
Expand All @@ -42,32 +41,33 @@ test('timeout', (t) => {
})

test('documentOlderThan', (t) => {
t.plan(3)
t.true(documentOlderThan(-1, objectDate, objectId))
t.false(documentOlderThan(1, objectDate, objectId))
// lt not lte
t.false(documentOlderThan(0, objectDate, objectId))
})

test('isYoutubeChannelId', (t) => {
t.plan(3)
t.true(isYoutubeChannelId('UCFNTTISby1c_H-rm5Ww5rZg'))
t.false(isYoutubeChannelId('UCFNTTISby1c_H-rm5Ww5rZ'))
t.false(isYoutubeChannelId('Brave'))
})

test('normalizeChannel', (t) => {
t.plan(4)
t.is(normalizeChannel('youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg'), 'youtube#channel:UCFNTTISby1c_H-rm5Ww5rZg')
t.is(normalizeChannel('youtube#channel:Brave'), 'youtube#user:Brave')
t.is(normalizeChannel('twitch#channel:Brave'), 'twitch#author:Brave')
t.is(normalizeChannel('www.brave.com'), 'www.brave.com')
})

test('surveyorChoices', (t) => {
t.plan(4)
t.deepEqual(surveyorChoices(0.55), [6, 10, 14, 20, 40], 'increment is less than')
t.deepEqual(surveyorChoices(0.5), [6, 10, 14, 20, 40], 'increment is equal to')
t.deepEqual(surveyorChoices(2), [3, 5, 7, 10, 20], 'increment can be above range')
t.deepEqual(surveyorChoices(0.02), [30, 50, 70, 100], 'increment can be below range')
})

test('hexTime', (t) => {
t.is(hexTime(new Date('2019-01-01')), '5c2aad800000000000000000', 'returns hexidecimal version of date')
t.is(hexTime(new Date('2018-01-01')), '5a497a000000000000000000', 'returns hexidecimal version of any date')
})
10 changes: 8 additions & 2 deletions ledger/controllers/grants.js
Expand Up @@ -6,7 +6,9 @@ const bson = require('bson')
const underscore = require('underscore')
const uuidV4 = require('uuid/v4')
const wreck = require('wreck')

const {
cooldownOffset
} = require('../lib/grants')
const utils = require('bat-utils')
const braveJoi = utils.extras.joi
const braveHapi = utils.extras.hapi
Expand Down Expand Up @@ -265,6 +267,7 @@ const getGrant = (protocolVersion) => (runtime) => {
const promotions = runtime.database.get('promotions', debug)
const wallets = runtime.database.get('wallets', debug)
let entries, promotionIds, wallet
let walletTooYoung = false

if (qaOnlyP(request)) return reply(boom.notFound())

Expand All @@ -276,6 +279,9 @@ const getGrant = (protocolVersion) => (runtime) => {
wallet.grants.forEach((grant) => { promotionIds.push(grant.promotionId) })
}
underscore.extend(query, { promotionId: { $nin: promotionIds } })
const offset = cooldownOffset()
walletTooYoung = braveUtils.createdTimestamp(wallet._id) > (new Date() - offset)
debug('offset', { offset, walletTooYoung })
}

if (protocolVersion === 4 && !paymentId) {
Expand All @@ -299,7 +305,7 @@ const getGrant = (protocolVersion) => (runtime) => {
underscore.extend(query, { providerId: wallet.addresses.CARD_ID })
}
const counted = await grants.count(query)
if (counted !== 0) {
if (counted !== 0 && !walletTooYoung) {
filteredPromotions.push({ promotionId, type })
}
}
Expand Down
15 changes: 15 additions & 0 deletions ledger/lib/grants.js
@@ -0,0 +1,15 @@
const _ = require('underscore')
const { WALLET_COOLDOWN_HRS } = process.env
module.exports = {
defaultCooldownHrs,
cooldownOffset
}

function defaultCooldownHrs (hours) {
const hrs = _.isUndefined(hours) ? WALLET_COOLDOWN_HRS : hours
return hrs ? (+hrs || 0) : 24
}

function cooldownOffset (hours = defaultCooldownHrs()) {
return hours * 60 * 60 * 1000
}
18 changes: 18 additions & 0 deletions test/ledger/grants.integration.test.js
Expand Up @@ -18,6 +18,10 @@ import {
timeout,
uint8tohex
} from 'bat-utils/lib/extras-utils'
import {
defaultCooldownHrs,
cooldownOffset
} from '../../ledger/lib/grants'

test.before(cleanDbs)
test.after(cleanDbs)
Expand All @@ -28,6 +32,20 @@ const expired = {'grants': ['eyJhbGciOiJFZERTQSIsImtpZCI6IiJ9.eyJhbHRjdXJyZW5jeS

const BAT_CAPTCHA_BRAVE_TOKEN = 'eyJhbGciOiJSUzI1NiIsIng1YyI6WyJNSUlGa2pDQ0JIcWdBd0lCQWdJUVJYcm9OMFpPZFJrQkFBQUFBQVB1bnpBTkJna3Foa2lHOXcwQkFRc0ZBREJDTVFzd0NRWURWUVFHRXdKVlV6RWVNQndHQTFVRUNoTVZSMjl2WjJ4bElGUnlkWE4wSUZObGNuWnBZMlZ6TVJNd0VRWURWUVFERXdwSFZGTWdRMEVnTVU4eE1CNFhEVEU0TVRBeE1EQTNNVGswTlZvWERURTVNVEF3T1RBM01UazBOVm93YkRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V4RmpBVUJnTlZCQWNURFUxdmRXNTBZV2x1SUZacFpYY3hFekFSQmdOVkJBb1RDa2R2YjJkc1pTQk1URU14R3pBWkJnTlZCQU1URW1GMGRHVnpkQzVoYm1SeWIybGtMbU52YlRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTmpYa3owZUsxU0U0bSsvRzV3T28rWEdTRUNycWRuODhzQ3BSN2ZzMTRmSzBSaDNaQ1laTEZIcUJrNkFtWlZ3Mks5RkcwTzlyUlBlUURJVlJ5RTMwUXVuUzl1Z0hDNGVnOW92dk9tK1FkWjJwOTNYaHp1blFFaFVXWEN4QURJRUdKSzNTMmFBZnplOTlQTFMyOWhMY1F1WVhIRGFDN09acU5ub3NpT0dpZnM4djFqaTZIL3hobHRDWmUybEorN0d1dHpleEtweHZwRS90WlNmYlk5MDVxU2xCaDlmcGowMTVjam5RRmtVc0FVd21LVkFVdWVVejR0S2NGSzRwZXZOTGF4RUFsK09raWxNdElZRGFjRDVuZWw0eEppeXM0MTNoYWdxVzBXaGg1RlAzOWhHazlFL0J3UVRqYXpTeEdkdlgwbTZ4RlloaC8yVk15WmpUNEt6UEpFQ0F3RUFBYU9DQWxnd2dnSlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBVEFNQmdOVkhSTUJBZjhFQWpBQU1CMEdBMVVkRGdRV0JCUXFCUXdHV29KQmExb1RLcXVwbzRXNnhUNmoyREFmQmdOVkhTTUVHREFXZ0JTWTBmaHVFT3ZQbSt4Z254aVFHNkRyZlFuOUt6QmtCZ2dyQmdFRkJRY0JBUVJZTUZZd0p3WUlLd1lCQlFVSE1BR0dHMmgwZEhBNkx5OXZZM053TG5CcmFTNW5iMjluTDJkMGN6RnZNVEFyQmdnckJnRUZCUWN3QW9ZZmFIUjBjRG92TDNCcmFTNW5iMjluTDJkemNqSXZSMVJUTVU4eExtTnlkREFkQmdOVkhSRUVGakFVZ2hKaGRIUmxjM1F1WVc1a2NtOXBaQzVqYjIwd0lRWURWUjBnQkJvd0dEQUlCZ1puZ1F3QkFnSXdEQVlLS3dZQkJBSFdlUUlGQXpBdkJnTlZIUjhFS0RBbU1DU2dJcUFnaGg1b2RIUndPaTh2WTNKc0xuQnJhUzVuYjI5bkwwZFVVekZQTVM1amNtd3dnZ0VFQmdvckJnRUVBZFo1QWdRQ0JJSDFCSUh5QVBBQWR3Q2t1UW1RdEJoWUZJZTdFNkxNWjNBS1BEV1lCUGtiMzdqamQ4ME95QTNjRUFBQUFXWmREM1BMQUFBRUF3QklNRVlDSVFDU1pDV2VMSnZzaVZXNkNnK2dqLzl3WVRKUnp1NEhpcWU0ZVk0Yy9teXpqZ0loQUxTYmkvVGh6Y3pxdGlqM2RrM3ZiTGNJVzNMbDJCMG83NUdRZGhNaWdiQmdBSFVBVmhRR21pL1h3dXpUOWVHOVJMSSt4MFoydWJ5WkVWekE3NVNZVmRhSjBOMEFBQUZtWFE5ejVBQUFCQU1BUmpCRUFpQmNDd0E5ajdOVEdYUDI3OHo0aHIvdUNIaUFGTHlvQ3EySzAreUxSd0pVYmdJZ2Y4Z0hqdnB3Mm1CMUVTanEyT2YzQTBBRUF3Q2tuQ2FFS0ZVeVo3Zi9RdEl3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUk5blRmUktJV2d0bFdsM3dCTDU1RVRWNmthenNwaFcxeUFjNUR1bTZYTzQxa1p6d0o2MXdKbWRSUlQvVXNDSXkxS0V0MmMwRWpnbG5KQ0YyZWF3Y0VXbExRWTJYUEx5RmprV1FOYlNoQjFpNFcyTlJHelBodDNtMWI0OWhic3R1WE02dFg1Q3lFSG5UaDhCb200L1dsRmloemhnbjgxRGxkb2d6L0syVXdNNlM2Q0IvU0V4a2lWZnYremJKMHJqdmc5NEFsZGpVZlV3a0k5Vk5NakVQNWU4eWRCM29MbDZnbHBDZUY1ZGdmU1g0VTl4MzVvai9JSWQzVUUvZFBwYi9xZ0d2c2tmZGV6dG1VdGUvS1Ntcml3Y2dVV1dlWGZUYkkzenNpa3daYmtwbVJZS21qUG1odjRybGl6R0NHdDhQbjhwcThNMktEZi9QM2tWb3QzZTE4UT0iLCJNSUlFU2pDQ0F6S2dBd0lCQWdJTkFlTzBtcUdOaXFtQkpXbFF1REFOQmdrcWhraUc5dzBCQVFzRkFEQk1NU0F3SGdZRFZRUUxFeGRIYkc5aVlXeFRhV2R1SUZKdmIzUWdRMEVnTFNCU01qRVRNQkVHQTFVRUNoTUtSMnh2WW1Gc1UybG5iakVUTUJFR0ExVUVBeE1LUjJ4dlltRnNVMmxuYmpBZUZ3MHhOekEyTVRVd01EQXdOREphRncweU1URXlNVFV3TURBd05ESmFNRUl4Q3pBSkJnTlZCQVlUQWxWVE1SNHdIQVlEVlFRS0V4VkhiMjluYkdVZ1ZISjFjM1FnVTJWeWRtbGpaWE14RXpBUkJnTlZCQU1UQ2tkVVV5QkRRU0F4VHpFd2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURRR005RjFJdk4wNXprUU85K3ROMXBJUnZKenp5T1RIVzVEekVaaEQyZVBDbnZVQTBRazI4RmdJQ2ZLcUM5RWtzQzRUMmZXQllrL2pDZkMzUjNWWk1kUy9kTjRaS0NFUFpSckF6RHNpS1VEelJybUJCSjV3dWRnem5kSU1ZY0xlL1JHR0ZsNXlPRElLZ2pFdi9TSkgvVUwrZEVhbHROMTFCbXNLK2VRbU1GKytBY3hHTmhyNTlxTS85aWw3MUkyZE44RkdmY2Rkd3VhZWo0YlhocDBMY1FCYmp4TWNJN0pQMGFNM1Q0SStEc2F4bUtGc2JqemFUTkM5dXpwRmxnT0lnN3JSMjV4b3luVXh2OHZObWtxN3pkUEdIWGt4V1k3b0c5aitKa1J5QkFCazdYckpmb3VjQlpFcUZKSlNQazdYQTBMS1cwWTN6NW96MkQwYzF0Skt3SEFnTUJBQUdqZ2dFek1JSUJMekFPQmdOVkhROEJBZjhFQkFNQ0FZWXdIUVlEVlIwbEJCWXdGQVlJS3dZQkJRVUhBd0VHQ0NzR0FRVUZCd01DTUJJR0ExVWRFd0VCL3dRSU1BWUJBZjhDQVFBd0hRWURWUjBPQkJZRUZKalIrRzRRNjgrYjdHQ2ZHSkFib090OUNmMHJNQjhHQTFVZEl3UVlNQmFBRkp2aUIxZG5IQjdBYWdiZVdiU2FMZC9jR1lZdU1EVUdDQ3NHQVFVRkJ3RUJCQ2t3SnpBbEJnZ3JCZ0VGQlFjd0FZWVphSFIwY0RvdkwyOWpjM0F1Y0d0cExtZHZiMmN2WjNOeU1qQXlCZ05WSFI4RUt6QXBNQ2VnSmFBamhpRm9kSFJ3T2k4dlkzSnNMbkJyYVM1bmIyOW5MMmR6Y2pJdlozTnlNaTVqY213d1B3WURWUjBnQkRnd05qQTBCZ1puZ1F3QkFnSXdLakFvQmdnckJnRUZCUWNDQVJZY2FIUjBjSE02THk5d2Eya3VaMjl2Wnk5eVpYQnZjMmwwYjNKNUx6QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFHb0ErTm5uNzh5NnBSamQ5WGxRV05hN0hUZ2laL3IzUk5Ha21VbVlIUFFxNlNjdGk5UEVhanZ3UlQyaVdUSFFyMDJmZXNxT3FCWTJFVFV3Z1pRK2xsdG9ORnZoc085dHZCQ09JYXpwc3dXQzlhSjl4anU0dFdEUUg4TlZVNllaWi9YdGVEU0dVOVl6SnFQalk4cTNNRHhyem1xZXBCQ2Y1bzhtdy93SjRhMkc2eHpVcjZGYjZUOE1jRE8yMlBMUkw2dTNNNFR6czNBMk0xajZieWtKWWk4d1dJUmRBdktMV1p1L2F4QlZielltcW13a201ekxTRFc1bklBSmJFTENRQ1p3TUg1NnQyRHZxb2Z4czZCQmNDRklaVVNweHU2eDZ0ZDBWN1N2SkNDb3NpclNtSWF0ai85ZFNTVkRRaWJldDhxLzdVSzR2NFpVTjgwYXRuWnoxeWc9PSJdfQ.eyJub25jZSI6InhnTUdCWVl3aW53dVhrQ2x4OXNYVDdtSWxLMEtodDJaWW5KaGRtVmZibTl1WTJVeE5UUXdORGszTnpJME1ESTIiLCJ0aW1lc3RhbXBNcyI6MTU0MDQ5NzcyNTQ4MCwiYXBrUGFja2FnZU5hbWUiOiJjb20uYnJhdmUuYnJvd3NlciIsImFwa0RpZ2VzdFNoYTI1NiI6IldPRTVQRk9pNjI4UjhRZHAxa3B2UUhMVVNwWUtnWjU2YUZkbFJyTE5UZ3M9IiwiY3RzUHJvZmlsZU1hdGNoIjp0cnVlLCJhcGtDZXJ0aWZpY2F0ZURpZ2VzdFNoYTI1NiI6WyJNcUw4ZE5jeEVGaFo1YWhkOFcyVjhRTFlXeUlKbTRCa3hkaVJYR0hhMGVBPSJdLCJiYXNpY0ludGVncml0eSI6dHJ1ZX0.K39pNLtS7w-jlnNlP1fz31RGH-xP23t_FyInL3FrxNJGQq5oRMpkBGUeE49sOeUJMi8gjYpQR1Ek2-3M8gS_0IwOUFcIXJjAJuLVJHwg_i0hxtgJLRvCAS3ifsfk-UX7HsYKdY1voUsPtZ9ilYLIJCY5Gy5uHqedgznDKyrGYKPMuiMNyfkp88AjN2XA9D2Axqys9s67uEivMF37HUDK_Kqh8uYF276vs9SU7ovedbz7tG1suGUT9zpEDCZBLqdhj2wfdiXphhOZJG2ogMUzp3IOCRLYsfWSha-OQX3UI84cYUG1Ubrqd4mahl5dpkxclkMr-zyFQC5WNCQLO2OA_g'

test('default cooldown hrs', async (t) => {
t.is(defaultCooldownHrs(), defaultCooldownHrs(process.env.WALLET_COOLDOWN_HRS), 'uses env var for default')
t.is(defaultCooldownHrs(12), 12, 'can be passed number')
t.is(defaultCooldownHrs('12'), 12, 'can be passed numeric string')
t.is(defaultCooldownHrs('0'), 0, 'can be passed falsey numeric string')
t.is(defaultCooldownHrs('a'), 0, 'defaults to 0 if passed non numeric values')
})

test('cooldown offset', async (t) => {
t.is(cooldownOffset(), cooldownOffset(defaultCooldownHrs()), 'calculates hours to offset in terms of milliseconds')
t.is(cooldownOffset(12), 12 * 60 * 60 * 1000, 'gives back in ms')
t.is(cooldownOffset({}), NaN, 'only takes numeric values')
})

test('grants: add expired grant and make sure it does not add to wallet', async t => {
t.plan(10)
let body, item
Expand Down

0 comments on commit 9c79d78

Please sign in to comment.