From 93064799ba0b1c2eeb61a8548898117bf23ec37d Mon Sep 17 00:00:00 2001 From: Steven Khong Date: Mon, 28 Mar 2022 14:34:17 +0800 Subject: [PATCH 1/4] Add carbon chain config and assets --- public/logos/carbon.svg | 91 ++++++++++++++++++++++++++++++++++ src/chains/mainnet/carbon.json | 19 +++++++ 2 files changed, 110 insertions(+) create mode 100644 public/logos/carbon.svg create mode 100644 src/chains/mainnet/carbon.json diff --git a/public/logos/carbon.svg b/public/logos/carbon.svg new file mode 100644 index 0000000000..1c1cea310a --- /dev/null +++ b/public/logos/carbon.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/chains/mainnet/carbon.json b/src/chains/mainnet/carbon.json new file mode 100644 index 0000000000..afdb5ee071 --- /dev/null +++ b/src/chains/mainnet/carbon.json @@ -0,0 +1,19 @@ +{ + "chain_name": "carbon", + "coingecko": "switcheo", + "api": "https://api.carbon.network", + "rpc": ["https://tm-api.carbon.network"], + "snapshot_provider": "", + "sdk_version": "0.45.2", + "coin_type": "118", + "min_tx_fee": "100000", + "addr_prefix": "swth", + "logo": "/logos/carbon.svg", + "assets": [{ + "base": "swth", + "symbol": "SWTH", + "exponent": "8", + "coingecko_id": "switcheo", + "logo": "/logos/carbon.svg" + }] +} From ec08c8c2c526b477c5bde15b1d1fe9ef589499b6 Mon Sep 17 00:00:00 2001 From: Steven Khong Date: Mon, 4 Apr 2022 14:57:43 +0800 Subject: [PATCH 2/4] Add carbon mainnet chain configs --- src/chains/mainnet/carbon.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains/mainnet/carbon.json b/src/chains/mainnet/carbon.json index afdb5ee071..8392a3fee6 100644 --- a/src/chains/mainnet/carbon.json +++ b/src/chains/mainnet/carbon.json @@ -6,7 +6,7 @@ "snapshot_provider": "", "sdk_version": "0.45.2", "coin_type": "118", - "min_tx_fee": "100000", + "min_tx_fee": "100000000", "addr_prefix": "swth", "logo": "/logos/carbon.svg", "assets": [{ From 7d9562354644c32b4088156c62873df253c19444 Mon Sep 17 00:00:00 2001 From: Steven Khong Date: Mon, 4 Apr 2022 14:58:24 +0800 Subject: [PATCH 3/4] Add keplr config fee override support --- src/chains/mainnet/carbon.json | 5 +++++ src/libs/data/signing.js | 16 ++++++++++++++-- src/libs/utils.js | 19 +++++++++++++++++-- src/views/OperationDelegateComponent.vue | 6 ++++-- src/views/OperationGovDepositComponent.vue | 5 ++++- src/views/OperationRedelegateComponent.vue | 2 ++ src/views/OperationTransfer2Component.vue | 2 ++ src/views/OperationTransferComponent.vue | 6 +++++- src/views/OperationUnbondComponent.vue | 2 ++ src/views/OperationVoteComponent.vue | 5 ++++- .../OperationWithdrawCommissionComponent.vue | 5 ++++- src/views/OperationWithdrawComponent.vue | 6 ++++-- .../components/KlineTrade/DepositeWindow.vue | 2 ++ 13 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/chains/mainnet/carbon.json b/src/chains/mainnet/carbon.json index 8392a3fee6..7de20fe401 100644 --- a/src/chains/mainnet/carbon.json +++ b/src/chains/mainnet/carbon.json @@ -9,6 +9,11 @@ "min_tx_fee": "100000000", "addr_prefix": "swth", "logo": "/logos/carbon.svg", + "sign_opts": { + "keplr": { + "preferNoSetFee": true + } + }, "assets": [{ "base": "swth", "symbol": "SWTH", diff --git a/src/libs/data/signing.js b/src/libs/data/signing.js index 71aec0e37e..745dc13d84 100644 --- a/src/libs/data/signing.js +++ b/src/libs/data/signing.js @@ -25,7 +25,8 @@ export default class PingWalletClient extends SigningStargateClient { return instance } - async signAmino2(signerAddress, messages, fee, memo, { accountNumber, sequence, chainId }) { + async signAmino2(signerAddress, messages, fee, memo, signerData, signOpts = {}) { + const { accountNumber, sequence, chainId } = signerData // utils_1.assert(!proto_signing_1.isOfflineDirectSigner(this.signer)) const accountFromSigner = (await this.signer.getAccounts()).find(account => account.address === signerAddress) if (!accountFromSigner) { @@ -37,7 +38,18 @@ export default class PingWalletClient extends SigningStargateClient { 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) + + let signature = null + let signed = null + if (this.signer.keplr && signOpts.keplr?.preferNoSetFee) { + // additional keplr signer specific sign opts + ({ signature, signed } = await this.signer.keplr.signAmino(this.signer.chainId, signerAddress, signDoc, { + preferNoSetFee: signOpts.keplr.preferNoSetFee, + })) + } else { + ({ signature, signed } = await this.signer.signAmino(signerAddress, signDoc)) + } + const signedTxBody = { messages: signed.msgs.map(msg => this.aminoTypes.fromAmino(msg)), memo: signed.memo, diff --git a/src/libs/utils.js b/src/libs/utils.js index 09befd4ff8..bfe9cf2f5d 100644 --- a/src/libs/utils.js +++ b/src/libs/utils.js @@ -193,7 +193,7 @@ function getHdPath(address) { return stringToPath(hdPath) } -export async function sign(device, chainId, signerAddress, messages, fee, memo, signerData) { +export async function sign(device, chainId, signerAddress, messages, fee, memo, signerData, signOpts) { let transport let signer switch (device) { @@ -226,7 +226,7 @@ export async function sign(device, chainId, signerAddress, messages, fee, memo, // Ensure the address has some tokens to spend const client = await PingWalletClient.offline(signer) // const client = await SigningStargateClient.offline(signer) - return client.signAmino2(device.startsWith('ledger') ? toSignAddress(signerAddress) : signerAddress, messages, fee, memo, signerData) + return client.signAmino2(device.startsWith('ledger') ? toSignAddress(signerAddress) : signerAddress, messages, fee, memo, signerData, signOpts) // return signDirect(signer, signerAddress, messages, fee, memo, signerData) } @@ -326,6 +326,21 @@ export function isToken(value) { return is } +export function findNativeConfigToken(balances, chain) { + if (!Array.isArray(balances)) return undefined + if (!Array.isArray(chain?.assets)) return balances + + const configAssetDenoms = chain.assets.map(i => i.base) + + // prioritise config tokens in token selection dropdown if available. + const token = balances.find(i => !i.denom.startsWith('ibc') && configAssetDenoms.includes(i.denom)) + + if (token) return token + + // if no token in config, return any native (non-ibc) token + return balances.find(i => !i.denom.startsWith('ibc')) +} + export function formatTokenDenom(tokenDenom) { if (tokenDenom && tokenDenom.code === undefined) { let denom = tokenDenom.denom_trace ? tokenDenom.denom_trace.base_denom : tokenDenom diff --git a/src/views/OperationDelegateComponent.vue b/src/views/OperationDelegateComponent.vue index 738daaeb65..aba39acb52 100644 --- a/src/views/OperationDelegateComponent.vue +++ b/src/views/OperationDelegateComponent.vue @@ -245,7 +245,7 @@ import { required, email, url, between, alpha, integer, password, min, digits, alphaDash, length, } from '@validations' import { - abbrAddress, extractAccountNumberAndSequence, formatToken, formatTokenDenom, getLocalAccounts, getUnitAmount, setLocalTxHistory, sign, timeIn, + abbrAddress, extractAccountNumberAndSequence, findNativeConfigToken, formatToken, formatTokenDenom, getLocalAccounts, getUnitAmount, setLocalTxHistory, sign, timeIn, } from '@/libs/utils' import vSelect from 'vue-select' import ToastificationContent from '@core/components/toastification/ToastificationContent.vue' @@ -349,7 +349,7 @@ export default { this.$http.getBankBalances(this.selectedAddress).then(res => { if (res && res.length > 0) { this.balance = res.reverse() - const token = this.balance.find(i => !i.denom.startsWith('ibc')) + const token = findNativeConfigToken(this.balance, this.$store.state.chains.selected) this.token = token.denom if (token) this.feeDenom = token.denom this.balance.filter(i => i.denom.startsWith('ibc')).forEach(x => { @@ -469,6 +469,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -477,6 +478,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationGovDepositComponent.vue b/src/views/OperationGovDepositComponent.vue index 0080c1e925..97b4b8ad15 100644 --- a/src/views/OperationGovDepositComponent.vue +++ b/src/views/OperationGovDepositComponent.vue @@ -215,6 +215,7 @@ import { import { abbrAddress, extractAccountNumberAndSequence, + findNativeConfigToken, formatToken, formatTokenDenom, getLocalAccounts, getUnitAmount, setLocalTxHistory, sign, timeIn, } from '@/libs/utils' import ToastificationContent from '@core/components/toastification/ToastificationContent.vue' @@ -317,7 +318,7 @@ export default { this.$http.getBankBalances(this.voter).then(res => { if (res && res.length > 0) { this.balance = res.reverse().filter(x => !x.denom.startsWith('ibc')) - const token = this.balance.find(i => !i.denom.startsWith('ibc')) + const token = findNativeConfigToken(this.balance, this.$store.state.chains.selected) if (token) { this.feeDenom = token.denom this.token = token.denom @@ -408,6 +409,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -416,6 +418,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationRedelegateComponent.vue b/src/views/OperationRedelegateComponent.vue index df1ceb6e50..834e9841fa 100644 --- a/src/views/OperationRedelegateComponent.vue +++ b/src/views/OperationRedelegateComponent.vue @@ -409,6 +409,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -417,6 +418,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationTransfer2Component.vue b/src/views/OperationTransfer2Component.vue index dcefc7d1b6..9ac875f63e 100644 --- a/src/views/OperationTransfer2Component.vue +++ b/src/views/OperationTransfer2Component.vue @@ -503,6 +503,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -511,6 +512,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationTransferComponent.vue b/src/views/OperationTransferComponent.vue index 08f72a44a3..42572f5a4c 100644 --- a/src/views/OperationTransferComponent.vue +++ b/src/views/OperationTransferComponent.vue @@ -217,6 +217,7 @@ import { } from '@validations' import { extractAccountNumberAndSequence, + findNativeConfigToken, formatToken, formatTokenDenom, getLocalAccounts, getLocalChains, getUnitAmount, setLocalTxHistory, sign, timeIn, } from '@/libs/utils' import ToastificationContent from '@core/components/toastification/ToastificationContent.vue' @@ -324,7 +325,8 @@ export default { if (res && res.length > 0) { this.balance = res.reverse() this.token = this.balance[0].denom - this.feeDenom = this.balance.find(x => !x.denom.startsWith('ibc')).denom + const token = findNativeConfigToken(this.balance, this.$store.state.chains.selected) + this.feeDenom = token?.denom this.balance.filter(i => i.denom.startsWith('ibc')).forEach(x => { if (!this.IBCDenom[x.denom]) { this.$http.getIBCDenomTrace(x.denom, this.selectedChain).then(denom => { @@ -404,6 +406,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -412,6 +415,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationUnbondComponent.vue b/src/views/OperationUnbondComponent.vue index 8268fb74d2..c5d5be8fe8 100644 --- a/src/views/OperationUnbondComponent.vue +++ b/src/views/OperationUnbondComponent.vue @@ -380,6 +380,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -388,6 +389,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationVoteComponent.vue b/src/views/OperationVoteComponent.vue index f6505d733c..59b2071d37 100644 --- a/src/views/OperationVoteComponent.vue +++ b/src/views/OperationVoteComponent.vue @@ -204,6 +204,7 @@ import { import { abbrAddress, extractAccountNumberAndSequence, + findNativeConfigToken, formatToken, getLocalAccounts, setLocalTxHistory, sign, timeIn, } from '@/libs/utils' import ToastificationContent from '@core/components/toastification/ToastificationContent.vue' @@ -299,7 +300,7 @@ export default { this.$http.getBankBalances(this.voter).then(res => { if (res && res.length > 0) { this.balance = res.reverse() - const token = this.balance.find(i => !i.denom.startsWith('ibc')) + const token = findNativeConfigToken(this.balance, this.$store.state.chains.selected) if (token) this.feeDenom = token.denom } }) @@ -382,6 +383,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -390,6 +392,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationWithdrawCommissionComponent.vue b/src/views/OperationWithdrawCommissionComponent.vue index 8264a8eda3..3811847a24 100644 --- a/src/views/OperationWithdrawCommissionComponent.vue +++ b/src/views/OperationWithdrawCommissionComponent.vue @@ -129,6 +129,7 @@ import { } from '@validations' import { extractAccountNumberAndSequence, + findNativeConfigToken, formatToken, setLocalTxHistory, sign, timeIn, } from '@/libs/utils' import ToastificationContent from '@core/components/toastification/ToastificationContent.vue' @@ -209,7 +210,7 @@ export default { this.$http.getBankBalances(this.address).then(res => { if (res && res.length > 0) { this.balance = res.reverse() - const token = this.balance.find(i => !i.denom.startsWith('ibc')) + const token = findNativeConfigToken(this.balance, this.$store.state.chains.selected) if (token) this.feeDenom = token.denom } }) @@ -287,6 +288,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -295,6 +297,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ diff --git a/src/views/OperationWithdrawComponent.vue b/src/views/OperationWithdrawComponent.vue index 1a455dc178..e352d0442a 100644 --- a/src/views/OperationWithdrawComponent.vue +++ b/src/views/OperationWithdrawComponent.vue @@ -136,7 +136,7 @@ import { required, email, url, between, alpha, integer, password, min, digits, alphaDash, length, } from '@validations' import { - formatToken, getLocalAccounts, getLocalChains, sign, timeIn, setLocalTxHistory, extractAccountNumberAndSequence, + formatToken, getLocalAccounts, getLocalChains, sign, timeIn, setLocalTxHistory, extractAccountNumberAndSequence, findNativeConfigToken, } from '@/libs/utils' import ToastificationContent from '@core/components/toastification/ToastificationContent.vue' import WalletInputVue from './components/WalletInput.vue' @@ -231,7 +231,7 @@ export default { this.$http.getBankBalances(this.address).then(res => { if (res && res.length > 0) { this.balance = res.reverse() - const token = this.balance.find(i => !i.denom.startsWith('ibc')) + const token = findNativeConfigToken(this.balance, this.$store.state.chains.selected) if (token) this.feeDenom = token.denom } }) @@ -311,6 +311,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -319,6 +320,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ diff --git a/src/views/components/KlineTrade/DepositeWindow.vue b/src/views/components/KlineTrade/DepositeWindow.vue index 7ab9e91c19..74590f4362 100644 --- a/src/views/components/KlineTrade/DepositeWindow.vue +++ b/src/views/components/KlineTrade/DepositeWindow.vue @@ -463,6 +463,7 @@ export default { chainId: this.chainId, } + const { sign_opts: signOpts } = this.$store.state.chains.selected sign( this.wallet, this.chainId, @@ -471,6 +472,7 @@ export default { txFee, this.memo, signerData, + signOpts, ).then(bodyBytes => { this.$http.broadcastTx(bodyBytes, this.selectedChain).then(res => { setLocalTxHistory({ op: 'ibc_sender', hash: res.txhash, time: new Date() }) From 899d7f1f85ea0a5ed1576a67fa2272af9f1217a8 Mon Sep 17 00:00:00 2001 From: Steven Khong Date: Mon, 4 Apr 2022 15:21:21 +0800 Subject: [PATCH 4/4] Add testnet config --- src/chains/README.md | 18 ++++++++++++++++++ src/chains/testnet/carbon.json | 24 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/chains/testnet/carbon.json diff --git a/src/chains/README.md b/src/chains/README.md index d804dc508c..faf3790b53 100644 --- a/src/chains/README.md +++ b/src/chains/README.md @@ -31,6 +31,24 @@ - **api** the rest api endpoint.(make sure that CORS is enabled: `Allow-Control-Allow-Origin: *`) - **rpc** the rpc endpoint, make sure that the port is added. rpc endpoint is only used for state sync. it's optional. - **assets** Native Assets on blockchain. + +# Additional Signing Configuration +```json +{ + "chain_name": "cosmos", + ... + "sign_opts": { + "keplr": { + "preferNoSetFee": true, + "preferNoSetMemo": true + } + }, + ... +} +``` +- **sign_opts** (optional) configuration for sign requests, only Keplr is supported at the moment. +- **sign_opts.keplr** (optional) KeplrSignOptions - See Keplr [documentation](https://docs.keplr.app/api/#interaction-options). + # Test please add these check points in comments with your PR, and adding your test result by clicking the checkbox of each line diff --git a/src/chains/testnet/carbon.json b/src/chains/testnet/carbon.json new file mode 100644 index 0000000000..807c22f40e --- /dev/null +++ b/src/chains/testnet/carbon.json @@ -0,0 +1,24 @@ +{ + "chain_name": "carbon", + "coingecko": "switcheo", + "api": "https://test-api.carbon.network", + "rpc": ["https://test-tm-api.carbon.network"], + "snapshot_provider": "", + "sdk_version": "0.45.2", + "coin_type": "118", + "min_tx_fee": "100000000", + "addr_prefix": "swth", + "logo": "/logos/carbon.svg", + "sign_opts": { + "keplr": { + "preferNoSetFee": true + } + }, + "assets": [{ + "base": "swth", + "symbol": "SWTH", + "exponent": "8", + "coingecko_id": "switcheo", + "logo": "/logos/carbon.svg" + }] +}