Skip to content
This repository was archived by the owner on Dec 11, 2019. It is now read-only.

Commit 3d9d3c2

Browse files
committed
ledger backup and recovery
1 parent 45b3e64 commit 3d9d3c2

File tree

6 files changed

+185
-3
lines changed

6 files changed

+185
-3
lines changed

app/extensions/brave/locales/en-US/preferences.properties

+18
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ bitcoinVisitAccount=Transfer BTC
5959
bitcoinBalance=Please transfer: 
6060
bitcoinWalletNotAvailable=Wallet information not available. :(
6161
usd=$
62+
cancel=Cancel
6263
done=Done
6364
off=off
6465
on=on
@@ -71,6 +72,9 @@ add=Fund with debit/credit
7172
transferTime=Transfer may take up to 40 minutes
7273
addFundsTitle=Add funds…
7374
addFunds=Three ways to add funds to your Brave Wallet
75+
copy=Copy
76+
firstKey=Key 1
77+
secondKey=Key 2
7478
copyToClipboard=Copy to clipboard
7579
smartphoneTitle=Use your smartphone app to transfer Bitcoin
7680
displayQRCode=Display QR code
@@ -110,6 +114,20 @@ offerSearchSuggestions=Autocomplete search term as you type
110114
doNotTrackTitle=Do Not Track
111115
doNotTrack=Send a 'Do Not Track' header with browsing requests (requires browser restart)
112116
blockCanvasFingerprinting=Fingerprinting Protection (may break some websites)
117+
advancedSettings=Advanced Settings...
118+
advancedSettingsTitle=Advanced Settings for Brave Payments
119+
ledgerRecoveryTitle=Recover your Brave wallet
120+
ledgerRecoverySubtitle=Enter your recovery keys below
121+
ledgerRecoveryContent=The balance of the recovered wallet will be transferred to your new Brave wallet. The old wallet will still exist as an empty wallet.
122+
ledgerBackupTitle=Backup your Brave wallet
123+
ledgerBackupContent=Below, you will find the anonymized recovery keys that are required if you ever lose access to this computer. We recommend that you print or save these keys and store them in a safe place, like your local safe deposit box, or under your mattress. It's really up to you!
124+
minimumPageTimeSetting=Minimum page time before logging a visit
125+
minimumVisitsSetting=Minimum visits for publisher relevancy
126+
backupLedger=Backup your wallet
127+
recoverLedger=Recover your wallet
128+
recover=Recover
129+
printKeys=Print keys
130+
saveRecoveryFile=Save recovery file...
113131
advancedPrivacySettings=Advanced Privacy Settings:
114132
braveryDefaults=Bravery Defaults
115133
blockAttackSites=Block reported attack sites (not available yet)

app/ledger.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ const doAction = (action) => {
136136
case settings.PAYMENTS_CONTRIBUTION_AMOUNT:
137137
setPaymentInfo(action.value)
138138
break
139+
case settings.MINIMUM_VISIT_TIME:
140+
break
141+
case settings.MINIMUM_VISTS:
142+
break
139143
default:
140144
break
141145
}
@@ -869,6 +873,10 @@ var ledgerInfo = {
869873
buyURL: undefined,
870874
bravery: undefined,
871875

876+
// wallet credentials
877+
paymentId: undefined,
878+
passphrase: undefined,
879+
872880
hasBitcoinHandler: false,
873881

874882
// geoIP/exchange information
@@ -1107,6 +1115,9 @@ var getStateInfo = (state) => {
11071115
var info = state.paymentInfo
11081116
var then = underscore.now() - msecs.year
11091117

1118+
ledgerInfo.paymentId = state.properties.wallet.paymentId
1119+
ledgerInfo.passphrase = state.properties.wallet.keychains.passphrase
1120+
11101121
ledgerInfo.created = !!state.properties.wallet
11111122
ledgerInfo.creating = !ledgerInfo.created
11121123

@@ -1228,7 +1239,6 @@ var getPaymentInfo = () => {
12281239

12291240
info = underscore.extend(info, underscore.pick(body, [ 'buyURL', 'buyURLExpires', 'balance', 'unconfirmed', 'satoshis' ]))
12301241
info.address = client.getWalletAddress()
1231-
info.passphrase = client.getWalletPassphrase()
12321242
if ((amount) && (currency)) {
12331243
info = underscore.extend(info, { amount: amount, currency: currency })
12341244
if ((body.rates) && (body.rates[currency])) {

js/about/preferences.js

+145-1
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ class TabsTab extends ImmutableComponent {
721721
class PaymentsTab extends ImmutableComponent {
722722
constructor () {
723723
super()
724+
this.printKeys = this.printKeys.bind(this)
724725
this.createWallet = this.createWallet.bind(this)
725726
}
726727

@@ -730,6 +731,23 @@ class PaymentsTab extends ImmutableComponent {
730731
}
731732
}
732733

734+
copyToClipboard (text) {
735+
aboutActions.setClipboard(text)
736+
}
737+
738+
printKeys () {
739+
const paymentId = this.props.ledgerData.get('paymentId')
740+
const passphrase = this.props.ledgerData.get('passphrase')
741+
742+
aboutActions.newFrame({
743+
location: `data:text/html,Brave Wallet Recovery keys
744+
Date created:
745+
Recovery Key 1: ${paymentId}
746+
Recovery Key 2: ${passphrase}
747+
Note: These keys are not stored on Brave servers. These keys are your only method of recovering your Brave wallet. Save these keys in a safe place, separate from your brave browser.`
748+
}, true)
749+
}
750+
733751
get enabled () {
734752
return getSetting(settings.PAYMENTS_ENABLED, this.props.settings)
735753
}
@@ -839,6 +857,111 @@ class PaymentsTab extends ImmutableComponent {
839857
</div>
840858
}
841859

860+
get advancedSettingsContent () {
861+
return <div className='board'>
862+
<div className='panel'>
863+
<div className='settingsPanelDivider'>
864+
<div data-l10n-id='minimumPageTimeSetting' />
865+
<SettingsList>
866+
<SettingItem>
867+
<select id='fundsSelectBox'>
868+
<option>5 seconds</option>
869+
<option>10 seconds</option>
870+
<option>1 minute</option>
871+
</select>
872+
</SettingItem>
873+
</SettingsList>
874+
<div data-l10n-id='minimumVisitsSetting' />
875+
<SettingsList>
876+
<SettingItem>
877+
<select id='fundsSelectBox'>
878+
<option>2 visits</option>
879+
<option>5 visits</option>
880+
<option>10 visits</option>
881+
</select>
882+
</SettingItem>
883+
</SettingsList>
884+
</div>
885+
{this.enabled
886+
? <SettingCheckbox
887+
dataL10nId='notifications'
888+
prefKey={settings.PAYMENTS_NOTIFICATIONS}
889+
settings={this.props.settings}
890+
onChangeSetting={this.props.onChangeSetting} />
891+
: null}
892+
</div>
893+
</div>
894+
}
895+
896+
get advancedSettingsFooter () {
897+
return <div className='panel advancedSettingsFooter'>
898+
<Button l10nId='backupLedger' className='primaryButton' onClick={this.props.showOverlay.bind(this, 'ledgerBackup')} />
899+
<Button l10nId='recoverLedger' className='primaryButton' onClick={this.props.showOverlay.bind(this, 'ledgerRecovery')} />
900+
<Button l10nId='done' className='whiteButton inlineButton' onClick={this.props.hideOverlay.bind(this, 'advancedSettings')} />
901+
</div>
902+
}
903+
904+
get ledgerBackupContent () {
905+
const paymentId = this.props.ledgerData.get('paymentId')
906+
const passphrase = this.props.ledgerData.get('passphrase')
907+
908+
return <div className='board'>
909+
<div className='panel'>
910+
<span data-l10n-id='ledgerBackupContent' />
911+
<div>
912+
<div className='copyContainer'>
913+
<Button l10nId='copy' className='whiteButton inlineButton' onClick={this.copyToClipboard.bind(this, paymentId)} />
914+
</div>
915+
<div className='keyContainer'>
916+
<h2 data-l10n-id='firstKey' />
917+
<span>{paymentId}</span>
918+
</div>
919+
</div>
920+
<div>
921+
<div className='copyContainer'>
922+
<Button l10nId='copy' className='whiteButton inlineButton' onClick={this.copyToClipboard.bind(this, passphrase)} />
923+
</div>
924+
<div className='keyContainer'>
925+
<h2 data-l10n-id='secondKey' />
926+
<span>{passphrase}</span>
927+
</div>
928+
</div>
929+
</div>
930+
</div>
931+
}
932+
933+
get ledgerBackupFooter () {
934+
return <div className='panel advancedSettingsFooter'>
935+
<Button l10nId='printKeys' className='primaryButton' onClick={this.printKeys} />
936+
<Button l10nId='saveRecoveryFile' className='primaryButton' />
937+
<Button l10nId='done' className='whiteButton inlineButton' onClick={this.props.hideOverlay.bind(this, 'ledgerBackup')} />
938+
</div>
939+
}
940+
941+
get ledgerRecoveryContent () {
942+
return <div className='board'>
943+
<div className='panel'>
944+
<h3 data-l10n-id='ledgerRecoverySubtitle' />
945+
<span data-l10n-id='ledgerRecoveryContent' />
946+
<SettingsList>
947+
<SettingItem>
948+
<h2>Key 1</h2>
949+
<input type='text' />
950+
<h2>Key 2</h2>
951+
<input type='text' />
952+
</SettingItem>
953+
</SettingsList>
954+
</div>
955+
</div>
956+
}
957+
958+
get ledgerRecoveryFooter () {
959+
return <div className='panel advancedSettingsFooter'>
960+
<Button l10nId='cancel' className='whiteButton inlineButton' onClick={this.props.hideOverlay.bind(this, 'ledgerBackup')} />
961+
<Button l10nId='recover' className='primaryButton' />
962+
</div>
963+
}
964+
842965
get nextReconcileDate () {
843966
const ledgerData = this.props.ledgerData
844967
if (!ledgerData.get('reconcileStamp')) {
@@ -947,6 +1070,21 @@ class PaymentsTab extends ImmutableComponent {
9471070
? <ModalOverlay title={'paymentHistoryTitle'} customTitleClasses={'paymentHistory'} content={this.paymentHistoryContent} footer={this.paymentHistoryFooter} onHide={this.props.hideOverlay.bind(this, 'paymentHistory')} />
9481071
: null
9491072
}
1073+
{
1074+
this.enabled && this.props.advancedSettingsOverlayVisible
1075+
? <ModalOverlay title={'advancedSettingsTitle'} content={this.advancedSettingsContent} footer={this.advancedSettingsFooter} onHide={this.props.hideOverlay.bind(this, 'advancedSettings')} />
1076+
: null
1077+
}
1078+
{
1079+
this.enabled && this.props.ledgerBackupOverlayVisible
1080+
? <ModalOverlay title={'ledgerBackupTitle'} content={this.ledgerBackupContent} footer={this.ledgerBackupFooter} onHide={this.props.hideOverlay.bind(this, 'ledgerBackup')} />
1081+
: null
1082+
}
1083+
{
1084+
this.enabled && this.props.ledgerRecoveryOverlayVisible
1085+
? <ModalOverlay title={'ledgerRecoveryTitle'} content={this.ledgerRecoveryContent} footer={this.ledgerRecoveryFooter} onHide={this.props.hideOverlay.bind(this, 'ledgerRecovery')} />
1086+
: null
1087+
}
9501088
<div className='titleBar'>
9511089
<div className='sectionTitleWrapper pull-left'>
9521090
<span className='sectionTitle'>Brave Payments</span>
@@ -957,7 +1095,7 @@ class PaymentsTab extends ImmutableComponent {
9571095
<span data-l10n-id='off' />
9581096
<SettingCheckbox dataL10nId='on' prefKey={settings.PAYMENTS_ENABLED} settings={this.props.settings} onChangeSetting={this.props.onChangeSetting} />
9591097
</div>
960-
{this.enabled ? <SettingCheckbox dataL10nId='notifications' prefKey={settings.PAYMENTS_NOTIFICATIONS} settings={this.props.settings} onChangeSetting={this.props.onChangeSetting} /> : null}
1098+
<Button l10nId='advancedSettings' className='whiteButton inlineButton' onClick={this.props.showOverlay.bind(this, 'advancedSettings')} />
9611099
</div>
9621100
</div>
9631101
{
@@ -1361,6 +1499,9 @@ class AboutPreferences extends React.Component {
13611499
bitcoinOverlayVisible: false,
13621500
qrcodeOverlayVisible: false,
13631501
paymentHistoryOverlayVisible: false,
1502+
advancedSettingsOverlayVisible: false,
1503+
ledgerBackupOverlayVisible: false,
1504+
ledgerRecoveryOverlayVisible: false,
13641505
addFundsOverlayVisible: false,
13651506
preferenceTab: hash.toUpperCase() in preferenceTabs ? hash : preferenceTabs.GENERAL,
13661507
hintNumber: this.getNextHintNumber(),
@@ -1491,6 +1632,9 @@ class AboutPreferences extends React.Component {
14911632
bitcoinOverlayVisible={this.state.bitcoinOverlayVisible}
14921633
qrcodeOverlayVisible={this.state.qrcodeOverlayVisible}
14931634
paymentHistoryOverlayVisible={this.state.paymentHistoryOverlayVisible}
1635+
advancedSettingsOverlayVisible={this.state.advancedSettingsOverlayVisible}
1636+
ledgerBackupOverlayVisible={this.state.ledgerBackupOverlayVisible}
1637+
ledgerRecoveryOverlayVisible={this.state.ledgerRecoveryOverlayVisible}
14941638
addFundsOverlayVisible={this.state.addFundsOverlayVisible}
14951639
showOverlay={this.setOverlayVisible.bind(this, true)}
14961640
hideOverlay={this.setOverlayVisible.bind(this, false)} />

js/constants/settings.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ const settings = {
5555
HARDWARE_ACCELERATION_ENABLED: 'advanced.hardware-acceleration-enabled',
5656
PDFJS_ENABLED: 'advanced.pdfjs-enabled',
5757
DEFAULT_ZOOM_LEVEL: 'advanced.default-zoom-level',
58-
SMOOTH_SCROLL_ENABLED: 'advanced.smooth-scroll-enabled'
58+
SMOOTH_SCROLL_ENABLED: 'advanced.smooth-scroll-enabled',
59+
MINIMUM_VISIT_TIME: 'advanced.minimum-visit-time',
60+
MINIMUM_VISTS: 'advanced.minimum-visits'
5961
}
6062

6163
module.exports = settings

less/about/preferences.less

+4
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,10 @@ div.nextPaymentSubmission {
897897
}
898898
}
899899

900+
.advancedSettingsFooter {
901+
padding: 20px 100px;
902+
}
903+
900904
#flashInfoIcon {
901905
padding: 5px 5px 5px 0;
902906
}

less/button.less

+4
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ span.browserButton,
118118
padding: 3px 35px;
119119
}
120120

121+
&.inlineButton {
122+
display: inline;
123+
}
124+
121125
&.secondaryButton {
122126
background-color: #eee;
123127
}

0 commit comments

Comments
 (0)