@keplr-wallet/background 0.12.20 → 0.12.21-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 (43) hide show
  1. package/build/analytics/handler.js +5 -0
  2. package/build/analytics/handler.js.map +1 -1
  3. package/build/analytics/init.js +1 -0
  4. package/build/analytics/init.js.map +1 -1
  5. package/build/analytics/messages.d.ts +9 -0
  6. package/build/analytics/messages.js +23 -1
  7. package/build/analytics/messages.js.map +1 -1
  8. package/build/index.d.ts +2 -2
  9. package/build/index.js +4 -4
  10. package/build/index.js.map +1 -1
  11. package/build/keyring-cosmos/handler.js +9 -2
  12. package/build/keyring-cosmos/handler.js.map +1 -1
  13. package/build/keyring-cosmos/init.js +1 -0
  14. package/build/keyring-cosmos/init.js.map +1 -1
  15. package/build/keyring-cosmos/messages.d.ts +12 -0
  16. package/build/keyring-cosmos/messages.js +45 -1
  17. package/build/keyring-cosmos/messages.js.map +1 -1
  18. package/build/keyring-cosmos/service.d.ts +7 -2
  19. package/build/keyring-cosmos/service.js +72 -4
  20. package/build/keyring-cosmos/service.js.map +1 -1
  21. package/build/phishing-list/handler.js +4 -0
  22. package/build/phishing-list/handler.js.map +1 -1
  23. package/build/phishing-list/messages.d.ts +1 -0
  24. package/build/phishing-list/messages.js +3 -0
  25. package/build/phishing-list/messages.js.map +1 -1
  26. package/build/phishing-list/service.d.ts +2 -1
  27. package/build/phishing-list/service.js +2 -1
  28. package/build/phishing-list/service.js.map +1 -1
  29. package/build/phishing-list/service.spec.js +7 -7
  30. package/build/phishing-list/service.spec.js.map +1 -1
  31. package/package.json +13 -13
  32. package/src/analytics/handler.ts +16 -1
  33. package/src/analytics/init.ts +6 -1
  34. package/src/analytics/messages.ts +29 -0
  35. package/src/index.ts +16 -10
  36. package/src/keyring-cosmos/handler.ts +23 -1
  37. package/src/keyring-cosmos/init.ts +2 -0
  38. package/src/keyring-cosmos/messages.ts +57 -0
  39. package/src/keyring-cosmos/service.ts +107 -3
  40. package/src/phishing-list/handler.ts +5 -0
  41. package/src/phishing-list/messages.ts +4 -0
  42. package/src/phishing-list/service.spec.ts +63 -42
  43. package/src/phishing-list/service.ts +2 -1
@@ -255,6 +255,10 @@ export class PrivilegeCosmosSignAminoWithdrawRewardsMsg extends Message<AminoSig
255
255
  }
256
256
  }
257
257
 
258
+ override approveExternal(): boolean {
259
+ return true;
260
+ }
261
+
258
262
  route(): string {
259
263
  return ROUTE;
260
264
  }
@@ -264,6 +268,59 @@ export class PrivilegeCosmosSignAminoWithdrawRewardsMsg extends Message<AminoSig
264
268
  }
265
269
  }
266
270
 
271
+ export class PrivilegeCosmosSignAminoDelegateMsg extends Message<AminoSignResponse> {
272
+ public static type() {
273
+ return "PrivilegeCosmosSignAminoDelegate";
274
+ }
275
+
276
+ constructor(
277
+ public readonly chainId: string,
278
+ public readonly signer: string,
279
+ public readonly signDoc: StdSignDoc
280
+ ) {
281
+ super();
282
+ }
283
+
284
+ validateBasic(): void {
285
+ if (!this.chainId) {
286
+ throw new KeplrError("keyring", 270, "chain id not set");
287
+ }
288
+
289
+ if (!this.signer) {
290
+ throw new KeplrError("keyring", 230, "signer not set");
291
+ }
292
+
293
+ // Validate bech32 address.
294
+ Bech32Address.validate(this.signer);
295
+
296
+ // Check and validate the ADR-36 sign doc.
297
+ // ADR-36 sign doc doesn't have the chain id
298
+ if (!checkAndValidateADR36AminoSignDoc(this.signDoc)) {
299
+ if (this.signDoc.chain_id !== this.chainId) {
300
+ throw new KeplrError(
301
+ "keyring",
302
+ 234,
303
+ "Chain id in the message is not matched with the requested chain id"
304
+ );
305
+ }
306
+ } else {
307
+ throw new Error("Can't use ADR-36 sign doc");
308
+ }
309
+ }
310
+
311
+ override approveExternal(): boolean {
312
+ return true;
313
+ }
314
+
315
+ route(): string {
316
+ return ROUTE;
317
+ }
318
+
319
+ type(): string {
320
+ return PrivilegeCosmosSignAminoDelegateMsg.type();
321
+ }
322
+ }
323
+
267
324
  export class RequestCosmosSignAminoADR36Msg extends Message<StdSignature> {
268
325
  public static type() {
269
326
  return "request-cosmos-sign-amino-adr-36";
@@ -37,7 +37,8 @@ export class KeyRingCosmosService {
37
37
  protected readonly keyRingService: KeyRingService,
38
38
  protected readonly interactionService: InteractionService,
39
39
  protected readonly chainsUIService: ChainsUIService,
40
- protected readonly analyticsService: AnalyticsService
40
+ protected readonly analyticsService: AnalyticsService,
41
+ protected readonly msgPrivilegedOrigins: string[]
41
42
  ) {}
42
43
 
43
44
  async init() {
@@ -283,12 +284,18 @@ export class KeyRingCosmosService {
283
284
  }
284
285
 
285
286
  async privilegeSignAminoWithdrawRewards(
287
+ env: Env,
288
+ origin: string,
286
289
  chainId: string,
287
290
  signer: string,
288
291
  signDoc: StdSignDoc
289
292
  ) {
290
293
  // TODO: 이 기능은 ledger에서는 사용할 수 없고 어케 이 문제를 해결할지도 아직 명확하지 않음.
291
294
 
295
+ if (!env.isInternalMsg && !this.msgPrivilegedOrigins.includes(origin)) {
296
+ throw new Error("Permission Rejected");
297
+ }
298
+
292
299
  const chainInfo = this.chainsService.getChainInfoOrThrow(chainId);
293
300
 
294
301
  const vaultId = this.keyRingService.selectedVaultId;
@@ -358,8 +365,8 @@ export class KeyRingCosmosService {
358
365
 
359
366
  this.analyticsService.logEventIgnoreError("tx_signed", {
360
367
  chainId,
361
- isInternal: true,
362
- origin: new URL(browser.runtime.getURL("")).origin,
368
+ isInternal: env.isInternalMsg,
369
+ origin,
363
370
  signMode: "amino",
364
371
  privileged: "withdrawRewards",
365
372
  });
@@ -373,6 +380,103 @@ export class KeyRingCosmosService {
373
380
  }
374
381
  }
375
382
 
383
+ async privilegeSignAminoDelegate(
384
+ env: Env,
385
+ origin: string,
386
+ chainId: string,
387
+ signer: string,
388
+ signDoc: StdSignDoc
389
+ ) {
390
+ // TODO: 이 기능은 ledger에서는 사용할 수 없고 어케 이 문제를 해결할지도 아직 명확하지 않음.
391
+
392
+ if (!env.isInternalMsg && !this.msgPrivilegedOrigins.includes(origin)) {
393
+ throw new Error("Permission Rejected");
394
+ }
395
+
396
+ const chainInfo = this.chainsService.getChainInfoOrThrow(chainId);
397
+
398
+ const vaultId = this.keyRingService.selectedVaultId;
399
+
400
+ const isEthermintLike = KeyRingService.isEthermintLike(chainInfo);
401
+
402
+ const keyInfo = this.keyRingService.getKeyInfo(vaultId);
403
+ if (!keyInfo) {
404
+ throw new Error("Null key info");
405
+ }
406
+
407
+ if (isEthermintLike && keyInfo.type === "ledger") {
408
+ KeyRingCosmosService.throwErrorIfEthermintWithLedgerButNotSupported(
409
+ chainId
410
+ );
411
+ }
412
+
413
+ signDoc = {
414
+ ...signDoc,
415
+ memo: escapeHTML(signDoc.memo),
416
+ };
417
+
418
+ signDoc = trimAminoSignDoc(signDoc);
419
+ signDoc = sortObjectByKey(signDoc);
420
+
421
+ const key = await this.getKey(vaultId, chainId);
422
+ const bech32Prefix =
423
+ this.chainsService.getChainInfoOrThrow(chainId).bech32Config
424
+ .bech32PrefixAccAddr;
425
+ const bech32Address = new Bech32Address(key.address).toBech32(bech32Prefix);
426
+ if (signer !== bech32Address) {
427
+ throw new Error("Signer mismatched");
428
+ }
429
+
430
+ const isADR36SignDoc = checkAndValidateADR36AminoSignDoc(
431
+ signDoc,
432
+ bech32Prefix
433
+ );
434
+ if (isADR36SignDoc) {
435
+ throw new Error("Can't use ADR-36 sign doc");
436
+ }
437
+
438
+ if (!signDoc.msgs || signDoc.msgs.length === 0) {
439
+ throw new Error("No msgs");
440
+ }
441
+
442
+ for (const msg of signDoc.msgs) {
443
+ // Some chains modify types for obscure reasons. For now, treat it like this:
444
+ const i = msg.type.indexOf("/");
445
+ if (i < 0) {
446
+ throw new Error("Invalid msg type");
447
+ }
448
+ const action = msg.type.slice(i + 1);
449
+ if (action !== "MsgDelegate") {
450
+ throw new Error("Invalid msg type");
451
+ }
452
+ }
453
+
454
+ try {
455
+ const _sig = await this.keyRingService.sign(
456
+ chainId,
457
+ vaultId,
458
+ serializeSignDoc(signDoc),
459
+ isEthermintLike ? "keccak256" : "sha256"
460
+ );
461
+ const signature = new Uint8Array([..._sig.r, ..._sig.s]);
462
+
463
+ this.analyticsService.logEventIgnoreError("tx_signed", {
464
+ chainId,
465
+ isInternal: env.isInternalMsg,
466
+ origin,
467
+ signMode: "amino",
468
+ privileged: "delegate",
469
+ });
470
+
471
+ return {
472
+ signed: signDoc,
473
+ signature: encodeSecp256k1Signature(key.pubKey, signature),
474
+ };
475
+ } finally {
476
+ this.interactionService.dispatchEvent(APP_PORT, "request-sign-end", {});
477
+ }
478
+ }
479
+
376
480
  async signAminoADR36Selected(
377
481
  env: Env,
378
482
  origin: string,
@@ -40,6 +40,11 @@ const handleURLTempAllow: (
40
40
  service: PhishingListService
41
41
  ) => InternalHandler<URLTempAllowMsg> =
42
42
  (service: PhishingListService) => (_, msg) => {
43
+ const blocklistPageURL = new URL(msg.origin);
44
+ if (blocklistPageURL.origin !== new URL(service.blocklistPageURL).origin) {
45
+ throw new Error("Permission rejected");
46
+ }
47
+
43
48
  service.allowUrlTemp(msg.url);
44
49
  };
45
50
 
@@ -46,6 +46,10 @@ export class URLTempAllowMsg extends Message<void> {
46
46
  parseDomain(url.origin);
47
47
  }
48
48
 
49
+ override approveExternal(): boolean {
50
+ return true;
51
+ }
52
+
49
53
  route(): string {
50
54
  return ROUTE;
51
55
  }
@@ -266,12 +266,15 @@ describe("Test phishing list service", () => {
266
266
  };
267
267
 
268
268
  test("Test basic PhishingListService with valid cases", async () => {
269
- const service = new PhishingListService({
270
- blockListUrl: `http://127.0.0.1:${port}/list1`,
271
- fetchingIntervalMs: 3600,
272
- retryIntervalMs: 3600,
273
- allowTimeoutMs: 100,
274
- });
269
+ const service = new PhishingListService(
270
+ {
271
+ blockListUrl: `http://127.0.0.1:${port}/list1`,
272
+ fetchingIntervalMs: 3600,
273
+ retryIntervalMs: 3600,
274
+ allowTimeoutMs: 100,
275
+ },
276
+ "http://noop.com"
277
+ );
275
278
  eachService = service;
276
279
 
277
280
  service.init();
@@ -282,12 +285,15 @@ describe("Test phishing list service", () => {
282
285
  });
283
286
 
284
287
  test("Test basic PhishingListService with strange separators", async () => {
285
- const service = new PhishingListService({
286
- blockListUrl: `http://127.0.0.1:${port}/list2`,
287
- fetchingIntervalMs: 3600,
288
- retryIntervalMs: 3600,
289
- allowTimeoutMs: 100,
290
- });
288
+ const service = new PhishingListService(
289
+ {
290
+ blockListUrl: `http://127.0.0.1:${port}/list2`,
291
+ fetchingIntervalMs: 3600,
292
+ retryIntervalMs: 3600,
293
+ allowTimeoutMs: 100,
294
+ },
295
+ "http://noop.com"
296
+ );
291
297
  eachService = service;
292
298
 
293
299
  service.init();
@@ -298,12 +304,15 @@ describe("Test phishing list service", () => {
298
304
  });
299
305
 
300
306
  test("Test basic PhishingListService with strange cases", async () => {
301
- const service = new PhishingListService({
302
- blockListUrl: `http://127.0.0.1:${port}/list3`,
303
- fetchingIntervalMs: 3600,
304
- retryIntervalMs: 3600,
305
- allowTimeoutMs: 100,
306
- });
307
+ const service = new PhishingListService(
308
+ {
309
+ blockListUrl: `http://127.0.0.1:${port}/list3`,
310
+ fetchingIntervalMs: 3600,
311
+ retryIntervalMs: 3600,
312
+ allowTimeoutMs: 100,
313
+ },
314
+ "http://noop.com"
315
+ );
307
316
  eachService = service;
308
317
 
309
318
  service.init();
@@ -314,12 +323,15 @@ describe("Test phishing list service", () => {
314
323
  });
315
324
 
316
325
  test("Test basic PhishingListService fetching interval", async () => {
317
- const service = new PhishingListService({
318
- blockListUrl: `http://127.0.0.1:${port}/list3`,
319
- fetchingIntervalMs: 200,
320
- retryIntervalMs: 3600,
321
- allowTimeoutMs: 100,
322
- });
326
+ const service = new PhishingListService(
327
+ {
328
+ blockListUrl: `http://127.0.0.1:${port}/list3`,
329
+ fetchingIntervalMs: 200,
330
+ retryIntervalMs: 3600,
331
+ allowTimeoutMs: 100,
332
+ },
333
+ "http://noop.com"
334
+ );
323
335
  const spyFetch = jest.spyOn(service.urlFetcher, "fetch");
324
336
  eachService = service;
325
337
 
@@ -357,12 +369,15 @@ describe("Test phishing list service", () => {
357
369
  });
358
370
 
359
371
  test("Test basic PhishingListService fetching interval with retry interval", async () => {
360
- const service = new PhishingListService({
361
- blockListUrl: `http://127.0.0.1:${port}/test-retry`,
362
- fetchingIntervalMs: 200,
363
- retryIntervalMs: 100,
364
- allowTimeoutMs: 100,
365
- });
372
+ const service = new PhishingListService(
373
+ {
374
+ blockListUrl: `http://127.0.0.1:${port}/test-retry`,
375
+ fetchingIntervalMs: 200,
376
+ retryIntervalMs: 100,
377
+ allowTimeoutMs: 100,
378
+ },
379
+ "http://noop.com"
380
+ );
366
381
  const spyFetch = jest.spyOn(service.urlFetcher, "fetch");
367
382
  eachService = service;
368
383
 
@@ -433,12 +448,15 @@ describe("Test phishing list service", () => {
433
448
  });
434
449
 
435
450
  test("Test addUrlTemp allow blocked url", async () => {
436
- const service = new PhishingListService({
437
- blockListUrl: `http://127.0.0.1:${port}/list1`,
438
- fetchingIntervalMs: 200,
439
- retryIntervalMs: 100,
440
- allowTimeoutMs: 100,
441
- });
451
+ const service = new PhishingListService(
452
+ {
453
+ blockListUrl: `http://127.0.0.1:${port}/list1`,
454
+ fetchingIntervalMs: 200,
455
+ retryIntervalMs: 100,
456
+ allowTimeoutMs: 100,
457
+ },
458
+ "http://noop.com"
459
+ );
442
460
  eachService = service;
443
461
 
444
462
  service.init();
@@ -476,12 +494,15 @@ describe("Test phishing list service", () => {
476
494
  });
477
495
 
478
496
  test("Test subdomains", async () => {
479
- const service = new PhishingListService({
480
- blockListUrl: `http://127.0.0.1:${port}/subdomains`,
481
- fetchingIntervalMs: 200,
482
- retryIntervalMs: 100,
483
- allowTimeoutMs: 100,
484
- });
497
+ const service = new PhishingListService(
498
+ {
499
+ blockListUrl: `http://127.0.0.1:${port}/subdomains`,
500
+ fetchingIntervalMs: 200,
501
+ retryIntervalMs: 100,
502
+ allowTimeoutMs: 100,
503
+ },
504
+ "http://noop.com"
505
+ );
485
506
  eachService = service;
486
507
 
487
508
  service.init();
@@ -86,7 +86,8 @@ export class PhishingListService {
86
86
  readonly fetchingIntervalMs: number;
87
87
  readonly retryIntervalMs: number;
88
88
  readonly allowTimeoutMs: number;
89
- }
89
+ },
90
+ public readonly blocklistPageURL: string
90
91
  ) {
91
92
  this.urlFetcher = new IntervalFetcher(
92
93
  {