@metamask-previews/account-tree-controller 0.6.0-preview-b8fffa99 → 0.6.0-preview-ed2a2e6

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 (114) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/AccountTreeController.cjs +86 -25
  3. package/dist/AccountTreeController.cjs.map +1 -1
  4. package/dist/AccountTreeController.d.cts +3 -1
  5. package/dist/AccountTreeController.d.cts.map +1 -1
  6. package/dist/AccountTreeController.d.mts +3 -1
  7. package/dist/AccountTreeController.d.mts.map +1 -1
  8. package/dist/AccountTreeController.mjs +87 -26
  9. package/dist/AccountTreeController.mjs.map +1 -1
  10. package/dist/AccountTreeGroup.cjs +51 -35
  11. package/dist/AccountTreeGroup.cjs.map +1 -1
  12. package/dist/AccountTreeGroup.d.cts +15 -22
  13. package/dist/AccountTreeGroup.d.cts.map +1 -1
  14. package/dist/AccountTreeGroup.d.mts +15 -22
  15. package/dist/AccountTreeGroup.d.mts.map +1 -1
  16. package/dist/AccountTreeGroup.mjs +49 -33
  17. package/dist/AccountTreeGroup.mjs.map +1 -1
  18. package/dist/AccountTreeWallet.cjs +61 -27
  19. package/dist/AccountTreeWallet.cjs.map +1 -1
  20. package/dist/AccountTreeWallet.d.cts +24 -17
  21. package/dist/AccountTreeWallet.d.cts.map +1 -1
  22. package/dist/AccountTreeWallet.d.mts +24 -17
  23. package/dist/AccountTreeWallet.d.mts.map +1 -1
  24. package/dist/AccountTreeWallet.mjs +60 -26
  25. package/dist/AccountTreeWallet.mjs.map +1 -1
  26. package/dist/rules/entropy.cjs +57 -0
  27. package/dist/rules/entropy.cjs.map +1 -0
  28. package/dist/rules/entropy.d.cts +13 -0
  29. package/dist/rules/entropy.d.cts.map +1 -0
  30. package/dist/rules/entropy.d.mts +13 -0
  31. package/dist/rules/entropy.d.mts.map +1 -0
  32. package/dist/rules/entropy.mjs +53 -0
  33. package/dist/rules/entropy.mjs.map +1 -0
  34. package/dist/rules/index.cjs +4 -4
  35. package/dist/rules/index.cjs.map +1 -1
  36. package/dist/rules/index.d.cts +4 -4
  37. package/dist/rules/index.d.cts.map +1 -1
  38. package/dist/rules/index.d.mts +4 -4
  39. package/dist/rules/index.d.mts.map +1 -1
  40. package/dist/rules/index.mjs +4 -4
  41. package/dist/rules/index.mjs.map +1 -1
  42. package/dist/rules/keyring.cjs +80 -0
  43. package/dist/rules/keyring.cjs.map +1 -0
  44. package/dist/rules/keyring.d.cts +20 -0
  45. package/dist/rules/keyring.d.cts.map +1 -0
  46. package/dist/rules/keyring.d.mts +20 -0
  47. package/dist/rules/keyring.d.mts.map +1 -0
  48. package/dist/rules/keyring.mjs +75 -0
  49. package/dist/rules/keyring.mjs.map +1 -0
  50. package/dist/rules/rule.cjs +10 -0
  51. package/dist/rules/rule.cjs.map +1 -0
  52. package/dist/rules/rule.d.cts +42 -0
  53. package/dist/rules/rule.d.cts.map +1 -0
  54. package/dist/rules/rule.d.mts +42 -0
  55. package/dist/rules/rule.d.mts.map +1 -0
  56. package/dist/rules/rule.mjs +6 -0
  57. package/dist/rules/rule.mjs.map +1 -0
  58. package/dist/rules/snap.cjs +53 -0
  59. package/dist/rules/snap.cjs.map +1 -0
  60. package/dist/rules/snap.d.cts +23 -0
  61. package/dist/rules/snap.d.cts.map +1 -0
  62. package/dist/rules/snap.d.mts +23 -0
  63. package/dist/rules/snap.d.mts.map +1 -0
  64. package/dist/rules/snap.mjs +49 -0
  65. package/dist/rules/snap.mjs.map +1 -0
  66. package/dist/types.cjs +3 -0
  67. package/dist/types.cjs.map +1 -0
  68. package/dist/types.d.cts +15 -0
  69. package/dist/types.d.cts.map +1 -0
  70. package/dist/types.d.mts +15 -0
  71. package/dist/types.d.mts.map +1 -0
  72. package/dist/types.mjs +2 -0
  73. package/dist/types.mjs.map +1 -0
  74. package/package.json +3 -3
  75. package/dist/rules/EntropySourceWalletRule.cjs +0 -100
  76. package/dist/rules/EntropySourceWalletRule.cjs.map +0 -1
  77. package/dist/rules/EntropySourceWalletRule.d.cts +0 -19
  78. package/dist/rules/EntropySourceWalletRule.d.cts.map +0 -1
  79. package/dist/rules/EntropySourceWalletRule.d.mts +0 -19
  80. package/dist/rules/EntropySourceWalletRule.d.mts.map +0 -1
  81. package/dist/rules/EntropySourceWalletRule.mjs +0 -95
  82. package/dist/rules/EntropySourceWalletRule.mjs.map +0 -1
  83. package/dist/rules/KeyringWalletRule.cjs +0 -99
  84. package/dist/rules/KeyringWalletRule.cjs.map +0 -1
  85. package/dist/rules/KeyringWalletRule.d.cts +0 -18
  86. package/dist/rules/KeyringWalletRule.d.cts.map +0 -1
  87. package/dist/rules/KeyringWalletRule.d.mts +0 -18
  88. package/dist/rules/KeyringWalletRule.d.mts.map +0 -1
  89. package/dist/rules/KeyringWalletRule.mjs +0 -94
  90. package/dist/rules/KeyringWalletRule.mjs.map +0 -1
  91. package/dist/rules/SnapWalletRule.cjs +0 -70
  92. package/dist/rules/SnapWalletRule.cjs.map +0 -1
  93. package/dist/rules/SnapWalletRule.d.cts +0 -10
  94. package/dist/rules/SnapWalletRule.d.cts.map +0 -1
  95. package/dist/rules/SnapWalletRule.d.mts +0 -10
  96. package/dist/rules/SnapWalletRule.d.mts.map +0 -1
  97. package/dist/rules/SnapWalletRule.mjs +0 -66
  98. package/dist/rules/SnapWalletRule.mjs.map +0 -1
  99. package/dist/rules/WalletRule.cjs +0 -13
  100. package/dist/rules/WalletRule.cjs.map +0 -1
  101. package/dist/rules/WalletRule.d.cts +0 -37
  102. package/dist/rules/WalletRule.d.cts.map +0 -1
  103. package/dist/rules/WalletRule.d.mts +0 -37
  104. package/dist/rules/WalletRule.d.mts.map +0 -1
  105. package/dist/rules/WalletRule.mjs +0 -9
  106. package/dist/rules/WalletRule.mjs.map +0 -1
  107. package/dist/rules/utils.cjs +0 -15
  108. package/dist/rules/utils.cjs.map +0 -1
  109. package/dist/rules/utils.d.cts +0 -11
  110. package/dist/rules/utils.d.cts.map +0 -1
  111. package/dist/rules/utils.d.mts +0 -11
  112. package/dist/rules/utils.d.mts.map +0 -1
  113. package/dist/rules/utils.mjs +0 -11
  114. package/dist/rules/utils.mjs.map +0 -1
@@ -0,0 +1,75 @@
1
+ import { AccountWalletCategory, toAccountGroupId, toAccountWalletId } from "@metamask/account-api";
2
+ import { KeyringTypes } from "@metamask/keyring-controller";
3
+ import { Rule } from "./rule.mjs";
4
+ /**
5
+ * Get wallet name from a keyring type.
6
+ *
7
+ * @param type - Keyring's type.
8
+ * @returns Wallet name.
9
+ */
10
+ export function getAccountWalletNameFromKeyringType(type) {
11
+ switch (type) {
12
+ case KeyringTypes.simple: {
13
+ return 'Imported accounts';
14
+ }
15
+ case KeyringTypes.trezor: {
16
+ return 'Trezor';
17
+ }
18
+ case KeyringTypes.oneKey: {
19
+ return 'OneKey';
20
+ }
21
+ case KeyringTypes.ledger: {
22
+ return 'Ledger';
23
+ }
24
+ case KeyringTypes.lattice: {
25
+ return 'Lattice';
26
+ }
27
+ case KeyringTypes.qr: {
28
+ return 'QR';
29
+ }
30
+ // Those keyrings should never really be used in such context since they
31
+ // should be used by other grouping rules.
32
+ case KeyringTypes.hd: {
33
+ return 'HD Wallet';
34
+ }
35
+ case KeyringTypes.snap: {
36
+ return 'Snap Wallet';
37
+ }
38
+ // ------------------------------------------------------------------------
39
+ default: {
40
+ return 'Unknown';
41
+ }
42
+ }
43
+ }
44
+ export class KeyringRule extends Rule {
45
+ constructor() {
46
+ super(...arguments);
47
+ this.category = AccountWalletCategory.Keyring;
48
+ }
49
+ match(account) {
50
+ // We assume that `type` is really a `KeyringTypes`.
51
+ const type = account.metadata.keyring.type;
52
+ const walletId = toAccountWalletId(this.category, type);
53
+ const groupId = toAccountGroupId(walletId, account.address);
54
+ // This rule cannot fail.
55
+ return {
56
+ walletId,
57
+ groupId,
58
+ };
59
+ }
60
+ getDefaultAccountWalletName(wallet) {
61
+ // Precondition: This method is invoked only if there was a match for
62
+ // this rule.
63
+ const account = wallet.getAnyAccount();
64
+ return getAccountWalletNameFromKeyringType(account.metadata.keyring.type);
65
+ }
66
+ getDefaultAccountGroupName(group) {
67
+ // Precondition: This method is invoked only if there was a match for
68
+ // this rule. Also, each of those account groups should contain
69
+ // only 1 account.
70
+ const account = group.getOnlyAccount();
71
+ // We only have 1 account for this kind of rule.
72
+ return account.metadata.name;
73
+ }
74
+ }
75
+ //# sourceMappingURL=keyring.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyring.mjs","sourceRoot":"","sources":["../../src/rules/keyring.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EAClB,8BAA8B;AAC/B,OAAO,EAAE,YAAY,EAAE,qCAAqC;AAI5D,OAAO,EAAE,IAAI,EAAE,mBAAe;AAG9B;;;;;GAKG;AACH,MAAM,UAAU,mCAAmC,CAAC,IAAkB;IACpE,QAAQ,IAAI,EAAE;QACZ,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,mBAAmB,CAAC;SAC5B;QACD,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,QAAQ,CAAC;SACjB;QACD,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,QAAQ,CAAC;SACjB;QACD,KAAK,YAAY,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,QAAQ,CAAC;SACjB;QACD,KAAK,YAAY,CAAC,OAAO,CAAC,CAAC;YACzB,OAAO,SAAS,CAAC;SAClB;QACD,KAAK,YAAY,CAAC,EAAE,CAAC,CAAC;YACpB,OAAO,IAAI,CAAC;SACb;QACD,wEAAwE;QACxE,0CAA0C;QAC1C,KAAK,YAAY,CAAC,EAAE,CAAC,CAAC;YACpB,OAAO,WAAW,CAAC;SACpB;QACD,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO,aAAa,CAAC;SACtB;QACD,2EAA2E;QAC3E,OAAO,CAAC,CAAC;YACP,OAAO,SAAS,CAAC;SAClB;KACF;AACH,CAAC;AAED,MAAM,OAAO,WAAY,SAAQ,IAAI;IAArC;;QACW,aAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC;IAmCpD,CAAC;IAjCC,KAAK,CAAC,OAAwB;QAC5B,oDAAoD;QACpD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAoB,CAAC;QAE3D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAE5D,yBAAyB;QACzB,OAAO;YACL,QAAQ;YACR,OAAO;SACR,CAAC;IACJ,CAAC;IAED,2BAA2B,CAAC,MAAyB;QACnD,qEAAqE;QACrE,aAAa;QACb,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;QAEvC,OAAO,mCAAmC,CACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAoB,CAC9C,CAAC;IACJ,CAAC;IAED,0BAA0B,CAAC,KAAuB;QAChD,qEAAqE;QACrE,+DAA+D;QAC/D,kBAAkB;QAClB,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QAEvC,gDAAgD;QAChD,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC/B,CAAC;CACF","sourcesContent":["import {\n AccountWalletCategory,\n toAccountGroupId,\n toAccountWalletId,\n} from '@metamask/account-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { AccountContext } from 'src/types';\n\nimport { Rule } from './rule';\nimport type { AccountTreeGroup, AccountTreeWallet } from '..';\n\n/**\n * Get wallet name from a keyring type.\n *\n * @param type - Keyring's type.\n * @returns Wallet name.\n */\nexport function getAccountWalletNameFromKeyringType(type: KeyringTypes) {\n switch (type) {\n case KeyringTypes.simple: {\n return 'Imported accounts';\n }\n case KeyringTypes.trezor: {\n return 'Trezor';\n }\n case KeyringTypes.oneKey: {\n return 'OneKey';\n }\n case KeyringTypes.ledger: {\n return 'Ledger';\n }\n case KeyringTypes.lattice: {\n return 'Lattice';\n }\n case KeyringTypes.qr: {\n return 'QR';\n }\n // Those keyrings should never really be used in such context since they\n // should be used by other grouping rules.\n case KeyringTypes.hd: {\n return 'HD Wallet';\n }\n case KeyringTypes.snap: {\n return 'Snap Wallet';\n }\n // ------------------------------------------------------------------------\n default: {\n return 'Unknown';\n }\n }\n}\n\nexport class KeyringRule extends Rule {\n readonly category = AccountWalletCategory.Keyring;\n\n match(account: InternalAccount): AccountContext | undefined {\n // We assume that `type` is really a `KeyringTypes`.\n const type = account.metadata.keyring.type as KeyringTypes;\n\n const walletId = toAccountWalletId(this.category, type);\n const groupId = toAccountGroupId(walletId, account.address);\n\n // This rule cannot fail.\n return {\n walletId,\n groupId,\n };\n }\n\n getDefaultAccountWalletName(wallet: AccountTreeWallet): string {\n // Precondition: This method is invoked only if there was a match for\n // this rule.\n const account = wallet.getAnyAccount();\n\n return getAccountWalletNameFromKeyringType(\n account.metadata.keyring.type as KeyringTypes,\n );\n }\n\n getDefaultAccountGroupName(group: AccountTreeGroup): string {\n // Precondition: This method is invoked only if there was a match for\n // this rule. Also, each of those account groups should contain\n // only 1 account.\n const account = group.getOnlyAccount();\n\n // We only have 1 account for this kind of rule.\n return account.metadata.name;\n }\n}\n"]}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Rule = void 0;
4
+ class Rule {
5
+ constructor(messenger) {
6
+ this.messenger = messenger;
7
+ }
8
+ }
9
+ exports.Rule = Rule;
10
+ //# sourceMappingURL=rule.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.cjs","sourceRoot":"","sources":["../../src/rules/rule.ts"],"names":[],"mappings":";;;AAOA,MAAsB,IAAI;IAKxB,YAAY,SAAyC;QACnD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CAmCF;AA1CD,oBA0CC","sourcesContent":["import type { AccountWalletCategory } from '@metamask/account-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountTreeGroup, AccountTreeWallet } from '..';\nimport type { AccountTreeControllerMessenger } from '../AccountTreeController';\nimport type { AccountContext } from '../types';\n\nexport abstract class Rule {\n abstract readonly category: AccountWalletCategory;\n\n protected readonly messenger: AccountTreeControllerMessenger;\n\n constructor(messenger: AccountTreeControllerMessenger) {\n this.messenger = messenger;\n }\n\n /**\n * Applies the rule and check if the account matches.\n *\n * If the account matches, then the rule will return a {@link RuleMatch} which means\n * this account needs to be grouped within a wallet associated with this rule.\n *\n * If a wallet already exists for this account (based on {@link RuleMatch}) then\n * the account will be added to that wallet instance into its proper group (different for\n * every wallets).\n *\n * @param account - The account to match.\n * @returns A {@link RuleMatch} if this account is part of that rule/wallet, returns\n * `undefined` otherwise.\n */\n abstract match(account: InternalAccount): AccountContext | undefined;\n\n /**\n * Gets default name for a wallet.\n *\n * @param wallet - Wallet associated to this rule.\n * @param context - Rule context.\n * @returns The default name for that wallet.\n */\n abstract getDefaultAccountWalletName(wallet: AccountTreeWallet): string;\n\n /**\n * Gets default name for a group.\n *\n * @param group - Group associated to this rule.\n * @param context - Rule context.\n * @returns The default name for that group.\n */\n abstract getDefaultAccountGroupName(group: AccountTreeGroup): string;\n}\n"]}
@@ -0,0 +1,42 @@
1
+ import type { AccountWalletCategory } from "@metamask/account-api";
2
+ import type { InternalAccount } from "@metamask/keyring-internal-api";
3
+ import type { AccountTreeGroup, AccountTreeWallet } from "../index.cjs";
4
+ import type { AccountTreeControllerMessenger } from "../AccountTreeController.cjs";
5
+ import type { AccountContext } from "../types.cjs";
6
+ export declare abstract class Rule {
7
+ abstract readonly category: AccountWalletCategory;
8
+ protected readonly messenger: AccountTreeControllerMessenger;
9
+ constructor(messenger: AccountTreeControllerMessenger);
10
+ /**
11
+ * Applies the rule and check if the account matches.
12
+ *
13
+ * If the account matches, then the rule will return a {@link RuleMatch} which means
14
+ * this account needs to be grouped within a wallet associated with this rule.
15
+ *
16
+ * If a wallet already exists for this account (based on {@link RuleMatch}) then
17
+ * the account will be added to that wallet instance into its proper group (different for
18
+ * every wallets).
19
+ *
20
+ * @param account - The account to match.
21
+ * @returns A {@link RuleMatch} if this account is part of that rule/wallet, returns
22
+ * `undefined` otherwise.
23
+ */
24
+ abstract match(account: InternalAccount): AccountContext | undefined;
25
+ /**
26
+ * Gets default name for a wallet.
27
+ *
28
+ * @param wallet - Wallet associated to this rule.
29
+ * @param context - Rule context.
30
+ * @returns The default name for that wallet.
31
+ */
32
+ abstract getDefaultAccountWalletName(wallet: AccountTreeWallet): string;
33
+ /**
34
+ * Gets default name for a group.
35
+ *
36
+ * @param group - Group associated to this rule.
37
+ * @param context - Rule context.
38
+ * @returns The default name for that group.
39
+ */
40
+ abstract getDefaultAccountGroupName(group: AccountTreeGroup): string;
41
+ }
42
+ //# sourceMappingURL=rule.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.d.cts","sourceRoot":"","sources":["../../src/rules/rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,8BAA8B;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,qBAAW;AAC9D,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAiB;AAE/C,8BAAsB,IAAI;IACxB,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IAElD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,8BAA8B,CAAC;gBAEjD,SAAS,EAAE,8BAA8B;IAIrD;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,SAAS;IAEpE;;;;;;OAMG;IACH,QAAQ,CAAC,2BAA2B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;IAEvE;;;;;;OAMG;IACH,QAAQ,CAAC,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM;CACrE"}
@@ -0,0 +1,42 @@
1
+ import type { AccountWalletCategory } from "@metamask/account-api";
2
+ import type { InternalAccount } from "@metamask/keyring-internal-api";
3
+ import type { AccountTreeGroup, AccountTreeWallet } from "../index.mjs";
4
+ import type { AccountTreeControllerMessenger } from "../AccountTreeController.mjs";
5
+ import type { AccountContext } from "../types.mjs";
6
+ export declare abstract class Rule {
7
+ abstract readonly category: AccountWalletCategory;
8
+ protected readonly messenger: AccountTreeControllerMessenger;
9
+ constructor(messenger: AccountTreeControllerMessenger);
10
+ /**
11
+ * Applies the rule and check if the account matches.
12
+ *
13
+ * If the account matches, then the rule will return a {@link RuleMatch} which means
14
+ * this account needs to be grouped within a wallet associated with this rule.
15
+ *
16
+ * If a wallet already exists for this account (based on {@link RuleMatch}) then
17
+ * the account will be added to that wallet instance into its proper group (different for
18
+ * every wallets).
19
+ *
20
+ * @param account - The account to match.
21
+ * @returns A {@link RuleMatch} if this account is part of that rule/wallet, returns
22
+ * `undefined` otherwise.
23
+ */
24
+ abstract match(account: InternalAccount): AccountContext | undefined;
25
+ /**
26
+ * Gets default name for a wallet.
27
+ *
28
+ * @param wallet - Wallet associated to this rule.
29
+ * @param context - Rule context.
30
+ * @returns The default name for that wallet.
31
+ */
32
+ abstract getDefaultAccountWalletName(wallet: AccountTreeWallet): string;
33
+ /**
34
+ * Gets default name for a group.
35
+ *
36
+ * @param group - Group associated to this rule.
37
+ * @param context - Rule context.
38
+ * @returns The default name for that group.
39
+ */
40
+ abstract getDefaultAccountGroupName(group: AccountTreeGroup): string;
41
+ }
42
+ //# sourceMappingURL=rule.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.d.mts","sourceRoot":"","sources":["../../src/rules/rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,8BAA8B;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,qBAAW;AAC9D,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAiB;AAE/C,8BAAsB,IAAI;IACxB,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IAElD,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,8BAA8B,CAAC;gBAEjD,SAAS,EAAE,8BAA8B;IAIrD;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,SAAS;IAEpE;;;;;;OAMG;IACH,QAAQ,CAAC,2BAA2B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;IAEvE;;;;;;OAMG;IACH,QAAQ,CAAC,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM;CACrE"}
@@ -0,0 +1,6 @@
1
+ export class Rule {
2
+ constructor(messenger) {
3
+ this.messenger = messenger;
4
+ }
5
+ }
6
+ //# sourceMappingURL=rule.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.mjs","sourceRoot":"","sources":["../../src/rules/rule.ts"],"names":[],"mappings":"AAOA,MAAM,OAAgB,IAAI;IAKxB,YAAY,SAAyC;QACnD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CAmCF","sourcesContent":["import type { AccountWalletCategory } from '@metamask/account-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountTreeGroup, AccountTreeWallet } from '..';\nimport type { AccountTreeControllerMessenger } from '../AccountTreeController';\nimport type { AccountContext } from '../types';\n\nexport abstract class Rule {\n abstract readonly category: AccountWalletCategory;\n\n protected readonly messenger: AccountTreeControllerMessenger;\n\n constructor(messenger: AccountTreeControllerMessenger) {\n this.messenger = messenger;\n }\n\n /**\n * Applies the rule and check if the account matches.\n *\n * If the account matches, then the rule will return a {@link RuleMatch} which means\n * this account needs to be grouped within a wallet associated with this rule.\n *\n * If a wallet already exists for this account (based on {@link RuleMatch}) then\n * the account will be added to that wallet instance into its proper group (different for\n * every wallets).\n *\n * @param account - The account to match.\n * @returns A {@link RuleMatch} if this account is part of that rule/wallet, returns\n * `undefined` otherwise.\n */\n abstract match(account: InternalAccount): AccountContext | undefined;\n\n /**\n * Gets default name for a wallet.\n *\n * @param wallet - Wallet associated to this rule.\n * @param context - Rule context.\n * @returns The default name for that wallet.\n */\n abstract getDefaultAccountWalletName(wallet: AccountTreeWallet): string;\n\n /**\n * Gets default name for a group.\n *\n * @param group - Group associated to this rule.\n * @param context - Rule context.\n * @returns The default name for that group.\n */\n abstract getDefaultAccountGroupName(group: AccountTreeGroup): string;\n}\n"]}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SnapRule = void 0;
4
+ const account_api_1 = require("@metamask/account-api");
5
+ const keyring_controller_1 = require("@metamask/keyring-controller");
6
+ const snaps_utils_1 = require("@metamask/snaps-utils");
7
+ const rule_1 = require("./rule.cjs");
8
+ class SnapRule extends rule_1.Rule {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.category = account_api_1.AccountWalletCategory.Snap;
12
+ }
13
+ isSnapAccount(account) {
14
+ return (account.metadata.keyring.type === keyring_controller_1.KeyringTypes.snap &&
15
+ account.metadata.snap !== undefined &&
16
+ account.metadata.snap.enabled);
17
+ }
18
+ match(account) {
19
+ if (!this.isSnapAccount(account)) {
20
+ return undefined;
21
+ }
22
+ const { id: snapId } = account.metadata.snap;
23
+ const walletId = (0, account_api_1.toAccountWalletId)(this.category, snapId);
24
+ const groupId = (0, account_api_1.toAccountGroupId)(walletId, account.address);
25
+ return {
26
+ walletId,
27
+ groupId,
28
+ };
29
+ }
30
+ getDefaultAccountWalletName(wallet) {
31
+ // Precondition: This method is invoked only if there was a match for
32
+ // a Snap account, so we can type-cast here.
33
+ const account = wallet.getAnyAccount();
34
+ const { id: snapId } = account.metadata.snap;
35
+ const snap = this.messenger.call('SnapController:get', snapId);
36
+ const snapName = snap
37
+ ? // TODO: Handle localization here, but that's a "client thing", so we don't have a `core` controller
38
+ // to refer to.
39
+ snap.manifest.proposedName
40
+ : (0, snaps_utils_1.stripSnapPrefix)(snapId);
41
+ return snapName;
42
+ }
43
+ getDefaultAccountGroupName(group) {
44
+ // Precondition: This method is invoked only if there was a match for
45
+ // a Snap account, so we can type-cast here. Also, each of those
46
+ // account groups should contain only 1 account.
47
+ const account = group.getOnlyAccount();
48
+ // We only have 1 account for this kind of rule.
49
+ return account.metadata.name;
50
+ }
51
+ }
52
+ exports.SnapRule = SnapRule;
53
+ //# sourceMappingURL=snap.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap.cjs","sourceRoot":"","sources":["../../src/rules/snap.ts"],"names":[],"mappings":";;;AAAA,uDAI+B;AAC/B,qEAA4D;AAG5D,uDAAwD;AAKxD,qCAA8B;AAU9B,MAAa,QAAS,SAAQ,WAAI;IAAlC;;QACW,aAAQ,GAAG,mCAAqB,CAAC,IAAI,CAAC;IAqDjD,CAAC;IAnDC,aAAa,CACX,OAAwB;QAExB,OAAO,CACL,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAM,iCAAY,CAAC,IAAe;YAC/D,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS;YACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAC9B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAwB;QAC5B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;YAChC,OAAO,SAAS,CAAC;SAClB;QAED,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAE7C,MAAM,QAAQ,GAAG,IAAA,+BAAiB,EAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAA,8BAAgB,EAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAE5D,OAAO;YACL,QAAQ;YACR,OAAO;SACR,CAAC;IACJ,CAAC;IAED,2BAA2B,CAAC,MAAyB;QACnD,qEAAqE;QACrE,4CAA4C;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,EAAkC,CAAC;QAEvE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,IAAI;YACnB,CAAC,CAAC,oGAAoG;gBACpG,eAAe;gBACf,IAAI,CAAC,QAAQ,CAAC,YAAY;YAC5B,CAAC,CAAC,IAAA,6BAAe,EAAC,MAAM,CAAC,CAAC;QAE5B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0BAA0B,CAAC,KAAuB;QAChD,qEAAqE;QACrE,gEAAgE;QAChE,gDAAgD;QAChD,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc,EAAkC,CAAC;QAEvE,gDAAgD;QAChD,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC/B,CAAC;CACF;AAtDD,4BAsDC","sourcesContent":["import {\n AccountWalletCategory,\n toAccountGroupId,\n toAccountWalletId,\n} from '@metamask/account-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { stripSnapPrefix } from '@metamask/snaps-utils';\nimport type { AccountTreeGroup } from 'src/AccountTreeGroup';\nimport type { AccountTreeWallet } from 'src/AccountTreeWallet';\nimport type { AccountContext } from 'src/types';\n\nimport { Rule } from './rule';\n\ntype SnapAccount<Account extends InternalAccount> = Account & {\n metadata: Account['metadata'] & {\n snap: {\n id: SnapId;\n };\n };\n};\n\nexport class SnapRule extends Rule {\n readonly category = AccountWalletCategory.Snap;\n\n isSnapAccount(\n account: InternalAccount,\n ): account is SnapAccount<InternalAccount> {\n return (\n account.metadata.keyring.type === (KeyringTypes.snap as string) &&\n account.metadata.snap !== undefined &&\n account.metadata.snap.enabled\n );\n }\n\n match(account: InternalAccount): AccountContext | undefined {\n if (!this.isSnapAccount(account)) {\n return undefined;\n }\n\n const { id: snapId } = account.metadata.snap;\n\n const walletId = toAccountWalletId(this.category, snapId);\n const groupId = toAccountGroupId(walletId, account.address);\n\n return {\n walletId,\n groupId,\n };\n }\n\n getDefaultAccountWalletName(wallet: AccountTreeWallet): string {\n // Precondition: This method is invoked only if there was a match for\n // a Snap account, so we can type-cast here.\n const account = wallet.getAnyAccount() as SnapAccount<InternalAccount>;\n\n const { id: snapId } = account.metadata.snap;\n const snap = this.messenger.call('SnapController:get', snapId);\n const snapName = snap\n ? // TODO: Handle localization here, but that's a \"client thing\", so we don't have a `core` controller\n // to refer to.\n snap.manifest.proposedName\n : stripSnapPrefix(snapId);\n\n return snapName;\n }\n\n getDefaultAccountGroupName(group: AccountTreeGroup): string {\n // Precondition: This method is invoked only if there was a match for\n // a Snap account, so we can type-cast here. Also, each of those\n // account groups should contain only 1 account.\n const account = group.getOnlyAccount() as SnapAccount<InternalAccount>;\n\n // We only have 1 account for this kind of rule.\n return account.metadata.name;\n }\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { AccountWalletCategory } from "@metamask/account-api";
2
+ import type { InternalAccount } from "@metamask/keyring-internal-api";
3
+ import type { SnapId } from "@metamask/snaps-sdk";
4
+ import type { AccountTreeGroup } from "src/AccountTreeGroup";
5
+ import type { AccountTreeWallet } from "src/AccountTreeWallet";
6
+ import type { AccountContext } from "src/types";
7
+ import { Rule } from "./rule.cjs";
8
+ type SnapAccount<Account extends InternalAccount> = Account & {
9
+ metadata: Account['metadata'] & {
10
+ snap: {
11
+ id: SnapId;
12
+ };
13
+ };
14
+ };
15
+ export declare class SnapRule extends Rule {
16
+ readonly category = AccountWalletCategory.Snap;
17
+ isSnapAccount(account: InternalAccount): account is SnapAccount<InternalAccount>;
18
+ match(account: InternalAccount): AccountContext | undefined;
19
+ getDefaultAccountWalletName(wallet: AccountTreeWallet): string;
20
+ getDefaultAccountGroupName(group: AccountTreeGroup): string;
21
+ }
22
+ export {};
23
+ //# sourceMappingURL=snap.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap.d.cts","sourceRoot":"","sources":["../../src/rules/snap.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAGtB,8BAA8B;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,6BAA6B;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,8BAA8B;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB;AAEhD,OAAO,EAAE,IAAI,EAAE,mBAAe;AAE9B,KAAK,WAAW,CAAC,OAAO,SAAS,eAAe,IAAI,OAAO,GAAG;IAC5D,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG;QAC9B,IAAI,EAAE;YACJ,EAAE,EAAE,MAAM,CAAC;SACZ,CAAC;KACH,CAAC;CACH,CAAC;AAEF,qBAAa,QAAS,SAAQ,IAAI;IAChC,QAAQ,CAAC,QAAQ,8BAA8B;IAE/C,aAAa,CACX,OAAO,EAAE,eAAe,GACvB,OAAO,IAAI,WAAW,CAAC,eAAe,CAAC;IAQ1C,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,SAAS;IAgB3D,2BAA2B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;IAgB9D,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM;CAS5D"}
@@ -0,0 +1,23 @@
1
+ import { AccountWalletCategory } from "@metamask/account-api";
2
+ import type { InternalAccount } from "@metamask/keyring-internal-api";
3
+ import type { SnapId } from "@metamask/snaps-sdk";
4
+ import type { AccountTreeGroup } from "src/AccountTreeGroup";
5
+ import type { AccountTreeWallet } from "src/AccountTreeWallet";
6
+ import type { AccountContext } from "src/types";
7
+ import { Rule } from "./rule.mjs";
8
+ type SnapAccount<Account extends InternalAccount> = Account & {
9
+ metadata: Account['metadata'] & {
10
+ snap: {
11
+ id: SnapId;
12
+ };
13
+ };
14
+ };
15
+ export declare class SnapRule extends Rule {
16
+ readonly category = AccountWalletCategory.Snap;
17
+ isSnapAccount(account: InternalAccount): account is SnapAccount<InternalAccount>;
18
+ match(account: InternalAccount): AccountContext | undefined;
19
+ getDefaultAccountWalletName(wallet: AccountTreeWallet): string;
20
+ getDefaultAccountGroupName(group: AccountTreeGroup): string;
21
+ }
22
+ export {};
23
+ //# sourceMappingURL=snap.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap.d.mts","sourceRoot":"","sources":["../../src/rules/snap.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAGtB,8BAA8B;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,6BAA6B;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,8BAA8B;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB;AAEhD,OAAO,EAAE,IAAI,EAAE,mBAAe;AAE9B,KAAK,WAAW,CAAC,OAAO,SAAS,eAAe,IAAI,OAAO,GAAG;IAC5D,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG;QAC9B,IAAI,EAAE;YACJ,EAAE,EAAE,MAAM,CAAC;SACZ,CAAC;KACH,CAAC;CACH,CAAC;AAEF,qBAAa,QAAS,SAAQ,IAAI;IAChC,QAAQ,CAAC,QAAQ,8BAA8B;IAE/C,aAAa,CACX,OAAO,EAAE,eAAe,GACvB,OAAO,IAAI,WAAW,CAAC,eAAe,CAAC;IAQ1C,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,SAAS;IAgB3D,2BAA2B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;IAgB9D,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM;CAS5D"}
@@ -0,0 +1,49 @@
1
+ import { AccountWalletCategory, toAccountGroupId, toAccountWalletId } from "@metamask/account-api";
2
+ import { KeyringTypes } from "@metamask/keyring-controller";
3
+ import { stripSnapPrefix } from "@metamask/snaps-utils";
4
+ import { Rule } from "./rule.mjs";
5
+ export class SnapRule extends Rule {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.category = AccountWalletCategory.Snap;
9
+ }
10
+ isSnapAccount(account) {
11
+ return (account.metadata.keyring.type === KeyringTypes.snap &&
12
+ account.metadata.snap !== undefined &&
13
+ account.metadata.snap.enabled);
14
+ }
15
+ match(account) {
16
+ if (!this.isSnapAccount(account)) {
17
+ return undefined;
18
+ }
19
+ const { id: snapId } = account.metadata.snap;
20
+ const walletId = toAccountWalletId(this.category, snapId);
21
+ const groupId = toAccountGroupId(walletId, account.address);
22
+ return {
23
+ walletId,
24
+ groupId,
25
+ };
26
+ }
27
+ getDefaultAccountWalletName(wallet) {
28
+ // Precondition: This method is invoked only if there was a match for
29
+ // a Snap account, so we can type-cast here.
30
+ const account = wallet.getAnyAccount();
31
+ const { id: snapId } = account.metadata.snap;
32
+ const snap = this.messenger.call('SnapController:get', snapId);
33
+ const snapName = snap
34
+ ? // TODO: Handle localization here, but that's a "client thing", so we don't have a `core` controller
35
+ // to refer to.
36
+ snap.manifest.proposedName
37
+ : stripSnapPrefix(snapId);
38
+ return snapName;
39
+ }
40
+ getDefaultAccountGroupName(group) {
41
+ // Precondition: This method is invoked only if there was a match for
42
+ // a Snap account, so we can type-cast here. Also, each of those
43
+ // account groups should contain only 1 account.
44
+ const account = group.getOnlyAccount();
45
+ // We only have 1 account for this kind of rule.
46
+ return account.metadata.name;
47
+ }
48
+ }
49
+ //# sourceMappingURL=snap.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap.mjs","sourceRoot":"","sources":["../../src/rules/snap.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EAClB,8BAA8B;AAC/B,OAAO,EAAE,YAAY,EAAE,qCAAqC;AAG5D,OAAO,EAAE,eAAe,EAAE,8BAA8B;AAKxD,OAAO,EAAE,IAAI,EAAE,mBAAe;AAU9B,MAAM,OAAO,QAAS,SAAQ,IAAI;IAAlC;;QACW,aAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC;IAqDjD,CAAC;IAnDC,aAAa,CACX,OAAwB;QAExB,OAAO,CACL,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAM,YAAY,CAAC,IAAe;YAC/D,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS;YACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAC9B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAwB;QAC5B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE;YAChC,OAAO,SAAS,CAAC;SAClB;QAED,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAE7C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAE5D,OAAO;YACL,QAAQ;YACR,OAAO;SACR,CAAC;IACJ,CAAC;IAED,2BAA2B,CAAC,MAAyB;QACnD,qEAAqE;QACrE,4CAA4C;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,EAAkC,CAAC;QAEvE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,IAAI;YACnB,CAAC,CAAC,oGAAoG;gBACpG,eAAe;gBACf,IAAI,CAAC,QAAQ,CAAC,YAAY;YAC5B,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAE5B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0BAA0B,CAAC,KAAuB;QAChD,qEAAqE;QACrE,gEAAgE;QAChE,gDAAgD;QAChD,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc,EAAkC,CAAC;QAEvE,gDAAgD;QAChD,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC/B,CAAC;CACF","sourcesContent":["import {\n AccountWalletCategory,\n toAccountGroupId,\n toAccountWalletId,\n} from '@metamask/account-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { stripSnapPrefix } from '@metamask/snaps-utils';\nimport type { AccountTreeGroup } from 'src/AccountTreeGroup';\nimport type { AccountTreeWallet } from 'src/AccountTreeWallet';\nimport type { AccountContext } from 'src/types';\n\nimport { Rule } from './rule';\n\ntype SnapAccount<Account extends InternalAccount> = Account & {\n metadata: Account['metadata'] & {\n snap: {\n id: SnapId;\n };\n };\n};\n\nexport class SnapRule extends Rule {\n readonly category = AccountWalletCategory.Snap;\n\n isSnapAccount(\n account: InternalAccount,\n ): account is SnapAccount<InternalAccount> {\n return (\n account.metadata.keyring.type === (KeyringTypes.snap as string) &&\n account.metadata.snap !== undefined &&\n account.metadata.snap.enabled\n );\n }\n\n match(account: InternalAccount): AccountContext | undefined {\n if (!this.isSnapAccount(account)) {\n return undefined;\n }\n\n const { id: snapId } = account.metadata.snap;\n\n const walletId = toAccountWalletId(this.category, snapId);\n const groupId = toAccountGroupId(walletId, account.address);\n\n return {\n walletId,\n groupId,\n };\n }\n\n getDefaultAccountWalletName(wallet: AccountTreeWallet): string {\n // Precondition: This method is invoked only if there was a match for\n // a Snap account, so we can type-cast here.\n const account = wallet.getAnyAccount() as SnapAccount<InternalAccount>;\n\n const { id: snapId } = account.metadata.snap;\n const snap = this.messenger.call('SnapController:get', snapId);\n const snapName = snap\n ? // TODO: Handle localization here, but that's a \"client thing\", so we don't have a `core` controller\n // to refer to.\n snap.manifest.proposedName\n : stripSnapPrefix(snapId);\n\n return snapName;\n }\n\n getDefaultAccountGroupName(group: AccountTreeGroup): string {\n // Precondition: This method is invoked only if there was a match for\n // a Snap account, so we can type-cast here. Also, each of those\n // account groups should contain only 1 account.\n const account = group.getOnlyAccount() as SnapAccount<InternalAccount>;\n\n // We only have 1 account for this kind of rule.\n return account.metadata.name;\n }\n}\n"]}
package/dist/types.cjs ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.cjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\n\n/**\n * Context for an account.\n */\nexport type AccountContext = {\n /**\n * Wallet ID associated to that account.\n */\n walletId: AccountWalletId;\n\n /**\n * Account group ID associated to that account.\n */\n groupId: AccountGroupId;\n};\n"]}
@@ -0,0 +1,15 @@
1
+ import type { AccountGroupId, AccountWalletId } from "@metamask/account-api";
2
+ /**
3
+ * Context for an account.
4
+ */
5
+ export type AccountContext = {
6
+ /**
7
+ * Wallet ID associated to that account.
8
+ */
9
+ walletId: AccountWalletId;
10
+ /**
11
+ * Account group ID associated to that account.
12
+ */
13
+ groupId: AccountGroupId;
14
+ };
15
+ //# sourceMappingURL=types.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,8BAA8B;AAE7E;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,QAAQ,EAAE,eAAe,CAAC;IAE1B;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC;CACzB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { AccountGroupId, AccountWalletId } from "@metamask/account-api";
2
+ /**
3
+ * Context for an account.
4
+ */
5
+ export type AccountContext = {
6
+ /**
7
+ * Wallet ID associated to that account.
8
+ */
9
+ walletId: AccountWalletId;
10
+ /**
11
+ * Account group ID associated to that account.
12
+ */
13
+ groupId: AccountGroupId;
14
+ };
15
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,8BAA8B;AAE7E;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,QAAQ,EAAE,eAAe,CAAC;IAE1B;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC;CACzB,CAAC"}
package/dist/types.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.mjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\n\n/**\n * Context for an account.\n */\nexport type AccountContext = {\n /**\n * Wallet ID associated to that account.\n */\n walletId: AccountWalletId;\n\n /**\n * Account group ID associated to that account.\n */\n groupId: AccountGroupId;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/account-tree-controller",
3
- "version": "0.6.0-preview-b8fffa99",
3
+ "version": "0.6.0-preview-ed2a2e6",
4
4
  "description": "Controller to group account together based on some pre-defined rules",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -53,7 +53,7 @@
53
53
  "lodash": "^4.17.21"
54
54
  },
55
55
  "devDependencies": {
56
- "@metamask/account-api": "^0.2.0",
56
+ "@metamask/account-api": "^0.3.0",
57
57
  "@metamask/accounts-controller": "^32.0.0",
58
58
  "@metamask/auto-changelog": "^3.4.4",
59
59
  "@metamask/keyring-api": "^19.0.0",
@@ -70,7 +70,7 @@
70
70
  "webextension-polyfill": "^0.12.0"
71
71
  },
72
72
  "peerDependencies": {
73
- "@metamask/account-api": "^0.2.0",
73
+ "@metamask/account-api": "^0.3.0",
74
74
  "@metamask/accounts-controller": "^32.0.0",
75
75
  "@metamask/keyring-controller": "^22.0.0",
76
76
  "@metamask/providers": "^22.0.0",
@@ -1,100 +0,0 @@
1
- "use strict";
2
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
- if (kind === "m") throw new TypeError("Private method is not writable");
4
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
- };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var _EntropySourceWalletRule_wallets;
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.EntropySourceWalletRule = exports.EntropySourceWallet = void 0;
16
- const account_api_1 = require("@metamask/account-api");
17
- const keyring_controller_1 = require("@metamask/keyring-controller");
18
- const utils_1 = require("./utils.cjs");
19
- const WalletRule_1 = require("./WalletRule.cjs");
20
- const AccountTreeWallet_1 = require("../AccountTreeWallet.cjs");
21
- class EntropySourceWallet extends AccountTreeWallet_1.MutableAccountTreeWallet {
22
- constructor(messenger, entropySource) {
23
- super(messenger, account_api_1.AccountWalletCategory.Entropy, entropySource);
24
- this.entropySource = entropySource;
25
- }
26
- static toAccountWalletId(entropySource) {
27
- return (0, account_api_1.toAccountWalletId)(account_api_1.AccountWalletCategory.Entropy, entropySource);
28
- }
29
- static getEntropySourceIndex(keyrings, entropySource) {
30
- return keyrings
31
- .filter((keyring) => keyring.type === keyring_controller_1.KeyringTypes.hd)
32
- .findIndex((keyring) => keyring.metadata.id === entropySource);
33
- }
34
- getDefaultName() {
35
- const { keyrings } = this.messenger.call('KeyringController:getState');
36
- const index = EntropySourceWallet.getEntropySourceIndex(keyrings, this.entropySource);
37
- if (index === -1) {
38
- // NOTE: This should never really fail, as we checked for this precondition
39
- // during rule matching.
40
- throw new Error('Unable to get index for entropy source');
41
- }
42
- return `Wallet ${index + 1}`; // Use human indexing.
43
- }
44
- }
45
- exports.EntropySourceWallet = EntropySourceWallet;
46
- class EntropySourceWalletRule extends WalletRule_1.BaseWalletRule {
47
- constructor(messenger) {
48
- super(messenger);
49
- _EntropySourceWalletRule_wallets.set(this, void 0);
50
- __classPrivateFieldSet(this, _EntropySourceWalletRule_wallets, new Map(), "f");
51
- }
52
- match(account) {
53
- let entropySource;
54
- if ((0, utils_1.hasKeyringType)(account, keyring_controller_1.KeyringTypes.hd)) {
55
- // TODO: Maybe use superstruct to validate the structure of HD account since they are not strongly-typed for now?
56
- if (!account.options.entropySource) {
57
- console.warn("! Found an HD account with no entropy source: account won't be associated to its wallet");
58
- return undefined;
59
- }
60
- entropySource = account.options.entropySource;
61
- }
62
- // TODO: For now, we're not checking if the Snap is a preinstalled one, and we probably should...
63
- if ((0, utils_1.hasKeyringType)(account, keyring_controller_1.KeyringTypes.snap) &&
64
- account.metadata.snap?.enabled) {
65
- // Not all Snaps have an entropy-source and options are not typed yet, so we have to check manually here.
66
- if (account.options.entropySource) {
67
- // We blindly trust the `entropySource` for now, but it could be wrong since it comes from a Snap.
68
- entropySource = account.options.entropySource;
69
- }
70
- }
71
- if (!entropySource) {
72
- return undefined;
73
- }
74
- // NOTE: We make this check now, so that we are guaranteed that `getDefaultName` will never fail if we
75
- // pass that point:
76
- // ------------------------------------------------------------------------------------------------------
77
- // We check if we can get the name for that entropy source, if not this means this entropy does not match
78
- // any HD keyrings, thus, is invalid (this account will be grouped by another rule).
79
- const { keyrings } = this.messenger.call('KeyringController:getState');
80
- if (EntropySourceWallet.getEntropySourceIndex(keyrings, entropySource) === -1) {
81
- console.warn('! Tried to name a wallet using an unknown entropy, this should not be possible.');
82
- return undefined;
83
- }
84
- // Check if a wallet already exists for that entropy source.
85
- let wallet = __classPrivateFieldGet(this, _EntropySourceWalletRule_wallets, "f").get(EntropySourceWallet.toAccountWalletId(entropySource));
86
- if (!wallet) {
87
- wallet = new EntropySourceWallet(this.messenger, entropySource);
88
- __classPrivateFieldGet(this, _EntropySourceWalletRule_wallets, "f").set(wallet.id, wallet);
89
- }
90
- // This will automatically creates the group if it's missing.
91
- const group = wallet.addAccount(account);
92
- return {
93
- wallet,
94
- group,
95
- };
96
- }
97
- }
98
- exports.EntropySourceWalletRule = EntropySourceWalletRule;
99
- _EntropySourceWalletRule_wallets = new WeakMap();
100
- //# sourceMappingURL=EntropySourceWalletRule.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EntropySourceWalletRule.cjs","sourceRoot":"","sources":["../../src/rules/EntropySourceWalletRule.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountWalletId } from '@metamask/account-api';\nimport {\n AccountWalletCategory,\n toAccountWalletId,\n} from '@metamask/account-api';\nimport type { KeyringObject } from '@metamask/keyring-controller';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport { hasKeyringType } from './utils';\nimport type { WalletRuleMatch } from './WalletRule';\nimport { BaseWalletRule } from './WalletRule';\nimport type { AccountTreeControllerMessenger } from '../AccountTreeController';\nimport { MutableAccountTreeWallet } from '../AccountTreeWallet';\n\nexport class EntropySourceWallet extends MutableAccountTreeWallet {\n readonly entropySource: string;\n\n constructor(\n messenger: AccountTreeControllerMessenger,\n entropySource: string,\n ) {\n super(messenger, AccountWalletCategory.Entropy, entropySource);\n this.entropySource = entropySource;\n }\n\n static toAccountWalletId(entropySource: string) {\n return toAccountWalletId(AccountWalletCategory.Entropy, entropySource);\n }\n\n static getEntropySourceIndex(\n keyrings: KeyringObject[],\n entropySource: string,\n ) {\n return keyrings\n .filter((keyring) => keyring.type === (KeyringTypes.hd as string))\n .findIndex((keyring) => keyring.metadata.id === entropySource);\n }\n\n getDefaultName(): string {\n const { keyrings } = this.messenger.call('KeyringController:getState');\n\n const index = EntropySourceWallet.getEntropySourceIndex(\n keyrings,\n this.entropySource,\n );\n if (index === -1) {\n // NOTE: This should never really fail, as we checked for this precondition\n // during rule matching.\n throw new Error('Unable to get index for entropy source');\n }\n\n return `Wallet ${index + 1}`; // Use human indexing.\n }\n}\n\nexport class EntropySourceWalletRule extends BaseWalletRule {\n readonly #wallets: Map<AccountWalletId, EntropySourceWallet>;\n\n constructor(messenger: AccountTreeControllerMessenger) {\n super(messenger);\n\n this.#wallets = new Map();\n }\n\n match(account: InternalAccount): WalletRuleMatch | undefined {\n let entropySource: string | undefined;\n\n if (hasKeyringType(account, KeyringTypes.hd)) {\n // TODO: Maybe use superstruct to validate the structure of HD account since they are not strongly-typed for now?\n if (!account.options.entropySource) {\n console.warn(\n \"! Found an HD account with no entropy source: account won't be associated to its wallet\",\n );\n return undefined;\n }\n\n entropySource = account.options.entropySource as string;\n }\n\n // TODO: For now, we're not checking if the Snap is a preinstalled one, and we probably should...\n if (\n hasKeyringType(account, KeyringTypes.snap) &&\n account.metadata.snap?.enabled\n ) {\n // Not all Snaps have an entropy-source and options are not typed yet, so we have to check manually here.\n if (account.options.entropySource) {\n // We blindly trust the `entropySource` for now, but it could be wrong since it comes from a Snap.\n entropySource = account.options.entropySource as string;\n }\n }\n\n if (!entropySource) {\n return undefined;\n }\n\n // NOTE: We make this check now, so that we are guaranteed that `getDefaultName` will never fail if we\n // pass that point:\n // ------------------------------------------------------------------------------------------------------\n // We check if we can get the name for that entropy source, if not this means this entropy does not match\n // any HD keyrings, thus, is invalid (this account will be grouped by another rule).\n const { keyrings } = this.messenger.call('KeyringController:getState');\n if (\n EntropySourceWallet.getEntropySourceIndex(keyrings, entropySource) === -1\n ) {\n console.warn(\n '! Tried to name a wallet using an unknown entropy, this should not be possible.',\n );\n return undefined;\n }\n\n // Check if a wallet already exists for that entropy source.\n let wallet = this.#wallets.get(\n EntropySourceWallet.toAccountWalletId(entropySource),\n );\n if (!wallet) {\n wallet = new EntropySourceWallet(this.messenger, entropySource);\n this.#wallets.set(wallet.id, wallet);\n }\n\n // This will automatically creates the group if it's missing.\n const group = wallet.addAccount(account);\n\n return {\n wallet,\n group,\n };\n }\n}\n"]}
@@ -1,19 +0,0 @@
1
- import type { KeyringObject } from "@metamask/keyring-controller";
2
- import type { InternalAccount } from "@metamask/keyring-internal-api";
3
- import type { WalletRuleMatch } from "./WalletRule.cjs";
4
- import { BaseWalletRule } from "./WalletRule.cjs";
5
- import type { AccountTreeControllerMessenger } from "../AccountTreeController.cjs";
6
- import { MutableAccountTreeWallet } from "../AccountTreeWallet.cjs";
7
- export declare class EntropySourceWallet extends MutableAccountTreeWallet {
8
- readonly entropySource: string;
9
- constructor(messenger: AccountTreeControllerMessenger, entropySource: string);
10
- static toAccountWalletId(entropySource: string): `entropy:${string}` | `keyring:${string}` | `snap:${string}`;
11
- static getEntropySourceIndex(keyrings: KeyringObject[], entropySource: string): number;
12
- getDefaultName(): string;
13
- }
14
- export declare class EntropySourceWalletRule extends BaseWalletRule {
15
- #private;
16
- constructor(messenger: AccountTreeControllerMessenger);
17
- match(account: InternalAccount): WalletRuleMatch | undefined;
18
- }
19
- //# sourceMappingURL=EntropySourceWalletRule.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EntropySourceWalletRule.d.cts","sourceRoot":"","sources":["../../src/rules/EntropySourceWalletRule.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,qCAAqC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAGtE,OAAO,KAAK,EAAE,eAAe,EAAE,yBAAqB;AACpD,OAAO,EAAE,cAAc,EAAE,yBAAqB;AAC9C,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,iCAA6B;AAEhE,qBAAa,mBAAoB,SAAQ,wBAAwB;IAC/D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAG7B,SAAS,EAAE,8BAA8B,EACzC,aAAa,EAAE,MAAM;IAMvB,MAAM,CAAC,iBAAiB,CAAC,aAAa,EAAE,MAAM;IAI9C,MAAM,CAAC,qBAAqB,CAC1B,QAAQ,EAAE,aAAa,EAAE,EACzB,aAAa,EAAE,MAAM;IAOvB,cAAc,IAAI,MAAM;CAezB;AAED,qBAAa,uBAAwB,SAAQ,cAAc;;gBAG7C,SAAS,EAAE,8BAA8B;IAMrD,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,eAAe,GAAG,SAAS;CA+D7D"}