finish ledger signature

This commit is contained in:
liangping 2021-09-10 20:13:31 +08:00
parent 3445a13cdf
commit fe36d08f35
12 changed files with 311 additions and 280 deletions

View File

@ -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",

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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>

View File

@ -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:

View File

@ -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))
},