inputPass: '请输入密码',
agreeService:'请阅读并同意使用条款。'
},
+ mnemonic:{
+ "title":"备份助记词",
+ "hint":"请牢记助记词,一旦丢失您的资产将无法找回!"
+ },
+ verifyMnemonic:{
+ "title":"验证助记词",
+ "hint":"请按顺序输入助记词,单词中间用空格隔开",
+ },
error:{
- BTM0000: '必填项'
+ BTM0000: '必填项',
+ BTM0001:'请输入助记词',
+ BTM0002:'助记词验证失败,请输入正确助记词。',
},
help: {
title: '帮助',
account.create = function(accountAlias, keyAlias, passwd, context) {
let retPromise = new Promise((resolve, reject) => {
- if(!keyAlias){
+ if (!keyAlias) {
keyAlias = `${accountAlias}-key-${uuid.v4()}`
}
const _bytom = context.bytom.clone();
- bytom.keys
- .createKey(keyAlias, passwd)
- .then(res => {
- _bytom.keychain.keys[keyAlias] = res
- context[Actions.UPDATE_STORED_BYTOM](_bytom).then(() => {
- bytom.accounts
- .createAccountUseServer(res.xpub, accountAlias)
- .then(ret => {
- resolve(ret)
- })
- .catch(error => {
- reject(error)
- })
- })
- .catch(error => {
- reject(error)
- })
+ const res = bytom.keys.createKey(keyAlias, passwd)
+ bytom.accounts.createNewAccount(res.xpub).then(ret => {
+ let resultObj = Object.assign(res, ret)
+ resultObj.alias = accountAlias
+ resultObj.keyAlias = keyAlias
+
+ _bytom.keychain.pairs[accountAlias] = resultObj
+ _bytom.currentAccount = resultObj
- });
+ context[Actions.UPDATE_STORED_BYTOM](_bytom).then(() => {
+ resolve(ret)
+ })
+ .catch(error => {
+ reject(error)
+ })
+ })
})
return retPromise
}
import '@/assets/style.css'
import Vuelidate from "vuelidate";
-
store.dispatch(Actions.LOAD_BYTOM).then(() => {
Vue.use(VueI18n)
const i18n = new VueI18n({
}
},
{
+ path: '/mnemonic',
+ name: 'welcome-mnemonic',
+ meta: { title: '备份助记词' },
+ component: resolve => {
+ require(['@/views/welcome/mnemonic.vue'], resolve)
+ }
+ },
+ {
+ path: '/verify-mnemonic',
+ name: 'welcome-verify-mnemonic',
+ meta: { title: '验证助记词' },
+ component: resolve => {
+ require(['@/views/welcome/verifyMnemonic.vue'], resolve)
+ }
+ },
+ {
path: '/import',
name: 'welcome-import',
meta: { title: '创建账户' },
const bytom = Bytom.fromJson(state.bytom);
bytom.settings.network = network;
account.setupNet(`${network}`)
- account.list().then(accounts => {
- bytom.accountList = accounts;
- if (accounts.length > 0) {
- bytom.currentAccount = accounts[0];
- }
+ bytom.settings.login = true
- bytom.settings.login = true
- bytom.settings.currency = "inCny"
- bytom.settings.netType = ''
- dispatch(Actions.UPDATE_STORED_BYTOM, bytom).then(_bytom => {
- dispatch(Actions.SET_BYTOM, Bytom.fromJson(_bytom));
- resolve();
- })
+ const language = bytom.settings.language
+
+ bytom.settings.currency = language ==='en'?'inUsd':"inCny"
+ bytom.settings.netType = ''
+ dispatch(Actions.UPDATE_STORED_BYTOM, bytom).then(_bytom => {
+ dispatch(Actions.SET_BYTOM, Bytom.fromJson(_bytom));
+ resolve();
})
})
language:state => state.bytom.settings.language,
login:state => state.bytom.settings.login,
currency:state => state.bytom.settings.currency,
- keys: state => state.bytom.keychain.keys,
+ pairs: state => state.bytom.keychain.pairs,
// FOR PROMPTS ONLY
messages:state => state.prompt.data.messages || [],
export default class Keychain {
constructor(){
- this.keys = {};
+ this.pairs = {};
}
static placeholder(){ return new Keychain(); }
static fromJson(json){
let p = Object.assign(this.placeholder(), json);
- if(json.hasOwnProperty('keys')) p.keys = json.keys;
+ if(json.hasOwnProperty('pairs')) p.pairs = json.pairs;
return p;
}
- findIdentity(publicKey){ return Object.values(this.keys).find(id => id.xpub === publicKey); }
+ findIdentity(publicKey){ return Object.values(this.pairs).find(id => id.xpub === publicKey); }
}
import { required, sameAs } from "vuelidate/lib/validators";
-let mainNet = null;
+let testNet = null;
export default {
name: "",
data() {
return {
nets: [],
- selected: mainNet,
+ selected: testNet,
formItem: {
accAlias: "",
passwd1: "",
this[Actions.CREATE_NEW_BYTOM](this.selected.value).then(() =>{
loader.hide();
this.formItem = {};
- this.$router.push('/');
+ this.$router.push('/mnemonic');
});
}).catch(err => {
loader.hide();
}
},
mounted() {
- mainNet = { label: this.$t('main.mainNet'), value: "mainnet" };
- this.nets = [mainNet];
+ testNet = { label: this.$t('main.testNet'), value: "testnet" };
+ this.nets = [testNet];
if (this.net != undefined) {
- if (this.net == "mainnet") {
- this.selected = mainNet;
+ if (this.net == "testnet") {
+ this.selected = testNet;
}
} else {
- this.selected = mainNet;
+ this.selected = testNet;
}
account.setupNet(`${this.selected.value}`);
this.i18n = getLanguage(this.language);
--- /dev/null
+<style scoped>
+
+.header {
+ position: relative;
+ margin:40px 0px 20px;
+ line-height: 37px;
+}
+.header p{
+ font-size: 16px;
+ color: rgba(255,255,255,0.5);
+ padding-top: 5px;
+}
+.container{
+ position: relative;
+ margin-top: 24px;
+}
+ .form-checkbox input{
+ margin-left:0px;
+ }
+ .topbar a{
+ position: fixed;
+ top: 10px;
+ right: 20px;
+ }
+ .topbar a i{
+ font-size: 25px;
+ color: white;
+ }
+ .welcome-title{
+ margin-top: 20px;
+ }
+ .btn-round{
+ padding: 15px 2px;
+ }
+
+ .mnemonic{
+ font-size: 16px;
+ width: 33%;
+ display: inline-block;
+ font-family: Roboto;
+ font-style: normal;
+ font-weight: 500;
+ text-align: center;
+ color: rgba(0, 0, 0, 0.88);
+ margin: 10px 0;
+ }
+
+ .mnemnonic-box{
+ background: #FAFAFA;
+ border: 1px solid #EBEBEB;
+ box-sizing: border-box;
+ border-radius: 8px;
+ word-break: break-all;
+ padding: 10px;
+ margin:12px 0;
+ }
+
+ .hint{
+ font-size: 14px;
+ color: rgba(0, 0, 0, 0.64);
+ }
+</style>
+
+<template>
+ <div>
+ <div class="warp bg-white">
+ <div class="header color-black">
+ <BackButton/>
+ <h1>
+ <div class="welcome-title">{{ $t('mnemonic.title')}}</div>
+ </h1>
+ </div>
+ <div class="divider"></div>
+ <div class="container">
+ <div>
+ <p class="hint">{{ $t('mnemonic.hint')}}</p>
+ <div class="mnemnonic-box">
+ <span class="mnemonic" v-for="n in mnemonic">{{ n }}</span>
+ </div>
+ </div>
+ <div>
+ <div class="btn btn-primary btn-round float-right" @click="$router.push({ name: 'welcome-verify-mnemonic' })"><i class="iconfont icon-right-arrow"></i></div>
+ </div>
+ </div>
+ </div>
+ <Footer/>
+ </div>
+</template>
+
+<script>
+import { getLanguage } from '@/assets/language'
+import { mapActions, mapGetters, mapState } from 'vuex'
+
+export default {
+ name: "",
+ computed: {
+ mnemonic: function () {
+ return this.currentAccount.mnemonic.split(' ')
+ },
+ ...mapState([
+ 'bytom'
+ ]),
+ ...mapGetters([
+ 'currentAccount'
+ ])
+ },
+};
+</script>
--- /dev/null
+<style scoped>
+
+.header {
+ position: relative;
+ margin:40px 0px 20px;
+ line-height: 37px;
+}
+.header p{
+ font-size: 16px;
+ color: rgba(255,255,255,0.5);
+ padding-top: 5px;
+}
+.container{
+ position: relative;
+ margin-top: 24px;
+}
+
+ .container{
+ position: relative;
+ }
+ .form-item{
+ margin: 10px 0;
+ }
+ .topbar a{
+ position: fixed;
+ top: 10px;
+ right: 20px;
+ }
+ .topbar a i{
+ font-size: 25px;
+ color: white;
+ }
+ .welcome-title{
+ margin-top: 20px;
+ }
+ .btn-round{
+ padding: 15px 2px;
+ }
+
+ .textarea{
+ width: calc(100% - 40px);
+ min-height: 213px;
+ background: #FAFAFA;
+ border-radius: 8px;
+ border: none;
+ padding: 20px;
+ }
+</style>
+
+<template>
+ <div>
+ <div class="warp bg-white">
+ <div class="header color-black">
+ <BackButton/>
+ <h1>
+ <div class="welcome-title">{{ $t('verifyMnemonic.title')}}</div>
+ </h1>
+ </div>
+ <div class="divider"></div>
+ <div class="container">
+ <div class="form">
+ <div class="form-item">
+ <div :class="[formItemContent, { 'error': $v.inputMnemonic.$error }]">
+ <textarea type="text"
+ class="textarea"
+ :placeholder="$t('verifyMnemonic.hint')"
+ id="inputMnemonic"
+ name="inputMnemonic"
+ ref="inputMnemonic"
+ v-model="$v.inputMnemonic.$model"
+ autofocus />
+ </div>
+ </div>
+ </div>
+ <div>
+ <div class="btn btn-primary btn-round float-right" @click="verify"><i class="iconfont icon-right-arrow"></i></div>
+ </div>
+ </div>
+ </div>
+ <Footer/>
+ </div>
+</template>
+
+<script>
+import account from "../../models/account";
+import { getLanguage } from '@/assets/language'
+import { mapActions, mapGetters, mapState } from 'vuex'
+import * as Actions from '@/store/constants';
+import { required } from "vuelidate/lib/validators";
+
+
+export default {
+ name: "",
+ data() {
+ return {
+ inputMnemonic:''
+ };
+ },
+ validations: {
+ inputMnemonic: {
+ required,
+ }
+ },
+ computed: {
+ formItemLabel: function () {
+ if (this.i18n == "cn") {
+ return "form-item-label form-item-label-cn";
+ } else if (this.i18n == "en") {
+ return "form-item-label";
+ }
+ return "form-item-label form-item-label-cn";
+ },
+ formItemContent: function () {
+ if (this.i18n == "cn") {
+ return "form-item-content content-cn";
+ } else if (this.i18n == "en") {
+ return "form-item-content content";
+ }
+ return "form-item-label form-item-label-cn";
+ },
+ ...mapState([
+ 'bytom'
+ ]),
+ ...mapGetters([
+ 'currentAccount'
+ ])
+ },
+ props: {
+ i18n: {
+ type: String,
+ default: 'cn',
+ }
+ },
+ methods: {
+ verify: function () {
+ this.$v.$touch();
+ if (this.$v.$invalid) {
+ const inputMnemonic = this.$v.inputMnemonic
+ if (inputMnemonic.$error) {
+
+ this.$toast.error(
+ this.$t("error.BTM0001")
+ );
+ this.$refs['inputMnemonic'].focus();
+ }
+ } else {
+ const formMnemonic = this.inputMnemonic.trim()
+
+ if (formMnemonic !== this.currentAccount.mnemonic) {
+ this.$toast.error(
+ this.$t("error.BTM0002")
+ );
+ return;
+ }
+
+ this.$router.push('/');
+ }
+ },
+ ...mapActions([
+ Actions.CREATE_NEW_BYTOM,
+ Actions.IMPORT_BYTOM,
+ Actions.UPDATE_STORED_BYTOM
+ ])
+ }
+};
+</script>