Skip to content

Commit

Permalink
Merge branch 'master' into mainnet
Browse files Browse the repository at this point in the history
  • Loading branch information
shrpne committed Mar 25, 2020
2 parents 71bdc64 + 5430336 commit a7d66d3
Show file tree
Hide file tree
Showing 38 changed files with 6,435 additions and 13,094 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ module.exports = {
'vue/singleline-html-element-content-newline': 0,
'vue/v-bind-style': 0,
'vue/v-on-style': 0,
'vue/no-unused-vars': 0,
// allow `$value`
'vue/prop-name-casing': 0,
'vue/prop-name-casing': ["warn"],

// VUE RECOMMENDED
'vue/no-v-html': 0,
Expand Down
10 changes: 5 additions & 5 deletions api/gate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import {GATE_API_URL, CHAIN_ID} from '~/assets/variables';

const minterApi = new MinterApi({apiType: 'gate', baseURL: GATE_API_URL, chainId: CHAIN_ID});

export const postTx = new PostTx(minterApi);
export const postTx = PostTx(minterApi);

export const postSignedTx = new PostSignedTx(minterApi);
export const postSignedTx = PostSignedTx(minterApi);

export const getNonce = new GetNonce(minterApi);
export const getNonce = GetNonce(minterApi);

export const ensureNonce = EnsureNonce(minterApi);

export const estimateCoinSell = new EstimateCoinSell(minterApi);
export const estimateCoinSell = EstimateCoinSell(minterApi);

export const estimateCoinBuy = new EstimateCoinBuy(minterApi);
export const estimateCoinBuy = EstimateCoinBuy(minterApi);



1 change: 1 addition & 0 deletions assets/less/include/layout.less
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
@media (min-width: @breakpoint-large-up) {
.u-cell--large--1-2 {width: 50%;}
.u-cell--large--1-3 { width: 33.3333%;}
.u-cell--large--1-4 {width: 25%;}
}
@media (min-width: @breakpoint-xlarge-up) {
.u-cell--xlarge--1-4 { width: 25%;}
Expand Down
2 changes: 1 addition & 1 deletion assets/less/include/modal.less
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
&::before {transform: rotate(45deg);}
&::after {transform: rotate(-45deg);}
}
.modal__container {max-width: 450px; margin: auto; text-align: center; padding-bottom: @modal-padding-vertical;}
.modal__container {max-width: 450px; width: 100%; margin: auto; text-align: center; padding-bottom: @modal-padding-vertical;}
.modal__title {margin-bottom: 10px;}
.modal__text {max-width: 480px; margin: 0 auto 20px; &:last-child {margin-bottom: 0;}}

Expand Down
54 changes: 15 additions & 39 deletions components/CheckIssueForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import {pretty} from '~/assets/utils';
import {NETWORK, TESTNET} from '~/assets/variables';
import Modal from '~/components/common/Modal';
import InputUppercase from '~/components/common/InputUppercase';
import FieldCoin from '~/components/common/FieldCoin.vue';
import InputMaskedAmount from '~/components/common/InputMaskedAmount';
import InputMaskedInteger from '~/components/common/InputMaskedInteger';
import ButtonCopyIcon from '~/components/common/ButtonCopyIcon';
Expand All @@ -25,7 +25,7 @@
QrcodeVue,
InlineSvg,
Modal,
InputUppercase,
FieldCoin,
InputMaskedAmount,
InputMaskedInteger,
ButtonCopyIcon,
Expand Down Expand Up @@ -185,23 +185,12 @@
<div class="form-field__help">{{ $td('Check\'s unique ID. Used for issuing several identical checks.', 'form.checks-issue-nonce-help') }}</div>
</div>
<div class="u-cell u-cell--medium--1-3 u-cell--xlarge--1-4">
<label class="form-field" :class="{'is-error': $v.form.coinSymbol.$error}">
<select class="form-field__input form-field__input--select" v-check-empty
v-model="form.coinSymbol"
@blur="$v.form.coinSymbol.$touch()"
v-if="balance && balance.length"
>
<option v-for="coin in balance" :key="coin.coin" :value="coin.coin">
{{ coin.coin | uppercase }} ({{ coin.amount | pretty }})
</option>
</select>
<InputUppercase class="form-field__input" type="text" v-check-empty
v-model.trim="form.coinSymbol"
@blur="$v.form.coinSymbol.$touch()"
v-else
/>
<span class="form-field__label">{{ $td('Coin', 'form.coin') }}</span>
</label>
<FieldCoin
v-model="form.coinSymbol"
:$value="$v.form.coinSymbol"
:label="$td('Coin', 'form.coin')"
:coin-list="balance"
/>
<span class="form-field__error" v-if="$v.form.coinSymbol.$dirty && !$v.form.coinSymbol.required">{{ $td('Enter coin symbol', 'form.coin-error-required') }}</span>
<span class="form-field__error" v-else-if="$v.form.coinSymbol.$dirty && !$v.form.coinSymbol.minLength">{{ $td('Min 3 letters', 'form.coin-error-min') }}</span>
<span class="form-field__error" v-else-if="$v.form.coinSymbol.$dirty && !$v.form.coinSymbol.maxLength">{{ $td('Max 10 letters', 'form.coin-error-max') }}</span>
Expand All @@ -227,25 +216,12 @@
<span class="form-field__error" v-if="$v.form.password.$dirty && !$v.form.password.required">{{ $td('Enter password', 'form.checks-issue-pass-error-required') }}</span>
</div>
<div class="u-cell u-cell--medium--1-3 u-cell--xlarge--1-4">
<label class="form-field" :class="{'is-error': $v.form.feeCoinSymbol.$error}">
<select class="form-field__input form-field__input--select is-not-empty"
v-model="form.feeCoinSymbol"
v-if="balance && balance.length"
>
<!--
<option :value="''">{{ fee.isBaseCoinEnough ? $td('Base coin', 'form.wallet-send-fee-base') : $td('Same as coin to send', 'form.wallet-send-fee-same') }}</option>
-->
<option v-for="coin in balance" :key="coin.coin" :value="coin.coin">
{{ coin.coin | uppercase }} ({{ coin.amount | pretty }})
</option>
</select>
<InputUppercase class="form-field__input" type="text" v-check-empty
v-model.trim="form.feeCoinSymbol"
@blur="$v.form.feeCoinSymbol.$touch()"
v-else
/>
<span class="form-field__label">{{ $td('Coin to pay fee', 'form.fee') }}</span>
</label>
<FieldCoin
v-model="form.feeCoinSymbol"
:$value="$v.form.feeCoinSymbol"
:label="$td('Coin to pay fee', 'form.fee')"
:coin-list="balance"
/>
<span class="form-field__error" v-if="$v.form.feeCoinSymbol.$dirty && !$v.form.feeCoinSymbol.minLength">{{ $td('Min 3 letters', 'form.coin-error-min') }}</span>
<span class="form-field__error" v-else-if="$v.form.feeCoinSymbol.$dirty && !$v.form.feeCoinSymbol.maxLength">{{ $td('Max 10 letters', 'form.coin-error-max') }}</span>
<!--
Expand Down Expand Up @@ -287,7 +263,7 @@
<dd class="u-select-all">{{ password }}</dd>

<dt>
{{ $td('Link to redeem.', 'form.checks-issue-result-link') }} <br>
{{ $td('Link to redeem:', 'form.checks-issue-result-link') }} <br>
<span class="u-emoji">⚠️</span> {{ $td('Warning! Password included in the link. Send the link only directly to the recipient.' , 'form.checks-issue-result-link-warning') }}
</dt>
<dd class="u-icon-wrap">
Expand Down
160 changes: 26 additions & 134 deletions components/CheckRedeemForm.vue
Original file line number Diff line number Diff line change
@@ -1,44 +1,28 @@
<script>
import QrcodeVue from 'qrcode.vue';
import {validationMixin} from 'vuelidate';
import required from 'vuelidate/lib/validators/required';
import minValue from 'vuelidate/lib/validators/minValue';
import {RedeemCheckTxParams} from "minter-js-sdk/src";
import {isValidCheck} from "minterjs-util";
import prepareSignedTx from 'minter-js-sdk/src/tx';
import {postTx} from '~/api/gate';
import {TX_TYPE} from 'minterjs-tx/src/tx-types';
import checkEmpty from '~/assets/v-check-empty';
import {getErrorText} from "~/assets/server-error";
import {getExplorerTxUrl} from "~/assets/utils";
import TxForm from '~/components/common/TxForm.vue';
import FieldQr from '~/components/common/FieldQr';
import ButtonCopyIcon from '~/components/common/ButtonCopyIcon';
import Loader from '~/components/common/Loader';
export default {
TX_TYPE,
components: {
QrcodeVue,
TxForm,
FieldQr,
ButtonCopyIcon,
Loader,
},
directives: {
checkEmpty,
},
filters: {
uppercase: (value) => value ? value.toUpperCase() : value,
},
mixins: [validationMixin],
data() {
return {
isFormSending: false,
serverError: '',
serverSuccess: '',
form: {
check: '',
password: '',
nonce: '',
},
signedTx: null,
};
},
validations() {
Expand All @@ -52,90 +36,30 @@
},
};
if (this.$store.getters.isOfflineMode) {
form.nonce = {
required,
minValue: minValue(1),
};
}
return {form};
},
methods: {
submit() {
if (this.$store.getters.isOfflineMode) {
this.generateTx();
} else {
this.postTx();
}
},
generateTx() {
if (this.$v.$invalid) {
this.$v.$touch();
return;
}
this.signedTx = null;
this.serverError = '';
this.serverSuccess = '';
this.signedTx = prepareSignedTx(new RedeemCheckTxParams({
privateKey: this.$store.getters.privateKey,
chainId: this.$store.getters.CHAIN_ID,
...this.form,
}), {privateKey: this.$store.getters.privateKey}).serialize().toString('hex');
this.clearForm();
},
postTx() {
if (this.isFormSending) {
return;
}
if (this.$v.$invalid) {
this.$v.$touch();
return;
}
this.isFormSending = true;
this.signedTx = null;
this.serverError = '';
this.serverSuccess = '';
this.$store.dispatch('FETCH_ADDRESS_ENCRYPTED')
.then(() => {
postTx(new RedeemCheckTxParams({
privateKey: this.$store.getters.privateKey,
...this.form,
})).then((txHash) => {
this.isFormSending = false;
this.serverSuccess = txHash;
this.clearForm();
}).catch((error) => {
console.log(error);
this.isFormSending = false;
this.serverError = getErrorText(error);
});
})
.catch((error) => {
this.isFormSending = false;
this.serverError = getErrorText(error);
});
},
clearForm() {
this.form.check = '';
this.form.password = '';
if (this.form.nonce && this.$store.getters.isOfflineMode) {
this.form.nonce += 1;
} else {
this.form.nonce = '';
}
this.$v.$reset();
},
getExplorerTxUrl,
},
};
</script>

<template>
<form class="panel__section" novalidate @submit.prevent="submit">
<div class="u-grid u-grid--small u-grid--vertical-margin--small">
<TxForm :txData="form" :$txData="$v.form" :txType="$options.TX_TYPE.REDEEM_CHECK" @clear-form="clearForm()">
<template v-slot:panel-header>
<h1 class="panel__header-title">
{{ $td('Redeem check', 'checks.redeem-title') }}
</h1>
<p class="panel__header-description">
{{ $td('Claim a check someone has written out to you.', 'checks.redeem-description') }}
</p>
</template>

<template v-slot:default="{fee, addressBalance}">
<div class="u-cell">
<FieldQr v-model.trim="form.check" :$value="$v.form.check" :label="$td('Check', 'form.checks-redeem-check')"/>
<span class="form-field__error" v-if="$v.form.check.$dirty && !$v.form.check.required">{{ $td('Check', 'form.checks-redeem-check-error-required') }}</span>
Expand All @@ -152,49 +76,17 @@
</label>
<span class="form-field__error" v-if="$v.form.password.$dirty && !$v.form.password.required">{{ $td('Enter password', 'form.checks-redeem-password-error-required') }}</span>
</div>
</template>

<!-- Generation -->
<div class="u-cell u-cell--small--1-2" v-if="$store.getters.isOfflineMode">
<FieldQr v-model="form.nonce"
:$value="$v.form.nonce"
:label="$td('Nonce', 'form.checks-issue-nonce')"
:isInteger="true"
/>
<span class="form-field__error" v-if="$v.form.nonce.$error && !$v.form.nonce.required">{{ $td('Enter nonce', 'form.checks-issue-nonce-error-required') }}</span>
<span class="form-field__error" v-else-if="$v.form.nonce.$dirty && !$v.form.nonce.minValue">{{ $td(`Minimum nonce is 1`, 'form.generate-nonce-error-min') }}</span>
<div class="form-field__help">{{ $td('Tx\'s unique ID. Should be: current user\'s tx count + 1', 'form.generate-nonce-help') }}</div>
</div>
<div class="u-cell u-cell--xlarge--1-2" v-if="$store.getters.isOfflineMode">
<button class="button button--main button--full" :class="{'is-disabled': $v.$invalid}">
{{ $td('Generate', 'form.generate-button') }}
</button>
</div>
<template v-slot:submit-title>
{{ $td('Redeem', 'form.checks-redeem-button') }}
</template>

<!-- Controls -->
<div class="u-cell" v-if="!$store.getters.isOfflineMode">
<button class="button button--main button--full" :class="{'is-loading': isFormSending, 'is-disabled': $v.$invalid}">
<span class="button__content">{{ $td('Redeem', 'form.checks-redeem-button') }}</span>
<Loader class="button__loader" :isLoading="true"/>
</button>
<div class="form-field__error" v-if="serverError">{{ serverError }}</div>
</div>
<div class="u-cell" v-if="serverSuccess">
<strong>{{ $td('Tx sent:', 'form.tx-sent') }}</strong> <a class="link--default u-text-break" :href="getExplorerTxUrl(serverSuccess)" target="_blank">{{ serverSuccess }}</a>
</div>

<div class="u-cell u-cell--order-2" v-if="signedTx">
<dl>
<dt>{{ $td('Signed tx:', 'form.generate-result-tx') }}</dt>
<dd class="u-icon-wrap">
<span class="u-select-all u-icon-text">
{{ signedTx }}
</span>
<ButtonCopyIcon class="u-icon--copy--right" :copy-text="signedTx"/>
</dd>
</dl>
<br>
<qrcode-vue :value="signedTx" :size="200" level="L"></qrcode-vue>
</div>
</div>
</form>
<template v-slot:confirm-modal-header>
<h1 class="panel__header-title">
<img class="panel__header-title-icon" :src="`${BASE_URL_PREFIX}/img/icon-feature-check.svg`" alt="" role="presentation" width="40" height="40">
{{ $td('Redeem check', 'checks.redeem-title') }}
</h1>
</template>
</TxForm>
</template>
Loading

0 comments on commit a7d66d3

Please sign in to comment.