@keplr-wallet/stores-eth 0.12.71-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/account/base.d.ts +36 -0
- package/build/account/base.js +235 -0
- package/build/account/base.js.map +1 -0
- package/build/account/index.d.ts +2 -0
- package/build/account/index.js +19 -0
- package/build/account/index.js.map +1 -0
- package/build/account/store.d.ts +9 -0
- package/build/account/store.js +20 -0
- package/build/account/store.js.map +1 -0
- package/build/constants.d.ts +2 -0
- package/build/constants.js +275 -0
- package/build/constants.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.js +20 -0
- package/build/index.js.map +1 -0
- package/build/queries/balance.d.ts +19 -0
- package/build/queries/balance.js +72 -0
- package/build/queries/balance.js.map +1 -0
- package/build/queries/block.d.ts +54 -0
- package/build/queries/block.js +45 -0
- package/build/queries/block.js.map +1 -0
- package/build/queries/erc20-balance.d.ts +20 -0
- package/build/queries/erc20-balance.js +79 -0
- package/build/queries/erc20-balance.js.map +1 -0
- package/build/queries/erc20-contract-info.d.ts +20 -0
- package/build/queries/erc20-contract-info.js +51 -0
- package/build/queries/erc20-contract-info.js.map +1 -0
- package/build/queries/erc20-metadata.d.ts +31 -0
- package/build/queries/erc20-metadata.js +142 -0
- package/build/queries/erc20-metadata.js.map +1 -0
- package/build/queries/evm-chain-json-rpc.d.ts +13 -0
- package/build/queries/evm-chain-json-rpc.js +27 -0
- package/build/queries/evm-chain-json-rpc.js.map +1 -0
- package/build/queries/fee-histroy.d.ts +17 -0
- package/build/queries/fee-histroy.js +55 -0
- package/build/queries/fee-histroy.js.map +1 -0
- package/build/queries/index.d.ts +21 -0
- package/build/queries/index.js +32 -0
- package/build/queries/index.js.map +1 -0
- package/jest.config.js +5 -0
- package/package.json +35 -0
- package/src/account/base.ts +302 -0
- package/src/account/index.ts +2 -0
- package/src/account/store.ts +19 -0
- package/src/constants.ts +272 -0
- package/src/index.ts +3 -0
- package/src/queries/balance.ts +94 -0
- package/src/queries/block.ts +111 -0
- package/src/queries/erc20-balance.ts +103 -0
- package/src/queries/erc20-contract-info.ts +66 -0
- package/src/queries/erc20-metadata.ts +184 -0
- package/src/queries/evm-chain-json-rpc.ts +48 -0
- package/src/queries/fee-histroy.ts +80 -0
- package/src/queries/index.ts +86 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { simpleFetch } from "@keplr-wallet/simple-fetch";
|
|
2
|
+
import { ChainGetter } from "@keplr-wallet/stores";
|
|
3
|
+
import {
|
|
4
|
+
AppCurrency,
|
|
5
|
+
ChainInfo,
|
|
6
|
+
EthSignType,
|
|
7
|
+
EthTxReceipt,
|
|
8
|
+
Keplr,
|
|
9
|
+
} from "@keplr-wallet/types";
|
|
10
|
+
import { DenomHelper, retry } from "@keplr-wallet/common";
|
|
11
|
+
import { erc20ContractInterface } from "../constants";
|
|
12
|
+
import { hexValue } from "@ethersproject/bytes";
|
|
13
|
+
import { parseUnits } from "@ethersproject/units";
|
|
14
|
+
import {
|
|
15
|
+
UnsignedTransaction,
|
|
16
|
+
serialize,
|
|
17
|
+
TransactionTypes,
|
|
18
|
+
} from "@ethersproject/transactions";
|
|
19
|
+
import { getAddress as getEthAddress } from "@ethersproject/address";
|
|
20
|
+
import { action, makeObservable, observable } from "mobx";
|
|
21
|
+
|
|
22
|
+
export class EthereumAccountBase {
|
|
23
|
+
@observable
|
|
24
|
+
protected _isSendingTx: boolean = false;
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
protected readonly chainGetter: ChainGetter,
|
|
28
|
+
protected readonly chainId: string,
|
|
29
|
+
protected readonly getKeplr: () => Promise<Keplr | undefined>
|
|
30
|
+
) {
|
|
31
|
+
makeObservable(this);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static evmInfo(chainInfo: ChainInfo): ChainInfo["evm"] | undefined {
|
|
35
|
+
return chainInfo.evm;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@action
|
|
39
|
+
setIsSendingTx(value: boolean) {
|
|
40
|
+
this._isSendingTx = value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get isSendingTx(): boolean {
|
|
44
|
+
return this._isSendingTx;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async simulateGas({
|
|
48
|
+
currency,
|
|
49
|
+
amount,
|
|
50
|
+
sender,
|
|
51
|
+
recipient,
|
|
52
|
+
}: {
|
|
53
|
+
currency: AppCurrency;
|
|
54
|
+
amount: string;
|
|
55
|
+
sender: string;
|
|
56
|
+
recipient: string;
|
|
57
|
+
}) {
|
|
58
|
+
const chainInfo = this.chainGetter.getChain(this.chainId);
|
|
59
|
+
const evmInfo = EthereumAccountBase.evmInfo(chainInfo);
|
|
60
|
+
if (!evmInfo) {
|
|
61
|
+
throw new Error("No EVM chain info provided");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!EthereumAccountBase.isEthereumHexAddressWithChecksum(sender)) {
|
|
65
|
+
throw new Error("Invalid sender address");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// If the recipient address is invalid, the sender address will be used as the recipient for gas estimating gas.
|
|
69
|
+
const tempRecipient = EthereumAccountBase.isEthereumHexAddressWithChecksum(
|
|
70
|
+
recipient
|
|
71
|
+
)
|
|
72
|
+
? recipient
|
|
73
|
+
: sender;
|
|
74
|
+
|
|
75
|
+
const parsedAmount = parseUnits(amount, currency.coinDecimals);
|
|
76
|
+
const denomHelper = new DenomHelper(currency.coinMinimalDenom);
|
|
77
|
+
|
|
78
|
+
const unsignedTx: UnsignedTransaction = (() => {
|
|
79
|
+
switch (denomHelper.type) {
|
|
80
|
+
case "erc20":
|
|
81
|
+
return {
|
|
82
|
+
from: sender,
|
|
83
|
+
to: denomHelper.contractAddress,
|
|
84
|
+
value: "0x0",
|
|
85
|
+
data: erc20ContractInterface.encodeFunctionData("transfer", [
|
|
86
|
+
tempRecipient,
|
|
87
|
+
hexValue(parsedAmount),
|
|
88
|
+
]),
|
|
89
|
+
};
|
|
90
|
+
default:
|
|
91
|
+
return {
|
|
92
|
+
from: sender,
|
|
93
|
+
to: tempRecipient,
|
|
94
|
+
value: hexValue(parsedAmount),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
})();
|
|
98
|
+
|
|
99
|
+
const estimateGasResponse = await simpleFetch<{
|
|
100
|
+
result: string;
|
|
101
|
+
}>(evmInfo.rpc, {
|
|
102
|
+
method: "POST",
|
|
103
|
+
headers: {
|
|
104
|
+
"content-type": "application/json",
|
|
105
|
+
},
|
|
106
|
+
body: JSON.stringify({
|
|
107
|
+
jsonrpc: "2.0",
|
|
108
|
+
method: "eth_estimateGas",
|
|
109
|
+
params: [unsignedTx],
|
|
110
|
+
id: 1,
|
|
111
|
+
}),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
gasUsed: Number(estimateGasResponse.data.result),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async makeSendTokenTx({
|
|
120
|
+
currency,
|
|
121
|
+
amount,
|
|
122
|
+
from,
|
|
123
|
+
to,
|
|
124
|
+
gasLimit,
|
|
125
|
+
maxFeePerGas,
|
|
126
|
+
maxPriorityFeePerGas,
|
|
127
|
+
}: {
|
|
128
|
+
currency: AppCurrency;
|
|
129
|
+
amount: string;
|
|
130
|
+
from: string;
|
|
131
|
+
to: string;
|
|
132
|
+
gasLimit: number;
|
|
133
|
+
maxFeePerGas: string;
|
|
134
|
+
maxPriorityFeePerGas: string;
|
|
135
|
+
}): Promise<UnsignedTransaction> {
|
|
136
|
+
const chainInfo = this.chainGetter.getChain(this.chainId);
|
|
137
|
+
const evmInfo = EthereumAccountBase.evmInfo(chainInfo);
|
|
138
|
+
if (!evmInfo) {
|
|
139
|
+
throw new Error("No EVM chain info provided");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const transactionCountResponse = await simpleFetch<{
|
|
143
|
+
result: string;
|
|
144
|
+
}>(evmInfo.rpc, {
|
|
145
|
+
method: "POST",
|
|
146
|
+
headers: {
|
|
147
|
+
"content-type": "application/json",
|
|
148
|
+
},
|
|
149
|
+
body: JSON.stringify({
|
|
150
|
+
jsonrpc: "2.0",
|
|
151
|
+
method: "eth_getTransactionCount",
|
|
152
|
+
params: [from, "pending"],
|
|
153
|
+
id: 1,
|
|
154
|
+
}),
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const parsedAmount = parseUnits(amount, currency.coinDecimals);
|
|
158
|
+
const denomHelper = new DenomHelper(currency.coinMinimalDenom);
|
|
159
|
+
|
|
160
|
+
// Support EIP-1559 transaction only.
|
|
161
|
+
const unsignedTx: UnsignedTransaction = (() => {
|
|
162
|
+
switch (denomHelper.type) {
|
|
163
|
+
case "erc20":
|
|
164
|
+
return {
|
|
165
|
+
type: TransactionTypes.eip1559,
|
|
166
|
+
chainId: evmInfo.chainId,
|
|
167
|
+
nonce: Number(transactionCountResponse.data.result),
|
|
168
|
+
gasLimit: hexValue(gasLimit),
|
|
169
|
+
maxFeePerGas: hexValue(Number(maxFeePerGas)),
|
|
170
|
+
maxPriorityFeePerGas: hexValue(Number(maxPriorityFeePerGas)),
|
|
171
|
+
to: denomHelper.contractAddress,
|
|
172
|
+
value: "0x0",
|
|
173
|
+
data: erc20ContractInterface.encodeFunctionData("transfer", [
|
|
174
|
+
to,
|
|
175
|
+
hexValue(parsedAmount),
|
|
176
|
+
]),
|
|
177
|
+
};
|
|
178
|
+
default:
|
|
179
|
+
return {
|
|
180
|
+
type: TransactionTypes.eip1559,
|
|
181
|
+
chainId: evmInfo.chainId,
|
|
182
|
+
nonce: Number(transactionCountResponse.data.result),
|
|
183
|
+
gasLimit: hexValue(gasLimit),
|
|
184
|
+
maxFeePerGas: hexValue(Number(maxFeePerGas)),
|
|
185
|
+
maxPriorityFeePerGas: hexValue(Number(maxPriorityFeePerGas)),
|
|
186
|
+
to,
|
|
187
|
+
value: hexValue(parsedAmount),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
})();
|
|
191
|
+
|
|
192
|
+
return unsignedTx;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async sendEthereumTx(
|
|
196
|
+
sender: string,
|
|
197
|
+
unsignedTx: UnsignedTransaction,
|
|
198
|
+
onTxEvents?: {
|
|
199
|
+
onBroadcastFailed?: (e?: Error) => void;
|
|
200
|
+
onBroadcasted?: (txHash: string) => void;
|
|
201
|
+
onFulfill?: (txReceipt: EthTxReceipt) => void;
|
|
202
|
+
}
|
|
203
|
+
) {
|
|
204
|
+
try {
|
|
205
|
+
const chainInfo = this.chainGetter.getChain(this.chainId);
|
|
206
|
+
const evmInfo = EthereumAccountBase.evmInfo(chainInfo);
|
|
207
|
+
if (!evmInfo) {
|
|
208
|
+
throw new Error("No EVM info provided");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
212
|
+
const keplr = (await this.getKeplr())!;
|
|
213
|
+
const signEthereum = keplr.signEthereum.bind(keplr);
|
|
214
|
+
const signature = await signEthereum(
|
|
215
|
+
this.chainId,
|
|
216
|
+
sender,
|
|
217
|
+
JSON.stringify(unsignedTx),
|
|
218
|
+
EthSignType.TRANSACTION
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const signedTx = Buffer.from(
|
|
222
|
+
serialize(unsignedTx, signature).replace("0x", ""),
|
|
223
|
+
"hex"
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const sendEthereumTx = keplr.sendEthereumTx.bind(keplr);
|
|
227
|
+
const txHash = await sendEthereumTx(this.chainId, signedTx);
|
|
228
|
+
if (!txHash) {
|
|
229
|
+
throw new Error("No tx hash responded");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (onTxEvents?.onBroadcasted) {
|
|
233
|
+
onTxEvents.onBroadcasted(txHash);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
retry(
|
|
237
|
+
() => {
|
|
238
|
+
return new Promise<void>(async (resolve, reject) => {
|
|
239
|
+
const txReceiptResponse = await simpleFetch<{
|
|
240
|
+
result: EthTxReceipt | null;
|
|
241
|
+
error?: Error;
|
|
242
|
+
}>(evmInfo.rpc, {
|
|
243
|
+
method: "POST",
|
|
244
|
+
headers: {
|
|
245
|
+
"content-type": "application/json",
|
|
246
|
+
},
|
|
247
|
+
body: JSON.stringify({
|
|
248
|
+
jsonrpc: "2.0",
|
|
249
|
+
method: "eth_getTransactionReceipt",
|
|
250
|
+
params: [txHash],
|
|
251
|
+
id: 1,
|
|
252
|
+
}),
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
if (txReceiptResponse.data.error) {
|
|
256
|
+
console.error(txReceiptResponse.data.error);
|
|
257
|
+
resolve();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const txReceipt = txReceiptResponse.data.result;
|
|
261
|
+
if (txReceipt) {
|
|
262
|
+
onTxEvents?.onFulfill?.(txReceipt);
|
|
263
|
+
resolve();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
reject();
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
maxRetries: 10,
|
|
271
|
+
waitMsAfterError: 500,
|
|
272
|
+
maxWaitMsAfterError: 4000,
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
return txHash;
|
|
277
|
+
} catch (e) {
|
|
278
|
+
if (onTxEvents?.onBroadcastFailed) {
|
|
279
|
+
onTxEvents.onBroadcastFailed(e);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
throw e;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
static isEthereumHexAddressWithChecksum(hexAddress: string): boolean {
|
|
287
|
+
const isHexAddress = !!hexAddress.match(/^0x[0-9A-Fa-f]*$/);
|
|
288
|
+
const isChecksumAddress = !!hexAddress.match(
|
|
289
|
+
/([A-F].*[a-f])|([a-f].*[A-F])/
|
|
290
|
+
);
|
|
291
|
+
if (!isHexAddress || hexAddress.length !== 42) {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const checksumHexAddress = getEthAddress(hexAddress.toLowerCase());
|
|
296
|
+
if (isChecksumAddress && checksumHexAddress !== hexAddress) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ChainGetter, HasMapStore } from "@keplr-wallet/stores";
|
|
2
|
+
import { EthereumAccountBase } from "./base";
|
|
3
|
+
import { Keplr } from "@keplr-wallet/types";
|
|
4
|
+
|
|
5
|
+
export class EthereumAccountStore extends HasMapStore<EthereumAccountBase> {
|
|
6
|
+
constructor(
|
|
7
|
+
protected readonly chainGetter: ChainGetter,
|
|
8
|
+
protected readonly getKeplr: () => Promise<Keplr | undefined>
|
|
9
|
+
) {
|
|
10
|
+
super((chainId: string) => {
|
|
11
|
+
return new EthereumAccountBase(chainGetter, chainId, getKeplr);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getAccount(chainId: string): EthereumAccountBase {
|
|
16
|
+
// chain identifier를 통한 접근도 허용하기 위해서 chainGetter를 통해 접근하도록 함.
|
|
17
|
+
return this.get(this.chainGetter.getChain(chainId).chainId);
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { Interface } from "@ethersproject/abi";
|
|
2
|
+
|
|
3
|
+
export const erc20ContractInterface: Interface = new Interface([
|
|
4
|
+
{ inputs: [], stateMutability: "nonpayable", type: "constructor" },
|
|
5
|
+
{
|
|
6
|
+
anonymous: false,
|
|
7
|
+
inputs: [
|
|
8
|
+
{
|
|
9
|
+
indexed: true,
|
|
10
|
+
internalType: "address",
|
|
11
|
+
name: "owner",
|
|
12
|
+
type: "address",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
indexed: true,
|
|
16
|
+
internalType: "address",
|
|
17
|
+
name: "spender",
|
|
18
|
+
type: "address",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
indexed: false,
|
|
22
|
+
internalType: "uint256",
|
|
23
|
+
name: "value",
|
|
24
|
+
type: "uint256",
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
name: "Approval",
|
|
28
|
+
type: "event",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
anonymous: false,
|
|
32
|
+
inputs: [
|
|
33
|
+
{
|
|
34
|
+
indexed: true,
|
|
35
|
+
internalType: "address",
|
|
36
|
+
name: "usr",
|
|
37
|
+
type: "address",
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
name: "Deny",
|
|
41
|
+
type: "event",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
anonymous: false,
|
|
45
|
+
inputs: [
|
|
46
|
+
{
|
|
47
|
+
indexed: true,
|
|
48
|
+
internalType: "address",
|
|
49
|
+
name: "usr",
|
|
50
|
+
type: "address",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
name: "Rely",
|
|
54
|
+
type: "event",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
anonymous: false,
|
|
58
|
+
inputs: [
|
|
59
|
+
{
|
|
60
|
+
indexed: true,
|
|
61
|
+
internalType: "address",
|
|
62
|
+
name: "from",
|
|
63
|
+
type: "address",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
indexed: true,
|
|
67
|
+
internalType: "address",
|
|
68
|
+
name: "to",
|
|
69
|
+
type: "address",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
indexed: false,
|
|
73
|
+
internalType: "uint256",
|
|
74
|
+
name: "value",
|
|
75
|
+
type: "uint256",
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
name: "Transfer",
|
|
79
|
+
type: "event",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
inputs: [],
|
|
83
|
+
name: "DOMAIN_SEPARATOR",
|
|
84
|
+
outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
85
|
+
stateMutability: "view",
|
|
86
|
+
type: "function",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
inputs: [],
|
|
90
|
+
name: "PERMIT_TYPEHASH",
|
|
91
|
+
outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
|
|
92
|
+
stateMutability: "view",
|
|
93
|
+
type: "function",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
inputs: [
|
|
97
|
+
{ internalType: "address", name: "", type: "address" },
|
|
98
|
+
{ internalType: "address", name: "", type: "address" },
|
|
99
|
+
],
|
|
100
|
+
name: "allowance",
|
|
101
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
102
|
+
stateMutability: "view",
|
|
103
|
+
type: "function",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
inputs: [
|
|
107
|
+
{ internalType: "address", name: "spender", type: "address" },
|
|
108
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
109
|
+
],
|
|
110
|
+
name: "approve",
|
|
111
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
112
|
+
stateMutability: "nonpayable",
|
|
113
|
+
type: "function",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
inputs: [{ internalType: "address", name: "", type: "address" }],
|
|
117
|
+
name: "balanceOf",
|
|
118
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
119
|
+
stateMutability: "view",
|
|
120
|
+
type: "function",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
inputs: [
|
|
124
|
+
{ internalType: "address", name: "from", type: "address" },
|
|
125
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
126
|
+
],
|
|
127
|
+
name: "burn",
|
|
128
|
+
outputs: [],
|
|
129
|
+
stateMutability: "nonpayable",
|
|
130
|
+
type: "function",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
inputs: [],
|
|
134
|
+
name: "decimals",
|
|
135
|
+
outputs: [{ internalType: "uint8", name: "", type: "uint8" }],
|
|
136
|
+
stateMutability: "view",
|
|
137
|
+
type: "function",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
inputs: [
|
|
141
|
+
{ internalType: "address", name: "spender", type: "address" },
|
|
142
|
+
{
|
|
143
|
+
internalType: "uint256",
|
|
144
|
+
name: "subtractedValue",
|
|
145
|
+
type: "uint256",
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
name: "decreaseAllowance",
|
|
149
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
150
|
+
stateMutability: "nonpayable",
|
|
151
|
+
type: "function",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
inputs: [{ internalType: "address", name: "usr", type: "address" }],
|
|
155
|
+
name: "deny",
|
|
156
|
+
outputs: [],
|
|
157
|
+
stateMutability: "nonpayable",
|
|
158
|
+
type: "function",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
inputs: [],
|
|
162
|
+
name: "deploymentChainId",
|
|
163
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
164
|
+
stateMutability: "view",
|
|
165
|
+
type: "function",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
inputs: [
|
|
169
|
+
{ internalType: "address", name: "spender", type: "address" },
|
|
170
|
+
{ internalType: "uint256", name: "addedValue", type: "uint256" },
|
|
171
|
+
],
|
|
172
|
+
name: "increaseAllowance",
|
|
173
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
174
|
+
stateMutability: "nonpayable",
|
|
175
|
+
type: "function",
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
inputs: [
|
|
179
|
+
{ internalType: "address", name: "to", type: "address" },
|
|
180
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
181
|
+
],
|
|
182
|
+
name: "mint",
|
|
183
|
+
outputs: [],
|
|
184
|
+
stateMutability: "nonpayable",
|
|
185
|
+
type: "function",
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
inputs: [],
|
|
189
|
+
name: "name",
|
|
190
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
191
|
+
stateMutability: "view",
|
|
192
|
+
type: "function",
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
inputs: [{ internalType: "address", name: "", type: "address" }],
|
|
196
|
+
name: "nonces",
|
|
197
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
198
|
+
stateMutability: "view",
|
|
199
|
+
type: "function",
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
inputs: [
|
|
203
|
+
{ internalType: "address", name: "owner", type: "address" },
|
|
204
|
+
{ internalType: "address", name: "spender", type: "address" },
|
|
205
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
206
|
+
{ internalType: "uint256", name: "deadline", type: "uint256" },
|
|
207
|
+
{ internalType: "uint8", name: "v", type: "uint8" },
|
|
208
|
+
{ internalType: "bytes32", name: "r", type: "bytes32" },
|
|
209
|
+
{ internalType: "bytes32", name: "s", type: "bytes32" },
|
|
210
|
+
],
|
|
211
|
+
name: "permit",
|
|
212
|
+
outputs: [],
|
|
213
|
+
stateMutability: "nonpayable",
|
|
214
|
+
type: "function",
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
inputs: [{ internalType: "address", name: "usr", type: "address" }],
|
|
218
|
+
name: "rely",
|
|
219
|
+
outputs: [],
|
|
220
|
+
stateMutability: "nonpayable",
|
|
221
|
+
type: "function",
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
inputs: [],
|
|
225
|
+
name: "symbol",
|
|
226
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
227
|
+
stateMutability: "view",
|
|
228
|
+
type: "function",
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
inputs: [],
|
|
232
|
+
name: "totalSupply",
|
|
233
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
234
|
+
stateMutability: "view",
|
|
235
|
+
type: "function",
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
inputs: [
|
|
239
|
+
{ internalType: "address", name: "to", type: "address" },
|
|
240
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
241
|
+
],
|
|
242
|
+
name: "transfer",
|
|
243
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
244
|
+
stateMutability: "nonpayable",
|
|
245
|
+
type: "function",
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
inputs: [
|
|
249
|
+
{ internalType: "address", name: "from", type: "address" },
|
|
250
|
+
{ internalType: "address", name: "to", type: "address" },
|
|
251
|
+
{ internalType: "uint256", name: "value", type: "uint256" },
|
|
252
|
+
],
|
|
253
|
+
name: "transferFrom",
|
|
254
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
255
|
+
stateMutability: "nonpayable",
|
|
256
|
+
type: "function",
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
inputs: [],
|
|
260
|
+
name: "version",
|
|
261
|
+
outputs: [{ internalType: "string", name: "", type: "string" }],
|
|
262
|
+
stateMutability: "view",
|
|
263
|
+
type: "function",
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
inputs: [{ internalType: "address", name: "", type: "address" }],
|
|
267
|
+
name: "wards",
|
|
268
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
269
|
+
stateMutability: "view",
|
|
270
|
+
type: "function",
|
|
271
|
+
},
|
|
272
|
+
]);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { DenomHelper } from "@keplr-wallet/common";
|
|
2
|
+
import {
|
|
3
|
+
BalanceRegistry,
|
|
4
|
+
ChainGetter,
|
|
5
|
+
IObservableQueryBalanceImpl,
|
|
6
|
+
ObservableJsonRPCQuery,
|
|
7
|
+
QuerySharedContext,
|
|
8
|
+
} from "@keplr-wallet/stores";
|
|
9
|
+
import { AppCurrency, ChainInfo } from "@keplr-wallet/types";
|
|
10
|
+
import { CoinPretty, Int } from "@keplr-wallet/unit";
|
|
11
|
+
import { computed, makeObservable } from "mobx";
|
|
12
|
+
import bigInteger from "big-integer";
|
|
13
|
+
import { EthereumAccountBase } from "../account";
|
|
14
|
+
|
|
15
|
+
export class ObservableQueryEthAccountBalanceImpl
|
|
16
|
+
extends ObservableJsonRPCQuery<string>
|
|
17
|
+
implements IObservableQueryBalanceImpl
|
|
18
|
+
{
|
|
19
|
+
constructor(
|
|
20
|
+
sharedContext: QuerySharedContext,
|
|
21
|
+
protected readonly chainId: string,
|
|
22
|
+
protected readonly chainGetter: ChainGetter,
|
|
23
|
+
protected readonly denomHelper: DenomHelper,
|
|
24
|
+
protected readonly ethereumURL: string,
|
|
25
|
+
protected readonly ethereumeHexAddress: string
|
|
26
|
+
) {
|
|
27
|
+
super(sharedContext, ethereumURL, "", "eth_getBalance", [
|
|
28
|
+
ethereumeHexAddress,
|
|
29
|
+
"latest",
|
|
30
|
+
]);
|
|
31
|
+
makeObservable(this);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@computed
|
|
35
|
+
get balance(): CoinPretty {
|
|
36
|
+
const denom = this.denomHelper.denom;
|
|
37
|
+
|
|
38
|
+
const chainInfo = this.chainGetter.getChain(this.chainId);
|
|
39
|
+
const currency = chainInfo.currencies.find(
|
|
40
|
+
(cur) => cur.coinMinimalDenom === denom
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (!currency) {
|
|
44
|
+
throw new Error(`Unknown currency: ${denom}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!this.response || !this.response.data) {
|
|
48
|
+
return new CoinPretty(currency, new Int(0)).ready(false);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return new CoinPretty(
|
|
52
|
+
currency,
|
|
53
|
+
new Int(bigInteger(this.response.data.replace("0x", ""), 16).toString())
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@computed
|
|
58
|
+
get currency(): AppCurrency {
|
|
59
|
+
const denom = this.denomHelper.denom;
|
|
60
|
+
|
|
61
|
+
const chainInfo = this.chainGetter.getChain(this.chainId);
|
|
62
|
+
return chainInfo.forceFindCurrency(denom);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class ObservableQueryEthAccountBalanceRegistry
|
|
67
|
+
implements BalanceRegistry
|
|
68
|
+
{
|
|
69
|
+
constructor(protected readonly sharedContext: QuerySharedContext) {}
|
|
70
|
+
|
|
71
|
+
getBalanceImpl(
|
|
72
|
+
chainId: string,
|
|
73
|
+
chainGetter: ChainGetter<ChainInfo>,
|
|
74
|
+
address: string,
|
|
75
|
+
minimalDenom: string
|
|
76
|
+
): IObservableQueryBalanceImpl | undefined {
|
|
77
|
+
const denomHelper = new DenomHelper(minimalDenom);
|
|
78
|
+
const chainInfo = chainGetter.getChain(chainId);
|
|
79
|
+
const isHexAddress =
|
|
80
|
+
EthereumAccountBase.isEthereumHexAddressWithChecksum(address);
|
|
81
|
+
if (denomHelper.type !== "native" || !isHexAddress || !chainInfo.evm) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return new ObservableQueryEthAccountBalanceImpl(
|
|
86
|
+
this.sharedContext,
|
|
87
|
+
chainId,
|
|
88
|
+
chainGetter,
|
|
89
|
+
denomHelper,
|
|
90
|
+
chainInfo.evm.rpc,
|
|
91
|
+
address
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|