@metamask-previews/multichain-account-service 0.0.0-preview-21df933
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/CHANGELOG.md +15 -0
- package/LICENSE +20 -0
- package/README.md +17 -0
- package/dist/MultichainAccountService.cjs +120 -0
- package/dist/MultichainAccountService.cjs.map +1 -0
- package/dist/MultichainAccountService.d.cts +55 -0
- package/dist/MultichainAccountService.d.cts.map +1 -0
- package/dist/MultichainAccountService.d.mts +55 -0
- package/dist/MultichainAccountService.d.mts.map +1 -0
- package/dist/MultichainAccountService.mjs +116 -0
- package/dist/MultichainAccountService.mjs.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/BaseAccountProvider.cjs +59 -0
- package/dist/providers/BaseAccountProvider.cjs.map +1 -0
- package/dist/providers/BaseAccountProvider.d.cts +26 -0
- package/dist/providers/BaseAccountProvider.d.cts.map +1 -0
- package/dist/providers/BaseAccountProvider.d.mts +26 -0
- package/dist/providers/BaseAccountProvider.d.mts.map +1 -0
- package/dist/providers/BaseAccountProvider.mjs +54 -0
- package/dist/providers/BaseAccountProvider.mjs.map +1 -0
- package/dist/providers/EvmAccountProvider.cjs +14 -0
- package/dist/providers/EvmAccountProvider.cjs.map +1 -0
- package/dist/providers/EvmAccountProvider.d.cts +6 -0
- package/dist/providers/EvmAccountProvider.d.cts.map +1 -0
- package/dist/providers/EvmAccountProvider.d.mts +6 -0
- package/dist/providers/EvmAccountProvider.d.mts.map +1 -0
- package/dist/providers/EvmAccountProvider.mjs +10 -0
- package/dist/providers/EvmAccountProvider.mjs.map +1 -0
- package/dist/providers/SolAccountProvider.cjs +15 -0
- package/dist/providers/SolAccountProvider.cjs.map +1 -0
- package/dist/providers/SolAccountProvider.d.cts +8 -0
- package/dist/providers/SolAccountProvider.d.cts.map +1 -0
- package/dist/providers/SolAccountProvider.d.mts +8 -0
- package/dist/providers/SolAccountProvider.d.mts.map +1 -0
- package/dist/providers/SolAccountProvider.mjs +11 -0
- package/dist/providers/SolAccountProvider.mjs.map +1 -0
- package/dist/tests/accounts.cjs +179 -0
- package/dist/tests/accounts.cjs.map +1 -0
- package/dist/tests/accounts.d.cts +82 -0
- package/dist/tests/accounts.d.cts.map +1 -0
- package/dist/tests/accounts.d.mts +82 -0
- package/dist/tests/accounts.d.mts.map +1 -0
- package/dist/tests/accounts.mjs +175 -0
- package/dist/tests/accounts.mjs.map +1 -0
- package/dist/tests/index.cjs +19 -0
- package/dist/tests/index.cjs.map +1 -0
- package/dist/tests/index.d.cts +3 -0
- package/dist/tests/index.d.cts.map +1 -0
- package/dist/tests/index.d.mts +3 -0
- package/dist/tests/index.d.mts.map +1 -0
- package/dist/tests/index.mjs +3 -0
- package/dist/tests/index.mjs.map +1 -0
- package/dist/tests/messenger.cjs +35 -0
- package/dist/tests/messenger.cjs.map +1 -0
- package/dist/tests/messenger.d.cts +16 -0
- package/dist/tests/messenger.d.cts.map +1 -0
- package/dist/tests/messenger.d.mts +16 -0
- package/dist/tests/messenger.d.mts.map +1 -0
- package/dist/tests/messenger.mjs +30 -0
- package/dist/tests/messenger.mjs.map +1 -0
- package/dist/types.cjs +3 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +30 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +30 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +89 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Add `MultichainAccountService` ([#6141](https://github.com/MetaMask/core/pull/6141))
|
|
13
|
+
- This service manages multichain accounts/wallets.
|
|
14
|
+
|
|
15
|
+
[Unreleased]: https://github.com/MetaMask/core/
|
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 MetaMask
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# `@metamask/multichain-account-service`
|
|
2
|
+
|
|
3
|
+
Multichain account service.
|
|
4
|
+
|
|
5
|
+
This service provides operations and functionalities around multichain accounts and wallets.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
`yarn add @metamask/multichain-account-service`
|
|
10
|
+
|
|
11
|
+
or
|
|
12
|
+
|
|
13
|
+
`npm install @metamask/multichain-account-service`
|
|
14
|
+
|
|
15
|
+
## Contributing
|
|
16
|
+
|
|
17
|
+
This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme).
|
|
@@ -0,0 +1,120 @@
|
|
|
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 _MultichainAccountService_instances, _MultichainAccountService_messenger, _MultichainAccountService_providers, _MultichainAccountService_wallets, _MultichainAccountService_setMultichainAccountWallets, _MultichainAccountService_getWallet;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.MultichainAccountService = void 0;
|
|
16
|
+
const account_api_1 = require("@metamask/account-api");
|
|
17
|
+
const keyring_controller_1 = require("@metamask/keyring-controller");
|
|
18
|
+
const EvmAccountProvider_1 = require("./providers/EvmAccountProvider.cjs");
|
|
19
|
+
const SolAccountProvider_1 = require("./providers/SolAccountProvider.cjs");
|
|
20
|
+
/**
|
|
21
|
+
* Select keyrings from keyring controller state.
|
|
22
|
+
*
|
|
23
|
+
* @param state - The keyring controller state.
|
|
24
|
+
* @returns The keyrings.
|
|
25
|
+
*/
|
|
26
|
+
function selectKeyringControllerKeyrings(state) {
|
|
27
|
+
return state.keyrings;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Service to expose multichain accounts capabilities.
|
|
31
|
+
*/
|
|
32
|
+
class MultichainAccountService {
|
|
33
|
+
/**
|
|
34
|
+
* Constructs a new MultichainAccountService.
|
|
35
|
+
*
|
|
36
|
+
* @param options - The options.
|
|
37
|
+
* @param options.messenger - The messenger suited to this
|
|
38
|
+
* MultichainAccountService.
|
|
39
|
+
*/
|
|
40
|
+
constructor({ messenger }) {
|
|
41
|
+
_MultichainAccountService_instances.add(this);
|
|
42
|
+
_MultichainAccountService_messenger.set(this, void 0);
|
|
43
|
+
_MultichainAccountService_providers.set(this, void 0);
|
|
44
|
+
_MultichainAccountService_wallets.set(this, void 0);
|
|
45
|
+
__classPrivateFieldSet(this, _MultichainAccountService_messenger, messenger, "f");
|
|
46
|
+
__classPrivateFieldSet(this, _MultichainAccountService_wallets, new Map(), "f");
|
|
47
|
+
// TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.
|
|
48
|
+
__classPrivateFieldSet(this, _MultichainAccountService_providers, [
|
|
49
|
+
new EvmAccountProvider_1.EvmAccountProvider(__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f")),
|
|
50
|
+
new SolAccountProvider_1.SolAccountProvider(__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f")),
|
|
51
|
+
], "f");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initialize the service and constructs the internal reprensentation of
|
|
55
|
+
* multichain accounts and wallets.
|
|
56
|
+
*/
|
|
57
|
+
init() {
|
|
58
|
+
// Gather all entropy sources first.
|
|
59
|
+
const state = __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").call('KeyringController:getState');
|
|
60
|
+
__classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_setMultichainAccountWallets).call(this, state.keyrings);
|
|
61
|
+
__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").subscribe('KeyringController:stateChange', (keyrings) => {
|
|
62
|
+
__classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_setMultichainAccountWallets).call(this, keyrings);
|
|
63
|
+
}, selectKeyringControllerKeyrings);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Gets a reference to the multichain account matching this entropy source and group index.
|
|
67
|
+
*
|
|
68
|
+
* @param options - Options.
|
|
69
|
+
* @param options.entropySource - The entropy source of the multichain account.
|
|
70
|
+
* @param options.groupIndex - The group index of the multichain account.
|
|
71
|
+
* @throws If none multichain account match this entropy source and group index.
|
|
72
|
+
* @returns A reference to the multichain account.
|
|
73
|
+
*/
|
|
74
|
+
getMultichainAccount({ entropySource, groupIndex, }) {
|
|
75
|
+
const multichainAccount = __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).getMultichainAccount(groupIndex);
|
|
76
|
+
if (!multichainAccount) {
|
|
77
|
+
throw new Error(`No multichain account for index: ${groupIndex}`);
|
|
78
|
+
}
|
|
79
|
+
return multichainAccount;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Gets all multichain accounts for a given entropy source.
|
|
83
|
+
*
|
|
84
|
+
* @param options - Options.
|
|
85
|
+
* @param options.entropySource - The entropy source to query.
|
|
86
|
+
* @throws If no multichain accounts match this entropy source.
|
|
87
|
+
* @returns A list of all multichain accounts.
|
|
88
|
+
*/
|
|
89
|
+
getMultichainAccounts({ entropySource, }) {
|
|
90
|
+
return __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).getMultichainAccounts();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
exports.MultichainAccountService = MultichainAccountService;
|
|
94
|
+
_MultichainAccountService_messenger = new WeakMap(), _MultichainAccountService_providers = new WeakMap(), _MultichainAccountService_wallets = new WeakMap(), _MultichainAccountService_instances = new WeakSet(), _MultichainAccountService_setMultichainAccountWallets = function _MultichainAccountService_setMultichainAccountWallets(keyrings) {
|
|
95
|
+
for (const keyring of keyrings) {
|
|
96
|
+
if (keyring.type === keyring_controller_1.KeyringTypes.hd) {
|
|
97
|
+
// Only HD keyrings have an entropy source/SRP.
|
|
98
|
+
const entropySource = keyring.metadata.id;
|
|
99
|
+
// Do not re-create wallets if they exists. Even if a keyrings got new accounts, this
|
|
100
|
+
// will be handled by the `*AccountProvider`s which are always in-sync with their
|
|
101
|
+
// keyrings and controllers (like the `AccountsController`).
|
|
102
|
+
if (!__classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").has((0, account_api_1.toMultichainAccountWalletId)(entropySource))) {
|
|
103
|
+
// This will automatically "associate" all multichain accounts for that wallet
|
|
104
|
+
// (based on the accounts owned by each account providers).
|
|
105
|
+
const wallet = new account_api_1.MultichainAccountWallet({
|
|
106
|
+
entropySource,
|
|
107
|
+
providers: __classPrivateFieldGet(this, _MultichainAccountService_providers, "f"),
|
|
108
|
+
});
|
|
109
|
+
__classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").set(wallet.id, wallet);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}, _MultichainAccountService_getWallet = function _MultichainAccountService_getWallet(entropySource) {
|
|
114
|
+
const wallet = __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").get((0, account_api_1.toMultichainAccountWalletId)(entropySource));
|
|
115
|
+
if (!wallet) {
|
|
116
|
+
throw new Error('Unknown wallet, no wallet matching this entropy source');
|
|
117
|
+
}
|
|
118
|
+
return wallet;
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=MultichainAccountService.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultichainAccountService.cjs","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAIA,uDAI+B;AAM/B,qEAA4D;AAG5D,2EAAoE;AACpE,2EAAoE;AAUpE;;;;;GAKG;AACH,SAAS,+BAA+B,CAAC,KAA6B;IACpE,OAAO,KAAK,CAAC,QAAQ,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAa,wBAAwB;IAUnC;;;;;;OAMG;IACH,YAAY,EAAE,SAAS,EAAmC;;QAhBjD,sDAA8C;QAE9C,sDAA+C;QAE/C,oDAGP;QAUA,uBAAA,IAAI,uCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,qCAAY,IAAI,GAAG,EAAE,MAAA,CAAC;QAC1B,mFAAmF;QACnF,uBAAA,IAAI,uCAAc;YAChB,IAAI,uCAAkB,CAAC,uBAAA,IAAI,2CAAW,CAAC;YACvC,IAAI,uCAAkB,CAAC,uBAAA,IAAI,2CAAW,CAAC;SACxC,MAAA,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,IAAI;QACF,oCAAoC;QACpC,MAAM,KAAK,GAAG,uBAAA,IAAI,2CAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACjE,uBAAA,IAAI,kGAA6B,MAAjC,IAAI,EAA8B,KAAK,CAAC,QAAQ,CAAC,CAAC;QAElD,uBAAA,IAAI,2CAAW,CAAC,SAAS,CACvB,+BAA+B,EAC/B,CAAC,QAAQ,EAAE,EAAE;YACX,uBAAA,IAAI,kGAA6B,MAAjC,IAAI,EAA8B,QAAQ,CAAC,CAAC;QAC9C,CAAC,EACD,+BAA+B,CAChC,CAAC;IACJ,CAAC;IAuCD;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EACnB,aAAa,EACb,UAAU,GAIX;QACC,MAAM,iBAAiB,GACrB,uBAAA,IAAI,gFAAW,MAAf,IAAI,EAAY,aAAa,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAElE,IAAI,CAAC,iBAAiB,EAAE;YACtB,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;SACnE;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED;;;;;;;OAOG;IACH,qBAAqB,CAAC,EACpB,aAAa,GAGd;QACC,OAAO,uBAAA,IAAI,gFAAW,MAAf,IAAI,EAAY,aAAa,CAAC,CAAC,qBAAqB,EAAE,CAAC;IAChE,CAAC;CACF;AA3HD,4DA2HC;yUA9E8B,QAAyB;IACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;QAC9B,IAAI,OAAO,CAAC,IAAI,KAAM,iCAAY,CAAC,EAAa,EAAE;YAChD,+CAA+C;YAC/C,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAE1C,qFAAqF;YACrF,iFAAiF;YACjF,4DAA4D;YAC5D,IAAI,CAAC,uBAAA,IAAI,yCAAS,CAAC,GAAG,CAAC,IAAA,yCAA2B,EAAC,aAAa,CAAC,CAAC,EAAE;gBAClE,8EAA8E;gBAC9E,2DAA2D;gBAC3D,MAAM,MAAM,GAAG,IAAI,qCAAuB,CAAC;oBACzC,aAAa;oBACb,SAAS,EAAE,uBAAA,IAAI,2CAAW;iBAC3B,CAAC,CAAC;gBAEH,uBAAA,IAAI,yCAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;aACtC;SACF;KACF;AACH,CAAC,qFAGC,aAA8B;IAE9B,MAAM,MAAM,GAAG,uBAAA,IAAI,yCAAS,CAAC,GAAG,CAC9B,IAAA,yCAA2B,EAAC,aAAa,CAAC,CAC3C,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;KAC3E;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type {\n MultichainAccountWalletId,\n AccountProvider,\n} from '@metamask/account-api';\nimport {\n MultichainAccountWallet,\n toMultichainAccountWalletId,\n type MultichainAccount,\n} from '@metamask/account-api';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport type {\n KeyringControllerState,\n KeyringObject,\n} from '@metamask/keyring-controller';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport { EvmAccountProvider } from './providers/EvmAccountProvider';\nimport { SolAccountProvider } from './providers/SolAccountProvider';\nimport type { MultichainAccountServiceMessenger } from './types';\n\n/**\n * The options that {@link MultichainAccountService} takes.\n */\ntype MultichainAccountServiceOptions = {\n messenger: MultichainAccountServiceMessenger;\n};\n\n/**\n * Select keyrings from keyring controller state.\n *\n * @param state - The keyring controller state.\n * @returns The keyrings.\n */\nfunction selectKeyringControllerKeyrings(state: KeyringControllerState) {\n return state.keyrings;\n}\n\n/**\n * Service to expose multichain accounts capabilities.\n */\nexport class MultichainAccountService {\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #providers: AccountProvider<InternalAccount>[];\n\n readonly #wallets: Map<\n MultichainAccountWalletId,\n MultichainAccountWallet<InternalAccount>\n >;\n\n /**\n * Constructs a new MultichainAccountService.\n *\n * @param options - The options.\n * @param options.messenger - The messenger suited to this\n * MultichainAccountService.\n */\n constructor({ messenger }: MultichainAccountServiceOptions) {\n this.#messenger = messenger;\n this.#wallets = new Map();\n // TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.\n this.#providers = [\n new EvmAccountProvider(this.#messenger),\n new SolAccountProvider(this.#messenger),\n ];\n }\n\n /**\n * Initialize the service and constructs the internal reprensentation of\n * multichain accounts and wallets.\n */\n init(): void {\n // Gather all entropy sources first.\n const state = this.#messenger.call('KeyringController:getState');\n this.#setMultichainAccountWallets(state.keyrings);\n\n this.#messenger.subscribe(\n 'KeyringController:stateChange',\n (keyrings) => {\n this.#setMultichainAccountWallets(keyrings);\n },\n selectKeyringControllerKeyrings,\n );\n }\n\n #setMultichainAccountWallets(keyrings: KeyringObject[]) {\n for (const keyring of keyrings) {\n if (keyring.type === (KeyringTypes.hd as string)) {\n // Only HD keyrings have an entropy source/SRP.\n const entropySource = keyring.metadata.id;\n\n // Do not re-create wallets if they exists. Even if a keyrings got new accounts, this\n // will be handled by the `*AccountProvider`s which are always in-sync with their\n // keyrings and controllers (like the `AccountsController`).\n if (!this.#wallets.has(toMultichainAccountWalletId(entropySource))) {\n // This will automatically \"associate\" all multichain accounts for that wallet\n // (based on the accounts owned by each account providers).\n const wallet = new MultichainAccountWallet({\n entropySource,\n providers: this.#providers,\n });\n\n this.#wallets.set(wallet.id, wallet);\n }\n }\n }\n }\n\n #getWallet(\n entropySource: EntropySourceId,\n ): MultichainAccountWallet<InternalAccount> {\n const wallet = this.#wallets.get(\n toMultichainAccountWalletId(entropySource),\n );\n\n if (!wallet) {\n throw new Error('Unknown wallet, no wallet matching this entropy source');\n }\n\n return wallet;\n }\n\n /**\n * Gets a reference to the multichain account matching this entropy source and group index.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @param options.groupIndex - The group index of the multichain account.\n * @throws If none multichain account match this entropy source and group index.\n * @returns A reference to the multichain account.\n */\n getMultichainAccount({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): MultichainAccount<InternalAccount> {\n const multichainAccount =\n this.#getWallet(entropySource).getMultichainAccount(groupIndex);\n\n if (!multichainAccount) {\n throw new Error(`No multichain account for index: ${groupIndex}`);\n }\n\n return multichainAccount;\n }\n\n /**\n * Gets all multichain accounts for a given entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source to query.\n * @throws If no multichain accounts match this entropy source.\n * @returns A list of all multichain accounts.\n */\n getMultichainAccounts({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccount<InternalAccount>[] {\n return this.#getWallet(entropySource).getMultichainAccounts();\n }\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type MultichainAccount } from "@metamask/account-api";
|
|
2
|
+
import type { EntropySourceId } from "@metamask/keyring-api";
|
|
3
|
+
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
4
|
+
import type { MultichainAccountServiceMessenger } from "./types.cjs";
|
|
5
|
+
/**
|
|
6
|
+
* The options that {@link MultichainAccountService} takes.
|
|
7
|
+
*/
|
|
8
|
+
type MultichainAccountServiceOptions = {
|
|
9
|
+
messenger: MultichainAccountServiceMessenger;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Service to expose multichain accounts capabilities.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MultichainAccountService {
|
|
15
|
+
#private;
|
|
16
|
+
/**
|
|
17
|
+
* Constructs a new MultichainAccountService.
|
|
18
|
+
*
|
|
19
|
+
* @param options - The options.
|
|
20
|
+
* @param options.messenger - The messenger suited to this
|
|
21
|
+
* MultichainAccountService.
|
|
22
|
+
*/
|
|
23
|
+
constructor({ messenger }: MultichainAccountServiceOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Initialize the service and constructs the internal reprensentation of
|
|
26
|
+
* multichain accounts and wallets.
|
|
27
|
+
*/
|
|
28
|
+
init(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Gets a reference to the multichain account matching this entropy source and group index.
|
|
31
|
+
*
|
|
32
|
+
* @param options - Options.
|
|
33
|
+
* @param options.entropySource - The entropy source of the multichain account.
|
|
34
|
+
* @param options.groupIndex - The group index of the multichain account.
|
|
35
|
+
* @throws If none multichain account match this entropy source and group index.
|
|
36
|
+
* @returns A reference to the multichain account.
|
|
37
|
+
*/
|
|
38
|
+
getMultichainAccount({ entropySource, groupIndex, }: {
|
|
39
|
+
entropySource: EntropySourceId;
|
|
40
|
+
groupIndex: number;
|
|
41
|
+
}): MultichainAccount<InternalAccount>;
|
|
42
|
+
/**
|
|
43
|
+
* Gets all multichain accounts for a given entropy source.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Options.
|
|
46
|
+
* @param options.entropySource - The entropy source to query.
|
|
47
|
+
* @throws If no multichain accounts match this entropy source.
|
|
48
|
+
* @returns A list of all multichain accounts.
|
|
49
|
+
*/
|
|
50
|
+
getMultichainAccounts({ entropySource, }: {
|
|
51
|
+
entropySource: EntropySourceId;
|
|
52
|
+
}): MultichainAccount<InternalAccount>[];
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=MultichainAccountService.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultichainAccountService.d.cts","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,iBAAiB,EACvB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAM7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAItE,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAEjE;;GAEG;AACH,KAAK,+BAA+B,GAAG;IACrC,SAAS,EAAE,iCAAiC,CAAC;CAC9C,CAAC;AAYF;;GAEG;AACH,qBAAa,wBAAwB;;IAUnC;;;;;;OAMG;gBACS,EAAE,SAAS,EAAE,EAAE,+BAA+B;IAU1D;;;OAGG;IACH,IAAI,IAAI,IAAI;IAmDZ;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EACnB,aAAa,EACb,UAAU,GACX,EAAE;QACD,aAAa,EAAE,eAAe,CAAC;QAC/B,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,iBAAiB,CAAC,eAAe,CAAC;IAWtC;;;;;;;OAOG;IACH,qBAAqB,CAAC,EACpB,aAAa,GACd,EAAE;QACD,aAAa,EAAE,eAAe,CAAC;KAChC,GAAG,iBAAiB,CAAC,eAAe,CAAC,EAAE;CAGzC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type MultichainAccount } from "@metamask/account-api";
|
|
2
|
+
import type { EntropySourceId } from "@metamask/keyring-api";
|
|
3
|
+
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
4
|
+
import type { MultichainAccountServiceMessenger } from "./types.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* The options that {@link MultichainAccountService} takes.
|
|
7
|
+
*/
|
|
8
|
+
type MultichainAccountServiceOptions = {
|
|
9
|
+
messenger: MultichainAccountServiceMessenger;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Service to expose multichain accounts capabilities.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MultichainAccountService {
|
|
15
|
+
#private;
|
|
16
|
+
/**
|
|
17
|
+
* Constructs a new MultichainAccountService.
|
|
18
|
+
*
|
|
19
|
+
* @param options - The options.
|
|
20
|
+
* @param options.messenger - The messenger suited to this
|
|
21
|
+
* MultichainAccountService.
|
|
22
|
+
*/
|
|
23
|
+
constructor({ messenger }: MultichainAccountServiceOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Initialize the service and constructs the internal reprensentation of
|
|
26
|
+
* multichain accounts and wallets.
|
|
27
|
+
*/
|
|
28
|
+
init(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Gets a reference to the multichain account matching this entropy source and group index.
|
|
31
|
+
*
|
|
32
|
+
* @param options - Options.
|
|
33
|
+
* @param options.entropySource - The entropy source of the multichain account.
|
|
34
|
+
* @param options.groupIndex - The group index of the multichain account.
|
|
35
|
+
* @throws If none multichain account match this entropy source and group index.
|
|
36
|
+
* @returns A reference to the multichain account.
|
|
37
|
+
*/
|
|
38
|
+
getMultichainAccount({ entropySource, groupIndex, }: {
|
|
39
|
+
entropySource: EntropySourceId;
|
|
40
|
+
groupIndex: number;
|
|
41
|
+
}): MultichainAccount<InternalAccount>;
|
|
42
|
+
/**
|
|
43
|
+
* Gets all multichain accounts for a given entropy source.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Options.
|
|
46
|
+
* @param options.entropySource - The entropy source to query.
|
|
47
|
+
* @throws If no multichain accounts match this entropy source.
|
|
48
|
+
* @returns A list of all multichain accounts.
|
|
49
|
+
*/
|
|
50
|
+
getMultichainAccounts({ entropySource, }: {
|
|
51
|
+
entropySource: EntropySourceId;
|
|
52
|
+
}): MultichainAccount<InternalAccount>[];
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=MultichainAccountService.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultichainAccountService.d.mts","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,iBAAiB,EACvB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAM7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAItE,OAAO,KAAK,EAAE,iCAAiC,EAAE,oBAAgB;AAEjE;;GAEG;AACH,KAAK,+BAA+B,GAAG;IACrC,SAAS,EAAE,iCAAiC,CAAC;CAC9C,CAAC;AAYF;;GAEG;AACH,qBAAa,wBAAwB;;IAUnC;;;;;;OAMG;gBACS,EAAE,SAAS,EAAE,EAAE,+BAA+B;IAU1D;;;OAGG;IACH,IAAI,IAAI,IAAI;IAmDZ;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EACnB,aAAa,EACb,UAAU,GACX,EAAE;QACD,aAAa,EAAE,eAAe,CAAC;QAC/B,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,iBAAiB,CAAC,eAAe,CAAC;IAWtC;;;;;;;OAOG;IACH,qBAAqB,CAAC,EACpB,aAAa,GACd,EAAE;QACD,aAAa,EAAE,eAAe,CAAC;KAChC,GAAG,iBAAiB,CAAC,eAAe,CAAC,EAAE;CAGzC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
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");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
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");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _MultichainAccountService_instances, _MultichainAccountService_messenger, _MultichainAccountService_providers, _MultichainAccountService_wallets, _MultichainAccountService_setMultichainAccountWallets, _MultichainAccountService_getWallet;
|
|
13
|
+
import { MultichainAccountWallet, toMultichainAccountWalletId } from "@metamask/account-api";
|
|
14
|
+
import { KeyringTypes } from "@metamask/keyring-controller";
|
|
15
|
+
import { EvmAccountProvider } from "./providers/EvmAccountProvider.mjs";
|
|
16
|
+
import { SolAccountProvider } from "./providers/SolAccountProvider.mjs";
|
|
17
|
+
/**
|
|
18
|
+
* Select keyrings from keyring controller state.
|
|
19
|
+
*
|
|
20
|
+
* @param state - The keyring controller state.
|
|
21
|
+
* @returns The keyrings.
|
|
22
|
+
*/
|
|
23
|
+
function selectKeyringControllerKeyrings(state) {
|
|
24
|
+
return state.keyrings;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Service to expose multichain accounts capabilities.
|
|
28
|
+
*/
|
|
29
|
+
export class MultichainAccountService {
|
|
30
|
+
/**
|
|
31
|
+
* Constructs a new MultichainAccountService.
|
|
32
|
+
*
|
|
33
|
+
* @param options - The options.
|
|
34
|
+
* @param options.messenger - The messenger suited to this
|
|
35
|
+
* MultichainAccountService.
|
|
36
|
+
*/
|
|
37
|
+
constructor({ messenger }) {
|
|
38
|
+
_MultichainAccountService_instances.add(this);
|
|
39
|
+
_MultichainAccountService_messenger.set(this, void 0);
|
|
40
|
+
_MultichainAccountService_providers.set(this, void 0);
|
|
41
|
+
_MultichainAccountService_wallets.set(this, void 0);
|
|
42
|
+
__classPrivateFieldSet(this, _MultichainAccountService_messenger, messenger, "f");
|
|
43
|
+
__classPrivateFieldSet(this, _MultichainAccountService_wallets, new Map(), "f");
|
|
44
|
+
// TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.
|
|
45
|
+
__classPrivateFieldSet(this, _MultichainAccountService_providers, [
|
|
46
|
+
new EvmAccountProvider(__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f")),
|
|
47
|
+
new SolAccountProvider(__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f")),
|
|
48
|
+
], "f");
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Initialize the service and constructs the internal reprensentation of
|
|
52
|
+
* multichain accounts and wallets.
|
|
53
|
+
*/
|
|
54
|
+
init() {
|
|
55
|
+
// Gather all entropy sources first.
|
|
56
|
+
const state = __classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").call('KeyringController:getState');
|
|
57
|
+
__classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_setMultichainAccountWallets).call(this, state.keyrings);
|
|
58
|
+
__classPrivateFieldGet(this, _MultichainAccountService_messenger, "f").subscribe('KeyringController:stateChange', (keyrings) => {
|
|
59
|
+
__classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_setMultichainAccountWallets).call(this, keyrings);
|
|
60
|
+
}, selectKeyringControllerKeyrings);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gets a reference to the multichain account matching this entropy source and group index.
|
|
64
|
+
*
|
|
65
|
+
* @param options - Options.
|
|
66
|
+
* @param options.entropySource - The entropy source of the multichain account.
|
|
67
|
+
* @param options.groupIndex - The group index of the multichain account.
|
|
68
|
+
* @throws If none multichain account match this entropy source and group index.
|
|
69
|
+
* @returns A reference to the multichain account.
|
|
70
|
+
*/
|
|
71
|
+
getMultichainAccount({ entropySource, groupIndex, }) {
|
|
72
|
+
const multichainAccount = __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).getMultichainAccount(groupIndex);
|
|
73
|
+
if (!multichainAccount) {
|
|
74
|
+
throw new Error(`No multichain account for index: ${groupIndex}`);
|
|
75
|
+
}
|
|
76
|
+
return multichainAccount;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Gets all multichain accounts for a given entropy source.
|
|
80
|
+
*
|
|
81
|
+
* @param options - Options.
|
|
82
|
+
* @param options.entropySource - The entropy source to query.
|
|
83
|
+
* @throws If no multichain accounts match this entropy source.
|
|
84
|
+
* @returns A list of all multichain accounts.
|
|
85
|
+
*/
|
|
86
|
+
getMultichainAccounts({ entropySource, }) {
|
|
87
|
+
return __classPrivateFieldGet(this, _MultichainAccountService_instances, "m", _MultichainAccountService_getWallet).call(this, entropySource).getMultichainAccounts();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
_MultichainAccountService_messenger = new WeakMap(), _MultichainAccountService_providers = new WeakMap(), _MultichainAccountService_wallets = new WeakMap(), _MultichainAccountService_instances = new WeakSet(), _MultichainAccountService_setMultichainAccountWallets = function _MultichainAccountService_setMultichainAccountWallets(keyrings) {
|
|
91
|
+
for (const keyring of keyrings) {
|
|
92
|
+
if (keyring.type === KeyringTypes.hd) {
|
|
93
|
+
// Only HD keyrings have an entropy source/SRP.
|
|
94
|
+
const entropySource = keyring.metadata.id;
|
|
95
|
+
// Do not re-create wallets if they exists. Even if a keyrings got new accounts, this
|
|
96
|
+
// will be handled by the `*AccountProvider`s which are always in-sync with their
|
|
97
|
+
// keyrings and controllers (like the `AccountsController`).
|
|
98
|
+
if (!__classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").has(toMultichainAccountWalletId(entropySource))) {
|
|
99
|
+
// This will automatically "associate" all multichain accounts for that wallet
|
|
100
|
+
// (based on the accounts owned by each account providers).
|
|
101
|
+
const wallet = new MultichainAccountWallet({
|
|
102
|
+
entropySource,
|
|
103
|
+
providers: __classPrivateFieldGet(this, _MultichainAccountService_providers, "f"),
|
|
104
|
+
});
|
|
105
|
+
__classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").set(wallet.id, wallet);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}, _MultichainAccountService_getWallet = function _MultichainAccountService_getWallet(entropySource) {
|
|
110
|
+
const wallet = __classPrivateFieldGet(this, _MultichainAccountService_wallets, "f").get(toMultichainAccountWalletId(entropySource));
|
|
111
|
+
if (!wallet) {
|
|
112
|
+
throw new Error('Unknown wallet, no wallet matching this entropy source');
|
|
113
|
+
}
|
|
114
|
+
return wallet;
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=MultichainAccountService.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultichainAccountService.mjs","sourceRoot":"","sources":["../src/MultichainAccountService.ts"],"names":[],"mappings":";;;;;;;;;;;;AAIA,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAE5B,8BAA8B;AAM/B,OAAO,EAAE,YAAY,EAAE,qCAAqC;AAG5D,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AACpE,OAAO,EAAE,kBAAkB,EAAE,2CAAuC;AAUpE;;;;;GAKG;AACH,SAAS,+BAA+B,CAAC,KAA6B;IACpE,OAAO,KAAK,CAAC,QAAQ,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,wBAAwB;IAUnC;;;;;;OAMG;IACH,YAAY,EAAE,SAAS,EAAmC;;QAhBjD,sDAA8C;QAE9C,sDAA+C;QAE/C,oDAGP;QAUA,uBAAA,IAAI,uCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,qCAAY,IAAI,GAAG,EAAE,MAAA,CAAC;QAC1B,mFAAmF;QACnF,uBAAA,IAAI,uCAAc;YAChB,IAAI,kBAAkB,CAAC,uBAAA,IAAI,2CAAW,CAAC;YACvC,IAAI,kBAAkB,CAAC,uBAAA,IAAI,2CAAW,CAAC;SACxC,MAAA,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,IAAI;QACF,oCAAoC;QACpC,MAAM,KAAK,GAAG,uBAAA,IAAI,2CAAW,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACjE,uBAAA,IAAI,kGAA6B,MAAjC,IAAI,EAA8B,KAAK,CAAC,QAAQ,CAAC,CAAC;QAElD,uBAAA,IAAI,2CAAW,CAAC,SAAS,CACvB,+BAA+B,EAC/B,CAAC,QAAQ,EAAE,EAAE;YACX,uBAAA,IAAI,kGAA6B,MAAjC,IAAI,EAA8B,QAAQ,CAAC,CAAC;QAC9C,CAAC,EACD,+BAA+B,CAChC,CAAC;IACJ,CAAC;IAuCD;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EACnB,aAAa,EACb,UAAU,GAIX;QACC,MAAM,iBAAiB,GACrB,uBAAA,IAAI,gFAAW,MAAf,IAAI,EAAY,aAAa,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAElE,IAAI,CAAC,iBAAiB,EAAE;YACtB,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;SACnE;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED;;;;;;;OAOG;IACH,qBAAqB,CAAC,EACpB,aAAa,GAGd;QACC,OAAO,uBAAA,IAAI,gFAAW,MAAf,IAAI,EAAY,aAAa,CAAC,CAAC,qBAAqB,EAAE,CAAC;IAChE,CAAC;CACF;yUA9E8B,QAAyB;IACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;QAC9B,IAAI,OAAO,CAAC,IAAI,KAAM,YAAY,CAAC,EAAa,EAAE;YAChD,+CAA+C;YAC/C,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAE1C,qFAAqF;YACrF,iFAAiF;YACjF,4DAA4D;YAC5D,IAAI,CAAC,uBAAA,IAAI,yCAAS,CAAC,GAAG,CAAC,2BAA2B,CAAC,aAAa,CAAC,CAAC,EAAE;gBAClE,8EAA8E;gBAC9E,2DAA2D;gBAC3D,MAAM,MAAM,GAAG,IAAI,uBAAuB,CAAC;oBACzC,aAAa;oBACb,SAAS,EAAE,uBAAA,IAAI,2CAAW;iBAC3B,CAAC,CAAC;gBAEH,uBAAA,IAAI,yCAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;aACtC;SACF;KACF;AACH,CAAC,qFAGC,aAA8B;IAE9B,MAAM,MAAM,GAAG,uBAAA,IAAI,yCAAS,CAAC,GAAG,CAC9B,2BAA2B,CAAC,aAAa,CAAC,CAC3C,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;KAC3E;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type {\n MultichainAccountWalletId,\n AccountProvider,\n} from '@metamask/account-api';\nimport {\n MultichainAccountWallet,\n toMultichainAccountWalletId,\n type MultichainAccount,\n} from '@metamask/account-api';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport type {\n KeyringControllerState,\n KeyringObject,\n} from '@metamask/keyring-controller';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport { EvmAccountProvider } from './providers/EvmAccountProvider';\nimport { SolAccountProvider } from './providers/SolAccountProvider';\nimport type { MultichainAccountServiceMessenger } from './types';\n\n/**\n * The options that {@link MultichainAccountService} takes.\n */\ntype MultichainAccountServiceOptions = {\n messenger: MultichainAccountServiceMessenger;\n};\n\n/**\n * Select keyrings from keyring controller state.\n *\n * @param state - The keyring controller state.\n * @returns The keyrings.\n */\nfunction selectKeyringControllerKeyrings(state: KeyringControllerState) {\n return state.keyrings;\n}\n\n/**\n * Service to expose multichain accounts capabilities.\n */\nexport class MultichainAccountService {\n readonly #messenger: MultichainAccountServiceMessenger;\n\n readonly #providers: AccountProvider<InternalAccount>[];\n\n readonly #wallets: Map<\n MultichainAccountWalletId,\n MultichainAccountWallet<InternalAccount>\n >;\n\n /**\n * Constructs a new MultichainAccountService.\n *\n * @param options - The options.\n * @param options.messenger - The messenger suited to this\n * MultichainAccountService.\n */\n constructor({ messenger }: MultichainAccountServiceOptions) {\n this.#messenger = messenger;\n this.#wallets = new Map();\n // TODO: Rely on keyring capabilities once the keyring API is used by all keyrings.\n this.#providers = [\n new EvmAccountProvider(this.#messenger),\n new SolAccountProvider(this.#messenger),\n ];\n }\n\n /**\n * Initialize the service and constructs the internal reprensentation of\n * multichain accounts and wallets.\n */\n init(): void {\n // Gather all entropy sources first.\n const state = this.#messenger.call('KeyringController:getState');\n this.#setMultichainAccountWallets(state.keyrings);\n\n this.#messenger.subscribe(\n 'KeyringController:stateChange',\n (keyrings) => {\n this.#setMultichainAccountWallets(keyrings);\n },\n selectKeyringControllerKeyrings,\n );\n }\n\n #setMultichainAccountWallets(keyrings: KeyringObject[]) {\n for (const keyring of keyrings) {\n if (keyring.type === (KeyringTypes.hd as string)) {\n // Only HD keyrings have an entropy source/SRP.\n const entropySource = keyring.metadata.id;\n\n // Do not re-create wallets if they exists. Even if a keyrings got new accounts, this\n // will be handled by the `*AccountProvider`s which are always in-sync with their\n // keyrings and controllers (like the `AccountsController`).\n if (!this.#wallets.has(toMultichainAccountWalletId(entropySource))) {\n // This will automatically \"associate\" all multichain accounts for that wallet\n // (based on the accounts owned by each account providers).\n const wallet = new MultichainAccountWallet({\n entropySource,\n providers: this.#providers,\n });\n\n this.#wallets.set(wallet.id, wallet);\n }\n }\n }\n }\n\n #getWallet(\n entropySource: EntropySourceId,\n ): MultichainAccountWallet<InternalAccount> {\n const wallet = this.#wallets.get(\n toMultichainAccountWalletId(entropySource),\n );\n\n if (!wallet) {\n throw new Error('Unknown wallet, no wallet matching this entropy source');\n }\n\n return wallet;\n }\n\n /**\n * Gets a reference to the multichain account matching this entropy source and group index.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source of the multichain account.\n * @param options.groupIndex - The group index of the multichain account.\n * @throws If none multichain account match this entropy source and group index.\n * @returns A reference to the multichain account.\n */\n getMultichainAccount({\n entropySource,\n groupIndex,\n }: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): MultichainAccount<InternalAccount> {\n const multichainAccount =\n this.#getWallet(entropySource).getMultichainAccount(groupIndex);\n\n if (!multichainAccount) {\n throw new Error(`No multichain account for index: ${groupIndex}`);\n }\n\n return multichainAccount;\n }\n\n /**\n * Gets all multichain accounts for a given entropy source.\n *\n * @param options - Options.\n * @param options.entropySource - The entropy source to query.\n * @throws If no multichain accounts match this entropy source.\n * @returns A list of all multichain accounts.\n */\n getMultichainAccounts({\n entropySource,\n }: {\n entropySource: EntropySourceId;\n }): MultichainAccount<InternalAccount>[] {\n return this.#getWallet(entropySource).getMultichainAccounts();\n }\n}\n"]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MultichainAccountService = void 0;
|
|
4
|
+
var MultichainAccountService_1 = require("./MultichainAccountService.cjs");
|
|
5
|
+
Object.defineProperty(exports, "MultichainAccountService", { enumerable: true, get: function () { return MultichainAccountService_1.MultichainAccountService; } });
|
|
6
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAKA,2EAAsE;AAA7D,oIAAA,wBAAwB,OAAA","sourcesContent":["export type {\n MultichainAccountServiceActions,\n MultichainAccountServiceEvents,\n MultichainAccountServiceMessenger,\n} from './types';\nexport { MultichainAccountService } from './MultichainAccountService';\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,iCAAiC,GAClC,oBAAgB;AACjB,OAAO,EAAE,wBAAwB,EAAE,uCAAmC"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,iCAAiC,GAClC,oBAAgB;AACjB,OAAO,EAAE,wBAAwB,EAAE,uCAAmC"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,uCAAmC","sourcesContent":["export type {\n MultichainAccountServiceActions,\n MultichainAccountServiceEvents,\n MultichainAccountServiceMessenger,\n} from './types';\nexport { MultichainAccountService } from './MultichainAccountService';\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
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");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var _BaseAccountProvider_instances, _BaseAccountProvider_getAccounts;
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.BaseAccountProvider = exports.isBip44Account = void 0;
|
|
10
|
+
const keyring_api_1 = require("@metamask/keyring-api");
|
|
11
|
+
/**
|
|
12
|
+
* Checks if an account is BIP-44 compatible.
|
|
13
|
+
*
|
|
14
|
+
* @param account - The account to be tested.
|
|
15
|
+
* @returns True if the account is BIP-44 compatible.
|
|
16
|
+
*/
|
|
17
|
+
function isBip44Account(account) {
|
|
18
|
+
if (!account.options.entropy ||
|
|
19
|
+
account.options.entropy.type !== keyring_api_1.KeyringAccountEntropyTypeOption.Mnemonic) {
|
|
20
|
+
console.warn("! Found an HD account with invalid entropy options: account won't be associated to its wallet.");
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
exports.isBip44Account = isBip44Account;
|
|
26
|
+
class BaseAccountProvider {
|
|
27
|
+
constructor(messenger) {
|
|
28
|
+
_BaseAccountProvider_instances.add(this);
|
|
29
|
+
this.messenger = messenger;
|
|
30
|
+
}
|
|
31
|
+
getAccounts() {
|
|
32
|
+
return __classPrivateFieldGet(this, _BaseAccountProvider_instances, "m", _BaseAccountProvider_getAccounts).call(this);
|
|
33
|
+
}
|
|
34
|
+
getAccount(id) {
|
|
35
|
+
// TODO: Maybe just use a proper find for faster lookup?
|
|
36
|
+
const [found] = __classPrivateFieldGet(this, _BaseAccountProvider_instances, "m", _BaseAccountProvider_getAccounts).call(this, (account) => account.id === id);
|
|
37
|
+
if (!found) {
|
|
38
|
+
throw new Error(`Unable to find account: ${id}`);
|
|
39
|
+
}
|
|
40
|
+
return found;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.BaseAccountProvider = BaseAccountProvider;
|
|
44
|
+
_BaseAccountProvider_instances = new WeakSet(), _BaseAccountProvider_getAccounts = function _BaseAccountProvider_getAccounts(filter = () => true) {
|
|
45
|
+
const accounts = [];
|
|
46
|
+
for (const account of this.messenger.call(
|
|
47
|
+
// NOTE: Even though the name is misleading, this only fetches all internal
|
|
48
|
+
// accounts, including EVM and non-EVM. We might wanna change this action
|
|
49
|
+
// name once we fully support multichain accounts.
|
|
50
|
+
'AccountsController:listMultichainAccounts')) {
|
|
51
|
+
if (this.isAccountCompatible(account) &&
|
|
52
|
+
isBip44Account(account) &&
|
|
53
|
+
filter(account)) {
|
|
54
|
+
accounts.push(account);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return accounts;
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=BaseAccountProvider.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseAccountProvider.cjs","sourceRoot":"","sources":["../../src/providers/BaseAccountProvider.ts"],"names":[],"mappings":";;;;;;;;;AAMA,uDAAwE;AAWxE;;;;;GAKG;AACH,SAAgB,cAAc,CAC5B,OAAgB;IAEhB,IACE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO;QACxB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,6CAA+B,CAAC,QAAQ,EACzE;QACA,OAAO,CAAC,IAAI,CACV,gGAAgG,CACjG,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAdD,wCAcC;AAED,MAAsB,mBAAmB;IAKvC,YAAY,SAA4C;;QACtD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAyBD,WAAW;QACT,OAAO,uBAAA,IAAI,wEAAa,MAAjB,IAAI,CAAe,CAAC;IAC7B,CAAC;IAED,UAAU,CAAC,EAAa;QACtB,wDAAwD;QACxD,MAAM,CAAC,KAAK,CAAC,GAAG,uBAAA,IAAI,wEAAa,MAAjB,IAAI,EAAc,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAElE,IAAI,CAAC,KAAK,EAAE;YACV,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;SAClD;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CAGF;AAhDD,kDAgDC;6HAtCG,SAAgD,GAAG,EAAE,CAAC,IAAI;IAE1D,MAAM,QAAQ,GAAoC,EAAE,CAAC;IAErD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI;IACvC,2EAA2E;IAC3E,yEAAyE;IACzE,kDAAkD;IAClD,2CAA2C,CAC5C,EAAE;QACD,IACE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;YACjC,cAAc,CAAC,OAAO,CAAC;YACvB,MAAM,CAAC,OAAO,CAAC,EACf;YACA,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;SACxB;KACF;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["import type { AccountProvider } from '@metamask/account-api';\nimport type { AccountId } from '@metamask/accounts-controller';\nimport type {\n KeyringAccount,\n KeyringAccountEntropyMnemonicOptions,\n} from '@metamask/keyring-api';\nimport { KeyringAccountEntropyTypeOption } from '@metamask/keyring-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { MultichainAccountServiceMessenger } from '../types';\n\nexport type Bip44Account<Account extends KeyringAccount> = Account & {\n options: {\n entropy: KeyringAccountEntropyMnemonicOptions;\n };\n};\n\n/**\n * Checks if an account is BIP-44 compatible.\n *\n * @param account - The account to be tested.\n * @returns True if the account is BIP-44 compatible.\n */\nexport function isBip44Account<Account extends KeyringAccount>(\n account: Account,\n): account is Bip44Account<Account> {\n if (\n !account.options.entropy ||\n account.options.entropy.type !== KeyringAccountEntropyTypeOption.Mnemonic\n ) {\n console.warn(\n \"! Found an HD account with invalid entropy options: account won't be associated to its wallet.\",\n );\n return false;\n }\n\n return true;\n}\n\nexport abstract class BaseAccountProvider\n implements AccountProvider<InternalAccount>\n{\n protected readonly messenger: MultichainAccountServiceMessenger;\n\n constructor(messenger: MultichainAccountServiceMessenger) {\n this.messenger = messenger;\n }\n\n #getAccounts(\n filter: (account: InternalAccount) => boolean = () => true,\n ): Bip44Account<InternalAccount>[] {\n const accounts: Bip44Account<InternalAccount>[] = [];\n\n for (const account of this.messenger.call(\n // NOTE: Even though the name is misleading, this only fetches all internal\n // accounts, including EVM and non-EVM. We might wanna change this action\n // name once we fully support multichain accounts.\n 'AccountsController:listMultichainAccounts',\n )) {\n if (\n this.isAccountCompatible(account) &&\n isBip44Account(account) &&\n filter(account)\n ) {\n accounts.push(account);\n }\n }\n\n return accounts;\n }\n\n getAccounts(): InternalAccount[] {\n return this.#getAccounts();\n }\n\n getAccount(id: AccountId): InternalAccount {\n // TODO: Maybe just use a proper find for faster lookup?\n const [found] = this.#getAccounts((account) => account.id === id);\n\n if (!found) {\n throw new Error(`Unable to find account: ${id}`);\n }\n\n return found;\n }\n\n abstract isAccountCompatible(account: InternalAccount): boolean;\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AccountProvider } from "@metamask/account-api";
|
|
2
|
+
import type { AccountId } from "@metamask/accounts-controller";
|
|
3
|
+
import type { KeyringAccount, KeyringAccountEntropyMnemonicOptions } from "@metamask/keyring-api";
|
|
4
|
+
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
5
|
+
import type { MultichainAccountServiceMessenger } from "../types.cjs";
|
|
6
|
+
export type Bip44Account<Account extends KeyringAccount> = Account & {
|
|
7
|
+
options: {
|
|
8
|
+
entropy: KeyringAccountEntropyMnemonicOptions;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Checks if an account is BIP-44 compatible.
|
|
13
|
+
*
|
|
14
|
+
* @param account - The account to be tested.
|
|
15
|
+
* @returns True if the account is BIP-44 compatible.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isBip44Account<Account extends KeyringAccount>(account: Account): account is Bip44Account<Account>;
|
|
18
|
+
export declare abstract class BaseAccountProvider implements AccountProvider<InternalAccount> {
|
|
19
|
+
#private;
|
|
20
|
+
protected readonly messenger: MultichainAccountServiceMessenger;
|
|
21
|
+
constructor(messenger: MultichainAccountServiceMessenger);
|
|
22
|
+
getAccounts(): InternalAccount[];
|
|
23
|
+
getAccount(id: AccountId): InternalAccount;
|
|
24
|
+
abstract isAccountCompatible(account: InternalAccount): boolean;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=BaseAccountProvider.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseAccountProvider.d.cts","sourceRoot":"","sources":["../../src/providers/BaseAccountProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,sCAAsC;AAC/D,OAAO,KAAK,EACV,cAAc,EACd,oCAAoC,EACrC,8BAA8B;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAiB;AAElE,MAAM,MAAM,YAAY,CAAC,OAAO,SAAS,cAAc,IAAI,OAAO,GAAG;IACnE,OAAO,EAAE;QACP,OAAO,EAAE,oCAAoC,CAAC;KAC/C,CAAC;CACH,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAS,cAAc,EAC3D,OAAO,EAAE,OAAO,GACf,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,CAYlC;AAED,8BAAsB,mBACpB,YAAW,eAAe,CAAC,eAAe,CAAC;;IAE3C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,iCAAiC,CAAC;gBAEpD,SAAS,EAAE,iCAAiC;IA2BxD,WAAW,IAAI,eAAe,EAAE;IAIhC,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,eAAe;IAW1C,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO;CAChE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AccountProvider } from "@metamask/account-api";
|
|
2
|
+
import type { AccountId } from "@metamask/accounts-controller";
|
|
3
|
+
import type { KeyringAccount, KeyringAccountEntropyMnemonicOptions } from "@metamask/keyring-api";
|
|
4
|
+
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
5
|
+
import type { MultichainAccountServiceMessenger } from "../types.mjs";
|
|
6
|
+
export type Bip44Account<Account extends KeyringAccount> = Account & {
|
|
7
|
+
options: {
|
|
8
|
+
entropy: KeyringAccountEntropyMnemonicOptions;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Checks if an account is BIP-44 compatible.
|
|
13
|
+
*
|
|
14
|
+
* @param account - The account to be tested.
|
|
15
|
+
* @returns True if the account is BIP-44 compatible.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isBip44Account<Account extends KeyringAccount>(account: Account): account is Bip44Account<Account>;
|
|
18
|
+
export declare abstract class BaseAccountProvider implements AccountProvider<InternalAccount> {
|
|
19
|
+
#private;
|
|
20
|
+
protected readonly messenger: MultichainAccountServiceMessenger;
|
|
21
|
+
constructor(messenger: MultichainAccountServiceMessenger);
|
|
22
|
+
getAccounts(): InternalAccount[];
|
|
23
|
+
getAccount(id: AccountId): InternalAccount;
|
|
24
|
+
abstract isAccountCompatible(account: InternalAccount): boolean;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=BaseAccountProvider.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/BaseAccountProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,8BAA8B;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,sCAAsC;AAC/D,OAAO,KAAK,EACV,cAAc,EACd,oCAAoC,EACrC,8BAA8B;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAiB;AAElE,MAAM,MAAM,YAAY,CAAC,OAAO,SAAS,cAAc,IAAI,OAAO,GAAG;IACnE,OAAO,EAAE;QACP,OAAO,EAAE,oCAAoC,CAAC;KAC/C,CAAC;CACH,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAS,cAAc,EAC3D,OAAO,EAAE,OAAO,GACf,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,CAYlC;AAED,8BAAsB,mBACpB,YAAW,eAAe,CAAC,eAAe,CAAC;;IAE3C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,iCAAiC,CAAC;gBAEpD,SAAS,EAAE,iCAAiC;IA2BxD,WAAW,IAAI,eAAe,EAAE;IAIhC,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,eAAe;IAW1C,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO;CAChE"}
|