finish ledger signature
This commit is contained in:
parent
3445a13cdf
commit
fe36d08f35
@ -31,6 +31,7 @@
|
||||
"proposal_description": "Description",
|
||||
"proposal_content": "Content",
|
||||
"proposal_total_deposit": "Total Deposit",
|
||||
"voting_time": "Voting Time",
|
||||
|
||||
"btn_vote": "Vote",
|
||||
"btn_detail": "Detail",
|
||||
|
@ -1,151 +1,23 @@
|
||||
import {
|
||||
Bech32, fromBase64, fromHex, toHex,
|
||||
} from '@cosmjs/encoding'
|
||||
import { sha256 } from '@cosmjs/crypto'
|
||||
import { sha256, stringToPath } from '@cosmjs/crypto'
|
||||
// ledger
|
||||
import TransportWebBLE from '@ledgerhq/hw-transport-web-ble'
|
||||
import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
|
||||
import { SigningStargateClient } from '@cosmjs/stargate'
|
||||
import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'
|
||||
// import Cosmos from '@ledgerhq/hw-app-cosmos'
|
||||
import CosmosApp from 'ledger-cosmos-js'
|
||||
import { LedgerSigner } from '@cosmjs/ledger-amino'
|
||||
import {
|
||||
makeAuthInfoBytes, makeSignBytes, Registry, SignMode,
|
||||
} from '@cosmjs/proto-signing'
|
||||
import { encodeSecp256k1Pubkey, encodeSecp256k1Signature, encodePubkey } from '@cosmjs/amino'
|
||||
import { Uint53 } from '@cosmjs/math'
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
import duration from 'dayjs/plugin/duration'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import localeData from 'dayjs/plugin/localeData'
|
||||
|
||||
const COSMOS_PATH = [44, 118, 0, 0, 0]
|
||||
|
||||
dayjs.extend(localeData)
|
||||
dayjs.extend(duration)
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
export async function connectLedger(transport = 'usb') {
|
||||
const trans = await transport === 'usb' ? TransportWebUSB.create() : TransportWebBLE.create()
|
||||
return new CosmosApp(trans)
|
||||
}
|
||||
|
||||
/* eslint-enable */
|
||||
function unharden(hdPath) {
|
||||
return hdPath.map(n => (n.isHardened() ? n.toNumber() - 2 ** 31 : n.toNumber()))
|
||||
}
|
||||
|
||||
function makeSignDoc(bodyBytes, authInfoBytes, chainId, accountNumber) {
|
||||
return {
|
||||
bodyBytes,
|
||||
authInfoBytes,
|
||||
chainId,
|
||||
accountNumber: Uint53.fromString(String(accountNumber)),
|
||||
}
|
||||
}
|
||||
|
||||
export async function signDirect(signer, signerAddress, messages, fee, memo, { accountNumber, sequence, chainId }) {
|
||||
// const accountFromSigner = (await this.signer.getAccounts()).find(account => account.address === signerAddress)
|
||||
// if (!accountFromSigner) {
|
||||
// throw new Error("Failed to retrieve account from signer");
|
||||
// }
|
||||
const accountFromSigner = await signer.getAddressAndPubKey(COSMOS_PATH, 'cosmos')
|
||||
if (!accountFromSigner) {
|
||||
throw new Error('Failed to retrieve account from signer')
|
||||
}
|
||||
const { pubkey } = accountFromSigner
|
||||
const txBodyEncodeObject = {
|
||||
typeUrl: '/cosmos.tx.v1beta1.TxBody',
|
||||
value: {
|
||||
messages,
|
||||
memo,
|
||||
},
|
||||
}
|
||||
const txBodyBytes = new Registry().encode(txBodyEncodeObject)
|
||||
const gasLimit = Uint53.fromString(String(fee.gas))
|
||||
const authInfoBytes = makeAuthInfoBytes([pubkey], fee.amount, gasLimit, sequence)
|
||||
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber)
|
||||
// const { signature, signed } = await signer.signDirect(signerAddress, signDoc)
|
||||
const signBytes = makeSignBytes(signDoc)
|
||||
const hashedMessage = sha256(signBytes)
|
||||
const signature = await signer.sign(unharden(COSMOS_PATH), hashedMessage)
|
||||
const signatureBytes = new Uint8Array([...signature.r(32), ...signature.s(32)])
|
||||
const stdSignature = encodeSecp256k1Signature(pubkey, signatureBytes)
|
||||
|
||||
return TxRaw.fromPartial({
|
||||
bodyBytes: txBodyBytes,
|
||||
authInfoBytes,
|
||||
signatures: [fromBase64(stdSignature)],
|
||||
})
|
||||
}
|
||||
|
||||
export async function signAmino(signerAddress, messages, fee, memo, { accountNumber, sequence, chainId }) {
|
||||
const accountFromSigner = (await this.signer.getAccounts()).find(account => account.address === signerAddress)
|
||||
if (!accountFromSigner) {
|
||||
throw new Error('Failed to retrieve account from signer')
|
||||
}
|
||||
const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey))
|
||||
const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON
|
||||
const msgs = messages.map(msg => this.aminoTypes.toAmino(msg))
|
||||
const signDoc = makeSignDoc(msgs, fee, chainId, memo, accountNumber, sequence)
|
||||
const { signature, signed } = await this.signer.signAmino(signerAddress, signDoc)
|
||||
const signedTxBody = {
|
||||
messages: signed.msgs.map(msg => this.aminoTypes.fromAmino(msg)),
|
||||
memo: signed.memo,
|
||||
}
|
||||
const signedTxBodyEncodeObject = {
|
||||
typeUrl: '/cosmos.tx.v1beta1.TxBody',
|
||||
value: signedTxBody,
|
||||
}
|
||||
const signedTxBodyBytes = this.registry.encode(signedTxBodyEncodeObject)
|
||||
const signedGasLimit = Number(signed.fee.gas)
|
||||
const signedSequence = Number(signed.sequence)
|
||||
const signedAuthInfoBytes = makeAuthInfoBytes([pubkey], signed.fee.amount, signedGasLimit, signedSequence, signMode)
|
||||
return TxRaw.fromPartial({
|
||||
bodyBytes: signedTxBodyBytes,
|
||||
authInfoBytes: signedAuthInfoBytes,
|
||||
signatures: [fromBase64(signature.signature)],
|
||||
})
|
||||
}
|
||||
|
||||
export async function sign(device, chainId, signerAddress, messages, fee, memo, signerData) {
|
||||
let transport
|
||||
let signer
|
||||
switch (device) {
|
||||
case 'ledgerBle':
|
||||
transport = await TransportWebBLE.create()
|
||||
signer = new LedgerSigner(transport)
|
||||
break
|
||||
case 'ledgerUSB':
|
||||
transport = await TransportWebUSB.create()
|
||||
signer = new LedgerSigner(transport)
|
||||
break
|
||||
case 'keplr':
|
||||
default:
|
||||
if (!window.getOfflineSigner || !window.keplr) {
|
||||
throw new Error('Please install keplr extension')
|
||||
}
|
||||
await window.keplr.enable(chainId)
|
||||
// signer = window.getOfflineSigner(chainId)
|
||||
signer = window.getOfflineSignerOnlyAmino(chainId)
|
||||
}
|
||||
|
||||
// Ensure the address has some tokens to spend
|
||||
const client = await SigningStargateClient.offline(signer)
|
||||
return client.sign(signerAddress, messages, fee, memo, signerData)
|
||||
// return signDirect(signer, signerAddress, messages, fee, memo, signerData)
|
||||
}
|
||||
|
||||
export async function getLedgerAddress(transport = 'blu') {
|
||||
const trans = transport === 'usb' ? await TransportWebUSB.create() : await TransportWebBLE.create()
|
||||
|
||||
trans.setDebugMode(true)
|
||||
const cosmos = new CosmosApp(trans)
|
||||
return cosmos.getAddressAndPubKey(COSMOS_PATH, 'cosmos')
|
||||
}
|
||||
|
||||
export function getLocalObject(name) {
|
||||
const text = localStorage.getItem(name)
|
||||
if (text) {
|
||||
@ -175,6 +47,98 @@ export function setLocalTxHistory(newTx) {
|
||||
return localStorage.setItem('txHistory', JSON.stringify([newTx]))
|
||||
}
|
||||
|
||||
export async function connectLedger(transport = 'usb') {
|
||||
const trans = await transport === 'usb' ? TransportWebUSB.create() : TransportWebBLE.create()
|
||||
return new CosmosApp(trans)
|
||||
}
|
||||
|
||||
export function operatorAddressToAccount(operAddress) {
|
||||
const { prefix, data } = Bech32.decode(operAddress)
|
||||
if (prefix === 'iva') { // handle special cases
|
||||
return Bech32.encode('iaa', data)
|
||||
}
|
||||
if (prefix === 'crocncl') { // handle special cases
|
||||
return Bech32.encode('cro', data)
|
||||
}
|
||||
return Bech32.encode(prefix.replace('valoper', ''), data)
|
||||
}
|
||||
|
||||
// TODO, not tested
|
||||
export function pubkeyToAccountAddress(pubkey, prefix) {
|
||||
return Bech32.encode(prefix, pubkey, 40)
|
||||
}
|
||||
|
||||
export function addressDecode(address) {
|
||||
return Bech32.decode(address)
|
||||
}
|
||||
|
||||
export function addressEnCode(prefix, pubkey) {
|
||||
return Bech32.encode(prefix, pubkey)
|
||||
}
|
||||
|
||||
export function consensusPubkeyToHexAddress(consensusPubkey) {
|
||||
let raw = null
|
||||
if (typeof consensusPubkey === 'object') {
|
||||
raw = toHex(fromBase64(consensusPubkey.value))
|
||||
} else {
|
||||
raw = toHex(Bech32.decode(consensusPubkey).data).toUpperCase().replace('1624DE6420', '')
|
||||
}
|
||||
const address = toHex(sha256(fromHex(raw))).slice(0, 40).toUpperCase()
|
||||
return address
|
||||
}
|
||||
|
||||
function toSignAddress(addr) {
|
||||
const { data } = addressDecode(addr)
|
||||
return addressEnCode('cosmos', data)
|
||||
}
|
||||
|
||||
function getHdPath(address) {
|
||||
let hdPath = "m/44'/118/0'/0/0"
|
||||
Object.values(getLocalAccounts()).forEach(item => {
|
||||
const curr = item.address.find(i => i.addr === address)
|
||||
if (curr && curr.hdpath) {
|
||||
hdPath = curr.hdpath
|
||||
}
|
||||
})
|
||||
// return [44, 118, 0, 0, 0]
|
||||
// m/0'/1/2'/2/1000000000
|
||||
return stringToPath(hdPath)
|
||||
}
|
||||
|
||||
export async function sign(device, chainId, signerAddress, messages, fee, memo, signerData) {
|
||||
let transport
|
||||
let signer
|
||||
switch (device) {
|
||||
case 'ledgerBle':
|
||||
transport = await TransportWebBLE.create()
|
||||
signer = new LedgerSigner(transport, { hdPaths: [getHdPath(signerAddress)] })
|
||||
break
|
||||
case 'ledgerUSB':
|
||||
transport = await TransportWebUSB.create()
|
||||
signer = new LedgerSigner(transport, { hdPaths: [getHdPath(signerAddress)] })
|
||||
break
|
||||
case 'keplr':
|
||||
default:
|
||||
if (!window.getOfflineSigner || !window.keplr) {
|
||||
throw new Error('Please install keplr extension')
|
||||
}
|
||||
await window.keplr.enable(chainId)
|
||||
// signer = window.getOfflineSigner(chainId)
|
||||
signer = window.getOfflineSignerOnlyAmino(chainId)
|
||||
}
|
||||
|
||||
// Ensure the address has some tokens to spend
|
||||
const client = await SigningStargateClient.offline(signer)
|
||||
return client.signAmino(toSignAddress(signerAddress), messages, fee, memo, signerData)
|
||||
// return signDirect(signer, signerAddress, messages, fee, memo, signerData)
|
||||
}
|
||||
|
||||
export async function getLedgerAddress(transport = 'blu', hdPath = "m/44'/118/0'/0/0") {
|
||||
const trans = transport === 'usb' ? await TransportWebUSB.create() : await TransportWebBLE.create()
|
||||
const signer = new LedgerSigner(trans, { hdPaths: [stringToPath(hdPath)] })
|
||||
return signer.getAccounts()
|
||||
}
|
||||
|
||||
export function toDuration(value) {
|
||||
return dayjs.duration(value).humanize()
|
||||
}
|
||||
@ -293,41 +257,6 @@ export function tokenFormatter(tokens) {
|
||||
return formatToken(tokens)
|
||||
}
|
||||
|
||||
export function operatorAddressToAccount(operAddress) {
|
||||
const { prefix, data } = Bech32.decode(operAddress)
|
||||
if (prefix === 'iva') { // handle special cases
|
||||
return Bech32.encode('iaa', data)
|
||||
}
|
||||
if (prefix === 'crocncl') { // handle special cases
|
||||
return Bech32.encode('cro', data)
|
||||
}
|
||||
return Bech32.encode(prefix.replace('valoper', ''), data)
|
||||
}
|
||||
|
||||
// TODO, not tested
|
||||
export function pubkeyToAccountAddress(pubkey, prefix) {
|
||||
return Bech32.encode(prefix, pubkey, 40)
|
||||
}
|
||||
|
||||
export function addressDecode(address) {
|
||||
return Bech32.decode(address)
|
||||
}
|
||||
|
||||
export function addressEnCode(prefix, pubkey) {
|
||||
return Bech32.encode(prefix, pubkey)
|
||||
}
|
||||
|
||||
export function consensusPubkeyToHexAddress(consensusPubkey) {
|
||||
let raw = null
|
||||
if (typeof consensusPubkey === 'object') {
|
||||
raw = toHex(fromBase64(consensusPubkey.value))
|
||||
} else {
|
||||
raw = toHex(Bech32.decode(consensusPubkey).data).toUpperCase().replace('1624DE6420', '')
|
||||
}
|
||||
const address = toHex(sha256(fromHex(raw))).slice(0, 40).toUpperCase()
|
||||
return address
|
||||
}
|
||||
|
||||
export function getCachedValidators(chainName) {
|
||||
const locals = localStorage.getItem(`validators-${chainName}`)
|
||||
return locals
|
||||
|
@ -102,13 +102,20 @@
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-input-group>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-form-input v-model="fee" />
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="feeDenom"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
>
|
||||
@ -120,9 +127,9 @@
|
||||
{{ item.denom }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -171,12 +178,11 @@
|
||||
>
|
||||
Keplr
|
||||
</b-form-radio>
|
||||
<!-- <b-form-radio
|
||||
<b-form-radio
|
||||
v-model="wallet"
|
||||
name="wallet"
|
||||
value="ledgerUSB"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (USB)
|
||||
</b-form-radio>
|
||||
@ -185,10 +191,9 @@
|
||||
name="wallet"
|
||||
value="ledgerBle"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (Bluetooth)
|
||||
</b-form-radio> -->
|
||||
</b-form-radio>
|
||||
</b-form-radio-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
@ -262,7 +267,7 @@ export default {
|
||||
balance: [],
|
||||
delegations: [],
|
||||
memo: '',
|
||||
fee: 800,
|
||||
fee: '800',
|
||||
feeDenom: '',
|
||||
wallet: 'keplr',
|
||||
error: null,
|
||||
|
@ -117,13 +117,20 @@
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-input-group>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-form-input v-model="fee" />
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="feeDenom"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
>
|
||||
@ -135,9 +142,9 @@
|
||||
{{ item.denom }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -186,12 +193,11 @@
|
||||
>
|
||||
Keplr
|
||||
</b-form-radio>
|
||||
<!-- <b-form-radio
|
||||
<b-form-radio
|
||||
v-model="wallet"
|
||||
name="wallet"
|
||||
value="ledgerUSB"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (USB)
|
||||
</b-form-radio>
|
||||
@ -200,10 +206,9 @@
|
||||
name="wallet"
|
||||
value="ledgerBle"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (Bluetooth)
|
||||
</b-form-radio> -->
|
||||
</b-form-radio>
|
||||
</b-form-radio-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
@ -278,7 +283,7 @@ export default {
|
||||
balance: [],
|
||||
delegations: [],
|
||||
memo: '',
|
||||
fee: 800,
|
||||
fee: '800',
|
||||
feeDenom: '',
|
||||
wallet: 'keplr',
|
||||
error: null,
|
||||
|
@ -129,13 +129,20 @@
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-input-group>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-form-input v-model="fee" />
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="feeDenom"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
>
|
||||
@ -147,9 +154,9 @@
|
||||
{{ item.denom }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -198,12 +205,11 @@
|
||||
>
|
||||
Keplr
|
||||
</b-form-radio>
|
||||
<!-- <b-form-radio
|
||||
<b-form-radio
|
||||
v-model="wallet"
|
||||
name="wallet"
|
||||
value="ledgerUSB"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (USB)
|
||||
</b-form-radio>
|
||||
@ -212,10 +218,9 @@
|
||||
name="wallet"
|
||||
value="ledgerBle"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (Bluetooth)
|
||||
</b-form-radio> -->
|
||||
</b-form-radio>
|
||||
</b-form-radio-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
@ -283,7 +288,7 @@ export default {
|
||||
amount: null,
|
||||
memo: '',
|
||||
recipient: null,
|
||||
fee: 800,
|
||||
fee: '800',
|
||||
feeDenom: '',
|
||||
wallet: 'keplr',
|
||||
error: null,
|
||||
|
@ -102,13 +102,20 @@
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-input-group>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-form-input v-model="fee" />
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="feeDenom"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
>
|
||||
@ -120,9 +127,9 @@
|
||||
{{ item.denom }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -171,12 +178,11 @@
|
||||
>
|
||||
Keplr
|
||||
</b-form-radio>
|
||||
<!-- <b-form-radio
|
||||
<b-form-radio
|
||||
v-model="wallet"
|
||||
name="wallet"
|
||||
value="ledgerUSB"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (USB)
|
||||
</b-form-radio>
|
||||
@ -185,10 +191,9 @@
|
||||
name="wallet"
|
||||
value="ledgerBle"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (Bluetooth)
|
||||
</b-form-radio> -->
|
||||
</b-form-radio>
|
||||
</b-form-radio-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
@ -262,7 +267,7 @@ export default {
|
||||
balance: [],
|
||||
delegations: [],
|
||||
memo: '',
|
||||
fee: 800,
|
||||
fee: '800',
|
||||
feeDenom: '',
|
||||
wallet: 'keplr',
|
||||
error: null,
|
||||
|
@ -92,13 +92,20 @@
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-input-group>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-form-input v-model="fee" />
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="feeDenom"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
>
|
||||
@ -110,9 +117,9 @@
|
||||
{{ item.denom }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -161,12 +168,11 @@
|
||||
>
|
||||
Keplr
|
||||
</b-form-radio>
|
||||
<!-- <b-form-radio
|
||||
<b-form-radio
|
||||
v-model="wallet"
|
||||
name="wallet"
|
||||
value="ledgerUSB"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (USB)
|
||||
</b-form-radio>
|
||||
@ -175,10 +181,9 @@
|
||||
name="wallet"
|
||||
value="ledgerBle"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (Bluetooth)
|
||||
</b-form-radio> -->
|
||||
</b-form-radio>
|
||||
</b-form-radio-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
@ -248,7 +253,7 @@ export default {
|
||||
selectedChain: '',
|
||||
balance: [],
|
||||
memo: '',
|
||||
fee: null,
|
||||
fee: '',
|
||||
feeDenom: '',
|
||||
wallet: 'keplr',
|
||||
error: null,
|
||||
|
@ -44,13 +44,20 @@
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-input-group>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-form-input v-model="fee" />
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="feeDenom"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
>
|
||||
@ -62,9 +69,9 @@
|
||||
{{ item.denom }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -113,12 +120,11 @@
|
||||
>
|
||||
Keplr
|
||||
</b-form-radio>
|
||||
<!-- <b-form-radio
|
||||
<b-form-radio
|
||||
v-model="wallet"
|
||||
name="wallet"
|
||||
value="ledgerUSB"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (USB)
|
||||
</b-form-radio>
|
||||
@ -127,10 +133,9 @@
|
||||
name="wallet"
|
||||
value="ledgerBle"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (Bluetooth)
|
||||
</b-form-radio> -->
|
||||
</b-form-radio>
|
||||
</b-form-radio-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
@ -199,7 +204,7 @@ export default {
|
||||
balance: [],
|
||||
delegations: [],
|
||||
memo: '',
|
||||
fee: 800,
|
||||
fee: '800',
|
||||
feeDenom: '',
|
||||
wallet: 'keplr',
|
||||
error: null,
|
||||
|
@ -44,13 +44,20 @@
|
||||
label="Fee"
|
||||
label-for="Fee"
|
||||
>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="fee"
|
||||
>
|
||||
<b-input-group>
|
||||
<b-input-group>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required|integer"
|
||||
name="fee"
|
||||
>
|
||||
<b-form-input v-model="fee" />
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<validation-provider
|
||||
v-slot="{ errors }"
|
||||
rules="required"
|
||||
name="feeDenom"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="feeDenom"
|
||||
>
|
||||
@ -62,9 +69,9 @@
|
||||
{{ item.denom }}
|
||||
</b-form-select-option>
|
||||
</b-form-select>
|
||||
</b-input-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -113,12 +120,11 @@
|
||||
>
|
||||
Keplr
|
||||
</b-form-radio>
|
||||
<!-- <b-form-radio
|
||||
<b-form-radio
|
||||
v-model="wallet"
|
||||
name="wallet"
|
||||
value="ledgerUSB"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (USB)
|
||||
</b-form-radio>
|
||||
@ -127,10 +133,9 @@
|
||||
name="wallet"
|
||||
value="ledgerBle"
|
||||
class="mb-1 mt-1"
|
||||
disabled
|
||||
>
|
||||
Ledger (Bluetooth)
|
||||
</b-form-radio> -->
|
||||
</b-form-radio>
|
||||
</b-form-radio-group>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
@ -154,7 +159,7 @@ import {
|
||||
required, email, url, between, alpha, integer, password, min, digits, alphaDash, length,
|
||||
} from '@validations'
|
||||
import {
|
||||
formatToken, getLocalAccounts, getLocalChains, setLocalTxHistory, sign, timeIn,
|
||||
formatToken, getLocalAccounts, getLocalChains, sign, timeIn, setLocalTxHistory,
|
||||
} from '@/libs/data'
|
||||
import chainAPI from '@/libs/fetch'
|
||||
import ToastificationContent from '@core/components/toastification/ToastificationContent.vue'
|
||||
@ -195,7 +200,7 @@ export default {
|
||||
balance: [],
|
||||
delegations: [],
|
||||
memo: '',
|
||||
fee: 800,
|
||||
fee: '800',
|
||||
feeDenom: '',
|
||||
wallet: 'keplr',
|
||||
error: null,
|
||||
|
@ -100,7 +100,9 @@
|
||||
</b-card-body>
|
||||
</b-card>
|
||||
|
||||
<b-card>
|
||||
<b-card
|
||||
v-if="delegations"
|
||||
>
|
||||
<b-card-header class="pt-0 pl-0 pr-0">
|
||||
<b-card-title>Delegation</b-card-title>
|
||||
<div>
|
||||
|
@ -79,6 +79,29 @@
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
<b-col
|
||||
v-if="device.startsWith('ledger')"
|
||||
md="12"
|
||||
>
|
||||
<b-form-group
|
||||
label="HD Path"
|
||||
label-for="hdpath"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
name="HD Path"
|
||||
rules="required"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="hdpath"
|
||||
class="mt-1"
|
||||
name="hdpath"
|
||||
placeholder="m/44'/118/0'/0/0"
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</validation-observer>
|
||||
</tab-content>
|
||||
@ -113,6 +136,29 @@
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
<b-col
|
||||
v-if="accounts"
|
||||
md="12"
|
||||
>
|
||||
<b-form-group
|
||||
label="Public Key"
|
||||
label-for="ir"
|
||||
>
|
||||
<validation-provider
|
||||
#default="{ errors }"
|
||||
name="Public Key"
|
||||
rules="required"
|
||||
>
|
||||
<b-form-input
|
||||
id="ir"
|
||||
:value="formatPubkey(accounts.pubkey)"
|
||||
readonly
|
||||
:state="errors.length > 0 ? false:null"
|
||||
/>
|
||||
<small class="text-danger">{{ errors[0] }}</small>
|
||||
</validation-provider>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
<b-col md="12">
|
||||
<b-form-group
|
||||
label="Import Address For Chains:"
|
||||
@ -216,6 +262,7 @@ import {
|
||||
import { required } from '@validations'
|
||||
import store from '@/store'
|
||||
import { addressDecode, addressEnCode, getLedgerAddress } from '@/libs/data'
|
||||
import { toHex } from '@cosmjs/encoding'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -241,6 +288,7 @@ export default {
|
||||
debug: '',
|
||||
device: 'keplr',
|
||||
address: '',
|
||||
hdpath: "m/44'/118/0'/0/0",
|
||||
name: '',
|
||||
options: {},
|
||||
required,
|
||||
@ -255,13 +303,17 @@ export default {
|
||||
},
|
||||
|
||||
addresses() {
|
||||
if (!this.accounts) return []
|
||||
const { data } = addressDecode(this.accounts.address)
|
||||
return this.selected.map(x => {
|
||||
const { logo, addr_prefix } = this.chains[x]
|
||||
const addr = addressEnCode(addr_prefix, data)
|
||||
return { chain: x, addr, logo }
|
||||
})
|
||||
if (this.accounts && this.accounts.address) {
|
||||
const { data } = addressDecode(this.accounts.address)
|
||||
return this.selected.map(x => {
|
||||
const { logo, addr_prefix } = this.chains[x]
|
||||
const addr = addressEnCode(addr_prefix, data)
|
||||
return {
|
||||
chain: x, addr, logo, hdpath: this.hdpath,
|
||||
}
|
||||
})
|
||||
}
|
||||
return []
|
||||
},
|
||||
},
|
||||
created() {
|
||||
@ -271,11 +323,18 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatPubkey(v) {
|
||||
if (typeof (v) === 'string') {
|
||||
return v
|
||||
}
|
||||
if (v) {
|
||||
return toHex(v)
|
||||
}
|
||||
return ''
|
||||
},
|
||||
async connect() {
|
||||
const transport = this.device === 'ledger' ? 'usb' : 'bluetooth'
|
||||
return getLedgerAddress(transport).catch(e => {
|
||||
this.debug = e
|
||||
})
|
||||
return getLedgerAddress(transport, this.hdpath)
|
||||
},
|
||||
async cennectKeplr() {
|
||||
if (!window.getOfflineSigner || !window.keplr) {
|
||||
@ -338,12 +397,12 @@ export default {
|
||||
case 'ledger2':
|
||||
await this.connect().then(accounts => {
|
||||
if (accounts) {
|
||||
this.accounts = {
|
||||
address: accounts.bech32_address,
|
||||
pubkey: accounts.compressed_pk,
|
||||
}
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
this.accounts = accounts[0]
|
||||
ok = true
|
||||
}
|
||||
}).catch(e => {
|
||||
this.debug = e
|
||||
})
|
||||
break
|
||||
default:
|
||||
|
@ -254,9 +254,14 @@ export default {
|
||||
return 0
|
||||
},
|
||||
removeAddress(v) {
|
||||
Object.values(this.accounts).forEach(item => {
|
||||
Object.keys(this.accounts).forEach(key => {
|
||||
const item = this.accounts[key]
|
||||
const newAddrs = item.address.filter(a => a.addr !== v)
|
||||
this.$set(item, 'address', newAddrs)
|
||||
if (newAddrs.length > 0) {
|
||||
this.$set(item, 'address', newAddrs)
|
||||
} else {
|
||||
delete this.accounts[key]
|
||||
}
|
||||
})
|
||||
localStorage.setItem('accounts', JSON.stringify(this.accounts))
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user