diff --git a/react/src/actions/actions/electrum.js b/react/src/actions/actions/electrum.js index 4991db5..312b4fc 100644 --- a/react/src/actions/actions/electrum.js +++ b/react/src/actions/actions/electrum.js @@ -311,4 +311,33 @@ export function shepherdElectrumListunspent(coin, address) { } }); }); +} + +export function shepherdElectrumBip39Keys(seed, match) { + return new Promise((resolve, reject) => { + fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/seed/bip39/match`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + seed, + match, + }), + }) + .catch((error) => { + console.log(error); + Store.dispatch( + triggerToaster( + 'shepherdElectrumSetServer', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => { + resolve(json); + }); + }); } \ No newline at end of file diff --git a/react/src/components/dashboard/settings/settings.bip39KeysPanel.js b/react/src/components/dashboard/settings/settings.bip39KeysPanel.js new file mode 100644 index 0000000..756a5d5 --- /dev/null +++ b/react/src/components/dashboard/settings/settings.bip39KeysPanel.js @@ -0,0 +1,182 @@ +import React from 'react'; +import { translate } from '../../../translate/translate'; +import { connect } from 'react-redux'; +import { + shepherdElectrumBip39Keys, + copyCoinAddress, + triggerToaster, +} from '../../../actions/actionCreators'; +import Store from '../../../store'; + +class Bip39KeysPanel extends React.Component { + constructor() { + super(); + this.state = { + keys: null, + match: '', + passphrase: '', + seedInputVisibility: false, + trimPassphraseTimer: null, + }; + this._getBip39Keys = this._getBip39Keys.bind(this); + this.updateInput = this.updateInput.bind(this); + this.toggleSeedInputVisibility = this.toggleSeedInputVisibility.bind(this); + this._copyCoinAddress = this._copyCoinAddress.bind(this); + } + + componentWillReceiveProps(props) { + if (props.Dashboard && + props.Dashboard.activeSection !== 'settings') { + // reset input vals + this.refs.passphrase.value = ''; + this.refs.passphraseTextarea.value = ''; + + this.setState(Object.assign({}, this.state, { + passphrase: '', + keys: null, + match: null, + })); + } + } + + toggleSeedInputVisibility() { + this.setState({ + seedInputVisibility: !this.state.seedInputVisibility, + }); + } + + updateInput(e) { + if (e.target.name === 'passphrase') { + // remove any empty chars from the start/end of the string + const newValue = e.target.value; + + clearTimeout(this.state.trimPassphraseTimer); + + const _trimPassphraseTimer = setTimeout(() => { + this.setState({ + passphrase: newValue ? newValue.trim() : '', // hardcoded field name + }); + }, 2000); + + this.resizeLoginTextarea(); + + this.setState({ + trimPassphraseTimer: _trimPassphraseTimer, + [e.target.name === 'passphraseTextarea' ? 'passphrase' : e.target.name]: newValue, + }); + } else { + this.setState({ + [e.target.name === 'passphraseTextarea' ? 'passphrase' : e.target.name]: e.target.value, + }); + } + } + + resizeLoginTextarea() { + // auto-size textarea + setTimeout(() => { + if (this.state.seedInputVisibility) { + document.querySelector('#passphraseTextarea').style.height = '1px'; + document.querySelector('#passphraseTextarea').style.height = `${(15 + document.querySelector('#passphraseTextarea').scrollHeight)}px`; + } + }, 100); + } + + _copyCoinAddress(address) { + Store.dispatch(copyCoinAddress(address)); + } + + _getBip39Keys() { + shepherdElectrumBip39Keys(this.state.passphrase, this.state.match) + .then((res) => { + this.setState({ + keys: res.result.priv ? res.result : 'empty', + }); + }); + } + + updateInput(e) { + this.setState({ + [e.target.name]: e.target.value, + }); + } + + render() { + return ( +