Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EVM native currency #1188

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions apps/extension/src/pages/send/amount/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ export const SendAmountPage: FunctionComponent = observer(() => {
const isERC20 = sendingDenomHelper.type === "erc20";
const isSendingNativeToken =
sendingDenomHelper.type === "native" &&
(chainInfo.stakeCurrency?.coinMinimalDenom ??
(chainInfo.evm?.nativeCurrency?.coinMinimalDenom ??
chainInfo.currencies[0].coinMinimalDenom) ===
sendingDenomHelper.denom;
const newIsEvmTx =
Expand All @@ -281,7 +281,28 @@ export const SendAmountPage: FunctionComponent = observer(() => {
? account.ethereumHexAddress
: account.bech32Address;

if (sendConfigs.feeConfig.type !== "manual") {
if (newIsEvmTx && chainInfo.evm?.nativeCurrency != null) {
sendConfigs.feeConfig.setSelectableFeeCurrencies([
chainInfo.evm.nativeCurrency,
]);
sendConfigs.feeConfig.setFee({
type: sendConfigs.feeConfig.type,
currency: chainInfo.evm.nativeCurrency,
});
} else {
sendConfigs.feeConfig.setSelectableFeeCurrencies(
chainInfo.feeCurrencies.slice(0, 1)
);
sendConfigs.feeConfig.setFee({
type: sendConfigs.feeConfig.type,
currency: sendConfigs.feeConfig.selectableFeeCurrencies[0],
});
}
}

sendConfigs.senderConfig.setValue(newSenderAddress);

setIsEvmTx(newIsEvmTx);
ethereumAccount.setIsSendingTx(false);
}
Expand All @@ -293,8 +314,10 @@ export const SendAmountPage: FunctionComponent = observer(() => {
sendConfigs.amountConfig.currency.coinMinimalDenom,
sendConfigs.recipientConfig.isRecipientEthereumHexAddress,
sendConfigs.senderConfig,
chainInfo.stakeCurrency?.coinMinimalDenom,
chainInfo.currencies,
sendConfigs.feeConfig,
chainInfo.evm?.nativeCurrency,
chainInfo.feeCurrencies,
]);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const EthSendTokenTxPretty: React.FunctionComponent<{

const currency = erc20ContractAddress
? chainInfo.forceFindCurrency(`erc20:${erc20ContractAddress}`)
: chainInfo.currencies[0];
: chainInfo.evm?.nativeCurrency ?? chainInfo.currencies[0];
const amountCoinPretty = new CoinPretty(currency, new Dec(Number(amount)));

const theme = useTheme();
Expand Down
2 changes: 1 addition & 1 deletion apps/extension/src/pages/sign/ethereum/view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export const EthereumSigningView: FunctionComponent<{
if (gasPriceFromTx > 0) {
feeConfig.setFee(
new CoinPretty(
chainInfo.currencies[0],
chainInfo.evm?.nativeCurrency ?? chainInfo.currencies[0],
new Dec(gasConfig.gas).mul(new Dec(gasPriceFromTx))
)
);
Expand Down
59 changes: 41 additions & 18 deletions packages/chain-validator/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ export const ChainInfoSchema = Joi.object<ChainInfo>({
evm: Joi.object({
chainId: Joi.number().required(),
rpc: Joi.string()
.uri()
.custom((value: string) => {
if (value.includes("?")) {
throw new Error("evm rpc should not have query string");
Expand All @@ -202,6 +203,16 @@ export const ChainInfoSchema = Joi.object<ChainInfo>({
return value;
})
.required(),
websocket: Joi.string()
.uri()
.custom((value: string) => {
if (value.includes("?")) {
throw new Error("evm websocket should not have query string");
}

return value;
}),
nativeCurrency: CurrencySchema,
}).unknown(true),
nodeProvider: Joi.object({
name: Joi.string().min(1).max(30).required(),
Expand Down Expand Up @@ -354,39 +365,51 @@ export const ChainInfoSchema = Joi.object<ChainInfo>({
}
}

// evm only chain이 아닌 ethermint같은 경우에만 위의 밸리데이션을 수행한다.
// evm only chain이 아닌 ethermint같은 경우에만 아래의 밸리데이션을 수행한다.
if (EIP155ChainIdSchema.validate(value.chainId).error) {
if (value.evm) {
const evmNativeCurency = value.evm.nativeCurrency;
const firstCurrency = value.currencies[0];
if (firstCurrency.coinDecimals !== 18) {
if (
evmNativeCurency != null &&
firstCurrency.coinMinimalDenom === evmNativeCurency.coinMinimalDenom
) {
throw new Error(
"The first currency's coin decimals should be 18 for EVM chain"
"The first currency should not be same with EVM native currency"
);
}
if (value.stakeCurrency) {
if (value.stakeCurrency.coinDecimals !== 18) {

if (evmNativeCurency == null) {
if (firstCurrency.coinDecimals !== 18) {
throw new Error(
"The stake currency's coin decimals should be 18 for EVM chain"
"The first currency's coin decimals should be 18 for EVM chain"
);
}
const cur = value.currencies.find(
(cur) =>
cur.coinMinimalDenom === value.stakeCurrency?.coinMinimalDenom
);
if (cur) {
if (cur.coinDecimals !== 18) {
if (value.stakeCurrency) {
if (value.stakeCurrency.coinDecimals !== 18) {
throw new Error(
"The stake currency's coin decimals should be 18 for EVM chain"
);
}
const cur = value.currencies.find(
(cur) =>
cur.coinMinimalDenom === value.stakeCurrency?.coinMinimalDenom
);
if (cur) {
if (cur.coinDecimals !== 18) {
throw new Error(
"The stake currency's coin decimals should be 18 for EVM chain"
);
}
}
}
}

const firstFeeCurrency = value.feeCurrencies[0];
if (firstFeeCurrency.coinDecimals !== 18) {
throw new Error(
"The first fee currency's coin decimals should be 18 for EVM chain"
);
const firstFeeCurrency = value.feeCurrencies[0];
if (firstFeeCurrency.coinDecimals !== 18) {
throw new Error(
"The first fee currency's coin decimals should be 18 for EVM chain"
);
}
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions packages/hooks/src/tx/fee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export class FeeConfig extends TxChainSetter implements IFeeConfig {
| CoinPretty[]
| undefined = undefined;

@observable.ref
protected _selectableFeeCurrencies: FeeCurrency[] | undefined = undefined;
/**
* `additionAmountToNeedFee` indicated that the fee config should consider the amount config's amount
* when checking that the fee is sufficient to send tx.
Expand Down Expand Up @@ -172,8 +174,20 @@ export class FeeConfig extends TxChainSetter implements IFeeConfig {
}
}

@action
setSelectableFeeCurrencies(currencies: FeeCurrency[]) {
this._selectableFeeCurrencies = currencies;
}

@computed
get selectableFeeCurrencies(): FeeCurrency[] {
if (
this._selectableFeeCurrencies &&
this._selectableFeeCurrencies.length > 0
) {
return this._selectableFeeCurrencies;
}

if (
this.chainInfo.bip44.coinType === 60 ||
this.chainInfo.hasFeature("eth-address-gen") ||
Expand Down
7 changes: 4 additions & 3 deletions packages/stores-eth/src/queries/balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ export class ObservableQueryEthAccountBalanceImpl
get balance(): CoinPretty {
const denom = this.denomHelper.denom;
const chainInfo = this.chainGetter.getChain(this.chainId);
const currency = chainInfo.currencies.find(
(cur) => cur.coinMinimalDenom === denom
);
const currency =
chainInfo?.evm?.nativeCurrency ??
chainInfo.currencies.find((cur) => cur.coinMinimalDenom === denom);

if (!currency) {
throw new Error(`Unknown currency: ${denom}`);
}
Expand Down
3 changes: 2 additions & 1 deletion packages/stores/src/chain/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
BIP44,
ChainInfo,
Currency,
EVMInfo,
FeeCurrency,
} from "@keplr-wallet/types";
import { IChainInfoImpl, IChainStore, CurrencyRegistrar } from "./types";
Expand Down Expand Up @@ -477,7 +478,7 @@ export class ChainInfoImpl<C extends ChainInfo = ChainInfo>
return this._embedded.chainSymbolImageUrl;
}

get evm(): { chainId: number; rpc: string } | undefined {
get evm(): EVMInfo | undefined {
return this._embedded.evm;
}

Expand Down
8 changes: 2 additions & 6 deletions packages/stores/src/chain/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
BIP44,
ChainInfo,
Currency,
EVMInfo,
FeeCurrency,
} from "@keplr-wallet/types";

Expand Down Expand Up @@ -62,11 +63,6 @@ export interface IChainInfoImpl<C extends ChainInfo = ChainInfo> {
readonly walletUrl: string | undefined;
readonly walletUrlForStaking: string | undefined;
readonly chainSymbolImageUrl: string | undefined;
readonly evm:
| {
chainId: number;
rpc: string;
}
| undefined;
readonly evm: EVMInfo | undefined;
readonly hideInUI: boolean | undefined;
}
3 changes: 3 additions & 0 deletions packages/types/src/ethereum.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { AppCurrency } from "./currency";

export enum EthSignType {
MESSAGE = "message",
TRANSACTION = "transaction",
Expand Down Expand Up @@ -45,6 +47,7 @@ export interface EVMInfo {
chainId: number;
rpc: string;
websocket?: string;
nativeCurrency?: AppCurrency;
}

export interface EthereumSignResponse {
Expand Down
Loading