@keplr-wallet/stores-core 0.12.32-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.
Files changed (54) hide show
  1. package/.eslintignore +2 -0
  2. package/.prettierignore +2 -0
  3. package/LICENSE +209 -0
  4. package/build/core/index.d.ts +4 -0
  5. package/build/core/index.js +21 -0
  6. package/build/core/index.js.map +1 -0
  7. package/build/core/interaction/chain-suggest.d.ts +35 -0
  8. package/build/core/interaction/chain-suggest.js +106 -0
  9. package/build/core/interaction/chain-suggest.js.map +1 -0
  10. package/build/core/interaction/eth-sign.d.ts +25 -0
  11. package/build/core/interaction/eth-sign.js +60 -0
  12. package/build/core/interaction/eth-sign.js.map +1 -0
  13. package/build/core/interaction/icns.d.ts +32 -0
  14. package/build/core/interaction/icns.js +58 -0
  15. package/build/core/interaction/icns.js.map +1 -0
  16. package/build/core/interaction/index.d.ts +6 -0
  17. package/build/core/interaction/index.js +23 -0
  18. package/build/core/interaction/index.js.map +1 -0
  19. package/build/core/interaction/interaction.d.ts +64 -0
  20. package/build/core/interaction/interaction.js +232 -0
  21. package/build/core/interaction/interaction.js.map +1 -0
  22. package/build/core/interaction/permission.d.ts +22 -0
  23. package/build/core/interaction/permission.js +108 -0
  24. package/build/core/interaction/permission.js.map +1 -0
  25. package/build/core/interaction/sign.d.ts +49 -0
  26. package/build/core/interaction/sign.js +78 -0
  27. package/build/core/interaction/sign.js.map +1 -0
  28. package/build/core/keyring.d.ts +132 -0
  29. package/build/core/keyring.js +278 -0
  30. package/build/core/keyring.js.map +1 -0
  31. package/build/core/permission-manager.d.ts +15 -0
  32. package/build/core/permission-manager.js +122 -0
  33. package/build/core/permission-manager.js.map +1 -0
  34. package/build/core/tokens.d.ts +39 -0
  35. package/build/core/tokens.js +225 -0
  36. package/build/core/tokens.js.map +1 -0
  37. package/build/index.d.ts +1 -0
  38. package/build/index.js +18 -0
  39. package/build/index.js.map +1 -0
  40. package/jest.config.js +5 -0
  41. package/package.json +31 -0
  42. package/src/core/index.ts +4 -0
  43. package/src/core/interaction/chain-suggest.ts +136 -0
  44. package/src/core/interaction/eth-sign.ts +71 -0
  45. package/src/core/interaction/icns.ts +68 -0
  46. package/src/core/interaction/index.ts +6 -0
  47. package/src/core/interaction/interaction.ts +290 -0
  48. package/src/core/interaction/permission.ts +121 -0
  49. package/src/core/interaction/sign.ts +124 -0
  50. package/src/core/keyring.ts +354 -0
  51. package/src/core/permission-manager.ts +114 -0
  52. package/src/core/tokens.ts +275 -0
  53. package/src/index.ts +1 -0
  54. package/tsconfig.json +12 -0
@@ -0,0 +1,275 @@
1
+ import { BACKGROUND_PORT, MessageRequester } from "@keplr-wallet/router";
2
+ import {
3
+ AddTokenMsg,
4
+ GetAllTokenInfosMsg,
5
+ RemoveTokenMsg,
6
+ TokenInfo,
7
+ } from "@keplr-wallet/background";
8
+ import { action, autorun, makeObservable, observable, runInAction } from "mobx";
9
+ import { AppCurrency } from "@keplr-wallet/types";
10
+ import { IChainStore, IAccountStore } from "@keplr-wallet/stores";
11
+ import { InteractionStore } from "./interaction";
12
+ import { Bech32Address, ChainIdHelper } from "@keplr-wallet/cosmos";
13
+ import { Buffer } from "buffer/";
14
+ import { KeyRingStore } from "./keyring";
15
+
16
+ export class TokensStore {
17
+ @observable
18
+ protected _isInitialized: boolean = false;
19
+
20
+ @observable.ref
21
+ protected tokenMap: ReadonlyMap<string, ReadonlyArray<TokenInfo>> = new Map();
22
+ // No need to be observable.
23
+ protected prevTokenMap: ReadonlyMap<string, ReadonlyArray<TokenInfo>> =
24
+ new Map();
25
+
26
+ constructor(
27
+ protected readonly eventListener: {
28
+ addEventListener: (type: string, fn: () => unknown) => void;
29
+ },
30
+ protected readonly requester: MessageRequester,
31
+ protected readonly chainStore: IChainStore,
32
+ protected readonly accountStore: IAccountStore,
33
+ protected readonly keyRingStore: KeyRingStore,
34
+ protected readonly interactionStore: InteractionStore
35
+ ) {
36
+ makeObservable(this);
37
+
38
+ this.init();
39
+ }
40
+
41
+ async init(): Promise<void> {
42
+ await this.refreshTokens();
43
+
44
+ // If key store in the keplr extension is changed, this event will be dispatched.
45
+ // This is needed becuase the token such as secret20 exists according to the account.
46
+ this.eventListener.addEventListener("keplr_keystorechange", () => {
47
+ this.clearTokensFromChainInfos();
48
+ this.refreshTokens();
49
+ });
50
+
51
+ autorun(() => {
52
+ // Account가 변경되었을때, 체인 정보가 변경되었을때 등에 반응해야하기 때문에 autorun 안에 넣는다.
53
+ this.updateChainInfos();
54
+ });
55
+
56
+ runInAction(() => {
57
+ this._isInitialized = true;
58
+ });
59
+ }
60
+
61
+ protected async refreshTokens() {
62
+ const msg = new GetAllTokenInfosMsg();
63
+ const tokens = await this.requester.sendMessage(BACKGROUND_PORT, msg);
64
+ runInAction(() => {
65
+ const map = new Map<string, TokenInfo[]>();
66
+ for (const [key, value] of Object.entries(tokens)) {
67
+ if (value) {
68
+ map.set(key, value);
69
+ }
70
+ }
71
+ this.tokenMap = map;
72
+ });
73
+ }
74
+
75
+ @action
76
+ protected clearTokensFromChainInfos() {
77
+ const chainInfos = this.chainStore.chainInfos;
78
+ for (const chainInfo of chainInfos) {
79
+ const chainIdentifier = ChainIdHelper.parse(chainInfo.chainId);
80
+
81
+ // Tokens should be changed whenever the account changed.
82
+ // But, the added currencies are not removed automatically.
83
+ // So, we should remove the prev token currencies from the chain info.
84
+ const prevTokens =
85
+ this.prevTokenMap.get(chainIdentifier.identifier) ?? [];
86
+ chainInfo.removeCurrencies(
87
+ ...prevTokens.map((token) => token.currency.coinMinimalDenom)
88
+ );
89
+ }
90
+ }
91
+
92
+ protected updateChainInfos() {
93
+ const chainInfos = this.chainStore.chainInfos;
94
+ for (const chainInfo of chainInfos) {
95
+ const chainIdentifier = ChainIdHelper.parse(chainInfo.chainId);
96
+
97
+ const tokens = this.tokenMap.get(chainIdentifier.identifier) ?? [];
98
+
99
+ const adds: AppCurrency[] = [];
100
+
101
+ for (const token of tokens) {
102
+ if (!token.associatedAccountAddress) {
103
+ adds.push(token.currency);
104
+ } else if (
105
+ this.keyRingStore.status === "unlocked" &&
106
+ this.accountStore.getAccount(chainInfo.chainId).bech32Address
107
+ ) {
108
+ if (
109
+ Buffer.from(
110
+ Bech32Address.fromBech32(
111
+ this.accountStore.getAccount(chainInfo.chainId).bech32Address
112
+ ).address
113
+ ).toString("hex") === token.associatedAccountAddress
114
+ ) {
115
+ adds.push(token.currency);
116
+ }
117
+ }
118
+ }
119
+
120
+ chainInfo.addCurrencies(...adds);
121
+ }
122
+
123
+ this.prevTokenMap = this.tokenMap;
124
+ }
125
+
126
+ get isInitialized(): boolean {
127
+ return this._isInitialized;
128
+ }
129
+
130
+ async waitUntilInitialized(): Promise<void> {
131
+ if (this.isInitialized) {
132
+ return;
133
+ }
134
+
135
+ return new Promise((resolve) => {
136
+ const disposal = autorun(() => {
137
+ if (this.isInitialized) {
138
+ resolve();
139
+
140
+ if (disposal) {
141
+ disposal();
142
+ }
143
+ }
144
+ });
145
+ });
146
+ }
147
+
148
+ getTokens(chainId: string): ReadonlyArray<TokenInfo> {
149
+ const bech32Address = this.accountStore.getAccount(chainId).bech32Address;
150
+ const chainInfo = this.chainStore.getChain(chainId);
151
+ const associatedAccountAddress = bech32Address
152
+ ? Buffer.from(
153
+ Bech32Address.fromBech32(
154
+ bech32Address,
155
+ chainInfo.bech32Config.bech32PrefixAccAddr
156
+ ).address
157
+ ).toString("hex")
158
+ : "";
159
+
160
+ const tokens =
161
+ this.tokenMap.get(ChainIdHelper.parse(chainId).identifier) ?? [];
162
+
163
+ return tokens.filter((token) => {
164
+ if (
165
+ token.associatedAccountAddress &&
166
+ token.associatedAccountAddress !== associatedAccountAddress
167
+ ) {
168
+ return false;
169
+ }
170
+
171
+ return true;
172
+ });
173
+ }
174
+
175
+ async addToken(chainId: string, currency: AppCurrency): Promise<void> {
176
+ const bech32Address = this.accountStore.getAccount(chainId).bech32Address;
177
+ if (!bech32Address) {
178
+ throw new Error("Account not initialized");
179
+ }
180
+ const chainInfo = this.chainStore.getChain(chainId);
181
+ const associatedAccountAddress = Buffer.from(
182
+ Bech32Address.fromBech32(
183
+ bech32Address,
184
+ chainInfo.bech32Config.bech32PrefixAccAddr
185
+ ).address
186
+ ).toString("hex");
187
+
188
+ const msg = new AddTokenMsg(chainId, associatedAccountAddress, currency);
189
+ const res = await this.requester.sendMessage(BACKGROUND_PORT, msg);
190
+ runInAction(() => {
191
+ const map = new Map<string, TokenInfo[]>();
192
+ for (const [key, value] of Object.entries(res)) {
193
+ if (value) {
194
+ map.set(key, value);
195
+ }
196
+ }
197
+ this.tokenMap = map;
198
+ });
199
+ }
200
+
201
+ async removeToken(chainId: string, tokenInfo: TokenInfo): Promise<void> {
202
+ const contractAddress = (() => {
203
+ if ("contractAddress" in tokenInfo.currency) {
204
+ return tokenInfo.currency.contractAddress;
205
+ }
206
+
207
+ throw new Error("Token info is not for contract");
208
+ })();
209
+
210
+ const msg = new RemoveTokenMsg(
211
+ chainId,
212
+ tokenInfo.associatedAccountAddress ?? "",
213
+ contractAddress
214
+ );
215
+ const res = await this.requester.sendMessage(BACKGROUND_PORT, msg);
216
+ runInAction(() => {
217
+ // Remove 이후에는 지워진 토큰에 대한 싱크를 맞추기 위해서 clearTokensFromChainInfos를 호출한다.
218
+ // 그냥 다 지우고 다시 다 설정하는 방식임.
219
+ this.clearTokensFromChainInfos();
220
+
221
+ const map = new Map<string, TokenInfo[]>();
222
+ for (const [key, value] of Object.entries(res)) {
223
+ if (value) {
224
+ map.set(key, value);
225
+ }
226
+ }
227
+ this.tokenMap = map;
228
+ });
229
+ }
230
+
231
+ get waitingSuggestedToken() {
232
+ const datas = this.interactionStore.getAllData<{
233
+ chainId: string;
234
+ contractAddress: string;
235
+ viewingKey?: string;
236
+ }>("suggest-token-cw20");
237
+
238
+ if (datas.length > 0) {
239
+ return datas[0];
240
+ }
241
+ }
242
+
243
+ async approveSuggestedTokenWithProceedNext(
244
+ id: string,
245
+ appCurrency: AppCurrency,
246
+ afterFn: (proceedNext: boolean) => void | Promise<void>
247
+ ) {
248
+ const d = this.interactionStore.getData<{
249
+ chainId: string;
250
+ contractAddress: string;
251
+ viewingKey?: string;
252
+ }>(id);
253
+ if (!d) {
254
+ return;
255
+ }
256
+
257
+ await this.interactionStore.approveWithProceedNext(
258
+ id,
259
+ appCurrency,
260
+ afterFn
261
+ );
262
+ this.refreshTokens();
263
+ }
264
+
265
+ async rejectSuggestedToken(
266
+ id: string,
267
+ afterFn: (proceedNext: boolean) => void | Promise<void>
268
+ ) {
269
+ await this.interactionStore.rejectWithProceedNext(id, afterFn);
270
+ }
271
+
272
+ async rejectAllSuggestedTokens() {
273
+ await this.interactionStore.rejectAll("suggest-token-cw20");
274
+ }
275
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./core";
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "outDir": "build",
6
+ "declaration": true,
7
+ "rootDir": "src"
8
+ },
9
+ "include": [
10
+ "src/**/*"
11
+ ]
12
+ }