@keplr-wallet/hooks-starknet 0.12.133-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/.eslintignore +2 -0
- package/.prettierignore +2 -0
- package/LICENSE +209 -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 +230 -0
- package/build/tx/amount.js.map +1 -0
- package/build/tx/chain.d.ts +11 -0
- package/build/tx/chain.js +37 -0
- package/build/tx/chain.js.map +1 -0
- package/build/tx/errors.d.ts +48 -0
- package/build/tx/errors.js +132 -0
- package/build/tx/errors.js.map +1 -0
- package/build/tx/fee.d.ts +30 -0
- package/build/tx/fee.js +167 -0
- package/build/tx/fee.js.map +1 -0
- package/build/tx/gas-simulator.d.ts +72 -0
- package/build/tx/gas-simulator.js +491 -0
- package/build/tx/gas-simulator.js.map +1 -0
- package/build/tx/gas.d.ts +14 -0
- package/build/tx/gas.js +116 -0
- package/build/tx/gas.js.map +1 -0
- package/build/tx/index.d.ts +12 -0
- package/build/tx/index.js +29 -0
- package/build/tx/index.js.map +1 -0
- package/build/tx/noop-amount.d.ts +20 -0
- package/build/tx/noop-amount.js +90 -0
- package/build/tx/noop-amount.js.map +1 -0
- package/build/tx/recipient.d.ts +12 -0
- package/build/tx/recipient.js +80 -0
- package/build/tx/recipient.js.map +1 -0
- package/build/tx/send-tx.d.ts +9 -0
- package/build/tx/send-tx.js +22 -0
- package/build/tx/send-tx.js.map +1 -0
- package/build/tx/sender.d.ts +14 -0
- package/build/tx/sender.js +88 -0
- package/build/tx/sender.js.map +1 -0
- package/build/tx/types.d.ts +63 -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 +52 -0
- package/build/tx/validate.js.map +1 -0
- package/jest.config.js +5 -0
- package/package.json +43 -0
- package/src/index.ts +1 -0
- package/src/tx/amount.ts +275 -0
- package/src/tx/chain.ts +32 -0
- package/src/tx/errors.ts +127 -0
- package/src/tx/fee.ts +209 -0
- package/src/tx/gas-simulator.ts +571 -0
- package/src/tx/gas.ts +131 -0
- package/src/tx/index.ts +12 -0
- package/src/tx/noop-amount.ts +92 -0
- package/src/tx/recipient.ts +82 -0
- package/src/tx/send-tx.ts +53 -0
- package/src/tx/sender.ts +104 -0
- package/src/tx/types.ts +97 -0
- package/src/tx/validate.ts +70 -0
- package/tsconfig.json +13 -0
package/src/tx/amount.ts
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
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 { ERC20Currency } from "@keplr-wallet/types";
|
|
11
|
+
import {
|
|
12
|
+
EmptyAmountError,
|
|
13
|
+
InsufficientAmountError,
|
|
14
|
+
InvalidNumberAmountError,
|
|
15
|
+
NegativeAmountError,
|
|
16
|
+
NotSupportedCurrencyError,
|
|
17
|
+
ZeroAmountError,
|
|
18
|
+
} from "./errors";
|
|
19
|
+
import { CoinPretty, Dec, DecUtils } from "@keplr-wallet/unit";
|
|
20
|
+
import { useState } from "react";
|
|
21
|
+
import { StarknetQueriesStore } from "@keplr-wallet/stores-starknet";
|
|
22
|
+
|
|
23
|
+
export class AmountConfig extends TxChainSetter implements IAmountConfig {
|
|
24
|
+
@observable.ref
|
|
25
|
+
protected _currency?: ERC20Currency = undefined;
|
|
26
|
+
|
|
27
|
+
@observable
|
|
28
|
+
protected _value: string = "";
|
|
29
|
+
|
|
30
|
+
@observable
|
|
31
|
+
protected _fraction: number = 0;
|
|
32
|
+
|
|
33
|
+
@observable.ref
|
|
34
|
+
protected _feeConfig: IFeeConfig | undefined = undefined;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
chainGetter: ChainGetter,
|
|
38
|
+
protected readonly starknetQueriesStore: StarknetQueriesStore,
|
|
39
|
+
initialChainId: string,
|
|
40
|
+
protected readonly senderConfig: ISenderConfig
|
|
41
|
+
) {
|
|
42
|
+
super(chainGetter, initialChainId);
|
|
43
|
+
|
|
44
|
+
makeObservable(this);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get feeConfig(): IFeeConfig | undefined {
|
|
48
|
+
return this._feeConfig;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@action
|
|
52
|
+
setFeeConfig(feeConfig: IFeeConfig | undefined) {
|
|
53
|
+
this._feeConfig = feeConfig;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@computed
|
|
57
|
+
get value(): string {
|
|
58
|
+
if (this.fraction > 0) {
|
|
59
|
+
let result = this.starknetQueriesStore
|
|
60
|
+
.get(this.chainId)
|
|
61
|
+
.queryStarknetERC20Balance.getBalance(
|
|
62
|
+
this.chainId,
|
|
63
|
+
this.chainGetter,
|
|
64
|
+
this.senderConfig.sender,
|
|
65
|
+
this.currency.coinMinimalDenom
|
|
66
|
+
)?.balance;
|
|
67
|
+
if (!result) {
|
|
68
|
+
return "0";
|
|
69
|
+
}
|
|
70
|
+
if (this.feeConfig) {
|
|
71
|
+
if (this.feeConfig.fee) {
|
|
72
|
+
result = result.sub(this.feeConfig.fee);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (result.toDec().lte(new Dec(0))) {
|
|
76
|
+
return "0";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return result
|
|
80
|
+
.mul(new Dec(this.fraction))
|
|
81
|
+
.trim(true)
|
|
82
|
+
.locale(false)
|
|
83
|
+
.hideDenom(true)
|
|
84
|
+
.toString();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return this._value;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@action
|
|
91
|
+
setValue(value: string): void {
|
|
92
|
+
if (value.startsWith(".")) {
|
|
93
|
+
value = "0" + value;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this._value = value;
|
|
97
|
+
|
|
98
|
+
this.setFraction(0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@computed
|
|
102
|
+
get amount(): CoinPretty[] {
|
|
103
|
+
let amount: Dec;
|
|
104
|
+
try {
|
|
105
|
+
if (this.value.trim() === "") {
|
|
106
|
+
amount = new Dec(0);
|
|
107
|
+
} else {
|
|
108
|
+
amount = new Dec(this.value);
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
amount = new Dec(0);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return [
|
|
115
|
+
new CoinPretty(
|
|
116
|
+
this.currency,
|
|
117
|
+
amount
|
|
118
|
+
.mul(DecUtils.getTenExponentN(this.currency.coinDecimals))
|
|
119
|
+
.truncate()
|
|
120
|
+
),
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@computed
|
|
125
|
+
get currency(): ERC20Currency {
|
|
126
|
+
const modularChainInfo = this.modularChainInfo;
|
|
127
|
+
if (!("starknet" in modularChainInfo)) {
|
|
128
|
+
throw new Error("Chain doesn't support the starknet");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (this._currency) {
|
|
132
|
+
const find = modularChainInfo.starknet.currencies.find(
|
|
133
|
+
(cur) => cur.coinMinimalDenom === this._currency!.coinMinimalDenom
|
|
134
|
+
);
|
|
135
|
+
if (find) {
|
|
136
|
+
return find;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return modularChainInfo.starknet.currencies[0];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@action
|
|
144
|
+
setCurrency(currency: ERC20Currency | undefined) {
|
|
145
|
+
if (currency?.coinMinimalDenom !== this._currency?.coinMinimalDenom) {
|
|
146
|
+
this._value = "";
|
|
147
|
+
this.setFraction(0);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this._currency = currency;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get fraction(): number {
|
|
154
|
+
return this._fraction;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@action
|
|
158
|
+
setFraction(fraction: number): void {
|
|
159
|
+
this._fraction = fraction;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
canUseCurrency(currency: ERC20Currency): boolean {
|
|
163
|
+
const modularChainInfo = this.modularChainInfo;
|
|
164
|
+
if (!("starknet" in modularChainInfo)) {
|
|
165
|
+
throw new Error("Chain doesn't support the starknet");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
modularChainInfo.starknet.currencies.find(
|
|
170
|
+
(cur) => cur.coinMinimalDenom === currency.coinMinimalDenom
|
|
171
|
+
) != null
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@computed
|
|
176
|
+
get uiProperties(): UIProperties {
|
|
177
|
+
if (!this.currency) {
|
|
178
|
+
return {
|
|
179
|
+
error: new Error("Currency to send not set"),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (this.value.trim() === "") {
|
|
184
|
+
return {
|
|
185
|
+
error: new EmptyAmountError("Amount is empty"),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
const dec = new Dec(this.value);
|
|
191
|
+
if (dec.equals(new Dec(0))) {
|
|
192
|
+
return {
|
|
193
|
+
error: new ZeroAmountError("Amount is zero"),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
if (dec.lt(new Dec(0))) {
|
|
197
|
+
return {
|
|
198
|
+
error: new NegativeAmountError("Amount is negative"),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
return {
|
|
203
|
+
error: new InvalidNumberAmountError("Invalid form of number"),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
for (const amount of this.amount) {
|
|
208
|
+
const currency = amount.currency;
|
|
209
|
+
|
|
210
|
+
if (!("type" in currency) || currency.type !== "erc20") {
|
|
211
|
+
return {
|
|
212
|
+
error: new NotSupportedCurrencyError("Not supported currency"),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (!this.canUseCurrency(currency)) {
|
|
217
|
+
return {
|
|
218
|
+
error: new NotSupportedCurrencyError("Not supported currency"),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const bal = this.starknetQueriesStore
|
|
223
|
+
.get(this.chainId)
|
|
224
|
+
.queryStarknetERC20Balance.getBalance(
|
|
225
|
+
this.chainId,
|
|
226
|
+
this.chainGetter,
|
|
227
|
+
this.senderConfig.sender,
|
|
228
|
+
currency.coinMinimalDenom
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
if (!bal) {
|
|
232
|
+
return {
|
|
233
|
+
warning: new Error(
|
|
234
|
+
`Can't parse the balance for ${currency.coinMinimalDenom}`
|
|
235
|
+
),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (bal.error) {
|
|
240
|
+
return {
|
|
241
|
+
warning: new Error("Failed to fetch balance"),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!bal.response) {
|
|
246
|
+
return {
|
|
247
|
+
loadingState: "loading-block",
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (bal.balance.toDec().lt(amount.toDec())) {
|
|
252
|
+
return {
|
|
253
|
+
error: new InsufficientAmountError("Insufficient amount"),
|
|
254
|
+
loadingState: bal.isFetching ? "loading" : undefined,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return {};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export const useAmountConfig = (
|
|
264
|
+
chainGetter: ChainGetter,
|
|
265
|
+
queriesStore: StarknetQueriesStore,
|
|
266
|
+
chainId: string,
|
|
267
|
+
senderConfig: ISenderConfig
|
|
268
|
+
) => {
|
|
269
|
+
const [txConfig] = useState(
|
|
270
|
+
() => new AmountConfig(chainGetter, queriesStore, chainId, senderConfig)
|
|
271
|
+
);
|
|
272
|
+
txConfig.setChain(chainId);
|
|
273
|
+
|
|
274
|
+
return txConfig;
|
|
275
|
+
};
|
package/src/tx/chain.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { action, computed, makeObservable, observable } from "mobx";
|
|
2
|
+
import { ChainGetter } from "@keplr-wallet/stores";
|
|
3
|
+
import { ITxChainSetter } from "./types";
|
|
4
|
+
import { ModularChainInfo } from "@keplr-wallet/types";
|
|
5
|
+
|
|
6
|
+
export class TxChainSetter implements ITxChainSetter {
|
|
7
|
+
@observable
|
|
8
|
+
protected _chainId: string;
|
|
9
|
+
|
|
10
|
+
constructor(
|
|
11
|
+
protected readonly chainGetter: ChainGetter,
|
|
12
|
+
initialChainId: string
|
|
13
|
+
) {
|
|
14
|
+
this._chainId = initialChainId;
|
|
15
|
+
|
|
16
|
+
makeObservable(this);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@computed
|
|
20
|
+
get modularChainInfo(): ModularChainInfo {
|
|
21
|
+
return this.chainGetter.getModularChain(this.chainId);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get chainId(): string {
|
|
25
|
+
return this._chainId;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@action
|
|
29
|
+
setChain(chainId: string) {
|
|
30
|
+
this._chainId = chainId;
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/tx/errors.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
export class AccountNotDeployed extends Error {
|
|
2
|
+
constructor(m: string) {
|
|
3
|
+
super(m);
|
|
4
|
+
// Set the prototype explicitly.
|
|
5
|
+
Object.setPrototypeOf(this, AccountNotDeployed.prototype);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class EmptyAddressError extends Error {
|
|
10
|
+
constructor(m: string) {
|
|
11
|
+
super(m);
|
|
12
|
+
// Set the prototype explicitly.
|
|
13
|
+
Object.setPrototypeOf(this, EmptyAddressError.prototype);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class InvalidBech32Error extends Error {
|
|
18
|
+
constructor(m: string) {
|
|
19
|
+
super(m);
|
|
20
|
+
// Set the prototype explicitly.
|
|
21
|
+
Object.setPrototypeOf(this, InvalidBech32Error.prototype);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class ICNSIsFetchingError extends Error {
|
|
26
|
+
constructor(m: string) {
|
|
27
|
+
super(m);
|
|
28
|
+
// Set the prototype explicitly.
|
|
29
|
+
Object.setPrototypeOf(this, ICNSIsFetchingError.prototype);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class ICNSFailedToFetchError extends Error {
|
|
34
|
+
constructor(m: string) {
|
|
35
|
+
super(m);
|
|
36
|
+
// Set the prototype explicitly.
|
|
37
|
+
Object.setPrototypeOf(this, ICNSFailedToFetchError.prototype);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class EmptyAmountError extends Error {
|
|
42
|
+
constructor(m: string) {
|
|
43
|
+
super(m);
|
|
44
|
+
// Set the prototype explicitly.
|
|
45
|
+
Object.setPrototypeOf(this, EmptyAmountError.prototype);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class InvalidNumberAmountError extends Error {
|
|
50
|
+
constructor(m: string) {
|
|
51
|
+
super(m);
|
|
52
|
+
// Set the prototype explicitly.
|
|
53
|
+
Object.setPrototypeOf(this, InvalidNumberAmountError.prototype);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class ZeroAmountError extends Error {
|
|
58
|
+
constructor(m: string) {
|
|
59
|
+
super(m);
|
|
60
|
+
// Set the prototype explicitly.
|
|
61
|
+
Object.setPrototypeOf(this, ZeroAmountError.prototype);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class NegativeAmountError extends Error {
|
|
66
|
+
constructor(m: string) {
|
|
67
|
+
super(m);
|
|
68
|
+
// Set the prototype explicitly.
|
|
69
|
+
Object.setPrototypeOf(this, NegativeAmountError.prototype);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class InsufficientAmountError extends Error {
|
|
74
|
+
constructor(m: string) {
|
|
75
|
+
super(m);
|
|
76
|
+
// Set the prototype explicitly.
|
|
77
|
+
Object.setPrototypeOf(this, InsufficientAmountError.prototype);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export class NotLoadedFeeError extends Error {
|
|
82
|
+
constructor(m: string) {
|
|
83
|
+
super(m);
|
|
84
|
+
// Set the prototype explicitly.
|
|
85
|
+
Object.setPrototypeOf(this, NotLoadedFeeError.prototype);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class InsufficientFeeError extends Error {
|
|
90
|
+
constructor(m: string) {
|
|
91
|
+
super(m);
|
|
92
|
+
// Set the prototype explicitly.
|
|
93
|
+
Object.setPrototypeOf(this, InsufficientFeeError.prototype);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export class UnknownCurrencyError extends Error {
|
|
98
|
+
constructor(m: string) {
|
|
99
|
+
super(m);
|
|
100
|
+
// Set the prototype explicitly.
|
|
101
|
+
Object.setPrototypeOf(this, UnknownCurrencyError.prototype);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export class NotSupportedCurrencyError extends Error {
|
|
106
|
+
constructor(m: string) {
|
|
107
|
+
super(m);
|
|
108
|
+
// Set the prototype explicitly.
|
|
109
|
+
Object.setPrototypeOf(this, UnknownCurrencyError.prototype);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export class InvalidHexError extends Error {
|
|
114
|
+
constructor(m: string) {
|
|
115
|
+
super(m);
|
|
116
|
+
// Set the prototype explicitly.
|
|
117
|
+
Object.setPrototypeOf(this, InvalidHexError.prototype);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export class MemoSuspectMnemonicInclusion extends Error {
|
|
122
|
+
constructor(m: string) {
|
|
123
|
+
super(m);
|
|
124
|
+
// Set the prototype explicitly.
|
|
125
|
+
Object.setPrototypeOf(this, MemoSuspectMnemonicInclusion.prototype);
|
|
126
|
+
}
|
|
127
|
+
}
|
package/src/tx/fee.ts
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IAmountConfig,
|
|
3
|
+
IFeeConfig,
|
|
4
|
+
IGasConfig,
|
|
5
|
+
ISenderConfig,
|
|
6
|
+
UIProperties,
|
|
7
|
+
} from "./types";
|
|
8
|
+
import { TxChainSetter } from "./chain";
|
|
9
|
+
import { ChainGetter } from "@keplr-wallet/stores";
|
|
10
|
+
import { action, computed, makeObservable, observable } from "mobx";
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import { StarknetQueriesStore } from "@keplr-wallet/stores-starknet";
|
|
13
|
+
import { CoinPretty, Dec, Int } from "@keplr-wallet/unit";
|
|
14
|
+
import { InsufficientFeeError } from "./errors";
|
|
15
|
+
|
|
16
|
+
export class FeeConfig extends TxChainSetter implements IFeeConfig {
|
|
17
|
+
@observable.ref
|
|
18
|
+
protected _gasPrice: CoinPretty | undefined = undefined;
|
|
19
|
+
@observable.ref
|
|
20
|
+
protected _maxGasPrice: CoinPretty | undefined = undefined;
|
|
21
|
+
@observable
|
|
22
|
+
protected _type: "ETH" | "STRK" = "STRK";
|
|
23
|
+
|
|
24
|
+
@observable
|
|
25
|
+
protected _disableBalanceCheck: boolean = false;
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
chainGetter: ChainGetter,
|
|
29
|
+
protected readonly starknetQueriesStore: StarknetQueriesStore,
|
|
30
|
+
initialChainId: string,
|
|
31
|
+
protected readonly senderConfig: ISenderConfig,
|
|
32
|
+
protected readonly amountConfig: IAmountConfig,
|
|
33
|
+
protected readonly gasConfig: IGasConfig
|
|
34
|
+
) {
|
|
35
|
+
super(chainGetter, initialChainId);
|
|
36
|
+
|
|
37
|
+
makeObservable(this);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@action
|
|
41
|
+
setDisableBalanceCheck(bool: boolean) {
|
|
42
|
+
this._disableBalanceCheck = bool;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get disableBalanceCheck(): boolean {
|
|
46
|
+
return this._disableBalanceCheck;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@computed
|
|
50
|
+
get uiProperties(): UIProperties {
|
|
51
|
+
if (this.disableBalanceCheck) {
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!this._gasPrice) {
|
|
56
|
+
return {
|
|
57
|
+
error: new Error("Fee is not set"),
|
|
58
|
+
loadingState: "loading-block",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!this._maxGasPrice) {
|
|
63
|
+
return {
|
|
64
|
+
error: new Error("Fee is not set"),
|
|
65
|
+
loadingState: "loading-block",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!this.fee) {
|
|
70
|
+
return {
|
|
71
|
+
error: new Error("Fee is not set"),
|
|
72
|
+
loadingState: "loading-block",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!this.maxFee) {
|
|
77
|
+
return {
|
|
78
|
+
error: new Error("Fee is not set"),
|
|
79
|
+
loadingState: "loading-block",
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const maxFee = this.maxFee;
|
|
84
|
+
|
|
85
|
+
const bal = this.starknetQueriesStore
|
|
86
|
+
.get(this.chainId)
|
|
87
|
+
.queryStarknetERC20Balance.getBalance(
|
|
88
|
+
this.chainId,
|
|
89
|
+
this.chainGetter,
|
|
90
|
+
this.senderConfig.value,
|
|
91
|
+
maxFee.currency.coinMinimalDenom
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
if (!bal) {
|
|
95
|
+
return {
|
|
96
|
+
warning: new Error(
|
|
97
|
+
`Can't parse the balance for ${maxFee.currency.coinMinimalDenom}`
|
|
98
|
+
),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (bal.error) {
|
|
103
|
+
return {
|
|
104
|
+
warning: new Error("Failed to fetch balance"),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!bal.response) {
|
|
109
|
+
return {
|
|
110
|
+
loadingState: "loading-block",
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
new Int(bal.balance.toCoin().amount).lt(new Int(maxFee.toCoin().amount))
|
|
116
|
+
) {
|
|
117
|
+
return {
|
|
118
|
+
error: new InsufficientFeeError("Insufficient fee"),
|
|
119
|
+
loadingState: bal.isFetching ? "loading" : undefined,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
get gasPrice(): CoinPretty | undefined {
|
|
127
|
+
return this._gasPrice;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
get maxGasPrice(): CoinPretty | undefined {
|
|
131
|
+
return this._maxGasPrice;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
get type(): "ETH" | "STRK" {
|
|
135
|
+
return this._type;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@action
|
|
139
|
+
setGasPrice(
|
|
140
|
+
gasPrice:
|
|
141
|
+
| {
|
|
142
|
+
gasPrice: CoinPretty;
|
|
143
|
+
maxGasPrice: CoinPretty;
|
|
144
|
+
}
|
|
145
|
+
| undefined
|
|
146
|
+
): void {
|
|
147
|
+
this._gasPrice = gasPrice?.gasPrice;
|
|
148
|
+
this._maxGasPrice = gasPrice?.maxGasPrice;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@action
|
|
152
|
+
setType(type: "ETH" | "STRK"): void {
|
|
153
|
+
if (this._type !== type) {
|
|
154
|
+
this._type = type;
|
|
155
|
+
this._gasPrice = undefined;
|
|
156
|
+
this._maxGasPrice = undefined;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@computed
|
|
161
|
+
get fee(): CoinPretty | undefined {
|
|
162
|
+
if (!this._gasPrice) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const gasDec = new Dec(this.gasConfig.gas);
|
|
167
|
+
return this._gasPrice.mul(gasDec);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@computed
|
|
171
|
+
get maxFee(): CoinPretty | undefined {
|
|
172
|
+
if (!this._maxGasPrice) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const gasDec = new Dec(this.gasConfig.gas);
|
|
177
|
+
return this._maxGasPrice.mul(gasDec);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export const useFeeConfig = (
|
|
182
|
+
chainGetter: ChainGetter,
|
|
183
|
+
queriesStore: StarknetQueriesStore,
|
|
184
|
+
chainId: string,
|
|
185
|
+
senderConfig: ISenderConfig,
|
|
186
|
+
amountConfig: IAmountConfig,
|
|
187
|
+
gasConfig: IGasConfig,
|
|
188
|
+
initialFn?: (config: FeeConfig) => void
|
|
189
|
+
) => {
|
|
190
|
+
const [config] = useState(() => {
|
|
191
|
+
const config = new FeeConfig(
|
|
192
|
+
chainGetter,
|
|
193
|
+
queriesStore,
|
|
194
|
+
chainId,
|
|
195
|
+
senderConfig,
|
|
196
|
+
amountConfig,
|
|
197
|
+
gasConfig
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
if (initialFn) {
|
|
201
|
+
initialFn(config);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return config;
|
|
205
|
+
});
|
|
206
|
+
config.setChain(chainId);
|
|
207
|
+
|
|
208
|
+
return config;
|
|
209
|
+
};
|