@keplr-wallet/hooks-evm 0.13.15-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +14 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +18 -0
- package/build/index.js.map +1 -0
- package/build/tx/amount.d.ts +27 -0
- package/build/tx/amount.js +238 -0
- package/build/tx/amount.js.map +1 -0
- package/build/tx/chain.d.ts +10 -0
- package/build/tx/chain.js +37 -0
- package/build/tx/chain.js.map +1 -0
- package/build/tx/errors.d.ts +30 -0
- package/build/tx/errors.js +84 -0
- package/build/tx/errors.js.map +1 -0
- package/build/tx/evm-fee-utils.d.ts +28 -0
- package/build/tx/evm-fee-utils.js +133 -0
- package/build/tx/evm-fee-utils.js.map +1 -0
- package/build/tx/fee.d.ts +61 -0
- package/build/tx/fee.js +523 -0
- package/build/tx/fee.js.map +1 -0
- package/build/tx/gas-simulator.d.ts +89 -0
- package/build/tx/gas-simulator.js +465 -0
- package/build/tx/gas-simulator.js.map +1 -0
- package/build/tx/gas.d.ts +12 -0
- package/build/tx/gas.js +84 -0
- package/build/tx/gas.js.map +1 -0
- package/build/tx/index.d.ts +13 -0
- package/build/tx/index.js +30 -0
- package/build/tx/index.js.map +1 -0
- package/build/tx/internal.d.ts +3 -0
- package/build/tx/internal.js +3 -0
- package/build/tx/internal.js.map +1 -0
- package/build/tx/name-service-ens.d.ts +40 -0
- package/build/tx/name-service-ens.js +189 -0
- package/build/tx/name-service-ens.js.map +1 -0
- package/build/tx/name-service.d.ts +20 -0
- package/build/tx/name-service.js +20 -0
- package/build/tx/name-service.js.map +1 -0
- package/build/tx/recipient.d.ts +35 -0
- package/build/tx/recipient.js +131 -0
- package/build/tx/recipient.js.map +1 -0
- package/build/tx/send-tx.d.ts +13 -0
- package/build/tx/send-tx.js +24 -0
- package/build/tx/send-tx.js.map +1 -0
- package/build/tx/sender.d.ts +12 -0
- package/build/tx/sender.js +73 -0
- package/build/tx/sender.js.map +1 -0
- package/build/tx/types.d.ts +102 -0
- package/build/tx/types.js +3 -0
- package/build/tx/types.js.map +1 -0
- package/build/tx/validate.d.ts +11 -0
- package/build/tx/validate.js +37 -0
- package/build/tx/validate.js.map +1 -0
- package/package.json +40 -0
- package/src/index.ts +1 -0
- package/src/tx/amount.ts +273 -0
- package/src/tx/chain.ts +31 -0
- package/src/tx/errors.ts +79 -0
- package/src/tx/evm-fee-utils.ts +217 -0
- package/src/tx/fee.ts +622 -0
- package/src/tx/gas-simulator.ts +567 -0
- package/src/tx/gas.ts +93 -0
- package/src/tx/index.ts +13 -0
- package/src/tx/internal.ts +4 -0
- package/src/tx/name-service-ens.ts +207 -0
- package/src/tx/name-service.ts +39 -0
- package/src/tx/recipient.ts +166 -0
- package/src/tx/send-tx.ts +55 -0
- package/src/tx/sender.ts +82 -0
- package/src/tx/types.ts +153 -0
- package/src/tx/validate.ts +55 -0
- package/tsconfig.check.json +90 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { AppCurrency, EvmGasSimulationOutcome, FeeCurrency, StdFee } from "@keplr-wallet/types";
|
|
2
|
+
import { CoinPretty, Dec } from "@keplr-wallet/unit";
|
|
3
|
+
import { NameService } from "./name-service";
|
|
4
|
+
import { IModularChainInfoImpl } from "@keplr-wallet/stores";
|
|
5
|
+
export interface ITxChainSetter {
|
|
6
|
+
chainId: string;
|
|
7
|
+
setChain(chainId: string): void;
|
|
8
|
+
modularChainInfo: IModularChainInfoImpl;
|
|
9
|
+
}
|
|
10
|
+
export interface UIProperties {
|
|
11
|
+
readonly error?: Error;
|
|
12
|
+
readonly warning?: Error;
|
|
13
|
+
readonly loadingState?: "loading" | "loading-block";
|
|
14
|
+
}
|
|
15
|
+
export type FeeType = "high" | "average" | "low";
|
|
16
|
+
export type EVMFeeType = FeeType | "custom";
|
|
17
|
+
export interface IGasConfig extends ITxChainSetter {
|
|
18
|
+
value: string;
|
|
19
|
+
setValue(value: string | number): void;
|
|
20
|
+
gas: number;
|
|
21
|
+
uiProperties: UIProperties;
|
|
22
|
+
}
|
|
23
|
+
export interface ISenderConfig extends ITxChainSetter {
|
|
24
|
+
value: string;
|
|
25
|
+
setValue(value: string): void;
|
|
26
|
+
sender: string;
|
|
27
|
+
uiProperties: UIProperties;
|
|
28
|
+
}
|
|
29
|
+
export interface IFeeConfig extends ITxChainSetter {
|
|
30
|
+
type: EVMFeeType;
|
|
31
|
+
setType(type: EVMFeeType): void;
|
|
32
|
+
maxFeePerGas: Dec | undefined;
|
|
33
|
+
maxPriorityFeePerGas: Dec | undefined;
|
|
34
|
+
gasPrice: Dec | undefined;
|
|
35
|
+
fee: CoinPretty | undefined;
|
|
36
|
+
maxFee: CoinPretty | undefined;
|
|
37
|
+
l1DataFee: Dec | undefined;
|
|
38
|
+
setL1DataFee(fee: Dec): void;
|
|
39
|
+
refreshEIP1559TxFees(): void;
|
|
40
|
+
customPriorityFee: string;
|
|
41
|
+
customPriorityFeeInput: string;
|
|
42
|
+
setCustomPriorityFee(fee: string): void;
|
|
43
|
+
isLegacyFeeMode: boolean;
|
|
44
|
+
customGasPrice: string;
|
|
45
|
+
customGasPriceInput: string;
|
|
46
|
+
setCustomGasPrice(value: string): void;
|
|
47
|
+
getEIP1559TxFees(feeType: EVMFeeType | "manual"): {
|
|
48
|
+
maxPriorityFeePerGas?: Dec;
|
|
49
|
+
maxFeePerGas?: Dec;
|
|
50
|
+
gasPrice?: Dec;
|
|
51
|
+
};
|
|
52
|
+
fees: CoinPretty[];
|
|
53
|
+
selectableFeeCurrencies: FeeCurrency[];
|
|
54
|
+
setFee(fee: {
|
|
55
|
+
type: EVMFeeType;
|
|
56
|
+
currency: FeeCurrency;
|
|
57
|
+
} | CoinPretty | CoinPretty[] | undefined): void;
|
|
58
|
+
getFeeTypePrettyForFeeCurrency(currency: FeeCurrency, feeType: EVMFeeType): CoinPretty;
|
|
59
|
+
toStdFee(): StdFee;
|
|
60
|
+
uiProperties: UIProperties;
|
|
61
|
+
}
|
|
62
|
+
export interface IRecipientConfig extends ITxChainSetter {
|
|
63
|
+
value: string;
|
|
64
|
+
setValue(value: string): void;
|
|
65
|
+
recipient: string;
|
|
66
|
+
uiProperties: UIProperties;
|
|
67
|
+
}
|
|
68
|
+
export interface IRecipientConfigWithNameServices extends IRecipientConfig {
|
|
69
|
+
preferredNameService: string | undefined;
|
|
70
|
+
setPreferredNameService(nameService: string | undefined): void;
|
|
71
|
+
getNameService(type: string): NameService | undefined;
|
|
72
|
+
getNameServices(): NameService[];
|
|
73
|
+
nameServiceResult: {
|
|
74
|
+
type: string;
|
|
75
|
+
address: string;
|
|
76
|
+
fullName: string;
|
|
77
|
+
domain: string;
|
|
78
|
+
suffix: string;
|
|
79
|
+
}[];
|
|
80
|
+
}
|
|
81
|
+
export interface IAmountConfig extends ITxChainSetter {
|
|
82
|
+
amount: CoinPretty[];
|
|
83
|
+
value: string;
|
|
84
|
+
setValue(value: string): void;
|
|
85
|
+
currency: AppCurrency;
|
|
86
|
+
setCurrency(currency: AppCurrency | undefined): void;
|
|
87
|
+
canUseCurrency(currency: AppCurrency): boolean;
|
|
88
|
+
fraction: number;
|
|
89
|
+
setFraction(fraction: number): void;
|
|
90
|
+
uiProperties: UIProperties;
|
|
91
|
+
}
|
|
92
|
+
export interface IGasSimulator {
|
|
93
|
+
enabled: boolean;
|
|
94
|
+
setEnabled(value: boolean): void;
|
|
95
|
+
isSimulating: boolean;
|
|
96
|
+
gasEstimated: number | undefined;
|
|
97
|
+
gasAdjustment: number;
|
|
98
|
+
gasAdjustmentValue: string;
|
|
99
|
+
setGasAdjustmentValue(gasAdjustment: string | number): void;
|
|
100
|
+
evmSimulationOutcome?: EvmGasSimulationOutcome;
|
|
101
|
+
uiProperties: UIProperties;
|
|
102
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tx/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IAmountConfig, IFeeConfig, IGasConfig, IGasSimulator, IRecipientConfig, ISenderConfig } from "./types";
|
|
2
|
+
export declare const useTxConfigsValidate: (configs: {
|
|
3
|
+
amountConfig?: IAmountConfig;
|
|
4
|
+
senderConfig?: ISenderConfig;
|
|
5
|
+
recipientConfig?: IRecipientConfig;
|
|
6
|
+
gasConfig?: IGasConfig;
|
|
7
|
+
feeConfig?: IFeeConfig;
|
|
8
|
+
gasSimulator?: IGasSimulator;
|
|
9
|
+
}) => {
|
|
10
|
+
interactionBlocked: boolean;
|
|
11
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useTxConfigsValidate = void 0;
|
|
4
|
+
// CONTRACT: Use with `observer`
|
|
5
|
+
const useTxConfigsValidate = (configs) => {
|
|
6
|
+
const interactionBlocked = (() => {
|
|
7
|
+
var _a, _b, _c, _d, _e, _f;
|
|
8
|
+
const amountConfigUIProperties = (_a = configs.amountConfig) === null || _a === void 0 ? void 0 : _a.uiProperties;
|
|
9
|
+
const senderConfigUIProperties = (_b = configs.senderConfig) === null || _b === void 0 ? void 0 : _b.uiProperties;
|
|
10
|
+
const recipientConfigUIProperties = (_c = configs.recipientConfig) === null || _c === void 0 ? void 0 : _c.uiProperties;
|
|
11
|
+
const gasConfigUIProperties = (_d = configs.gasConfig) === null || _d === void 0 ? void 0 : _d.uiProperties;
|
|
12
|
+
const feeConfigUIProperties = (_e = configs.feeConfig) === null || _e === void 0 ? void 0 : _e.uiProperties;
|
|
13
|
+
const gasSimulatorUIProperties = (_f = configs.gasSimulator) === null || _f === void 0 ? void 0 : _f.uiProperties;
|
|
14
|
+
if ((amountConfigUIProperties === null || amountConfigUIProperties === void 0 ? void 0 : amountConfigUIProperties.error) ||
|
|
15
|
+
(senderConfigUIProperties === null || senderConfigUIProperties === void 0 ? void 0 : senderConfigUIProperties.error) ||
|
|
16
|
+
(recipientConfigUIProperties === null || recipientConfigUIProperties === void 0 ? void 0 : recipientConfigUIProperties.error) ||
|
|
17
|
+
(gasConfigUIProperties === null || gasConfigUIProperties === void 0 ? void 0 : gasConfigUIProperties.error) ||
|
|
18
|
+
(feeConfigUIProperties === null || feeConfigUIProperties === void 0 ? void 0 : feeConfigUIProperties.error) ||
|
|
19
|
+
(gasSimulatorUIProperties === null || gasSimulatorUIProperties === void 0 ? void 0 : gasSimulatorUIProperties.error)) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if ((amountConfigUIProperties === null || amountConfigUIProperties === void 0 ? void 0 : amountConfigUIProperties.loadingState) === "loading-block" ||
|
|
23
|
+
(senderConfigUIProperties === null || senderConfigUIProperties === void 0 ? void 0 : senderConfigUIProperties.loadingState) === "loading-block" ||
|
|
24
|
+
(recipientConfigUIProperties === null || recipientConfigUIProperties === void 0 ? void 0 : recipientConfigUIProperties.loadingState) === "loading-block" ||
|
|
25
|
+
(gasConfigUIProperties === null || gasConfigUIProperties === void 0 ? void 0 : gasConfigUIProperties.loadingState) === "loading-block" ||
|
|
26
|
+
(feeConfigUIProperties === null || feeConfigUIProperties === void 0 ? void 0 : feeConfigUIProperties.loadingState) === "loading-block" ||
|
|
27
|
+
(gasSimulatorUIProperties === null || gasSimulatorUIProperties === void 0 ? void 0 : gasSimulatorUIProperties.loadingState) === "loading-block") {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
})();
|
|
32
|
+
return {
|
|
33
|
+
interactionBlocked,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
exports.useTxConfigsValidate = useTxConfigsValidate;
|
|
37
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tx/validate.ts"],"names":[],"mappings":";;;AASA,gCAAgC;AACzB,MAAM,oBAAoB,GAAG,CAAC,OAOpC,EAAE,EAAE;IACH,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE;;QAC/B,MAAM,wBAAwB,GAAG,MAAA,OAAO,CAAC,YAAY,0CAAE,YAAY,CAAC;QACpE,MAAM,wBAAwB,GAAG,MAAA,OAAO,CAAC,YAAY,0CAAE,YAAY,CAAC;QACpE,MAAM,2BAA2B,GAAG,MAAA,OAAO,CAAC,eAAe,0CAAE,YAAY,CAAC;QAC1E,MAAM,qBAAqB,GAAG,MAAA,OAAO,CAAC,SAAS,0CAAE,YAAY,CAAC;QAC9D,MAAM,qBAAqB,GAAG,MAAA,OAAO,CAAC,SAAS,0CAAE,YAAY,CAAC;QAC9D,MAAM,wBAAwB,GAAG,MAAA,OAAO,CAAC,YAAY,0CAAE,YAAY,CAAC;QAEpE,IACE,CAAA,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAE,KAAK;aAC/B,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAE,KAAK,CAAA;aAC/B,2BAA2B,aAA3B,2BAA2B,uBAA3B,2BAA2B,CAAE,KAAK,CAAA;aAClC,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,KAAK,CAAA;aAC5B,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,KAAK,CAAA;aAC5B,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAE,KAAK,CAAA,EAC/B;YACA,OAAO,IAAI,CAAC;SACb;QAED,IACE,CAAA,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAE,YAAY,MAAK,eAAe;YAC1D,CAAA,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAE,YAAY,MAAK,eAAe;YAC1D,CAAA,2BAA2B,aAA3B,2BAA2B,uBAA3B,2BAA2B,CAAE,YAAY,MAAK,eAAe;YAC7D,CAAA,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,YAAY,MAAK,eAAe;YACvD,CAAA,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,YAAY,MAAK,eAAe;YACvD,CAAA,wBAAwB,aAAxB,wBAAwB,uBAAxB,wBAAwB,CAAE,YAAY,MAAK,eAAe,EAC1D;YACA,OAAO,IAAI,CAAC;SACb;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO;QACL,kBAAkB;KACnB,CAAC;AACJ,CAAC,CAAC;AA5CW,QAAA,oBAAoB,wBA4C/B"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@keplr-wallet/hooks-evm",
|
|
3
|
+
"version": "0.13.15-rc.0",
|
|
4
|
+
"main": "build/index.js",
|
|
5
|
+
"author": "chainapsis",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/chainapsis/keplr-wallet.git"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"clean": "rm -rf node_modules; rm -rf build",
|
|
16
|
+
"build": "npx tsc",
|
|
17
|
+
"dev": "npx tsc -w",
|
|
18
|
+
"test": "npx jest --passWithNoTests",
|
|
19
|
+
"lint-test": "npx eslint \"src/**/*\" && npx prettier --check \"src/**/*\"",
|
|
20
|
+
"lint-fix": "npx eslint --fix \"src/**/*\" && npx prettier --write \"src/**/*\"",
|
|
21
|
+
"typecheck": "npx tsc -p tsconfig.check.json"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@ethersproject/address": "^5.7.0",
|
|
25
|
+
"@ethersproject/providers": "^5.7.0",
|
|
26
|
+
"@keplr-wallet/common": "0.13.15-rc.0",
|
|
27
|
+
"@keplr-wallet/cosmos": "0.13.15-rc.0",
|
|
28
|
+
"@keplr-wallet/simple-fetch": "0.13.15-rc.0",
|
|
29
|
+
"@keplr-wallet/stores": "0.13.15-rc.0",
|
|
30
|
+
"@keplr-wallet/stores-eth": "0.13.15-rc.0",
|
|
31
|
+
"@keplr-wallet/types": "0.13.15-rc.0",
|
|
32
|
+
"@keplr-wallet/unit": "0.13.15-rc.0",
|
|
33
|
+
"buffer": "^6.0.3"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"mobx": "^6",
|
|
37
|
+
"mobx-utils": "^6",
|
|
38
|
+
"react": "^16.8.0 || ^17 || ^18"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./tx";
|
package/src/tx/amount.ts
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IAmountConfig,
|
|
3
|
+
IFeeConfig,
|
|
4
|
+
ISenderConfig,
|
|
5
|
+
UIProperties,
|
|
6
|
+
} from "./types";
|
|
7
|
+
import { TxChainSetter } from "./chain";
|
|
8
|
+
import { ChainGetter } from "@keplr-wallet/stores";
|
|
9
|
+
import { action, computed, makeObservable, observable } from "mobx";
|
|
10
|
+
import { AppCurrency } from "@keplr-wallet/types";
|
|
11
|
+
import {
|
|
12
|
+
EmptyAmountError,
|
|
13
|
+
InsufficientAmountError,
|
|
14
|
+
InvalidNumberAmountError,
|
|
15
|
+
NegativeAmountError,
|
|
16
|
+
ZeroAmountError,
|
|
17
|
+
} from "./errors";
|
|
18
|
+
import { CoinPretty, Dec, DecUtils } from "@keplr-wallet/unit";
|
|
19
|
+
import { useState } from "react";
|
|
20
|
+
import { QueriesStore } from "./internal";
|
|
21
|
+
|
|
22
|
+
export class AmountConfig extends TxChainSetter implements IAmountConfig {
|
|
23
|
+
@observable.ref
|
|
24
|
+
protected _currency?: AppCurrency = undefined;
|
|
25
|
+
|
|
26
|
+
@observable
|
|
27
|
+
protected _value: string = "";
|
|
28
|
+
|
|
29
|
+
@observable
|
|
30
|
+
protected _fraction: number = 0;
|
|
31
|
+
|
|
32
|
+
@observable.ref
|
|
33
|
+
protected _feeConfig: IFeeConfig | undefined = undefined;
|
|
34
|
+
|
|
35
|
+
constructor(
|
|
36
|
+
chainGetter: ChainGetter,
|
|
37
|
+
protected readonly queriesStore: QueriesStore,
|
|
38
|
+
initialChainId: string,
|
|
39
|
+
protected readonly senderConfig: ISenderConfig
|
|
40
|
+
) {
|
|
41
|
+
super(chainGetter, initialChainId);
|
|
42
|
+
|
|
43
|
+
makeObservable(this);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get feeConfig(): IFeeConfig | undefined {
|
|
47
|
+
return this._feeConfig;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@action
|
|
51
|
+
setFeeConfig(feeConfig: IFeeConfig | undefined) {
|
|
52
|
+
this._feeConfig = feeConfig;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@computed
|
|
56
|
+
get value(): string {
|
|
57
|
+
if (this.fraction > 0) {
|
|
58
|
+
let result = this.queriesStore
|
|
59
|
+
.get(this.chainId)
|
|
60
|
+
.queryBalances.getQueryEthereumHexAddress(this.senderConfig.sender)
|
|
61
|
+
.getBalance(this.currency)?.balance;
|
|
62
|
+
if (!result) {
|
|
63
|
+
return "0";
|
|
64
|
+
}
|
|
65
|
+
if (this.feeConfig && this.feeConfig.maxFee) {
|
|
66
|
+
if (
|
|
67
|
+
this.currency.coinMinimalDenom ===
|
|
68
|
+
this.feeConfig.maxFee.currency.coinMinimalDenom
|
|
69
|
+
) {
|
|
70
|
+
result = result.sub(this.feeConfig.maxFee);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (result.toDec().lte(new Dec(0))) {
|
|
74
|
+
return "0";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return result
|
|
78
|
+
.mul(new Dec(this.fraction))
|
|
79
|
+
.trim(true)
|
|
80
|
+
.locale(false)
|
|
81
|
+
.hideDenom(true)
|
|
82
|
+
.toString();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return this._value;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@action
|
|
89
|
+
setValue(value: string): void {
|
|
90
|
+
if (value.startsWith(".")) {
|
|
91
|
+
value = "0" + value;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this._value = value;
|
|
95
|
+
|
|
96
|
+
this.setFraction(0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@computed
|
|
100
|
+
get amount(): CoinPretty[] {
|
|
101
|
+
let amount: Dec;
|
|
102
|
+
try {
|
|
103
|
+
if (this.value.trim() === "") {
|
|
104
|
+
amount = new Dec(0);
|
|
105
|
+
} else {
|
|
106
|
+
amount = new Dec(this.value);
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
amount = new Dec(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
return [
|
|
114
|
+
new CoinPretty(
|
|
115
|
+
this.currency,
|
|
116
|
+
amount
|
|
117
|
+
.mul(DecUtils.getTenExponentN(this.currency.coinDecimals))
|
|
118
|
+
.truncate()
|
|
119
|
+
),
|
|
120
|
+
];
|
|
121
|
+
} catch {
|
|
122
|
+
return [new CoinPretty(this.currency, new Dec(0))];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@computed
|
|
127
|
+
get currency(): AppCurrency {
|
|
128
|
+
const u = this.modularChainInfo.unwrapped;
|
|
129
|
+
if (u.type !== "evm" && u.type !== "ethermint") {
|
|
130
|
+
throw new Error("Chain is not an EVM compatible chain");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (this._currency) {
|
|
134
|
+
const allCurrencies: AppCurrency[] = [
|
|
135
|
+
u.evm.nativeCurrency,
|
|
136
|
+
...(u.evm.tokens ?? []),
|
|
137
|
+
];
|
|
138
|
+
const find = allCurrencies.find(
|
|
139
|
+
(cur) => cur.coinMinimalDenom === this._currency!.coinMinimalDenom
|
|
140
|
+
);
|
|
141
|
+
if (find) {
|
|
142
|
+
return find;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return u.evm.nativeCurrency;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@action
|
|
150
|
+
setCurrency(currency: AppCurrency | undefined) {
|
|
151
|
+
if (currency?.coinMinimalDenom !== this._currency?.coinMinimalDenom) {
|
|
152
|
+
this._value = "";
|
|
153
|
+
this.setFraction(0);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this._currency = currency;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get fraction(): number {
|
|
160
|
+
return this._fraction;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@action
|
|
164
|
+
setFraction(fraction: number): void {
|
|
165
|
+
this._fraction = fraction;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
canUseCurrency(currency: AppCurrency): boolean {
|
|
169
|
+
const u = this.modularChainInfo.unwrapped;
|
|
170
|
+
if (u.type !== "evm" && u.type !== "ethermint") {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const allCurrencies: AppCurrency[] = [
|
|
175
|
+
u.evm.nativeCurrency,
|
|
176
|
+
...(u.evm.tokens ?? []),
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
allCurrencies.find(
|
|
181
|
+
(cur) => cur.coinMinimalDenom === currency.coinMinimalDenom
|
|
182
|
+
) != null
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@computed
|
|
187
|
+
get uiProperties(): UIProperties {
|
|
188
|
+
if (!this.currency) {
|
|
189
|
+
return {
|
|
190
|
+
error: new Error("Currency to send not set"),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (this.value.trim() === "") {
|
|
195
|
+
return {
|
|
196
|
+
error: new EmptyAmountError("Amount is empty"),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
const dec = new Dec(this.value);
|
|
202
|
+
if (dec.equals(new Dec(0))) {
|
|
203
|
+
return {
|
|
204
|
+
error: new ZeroAmountError("Amount is zero"),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (dec.lt(new Dec(0))) {
|
|
208
|
+
return {
|
|
209
|
+
error: new NegativeAmountError("Enter a positive number"),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
new CoinPretty(
|
|
214
|
+
this.currency,
|
|
215
|
+
dec.mul(DecUtils.getTenExponentN(this.currency.coinDecimals)).truncate()
|
|
216
|
+
);
|
|
217
|
+
} catch {
|
|
218
|
+
return {
|
|
219
|
+
error: new InvalidNumberAmountError("Enter a valid number"),
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
for (const amount of this.amount) {
|
|
224
|
+
const bal = this.queriesStore
|
|
225
|
+
.get(this.chainId)
|
|
226
|
+
.queryBalances.getQueryEthereumHexAddress(this.senderConfig.sender)
|
|
227
|
+
.getBalance(amount.currency);
|
|
228
|
+
|
|
229
|
+
if (!bal) {
|
|
230
|
+
return {
|
|
231
|
+
warning: new Error(
|
|
232
|
+
`Can't parse the balance for ${amount.currency.coinMinimalDenom}`
|
|
233
|
+
),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (bal.error) {
|
|
238
|
+
return {
|
|
239
|
+
warning: new Error("Failed to fetch balance"),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (!bal.response) {
|
|
244
|
+
return {
|
|
245
|
+
loadingState: "loading-block",
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (bal.balance.toDec().lt(amount.toDec())) {
|
|
250
|
+
return {
|
|
251
|
+
error: new InsufficientAmountError("Insufficient balance"),
|
|
252
|
+
loadingState: bal.isFetching ? "loading" : undefined,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return {};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export const useAmountConfig = (
|
|
262
|
+
chainGetter: ChainGetter,
|
|
263
|
+
queriesStore: QueriesStore,
|
|
264
|
+
chainId: string,
|
|
265
|
+
senderConfig: ISenderConfig
|
|
266
|
+
) => {
|
|
267
|
+
const [txConfig] = useState(
|
|
268
|
+
() => new AmountConfig(chainGetter, queriesStore, chainId, senderConfig)
|
|
269
|
+
);
|
|
270
|
+
txConfig.setChain(chainId);
|
|
271
|
+
|
|
272
|
+
return txConfig;
|
|
273
|
+
};
|
package/src/tx/chain.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { action, computed, makeObservable, observable } from "mobx";
|
|
2
|
+
import { ChainGetter, IModularChainInfoImpl } from "@keplr-wallet/stores";
|
|
3
|
+
import { ITxChainSetter } from "./types";
|
|
4
|
+
|
|
5
|
+
export class TxChainSetter implements ITxChainSetter {
|
|
6
|
+
@observable
|
|
7
|
+
protected _chainId: string;
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
protected readonly chainGetter: ChainGetter,
|
|
11
|
+
initialChainId: string
|
|
12
|
+
) {
|
|
13
|
+
this._chainId = initialChainId;
|
|
14
|
+
|
|
15
|
+
makeObservable(this);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@computed
|
|
19
|
+
get modularChainInfo(): IModularChainInfoImpl {
|
|
20
|
+
return this.chainGetter.getModularChain(this.chainId);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get chainId(): string {
|
|
24
|
+
return this._chainId;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@action
|
|
28
|
+
setChain(chainId: string) {
|
|
29
|
+
this._chainId = chainId;
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/tx/errors.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export class EmptyAddressError extends Error {
|
|
2
|
+
constructor(m: string) {
|
|
3
|
+
super(m);
|
|
4
|
+
// Set the prototype explicitly.
|
|
5
|
+
Object.setPrototypeOf(this, EmptyAddressError.prototype);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class InvalidHexError extends Error {
|
|
10
|
+
constructor(m: string) {
|
|
11
|
+
super(m);
|
|
12
|
+
// Set the prototype explicitly.
|
|
13
|
+
Object.setPrototypeOf(this, InvalidHexError.prototype);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class EmptyAmountError extends Error {
|
|
18
|
+
constructor(m: string) {
|
|
19
|
+
super(m);
|
|
20
|
+
// Set the prototype explicitly.
|
|
21
|
+
Object.setPrototypeOf(this, EmptyAmountError.prototype);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class InvalidNumberAmountError extends Error {
|
|
26
|
+
constructor(m: string) {
|
|
27
|
+
super(m);
|
|
28
|
+
// Set the prototype explicitly.
|
|
29
|
+
Object.setPrototypeOf(this, InvalidNumberAmountError.prototype);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class ZeroAmountError extends Error {
|
|
34
|
+
constructor(m: string) {
|
|
35
|
+
super(m);
|
|
36
|
+
// Set the prototype explicitly.
|
|
37
|
+
Object.setPrototypeOf(this, ZeroAmountError.prototype);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class NegativeAmountError extends Error {
|
|
42
|
+
constructor(m: string) {
|
|
43
|
+
super(m);
|
|
44
|
+
// Set the prototype explicitly.
|
|
45
|
+
Object.setPrototypeOf(this, NegativeAmountError.prototype);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class InsufficientAmountError extends Error {
|
|
50
|
+
constructor(m: string) {
|
|
51
|
+
super(m);
|
|
52
|
+
// Set the prototype explicitly.
|
|
53
|
+
Object.setPrototypeOf(this, InsufficientAmountError.prototype);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class InsufficientFeeError extends Error {
|
|
58
|
+
constructor(m: string) {
|
|
59
|
+
super(m);
|
|
60
|
+
// Set the prototype explicitly.
|
|
61
|
+
Object.setPrototypeOf(this, InsufficientFeeError.prototype);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class ENSIsFetchingError extends Error {
|
|
66
|
+
constructor(m: string) {
|
|
67
|
+
super(m);
|
|
68
|
+
// Set the prototype explicitly.
|
|
69
|
+
Object.setPrototypeOf(this, ENSIsFetchingError.prototype);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class ENSFailedToFetchError extends Error {
|
|
74
|
+
constructor(m: string) {
|
|
75
|
+
super(m);
|
|
76
|
+
// Set the prototype explicitly.
|
|
77
|
+
Object.setPrototypeOf(this, ENSFailedToFetchError.prototype);
|
|
78
|
+
}
|
|
79
|
+
}
|