@metamask/assets-controllers 55.0.1 → 57.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -1
- package/README.md +1 -0
- package/dist/AccountTrackerController.cjs +7 -25
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts +5 -10
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts +5 -10
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +7 -25
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/CurrencyRateController.cjs +3 -0
- package/dist/CurrencyRateController.cjs.map +1 -1
- package/dist/CurrencyRateController.d.cts +1 -1
- package/dist/CurrencyRateController.d.cts.map +1 -1
- package/dist/CurrencyRateController.d.mts +1 -1
- package/dist/CurrencyRateController.d.mts.map +1 -1
- package/dist/CurrencyRateController.mjs +3 -0
- package/dist/CurrencyRateController.mjs.map +1 -1
- package/dist/DeFiPositionsController/DeFiPositionsController.cjs +126 -0
- package/dist/DeFiPositionsController/DeFiPositionsController.cjs.map +1 -0
- package/dist/DeFiPositionsController/DeFiPositionsController.d.cts +72 -0
- package/dist/DeFiPositionsController/DeFiPositionsController.d.cts.map +1 -0
- package/dist/DeFiPositionsController/DeFiPositionsController.d.mts +72 -0
- package/dist/DeFiPositionsController/DeFiPositionsController.d.mts.map +1 -0
- package/dist/DeFiPositionsController/DeFiPositionsController.mjs +121 -0
- package/dist/DeFiPositionsController/DeFiPositionsController.mjs.map +1 -0
- package/dist/DeFiPositionsController/fetch-positions.cjs +21 -0
- package/dist/DeFiPositionsController/fetch-positions.cjs.map +1 -0
- package/dist/DeFiPositionsController/fetch-positions.d.cts +59 -0
- package/dist/DeFiPositionsController/fetch-positions.d.cts.map +1 -0
- package/dist/DeFiPositionsController/fetch-positions.d.mts +59 -0
- package/dist/DeFiPositionsController/fetch-positions.d.mts.map +1 -0
- package/dist/DeFiPositionsController/fetch-positions.mjs +17 -0
- package/dist/DeFiPositionsController/fetch-positions.mjs.map +1 -0
- package/dist/DeFiPositionsController/group-defi-positions.cjs +96 -0
- package/dist/DeFiPositionsController/group-defi-positions.cjs.map +1 -0
- package/dist/DeFiPositionsController/group-defi-positions.d.cts +36 -0
- package/dist/DeFiPositionsController/group-defi-positions.d.cts.map +1 -0
- package/dist/DeFiPositionsController/group-defi-positions.d.mts +36 -0
- package/dist/DeFiPositionsController/group-defi-positions.d.mts.map +1 -0
- package/dist/DeFiPositionsController/group-defi-positions.mjs +92 -0
- package/dist/DeFiPositionsController/group-defi-positions.mjs.map +1 -0
- package/dist/TokenListController.cjs +0 -13
- package/dist/TokenListController.cjs.map +1 -1
- package/dist/TokenListController.d.cts +0 -1
- package/dist/TokenListController.d.cts.map +1 -1
- package/dist/TokenListController.d.mts +0 -1
- package/dist/TokenListController.d.mts.map +1 -1
- package/dist/TokenListController.mjs +0 -13
- package/dist/TokenListController.mjs.map +1 -1
- package/dist/TokenRatesController.cjs +5 -1
- package/dist/TokenRatesController.cjs.map +1 -1
- package/dist/TokenRatesController.d.cts.map +1 -1
- package/dist/TokenRatesController.d.mts.map +1 -1
- package/dist/TokenRatesController.mjs +5 -1
- package/dist/TokenRatesController.mjs.map +1 -1
- package/dist/TokensController.cjs +35 -78
- package/dist/TokensController.cjs.map +1 -1
- package/dist/TokensController.d.cts +0 -6
- package/dist/TokensController.d.cts.map +1 -1
- package/dist/TokensController.d.mts +0 -6
- package/dist/TokensController.d.mts.map +1 -1
- package/dist/TokensController.mjs +36 -78
- package/dist/TokensController.mjs.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyRateController.cjs","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":";;;AAKA,iEAGoC;AAEpC,qEAA+E;AAC/E,6CAAoC;AAEpC,+EAAmG;AAsBnG,MAAM,IAAI,GAAG,wBAAwB,CAAC;AA0BtC,MAAM,QAAQ,GAAG;IACf,eAAe,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IACnD,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;CAClD,CAAC;AAEF,MAAM,YAAY,GAAG;IACnB,eAAe,EAAE,KAAK;IACtB,aAAa,EAAE;QACb,GAAG,EAAE;YACH,cAAc,EAAE,CAAC;YACjB,cAAc,EAAE,CAAC;YACjB,iBAAiB,EAAE,IAAI;SACxB;KACF;CACF,CAAC;AAOF;;;GAGG;AACH,MAAa,sBAAuB,SAAQ,IAAA,oDAA+B,GAI1E;IAOC;;;;;;;;;OASG;IACH,YAAY,EACV,cAAc,GAAG,KAAK,EACtB,QAAQ,GAAG,MAAM,EACjB,SAAS,EACT,KAAK,EACL,sBAAsB,GAAG,+CAA6B,GAOvD;QACC,KAAK,CAAC;YACJ,IAAI;YACJ,QAAQ;YACR,SAAS;YACT,KAAK,EAAE,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE;SACrC,CAAC,CAAC;QAlCY,UAAK,GAAG,IAAI,mBAAK,EAAE,CAAC;QAmCnC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,sBAAsB,GAAG,sBAAsB,CAAC;IACvD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,kBAAkB,CAAC,eAAuB;QAC9C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC/C,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC/D,IAAI;YACF,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;gBACf,OAAO;oBACL,GAAG,YAAY;oBACf,eAAe;iBAChB,CAAC;YACJ,CAAC,CAAC,CAAC;SACJ;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;QACD,gFAAgF;QAChF,mEAAmE;QACnE,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,kBAAkB,CAAC,gBAA0B;QACjD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC/C,IAAI;YACF,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YAEvC,wFAAwF;YACxF,kEAAkE;YAClE,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,yCAAsB,CAAC,CAAC;YAC7D,MAAM,uBAAuB,GAAG,gBAAgB,CAAC,MAAM,CACrD,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE;gBACtB,GAAG,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,cAAc,CAAC;oBAC3D,CAAC,CAAC,wCAAqB;oBACvB,CAAC,CAAC,cAAc,CAAC;gBACnB,OAAO,GAAG,CAAC;YACb,CAAC,EACD,EAA4B,CAC7B,CAAC;YAEF,MAAM,yBAAyB,GAAG,MAAM,IAAI,CAAC,sBAAsB,CACjE,eAAe,EACf,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC,EACpD,IAAI,CAAC,cAAc,CACpB,CAAC;YAEF,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAC1D,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC,EAAE,EAAE;gBACzC,MAAM,IAAI,GAAG,yBAAyB,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC,CAAC;gBACtE,GAAG,CAAC,cAAc,CAAC,GAAG;oBACpB,cAAc,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI;oBAC7D,cAAc,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI;oBAC7D,iBAAiB,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI;iBACrC,CAAC;gBACF,OAAO,GAAG,CAAC;YACb,CAAC,EACD,EAAwC,CACzC,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,aAAa,GAAG;oBACpB,GAAG,KAAK,CAAC,aAAa;oBACtB,GAAG,KAAK;iBACT,CAAC;YACJ,CAAC,CAAC,CAAC;SACJ;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;YACxD,MAAM,KAAK,CAAC;SACb;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;IAED;;;;OAIG;IACM,OAAO;QACd,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,EACjB,gBAAgB,GACS;QACzB,MAAM,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAClD,CAAC;CACF;AAjJD,wDAiJC;AAED,kBAAe,sBAAsB,CAAC","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { Mutex } from 'async-mutex';\n\nimport { fetchMultiExchangeRate as defaultFetchMultiExchangeRate } from './crypto-compare-service';\n\n/**\n * @type CurrencyRateState\n * @property currencyRates - Object keyed by native currency\n * @property currencyRates.conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property currencyRates.conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n currentCurrency: string;\n currencyRates: Record<\n string,\n {\n conversionDate: number | null;\n conversionRate: number | null;\n usdConversionRate: number | null;\n }\n >;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = ControllerStateChangeEvent<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerEvents = CurrencyRateStateChange;\n\nexport type GetCurrencyRateState = ControllerGetStateAction<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerActions = GetCurrencyRateState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype CurrencyRateMessenger = RestrictedMessenger<\n typeof name,\n CurrencyRateControllerActions | AllowedActions,\n CurrencyRateControllerEvents,\n AllowedActions['type'],\n never\n>;\n\nconst metadata = {\n currentCurrency: { persist: true, anonymous: true },\n currencyRates: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n currentCurrency: 'usd',\n currencyRates: {\n ETH: {\n conversionDate: 0,\n conversionRate: 0,\n usdConversionRate: null,\n },\n },\n};\n\n/** The input to start polling for the {@link CurrencyRateController} */\ntype CurrencyRatePollingInput = {\n nativeCurrencies: string[];\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends StaticIntervalPollingController<CurrencyRatePollingInput>()<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private readonly mutex = new Mutex();\n\n private readonly fetchMultiExchangeRate;\n\n private readonly includeUsdRate;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchMultiExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchMultiExchangeRate = defaultFetchMultiExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchMultiExchangeRate?: typeof defaultFetchMultiExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.setIntervalLength(interval);\n this.fetchMultiExchangeRate = fetchMultiExchangeRate;\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n const releaseLock = await this.mutex.acquire();\n const nativeCurrencies = Object.keys(this.state.currencyRates);\n try {\n this.update(() => {\n return {\n ...defaultState,\n currentCurrency,\n };\n });\n } finally {\n releaseLock();\n }\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updateExchangeRate(nativeCurrencies);\n }\n\n /**\n * Updates the exchange rate for the current currency and native currency pairs.\n *\n * @param nativeCurrencies - The native currency symbols to fetch exchange rates for.\n */\n async updateExchangeRate(nativeCurrencies: string[]): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { currentCurrency } = this.state;\n\n // For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.\n // Map each native currency to the symbol we want to fetch for it.\n const testnetSymbols = Object.values(TESTNET_TICKER_SYMBOLS);\n const nativeCurrenciesToFetch = nativeCurrencies.reduce(\n (acc, nativeCurrency) => {\n acc[nativeCurrency] = testnetSymbols.includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY\n : nativeCurrency;\n return acc;\n },\n {} as Record<string, string>,\n );\n\n const fetchExchangeRateResponse = await this.fetchMultiExchangeRate(\n currentCurrency,\n [...new Set(Object.values(nativeCurrenciesToFetch))],\n this.includeUsdRate,\n );\n\n const rates = Object.entries(nativeCurrenciesToFetch).reduce(\n (acc, [nativeCurrency, fetchedCurrency]) => {\n const rate = fetchExchangeRateResponse[fetchedCurrency.toLowerCase()];\n acc[nativeCurrency] = {\n conversionDate: rate !== undefined ? Date.now() / 1000 : null,\n conversionRate: rate?.[currentCurrency.toLowerCase()] ?? null,\n usdConversionRate: rate?.usd ?? null,\n };\n return acc;\n },\n {} as CurrencyRateState['currencyRates'],\n );\n\n this.update((state) => {\n state.currencyRates = {\n ...state.currencyRates,\n ...rates,\n };\n });\n } catch (error) {\n console.error('Failed to fetch exchange rates.', error);\n throw error;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopAllPolling();\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @param input - The input for the poll.\n * @param input.nativeCurrencies - The native currency symbols to poll prices for.\n */\n async _executePoll({\n nativeCurrencies,\n }: CurrencyRatePollingInput): Promise<void> {\n await this.updateExchangeRate(nativeCurrencies);\n }\n}\n\nexport default CurrencyRateController;\n"]}
|
|
1
|
+
{"version":3,"file":"CurrencyRateController.cjs","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { Mutex } from 'async-mutex';\n\nimport { fetchMultiExchangeRate as defaultFetchMultiExchangeRate } from './crypto-compare-service';\n\n/**\n * @type CurrencyRateState\n * @property currencyRates - Object keyed by native currency\n * @property currencyRates.conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property currencyRates.conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n currentCurrency: string;\n currencyRates: Record<\n string,\n {\n conversionDate: number | null;\n conversionRate: number | null;\n usdConversionRate: number | null;\n }\n >;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = ControllerStateChangeEvent<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerEvents = CurrencyRateStateChange;\n\nexport type GetCurrencyRateState = ControllerGetStateAction<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerActions = GetCurrencyRateState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype CurrencyRateMessenger = RestrictedMessenger<\n typeof name,\n CurrencyRateControllerActions | AllowedActions,\n CurrencyRateControllerEvents,\n AllowedActions['type'],\n never\n>;\n\nconst metadata = {\n currentCurrency: { persist: true, anonymous: true },\n currencyRates: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n currentCurrency: 'usd',\n currencyRates: {\n ETH: {\n conversionDate: 0,\n conversionRate: 0,\n usdConversionRate: null,\n },\n },\n};\n\n/** The input to start polling for the {@link CurrencyRateController} */\ntype CurrencyRatePollingInput = {\n nativeCurrencies: string[];\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends StaticIntervalPollingController<CurrencyRatePollingInput>()<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private readonly mutex = new Mutex();\n\n private readonly fetchMultiExchangeRate;\n\n private readonly includeUsdRate;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchMultiExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchMultiExchangeRate = defaultFetchMultiExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchMultiExchangeRate?: typeof defaultFetchMultiExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.setIntervalLength(interval);\n this.fetchMultiExchangeRate = fetchMultiExchangeRate;\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n const releaseLock = await this.mutex.acquire();\n const nativeCurrencies = Object.keys(this.state.currencyRates);\n try {\n this.update(() => {\n return {\n ...defaultState,\n currentCurrency,\n };\n });\n } finally {\n releaseLock();\n }\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updateExchangeRate(nativeCurrencies);\n }\n\n /**\n * Updates the exchange rate for the current currency and native currency pairs.\n *\n * @param nativeCurrencies - The native currency symbols to fetch exchange rates for.\n */\n async updateExchangeRate(\n nativeCurrencies: (string | undefined)[],\n ): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { currentCurrency } = this.state;\n\n // For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.\n // Map each native currency to the symbol we want to fetch for it.\n const testnetSymbols = Object.values(TESTNET_TICKER_SYMBOLS);\n const nativeCurrenciesToFetch = nativeCurrencies.reduce(\n (acc, nativeCurrency) => {\n if (!nativeCurrency) {\n return acc;\n }\n\n acc[nativeCurrency] = testnetSymbols.includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY\n : nativeCurrency;\n return acc;\n },\n {} as Record<string, string>,\n );\n\n const fetchExchangeRateResponse = await this.fetchMultiExchangeRate(\n currentCurrency,\n [...new Set(Object.values(nativeCurrenciesToFetch))],\n this.includeUsdRate,\n );\n\n const rates = Object.entries(nativeCurrenciesToFetch).reduce(\n (acc, [nativeCurrency, fetchedCurrency]) => {\n const rate = fetchExchangeRateResponse[fetchedCurrency.toLowerCase()];\n acc[nativeCurrency] = {\n conversionDate: rate !== undefined ? Date.now() / 1000 : null,\n conversionRate: rate?.[currentCurrency.toLowerCase()] ?? null,\n usdConversionRate: rate?.usd ?? null,\n };\n return acc;\n },\n {} as CurrencyRateState['currencyRates'],\n );\n\n this.update((state) => {\n state.currencyRates = {\n ...state.currencyRates,\n ...rates,\n };\n });\n } catch (error) {\n console.error('Failed to fetch exchange rates.', error);\n throw error;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopAllPolling();\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @param input - The input for the poll.\n * @param input.nativeCurrencies - The native currency symbols to poll prices for.\n */\n async _executePoll({\n nativeCurrencies,\n }: CurrencyRatePollingInput): Promise<void> {\n await this.updateExchangeRate(nativeCurrencies);\n }\n}\n\nexport default CurrencyRateController;\n"]}
|
|
@@ -79,7 +79,7 @@ export declare class CurrencyRateController extends CurrencyRateController_base<
|
|
|
79
79
|
*
|
|
80
80
|
* @param nativeCurrencies - The native currency symbols to fetch exchange rates for.
|
|
81
81
|
*/
|
|
82
|
-
updateExchangeRate(nativeCurrencies: string[]): Promise<void>;
|
|
82
|
+
updateExchangeRate(nativeCurrencies: (string | undefined)[]): Promise<void>;
|
|
83
83
|
/**
|
|
84
84
|
* Prepare to discard this controller.
|
|
85
85
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyRateController.d.cts","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AAKnC,OAAO,KAAK,EAAE,2CAA2C,EAAE,qCAAqC;AAIhG,OAAO,EAAE,sBAAsB,IAAI,6BAA6B,EAAE,2CAAiC;AAEnG;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CACnB,MAAM,EACN;QACE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CACF,CAAC;CACH,CAAC;AAEF,QAAA,MAAM,IAAI,2BAA2B,CAAC;AAEtC,MAAM,MAAM,uBAAuB,GAAG,0BAA0B,CAC9D,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,uBAAuB,CAAC;AAEnE,MAAM,MAAM,oBAAoB,GAAG,wBAAwB,CACzD,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAEjE,KAAK,cAAc,GAAG,2CAA2C,CAAC;AAElE,KAAK,qBAAqB,GAAG,mBAAmB,CAC9C,OAAO,IAAI,EACX,6BAA6B,GAAG,cAAc,EAC9C,4BAA4B,EAC5B,cAAc,CAAC,MAAM,CAAC,EACtB,KAAK,CACN,CAAC;AAkBF,wEAAwE;AACxE,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,4BAC1C,OAAO,IAAI,EACX,iBAAiB,EACjB,qBAAqB,CACtB;IACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAExC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAEhC;;;;;;;;;OASG;gBACS,EACV,cAAsB,EACtB,QAAiB,EACjB,SAAS,EACT,KAAK,EACL,sBAAsD,GACvD,EAAE;QACD,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,qBAAqB,CAAC;QACjC,KAAK,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACnC,sBAAsB,CAAC,EAAE,OAAO,6BAA6B,CAAC;KAC/D;IAYD;;;;OAIG;IACG,kBAAkB,CAAC,eAAe,EAAE,MAAM;IAkBhD;;;;OAIG;IACG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"CurrencyRateController.d.cts","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AAKnC,OAAO,KAAK,EAAE,2CAA2C,EAAE,qCAAqC;AAIhG,OAAO,EAAE,sBAAsB,IAAI,6BAA6B,EAAE,2CAAiC;AAEnG;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CACnB,MAAM,EACN;QACE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CACF,CAAC;CACH,CAAC;AAEF,QAAA,MAAM,IAAI,2BAA2B,CAAC;AAEtC,MAAM,MAAM,uBAAuB,GAAG,0BAA0B,CAC9D,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,uBAAuB,CAAC;AAEnE,MAAM,MAAM,oBAAoB,GAAG,wBAAwB,CACzD,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAEjE,KAAK,cAAc,GAAG,2CAA2C,CAAC;AAElE,KAAK,qBAAqB,GAAG,mBAAmB,CAC9C,OAAO,IAAI,EACX,6BAA6B,GAAG,cAAc,EAC9C,4BAA4B,EAC5B,cAAc,CAAC,MAAM,CAAC,EACtB,KAAK,CACN,CAAC;AAkBF,wEAAwE;AACxE,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,4BAC1C,OAAO,IAAI,EACX,iBAAiB,EACjB,qBAAqB,CACtB;IACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAExC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAEhC;;;;;;;;;OASG;gBACS,EACV,cAAsB,EACtB,QAAiB,EACjB,SAAS,EACT,KAAK,EACL,sBAAsD,GACvD,EAAE;QACD,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,qBAAqB,CAAC;QACjC,KAAK,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACnC,sBAAsB,CAAC,EAAE,OAAO,6BAA6B,CAAC;KAC/D;IAYD;;;;OAIG;IACG,kBAAkB,CAAC,eAAe,EAAE,MAAM;IAkBhD;;;;OAIG;IACG,kBAAkB,CACtB,gBAAgB,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GACvC,OAAO,CAAC,IAAI,CAAC;IAuDhB;;;;OAIG;IACM,OAAO;IAKhB;;;;;OAKG;IACG,YAAY,CAAC,EACjB,gBAAgB,GACjB,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;CAG5C;AAED,eAAe,sBAAsB,CAAC"}
|
|
@@ -79,7 +79,7 @@ export declare class CurrencyRateController extends CurrencyRateController_base<
|
|
|
79
79
|
*
|
|
80
80
|
* @param nativeCurrencies - The native currency symbols to fetch exchange rates for.
|
|
81
81
|
*/
|
|
82
|
-
updateExchangeRate(nativeCurrencies: string[]): Promise<void>;
|
|
82
|
+
updateExchangeRate(nativeCurrencies: (string | undefined)[]): Promise<void>;
|
|
83
83
|
/**
|
|
84
84
|
* Prepare to discard this controller.
|
|
85
85
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyRateController.d.mts","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AAKnC,OAAO,KAAK,EAAE,2CAA2C,EAAE,qCAAqC;AAIhG,OAAO,EAAE,sBAAsB,IAAI,6BAA6B,EAAE,2CAAiC;AAEnG;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CACnB,MAAM,EACN;QACE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CACF,CAAC;CACH,CAAC;AAEF,QAAA,MAAM,IAAI,2BAA2B,CAAC;AAEtC,MAAM,MAAM,uBAAuB,GAAG,0BAA0B,CAC9D,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,uBAAuB,CAAC;AAEnE,MAAM,MAAM,oBAAoB,GAAG,wBAAwB,CACzD,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAEjE,KAAK,cAAc,GAAG,2CAA2C,CAAC;AAElE,KAAK,qBAAqB,GAAG,mBAAmB,CAC9C,OAAO,IAAI,EACX,6BAA6B,GAAG,cAAc,EAC9C,4BAA4B,EAC5B,cAAc,CAAC,MAAM,CAAC,EACtB,KAAK,CACN,CAAC;AAkBF,wEAAwE;AACxE,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,4BAC1C,OAAO,IAAI,EACX,iBAAiB,EACjB,qBAAqB,CACtB;IACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAExC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAEhC;;;;;;;;;OASG;gBACS,EACV,cAAsB,EACtB,QAAiB,EACjB,SAAS,EACT,KAAK,EACL,sBAAsD,GACvD,EAAE;QACD,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,qBAAqB,CAAC;QACjC,KAAK,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACnC,sBAAsB,CAAC,EAAE,OAAO,6BAA6B,CAAC;KAC/D;IAYD;;;;OAIG;IACG,kBAAkB,CAAC,eAAe,EAAE,MAAM;IAkBhD;;;;OAIG;IACG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"CurrencyRateController.d.mts","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AAKnC,OAAO,KAAK,EAAE,2CAA2C,EAAE,qCAAqC;AAIhG,OAAO,EAAE,sBAAsB,IAAI,6BAA6B,EAAE,2CAAiC;AAEnG;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CACnB,MAAM,EACN;QACE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;KAClC,CACF,CAAC;CACH,CAAC;AAEF,QAAA,MAAM,IAAI,2BAA2B,CAAC;AAEtC,MAAM,MAAM,uBAAuB,GAAG,0BAA0B,CAC9D,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,uBAAuB,CAAC;AAEnE,MAAM,MAAM,oBAAoB,GAAG,wBAAwB,CACzD,OAAO,IAAI,EACX,iBAAiB,CAClB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,oBAAoB,CAAC;AAEjE,KAAK,cAAc,GAAG,2CAA2C,CAAC;AAElE,KAAK,qBAAqB,GAAG,mBAAmB,CAC9C,OAAO,IAAI,EACX,6BAA6B,GAAG,cAAc,EAC9C,4BAA4B,EAC5B,cAAc,CAAC,MAAM,CAAC,EACtB,KAAK,CACN,CAAC;AAkBF,wEAAwE;AACxE,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,4BAC1C,OAAO,IAAI,EACX,iBAAiB,EACjB,qBAAqB,CACtB;IACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAExC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAEhC;;;;;;;;;OASG;gBACS,EACV,cAAsB,EACtB,QAAiB,EACjB,SAAS,EACT,KAAK,EACL,sBAAsD,GACvD,EAAE;QACD,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,qBAAqB,CAAC;QACjC,KAAK,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACnC,sBAAsB,CAAC,EAAE,OAAO,6BAA6B,CAAC;KAC/D;IAYD;;;;OAIG;IACG,kBAAkB,CAAC,eAAe,EAAE,MAAM;IAkBhD;;;;OAIG;IACG,kBAAkB,CACtB,gBAAgB,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GACvC,OAAO,CAAC,IAAI,CAAC;IAuDhB;;;;OAIG;IACM,OAAO;IAKhB;;;;;OAKG;IACG,YAAY,CAAC,EACjB,gBAAgB,GACjB,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;CAG5C;AAED,eAAe,sBAAsB,CAAC"}
|
|
@@ -80,6 +80,9 @@ export class CurrencyRateController extends StaticIntervalPollingController() {
|
|
|
80
80
|
// Map each native currency to the symbol we want to fetch for it.
|
|
81
81
|
const testnetSymbols = Object.values(TESTNET_TICKER_SYMBOLS);
|
|
82
82
|
const nativeCurrenciesToFetch = nativeCurrencies.reduce((acc, nativeCurrency) => {
|
|
83
|
+
if (!nativeCurrency) {
|
|
84
|
+
return acc;
|
|
85
|
+
}
|
|
83
86
|
acc[nativeCurrency] = testnetSymbols.includes(nativeCurrency)
|
|
84
87
|
? FALL_BACK_VS_CURRENCY
|
|
85
88
|
: nativeCurrency;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyRateController.mjs","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { Mutex } from 'async-mutex';\n\nimport { fetchMultiExchangeRate as defaultFetchMultiExchangeRate } from './crypto-compare-service';\n\n/**\n * @type CurrencyRateState\n * @property currencyRates - Object keyed by native currency\n * @property currencyRates.conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property currencyRates.conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n currentCurrency: string;\n currencyRates: Record<\n string,\n {\n conversionDate: number | null;\n conversionRate: number | null;\n usdConversionRate: number | null;\n }\n >;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = ControllerStateChangeEvent<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerEvents = CurrencyRateStateChange;\n\nexport type GetCurrencyRateState = ControllerGetStateAction<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerActions = GetCurrencyRateState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype CurrencyRateMessenger = RestrictedMessenger<\n typeof name,\n CurrencyRateControllerActions | AllowedActions,\n CurrencyRateControllerEvents,\n AllowedActions['type'],\n never\n>;\n\nconst metadata = {\n currentCurrency: { persist: true, anonymous: true },\n currencyRates: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n currentCurrency: 'usd',\n currencyRates: {\n ETH: {\n conversionDate: 0,\n conversionRate: 0,\n usdConversionRate: null,\n },\n },\n};\n\n/** The input to start polling for the {@link CurrencyRateController} */\ntype CurrencyRatePollingInput = {\n nativeCurrencies: string[];\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends StaticIntervalPollingController<CurrencyRatePollingInput>()<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private readonly mutex = new Mutex();\n\n private readonly fetchMultiExchangeRate;\n\n private readonly includeUsdRate;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchMultiExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchMultiExchangeRate = defaultFetchMultiExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchMultiExchangeRate?: typeof defaultFetchMultiExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.setIntervalLength(interval);\n this.fetchMultiExchangeRate = fetchMultiExchangeRate;\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n const releaseLock = await this.mutex.acquire();\n const nativeCurrencies = Object.keys(this.state.currencyRates);\n try {\n this.update(() => {\n return {\n ...defaultState,\n currentCurrency,\n };\n });\n } finally {\n releaseLock();\n }\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updateExchangeRate(nativeCurrencies);\n }\n\n /**\n * Updates the exchange rate for the current currency and native currency pairs.\n *\n * @param nativeCurrencies - The native currency symbols to fetch exchange rates for.\n */\n async updateExchangeRate(nativeCurrencies: string[]): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { currentCurrency } = this.state;\n\n // For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.\n // Map each native currency to the symbol we want to fetch for it.\n const testnetSymbols = Object.values(TESTNET_TICKER_SYMBOLS);\n const nativeCurrenciesToFetch = nativeCurrencies.reduce(\n (acc, nativeCurrency) => {\n acc[nativeCurrency] = testnetSymbols.includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY\n : nativeCurrency;\n return acc;\n },\n {} as Record<string, string>,\n );\n\n const fetchExchangeRateResponse = await this.fetchMultiExchangeRate(\n currentCurrency,\n [...new Set(Object.values(nativeCurrenciesToFetch))],\n this.includeUsdRate,\n );\n\n const rates = Object.entries(nativeCurrenciesToFetch).reduce(\n (acc, [nativeCurrency, fetchedCurrency]) => {\n const rate = fetchExchangeRateResponse[fetchedCurrency.toLowerCase()];\n acc[nativeCurrency] = {\n conversionDate: rate !== undefined ? Date.now() / 1000 : null,\n conversionRate: rate?.[currentCurrency.toLowerCase()] ?? null,\n usdConversionRate: rate?.usd ?? null,\n };\n return acc;\n },\n {} as CurrencyRateState['currencyRates'],\n );\n\n this.update((state) => {\n state.currencyRates = {\n ...state.currencyRates,\n ...rates,\n };\n });\n } catch (error) {\n console.error('Failed to fetch exchange rates.', error);\n throw error;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopAllPolling();\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @param input - The input for the poll.\n * @param input.nativeCurrencies - The native currency symbols to poll prices for.\n */\n async _executePoll({\n nativeCurrencies,\n }: CurrencyRatePollingInput): Promise<void> {\n await this.updateExchangeRate(nativeCurrencies);\n }\n}\n\nexport default CurrencyRateController;\n"]}
|
|
1
|
+
{"version":3,"file":"CurrencyRateController.mjs","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { Mutex } from 'async-mutex';\n\nimport { fetchMultiExchangeRate as defaultFetchMultiExchangeRate } from './crypto-compare-service';\n\n/**\n * @type CurrencyRateState\n * @property currencyRates - Object keyed by native currency\n * @property currencyRates.conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property currencyRates.conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n currentCurrency: string;\n currencyRates: Record<\n string,\n {\n conversionDate: number | null;\n conversionRate: number | null;\n usdConversionRate: number | null;\n }\n >;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = ControllerStateChangeEvent<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerEvents = CurrencyRateStateChange;\n\nexport type GetCurrencyRateState = ControllerGetStateAction<\n typeof name,\n CurrencyRateState\n>;\n\nexport type CurrencyRateControllerActions = GetCurrencyRateState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype CurrencyRateMessenger = RestrictedMessenger<\n typeof name,\n CurrencyRateControllerActions | AllowedActions,\n CurrencyRateControllerEvents,\n AllowedActions['type'],\n never\n>;\n\nconst metadata = {\n currentCurrency: { persist: true, anonymous: true },\n currencyRates: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n currentCurrency: 'usd',\n currencyRates: {\n ETH: {\n conversionDate: 0,\n conversionRate: 0,\n usdConversionRate: null,\n },\n },\n};\n\n/** The input to start polling for the {@link CurrencyRateController} */\ntype CurrencyRatePollingInput = {\n nativeCurrencies: string[];\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends StaticIntervalPollingController<CurrencyRatePollingInput>()<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private readonly mutex = new Mutex();\n\n private readonly fetchMultiExchangeRate;\n\n private readonly includeUsdRate;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchMultiExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchMultiExchangeRate = defaultFetchMultiExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchMultiExchangeRate?: typeof defaultFetchMultiExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.setIntervalLength(interval);\n this.fetchMultiExchangeRate = fetchMultiExchangeRate;\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n const releaseLock = await this.mutex.acquire();\n const nativeCurrencies = Object.keys(this.state.currencyRates);\n try {\n this.update(() => {\n return {\n ...defaultState,\n currentCurrency,\n };\n });\n } finally {\n releaseLock();\n }\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updateExchangeRate(nativeCurrencies);\n }\n\n /**\n * Updates the exchange rate for the current currency and native currency pairs.\n *\n * @param nativeCurrencies - The native currency symbols to fetch exchange rates for.\n */\n async updateExchangeRate(\n nativeCurrencies: (string | undefined)[],\n ): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n const { currentCurrency } = this.state;\n\n // For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.\n // Map each native currency to the symbol we want to fetch for it.\n const testnetSymbols = Object.values(TESTNET_TICKER_SYMBOLS);\n const nativeCurrenciesToFetch = nativeCurrencies.reduce(\n (acc, nativeCurrency) => {\n if (!nativeCurrency) {\n return acc;\n }\n\n acc[nativeCurrency] = testnetSymbols.includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY\n : nativeCurrency;\n return acc;\n },\n {} as Record<string, string>,\n );\n\n const fetchExchangeRateResponse = await this.fetchMultiExchangeRate(\n currentCurrency,\n [...new Set(Object.values(nativeCurrenciesToFetch))],\n this.includeUsdRate,\n );\n\n const rates = Object.entries(nativeCurrenciesToFetch).reduce(\n (acc, [nativeCurrency, fetchedCurrency]) => {\n const rate = fetchExchangeRateResponse[fetchedCurrency.toLowerCase()];\n acc[nativeCurrency] = {\n conversionDate: rate !== undefined ? Date.now() / 1000 : null,\n conversionRate: rate?.[currentCurrency.toLowerCase()] ?? null,\n usdConversionRate: rate?.usd ?? null,\n };\n return acc;\n },\n {} as CurrencyRateState['currencyRates'],\n );\n\n this.update((state) => {\n state.currencyRates = {\n ...state.currencyRates,\n ...rates,\n };\n });\n } catch (error) {\n console.error('Failed to fetch exchange rates.', error);\n throw error;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopAllPolling();\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @param input - The input for the poll.\n * @param input.nativeCurrencies - The native currency symbols to poll prices for.\n */\n async _executePoll({\n nativeCurrencies,\n }: CurrencyRatePollingInput): Promise<void> {\n await this.updateExchangeRate(nativeCurrencies);\n }\n}\n\nexport default CurrencyRateController;\n"]}
|
|
@@ -0,0 +1,126 @@
|
|
|
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 _DeFiPositionsController_instances, _DeFiPositionsController_fetchPositions, _DeFiPositionsController_isEnabled, _DeFiPositionsController_updateAccountPositions, _DeFiPositionsController_fetchAccountPositions;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.DeFiPositionsController = exports.getDefaultDefiPositionsControllerState = void 0;
|
|
16
|
+
const polling_controller_1 = require("@metamask/polling-controller");
|
|
17
|
+
const fetch_positions_1 = require("./fetch-positions.cjs");
|
|
18
|
+
const group_defi_positions_1 = require("./group-defi-positions.cjs");
|
|
19
|
+
const assetsUtil_1 = require("../assetsUtil.cjs");
|
|
20
|
+
const TEN_MINUTES_IN_MS = 60000;
|
|
21
|
+
const FETCH_POSITIONS_BATCH_SIZE = 10;
|
|
22
|
+
const controllerName = 'DeFiPositionsController';
|
|
23
|
+
const controllerMetadata = {
|
|
24
|
+
allDeFiPositions: {
|
|
25
|
+
persist: false,
|
|
26
|
+
anonymous: false,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const getDefaultDefiPositionsControllerState = () => {
|
|
30
|
+
return {
|
|
31
|
+
allDeFiPositions: {},
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
exports.getDefaultDefiPositionsControllerState = getDefaultDefiPositionsControllerState;
|
|
35
|
+
/**
|
|
36
|
+
* Controller that stores assets and exposes convenience methods
|
|
37
|
+
*/
|
|
38
|
+
class DeFiPositionsController extends (0, polling_controller_1.StaticIntervalPollingController)() {
|
|
39
|
+
/**
|
|
40
|
+
* DeFiPositionsController constuctor
|
|
41
|
+
*
|
|
42
|
+
* @param options - Constructor options.
|
|
43
|
+
* @param options.messenger - The controller messenger.
|
|
44
|
+
* @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)
|
|
45
|
+
*/
|
|
46
|
+
constructor({ messenger, isEnabled = () => true, }) {
|
|
47
|
+
super({
|
|
48
|
+
name: controllerName,
|
|
49
|
+
metadata: controllerMetadata,
|
|
50
|
+
messenger,
|
|
51
|
+
state: (0, exports.getDefaultDefiPositionsControllerState)(),
|
|
52
|
+
});
|
|
53
|
+
_DeFiPositionsController_instances.add(this);
|
|
54
|
+
_DeFiPositionsController_fetchPositions.set(this, void 0);
|
|
55
|
+
_DeFiPositionsController_isEnabled.set(this, void 0);
|
|
56
|
+
this.setIntervalLength(TEN_MINUTES_IN_MS);
|
|
57
|
+
__classPrivateFieldSet(this, _DeFiPositionsController_fetchPositions, (0, fetch_positions_1.buildPositionFetcher)(), "f");
|
|
58
|
+
__classPrivateFieldSet(this, _DeFiPositionsController_isEnabled, isEnabled, "f");
|
|
59
|
+
this.messagingSystem.subscribe('KeyringController:unlock', () => {
|
|
60
|
+
this.startPolling(null);
|
|
61
|
+
});
|
|
62
|
+
this.messagingSystem.subscribe('KeyringController:lock', () => {
|
|
63
|
+
this.stopAllPolling();
|
|
64
|
+
});
|
|
65
|
+
this.messagingSystem.subscribe('TransactionController:transactionConfirmed', async (transactionMeta) => {
|
|
66
|
+
if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, transactionMeta.txParams.from);
|
|
70
|
+
});
|
|
71
|
+
this.messagingSystem.subscribe('AccountsController:accountAdded', async (account) => {
|
|
72
|
+
if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this) || !account.type.startsWith('eip155:')) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, account.address);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async _executePoll() {
|
|
79
|
+
if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const accounts = this.messagingSystem.call('AccountsController:listAccounts');
|
|
83
|
+
const initialResult = [];
|
|
84
|
+
const results = await (0, assetsUtil_1.reduceInBatchesSerially)({
|
|
85
|
+
initialResult,
|
|
86
|
+
values: accounts,
|
|
87
|
+
batchSize: FETCH_POSITIONS_BATCH_SIZE,
|
|
88
|
+
eachBatch: async (workingResult, batch) => {
|
|
89
|
+
const batchResults = (await Promise.all(batch.map(async ({ address: accountAddress, type }) => {
|
|
90
|
+
if (type.startsWith('eip155:')) {
|
|
91
|
+
const positions = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
|
|
92
|
+
return {
|
|
93
|
+
accountAddress,
|
|
94
|
+
positions,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}))).filter(Boolean);
|
|
99
|
+
return [...workingResult, ...batchResults];
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
const allDefiPositions = results.reduce((acc, { accountAddress, positions }) => {
|
|
103
|
+
acc[accountAddress] = positions;
|
|
104
|
+
return acc;
|
|
105
|
+
}, {});
|
|
106
|
+
this.update((state) => {
|
|
107
|
+
state.allDeFiPositions = allDefiPositions;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.DeFiPositionsController = DeFiPositionsController;
|
|
112
|
+
_DeFiPositionsController_fetchPositions = new WeakMap(), _DeFiPositionsController_isEnabled = new WeakMap(), _DeFiPositionsController_instances = new WeakSet(), _DeFiPositionsController_updateAccountPositions = async function _DeFiPositionsController_updateAccountPositions(accountAddress) {
|
|
113
|
+
const accountPositionsPerChain = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
|
|
114
|
+
this.update((state) => {
|
|
115
|
+
state.allDeFiPositions[accountAddress] = accountPositionsPerChain;
|
|
116
|
+
});
|
|
117
|
+
}, _DeFiPositionsController_fetchAccountPositions = async function _DeFiPositionsController_fetchAccountPositions(accountAddress) {
|
|
118
|
+
try {
|
|
119
|
+
const defiPositionsResponse = await __classPrivateFieldGet(this, _DeFiPositionsController_fetchPositions, "f").call(this, accountAddress);
|
|
120
|
+
return (0, group_defi_positions_1.groupDeFiPositions)(defiPositionsResponse);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=DeFiPositionsController.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeFiPositionsController.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerListAccountsAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type { KeyringControllerUnlockEvent } from '@metamask/keyring-controller';\nimport type { KeyringControllerLockEvent } from '@metamask/keyring-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport type { DefiPositionResponse } from './fetch-positions';\nimport { buildPositionFetcher } from './fetch-positions';\nimport {\n groupDeFiPositions,\n type GroupedDeFiPositions,\n} from './group-defi-positions';\nimport { reduceInBatchesSerially } from '../assetsUtil';\n\nconst TEN_MINUTES_IN_MS = 60_000;\n\nconst FETCH_POSITIONS_BATCH_SIZE = 10;\n\nconst controllerName = 'DeFiPositionsController';\n\ntype GroupedDeFiPositionsPerChain = {\n [chain: Hex]: GroupedDeFiPositions;\n};\n\nexport type DeFiPositionsControllerState = {\n /**\n * Object containing DeFi positions per account and network\n */\n allDeFiPositions: {\n [accountAddress: string]: GroupedDeFiPositionsPerChain | null;\n };\n};\n\nconst controllerMetadata: StateMetadata<DeFiPositionsControllerState> = {\n allDeFiPositions: {\n persist: false,\n anonymous: false,\n },\n};\n\nexport const getDefaultDefiPositionsControllerState =\n (): DeFiPositionsControllerState => {\n return {\n allDeFiPositions: {},\n };\n };\n\nexport type DeFiPositionsControllerActions =\n DeFiPositionsControllerGetStateAction;\n\nexport type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n DeFiPositionsControllerState\n>;\n\nexport type DeFiPositionsControllerEvents =\n DeFiPositionsControllerStateChangeEvent;\n\nexport type DeFiPositionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n DeFiPositionsControllerState\n >;\n\n/**\n * The external actions available to the {@link DeFiPositionsController}.\n */\nexport type AllowedActions = AccountsControllerListAccountsAction;\n\n/**\n * The external events available to the {@link DeFiPositionsController}.\n */\nexport type AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | TransactionControllerTransactionConfirmedEvent\n | AccountsControllerAccountAddedEvent;\n\n/**\n * The messenger of the {@link DeFiPositionsController}.\n */\nexport type DeFiPositionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n DeFiPositionsControllerActions | AllowedActions,\n DeFiPositionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class DeFiPositionsController extends StaticIntervalPollingController()<\n typeof controllerName,\n DeFiPositionsControllerState,\n DeFiPositionsControllerMessenger\n> {\n readonly #fetchPositions: (\n accountAddress: string,\n ) => Promise<DefiPositionResponse[]>;\n\n readonly #isEnabled: () => boolean;\n\n /**\n * DeFiPositionsController constuctor\n *\n * @param options - Constructor options.\n * @param options.messenger - The controller messenger.\n * @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)\n */\n constructor({\n messenger,\n isEnabled = () => true,\n }: {\n messenger: DeFiPositionsControllerMessenger;\n isEnabled?: () => boolean;\n }) {\n super({\n name: controllerName,\n metadata: controllerMetadata,\n messenger,\n state: getDefaultDefiPositionsControllerState(),\n });\n\n this.setIntervalLength(TEN_MINUTES_IN_MS);\n\n this.#fetchPositions = buildPositionFetcher();\n this.#isEnabled = isEnabled;\n\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.startPolling(null);\n });\n\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.stopAllPolling();\n });\n\n this.messagingSystem.subscribe(\n 'TransactionController:transactionConfirmed',\n async (transactionMeta) => {\n if (!this.#isEnabled()) {\n return;\n }\n\n await this.#updateAccountPositions(transactionMeta.txParams.from);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n async (account) => {\n if (!this.#isEnabled() || !account.type.startsWith('eip155:')) {\n return;\n }\n\n await this.#updateAccountPositions(account.address);\n },\n );\n }\n\n async _executePoll(): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const accounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n\n const initialResult: {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[] = [];\n\n const results = await reduceInBatchesSerially({\n initialResult,\n values: accounts,\n batchSize: FETCH_POSITIONS_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const batchResults = (\n await Promise.all(\n batch.map(async ({ address: accountAddress, type }) => {\n if (type.startsWith('eip155:')) {\n const positions =\n await this.#fetchAccountPositions(accountAddress);\n\n return {\n accountAddress,\n positions,\n };\n }\n\n return undefined;\n }),\n )\n ).filter(Boolean) as {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[];\n\n return [...workingResult, ...batchResults];\n },\n });\n\n const allDefiPositions = results.reduce(\n (acc, { accountAddress, positions }) => {\n acc[accountAddress] = positions;\n return acc;\n },\n {} as DeFiPositionsControllerState['allDeFiPositions'],\n );\n\n this.update((state) => {\n state.allDeFiPositions = allDefiPositions;\n });\n }\n\n async #updateAccountPositions(accountAddress: string): Promise<void> {\n const accountPositionsPerChain =\n await this.#fetchAccountPositions(accountAddress);\n\n this.update((state) => {\n state.allDeFiPositions[accountAddress] = accountPositionsPerChain;\n });\n }\n\n async #fetchAccountPositions(\n accountAddress: string,\n ): Promise<GroupedDeFiPositionsPerChain | null> {\n try {\n const defiPositionsResponse = await this.#fetchPositions(accountAddress);\n\n return groupDeFiPositions(defiPositionsResponse);\n } catch {\n return null;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { AccountsControllerAccountAddedEvent, AccountsControllerListAccountsAction } from "@metamask/accounts-controller";
|
|
3
|
+
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
|
4
|
+
import type { KeyringControllerUnlockEvent } from "@metamask/keyring-controller";
|
|
5
|
+
import type { KeyringControllerLockEvent } from "@metamask/keyring-controller";
|
|
6
|
+
import type { TransactionControllerTransactionConfirmedEvent } from "@metamask/transaction-controller";
|
|
7
|
+
import type { Hex } from "@metamask/utils";
|
|
8
|
+
import { type GroupedDeFiPositions } from "./group-defi-positions.cjs";
|
|
9
|
+
declare const controllerName = "DeFiPositionsController";
|
|
10
|
+
type GroupedDeFiPositionsPerChain = {
|
|
11
|
+
[chain: Hex]: GroupedDeFiPositions;
|
|
12
|
+
};
|
|
13
|
+
export type DeFiPositionsControllerState = {
|
|
14
|
+
/**
|
|
15
|
+
* Object containing DeFi positions per account and network
|
|
16
|
+
*/
|
|
17
|
+
allDeFiPositions: {
|
|
18
|
+
[accountAddress: string]: GroupedDeFiPositionsPerChain | null;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare const getDefaultDefiPositionsControllerState: () => DeFiPositionsControllerState;
|
|
22
|
+
export type DeFiPositionsControllerActions = DeFiPositionsControllerGetStateAction;
|
|
23
|
+
export type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<typeof controllerName, DeFiPositionsControllerState>;
|
|
24
|
+
export type DeFiPositionsControllerEvents = DeFiPositionsControllerStateChangeEvent;
|
|
25
|
+
export type DeFiPositionsControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, DeFiPositionsControllerState>;
|
|
26
|
+
/**
|
|
27
|
+
* The external actions available to the {@link DeFiPositionsController}.
|
|
28
|
+
*/
|
|
29
|
+
export type AllowedActions = AccountsControllerListAccountsAction;
|
|
30
|
+
/**
|
|
31
|
+
* The external events available to the {@link DeFiPositionsController}.
|
|
32
|
+
*/
|
|
33
|
+
export type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent | TransactionControllerTransactionConfirmedEvent | AccountsControllerAccountAddedEvent;
|
|
34
|
+
/**
|
|
35
|
+
* The messenger of the {@link DeFiPositionsController}.
|
|
36
|
+
*/
|
|
37
|
+
export type DeFiPositionsControllerMessenger = RestrictedMessenger<typeof controllerName, DeFiPositionsControllerActions | AllowedActions, DeFiPositionsControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
|
38
|
+
declare const DeFiPositionsController_base: (abstract new (...args: any[]) => {
|
|
39
|
+
readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
|
|
40
|
+
"__#14@#intervalLength": number | undefined;
|
|
41
|
+
setIntervalLength(intervalLength: number): void;
|
|
42
|
+
getIntervalLength(): number | undefined;
|
|
43
|
+
_startPolling(input: import("@metamask/utils").Json): void;
|
|
44
|
+
_stopPollingByPollingTokenSetId(key: string): void;
|
|
45
|
+
readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
|
|
46
|
+
"__#3@#callbacks": Map<string, Set<(input: import("@metamask/utils").Json) => void>>;
|
|
47
|
+
_executePoll(input: import("@metamask/utils").Json): Promise<void>;
|
|
48
|
+
startPolling(input: import("@metamask/utils").Json): string;
|
|
49
|
+
stopAllPolling(): void;
|
|
50
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
51
|
+
onPollingComplete(input: import("@metamask/utils").Json, callback: (input: import("@metamask/utils").Json) => void): void;
|
|
52
|
+
}) & typeof import("@metamask/base-controller").BaseController;
|
|
53
|
+
/**
|
|
54
|
+
* Controller that stores assets and exposes convenience methods
|
|
55
|
+
*/
|
|
56
|
+
export declare class DeFiPositionsController extends DeFiPositionsController_base<typeof controllerName, DeFiPositionsControllerState, DeFiPositionsControllerMessenger> {
|
|
57
|
+
#private;
|
|
58
|
+
/**
|
|
59
|
+
* DeFiPositionsController constuctor
|
|
60
|
+
*
|
|
61
|
+
* @param options - Constructor options.
|
|
62
|
+
* @param options.messenger - The controller messenger.
|
|
63
|
+
* @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)
|
|
64
|
+
*/
|
|
65
|
+
constructor({ messenger, isEnabled, }: {
|
|
66
|
+
messenger: DeFiPositionsControllerMessenger;
|
|
67
|
+
isEnabled?: () => boolean;
|
|
68
|
+
});
|
|
69
|
+
_executePoll(): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=DeFiPositionsController.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeFiPositionsController.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,oCAAoC,EACrC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AACnC,OAAO,KAAK,EAAE,4BAA4B,EAAE,qCAAqC;AACjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,qCAAqC;AAE/E,OAAO,KAAK,EAAE,8CAA8C,EAAE,yCAAyC;AACvG,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,EAEL,KAAK,oBAAoB,EAC1B,mCAA+B;AAOhC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,KAAK,4BAA4B,GAAG;IAClC,CAAC,KAAK,EAAE,GAAG,GAAG,oBAAoB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,gBAAgB,EAAE;QAChB,CAAC,cAAc,EAAE,MAAM,GAAG,4BAA4B,GAAG,IAAI,CAAC;KAC/D,CAAC;CACH,CAAC;AASF,eAAO,MAAM,sCAAsC,QAC7C,4BAIH,CAAC;AAEJ,MAAM,MAAM,8BAA8B,GACxC,qCAAqC,CAAC;AAExC,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACvC,uCAAuC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,oCAAoC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,4BAA4B,GAC5B,0BAA0B,GAC1B,8CAA8C,GAC9C,mCAAmC,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,mBAAmB,CAChE,OAAO,cAAc,EACrB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,EAC7C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;;;;;;;;;;;;;;;;AAEF;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,6BAC3C,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;IAOC;;;;;;OAMG;gBACS,EACV,SAAS,EACT,SAAsB,GACvB,EAAE;QACD,SAAS,EAAE,gCAAgC,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;KAC3B;IA4CK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CA6EpC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { AccountsControllerAccountAddedEvent, AccountsControllerListAccountsAction } from "@metamask/accounts-controller";
|
|
3
|
+
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
|
4
|
+
import type { KeyringControllerUnlockEvent } from "@metamask/keyring-controller";
|
|
5
|
+
import type { KeyringControllerLockEvent } from "@metamask/keyring-controller";
|
|
6
|
+
import type { TransactionControllerTransactionConfirmedEvent } from "@metamask/transaction-controller";
|
|
7
|
+
import type { Hex } from "@metamask/utils";
|
|
8
|
+
import { type GroupedDeFiPositions } from "./group-defi-positions.mjs";
|
|
9
|
+
declare const controllerName = "DeFiPositionsController";
|
|
10
|
+
type GroupedDeFiPositionsPerChain = {
|
|
11
|
+
[chain: Hex]: GroupedDeFiPositions;
|
|
12
|
+
};
|
|
13
|
+
export type DeFiPositionsControllerState = {
|
|
14
|
+
/**
|
|
15
|
+
* Object containing DeFi positions per account and network
|
|
16
|
+
*/
|
|
17
|
+
allDeFiPositions: {
|
|
18
|
+
[accountAddress: string]: GroupedDeFiPositionsPerChain | null;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare const getDefaultDefiPositionsControllerState: () => DeFiPositionsControllerState;
|
|
22
|
+
export type DeFiPositionsControllerActions = DeFiPositionsControllerGetStateAction;
|
|
23
|
+
export type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<typeof controllerName, DeFiPositionsControllerState>;
|
|
24
|
+
export type DeFiPositionsControllerEvents = DeFiPositionsControllerStateChangeEvent;
|
|
25
|
+
export type DeFiPositionsControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, DeFiPositionsControllerState>;
|
|
26
|
+
/**
|
|
27
|
+
* The external actions available to the {@link DeFiPositionsController}.
|
|
28
|
+
*/
|
|
29
|
+
export type AllowedActions = AccountsControllerListAccountsAction;
|
|
30
|
+
/**
|
|
31
|
+
* The external events available to the {@link DeFiPositionsController}.
|
|
32
|
+
*/
|
|
33
|
+
export type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent | TransactionControllerTransactionConfirmedEvent | AccountsControllerAccountAddedEvent;
|
|
34
|
+
/**
|
|
35
|
+
* The messenger of the {@link DeFiPositionsController}.
|
|
36
|
+
*/
|
|
37
|
+
export type DeFiPositionsControllerMessenger = RestrictedMessenger<typeof controllerName, DeFiPositionsControllerActions | AllowedActions, DeFiPositionsControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
|
38
|
+
declare const DeFiPositionsController_base: (abstract new (...args: any[]) => {
|
|
39
|
+
readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
|
|
40
|
+
"__#14@#intervalLength": number | undefined;
|
|
41
|
+
setIntervalLength(intervalLength: number): void;
|
|
42
|
+
getIntervalLength(): number | undefined;
|
|
43
|
+
_startPolling(input: import("@metamask/utils").Json): void;
|
|
44
|
+
_stopPollingByPollingTokenSetId(key: string): void;
|
|
45
|
+
readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
|
|
46
|
+
"__#3@#callbacks": Map<string, Set<(input: import("@metamask/utils").Json) => void>>;
|
|
47
|
+
_executePoll(input: import("@metamask/utils").Json): Promise<void>;
|
|
48
|
+
startPolling(input: import("@metamask/utils").Json): string;
|
|
49
|
+
stopAllPolling(): void;
|
|
50
|
+
stopPollingByPollingToken(pollingToken: string): void;
|
|
51
|
+
onPollingComplete(input: import("@metamask/utils").Json, callback: (input: import("@metamask/utils").Json) => void): void;
|
|
52
|
+
}) & typeof import("@metamask/base-controller").BaseController;
|
|
53
|
+
/**
|
|
54
|
+
* Controller that stores assets and exposes convenience methods
|
|
55
|
+
*/
|
|
56
|
+
export declare class DeFiPositionsController extends DeFiPositionsController_base<typeof controllerName, DeFiPositionsControllerState, DeFiPositionsControllerMessenger> {
|
|
57
|
+
#private;
|
|
58
|
+
/**
|
|
59
|
+
* DeFiPositionsController constuctor
|
|
60
|
+
*
|
|
61
|
+
* @param options - Constructor options.
|
|
62
|
+
* @param options.messenger - The controller messenger.
|
|
63
|
+
* @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)
|
|
64
|
+
*/
|
|
65
|
+
constructor({ messenger, isEnabled, }: {
|
|
66
|
+
messenger: DeFiPositionsControllerMessenger;
|
|
67
|
+
isEnabled?: () => boolean;
|
|
68
|
+
});
|
|
69
|
+
_executePoll(): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=DeFiPositionsController.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeFiPositionsController.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,oCAAoC,EACrC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AACnC,OAAO,KAAK,EAAE,4BAA4B,EAAE,qCAAqC;AACjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,qCAAqC;AAE/E,OAAO,KAAK,EAAE,8CAA8C,EAAE,yCAAyC;AACvG,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,EAEL,KAAK,oBAAoB,EAC1B,mCAA+B;AAOhC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,KAAK,4BAA4B,GAAG;IAClC,CAAC,KAAK,EAAE,GAAG,GAAG,oBAAoB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,gBAAgB,EAAE;QAChB,CAAC,cAAc,EAAE,MAAM,GAAG,4BAA4B,GAAG,IAAI,CAAC;KAC/D,CAAC;CACH,CAAC;AASF,eAAO,MAAM,sCAAsC,QAC7C,4BAIH,CAAC;AAEJ,MAAM,MAAM,8BAA8B,GACxC,qCAAqC,CAAC;AAExC,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACvC,uCAAuC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,oCAAoC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,4BAA4B,GAC5B,0BAA0B,GAC1B,8CAA8C,GAC9C,mCAAmC,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,mBAAmB,CAChE,OAAO,cAAc,EACrB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,EAC7C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;;;;;;;;;;;;;;;;AAEF;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,6BAC3C,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;IAOC;;;;;;OAMG;gBACS,EACV,SAAS,EACT,SAAsB,GACvB,EAAE;QACD,SAAS,EAAE,gCAAgC,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;KAC3B;IA4CK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CA6EpC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
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 _DeFiPositionsController_instances, _DeFiPositionsController_fetchPositions, _DeFiPositionsController_isEnabled, _DeFiPositionsController_updateAccountPositions, _DeFiPositionsController_fetchAccountPositions;
|
|
13
|
+
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
|
14
|
+
import { buildPositionFetcher } from "./fetch-positions.mjs";
|
|
15
|
+
import { groupDeFiPositions } from "./group-defi-positions.mjs";
|
|
16
|
+
import { reduceInBatchesSerially } from "../assetsUtil.mjs";
|
|
17
|
+
const TEN_MINUTES_IN_MS = 60000;
|
|
18
|
+
const FETCH_POSITIONS_BATCH_SIZE = 10;
|
|
19
|
+
const controllerName = 'DeFiPositionsController';
|
|
20
|
+
const controllerMetadata = {
|
|
21
|
+
allDeFiPositions: {
|
|
22
|
+
persist: false,
|
|
23
|
+
anonymous: false,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
export const getDefaultDefiPositionsControllerState = () => {
|
|
27
|
+
return {
|
|
28
|
+
allDeFiPositions: {},
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Controller that stores assets and exposes convenience methods
|
|
33
|
+
*/
|
|
34
|
+
export class DeFiPositionsController extends StaticIntervalPollingController() {
|
|
35
|
+
/**
|
|
36
|
+
* DeFiPositionsController constuctor
|
|
37
|
+
*
|
|
38
|
+
* @param options - Constructor options.
|
|
39
|
+
* @param options.messenger - The controller messenger.
|
|
40
|
+
* @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)
|
|
41
|
+
*/
|
|
42
|
+
constructor({ messenger, isEnabled = () => true, }) {
|
|
43
|
+
super({
|
|
44
|
+
name: controllerName,
|
|
45
|
+
metadata: controllerMetadata,
|
|
46
|
+
messenger,
|
|
47
|
+
state: getDefaultDefiPositionsControllerState(),
|
|
48
|
+
});
|
|
49
|
+
_DeFiPositionsController_instances.add(this);
|
|
50
|
+
_DeFiPositionsController_fetchPositions.set(this, void 0);
|
|
51
|
+
_DeFiPositionsController_isEnabled.set(this, void 0);
|
|
52
|
+
this.setIntervalLength(TEN_MINUTES_IN_MS);
|
|
53
|
+
__classPrivateFieldSet(this, _DeFiPositionsController_fetchPositions, buildPositionFetcher(), "f");
|
|
54
|
+
__classPrivateFieldSet(this, _DeFiPositionsController_isEnabled, isEnabled, "f");
|
|
55
|
+
this.messagingSystem.subscribe('KeyringController:unlock', () => {
|
|
56
|
+
this.startPolling(null);
|
|
57
|
+
});
|
|
58
|
+
this.messagingSystem.subscribe('KeyringController:lock', () => {
|
|
59
|
+
this.stopAllPolling();
|
|
60
|
+
});
|
|
61
|
+
this.messagingSystem.subscribe('TransactionController:transactionConfirmed', async (transactionMeta) => {
|
|
62
|
+
if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, transactionMeta.txParams.from);
|
|
66
|
+
});
|
|
67
|
+
this.messagingSystem.subscribe('AccountsController:accountAdded', async (account) => {
|
|
68
|
+
if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this) || !account.type.startsWith('eip155:')) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, account.address);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async _executePoll() {
|
|
75
|
+
if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const accounts = this.messagingSystem.call('AccountsController:listAccounts');
|
|
79
|
+
const initialResult = [];
|
|
80
|
+
const results = await reduceInBatchesSerially({
|
|
81
|
+
initialResult,
|
|
82
|
+
values: accounts,
|
|
83
|
+
batchSize: FETCH_POSITIONS_BATCH_SIZE,
|
|
84
|
+
eachBatch: async (workingResult, batch) => {
|
|
85
|
+
const batchResults = (await Promise.all(batch.map(async ({ address: accountAddress, type }) => {
|
|
86
|
+
if (type.startsWith('eip155:')) {
|
|
87
|
+
const positions = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
|
|
88
|
+
return {
|
|
89
|
+
accountAddress,
|
|
90
|
+
positions,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}))).filter(Boolean);
|
|
95
|
+
return [...workingResult, ...batchResults];
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
const allDefiPositions = results.reduce((acc, { accountAddress, positions }) => {
|
|
99
|
+
acc[accountAddress] = positions;
|
|
100
|
+
return acc;
|
|
101
|
+
}, {});
|
|
102
|
+
this.update((state) => {
|
|
103
|
+
state.allDeFiPositions = allDefiPositions;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
_DeFiPositionsController_fetchPositions = new WeakMap(), _DeFiPositionsController_isEnabled = new WeakMap(), _DeFiPositionsController_instances = new WeakSet(), _DeFiPositionsController_updateAccountPositions = async function _DeFiPositionsController_updateAccountPositions(accountAddress) {
|
|
108
|
+
const accountPositionsPerChain = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
|
|
109
|
+
this.update((state) => {
|
|
110
|
+
state.allDeFiPositions[accountAddress] = accountPositionsPerChain;
|
|
111
|
+
});
|
|
112
|
+
}, _DeFiPositionsController_fetchAccountPositions = async function _DeFiPositionsController_fetchAccountPositions(accountAddress) {
|
|
113
|
+
try {
|
|
114
|
+
const defiPositionsResponse = await __classPrivateFieldGet(this, _DeFiPositionsController_fetchPositions, "f").call(this, accountAddress);
|
|
115
|
+
return groupDeFiPositions(defiPositionsResponse);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=DeFiPositionsController.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeFiPositionsController.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerListAccountsAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type { KeyringControllerUnlockEvent } from '@metamask/keyring-controller';\nimport type { KeyringControllerLockEvent } from '@metamask/keyring-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport type { DefiPositionResponse } from './fetch-positions';\nimport { buildPositionFetcher } from './fetch-positions';\nimport {\n groupDeFiPositions,\n type GroupedDeFiPositions,\n} from './group-defi-positions';\nimport { reduceInBatchesSerially } from '../assetsUtil';\n\nconst TEN_MINUTES_IN_MS = 60_000;\n\nconst FETCH_POSITIONS_BATCH_SIZE = 10;\n\nconst controllerName = 'DeFiPositionsController';\n\ntype GroupedDeFiPositionsPerChain = {\n [chain: Hex]: GroupedDeFiPositions;\n};\n\nexport type DeFiPositionsControllerState = {\n /**\n * Object containing DeFi positions per account and network\n */\n allDeFiPositions: {\n [accountAddress: string]: GroupedDeFiPositionsPerChain | null;\n };\n};\n\nconst controllerMetadata: StateMetadata<DeFiPositionsControllerState> = {\n allDeFiPositions: {\n persist: false,\n anonymous: false,\n },\n};\n\nexport const getDefaultDefiPositionsControllerState =\n (): DeFiPositionsControllerState => {\n return {\n allDeFiPositions: {},\n };\n };\n\nexport type DeFiPositionsControllerActions =\n DeFiPositionsControllerGetStateAction;\n\nexport type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n DeFiPositionsControllerState\n>;\n\nexport type DeFiPositionsControllerEvents =\n DeFiPositionsControllerStateChangeEvent;\n\nexport type DeFiPositionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n DeFiPositionsControllerState\n >;\n\n/**\n * The external actions available to the {@link DeFiPositionsController}.\n */\nexport type AllowedActions = AccountsControllerListAccountsAction;\n\n/**\n * The external events available to the {@link DeFiPositionsController}.\n */\nexport type AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | TransactionControllerTransactionConfirmedEvent\n | AccountsControllerAccountAddedEvent;\n\n/**\n * The messenger of the {@link DeFiPositionsController}.\n */\nexport type DeFiPositionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n DeFiPositionsControllerActions | AllowedActions,\n DeFiPositionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class DeFiPositionsController extends StaticIntervalPollingController()<\n typeof controllerName,\n DeFiPositionsControllerState,\n DeFiPositionsControllerMessenger\n> {\n readonly #fetchPositions: (\n accountAddress: string,\n ) => Promise<DefiPositionResponse[]>;\n\n readonly #isEnabled: () => boolean;\n\n /**\n * DeFiPositionsController constuctor\n *\n * @param options - Constructor options.\n * @param options.messenger - The controller messenger.\n * @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)\n */\n constructor({\n messenger,\n isEnabled = () => true,\n }: {\n messenger: DeFiPositionsControllerMessenger;\n isEnabled?: () => boolean;\n }) {\n super({\n name: controllerName,\n metadata: controllerMetadata,\n messenger,\n state: getDefaultDefiPositionsControllerState(),\n });\n\n this.setIntervalLength(TEN_MINUTES_IN_MS);\n\n this.#fetchPositions = buildPositionFetcher();\n this.#isEnabled = isEnabled;\n\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.startPolling(null);\n });\n\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.stopAllPolling();\n });\n\n this.messagingSystem.subscribe(\n 'TransactionController:transactionConfirmed',\n async (transactionMeta) => {\n if (!this.#isEnabled()) {\n return;\n }\n\n await this.#updateAccountPositions(transactionMeta.txParams.from);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n async (account) => {\n if (!this.#isEnabled() || !account.type.startsWith('eip155:')) {\n return;\n }\n\n await this.#updateAccountPositions(account.address);\n },\n );\n }\n\n async _executePoll(): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const accounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n\n const initialResult: {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[] = [];\n\n const results = await reduceInBatchesSerially({\n initialResult,\n values: accounts,\n batchSize: FETCH_POSITIONS_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const batchResults = (\n await Promise.all(\n batch.map(async ({ address: accountAddress, type }) => {\n if (type.startsWith('eip155:')) {\n const positions =\n await this.#fetchAccountPositions(accountAddress);\n\n return {\n accountAddress,\n positions,\n };\n }\n\n return undefined;\n }),\n )\n ).filter(Boolean) as {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[];\n\n return [...workingResult, ...batchResults];\n },\n });\n\n const allDefiPositions = results.reduce(\n (acc, { accountAddress, positions }) => {\n acc[accountAddress] = positions;\n return acc;\n },\n {} as DeFiPositionsControllerState['allDeFiPositions'],\n );\n\n this.update((state) => {\n state.allDeFiPositions = allDefiPositions;\n });\n }\n\n async #updateAccountPositions(accountAddress: string): Promise<void> {\n const accountPositionsPerChain =\n await this.#fetchAccountPositions(accountAddress);\n\n this.update((state) => {\n state.allDeFiPositions[accountAddress] = accountPositionsPerChain;\n });\n }\n\n async #fetchAccountPositions(\n accountAddress: string,\n ): Promise<GroupedDeFiPositionsPerChain | null> {\n try {\n const defiPositionsResponse = await this.#fetchPositions(accountAddress);\n\n return groupDeFiPositions(defiPositionsResponse);\n } catch {\n return null;\n }\n }\n}\n"]}
|