add keplr support for evmos
This commit is contained in:
parent
5aac799522
commit
db4b27c98e
18
.eslintrc.js
18
.eslintrc.js
@ -6,13 +6,21 @@ module.exports = {
|
|||||||
extends: [
|
extends: [
|
||||||
'@vue/airbnb',
|
'@vue/airbnb',
|
||||||
'plugin:vue/recommended',
|
'plugin:vue/recommended',
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:import/typescript',
|
'plugin:import/typescript',
|
||||||
|
// 'prettier/@typescript-eslint',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
// "plugin:prettier/recommended",
|
// "plugin:prettier/recommended",
|
||||||
// "prettier/@typescript-eslint"
|
|
||||||
],
|
],
|
||||||
|
parser: 'vue-eslint-parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: '@babel/eslint-parser',
|
parser: '@typescript-eslint/parser',
|
||||||
|
ecmaVersion: 6,
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaFeatures: {
|
||||||
|
jsx: false,
|
||||||
|
modules: true,
|
||||||
|
experimentalObjectRestSpread: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
@ -23,10 +31,12 @@ module.exports = {
|
|||||||
'linebreak-style': 'off',
|
'linebreak-style': 'off',
|
||||||
// camelcase: ['error', { properties: 'never', ignoreDestructuring: true, ignoreImports: true }],
|
// camelcase: ['error', { properties: 'never', ignoreDestructuring: true, ignoreImports: true }],
|
||||||
'arrow-parens': ['error', 'as-needed'],
|
'arrow-parens': ['error', 'as-needed'],
|
||||||
'vue/multiline-html-element-content-newline': 'off',
|
'vue/new-line-between-multi-line-property': 0,
|
||||||
|
'vue/multiline-html-element-content-newline': 0,
|
||||||
'vue/multi-word-component-names': 0,
|
'vue/multi-word-component-names': 0,
|
||||||
'vue/no-mutating-props': 0,
|
'vue/no-mutating-props': 0,
|
||||||
'vue/v-slot-style': 0,
|
'vue/v-slot-style': 0,
|
||||||
|
'@typescript-eslint/no-empty-function': 1,
|
||||||
camelcase: 0,
|
camelcase: 0,
|
||||||
'vuejs-accessibility/click-events-have-key-events': 'off',
|
'vuejs-accessibility/click-events-have-key-events': 'off',
|
||||||
'vuejs-accessibility/mouse-events-have-key-events': 'off',
|
'vuejs-accessibility/mouse-events-have-key-events': 'off',
|
||||||
|
@ -11,37 +11,22 @@ import {
|
|||||||
createIbcAminoConverters,
|
createIbcAminoConverters,
|
||||||
createStakingAminoConverters,
|
createStakingAminoConverters,
|
||||||
} from '@cosmjs/stargate'
|
} from '@cosmjs/stargate'
|
||||||
import {
|
import { EncodeObject } from '@cosmjs/proto-signing'
|
||||||
EncodeObject, TxBodyEncodeObject, makeAuthInfoBytes,
|
|
||||||
} from '@cosmjs/proto-signing'
|
|
||||||
import { LedgerSigner } from '@cosmjs/ledger-amino'
|
import { LedgerSigner } from '@cosmjs/ledger-amino'
|
||||||
import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
|
import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
|
||||||
import TransportWebBLE from '@ledgerhq/hw-transport-web-ble'
|
import TransportWebBLE from '@ledgerhq/hw-transport-web-ble'
|
||||||
import {
|
import {
|
||||||
StdFee,
|
StdFee,
|
||||||
} from '@cosmjs/amino'
|
} from '@cosmjs/amino'
|
||||||
import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'
|
|
||||||
import {
|
import {
|
||||||
generateMessageWithMultipleTransactions,
|
generateMessageWithMultipleTransactions,
|
||||||
generateTypes,
|
generateTypes,
|
||||||
generateFee,
|
generateFee,
|
||||||
createEIP712,
|
createEIP712,
|
||||||
} from '@tharsis/eip712'
|
} from '@tharsis/eip712'
|
||||||
import {
|
import { createTxRawEIP712, signatureToWeb3Extension, Chain } from '@tharsis/transactions'
|
||||||
createTxRawEIP712, signatureToWeb3Extension, Chain,
|
import { createTransactionWithMultipleMessages } from '@tharsis/proto'
|
||||||
} from '@tharsis/transactions'
|
import { fromBech32, toBase64 } from '@cosmjs/encoding'
|
||||||
import {
|
|
||||||
createTransactionWithMultipleMessages,
|
|
||||||
} from '@tharsis/proto'
|
|
||||||
import {
|
|
||||||
fromBase64, fromBech32, fromHex, toBase64,
|
|
||||||
} from '@cosmjs/encoding'
|
|
||||||
// import { generateEndpointBroadcast, generatePostBodyBroadcast } from '@tharsis/provider'
|
|
||||||
import { SignMode } from 'cosmjs-types/cosmos/tx/signing/v1beta1/signing'
|
|
||||||
import * as eth from '@tharsis/proto/dist/proto/ethermint/crypto/v1/ethsecp256k1/keys' // /ethermint/crypto/v1/ethsecp256k1/keys'
|
|
||||||
import { PubKey } from 'cosmjs-types/cosmos/crypto/secp256k1/keys'
|
|
||||||
import { Int53 } from '@cosmjs/math'
|
|
||||||
import { Any } from 'cosmjs-types/google/protobuf/any'
|
|
||||||
import EthereumLedgerSigner from './EthereumLedgerSigner'
|
import EthereumLedgerSigner from './EthereumLedgerSigner'
|
||||||
import { defaultMessageAdapter } from './MessageAdapter'
|
import { defaultMessageAdapter } from './MessageAdapter'
|
||||||
|
|
||||||
@ -152,52 +137,6 @@ export class SigningEthermintClient {
|
|||||||
return Promise.resolve(rawTx)
|
return Promise.resolve(rawTx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function encodePubkey(pubkey: string): Any {
|
|
||||||
// const value = new eth.ethermint.crypto.v1.ethsecp256k1.PubKey({ key: fromBase64(pubkey) })
|
|
||||||
// return Any.fromPartial({
|
|
||||||
// typeUrl: '/ethermint.crypto.v1.ethsecp256k1.PubKey',
|
|
||||||
// value: value.serializeBinary(),
|
|
||||||
// })
|
|
||||||
return Any.fromPartial({
|
|
||||||
typeUrl: '/ethermint.crypto.v1.ethsecp256k1.PubKey',
|
|
||||||
value: PubKey.encode({
|
|
||||||
key: fromBase64(pubkey),
|
|
||||||
}).finish(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeRawTx(sender, messages, memo, fee, signature, registry): TxRaw {
|
|
||||||
const pubkey = encodePubkey(sender.pubkey)
|
|
||||||
|
|
||||||
const signedTxBody = {
|
|
||||||
messages,
|
|
||||||
memo,
|
|
||||||
}
|
|
||||||
const signedTxBodyEncodeObject: TxBodyEncodeObject = {
|
|
||||||
typeUrl: '/cosmos.tx.v1beta1.TxBody',
|
|
||||||
value: signedTxBody,
|
|
||||||
}
|
|
||||||
const signedTxBodyBytes = registry.encode(signedTxBodyEncodeObject)
|
|
||||||
const signedGasLimit = Int53.fromString(fee.gas).toNumber()
|
|
||||||
// const signedSequence = sender.sequence
|
|
||||||
const signedAuthInfoBytes = makeAuthInfoBytes(
|
|
||||||
[{ pubkey, sequence: sender.sequence }],
|
|
||||||
fee.amount,
|
|
||||||
signedGasLimit,
|
|
||||||
SignMode.SIGN_MODE_LEGACY_AMINO_JSON,
|
|
||||||
)
|
|
||||||
const rawTx = TxRaw.fromPartial({
|
|
||||||
bodyBytes: signedTxBodyBytes,
|
|
||||||
authInfoBytes: signedAuthInfoBytes,
|
|
||||||
signatures: [fromHex(signature)],
|
|
||||||
})
|
|
||||||
|
|
||||||
return rawTx
|
|
||||||
}
|
|
||||||
|
|
||||||
// export function createAnyMessage(messages: readonly EncodeObject[]) {
|
|
||||||
// return messages.map(x => x.)
|
|
||||||
// }
|
|
||||||
|
|
||||||
export declare type SigningClient = SigningStargateClient | SigningEthermintClient;
|
export declare type SigningClient = SigningStargateClient | SigningEthermintClient;
|
||||||
|
|
59
src/libs/client/SigningKeplrEthermintClient.ts
Normal file
59
src/libs/client/SigningKeplrEthermintClient.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { fromBase64 } from '@cosmjs/encoding'
|
||||||
|
import { Int53 } from '@cosmjs/math'
|
||||||
|
import {
|
||||||
|
EncodeObject, makeAuthInfoBytes, makeSignDoc, OfflineSigner,
|
||||||
|
} from '@cosmjs/proto-signing'
|
||||||
|
import {
|
||||||
|
SignerData, SigningStargateClient, SigningStargateClientOptions, StdFee,
|
||||||
|
} from '@cosmjs/stargate'
|
||||||
|
import { PubKey } from 'cosmjs-types/cosmos/crypto/secp256k1/keys'
|
||||||
|
import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'
|
||||||
|
import { Any } from 'cosmjs-types/google/protobuf/any'
|
||||||
|
|
||||||
|
export default class SigningKeplerEthermintClient {
|
||||||
|
private signer
|
||||||
|
|
||||||
|
private client
|
||||||
|
|
||||||
|
static async offline(signer: OfflineSigner, options?: SigningStargateClientOptions): Promise<SigningKeplerEthermintClient> {
|
||||||
|
const instance = new SigningKeplerEthermintClient()
|
||||||
|
instance.client = await SigningStargateClient.offline(signer, options)
|
||||||
|
instance.signer = signer
|
||||||
|
return Promise.resolve(instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
async sign(signerAddress: string, messages: readonly EncodeObject[], fee: StdFee, memo: string, explicitSignerData?: SignerData): Promise<Uint8Array> {
|
||||||
|
const account = await this.signer.getAccounts()
|
||||||
|
const acc = account.find(x => x.address === signerAddress)
|
||||||
|
if (!acc) {
|
||||||
|
throw new Error('The signer address dose not exsits in Ledger!')
|
||||||
|
}
|
||||||
|
// Custom typeUrl for EVMOS
|
||||||
|
const pubk = Any.fromPartial({
|
||||||
|
typeUrl: '/ethermint.crypto.v1.ethsecp256k1.PubKey',
|
||||||
|
value: PubKey.encode({
|
||||||
|
key: acc.pubkey,
|
||||||
|
}).finish(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const txBodyEncodeObject = {
|
||||||
|
typeUrl: '/cosmos.tx.v1beta1.TxBody',
|
||||||
|
value: {
|
||||||
|
messages,
|
||||||
|
memo,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const txBodyBytes = this.client.registry.encode(txBodyEncodeObject)
|
||||||
|
const gasLimit = Int53.fromString(fee.gas).toNumber()
|
||||||
|
const authInfoBytes = makeAuthInfoBytes([{ pubkey: pubk, sequence: explicitSignerData.sequence }], fee.amount, gasLimit)
|
||||||
|
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, explicitSignerData.chainId, explicitSignerData.accountNumber)
|
||||||
|
const { signature, signed } = await this.signer.signDirect(signerAddress, signDoc)
|
||||||
|
|
||||||
|
// returns txBytes for broadcast
|
||||||
|
return Promise.resolve(TxRaw.encode({
|
||||||
|
bodyBytes: signed.bodyBytes,
|
||||||
|
authInfoBytes: signed.authInfoBytes,
|
||||||
|
signatures: [fromBase64(signature.signature)],
|
||||||
|
}).finish())
|
||||||
|
}
|
||||||
|
}
|
@ -20,8 +20,9 @@ import { $themeColors } from '@themeConfig'
|
|||||||
// import { SigningStargateClient } from '@cosmjs/stargate'
|
// import { SigningStargateClient } from '@cosmjs/stargate'
|
||||||
// import PingWalletClient from './data/signing'
|
// import PingWalletClient from './data/signing'
|
||||||
import { SigningStargateClient } from '@cosmjs/stargate'
|
import { SigningStargateClient } from '@cosmjs/stargate'
|
||||||
import { getSigningClient } from './client/PingWalletClient.ts'
|
import { getSigningClient } from './client/SigningEthermintClient.ts'
|
||||||
import { EthereumLedgerSigner } from './client/EthereumLedgerSigner.ts'
|
import EthereumLedgerSigner from './client/EthereumLedgerSigner.ts'
|
||||||
|
import SigningKeplerEthermintClient from './client/SigningKeplrEthermintClient'
|
||||||
|
|
||||||
dayjs.extend(localeData)
|
dayjs.extend(localeData)
|
||||||
dayjs.extend(duration)
|
dayjs.extend(duration)
|
||||||
@ -231,6 +232,34 @@ function getHdPath(address) {
|
|||||||
return stringToPath(hdPath)
|
return stringToPath(hdPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isEvmosBasedChain(chainId) {
|
||||||
|
const re = /[_]{1}[\d]{4}[\\-]{1}[\d]+$/g
|
||||||
|
return re.test(chainId)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function sign(device, chainId, signerAddress, messages, fee, memo, signerData) {
|
||||||
|
const hdpath = getHdPath(signerAddress)
|
||||||
|
let client
|
||||||
|
if (device.startsWith('ledger')) {
|
||||||
|
client = await getSigningClient(device, hdpath)
|
||||||
|
} else {
|
||||||
|
if (!window.getOfflineSigner || !window.keplr) {
|
||||||
|
throw new Error('Please install keplr extension')
|
||||||
|
}
|
||||||
|
await window.keplr.enable(chainId)
|
||||||
|
const signer = window.getOfflineSigner(chainId)
|
||||||
|
if (isEvmosBasedChain(chainId)) {
|
||||||
|
client = await SigningKeplerEthermintClient.offline(signer)
|
||||||
|
} else {
|
||||||
|
client = await SigningStargateClient.offline(signer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const coinType = Number(hdpath[1])
|
||||||
|
const addr = device.startsWith('ledger') && coinType !== 60 ? toSignAddress(signerAddress) : signerAddress
|
||||||
|
return client.sign(addr, messages, fee, memo, signerData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// import address from ledger
|
||||||
async function getLedgerAppName(coinType, device, hdpath) {
|
async function getLedgerAppName(coinType, device, hdpath) {
|
||||||
let ledgerAppName = 'Cosmos'
|
let ledgerAppName = 'Cosmos'
|
||||||
switch (coinType) {
|
switch (coinType) {
|
||||||
@ -252,27 +281,6 @@ async function getLedgerAppName(coinType, device, hdpath) {
|
|||||||
return new LedgerSigner(transport, { hdPaths: [hdpath], ledgerAppName })
|
return new LedgerSigner(transport, { hdPaths: [hdpath], ledgerAppName })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sign(device, chainId, signerAddress, messages, fee, memo, signerData) {
|
|
||||||
const hdpath = getHdPath(signerAddress)
|
|
||||||
let client
|
|
||||||
if (device.startsWith('ledger')) {
|
|
||||||
client = await getSigningClient(device, hdpath)
|
|
||||||
} else {
|
|
||||||
if (!window.getOfflineSigner || !window.keplr) {
|
|
||||||
throw new Error('Please install keplr extension')
|
|
||||||
}
|
|
||||||
await window.keplr.enable(chainId)
|
|
||||||
const signer = window.getOfflineSignerOnlyAmino(chainId)
|
|
||||||
client = await SigningStargateClient.offline(signer)
|
|
||||||
}
|
|
||||||
// let transport
|
|
||||||
// let signer
|
|
||||||
// const hdpath = getHdPath(signerAddress)
|
|
||||||
const coinType = Number(hdpath[1])
|
|
||||||
const addr = device.startsWith('ledger') && coinType !== 60 ? toSignAddress(signerAddress) : signerAddress
|
|
||||||
return client.sign(addr, messages, fee, memo, signerData)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getLedgerAddress(transport = 'blu', hdPath = "m/44'/118/0'/0/0") {
|
export async function getLedgerAddress(transport = 'blu', hdPath = "m/44'/118/0'/0/0") {
|
||||||
const protocol = transport === 'usb' ? await TransportWebUSB.create() : await TransportWebBLE.create()
|
const protocol = transport === 'usb' ? await TransportWebUSB.create() : await TransportWebBLE.create()
|
||||||
// extract Cointype from from HDPath
|
// extract Cointype from from HDPath
|
||||||
@ -280,6 +288,7 @@ export async function getLedgerAddress(transport = 'blu', hdPath = "m/44'/118/0'
|
|||||||
const signer = await getLedgerAppName(coinType, protocol, stringToPath(hdPath))
|
const signer = await getLedgerAppName(coinType, protocol, stringToPath(hdPath))
|
||||||
return signer.getAccounts()
|
return signer.getAccounts()
|
||||||
}
|
}
|
||||||
|
/// end import address from ledger
|
||||||
|
|
||||||
export function toDuration(value) {
|
export function toDuration(value) {
|
||||||
return dayjs.duration(value).humanize()
|
return dayjs.duration(value).humanize()
|
||||||
|
@ -651,7 +651,7 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$http.getAuthAccount(this.address).then(acc => {
|
this.$http.getAuthAccount(this.address).then(acc => {
|
||||||
this.account = acc
|
this.account = acc.account
|
||||||
this.initial()
|
this.initial()
|
||||||
this.$http.getTxsBySender(this.address).then(res => {
|
this.$http.getTxsBySender(this.address).then(res => {
|
||||||
this.transactions = res
|
this.transactions = res
|
||||||
|
Loading…
Reference in New Issue
Block a user