Hooked up RPC calls + more UI changes.

This commit is contained in:
Mikunj Varsani 2019-06-13 11:52:38 +10:00
parent 247444b382
commit dd271a2130
9 changed files with 346 additions and 80 deletions

View File

@ -252,6 +252,14 @@ export class WalletRPC {
this.transfer(params.password, params.amount, params.address, params.payment_id, params.priority, params.note || "", params.address_book)
break
case "prove_transaction":
this.proveTransaction(params.txid, params.address, params.message)
break
case "check_transaction":
this.checkTransactionProof(params.signature, params.txid, params.address, params.message)
break
case "add_address_book":
this.addAddressBook(params.address, params.payment_id,
params.description, params.name, params.starred,
@ -975,6 +983,83 @@ export class WalletRPC {
})
}
proveTransaction (txid, address, message) {
const _address = address.trim() === "" ? null : address
const _message = message.trim() === "" ? null : message
const rpc_endpoint = _address ? "get_tx_proof" : "get_spend_proof"
const params = {
txid,
address: _address,
message: _message
}
this.sendGateway("set_prove_transaction_status", {
code: 1,
message: ""
})
this.sendRPC(rpc_endpoint, params).then((data) => {
if (data.hasOwnProperty("error")) {
let error = data.error.message.charAt(0).toUpperCase() + data.error.message.slice(1)
this.sendGateway("set_prove_transaction_status", {
code: -1,
message: error,
state: {}
})
return
}
this.sendGateway("set_prove_transaction_status", {
code: 0,
message: "",
state: {
txid,
...(data.result || {})
}
})
})
}
checkTransactionProof (signature, txid, address, message) {
const _address = address.trim() === "" ? null : address
const _message = message.trim() === "" ? null : message
const rpc_endpoint = _address ? "check_tx_proof" : "check_spend_proof"
const params = {
txid,
signature,
address: _address,
message: _message
}
this.sendGateway("set_check_transaction_status", {
code: 1,
message: ""
})
this.sendRPC(rpc_endpoint, params).then((data) => {
if (data.hasOwnProperty("error")) {
let error = data.error.message.charAt(0).toUpperCase() + data.error.message.slice(1)
this.sendGateway("set_check_transaction_status", {
code: -1,
message: error,
state: {}
})
return
}
this.sendGateway("set_check_transaction_status", {
code: 0,
message: "",
state: {
txid,
...(data.result || {})
}
})
})
}
rescanBlockchain () {
this.sendRPC("rescan_blockchain")
}

View File

@ -2,42 +2,66 @@
<div class="check-transaction">
<div class="q-pa-md">
<div class="q-mb-lg description">
{{ $t('strings.checkTransactionDescription') }}
{{ $t('strings.checkTransaction.description') }}
</div>
<div>
<LokiField :label="$t('fieldLabels.transactionId')" :error="$v.txid.$error">
<q-input v-model="txid"
:dark="theme=='dark'"
:placeholder="$t('placeholders.pasteTransactionId')"
@blur="$v.txid.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.address')" :error="$v.address.$error" optional>
<q-input v-model="address"
:dark="theme=='dark'"
:placeholder="$t('placeholders.recipientWalletAddress')"
@blur="$v.address.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.message')" optional>
<q-input v-model="message"
:dark="theme=='dark'"
:placeholder="$t('placeholders.proveOptionalMessage')"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.signature')" :error="$v.signature.$error">
<q-input v-model="signature"
:dark="theme=='dark'"
:placeholder="$t('placeholders.pasteTransactionProof')"
hide-underline
/>
</LokiField>
<q-field class="buttons q-pt-sm">
<q-btn color="primary" @click="check" :label="$t('buttons.check')" />
<q-btn color="secondary" @click="clear" :label="$t('buttons.clear')" v-if="canClear"/>
</q-field>
</div>
<div v-if="status.state.txid">
<div class="q-mb-sm">
<div class="title">{{ $t('strings.transactionID') }}</div>
<div>{{ status.state.txid }}</div>
</div>
<div class="q-mb-sm">
<div class="title">{{ $t('strings.checkTransaction.infoTitles.validTransaction') }}</div>
<div :class="status.state.good ? 'good' : 'bad'">{{ validTransaction }}</div>
</div>
<div class="q-mb-sm" v-if="status.state.received != null">
<div class="title">{{ $t('strings.checkTransaction.infoTitles.received') }}</div>
<div><FormatLoki :amount="status.state.received" raw-value /></div>
</div>
<div class="q-mb-sm" v-if="status.state.in_pool != null">
<div class="title">{{ $t('strings.checkTransaction.infoTitles.inPool') }}</div>
<div>{{ status.state.in_pool }}</div>
</div>
<div class="q-mb-sm" v-if="status.state.confirmations != null">
<div class="title">{{ $t('strings.checkTransaction.infoTitles.confirmations') }}</div>
<div>{{ status.state.confirmations }}</div>
</div>
</div>
<LokiField :label="$t('fieldLabels.transactionId')" :error="$v.transactionId.$error">
<q-input v-model="transactionId"
:dark="theme=='dark'"
:placeholder="$t('placeholders.pasteTransactionId')"
@blur="$v.transactionId.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.address')" :error="$v.address.$error" optional>
<q-input v-model="address"
:dark="theme=='dark'"
:placeholder="$t('placeholders.recipientWalletAddress')"
@blur="$v.address.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.message')" optional>
<q-input v-model="message"
:dark="theme=='dark'"
:placeholder="$t('placeholders.proveOptionalMessage')"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.signature')" :error="$v.signature.$error">
<q-input v-model="signature"
:dark="theme=='dark'"
:placeholder="$t('placeholders.pasteTransactionProof')"
hide-underline
/>
</LokiField>
<q-field class="buttons q-pt-sm">
<q-btn color="primary" @click="check" :label="$t('buttons.check')" />
<q-btn color="secondary" @click="clear" :label="$t('buttons.clear')" v-if="canClear"/>
</q-field>
</div>
</div>
</template>
@ -46,26 +70,33 @@
import { mapState } from "vuex"
import { required } from "vuelidate/lib/validators"
import { address } from "src/validators/common"
import { i18n } from "plugins/i18n"
import LokiField from "components/loki_field"
import FormatLoki from "components/format_loki"
export default {
name: "CheckTransaction",
computed: mapState({
theme: state => state.gateway.app.config.appearance.theme,
status: state => state.gateway.check_transaction_status,
canClear () {
return this.transactionId !== "" || this.address !== "" || this.message !== "" || this.signature != ""
return this.txid !== "" || this.address !== "" || this.message !== "" || this.signature != ""
},
validTransaction () {
let key = this.status.state.good ? "yes" : "no"
return i18n.t(`strings.checkTransaction.validTransaction.${key}`)
}
}),
data() {
return {
transactionId: "",
txid: "",
address: "",
message: "",
signature: ""
}
},
validations: {
transactionId: { required },
txid: { required },
address: {
isAddress(value) {
if (value === '') return true
@ -79,13 +110,30 @@ export default {
},
signature: { required }
},
watch: {
status: {
handler(val, old){
if(val.code == old.code) return
switch(this.status.code) {
case -1:
this.$q.notify({
type: "negative",
timeout: 3000,
message: this.status.message
})
break;
}
},
deep: true
},
},
methods: {
check() {
this.$v.transactionId.$touch()
this.$v.txid.$touch()
this.$v.address.$touch()
this.$v.signature.$touch()
if (this.$v.transactionId.$error) {
if (this.$v.txid.$error) {
this.$q.notify({
type: "negative",
timeout: 1000,
@ -112,10 +160,15 @@ export default {
return
}
this.$gateway.send("wallet", "check_transaction", {
txid: this.txid,
signature: this.signature,
address: this.address,
message: this.message
})
},
clear() {
this.transactionId = ""
this.txid = ""
this.address = ""
this.message = ""
this.signature = ""
@ -123,7 +176,8 @@ export default {
}
},
components: {
LokiField
LokiField,
FormatLoki
}
}
</script>

View File

@ -4,33 +4,45 @@
<div class="q-mb-lg description">
{{ $t('strings.proveTransactionDescription') }}
</div>
<LokiField :label="$t('fieldLabels.transactionId')" :error="$v.transactionId.$error">
<q-input v-model="transactionId"
:dark="theme=='dark'"
:placeholder="$t('placeholders.pasteTransactionId')"
@blur="$v.transactionId.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.address')" :error="$v.address.$error" optional>
<q-input v-model="address"
:dark="theme=='dark'"
:placeholder="$t('placeholders.recipientWalletAddress')"
@blur="$v.address.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.message')" optional>
<q-input v-model="message"
:dark="theme=='dark'"
:placeholder="$t('placeholders.proveOptionalMessage')"
hide-underline
/>
</LokiField>
<q-field class="buttons q-pt-sm">
<q-btn color="primary" @click="generate" :label="$t('buttons.generate')" />
<q-btn color="secondary" @click="clear" :label="$t('buttons.clear')" v-if="canClear"/>
</q-field>
<div>
<LokiField :label="$t('fieldLabels.transactionId')" :error="$v.txid.$error">
<q-input v-model="txid"
:dark="theme=='dark'"
:placeholder="$t('placeholders.pasteTransactionId')"
@blur="$v.txid.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.address')" :error="$v.address.$error" optional>
<q-input v-model="address"
:dark="theme=='dark'"
:placeholder="$t('placeholders.recipientWalletAddress')"
@blur="$v.address.$touch"
hide-underline
/>
</LokiField>
<LokiField class="q-mt-md" :label="$t('fieldLabels.message')" optional>
<q-input v-model="message"
:dark="theme=='dark'"
:placeholder="$t('placeholders.proveOptionalMessage')"
hide-underline
/>
</LokiField>
<q-field class="buttons q-pt-sm">
<q-btn color="primary" @click="generate" :label="$t('buttons.generate')" />
<q-btn color="secondary" @click="clear" :label="$t('buttons.clear')" v-if="canClear"/>
<q-btn color="secondary" @click="copy" :label="$t('buttons.copySignature')" v-if="status.state.signature"/>
</q-field>
</div>
<div v-if="status.state.signature">
<div class="txid q-mb-sm">
<div class="title">{{ $t('strings.transactionID') }}</div>
<div>{{ status.state.txid }}</div>
</div>
<p class="signature">
{{ status.state.signature }}
</p>
</div>
</div>
</div>
</template>
@ -40,24 +52,26 @@ import { mapState } from "vuex"
import { required } from "vuelidate/lib/validators"
import { address } from "src/validators/common"
import LokiField from "components/loki_field"
import { clipboard } from 'electron';
export default {
name: "ProveTransaction",
computed: mapState({
theme: state => state.gateway.app.config.appearance.theme,
status: state => state.gateway.prove_transaction_status,
canClear () {
return this.transactionId !== "" || this.address !== "" || this.message !== ""
return this.txid !== "" || this.address !== "" || this.message !== ""
}
}),
data() {
return {
transactionId: "",
txid: "",
address: "",
message: "",
}
},
validations: {
transactionId: { required },
txid: { required },
address: {
isAddress(value) {
if (value === '') return true
@ -70,12 +84,29 @@ export default {
}
}
},
watch: {
status: {
handler(val, old){
if(val.code == old.code) return
switch(this.status.code) {
case -1:
this.$q.notify({
type: "negative",
timeout: 3000,
message: this.status.message
})
break;
}
},
deep: true
},
},
methods: {
generate() {
this.$v.transactionId.$touch()
this.$v.txid.$touch()
this.$v.address.$touch()
if (this.$v.transactionId.$error) {
if (this.$v.txid.$error) {
this.$q.notify({
type: "negative",
timeout: 1000,
@ -93,13 +124,25 @@ export default {
return
}
this.$gateway.send("wallet", "prove_transaction", {
txid: this.txid.trim(),
address: this.address.trim(),
message: this.message.trim()
})
},
clear() {
this.transactionId = ""
this.txid = ""
this.address = ""
this.message = ""
this.$v.$reset();
},
copy() {
clipboard.writeText(this.status.state.signature)
this.$q.notify({
type: "positive",
timeout: 1000,
message: this.$t("notification.positive.signatureCopied")
})
}
},
components: {
@ -119,5 +162,13 @@ export default {
margin-left: 8px;
}
}
.signature {
flex: 1;
word-break: break-all;
word-wrap: break-word;
-webkit-user-select: all;
user-select: all;
padding: 8px;
}
}
</style>

View File

@ -597,3 +597,29 @@ footer,
color: $loki-black-50;
}
}
.prove-transaction {
.signature {
background: rgba(0,0,0,0.5);
border: #0a0a0a 1px solid;
border-radius: 2px;
color: #b7b7b7;
}
}
.check-transaction {
.good {
color: #43bd43;
}
.bad {
color: $negative;
}
}
.check-transaction, .prove-transaction {
.title {
color: #b7b7b7;
font-size: 14px;
}
}

View File

@ -148,7 +148,7 @@ export class Gateway extends EventEmitter {
break
}
case "set_snode_status":
case "set_snode_status": {
const data = { ...decrypted_data.data }
// We have multiple nested objects in service_node_status
@ -158,7 +158,27 @@ export class Gateway extends EventEmitter {
this.app.store.commit("gateway/set_snode_status", data)
break
}
case "set_prove_transaction_status": {
const data = { ...decrypted_data.data }
if (data.i18n) {
data.message = this.geti18n(data.i18n)
}
this.app.store.commit("gateway/set_prove_transaction_status", data)
break
}
case "set_check_transaction_status": {
const data = { ...decrypted_data.data }
if (data.i18n) {
data.message = this.geti18n(data.i18n)
}
this.app.store.commit("gateway/set_check_transaction_status", data)
break
}
case "set_old_gui_import_status":
this.app.store.commit("gateway/set_old_gui_import_status", decrypted_data.data)
break

View File

@ -12,6 +12,7 @@ export default {
close: "CLOSE",
contacts: "CONTACTS",
copyAddress: "COPY ADDRESS",
copySignature: "COPY SIGNATURE",
createWallet: "CREATE WALLET",
delete: "DELETE",
edit: "EDIT",
@ -262,6 +263,7 @@ export default {
qrCopied: "QR code copied to clipboard",
registerServiceNodeSuccess: "Successfully registered service node",
sendSuccess: "Transaction successfully sent",
signatureCopied: "Signature copied to clipboard",
stakeSuccess: "Successfully staked",
transactionNotesSaved: "Transaction notes saved"
},
@ -353,7 +355,19 @@ export default {
},
blockHeight: "Height",
transactionConfirmed: "confirmed",
checkTransactionDescription: "Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature.\nFor the case with 'Spend Proof', you don't need to specify the recipient address.",
checkTransaction: {
description: "Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature.\nFor a 'Spend Proof' you dont need to provide the recipient address.",
infoTitles: {
confirmations: "Confirmations",
inPool: "In pool",
validTransaction: "Valid transaction",
received: "Received amount"
},
validTransaction: {
no: "NO",
yes: "YES"
}
},
closing: "Closing",
connectingToBackend: "Connecting to backend",
contribution: "Contribution",

View File

@ -54,7 +54,7 @@
class="large-btn"
:label="$t('buttons.advanced')"
size="md"
icon-right="router"
icon-right="tune"
align="left"
/>
</router-link>

View File

@ -21,3 +21,9 @@ export const set_tx_status = (state, data) => {
export const set_snode_status = (state, data) => {
state.service_node_status = objectAssignDeep.noMutate(state.service_node_status, data)
}
export const set_prove_transaction_status = (state, data) => {
state.prove_transaction_status = data
}
export const set_check_transaction_status = (state, data) => {
state.check_transaction_status = data
}

View File

@ -73,6 +73,16 @@ export default {
sending: false
}
},
prove_transaction_status: {
code: 0,
message: "",
state: {}
},
check_transaction_status: {
code: 0,
message: "",
state: {}
},
daemon: {
info: {
alt_blocks_count: 0,