Skip to content

Commit

Permalink
feat: allow entering mnemonic (#23)
Browse files Browse the repository at this point in the history
Add a screen to allow entering you mnemonic when the wallet is used for
the first time.

closes #3
  • Loading branch information
rllola authored Sep 10, 2024
1 parent f7ddb58 commit c19811c
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 33 deletions.
4 changes: 3 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ async function app (args) {
} catch (err) {
const mnemonic = Wallet.generateMnemonic()
let mnemonicScreen = new Mnemonic(mnemonic)
await mnemonicScreen.validateMnemonic()

// The return value is the mnemonic that we either generated or the one we entered
const menmonic = await mnemonicScreen.completion()
Wallet.createSeedFile(mnemonic, SEED_FILE)
}

Expand Down
50 changes: 50 additions & 0 deletions src/mnemonic/choice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const {
QMainWindow,
QStackedWidget,
QIcon,
QPushButton,
AlignmentFlag,
QGridLayout,
Direction,
QLabel
} = require("@nodegui/nodegui")
const View = require('../components/view')

class MnemonicChoice extends View {
constructor (viewManager) {
super()

const layout = new QGridLayout()

this.buttonNewWallet = new QPushButton()
this.buttonNewWallet.setText('New Wallet')
this.buttonNewWallet.setInlineStyle('padding: 5px; background-color: white; border-radius: 30%; color: #131620;')
this.buttonNewWallet.setFixedSize(240, 60)

const orText = new QLabel()
orText.setText('Or')

this.buttonEnterMnemonic = new QPushButton()
this.buttonEnterMnemonic.setText('Enter Mnemonic')
this.buttonEnterMnemonic.setInlineStyle('padding: 5px; background-color: white; border-radius: 30%; color: #131620;')
this.buttonEnterMnemonic.setFixedSize(240, 60)

layout.addWidget(this.buttonNewWallet, 0, 0, 3, 0, AlignmentFlag.AlignCenter)
layout.addWidget(orText, 1, 0, 3, 0, AlignmentFlag.AlignCenter)
layout.addWidget(this.buttonEnterMnemonic, 2, 0, 3, 0, AlignmentFlag.AlignCenter)

this.buttonNewWallet.addEventListener('clicked', () => {
console.log('New Wallet clicked')
viewManager.emit('changeView', 'new')
})

this.buttonEnterMnemonic.addEventListener('clicked', () => {
console.log('Enter Mnemonic clicked')
viewManager.emit('changeView', 'enter')
})

this.setLayout(layout)
}
}

module.exports = MnemonicChoice
45 changes: 45 additions & 0 deletions src/mnemonic/enter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const {
QPushButton,
AlignmentFlag,
QGridLayout,
Direction,
QLabel,
QTextEdit,
} = require("@nodegui/nodegui")
const View = require('../components/view')

class MnemonicEnter extends View {
constructor (viewManager) {
super()

const layout = new QGridLayout()

const enterLabel = new QLabel()
enterLabel.setText('Enter your mnemonic :')
enterLabel.setFixedHeight(80)

this.edit = new QTextEdit()
this.edit.setInlineStyle('padding: 15px; background-color: white; border-radius: 2%; color: #131620;')
this.edit.setFixedWidth(320)

this.buttonValidate = new QPushButton()
this.buttonValidate.setText('Validate')
this.buttonValidate.setInlineStyle('padding: 5px; background-color: white; border-radius: 30%; color: #131620;')
this.buttonValidate.setFixedSize(240, 60)

// TODO: fix the layout so it doesn't look so weird
layout.addWidget(enterLabel, 1, 0, 1, 0, AlignmentFlag.AlignCenter)
layout.addWidget(this.edit, 2, 0, 1, 0, AlignmentFlag.AlignCenter)
layout.addWidget(this.buttonValidate, 3, 0, 3, 0, AlignmentFlag.AlignCenter)

this.buttonValidate.addEventListener('clicked', () => {
// TODO: validate the mnemonic here
const mnemonic = this.edit.toPlainText()
viewManager.emit('completed', mnemonic)
})

this.setLayout(layout)
}
}

module.exports = MnemonicEnter
83 changes: 52 additions & 31 deletions src/mnemonic/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const {
QMainWindow,
QPlainTextEdit,
QStackedWidget,
QIcon,
QPushButton,
QFrame,
QGridLayout,
AlignmentFlag

} = require("@nodegui/nodegui")
const path = require("path")
const EventEmitter = require('events')

// Screens
const MnemonicChoice = require('./choice')
const MnemonicShow = require('./show')
const MnemonicEnter = require('./enter')

// icons path
const icon = typeof __webpack_require__ === 'function' ? "./assets/logo.png" : "../assets/logo.png"
Expand All @@ -23,43 +24,63 @@ class Mnemonic extends QMainWindow {
this.setWindowIcon(winIcon)
this.setFixedSize(460, 720)

const frame = new QFrame()
const layout = new QGridLayout()

/* Text edit widget */
const plainTextEdit = new QPlainTextEdit()
plainTextEdit.setPlainText(mnemonic)
plainTextEdit.setDisabled(true)
plainTextEdit.setInlineStyle('margin: 180px 20px; border: none; font-size: 2em;')

// -------------------
// Stacked Widget (manage views)
// -------------------
const views = new QStackedWidget()
const viewManager = new EventEmitter()

this.button = new QPushButton()
this.button.setText('I have saved my mnemonic')
this.button.setInlineStyle('padding: 5px; background-color: white; border-radius: 30%; color: #131620;')
this.button.setFixedSize(240, 60)

layout.addWidget(plainTextEdit, 0, 0, 1, 0, AlignmentFlag.AlignTop)
layout.addWidget(this.button, 1, 0, 1, 0, AlignmentFlag.AlignCenter)
const choice = new MnemonicChoice(viewManager)
const show = new MnemonicShow(viewManager, mnemonic)
const enter = new MnemonicEnter(viewManager)

views.addWidget(choice)
views.addWidget(show)
views.addWidget(enter)

// frame.setInlineStyle('border: none;')
frame.setInlineStyle('margin: 20px;')
views.setCurrentWidget(choice)

this.setCentralWidget(views)
this.setStyleSheet('background-color: #131620;')

frame.setLayout(layout)
this.setCentralWidget(frame)
// View Manager
viewManager.on('changeView', async (view) => {
switch (view) {
case 'new':
views.setCurrentIndex(1)
break
case 'enter':
views.setCurrentIndex(2)
break
default:
console.log('unknown view')
}
})

this.setStyleSheet('background-color: #131620;')
// -------------------
// Event manager for completion
// -------------------
this.viewManager = viewManager

this.show()
}

async validateMnemonic () {
async completion () {
return new Promise((resolve, reject) => {
this.button.addEventListener('clicked', () => {
this.viewManager.on('completed', (mnemonic) => {
// close the mnemonic window
this.close()
resolve()
})

console.log("completed")

// We return the menmonic in case we have entered one
resolve(mnemonic)
})
this.viewManager.on('failed', () => {
// close the mnemonic window
this.close()
reject()
})
})
}
}
Expand Down
43 changes: 43 additions & 0 deletions src/mnemonic/show.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const {
QGridLayout,
AlignmentFlag,
QPushButton,
QFrame,
QPlainTextEdit,
} = require("@nodegui/nodegui")
const View = require('../components/view')

class MnemonicShow extends View {
constructor (viewManager, mnemonic) {
super()

const layout = new QGridLayout()

/* Text edit widget */
const plainTextEdit = new QPlainTextEdit()
plainTextEdit.setPlainText(mnemonic)
plainTextEdit.setDisabled(true)
plainTextEdit.setInlineStyle('margin: 180px 20px; border: none; font-size: 2em;')


this.button = new QPushButton()
this.button.setText('I have saved my mnemonic')
this.button.setInlineStyle('padding: 5px; background-color: white; border-radius: 30%; color: #131620;')
this.button.setFixedSize(240, 60)

layout.addWidget(plainTextEdit, 0, 0, 1, 0, AlignmentFlag.AlignTop)
layout.addWidget(this.button, 1, 0, 1, 0, AlignmentFlag.AlignCenter)

// frame.setInlineStyle('border: none;')
this.setInlineStyle('margin: 20px;')

this.setLayout(layout)

this.button.addEventListener('clicked', () => {
viewManager.emit('completed', mnemonic)
})

}
}

module.exports = MnemonicShow
2 changes: 1 addition & 1 deletion src/win.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const Home = require('./home')
const Send = require('./send')
const Receive = require('./receive')
const Settings = require('./settings')
const Mnemonic = require('./mnemonic')


// icons path
const icon = typeof __webpack_require__ === 'function' ? "./assets/logo.png" : "../assets/logo.png"
Expand Down

0 comments on commit c19811c

Please sign in to comment.