@keplr-wallet/provider 0.12.118 → 0.12.120-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/build/core.d.ts +5 -1
- package/build/core.js +672 -136
- package/build/core.js.map +1 -1
- package/build/inject.js +3 -0
- package/build/inject.js.map +1 -1
- package/package.json +4 -4
- package/src/core.ts +945 -297
- package/src/inject.ts +4 -0
package/src/core.ts
CHANGED
@@ -57,16 +57,45 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
57
57
|
);
|
58
58
|
}
|
59
59
|
|
60
|
-
|
60
|
+
enable(chainIds: string | string[]): Promise<void> {
|
61
61
|
if (typeof chainIds === "string") {
|
62
62
|
chainIds = [chainIds];
|
63
63
|
}
|
64
64
|
|
65
|
-
|
65
|
+
return new Promise((resolve, reject) => {
|
66
|
+
let f = false;
|
67
|
+
sendSimpleMessage(
|
68
|
+
this.requester,
|
69
|
+
BACKGROUND_PORT,
|
70
|
+
"permission-interactive",
|
71
|
+
"enable-access",
|
72
|
+
{
|
73
|
+
chainIds,
|
74
|
+
}
|
75
|
+
)
|
76
|
+
.then(resolve)
|
77
|
+
.catch(reject)
|
78
|
+
.finally(() => (f = true));
|
79
|
+
|
80
|
+
setTimeout(() => {
|
81
|
+
if (!f) {
|
82
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
83
|
+
}
|
84
|
+
}, 100);
|
85
|
+
});
|
86
|
+
}
|
87
|
+
|
88
|
+
// TODO: 웹페이지에서도 필요할수도 있을 것 같으니 나중에 keplr의 API로 추가해준다.
|
89
|
+
async isEnabled(chainIds: string | string[]): Promise<boolean> {
|
90
|
+
if (typeof chainIds === "string") {
|
91
|
+
chainIds = [chainIds];
|
92
|
+
}
|
93
|
+
|
94
|
+
return await sendSimpleMessage(
|
66
95
|
this.requester,
|
67
96
|
BACKGROUND_PORT,
|
68
97
|
"permission-interactive",
|
69
|
-
"
|
98
|
+
"is-enabled-access",
|
70
99
|
{
|
71
100
|
chainIds,
|
72
101
|
}
|
@@ -78,15 +107,27 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
78
107
|
chainIds = [chainIds];
|
79
108
|
}
|
80
109
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
110
|
+
return new Promise((resolve, reject) => {
|
111
|
+
let f = false;
|
112
|
+
sendSimpleMessage(
|
113
|
+
this.requester,
|
114
|
+
BACKGROUND_PORT,
|
115
|
+
"permission-interactive",
|
116
|
+
"disable-access",
|
117
|
+
{
|
118
|
+
chainIds: chainIds ?? [],
|
119
|
+
}
|
120
|
+
)
|
121
|
+
.then(resolve)
|
122
|
+
.catch(reject)
|
123
|
+
.finally(() => (f = true));
|
124
|
+
|
125
|
+
setTimeout(() => {
|
126
|
+
if (!f) {
|
127
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
128
|
+
}
|
129
|
+
}, 100);
|
130
|
+
});
|
90
131
|
}
|
91
132
|
|
92
133
|
async experimentalSuggestChain(
|
@@ -134,58 +175,105 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
134
175
|
delete (chainInfo as any).coinType;
|
135
176
|
}
|
136
177
|
|
137
|
-
return
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
178
|
+
return new Promise((resolve, reject) => {
|
179
|
+
let f = false;
|
180
|
+
sendSimpleMessage(
|
181
|
+
this.requester,
|
182
|
+
BACKGROUND_PORT,
|
183
|
+
"chains",
|
184
|
+
"suggest-chain-info",
|
185
|
+
{
|
186
|
+
chainInfo,
|
187
|
+
}
|
188
|
+
)
|
189
|
+
.then(resolve)
|
190
|
+
.catch(reject)
|
191
|
+
.finally(() => (f = true));
|
192
|
+
|
193
|
+
setTimeout(() => {
|
194
|
+
if (!f) {
|
195
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
196
|
+
}
|
197
|
+
}, 100);
|
198
|
+
});
|
146
199
|
}
|
147
200
|
|
148
201
|
async getKey(chainId: string): Promise<Key> {
|
149
|
-
return
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
202
|
+
return new Promise((resolve, reject) => {
|
203
|
+
let f = false;
|
204
|
+
sendSimpleMessage(
|
205
|
+
this.requester,
|
206
|
+
BACKGROUND_PORT,
|
207
|
+
"keyring-cosmos",
|
208
|
+
"get-cosmos-key",
|
209
|
+
{
|
210
|
+
chainId,
|
211
|
+
}
|
212
|
+
)
|
213
|
+
.then(resolve)
|
214
|
+
.catch(reject)
|
215
|
+
.finally(() => (f = true));
|
216
|
+
|
217
|
+
setTimeout(() => {
|
218
|
+
if (!f) {
|
219
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
220
|
+
}
|
221
|
+
}, 100);
|
222
|
+
});
|
158
223
|
}
|
159
224
|
|
160
225
|
async getKeysSettled(chainIds: string[]): Promise<SettledResponses<Key>> {
|
161
|
-
return
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
226
|
+
return new Promise((resolve, reject) => {
|
227
|
+
let f = false;
|
228
|
+
sendSimpleMessage(
|
229
|
+
this.requester,
|
230
|
+
BACKGROUND_PORT,
|
231
|
+
"keyring-cosmos",
|
232
|
+
"get-cosmos-keys-settled",
|
233
|
+
{
|
234
|
+
chainIds,
|
235
|
+
}
|
236
|
+
)
|
237
|
+
.then(resolve)
|
238
|
+
.catch(reject)
|
239
|
+
.finally(() => (f = true));
|
240
|
+
|
241
|
+
setTimeout(() => {
|
242
|
+
if (!f) {
|
243
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
244
|
+
}
|
245
|
+
}, 100);
|
246
|
+
});
|
170
247
|
}
|
171
248
|
|
172
249
|
async getChainInfosWithoutEndpoints(): Promise<ChainInfoWithoutEndpoints[]> {
|
173
|
-
return (
|
174
|
-
|
250
|
+
return new Promise((resolve, reject) => {
|
251
|
+
let f = false;
|
252
|
+
sendSimpleMessage(
|
175
253
|
this.requester,
|
176
254
|
BACKGROUND_PORT,
|
177
255
|
"chains",
|
178
256
|
"get-chain-infos-without-endpoints",
|
179
257
|
{}
|
180
258
|
)
|
181
|
-
|
259
|
+
.then((r) => resolve(r.chainInfos))
|
260
|
+
.catch(reject)
|
261
|
+
.finally(() => (f = true));
|
262
|
+
|
263
|
+
setTimeout(() => {
|
264
|
+
if (!f) {
|
265
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
266
|
+
}
|
267
|
+
}, 100);
|
268
|
+
});
|
182
269
|
}
|
183
270
|
|
184
271
|
async getChainInfoWithoutEndpoints(
|
185
272
|
chainId: string
|
186
273
|
): Promise<ChainInfoWithoutEndpoints> {
|
187
|
-
return (
|
188
|
-
|
274
|
+
return new Promise((resolve, reject) => {
|
275
|
+
let f = false;
|
276
|
+
sendSimpleMessage(
|
189
277
|
this.requester,
|
190
278
|
BACKGROUND_PORT,
|
191
279
|
"chains",
|
@@ -194,7 +282,16 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
194
282
|
chainId,
|
195
283
|
}
|
196
284
|
)
|
197
|
-
|
285
|
+
.then((r) => resolve(r.chainInfos))
|
286
|
+
.catch(reject)
|
287
|
+
.finally(() => (f = true));
|
288
|
+
|
289
|
+
setTimeout(() => {
|
290
|
+
if (!f) {
|
291
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
292
|
+
}
|
293
|
+
}, 100);
|
294
|
+
});
|
198
295
|
}
|
199
296
|
|
200
297
|
async sendTx(
|
@@ -202,6 +299,11 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
202
299
|
tx: StdTx | Uint8Array,
|
203
300
|
mode: BroadcastMode
|
204
301
|
): Promise<Uint8Array> {
|
302
|
+
// XXX: 원래 enable을 미리하지 않아도 백그라운드에서 알아서 처리해주는 시스템이였는데...
|
303
|
+
// side panel에서는 불가능하기 때문에 이젠 provider에서 permission도 관리해줘야한다...
|
304
|
+
// sendTx의 경우는 일종의 쿼리이기 때문에 언제 결과가 올지 알 수 없다. 그러므로 미리 권한 처리를 해야한다.
|
305
|
+
await this.enable(chainId);
|
306
|
+
|
205
307
|
return await sendSimpleMessage(
|
206
308
|
this.requester,
|
207
309
|
BACKGROUND_PORT,
|
@@ -221,18 +323,30 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
221
323
|
signDoc: StdSignDoc,
|
222
324
|
signOptions: KeplrSignOptions = {}
|
223
325
|
): Promise<AminoSignResponse> {
|
224
|
-
return
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
326
|
+
return new Promise((resolve, reject) => {
|
327
|
+
let f = false;
|
328
|
+
sendSimpleMessage(
|
329
|
+
this.requester,
|
330
|
+
BACKGROUND_PORT,
|
331
|
+
"keyring-cosmos",
|
332
|
+
"request-cosmos-sign-amino",
|
333
|
+
{
|
334
|
+
chainId,
|
335
|
+
signer,
|
336
|
+
signDoc,
|
337
|
+
signOptions: deepmerge(this.defaultOptions.sign ?? {}, signOptions),
|
338
|
+
}
|
339
|
+
)
|
340
|
+
.then(resolve)
|
341
|
+
.catch(reject)
|
342
|
+
.finally(() => (f = true));
|
343
|
+
|
344
|
+
setTimeout(() => {
|
345
|
+
if (!f) {
|
346
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
347
|
+
}
|
348
|
+
}, 100);
|
349
|
+
});
|
236
350
|
}
|
237
351
|
|
238
352
|
async signDirect(
|
@@ -246,35 +360,47 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
246
360
|
},
|
247
361
|
signOptions: KeplrSignOptions = {}
|
248
362
|
): Promise<DirectSignResponse> {
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
:
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
363
|
+
return new Promise((resolve, reject) => {
|
364
|
+
let f = false;
|
365
|
+
sendSimpleMessage(
|
366
|
+
this.requester,
|
367
|
+
BACKGROUND_PORT,
|
368
|
+
"keyring-cosmos",
|
369
|
+
"request-cosmos-sign-direct",
|
370
|
+
{
|
371
|
+
chainId,
|
372
|
+
signer,
|
373
|
+
signDoc: {
|
374
|
+
bodyBytes: signDoc.bodyBytes,
|
375
|
+
authInfoBytes: signDoc.authInfoBytes,
|
376
|
+
chainId: signDoc.chainId,
|
377
|
+
accountNumber: signDoc.accountNumber
|
378
|
+
? signDoc.accountNumber.toString()
|
379
|
+
: null,
|
380
|
+
},
|
381
|
+
signOptions: deepmerge(this.defaultOptions.sign ?? {}, signOptions),
|
382
|
+
}
|
383
|
+
)
|
384
|
+
.then((r) =>
|
385
|
+
resolve({
|
386
|
+
signed: {
|
387
|
+
bodyBytes: r.signed.bodyBytes,
|
388
|
+
authInfoBytes: r.signed.authInfoBytes,
|
389
|
+
chainId: r.signed.chainId,
|
390
|
+
accountNumber: Long.fromString(r.signed.accountNumber),
|
391
|
+
},
|
392
|
+
signature: r.signature,
|
393
|
+
})
|
394
|
+
)
|
395
|
+
.catch(reject)
|
396
|
+
.finally(() => (f = true));
|
268
397
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
},
|
276
|
-
signature: response.signature,
|
277
|
-
};
|
398
|
+
setTimeout(() => {
|
399
|
+
if (!f) {
|
400
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
401
|
+
}
|
402
|
+
}, 100);
|
403
|
+
});
|
278
404
|
}
|
279
405
|
|
280
406
|
async signDirectAux(
|
@@ -295,42 +421,54 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
295
421
|
"preferNoSetFee" | "disableBalanceCheck"
|
296
422
|
> = {}
|
297
423
|
): Promise<DirectAuxSignResponse> {
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
:
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
{
|
317
|
-
preferNoSetMemo: this.defaultOptions.sign?.preferNoSetMemo,
|
424
|
+
return new Promise((resolve, reject) => {
|
425
|
+
let f = false;
|
426
|
+
sendSimpleMessage(
|
427
|
+
this.requester,
|
428
|
+
BACKGROUND_PORT,
|
429
|
+
"keyring-cosmos",
|
430
|
+
"request-cosmos-sign-direct-aux",
|
431
|
+
{
|
432
|
+
chainId,
|
433
|
+
signer,
|
434
|
+
signDoc: {
|
435
|
+
bodyBytes: signDoc.bodyBytes,
|
436
|
+
publicKey: signDoc.publicKey,
|
437
|
+
chainId: signDoc.chainId,
|
438
|
+
accountNumber: signDoc.accountNumber
|
439
|
+
? signDoc.accountNumber.toString()
|
440
|
+
: null,
|
441
|
+
sequence: signDoc.sequence ? signDoc.sequence.toString() : null,
|
318
442
|
},
|
319
|
-
signOptions
|
320
|
-
|
321
|
-
|
322
|
-
|
443
|
+
signOptions: deepmerge(
|
444
|
+
{
|
445
|
+
preferNoSetMemo: this.defaultOptions.sign?.preferNoSetMemo,
|
446
|
+
},
|
447
|
+
signOptions
|
448
|
+
),
|
449
|
+
}
|
450
|
+
)
|
451
|
+
.then((r) =>
|
452
|
+
resolve({
|
453
|
+
signed: {
|
454
|
+
bodyBytes: r.signed.bodyBytes,
|
455
|
+
publicKey: r.signed.publicKey,
|
456
|
+
chainId: r.signed.chainId,
|
457
|
+
accountNumber: Long.fromString(r.signed.accountNumber),
|
458
|
+
sequence: Long.fromString(r.signed.sequence),
|
459
|
+
},
|
460
|
+
signature: r.signature,
|
461
|
+
})
|
462
|
+
)
|
463
|
+
.catch(reject)
|
464
|
+
.finally(() => (f = true));
|
323
465
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
sequence: Long.fromString(response.signed.sequence),
|
331
|
-
},
|
332
|
-
signature: response.signature,
|
333
|
-
};
|
466
|
+
setTimeout(() => {
|
467
|
+
if (!f) {
|
468
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
469
|
+
}
|
470
|
+
}, 100);
|
471
|
+
});
|
334
472
|
}
|
335
473
|
|
336
474
|
async signArbitrary(
|
@@ -338,20 +476,32 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
338
476
|
signer: string,
|
339
477
|
data: string | Uint8Array
|
340
478
|
): Promise<StdSignature> {
|
341
|
-
return
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
479
|
+
return new Promise((resolve, reject) => {
|
480
|
+
let f = false;
|
481
|
+
sendSimpleMessage(
|
482
|
+
this.requester,
|
483
|
+
BACKGROUND_PORT,
|
484
|
+
"keyring-cosmos",
|
485
|
+
"request-cosmos-sign-amino-adr-36",
|
486
|
+
{
|
487
|
+
chainId,
|
488
|
+
signer,
|
489
|
+
data: typeof data === "string" ? Buffer.from(data) : data,
|
490
|
+
signOptions: {
|
491
|
+
isADR36WithString: typeof data === "string",
|
492
|
+
},
|
493
|
+
}
|
494
|
+
)
|
495
|
+
.then(resolve)
|
496
|
+
.catch(reject)
|
497
|
+
.finally(() => (f = true));
|
498
|
+
|
499
|
+
setTimeout(() => {
|
500
|
+
if (!f) {
|
501
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
502
|
+
}
|
503
|
+
}, 100);
|
504
|
+
});
|
355
505
|
}
|
356
506
|
|
357
507
|
async verifyArbitrary(
|
@@ -364,18 +514,30 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
364
514
|
data = Buffer.from(data);
|
365
515
|
}
|
366
516
|
|
367
|
-
return
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
517
|
+
return new Promise((resolve, reject) => {
|
518
|
+
let f = false;
|
519
|
+
sendSimpleMessage(
|
520
|
+
this.requester,
|
521
|
+
BACKGROUND_PORT,
|
522
|
+
"keyring-cosmos",
|
523
|
+
"verify-cosmos-sign-amino-adr-36",
|
524
|
+
{
|
525
|
+
chainId,
|
526
|
+
signer,
|
527
|
+
data,
|
528
|
+
signature,
|
529
|
+
}
|
530
|
+
)
|
531
|
+
.then(resolve)
|
532
|
+
.catch(reject)
|
533
|
+
.finally(() => (f = true));
|
534
|
+
|
535
|
+
setTimeout(() => {
|
536
|
+
if (!f) {
|
537
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
538
|
+
}
|
539
|
+
}, 100);
|
540
|
+
});
|
379
541
|
}
|
380
542
|
|
381
543
|
async signEthereum(
|
@@ -384,18 +546,30 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
384
546
|
message: string | Uint8Array,
|
385
547
|
signType: EthSignType
|
386
548
|
): Promise<Uint8Array> {
|
387
|
-
return
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
549
|
+
return new Promise((resolve, reject) => {
|
550
|
+
let f = false;
|
551
|
+
sendSimpleMessage(
|
552
|
+
this.requester,
|
553
|
+
BACKGROUND_PORT,
|
554
|
+
"keyring-ethereum",
|
555
|
+
"request-sign-ethereum",
|
556
|
+
{
|
557
|
+
chainId,
|
558
|
+
signer,
|
559
|
+
message: typeof message === "string" ? Buffer.from(message) : message,
|
560
|
+
signType,
|
561
|
+
}
|
562
|
+
)
|
563
|
+
.then(resolve)
|
564
|
+
.catch(reject)
|
565
|
+
.finally(() => (f = true));
|
566
|
+
|
567
|
+
setTimeout(() => {
|
568
|
+
if (!f) {
|
569
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
570
|
+
}
|
571
|
+
}, 100);
|
572
|
+
});
|
399
573
|
}
|
400
574
|
|
401
575
|
async signICNSAdr36(
|
@@ -405,19 +579,31 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
405
579
|
username: string,
|
406
580
|
addressChainIds: string[]
|
407
581
|
): Promise<ICNSAdr36Signatures> {
|
408
|
-
return
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
582
|
+
return new Promise((resolve, reject) => {
|
583
|
+
let f = false;
|
584
|
+
sendSimpleMessage(
|
585
|
+
this.requester,
|
586
|
+
BACKGROUND_PORT,
|
587
|
+
"keyring-cosmos",
|
588
|
+
"request-icns-adr-36-signatures-v2",
|
589
|
+
{
|
590
|
+
chainId,
|
591
|
+
contractAddress,
|
592
|
+
owner,
|
593
|
+
username,
|
594
|
+
addressChainIds,
|
595
|
+
}
|
596
|
+
)
|
597
|
+
.then(resolve)
|
598
|
+
.catch(reject)
|
599
|
+
.finally(() => (f = true));
|
600
|
+
|
601
|
+
setTimeout(() => {
|
602
|
+
if (!f) {
|
603
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
604
|
+
}
|
605
|
+
}, 100);
|
606
|
+
});
|
421
607
|
}
|
422
608
|
|
423
609
|
getOfflineSigner(
|
@@ -450,61 +636,109 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
450
636
|
contractAddress: string,
|
451
637
|
viewingKey?: string
|
452
638
|
): Promise<void> {
|
453
|
-
return
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
639
|
+
return new Promise((resolve, reject) => {
|
640
|
+
let f = false;
|
641
|
+
sendSimpleMessage(
|
642
|
+
this.requester,
|
643
|
+
BACKGROUND_PORT,
|
644
|
+
"token-cw20",
|
645
|
+
"SuggestTokenMsg",
|
646
|
+
{
|
647
|
+
chainId,
|
648
|
+
contractAddress,
|
649
|
+
viewingKey,
|
650
|
+
}
|
651
|
+
)
|
652
|
+
.then(resolve)
|
653
|
+
.catch(reject)
|
654
|
+
.finally(() => (f = true));
|
655
|
+
|
656
|
+
setTimeout(() => {
|
657
|
+
if (!f) {
|
658
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
659
|
+
}
|
660
|
+
}, 100);
|
661
|
+
});
|
464
662
|
}
|
465
663
|
|
466
664
|
async getSecret20ViewingKey(
|
467
665
|
chainId: string,
|
468
666
|
contractAddress: string
|
469
667
|
): Promise<string> {
|
470
|
-
return
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
668
|
+
return new Promise((resolve, reject) => {
|
669
|
+
let f = false;
|
670
|
+
sendSimpleMessage(
|
671
|
+
this.requester,
|
672
|
+
BACKGROUND_PORT,
|
673
|
+
"token-cw20",
|
674
|
+
"get-secret20-viewing-key",
|
675
|
+
{
|
676
|
+
chainId,
|
677
|
+
contractAddress,
|
678
|
+
}
|
679
|
+
)
|
680
|
+
.then(resolve)
|
681
|
+
.catch(reject)
|
682
|
+
.finally(() => (f = true));
|
683
|
+
|
684
|
+
setTimeout(() => {
|
685
|
+
if (!f) {
|
686
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
687
|
+
}
|
688
|
+
}, 100);
|
689
|
+
});
|
480
690
|
}
|
481
691
|
|
482
692
|
async getEnigmaPubKey(chainId: string): Promise<Uint8Array> {
|
483
|
-
return
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
693
|
+
return new Promise((resolve, reject) => {
|
694
|
+
let f = false;
|
695
|
+
sendSimpleMessage(
|
696
|
+
this.requester,
|
697
|
+
BACKGROUND_PORT,
|
698
|
+
"secret-wasm",
|
699
|
+
"get-pubkey-msg",
|
700
|
+
{
|
701
|
+
chainId,
|
702
|
+
}
|
703
|
+
)
|
704
|
+
.then(resolve)
|
705
|
+
.catch(reject)
|
706
|
+
.finally(() => (f = true));
|
707
|
+
|
708
|
+
setTimeout(() => {
|
709
|
+
if (!f) {
|
710
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
711
|
+
}
|
712
|
+
}, 100);
|
713
|
+
});
|
492
714
|
}
|
493
715
|
|
494
716
|
async getEnigmaTxEncryptionKey(
|
495
717
|
chainId: string,
|
496
718
|
nonce: Uint8Array
|
497
719
|
): Promise<Uint8Array> {
|
498
|
-
return
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
720
|
+
return new Promise((resolve, reject) => {
|
721
|
+
let f = false;
|
722
|
+
sendSimpleMessage(
|
723
|
+
this.requester,
|
724
|
+
BACKGROUND_PORT,
|
725
|
+
"secret-wasm",
|
726
|
+
"get-tx-encryption-key-msg",
|
727
|
+
{
|
728
|
+
chainId,
|
729
|
+
nonce,
|
730
|
+
}
|
731
|
+
)
|
732
|
+
.then(resolve)
|
733
|
+
.catch(reject)
|
734
|
+
.finally(() => (f = true));
|
735
|
+
|
736
|
+
setTimeout(() => {
|
737
|
+
if (!f) {
|
738
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
739
|
+
}
|
740
|
+
}, 100);
|
741
|
+
});
|
508
742
|
}
|
509
743
|
|
510
744
|
async enigmaEncrypt(
|
@@ -513,17 +747,29 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
513
747
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
514
748
|
msg: object
|
515
749
|
): Promise<Uint8Array> {
|
516
|
-
return
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
750
|
+
return new Promise((resolve, reject) => {
|
751
|
+
let f = false;
|
752
|
+
sendSimpleMessage(
|
753
|
+
this.requester,
|
754
|
+
BACKGROUND_PORT,
|
755
|
+
"secret-wasm",
|
756
|
+
"request-encrypt-msg",
|
757
|
+
{
|
758
|
+
chainId,
|
759
|
+
contractCodeHash,
|
760
|
+
msg,
|
761
|
+
}
|
762
|
+
)
|
763
|
+
.then(resolve)
|
764
|
+
.catch(reject)
|
765
|
+
.finally(() => (f = true));
|
766
|
+
|
767
|
+
setTimeout(() => {
|
768
|
+
if (!f) {
|
769
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
770
|
+
}
|
771
|
+
}, 100);
|
772
|
+
});
|
527
773
|
}
|
528
774
|
|
529
775
|
async enigmaDecrypt(
|
@@ -535,17 +781,29 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
535
781
|
return new Uint8Array();
|
536
782
|
}
|
537
783
|
|
538
|
-
return
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
784
|
+
return new Promise((resolve, reject) => {
|
785
|
+
let f = false;
|
786
|
+
sendSimpleMessage(
|
787
|
+
this.requester,
|
788
|
+
BACKGROUND_PORT,
|
789
|
+
"secret-wasm",
|
790
|
+
"request-decrypt-msg",
|
791
|
+
{
|
792
|
+
chainId,
|
793
|
+
cipherText,
|
794
|
+
nonce,
|
795
|
+
}
|
796
|
+
)
|
797
|
+
.then(resolve)
|
798
|
+
.catch(reject)
|
799
|
+
.finally(() => (f = true));
|
800
|
+
|
801
|
+
setTimeout(() => {
|
802
|
+
if (!f) {
|
803
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
804
|
+
}
|
805
|
+
}, 100);
|
806
|
+
});
|
549
807
|
}
|
550
808
|
|
551
809
|
getEnigmaUtils(chainId: string): SecretUtils {
|
@@ -570,19 +828,31 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
570
828
|
signDoc: StdSignDoc,
|
571
829
|
signOptions: KeplrSignOptions = {}
|
572
830
|
): Promise<AminoSignResponse> {
|
573
|
-
return
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
831
|
+
return new Promise((resolve, reject) => {
|
832
|
+
let f = false;
|
833
|
+
sendSimpleMessage(
|
834
|
+
this.requester,
|
835
|
+
BACKGROUND_PORT,
|
836
|
+
"keyring-cosmos",
|
837
|
+
"request-sign-eip-712-cosmos-tx-v0",
|
838
|
+
{
|
839
|
+
chainId,
|
840
|
+
signer,
|
841
|
+
eip712,
|
842
|
+
signDoc,
|
843
|
+
signOptions: deepmerge(this.defaultOptions.sign ?? {}, signOptions),
|
844
|
+
}
|
845
|
+
)
|
846
|
+
.then(resolve)
|
847
|
+
.catch(reject)
|
848
|
+
.finally(() => (f = true));
|
849
|
+
|
850
|
+
setTimeout(() => {
|
851
|
+
if (!f) {
|
852
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
853
|
+
}
|
854
|
+
}, 100);
|
855
|
+
});
|
586
856
|
}
|
587
857
|
|
588
858
|
async __core__getAnalyticsId(): Promise<string> {
|
@@ -602,16 +872,28 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
602
872
|
defaultName: string;
|
603
873
|
editable?: boolean;
|
604
874
|
}): Promise<string> {
|
605
|
-
return
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
875
|
+
return new Promise((resolve, reject) => {
|
876
|
+
let f = false;
|
877
|
+
sendSimpleMessage(
|
878
|
+
this.requester,
|
879
|
+
BACKGROUND_PORT,
|
880
|
+
"keyring-v2",
|
881
|
+
"change-keyring-name-interactive",
|
882
|
+
{
|
883
|
+
defaultName,
|
884
|
+
editable,
|
885
|
+
}
|
886
|
+
)
|
887
|
+
.then(resolve)
|
888
|
+
.catch(reject)
|
889
|
+
.finally(() => (f = true));
|
890
|
+
|
891
|
+
setTimeout(() => {
|
892
|
+
if (!f) {
|
893
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
894
|
+
}
|
895
|
+
}, 100);
|
896
|
+
});
|
615
897
|
}
|
616
898
|
|
617
899
|
async __core__privilageSignAminoWithdrawRewards(
|
@@ -651,6 +933,11 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
651
933
|
}
|
652
934
|
|
653
935
|
async sendEthereumTx(chainId: string, tx: Uint8Array): Promise<string> {
|
936
|
+
// XXX: 원래 enable을 미리하지 않아도 백그라운드에서 알아서 처리해주는 시스템이였는데...
|
937
|
+
// side panel에서는 불가능하기 때문에 이젠 provider에서 permission도 관리해줘야한다...
|
938
|
+
// sendTx의 경우는 일종의 쿼리이기 때문에 언제 결과가 올지 알 수 없다. 그러므로 미리 권한 처리를 해야한다.
|
939
|
+
await this.enable(chainId);
|
940
|
+
|
654
941
|
return await sendSimpleMessage(
|
655
942
|
this.requester,
|
656
943
|
BACKGROUND_PORT,
|
@@ -664,21 +951,344 @@ export class Keplr implements IKeplr, KeplrCoreTypes {
|
|
664
951
|
}
|
665
952
|
|
666
953
|
async suggestERC20(chainId: string, contractAddress: string): Promise<void> {
|
667
|
-
return
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
954
|
+
return new Promise((resolve, reject) => {
|
955
|
+
let f = false;
|
956
|
+
sendSimpleMessage(
|
957
|
+
this.requester,
|
958
|
+
BACKGROUND_PORT,
|
959
|
+
"token-erc20",
|
960
|
+
"SuggestERC20TokenMsg",
|
961
|
+
{
|
962
|
+
chainId,
|
963
|
+
contractAddress,
|
964
|
+
}
|
965
|
+
)
|
966
|
+
.then(resolve)
|
967
|
+
.catch(reject)
|
968
|
+
.finally(() => (f = true));
|
969
|
+
|
970
|
+
setTimeout(() => {
|
971
|
+
if (!f) {
|
972
|
+
this.protectedTryOpenSidePanelIfEnabled();
|
973
|
+
}
|
974
|
+
}, 100);
|
975
|
+
});
|
976
|
+
}
|
977
|
+
|
978
|
+
// IMPORTANT: protected로 시작하는 method는 InjectedKeplr.startProxy()에서 injected 쪽에서 event system으로도 호출할 수 없도록 막혀있다.
|
979
|
+
// protected로 시작하지 않는 method는 injected keplr에 없어도 event system을 통하면 호출 할 수 있다.
|
980
|
+
// 이를 막기 위해서 method 이름을 protected로 시작하게 한다.
|
981
|
+
async protectedTryOpenSidePanelIfEnabled(
|
982
|
+
ignoreGestureFailure: boolean = false
|
983
|
+
): Promise<void> {
|
984
|
+
let isInContentScript = false;
|
985
|
+
// 이 provider가 content script 위에서 동작하고 있는지 아닌지 구분해야한다.
|
986
|
+
// content script일때만 side panel을 열도록 시도해볼 가치가 있다.
|
987
|
+
// 근데 js 자체적으로 api등을 통해서는 이를 알아낼 방법이 없다.
|
988
|
+
// extension 상에서 content script에서 keplr provider proxy를 시작하기 전에 window에 밑의 field를 알아서 주입하는 방식으로 처리한다.
|
989
|
+
if (
|
990
|
+
typeof window !== "undefined" &&
|
991
|
+
(window as any).__keplr_content_script === true
|
992
|
+
) {
|
993
|
+
isInContentScript = true;
|
994
|
+
}
|
995
|
+
|
996
|
+
if (isInContentScript) {
|
997
|
+
const isEnabled = await sendSimpleMessage<{
|
998
|
+
enabled: boolean;
|
999
|
+
}>(
|
1000
|
+
this.requester,
|
1001
|
+
BACKGROUND_PORT,
|
1002
|
+
"side-panel",
|
1003
|
+
"GetSidePanelEnabledMsg",
|
1004
|
+
{}
|
1005
|
+
);
|
1006
|
+
|
1007
|
+
if (isEnabled.enabled) {
|
1008
|
+
try {
|
1009
|
+
// IMPORTANT: "tryOpenSidePanelIfEnabled"는 다른 msg system과 아예 분리되어있고 다르게 동작한다.
|
1010
|
+
// router-extension package의 src/router/extension.ts에 있는 주석을 참고할 것.
|
1011
|
+
return await sendSimpleMessage(
|
1012
|
+
this.requester,
|
1013
|
+
BACKGROUND_PORT,
|
1014
|
+
"router-extension/src/router/extension.ts",
|
1015
|
+
"tryOpenSidePanelIfEnabled",
|
1016
|
+
{}
|
1017
|
+
);
|
1018
|
+
} catch (e) {
|
1019
|
+
console.log(e);
|
1020
|
+
|
1021
|
+
if (
|
1022
|
+
!ignoreGestureFailure &&
|
1023
|
+
e.message &&
|
1024
|
+
e.message.includes("in response to a user gesture")
|
1025
|
+
) {
|
1026
|
+
if (!document.getElementById("__open_keplr_side_panel__")) {
|
1027
|
+
const sidePanelPing = await sendSimpleMessage<boolean>(
|
1028
|
+
this.requester,
|
1029
|
+
BACKGROUND_PORT,
|
1030
|
+
"interaction",
|
1031
|
+
"ping-content-script-tab-has-opened-side-panel",
|
1032
|
+
{}
|
1033
|
+
);
|
1034
|
+
|
1035
|
+
// 유저가 직접 side panel을 이미 열어논 상태일 수 있다.
|
1036
|
+
// 이 경우는 무시하도록 한다.
|
1037
|
+
if (sidePanelPing) {
|
1038
|
+
return;
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
const isKeplrLocked = await sendSimpleMessage<boolean>(
|
1042
|
+
this.requester,
|
1043
|
+
BACKGROUND_PORT,
|
1044
|
+
"keyring",
|
1045
|
+
"GetIsLockedMsg",
|
1046
|
+
{}
|
1047
|
+
);
|
1048
|
+
|
1049
|
+
const keplrThemeOption = await sendSimpleMessage<
|
1050
|
+
"light" | "dark" | "auto"
|
1051
|
+
>(
|
1052
|
+
this.requester,
|
1053
|
+
BACKGROUND_PORT,
|
1054
|
+
"settings",
|
1055
|
+
"GetThemeOptionMsg",
|
1056
|
+
{}
|
1057
|
+
);
|
1058
|
+
|
1059
|
+
// extension에서 `web_accessible_resources`에 추가된 파일은 이렇게 접근이 가능함
|
1060
|
+
const fontUrl = chrome.runtime.getURL(
|
1061
|
+
"/assets/Inter-SemiBold.ttf"
|
1062
|
+
);
|
1063
|
+
const fontFaceAndKeyFrames = `
|
1064
|
+
@font-face {
|
1065
|
+
font-family: 'Inter-SemiBold-Keplr';
|
1066
|
+
src: url('${fontUrl}') format('truetype');
|
1067
|
+
font-weight: 600;
|
1068
|
+
font-style: normal;
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
@keyframes slide-left {
|
1072
|
+
0% {
|
1073
|
+
transform: translateY(0%) translateX(100%);
|
1074
|
+
}
|
1075
|
+
100% {
|
1076
|
+
transform: translateY(0%) translateX(0);
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
|
1080
|
+
@keyframes tada {
|
1081
|
+
0% {
|
1082
|
+
transform: scale3d(1, 1, 1);
|
1083
|
+
}
|
1084
|
+
10%, 20% {
|
1085
|
+
transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
|
1086
|
+
}
|
1087
|
+
30%, 50%, 70%, 90% {
|
1088
|
+
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
|
1089
|
+
}
|
1090
|
+
40%, 60%, 80% {
|
1091
|
+
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
|
1092
|
+
}
|
1093
|
+
100% {
|
1094
|
+
transform: scale3d(1, 1, 1);
|
1095
|
+
}
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
`;
|
1099
|
+
|
1100
|
+
const isLightMode =
|
1101
|
+
keplrThemeOption === "auto"
|
1102
|
+
? !window.matchMedia("(prefers-color-scheme: dark)").matches
|
1103
|
+
: keplrThemeOption === "light";
|
1104
|
+
|
1105
|
+
// 폰트와 애니메이션을 위한 스타일 요소를 head에 추가
|
1106
|
+
const styleElement = document.createElement("style");
|
1107
|
+
styleElement.appendChild(
|
1108
|
+
document.createTextNode(fontFaceAndKeyFrames)
|
1109
|
+
);
|
1110
|
+
document.head.appendChild(styleElement);
|
1111
|
+
|
1112
|
+
const button = document.createElement("div");
|
1113
|
+
button.id = "__open_keplr_side_panel__";
|
1114
|
+
button.style.boxSizing = "border-box";
|
1115
|
+
button.style.animation = "slide-left 0.5s forwards";
|
1116
|
+
button.style.position = "fixed";
|
1117
|
+
button.style.right = "1.5rem";
|
1118
|
+
button.style.top = "1.5rem";
|
1119
|
+
button.style.padding = "1rem 1.75rem 1rem 0.75rem";
|
1120
|
+
button.style.zIndex = "2147483647"; // 페이지 상의 다른 요소보다 버튼이 위에 오도록 함
|
1121
|
+
button.style.borderRadius = "1rem";
|
1122
|
+
button.style.display = "flex";
|
1123
|
+
button.style.alignItems = "center";
|
1124
|
+
|
1125
|
+
button.style.fontFamily = "Inter-SemiBold-Keplr";
|
1126
|
+
button.style.fontWeight = "600";
|
1127
|
+
|
1128
|
+
// button.style.cursor = "pointer";
|
1129
|
+
button.style.background = isLightMode ? "#FEFEFE" : "#1D1D1F";
|
1130
|
+
// if (isLightMode) {
|
1131
|
+
// button.style.boxShadow =
|
1132
|
+
// "0px 0px 15.5px 0px rgba(0, 0, 0, 0.20)";
|
1133
|
+
// }
|
1134
|
+
// button.addEventListener("mouseover", () => {
|
1135
|
+
// button.style.background = isLightMode ? "#F2F2F6" : "#242428";
|
1136
|
+
// });
|
1137
|
+
// button.addEventListener("mouseout", () => {
|
1138
|
+
// button.style.background = isLightMode ? "#FEFEFE" : "#1D1D1F";
|
1139
|
+
// });
|
1140
|
+
|
1141
|
+
// const megaphoneWrapper = document.createElement("div");
|
1142
|
+
// megaphoneWrapper.style.boxSizing = "border-box";
|
1143
|
+
// megaphoneWrapper.style.display = "flex";
|
1144
|
+
// megaphoneWrapper.style.position = "absolute";
|
1145
|
+
// megaphoneWrapper.style.left = "-10px";
|
1146
|
+
// megaphoneWrapper.style.top = "-10px";
|
1147
|
+
// megaphoneWrapper.style.padding = "6.5px 6px 5.5px";
|
1148
|
+
// megaphoneWrapper.style.borderRadius = "255px";
|
1149
|
+
// megaphoneWrapper.style.background = "#FC8441";
|
1150
|
+
//
|
1151
|
+
// const megaphone = document.createElement("img");
|
1152
|
+
// const megaphoneUrl = chrome.runtime.getURL(
|
1153
|
+
// "/assets/megaphone.svg"
|
1154
|
+
// );
|
1155
|
+
// megaphone.src = megaphoneUrl;
|
1156
|
+
// megaphone.style.width = "1.25rem";
|
1157
|
+
// megaphone.style.height = "1.25rem";
|
1158
|
+
// megaphone.style.animation = "tada 1s infinite";
|
1159
|
+
// megaphoneWrapper.appendChild(megaphone);
|
1160
|
+
|
1161
|
+
const arrowTop = document.createElement("div");
|
1162
|
+
arrowTop.style.boxSizing = "border-box";
|
1163
|
+
arrowTop.style.transform = "translateY(-0.65rem)";
|
1164
|
+
arrowTop.style.marginRight = "0.35rem";
|
1165
|
+
arrowTop.innerHTML = `
|
1166
|
+
<svg width="31" height="31" viewBox="0 0 31 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
1167
|
+
<path d="M30 29.7522C25.1484 31.0691 16.7109 27.1184 18.6093 18.3391C20.5078 9.55979 25.5703 11.5351 26.414 12.852C27.2578 14.1689 28.3125 22.2898 15.8672 19.2171C5.9109 16.7589 7.15625 6.04811 8 1M8 1L14 8M8 1L1 7.5" stroke="${
|
1168
|
+
isLightMode ? "#2C4BE2" : "#72747B"
|
1169
|
+
}"/>
|
1170
|
+
</svg>
|
1171
|
+
`;
|
1172
|
+
|
1173
|
+
const keplrLogoWrap = document.createElement("div");
|
1174
|
+
keplrLogoWrap.style.boxSizing = "border-box";
|
1175
|
+
keplrLogoWrap.style.position = "relative";
|
1176
|
+
keplrLogoWrap.style.marginRight = "1rem";
|
1177
|
+
const keplrLogo = document.createElement("img");
|
1178
|
+
const keplrLogoUrl = chrome.runtime.getURL(
|
1179
|
+
`/assets/${
|
1180
|
+
isKeplrLocked ? "locked-keplr-logo" : "icon"
|
1181
|
+
}-128.png`
|
1182
|
+
);
|
1183
|
+
keplrLogo.src = keplrLogoUrl;
|
1184
|
+
keplrLogo.style.boxSizing = "border-box";
|
1185
|
+
keplrLogo.style.width = "3rem";
|
1186
|
+
keplrLogo.style.height = "3rem";
|
1187
|
+
keplrLogoWrap.appendChild(keplrLogo);
|
1188
|
+
|
1189
|
+
const logoClickCursor = document.createElement("img");
|
1190
|
+
const logoClickCursorUrl = chrome.runtime.getURL(
|
1191
|
+
"assets/icon-click-cursor.png"
|
1192
|
+
);
|
1193
|
+
logoClickCursor.src = logoClickCursorUrl;
|
1194
|
+
logoClickCursor.style.boxSizing = "border-box";
|
1195
|
+
logoClickCursor.style.position = "absolute";
|
1196
|
+
logoClickCursor.style.right = "-0.2rem";
|
1197
|
+
logoClickCursor.style.bottom = "-0.2rem";
|
1198
|
+
logoClickCursor.style.aspectRatio = "78/98";
|
1199
|
+
logoClickCursor.style.height = "1.375rem";
|
1200
|
+
keplrLogoWrap.appendChild(logoClickCursor);
|
1201
|
+
|
1202
|
+
const mainText = document.createElement("span");
|
1203
|
+
mainText.style.boxSizing = "border-box";
|
1204
|
+
// mainText.style.maxWidth = "9.125rem";
|
1205
|
+
mainText.style.fontSize = "1rem";
|
1206
|
+
mainText.style.color = isLightMode ? "#020202" : "#FEFEFE";
|
1207
|
+
mainText.textContent = isKeplrLocked
|
1208
|
+
? "Unlock Keplr to proceed"
|
1209
|
+
: "Open Keplr to approve request(s)";
|
1210
|
+
|
1211
|
+
// const arrowLeftOpenWrapper = document.createElement("div");
|
1212
|
+
// arrowLeftOpenWrapper.style.boxSizing = "border-box";
|
1213
|
+
// arrowLeftOpenWrapper.style.display = "flex";
|
1214
|
+
// arrowLeftOpenWrapper.style.alignItems = "center";
|
1215
|
+
// arrowLeftOpenWrapper.style.padding = "0.5rem 0.75rem";
|
1216
|
+
//
|
1217
|
+
// arrowLeftOpenWrapper.innerHTML = `
|
1218
|
+
// <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
1219
|
+
// <path d="M13 5L6.25 11.75L13 18.5" stroke=${
|
1220
|
+
// isLightMode ? "#1633C0" : "#566FEC"
|
1221
|
+
// } stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
1222
|
+
// <path d="M19.3333 5L12.5833 11.75L19.3333 18.5" stroke=${
|
1223
|
+
// isLightMode ? "#1633C0" : "#566FEC"
|
1224
|
+
// } stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
1225
|
+
// </svg>`;
|
1226
|
+
//
|
1227
|
+
// const openText = document.createElement("span");
|
1228
|
+
// openText.style.boxSizing = "border-box";
|
1229
|
+
// openText.style.fontSize = "1rem";
|
1230
|
+
// openText.style.color = isLightMode ? "#1633C0" : "#566FEC";
|
1231
|
+
// openText.textContent = "OPEN";
|
1232
|
+
//
|
1233
|
+
// arrowLeftOpenWrapper.appendChild(openText);
|
1234
|
+
|
1235
|
+
// button.appendChild(megaphoneWrapper);
|
1236
|
+
button.appendChild(arrowTop);
|
1237
|
+
button.appendChild(keplrLogoWrap);
|
1238
|
+
button.appendChild(mainText);
|
1239
|
+
// button.appendChild(arrowLeftOpenWrapper);
|
1240
|
+
|
1241
|
+
// 버튼을 추가하기 전에 한 번 더 이미 추가된 버튼이 있는지 확인
|
1242
|
+
const hasAlready = document.getElementById(
|
1243
|
+
"__open_keplr_side_panel__"
|
1244
|
+
);
|
1245
|
+
|
1246
|
+
if (!hasAlready) {
|
1247
|
+
let removed = false;
|
1248
|
+
// 유저가 이 button이 아니라 다른 방식(직접 작업줄의 아이콘을 눌러서 등등)으로 side panel을 열수도 있다.
|
1249
|
+
// 이 경우를 감지해서 side panel이 열렸으면 자동으로 이 버튼이 삭제되도록 한다.
|
1250
|
+
const intervalId = setInterval(() => {
|
1251
|
+
sendSimpleMessage<boolean>(
|
1252
|
+
this.requester,
|
1253
|
+
BACKGROUND_PORT,
|
1254
|
+
"interaction",
|
1255
|
+
"ping-content-script-tab-has-opened-side-panel",
|
1256
|
+
{}
|
1257
|
+
).then((sidePanelPing) => {
|
1258
|
+
if (sidePanelPing) {
|
1259
|
+
clearInterval(intervalId);
|
1260
|
+
if (!removed) {
|
1261
|
+
button.remove();
|
1262
|
+
removed = true;
|
1263
|
+
}
|
1264
|
+
}
|
1265
|
+
});
|
1266
|
+
}, 300);
|
1267
|
+
|
1268
|
+
// 버튼을 body에 추가
|
1269
|
+
document.body.appendChild(button);
|
1270
|
+
|
1271
|
+
// XXX: 현재 크롬의 버그로 인해서 밑의 코드가 동작할 수 없기 때문에 일단 주석처리한다.
|
1272
|
+
// 버튼 클릭 이벤트 추가 (필요한 동작을 정의)
|
1273
|
+
// button.addEventListener("click", () => {
|
1274
|
+
// this.protectedTryOpenSidePanelIfEnabled(true);
|
1275
|
+
//
|
1276
|
+
// clearInterval(intervalId);
|
1277
|
+
// if (!removed) {
|
1278
|
+
// button.remove();
|
1279
|
+
// removed = true;
|
1280
|
+
// }
|
1281
|
+
// });
|
1282
|
+
}
|
1283
|
+
}
|
1284
|
+
}
|
1285
|
+
}
|
675
1286
|
}
|
676
|
-
|
1287
|
+
}
|
677
1288
|
}
|
678
1289
|
|
679
|
-
public readonly ethereum = new EthereumProvider(this.requester);
|
1290
|
+
public readonly ethereum = new EthereumProvider(this, this.requester);
|
680
1291
|
}
|
681
|
-
|
682
1292
|
class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
683
1293
|
chainId: string | null = null;
|
684
1294
|
selectedAddress: string | null = null;
|
@@ -687,10 +1297,36 @@ class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
|
687
1297
|
isKeplr: boolean = true;
|
688
1298
|
isMetaMask: boolean = true;
|
689
1299
|
|
690
|
-
constructor(
|
1300
|
+
constructor(
|
1301
|
+
protected readonly keplr: Keplr,
|
1302
|
+
protected readonly requester: MessageRequester
|
1303
|
+
) {
|
691
1304
|
super();
|
692
1305
|
}
|
693
1306
|
|
1307
|
+
protected async protectedEnableAccess(): Promise<void> {
|
1308
|
+
return new Promise((resolve, reject) => {
|
1309
|
+
let f = false;
|
1310
|
+
|
1311
|
+
sendSimpleMessage(
|
1312
|
+
this.requester,
|
1313
|
+
BACKGROUND_PORT,
|
1314
|
+
"permission-interactive",
|
1315
|
+
"enable-access-for-evm",
|
1316
|
+
{}
|
1317
|
+
)
|
1318
|
+
.then(resolve)
|
1319
|
+
.catch(reject)
|
1320
|
+
.finally(() => (f = true));
|
1321
|
+
|
1322
|
+
setTimeout(() => {
|
1323
|
+
if (!f) {
|
1324
|
+
this.keplr.protectedTryOpenSidePanelIfEnabled();
|
1325
|
+
}
|
1326
|
+
}, 100);
|
1327
|
+
});
|
1328
|
+
}
|
1329
|
+
|
694
1330
|
isConnected(): boolean {
|
695
1331
|
return true;
|
696
1332
|
}
|
@@ -706,18 +1342,35 @@ class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
|
706
1342
|
providerId?: string;
|
707
1343
|
chainId?: string;
|
708
1344
|
}): Promise<T> {
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
1345
|
+
// XXX: 원래 enable을 미리하지 않아도 백그라운드에서 알아서 처리해주는 시스템이였는데...
|
1346
|
+
// side panel에서는 불가능하기 때문에 이젠 provider에서 permission도 관리해줘야한다...
|
1347
|
+
// request의 경우는 일종의 쿼리이기 때문에 언제 결과가 올지 알 수 없다. 그러므로 미리 권한 처리를 해야한다.
|
1348
|
+
await this.protectedEnableAccess();
|
1349
|
+
|
1350
|
+
return new Promise((resolve, reject) => {
|
1351
|
+
let f = false;
|
1352
|
+
sendSimpleMessage(
|
1353
|
+
this.requester,
|
1354
|
+
BACKGROUND_PORT,
|
1355
|
+
"keyring-ethereum",
|
1356
|
+
"request-json-rpc-to-evm",
|
1357
|
+
{
|
1358
|
+
method,
|
1359
|
+
params,
|
1360
|
+
providerId,
|
1361
|
+
chainId,
|
1362
|
+
}
|
1363
|
+
)
|
1364
|
+
.then(resolve)
|
1365
|
+
.catch(reject)
|
1366
|
+
.finally(() => (f = true));
|
1367
|
+
|
1368
|
+
setTimeout(() => {
|
1369
|
+
if (!f && sidePanelOpenNeededJSONRPCMethods.includes(method)) {
|
1370
|
+
this.keplr.protectedTryOpenSidePanelIfEnabled();
|
1371
|
+
}
|
1372
|
+
}, 100);
|
1373
|
+
});
|
721
1374
|
}
|
722
1375
|
|
723
1376
|
/**
|
@@ -725,26 +1378,21 @@ class EthereumProvider extends EventEmitter implements IEthereumProvider {
|
|
725
1378
|
*/
|
726
1379
|
|
727
1380
|
async enable(): Promise<string[]> {
|
728
|
-
return await
|
729
|
-
this.requester,
|
730
|
-
BACKGROUND_PORT,
|
731
|
-
"keyring-ethereum",
|
732
|
-
"request-json-rpc-to-evm",
|
733
|
-
{
|
734
|
-
method: "eth_requestAccounts",
|
735
|
-
}
|
736
|
-
);
|
1381
|
+
return await this.request({ method: "eth_requestAccounts" });
|
737
1382
|
}
|
738
1383
|
|
739
1384
|
async net_version(): Promise<string> {
|
740
|
-
return await
|
741
|
-
this.requester,
|
742
|
-
BACKGROUND_PORT,
|
743
|
-
"keyring-ethereum",
|
744
|
-
"request-json-rpc-to-evm",
|
745
|
-
{
|
746
|
-
method: "net_version",
|
747
|
-
}
|
748
|
-
);
|
1385
|
+
return await this.request({ method: "net_version" });
|
749
1386
|
}
|
750
1387
|
}
|
1388
|
+
|
1389
|
+
// IMPORTANT: 사이드 패널을 열어야하는 JSON-RPC 메소드들이 생길 때마다 여기에 추가해야한다.
|
1390
|
+
const sidePanelOpenNeededJSONRPCMethods = [
|
1391
|
+
"eth_sendTransaction",
|
1392
|
+
"personal_sign",
|
1393
|
+
"eth_signTypedData_v3",
|
1394
|
+
"eth_signTypedData_v4",
|
1395
|
+
"wallet_addEthereumChain",
|
1396
|
+
"wallet_switchEthereumChain",
|
1397
|
+
"wallet_watchAsset",
|
1398
|
+
];
|