forked from cerc-io/cosmos-explorer
update dependency for ethereum ledger
This commit is contained in:
parent
7d266ddaf0
commit
8192b9e1a4
13
.eslintrc.js
13
.eslintrc.js
@ -5,7 +5,7 @@ module.exports = {
|
||||
},
|
||||
extends: ['plugin:vue/recommended', '@vue/airbnb'],
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
parser: '@babel/eslint-parser',
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
@ -14,8 +14,17 @@ module.exports = {
|
||||
semi: ['error', 'never'],
|
||||
'max-len': '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'],
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/multi-word-component-names': 0,
|
||||
'vue/no-mutating-props': 0,
|
||||
'vue/v-slot-style': 0,
|
||||
'camelcase': 0,
|
||||
'vuejs-accessibility/click-events-have-key-events': 'off',
|
||||
'vuejs-accessibility/mouse-events-have-key-events': 'off',
|
||||
'vuejs-accessibility/anchor-has-content': 'off',
|
||||
'no-unsafe-optional-chaining': 1,
|
||||
'vuejs-accessibility/label-has-for': 1,
|
||||
},
|
||||
}
|
||||
|
31664
package-lock.json
generated
31664
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@ -23,9 +23,9 @@
|
||||
"@cosmjs/proto-signing": "^0.28.4",
|
||||
"@cosmjs/stargate": "0.28.4",
|
||||
"@intlify/vue-i18n-loader": "^2.1.2",
|
||||
"@ledgerhq/hw-app-cosmos": "^6.3.0",
|
||||
"@ledgerhq/hw-transport-web-ble": "^6.3.0",
|
||||
"@ledgerhq/hw-transport-webusb": "^6.3.0",
|
||||
"@ledgerhq/hw-app-eth": "^6.28.2",
|
||||
"@ledgerhq/hw-transport-web-ble": "^6.27.1",
|
||||
"@ledgerhq/hw-transport-webusb": "^6.27.1",
|
||||
"@vue/composition-api": "^1.4.9",
|
||||
"@vueuse/core": "4.0.0",
|
||||
"animate.css": "4.1.1",
|
||||
@ -37,7 +37,7 @@
|
||||
"bootstrap-vue": "2.21.1",
|
||||
"chart.js": "2.9.4",
|
||||
"compare-versions": "^3.6.0",
|
||||
"core-js": "^3.8.1",
|
||||
"core-js": "^3.22.5",
|
||||
"cosmjs-types": "^0.2.0",
|
||||
"dayjs": "^1.10.6",
|
||||
"echarts": "5.3.0",
|
||||
@ -45,9 +45,9 @@
|
||||
"ledger-cosmos-js": "2.1.8",
|
||||
"long": "^5.2.0",
|
||||
"node-fetch": "^2.6.5",
|
||||
"node-polyfill-webpack-plugin": "^1.1.4",
|
||||
"pako": "^1.0.11",
|
||||
"portal-vue": "2.1.7",
|
||||
"postcss-rtl": "1.7.3",
|
||||
"prismjs": "1.25.0",
|
||||
"protobufjs-cli-dbx": "^7.0.7",
|
||||
"protobufjs-dbx": "^7.0.0",
|
||||
@ -90,18 +90,22 @@
|
||||
"vuex": "3.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.9",
|
||||
"@vue/cli-plugin-eslint": "~4.5.9",
|
||||
"@vue/cli-plugin-router": "~4.5.9",
|
||||
"@vue/cli-plugin-vuex": "~4.5.9",
|
||||
"@vue/cli-service": "~4.5.9",
|
||||
"@vue/eslint-config-airbnb": "^5.3.0",
|
||||
"@babel/eslint-parser": "^7.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.25.0",
|
||||
"@typescript-eslint/parser": "^5.25.0",
|
||||
"@vue/cli-plugin-babel": "~5.0.4",
|
||||
"@vue/cli-plugin-eslint": "~5.0.4",
|
||||
"@vue/cli-plugin-router": "~5.0.4",
|
||||
"@vue/cli-plugin-vuex": "~5.0.4",
|
||||
"@vue/cli-service": "~5.0.4",
|
||||
"@vue/eslint-config-airbnb": "^6.0.0",
|
||||
"@vue/eslint-config-standard": "6.1.0",
|
||||
"@vuepress/plugin-medium-zoom": "^1.7.1",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"compression-webpack-plugin": "6.1.1",
|
||||
"eslint": "6.8.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-vue": "6.2.2",
|
||||
"eslint": "^8.15.0",
|
||||
"eslint-plugin-vue": "9.0.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-vuejs-accessibility": "^1.1.1",
|
||||
"sass": "1.32.*",
|
||||
"sass-loader": "^10.1.0",
|
||||
"ts-loader": "8.2.0",
|
||||
|
@ -1,5 +0,0 @@
|
||||
const rtl = require('postcss-rtl')
|
||||
|
||||
module.exports = {
|
||||
plugins: [rtl()],
|
||||
}
|
@ -39,12 +39,6 @@ export default {
|
||||
BDropdownItem,
|
||||
BImg,
|
||||
},
|
||||
// ! Need to move this computed property to comp function once we get to Vue 3
|
||||
computed: {
|
||||
currentLocale() {
|
||||
return this.locales.find(l => l.locale === this.$i18n.locale)
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
/* eslint-disable global-require */
|
||||
const locales = [
|
||||
@ -75,6 +69,12 @@ export default {
|
||||
locales,
|
||||
}
|
||||
},
|
||||
// ! Need to move this computed property to comp function once we get to Vue 3
|
||||
computed: {
|
||||
currentLocale() {
|
||||
return this.locales.find(l => l.locale === this.$i18n.locale)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
v-if="showSearchBar"
|
||||
v-model="searchQuery"
|
||||
placeholder="Search Height/Transaction/Account Address"
|
||||
autofocus
|
||||
:state="false"
|
||||
autocomplete="off"
|
||||
@keyup.enter="doQuery"
|
||||
|
@ -13,9 +13,9 @@
|
||||
>
|
||||
<slot
|
||||
name="navbar"
|
||||
:toggleVerticalMenuActive="toggleVerticalMenuActive"
|
||||
:navbarBackgroundColor="navbarBackgroundColor"
|
||||
:navbarTypeClass="[...navbarTypeClass, 'header-navbar navbar navbar-shadow align-items-center']"
|
||||
:toggle-vertical-menu-active="toggleVerticalMenuActive"
|
||||
:navbar-background-color="navbarBackgroundColor"
|
||||
:navbar-type-class="[...navbarTypeClass, 'header-navbar navbar navbar-shadow align-items-center']"
|
||||
>
|
||||
<app-navbar-vertical-layout :toggle-vertical-menu-active="toggleVerticalMenuActive" />
|
||||
</slot>
|
||||
@ -109,14 +109,6 @@ export default {
|
||||
LayoutContentRendererDefault,
|
||||
},
|
||||
mixins: [mixinVerticalLayout],
|
||||
computed: {
|
||||
layoutContentRenderer() {
|
||||
const rendererType = this.$route.meta.contentRenderer
|
||||
if (rendererType === 'sidebar-left') return 'layout-content-renderer-left'
|
||||
if (rendererType === 'sidebar-left-detached') return 'layout-content-renderer-left-detached'
|
||||
return 'layout-content-renderer-default'
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const {
|
||||
routerTransition, navbarBackgroundColor, navbarType, footerType, isNavMenuHidden,
|
||||
@ -155,6 +147,14 @@ export default {
|
||||
isNavMenuHidden,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
layoutContentRenderer() {
|
||||
const rendererType = this.$route.meta.contentRenderer
|
||||
if (rendererType === 'sidebar-left') return 'layout-content-renderer-left'
|
||||
if (rendererType === 'sidebar-left-detached') return 'layout-content-renderer-left-detached'
|
||||
return 'layout-content-renderer-default'
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -12,9 +12,9 @@
|
||||
<div class="navbar-header expanded">
|
||||
<slot
|
||||
name="header"
|
||||
:toggleVerticalMenuActive="toggleVerticalMenuActive"
|
||||
:toggleCollapsed="toggleCollapsed"
|
||||
:collapseTogglerIcon="collapseTogglerIcon"
|
||||
:toggle-vertical-menu-active="toggleVerticalMenuActive"
|
||||
:toggle-collapsed="toggleCollapsed"
|
||||
:collapse-toggler-icon="collapseTogglerIcon"
|
||||
>
|
||||
<ul class="nav navbar-nav flex-row">
|
||||
|
||||
|
57
src/App.vue
57
src/App.vue
@ -30,7 +30,35 @@ export default {
|
||||
LayoutVertical,
|
||||
LayoutFull,
|
||||
},
|
||||
setup() {
|
||||
const { skin, skinClasses } = useAppConfig()
|
||||
|
||||
// If skin is dark when initialized => Add class to body
|
||||
if (skin.value === 'dark') document.body.classList.add('dark-layout')
|
||||
|
||||
// Provide toast for Composition API usage
|
||||
// This for those apps/components which uses composition API
|
||||
// Demos will still use Options API for ease
|
||||
provideToast({
|
||||
hideProgressBar: true,
|
||||
closeOnClick: false,
|
||||
closeButton: false,
|
||||
icon: false,
|
||||
timeout: 3000,
|
||||
transition: 'Vue-Toastification__fade',
|
||||
})
|
||||
|
||||
// Set Window Width in store
|
||||
store.commit('app/UPDATE_WINDOW_WIDTH', window.innerWidth)
|
||||
const { width: windowWidth } = useWindowSize()
|
||||
watch(windowWidth, val => {
|
||||
store.commit('app/UPDATE_WINDOW_WIDTH', val)
|
||||
})
|
||||
|
||||
return {
|
||||
skinClasses,
|
||||
}
|
||||
},
|
||||
// ! We can move this computed: layout & contentLayoutType once we get to use Vue 3
|
||||
// Currently, router.currentRoute is not reactive and doesn't trigger any change
|
||||
computed: {
|
||||
@ -65,35 +93,6 @@ export default {
|
||||
const { isRTL } = $themeConfig.layout
|
||||
document.documentElement.setAttribute('dir', isRTL ? 'rtl' : 'ltr')
|
||||
},
|
||||
setup() {
|
||||
const { skin, skinClasses } = useAppConfig()
|
||||
|
||||
// If skin is dark when initialized => Add class to body
|
||||
if (skin.value === 'dark') document.body.classList.add('dark-layout')
|
||||
|
||||
// Provide toast for Composition API usage
|
||||
// This for those apps/components which uses composition API
|
||||
// Demos will still use Options API for ease
|
||||
provideToast({
|
||||
hideProgressBar: true,
|
||||
closeOnClick: false,
|
||||
closeButton: false,
|
||||
icon: false,
|
||||
timeout: 3000,
|
||||
transition: 'Vue-Toastification__fade',
|
||||
})
|
||||
|
||||
// Set Window Width in store
|
||||
store.commit('app/UPDATE_WINDOW_WIDTH', window.innerWidth)
|
||||
const { width: windowWidth } = useWindowSize()
|
||||
watch(windowWidth, val => {
|
||||
store.commit('app/UPDATE_WINDOW_WIDTH', val)
|
||||
})
|
||||
|
||||
return {
|
||||
skinClasses,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
store.dispatch('chains/getQuotes')
|
||||
store.dispatch('chains/getAllIBCDenoms', this)
|
||||
|
48
src/libs/client/EthereumLedgerSigner.ts
Normal file
48
src/libs/client/EthereumLedgerSigner.ts
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
import { AccountData, AminoSignResponse, encodeSecp256k1Signature, OfflineAminoSigner, StdSignature, StdSignDoc } from "@cosmjs/amino";
|
||||
import Transport from "@ledgerhq/hw-transport";
|
||||
|
||||
import Eth from "@ledgerhq/hw-app-eth";
|
||||
import { LedgerEthTransactionResolution, LoadConfig } from "@ledgerhq/hw-app-eth/lib/services/types";
|
||||
import { toHex } from "@cosmjs/encoding";
|
||||
|
||||
class EthereumLedgerSigner implements OfflineAminoSigner {
|
||||
app: Eth
|
||||
hdpath: string
|
||||
constructor(trasport: Transport, hdpath: string, scrambleKey?: string, loadConfig?: LoadConfig) {
|
||||
this.app = new Eth(trasport, scrambleKey, loadConfig)
|
||||
}
|
||||
async getAccounts(): Promise<readonly AccountData[]> {
|
||||
return this.app.getAddress(this.hdpath).then(x => {
|
||||
const x2: AccountData = {
|
||||
pubkey: new TextEncoder().encode(x.publicKey),
|
||||
address: x.address,
|
||||
algo: "secp256k1"
|
||||
}
|
||||
return [x2]
|
||||
})
|
||||
};
|
||||
|
||||
async signAmino(signerAddress: string, signDoc: StdSignDoc): Promise<AminoSignResponse> {
|
||||
return this.getAccounts().then(list => {
|
||||
const acc = list.find(x => x.address === signerAddress)
|
||||
if (acc) {
|
||||
const messageHex: string = toHex(new TextEncoder().encode(JSON.stringify(signDoc)))
|
||||
this.app.signPersonalMessage(this.hdpath, messageHex).then(r => {
|
||||
const signature: StdSignature = encodeSecp256k1Signature(acc.pubkey, new TextEncoder().encode(r['s']))
|
||||
const output: AminoSignResponse = {
|
||||
signed: signDoc,
|
||||
signature
|
||||
}
|
||||
console.log(r)
|
||||
return output
|
||||
})
|
||||
}
|
||||
throw new Error('Account Does not exists!')
|
||||
})
|
||||
};
|
||||
|
||||
signTransaction(rawTxHex: string, resolution: LedgerEthTransactionResolution) {
|
||||
return this.app.signTransaction(this.hdpath, rawTxHex, resolution )
|
||||
}
|
||||
}
|
@ -26,23 +26,19 @@ export default class PingWalletClient extends SigningStargateClient {
|
||||
}
|
||||
|
||||
async signAmino2(signerAddress, messages, fee, memo, { accountNumber, sequence, chainId }) {
|
||||
// utils_1.assert(!proto_signing_1.isOfflineDirectSigner(this.signer))
|
||||
const accountFromSigner = (await this.signer.getAccounts()).find(account => account.address === signerAddress)
|
||||
if (!accountFromSigner) {
|
||||
throw new Error('Failed to retrieve account from signer')
|
||||
}
|
||||
const pubkey = proto_signing_1.encodePubkey(amino_1.encodeSecp256k1Pubkey(accountFromSigner.pubkey))
|
||||
const signMode = signing_1.SignMode.SIGN_MODE_LEGACY_AMINO_JSON
|
||||
// console.log('messages:', messages)
|
||||
const msgs = messages.map(msg => this.aminoTypes.toAmino(msg))
|
||||
// console.log('msgs:', msgs)
|
||||
const signDoc = amino_1.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,
|
||||
}
|
||||
// console.log(signedTxBody)
|
||||
const signedTxBodyEncodeObject = {
|
||||
typeUrl: '/cosmos.tx.v1beta1.TxBody',
|
||||
value: signedTxBody,
|
||||
|
@ -57,6 +57,13 @@ export default {
|
||||
ObjectFieldComponent,
|
||||
ArrayFieldComponent,
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
const { height } = to.params
|
||||
if (height > 0 && height !== from.params.height) {
|
||||
this.initData(height)
|
||||
next()
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
block: { block: { header: {}, data: {}, evidence: {} } },
|
||||
@ -69,13 +76,6 @@ export default {
|
||||
],
|
||||
}
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
const { height } = to.params
|
||||
if (height > 0 && height !== from.params.height) {
|
||||
this.initData(height)
|
||||
next()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const { height } = this.$route.params
|
||||
this.initData(height)
|
||||
|
@ -133,6 +133,12 @@ export default {
|
||||
SummaryPriceChart,
|
||||
FeatherIcon,
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
const { poolid } = to.params
|
||||
this.init(poolid)
|
||||
next()
|
||||
// }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
@ -206,12 +212,6 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
const { poolid } = to.params
|
||||
this.init(poolid)
|
||||
next()
|
||||
// }
|
||||
},
|
||||
methods: {
|
||||
getPrice(symbol) {
|
||||
const p1 = this.$store.state.chains.quotes[symbol[0]]
|
||||
|
@ -120,12 +120,6 @@ export default {
|
||||
BBadge,
|
||||
ObjectFieldComponent,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
error: null,
|
||||
tx: { tx: {} },
|
||||
}
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
const { hash } = to.params
|
||||
if (hash !== from.params.hash) {
|
||||
@ -138,6 +132,12 @@ export default {
|
||||
next()
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
error: null,
|
||||
tx: { tx: {} },
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const { hash } = this.$route.params
|
||||
this.$http.getTxs(hash).then(res => {
|
||||
|
@ -464,6 +464,23 @@ export default {
|
||||
'b-tooltip': VBTooltip,
|
||||
Ripple,
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
// const { address } = this.$route.params
|
||||
const { address } = to.params
|
||||
if (address !== from.params.hash) {
|
||||
this.address = address
|
||||
this.$http.getAuthAccount(this.address).then(acc => {
|
||||
this.account = acc
|
||||
this.initial()
|
||||
this.$http.getTxsBySender(this.address).then(res => {
|
||||
this.transactions = res
|
||||
})
|
||||
}).catch(err => {
|
||||
this.error = err
|
||||
})
|
||||
next()
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const { address } = this.$route.params
|
||||
return {
|
||||
@ -646,23 +663,6 @@ export default {
|
||||
this.error = err
|
||||
})
|
||||
},
|
||||
beforeRouteUpdate(to, from, next) {
|
||||
// const { address } = this.$route.params
|
||||
const { address } = to.params
|
||||
if (address !== from.params.hash) {
|
||||
this.address = address
|
||||
this.$http.getAuthAccount(this.address).then(acc => {
|
||||
this.account = acc
|
||||
this.initial()
|
||||
this.$http.getTxsBySender(this.address).then(res => {
|
||||
this.transactions = res
|
||||
})
|
||||
}).catch(err => {
|
||||
this.error = err
|
||||
})
|
||||
next()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const elem = document.getElementById('txevent')
|
||||
elem.addEventListener('txcompleted', () => {
|
||||
|
@ -18,7 +18,7 @@
|
||||
</b-tabs>
|
||||
<PlaceForm
|
||||
:type="tabIndex"
|
||||
:pool.sync="pool"
|
||||
:pool="pool"
|
||||
:denom-trace="denomTrace"
|
||||
/>
|
||||
</div>
|
||||
|
@ -95,10 +95,10 @@
|
||||
class="px-0"
|
||||
>
|
||||
<b-form-group>
|
||||
<label>
|
||||
<label for="slip">
|
||||
Slippage Tolerance
|
||||
</label>
|
||||
<div>
|
||||
<div id="slip">
|
||||
<b-form-radio
|
||||
v-model="slippage"
|
||||
value="0.01"
|
||||
|
@ -32,15 +32,15 @@ export default {
|
||||
components: {
|
||||
VChart,
|
||||
},
|
||||
provide: {
|
||||
[THEME_KEY]: 'light',
|
||||
},
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
provide: {
|
||||
[THEME_KEY]: 'light',
|
||||
},
|
||||
computed: {
|
||||
option() {
|
||||
const colors = chartColors()
|
||||
|
@ -2,20 +2,19 @@
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"dom",
|
||||
"es5",
|
||||
"es2015"
|
||||
"es6",
|
||||
"es2016"
|
||||
],
|
||||
"target": "es5",
|
||||
"jsx": "preserve",
|
||||
"allowJs": true,
|
||||
"target": "es6",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"src/**/*.d.ts"
|
||||
"src/**/*",
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
const path = require('path')
|
||||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
|
||||
const CompressionWebpackPlugin = require('compression-webpack-plugin')
|
||||
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
|
||||
|
||||
const productionGzipExtensions = ['js', 'css']
|
||||
|
||||
@ -26,6 +27,7 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new NodePolyfillPlugin(),
|
||||
new BundleAnalyzerPlugin({
|
||||
analyzerMode: 'disabled',
|
||||
openAnalyzer: false,
|
||||
|
Loading…
Reference in New Issue
Block a user