@metamask-previews/assets-controller 2.0.2-preview-3d4d0d0ef → 2.0.2-preview-835c0b0
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 +17 -1
- package/dist/AssetsController-method-action-types.cjs.map +1 -1
- package/dist/AssetsController-method-action-types.d.cts +5 -0
- package/dist/AssetsController-method-action-types.d.cts.map +1 -1
- package/dist/AssetsController-method-action-types.d.mts +5 -0
- package/dist/AssetsController-method-action-types.d.mts.map +1 -1
- package/dist/AssetsController-method-action-types.mjs.map +1 -1
- package/dist/AssetsController.cjs +148 -29
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts +37 -5
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts +37 -5
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +148 -29
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.cjs +1 -0
- package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.mjs +1 -0
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.cjs +16 -4
- package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
- package/dist/data-sources/BackendWebsocketDataSource.mjs +13 -4
- package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
- package/dist/data-sources/PriceDataSource.cjs +20 -14
- package/dist/data-sources/PriceDataSource.cjs.map +1 -1
- package/dist/data-sources/PriceDataSource.d.cts +2 -2
- package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
- package/dist/data-sources/PriceDataSource.d.mts +2 -2
- package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
- package/dist/data-sources/PriceDataSource.mjs +20 -14
- package/dist/data-sources/PriceDataSource.mjs.map +1 -1
- package/dist/data-sources/RpcDataSource.cjs +2 -0
- package/dist/data-sources/RpcDataSource.cjs.map +1 -1
- package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
- package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
- package/dist/data-sources/RpcDataSource.mjs +2 -0
- package/dist/data-sources/RpcDataSource.mjs.map +1 -1
- package/dist/data-sources/SnapDataSource.cjs +3 -2
- package/dist/data-sources/SnapDataSource.cjs.map +1 -1
- package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
- package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
- package/dist/data-sources/SnapDataSource.mjs +3 -2
- package/dist/data-sources/SnapDataSource.mjs.map +1 -1
- package/dist/data-sources/TokenDataSource.cjs +1 -0
- package/dist/data-sources/TokenDataSource.cjs.map +1 -1
- package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
- package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
- package/dist/data-sources/TokenDataSource.mjs +1 -0
- package/dist/data-sources/TokenDataSource.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.cjs +44 -27
- package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.cts +15 -9
- package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.mts +15 -9
- package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.mjs +44 -27
- package/dist/middlewares/DetectionMiddleware.mjs.map +1 -1
- package/dist/middlewares/ParallelMiddleware.cjs +216 -0
- package/dist/middlewares/ParallelMiddleware.cjs.map +1 -0
- package/dist/middlewares/ParallelMiddleware.d.cts +45 -0
- package/dist/middlewares/ParallelMiddleware.d.cts.map +1 -0
- package/dist/middlewares/ParallelMiddleware.d.mts +45 -0
- package/dist/middlewares/ParallelMiddleware.d.mts.map +1 -0
- package/dist/middlewares/ParallelMiddleware.mjs +214 -0
- package/dist/middlewares/ParallelMiddleware.mjs.map +1 -0
- package/dist/middlewares/index.cjs +5 -1
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +2 -0
- package/dist/middlewares/index.d.cts.map +1 -1
- package/dist/middlewares/index.d.mts +2 -0
- package/dist/middlewares/index.d.mts.map +1 -1
- package/dist/middlewares/index.mjs +1 -0
- package/dist/middlewares/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +16 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +16 -0
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetectionMiddleware.cjs","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":";;;AAAA,0CAA8D;AAC9D,wCAAwC;AAGxC,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,uBAAuB;AACvB,IAAA,2BAAkB,EAAC,sBAAa,EAAE,eAAe,CAAC,CAAC;AAEnD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E
|
|
1
|
+
{"version":3,"file":"DetectionMiddleware.cjs","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":";;;AAAA,0CAA8D;AAC9D,wCAAwC;AAGxC,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,uBAAuB;AACvB,IAAA,2BAAkB,EAAC,sBAAa,EAAE,eAAe,CAAC,CAAC;AAEnD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,mBAAmB;IAAhC;QACW,SAAI,GAAG,eAAe,CAAC;IAwElC,CAAC;IAtEC,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,gBAAgB;QAClB,OAAO,IAAA,oBAAY,EAAC,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YACnD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;YAElC,8BAA8B;YAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACnC,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;YAElD,MAAM,cAAc,GAAuC,EAAE,CAAC;YAE9D,iHAAiH;YACjH,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;gBAC3B,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CACvD,QAAQ,CAAC,aAAa,CACvB,EAAE,CAAC;oBACF,MAAM,QAAQ,GAAoB,EAAE,CAAC;oBAErC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAC/B,eAA0C,CAC3C,EAAE,CAAC;wBACF,QAAQ,CAAC,IAAI,CAAC,OAAwB,CAAC,CAAC;oBAC1C,CAAC;oBAED,gDAAgD;oBAChD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;oBAC9D,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;wBACvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;4BAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACzB,CAAC;oBACH,CAAC;oBAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACxB,cAAc,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;oBACvC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,uFAAuF;YACvF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,OAAO,CAAC,2BAA2B,EAAE,CAAC;gBAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC;gBAC7B,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC9B,SAAS;gBACX,CAAC;gBACD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC9D,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChC,cAAc,CAAC,SAAS,CAAC,GAAG,gBAAgB,CAAC;gBAC/C,CAAC;YACH,CAAC;YAED,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3C,QAAQ,CAAC,cAAc,GAAG,cAAc,CAAC;YAC3C,CAAC;YAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAzED,kDAyEC","sourcesContent":["import { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type { AccountId, Caip19AssetId, Middleware } from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'DetectionMiddleware';\n\n// Logger for debugging\ncreateModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// DETECTION MIDDLEWARE\n// ============================================================================\n\n/**\n * DetectionMiddleware builds the set of assets that downstream sources use for\n * metadata and price fetching.\n *\n * This middleware:\n * - Includes every asset that appears in response.assetsBalance (so prices and\n * metadata are fetched for existing assets as well as new ones)\n * - Includes each account's custom assets from state (so custom tokens get\n * metadata and prices even when they have no balance yet)\n * - Fills response.detectedAssets with these asset IDs per account\n *\n * TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource\n * then filters to only fetch metadata for assets that lack it; PriceDataSource\n * fetches prices for all detected assets.\n *\n * Usage:\n * ```typescript\n * const detectionMiddleware = new DetectionMiddleware();\n * const middleware = detectionMiddleware.assetsMiddleware;\n * ```\n */\nexport class DetectionMiddleware {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /**\n * Get the middleware that builds detectedAssets for metadata and price fetching.\n *\n * This middleware:\n * 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)\n * 2. Merges each account's custom assets from state\n * 3. Fills response.detectedAssets with these asset IDs per account\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['balance'], async (ctx, next) => {\n const { request, response } = ctx;\n\n // Get state for custom assets\n const state = ctx.getAssetsState();\n const { customAssets: stateCustomAssets } = state;\n\n const detectedAssets: Record<AccountId, Caip19AssetId[]> = {};\n\n // 1. From balance response: include every asset with balance (so prices + metadata path include existing assets)\n if (response.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n response.assetsBalance,\n )) {\n const detected: Caip19AssetId[] = [];\n\n for (const assetId of Object.keys(\n accountBalances as Record<string, unknown>,\n )) {\n detected.push(assetId as Caip19AssetId);\n }\n\n // Merge this account's custom assets from state\n const customForAccount = stateCustomAssets?.[accountId] ?? [];\n for (const assetId of customForAccount) {\n if (!detected.includes(assetId)) {\n detected.push(assetId);\n }\n }\n\n if (detected.length > 0) {\n detectedAssets[accountId] = detected;\n }\n }\n }\n\n // 2. Accounts in request that weren't in balance response: include their custom assets\n for (const { account } of request.accountsWithSupportedChains) {\n const accountId = account.id;\n if (detectedAssets[accountId]) {\n continue;\n }\n const customForAccount = stateCustomAssets?.[accountId] ?? [];\n if (customForAccount.length > 0) {\n detectedAssets[accountId] = customForAccount;\n }\n }\n\n if (Object.keys(detectedAssets).length > 0) {\n response.detectedAssets = detectedAssets;\n }\n\n return next(ctx);\n });\n }\n}\n"]}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { Middleware } from "../types.cjs";
|
|
2
2
|
/**
|
|
3
|
-
* DetectionMiddleware
|
|
3
|
+
* DetectionMiddleware builds the set of assets that downstream sources use for
|
|
4
|
+
* metadata and price fetching.
|
|
4
5
|
*
|
|
5
6
|
* This middleware:
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
7
|
+
* - Includes every asset that appears in response.assetsBalance (so prices and
|
|
8
|
+
* metadata are fetched for existing assets as well as new ones)
|
|
9
|
+
* - Includes each account's custom assets from state (so custom tokens get
|
|
10
|
+
* metadata and prices even when they have no balance yet)
|
|
11
|
+
* - Fills response.detectedAssets with these asset IDs per account
|
|
12
|
+
*
|
|
13
|
+
* TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource
|
|
14
|
+
* then filters to only fetch metadata for assets that lack it; PriceDataSource
|
|
15
|
+
* fetches prices for all detected assets.
|
|
9
16
|
*
|
|
10
17
|
* Usage:
|
|
11
18
|
* ```typescript
|
|
@@ -17,13 +24,12 @@ export declare class DetectionMiddleware {
|
|
|
17
24
|
readonly name = "DetectionMiddleware";
|
|
18
25
|
getName(): string;
|
|
19
26
|
/**
|
|
20
|
-
* Get the middleware for
|
|
27
|
+
* Get the middleware that builds detectedAssets for metadata and price fetching.
|
|
21
28
|
*
|
|
22
29
|
* This middleware:
|
|
23
|
-
* 1.
|
|
24
|
-
* 2.
|
|
25
|
-
* 3. Fills response.detectedAssets with
|
|
26
|
-
* 4. Calls next() to continue the middleware chain
|
|
30
|
+
* 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)
|
|
31
|
+
* 2. Merges each account's custom assets from state
|
|
32
|
+
* 3. Fills response.detectedAssets with these asset IDs per account
|
|
27
33
|
*
|
|
28
34
|
* @returns The middleware function for the assets pipeline.
|
|
29
35
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetectionMiddleware.d.cts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE
|
|
1
|
+
{"version":3,"file":"DetectionMiddleware.d.cts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,IAAI,yBAAmB;IAEhC,OAAO,IAAI,MAAM;IAIjB;;;;;;;;;OASG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAuDjC;CACF"}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { Middleware } from "../types.mjs";
|
|
2
2
|
/**
|
|
3
|
-
* DetectionMiddleware
|
|
3
|
+
* DetectionMiddleware builds the set of assets that downstream sources use for
|
|
4
|
+
* metadata and price fetching.
|
|
4
5
|
*
|
|
5
6
|
* This middleware:
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
7
|
+
* - Includes every asset that appears in response.assetsBalance (so prices and
|
|
8
|
+
* metadata are fetched for existing assets as well as new ones)
|
|
9
|
+
* - Includes each account's custom assets from state (so custom tokens get
|
|
10
|
+
* metadata and prices even when they have no balance yet)
|
|
11
|
+
* - Fills response.detectedAssets with these asset IDs per account
|
|
12
|
+
*
|
|
13
|
+
* TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource
|
|
14
|
+
* then filters to only fetch metadata for assets that lack it; PriceDataSource
|
|
15
|
+
* fetches prices for all detected assets.
|
|
9
16
|
*
|
|
10
17
|
* Usage:
|
|
11
18
|
* ```typescript
|
|
@@ -17,13 +24,12 @@ export declare class DetectionMiddleware {
|
|
|
17
24
|
readonly name = "DetectionMiddleware";
|
|
18
25
|
getName(): string;
|
|
19
26
|
/**
|
|
20
|
-
* Get the middleware for
|
|
27
|
+
* Get the middleware that builds detectedAssets for metadata and price fetching.
|
|
21
28
|
*
|
|
22
29
|
* This middleware:
|
|
23
|
-
* 1.
|
|
24
|
-
* 2.
|
|
25
|
-
* 3. Fills response.detectedAssets with
|
|
26
|
-
* 4. Calls next() to continue the middleware chain
|
|
30
|
+
* 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)
|
|
31
|
+
* 2. Merges each account's custom assets from state
|
|
32
|
+
* 3. Fills response.detectedAssets with these asset IDs per account
|
|
27
33
|
*
|
|
28
34
|
* @returns The middleware function for the assets pipeline.
|
|
29
35
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetectionMiddleware.d.mts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE
|
|
1
|
+
{"version":3,"file":"DetectionMiddleware.d.mts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,IAAI,yBAAmB;IAEhC,OAAO,IAAI,MAAM;IAIjB;;;;;;;;;OASG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAuDjC;CACF"}
|
|
@@ -10,12 +10,19 @@ createModuleLogger(projectLogger, CONTROLLER_NAME);
|
|
|
10
10
|
// DETECTION MIDDLEWARE
|
|
11
11
|
// ============================================================================
|
|
12
12
|
/**
|
|
13
|
-
* DetectionMiddleware
|
|
13
|
+
* DetectionMiddleware builds the set of assets that downstream sources use for
|
|
14
|
+
* metadata and price fetching.
|
|
14
15
|
*
|
|
15
16
|
* This middleware:
|
|
16
|
-
* -
|
|
17
|
-
*
|
|
18
|
-
* -
|
|
17
|
+
* - Includes every asset that appears in response.assetsBalance (so prices and
|
|
18
|
+
* metadata are fetched for existing assets as well as new ones)
|
|
19
|
+
* - Includes each account's custom assets from state (so custom tokens get
|
|
20
|
+
* metadata and prices even when they have no balance yet)
|
|
21
|
+
* - Fills response.detectedAssets with these asset IDs per account
|
|
22
|
+
*
|
|
23
|
+
* TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource
|
|
24
|
+
* then filters to only fetch metadata for assets that lack it; PriceDataSource
|
|
25
|
+
* fetches prices for all detected assets.
|
|
19
26
|
*
|
|
20
27
|
* Usage:
|
|
21
28
|
* ```typescript
|
|
@@ -31,45 +38,55 @@ export class DetectionMiddleware {
|
|
|
31
38
|
return this.name;
|
|
32
39
|
}
|
|
33
40
|
/**
|
|
34
|
-
* Get the middleware for
|
|
41
|
+
* Get the middleware that builds detectedAssets for metadata and price fetching.
|
|
35
42
|
*
|
|
36
43
|
* This middleware:
|
|
37
|
-
* 1.
|
|
38
|
-
* 2.
|
|
39
|
-
* 3. Fills response.detectedAssets with
|
|
40
|
-
* 4. Calls next() to continue the middleware chain
|
|
44
|
+
* 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)
|
|
45
|
+
* 2. Merges each account's custom assets from state
|
|
46
|
+
* 3. Fills response.detectedAssets with these asset IDs per account
|
|
41
47
|
*
|
|
42
48
|
* @returns The middleware function for the assets pipeline.
|
|
43
49
|
*/
|
|
44
50
|
get assetsMiddleware() {
|
|
45
51
|
return forDataTypes(['balance'], async (ctx, next) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return next(ctx);
|
|
51
|
-
}
|
|
52
|
-
// Get metadata from state
|
|
53
|
-
const { assetsInfo: stateMetadata } = ctx.getAssetsState();
|
|
52
|
+
const { request, response } = ctx;
|
|
53
|
+
// Get state for custom assets
|
|
54
|
+
const state = ctx.getAssetsState();
|
|
55
|
+
const { customAssets: stateCustomAssets } = state;
|
|
54
56
|
const detectedAssets = {};
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (!stateMetadata[assetId]) {
|
|
57
|
+
// 1. From balance response: include every asset with balance (so prices + metadata path include existing assets)
|
|
58
|
+
if (response.assetsBalance) {
|
|
59
|
+
for (const [accountId, accountBalances] of Object.entries(response.assetsBalance)) {
|
|
60
|
+
const detected = [];
|
|
61
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
61
62
|
detected.push(assetId);
|
|
62
63
|
}
|
|
64
|
+
// Merge this account's custom assets from state
|
|
65
|
+
const customForAccount = stateCustomAssets?.[accountId] ?? [];
|
|
66
|
+
for (const assetId of customForAccount) {
|
|
67
|
+
if (!detected.includes(assetId)) {
|
|
68
|
+
detected.push(assetId);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (detected.length > 0) {
|
|
72
|
+
detectedAssets[accountId] = detected;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// 2. Accounts in request that weren't in balance response: include their custom assets
|
|
77
|
+
for (const { account } of request.accountsWithSupportedChains) {
|
|
78
|
+
const accountId = account.id;
|
|
79
|
+
if (detectedAssets[accountId]) {
|
|
80
|
+
continue;
|
|
63
81
|
}
|
|
64
|
-
|
|
65
|
-
|
|
82
|
+
const customForAccount = stateCustomAssets?.[accountId] ?? [];
|
|
83
|
+
if (customForAccount.length > 0) {
|
|
84
|
+
detectedAssets[accountId] = customForAccount;
|
|
66
85
|
}
|
|
67
86
|
}
|
|
68
|
-
// Fill detectedAssets in the response
|
|
69
87
|
if (Object.keys(detectedAssets).length > 0) {
|
|
70
88
|
response.detectedAssets = detectedAssets;
|
|
71
89
|
}
|
|
72
|
-
// Call next() to continue the middleware chain
|
|
73
90
|
return next(ctx);
|
|
74
91
|
});
|
|
75
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetectionMiddleware.mjs","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,sBAAkB;AAC9D,OAAO,EAAE,YAAY,EAAE,qBAAiB;AAGxC,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,uBAAuB;AACvB,kBAAkB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AAEnD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E
|
|
1
|
+
{"version":3,"file":"DetectionMiddleware.mjs","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,sBAAkB;AAC9D,OAAO,EAAE,YAAY,EAAE,qBAAiB;AAGxC,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,uBAAuB;AACvB,kBAAkB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AAEnD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,mBAAmB;IAAhC;QACW,SAAI,GAAG,eAAe,CAAC;IAwElC,CAAC;IAtEC,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,gBAAgB;QAClB,OAAO,YAAY,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YACnD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;YAElC,8BAA8B;YAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACnC,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;YAElD,MAAM,cAAc,GAAuC,EAAE,CAAC;YAE9D,iHAAiH;YACjH,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;gBAC3B,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CACvD,QAAQ,CAAC,aAAa,CACvB,EAAE,CAAC;oBACF,MAAM,QAAQ,GAAoB,EAAE,CAAC;oBAErC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAC/B,eAA0C,CAC3C,EAAE,CAAC;wBACF,QAAQ,CAAC,IAAI,CAAC,OAAwB,CAAC,CAAC;oBAC1C,CAAC;oBAED,gDAAgD;oBAChD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;oBAC9D,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;wBACvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;4BAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACzB,CAAC;oBACH,CAAC;oBAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACxB,cAAc,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;oBACvC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,uFAAuF;YACvF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,OAAO,CAAC,2BAA2B,EAAE,CAAC;gBAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC;gBAC7B,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC9B,SAAS;gBACX,CAAC;gBACD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC9D,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChC,cAAc,CAAC,SAAS,CAAC,GAAG,gBAAgB,CAAC;gBAC/C,CAAC;YACH,CAAC;YAED,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3C,QAAQ,CAAC,cAAc,GAAG,cAAc,CAAC;YAC3C,CAAC;YAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type { AccountId, Caip19AssetId, Middleware } from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'DetectionMiddleware';\n\n// Logger for debugging\ncreateModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// DETECTION MIDDLEWARE\n// ============================================================================\n\n/**\n * DetectionMiddleware builds the set of assets that downstream sources use for\n * metadata and price fetching.\n *\n * This middleware:\n * - Includes every asset that appears in response.assetsBalance (so prices and\n * metadata are fetched for existing assets as well as new ones)\n * - Includes each account's custom assets from state (so custom tokens get\n * metadata and prices even when they have no balance yet)\n * - Fills response.detectedAssets with these asset IDs per account\n *\n * TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource\n * then filters to only fetch metadata for assets that lack it; PriceDataSource\n * fetches prices for all detected assets.\n *\n * Usage:\n * ```typescript\n * const detectionMiddleware = new DetectionMiddleware();\n * const middleware = detectionMiddleware.assetsMiddleware;\n * ```\n */\nexport class DetectionMiddleware {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /**\n * Get the middleware that builds detectedAssets for metadata and price fetching.\n *\n * This middleware:\n * 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)\n * 2. Merges each account's custom assets from state\n * 3. Fills response.detectedAssets with these asset IDs per account\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['balance'], async (ctx, next) => {\n const { request, response } = ctx;\n\n // Get state for custom assets\n const state = ctx.getAssetsState();\n const { customAssets: stateCustomAssets } = state;\n\n const detectedAssets: Record<AccountId, Caip19AssetId[]> = {};\n\n // 1. From balance response: include every asset with balance (so prices + metadata path include existing assets)\n if (response.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n response.assetsBalance,\n )) {\n const detected: Caip19AssetId[] = [];\n\n for (const assetId of Object.keys(\n accountBalances as Record<string, unknown>,\n )) {\n detected.push(assetId as Caip19AssetId);\n }\n\n // Merge this account's custom assets from state\n const customForAccount = stateCustomAssets?.[accountId] ?? [];\n for (const assetId of customForAccount) {\n if (!detected.includes(assetId)) {\n detected.push(assetId);\n }\n }\n\n if (detected.length > 0) {\n detectedAssets[accountId] = detected;\n }\n }\n }\n\n // 2. Accounts in request that weren't in balance response: include their custom assets\n for (const { account } of request.accountsWithSupportedChains) {\n const accountId = account.id;\n if (detectedAssets[accountId]) {\n continue;\n }\n const customForAccount = stateCustomAssets?.[accountId] ?? [];\n if (customForAccount.length > 0) {\n detectedAssets[accountId] = customForAccount;\n }\n }\n\n if (Object.keys(detectedAssets).length > 0) {\n response.detectedAssets = detectedAssets;\n }\n\n return next(ctx);\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createParallelMiddleware = exports.createParallelBalanceMiddleware = exports.mergeDataResponses = void 0;
|
|
7
|
+
const p_limit_1 = __importDefault(require("p-limit/index.js"));
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// MERGE HELPER
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Deep-merge multiple DataResponses into one.
|
|
13
|
+
* Used when running balance data sources in parallel.
|
|
14
|
+
*
|
|
15
|
+
* @param responses - Array of DataResponse from each source.
|
|
16
|
+
* @returns Single merged DataResponse.
|
|
17
|
+
*/
|
|
18
|
+
function mergeDataResponses(responses) {
|
|
19
|
+
const merged = {};
|
|
20
|
+
for (const response of responses) {
|
|
21
|
+
if (response.assetsBalance) {
|
|
22
|
+
merged.assetsBalance ?? (merged.assetsBalance = {});
|
|
23
|
+
for (const [accountId, accountBalances] of Object.entries(response.assetsBalance)) {
|
|
24
|
+
merged.assetsBalance[accountId] = {
|
|
25
|
+
...(merged.assetsBalance[accountId] ?? {}),
|
|
26
|
+
...accountBalances,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (response.assetsInfo) {
|
|
31
|
+
merged.assetsInfo = {
|
|
32
|
+
...(merged.assetsInfo ?? {}),
|
|
33
|
+
...response.assetsInfo,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (response.assetsPrice) {
|
|
37
|
+
merged.assetsPrice = {
|
|
38
|
+
...(merged.assetsPrice ?? {}),
|
|
39
|
+
...response.assetsPrice,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (response.errors) {
|
|
43
|
+
merged.errors = {
|
|
44
|
+
...(merged.errors ?? {}),
|
|
45
|
+
...response.errors,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (response.detectedAssets) {
|
|
49
|
+
merged.detectedAssets = {
|
|
50
|
+
...(merged.detectedAssets ?? {}),
|
|
51
|
+
...response.detectedAssets,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (response.updateMode === 'full') {
|
|
55
|
+
merged.updateMode = 'full';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
merged.updateMode ?? (merged.updateMode = 'merge');
|
|
59
|
+
return merged;
|
|
60
|
+
}
|
|
61
|
+
exports.mergeDataResponses = mergeDataResponses;
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// PARALLEL BALANCE MIDDLEWARE
|
|
64
|
+
// ============================================================================
|
|
65
|
+
const PARALLEL_BALANCE_MIDDLEWARE_NAME = 'ParallelBalanceMiddleware';
|
|
66
|
+
/** Max concurrent balance source calls (round 1 and fallback). */
|
|
67
|
+
const BALANCE_CONCURRENCY = 3;
|
|
68
|
+
/**
|
|
69
|
+
* Partition request.chainIds so each chain is assigned to exactly one source
|
|
70
|
+
* (by source order: first source that supports the chain gets it). Ensures no
|
|
71
|
+
* chain overlap across data source calls.
|
|
72
|
+
*
|
|
73
|
+
* @param request - The data request with chainIds to partition.
|
|
74
|
+
* @param sources - Balance sources in priority order (e.g. AccountsAPI, Snap, Rpc).
|
|
75
|
+
* @returns Array of requests, one per source, each with only that source's assigned chainIds.
|
|
76
|
+
*/
|
|
77
|
+
function partitionChainsBySource(request, sources) {
|
|
78
|
+
const { chainIds } = request;
|
|
79
|
+
const assigned = new Set();
|
|
80
|
+
return sources.map((source) => {
|
|
81
|
+
const supported = new Set(source.getActiveChainsSync());
|
|
82
|
+
const chainsForSource = chainIds.filter((id) => supported.has(id) && !assigned.has(id));
|
|
83
|
+
chainsForSource.forEach((id) => assigned.add(id));
|
|
84
|
+
return {
|
|
85
|
+
...request,
|
|
86
|
+
chainIds: chainsForSource,
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Collect chain IDs that failed in the first round (present in response.errors).
|
|
92
|
+
* Used to run a fallback round with remaining sources.
|
|
93
|
+
*
|
|
94
|
+
* @param requests - Partitioned requests, one per source (same order as results).
|
|
95
|
+
* @param results - Results from each source; chain IDs in requests[i] that have errors in results[i].response.errors are considered failed.
|
|
96
|
+
* @returns Set of chain IDs that had errors in the first round.
|
|
97
|
+
*/
|
|
98
|
+
function getFailedChainIds(requests, results) {
|
|
99
|
+
const failed = new Set();
|
|
100
|
+
for (let i = 0; i < results.length; i++) {
|
|
101
|
+
const errors = results[i].response.errors ?? {};
|
|
102
|
+
for (const chainId of requests[i].chainIds) {
|
|
103
|
+
if (errors[chainId]) {
|
|
104
|
+
failed.add(chainId);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return failed;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Middleware that runs multiple balance data source middlewares in parallel,
|
|
112
|
+
* with no chain overlap. Chains that fail (response.errors) are re-partitioned
|
|
113
|
+
* and fetched again in a fallback round so lower-priority sources can try them.
|
|
114
|
+
*
|
|
115
|
+
* @param sources - Array of balance sources in priority order (each with getName(), getActiveChainsSync(), assetsMiddleware).
|
|
116
|
+
* @returns A single middleware that runs all sources in parallel and merges responses.
|
|
117
|
+
*/
|
|
118
|
+
function createParallelBalanceMiddleware(sources) {
|
|
119
|
+
return {
|
|
120
|
+
getName() {
|
|
121
|
+
return PARALLEL_BALANCE_MIDDLEWARE_NAME;
|
|
122
|
+
},
|
|
123
|
+
assetsMiddleware: async (context, next) => {
|
|
124
|
+
if (sources.length === 0) {
|
|
125
|
+
return next(context);
|
|
126
|
+
}
|
|
127
|
+
const noopNext = async (ctx) => ctx;
|
|
128
|
+
const limit = (0, p_limit_1.default)(BALANCE_CONCURRENCY);
|
|
129
|
+
// Round 1: partition chains (no overlap), run with limited concurrency
|
|
130
|
+
const requests = partitionChainsBySource(context.request, sources);
|
|
131
|
+
const results = await Promise.all(sources.map((source, i) => limit(() => source.assetsMiddleware({
|
|
132
|
+
request: requests[i],
|
|
133
|
+
response: {},
|
|
134
|
+
getAssetsState: context.getAssetsState,
|
|
135
|
+
}, noopNext))));
|
|
136
|
+
let mergedResponse = mergeDataResponses(results.map((result) => result.response));
|
|
137
|
+
// Fallback: chains that failed (in errors) get re-partitioned and tried again
|
|
138
|
+
const failedChainIds = getFailedChainIds(requests, results);
|
|
139
|
+
if (failedChainIds.size > 0) {
|
|
140
|
+
const fallbackRequest = {
|
|
141
|
+
...context.request,
|
|
142
|
+
chainIds: [...failedChainIds],
|
|
143
|
+
};
|
|
144
|
+
const fallbackRequests = partitionChainsBySource(fallbackRequest, sources);
|
|
145
|
+
const fallbackResults = await Promise.all(sources.map((source, i) => limit(() => source.assetsMiddleware({
|
|
146
|
+
request: fallbackRequests[i],
|
|
147
|
+
response: {},
|
|
148
|
+
getAssetsState: context.getAssetsState,
|
|
149
|
+
}, noopNext))));
|
|
150
|
+
const fallbackMerged = mergeDataResponses(fallbackResults.map((result) => result.response));
|
|
151
|
+
mergedResponse = mergeDataResponses([mergedResponse, fallbackMerged]);
|
|
152
|
+
// Remove errors for chains we successfully got balance for in fallback
|
|
153
|
+
if (mergedResponse.errors && mergedResponse.assetsBalance) {
|
|
154
|
+
const chainsWithBalance = new Set();
|
|
155
|
+
for (const accountBalances of Object.values(mergedResponse.assetsBalance)) {
|
|
156
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
157
|
+
const chainId = assetId.split('/')[0];
|
|
158
|
+
chainsWithBalance.add(chainId);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
for (const chainId of failedChainIds) {
|
|
162
|
+
if (chainsWithBalance.has(chainId)) {
|
|
163
|
+
delete mergedResponse.errors[chainId];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return next({
|
|
169
|
+
...context,
|
|
170
|
+
response: mergeDataResponses([context.response, mergedResponse]),
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
exports.createParallelBalanceMiddleware = createParallelBalanceMiddleware;
|
|
176
|
+
// ============================================================================
|
|
177
|
+
// PARALLEL TOKEN/PRICE MIDDLEWARE
|
|
178
|
+
// ============================================================================
|
|
179
|
+
const PARALLEL_MIDDLEWARE_NAME = 'ParallelMiddleware';
|
|
180
|
+
/** Max concurrent token/price source calls. */
|
|
181
|
+
const CONCURRENCY = 2;
|
|
182
|
+
/**
|
|
183
|
+
* Middleware that runs multiple data source middlewares (e.g. TokenDataSource,
|
|
184
|
+
* PriceDataSource) in parallel with the same request. Responses are merged so
|
|
185
|
+
* that assetsInfo (token metadata) and assetsPrice are combined. Use this to
|
|
186
|
+
* fetch token and price data concurrently instead of sequentially.
|
|
187
|
+
*
|
|
188
|
+
* @param sources - Array of sources with getName() and assetsMiddleware.
|
|
189
|
+
* @returns A single middleware that runs all sources in parallel and merges responses.
|
|
190
|
+
*/
|
|
191
|
+
function createParallelMiddleware(sources) {
|
|
192
|
+
return {
|
|
193
|
+
getName() {
|
|
194
|
+
return PARALLEL_MIDDLEWARE_NAME;
|
|
195
|
+
},
|
|
196
|
+
assetsMiddleware: async (context, next) => {
|
|
197
|
+
if (sources.length === 0) {
|
|
198
|
+
return next(context);
|
|
199
|
+
}
|
|
200
|
+
const noopNext = async (ctx) => ctx;
|
|
201
|
+
const limit = (0, p_limit_1.default)(CONCURRENCY);
|
|
202
|
+
const results = await Promise.all(sources.map((source) => limit(() => source.assetsMiddleware({
|
|
203
|
+
request: context.request,
|
|
204
|
+
response: { ...context.response },
|
|
205
|
+
getAssetsState: context.getAssetsState,
|
|
206
|
+
}, noopNext))));
|
|
207
|
+
const mergedResponse = mergeDataResponses(results.map((result) => result.response));
|
|
208
|
+
return next({
|
|
209
|
+
...context,
|
|
210
|
+
response: mergeDataResponses([context.response, mergedResponse]),
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
exports.createParallelMiddleware = createParallelMiddleware;
|
|
216
|
+
//# sourceMappingURL=ParallelMiddleware.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParallelMiddleware.cjs","sourceRoot":"","sources":["../../src/middlewares/ParallelMiddleware.ts"],"names":[],"mappings":";;;;;;AAAA,+DAA6B;AAU7B,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAAC,SAAyB;IAC1D,MAAM,MAAM,GAAiB,EAAE,CAAC;IAEhC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;YAC3B,MAAM,CAAC,aAAa,KAApB,MAAM,CAAC,aAAa,GAAK,EAAE,EAAC;YAC5B,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CACvD,QAAQ,CAAC,aAAa,CACvB,EAAE,CAAC;gBACF,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG;oBAChC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;oBAC1C,GAAG,eAAe;iBACnB,CAAC;YACJ,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YACxB,MAAM,CAAC,UAAU,GAAG;gBAClB,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;gBAC5B,GAAG,QAAQ,CAAC,UAAU;aACvB,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACzB,MAAM,CAAC,WAAW,GAAG;gBACnB,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;gBAC7B,GAAG,QAAQ,CAAC,WAAW;aACxB,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,GAAG;gBACd,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;gBACxB,GAAG,QAAQ,CAAC,MAAM;aACnB,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;YAC5B,MAAM,CAAC,cAAc,GAAG;gBACtB,GAAG,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;gBAChC,GAAG,QAAQ,CAAC,cAAc;aAC3B,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;YACnC,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,MAAM,CAAC,UAAU,KAAjB,MAAM,CAAC,UAAU,GAAK,OAAO,EAAC;IAE9B,OAAO,MAAM,CAAC;AAChB,CAAC;AA9CD,gDA8CC;AAED,+EAA+E;AAC/E,8BAA8B;AAC9B,+EAA+E;AAE/E,MAAM,gCAAgC,GAAG,2BAA2B,CAAC;AAErE,kEAAkE;AAClE,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAS9B;;;;;;;;GAQG;AACH,SAAS,uBAAuB,CAC9B,OAAoB,EACpB,OAAwB;IAExB,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC7B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAW,CAAC;IAEpC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QAC5B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACxD,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CACrC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAC/C,CAAC;QACF,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAElD,OAAO;YACL,GAAG,OAAO;YACV,QAAQ,EAAE,eAAe;SAC1B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB,CACxB,QAAuB,EACvB,OAAqC;IAErC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAW,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC;QAChD,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC3C,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpB,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,+BAA+B,CAAC,OAAwB;IAItE,OAAO;QACL,OAAO;YACL,OAAO,gCAAgC,CAAC;QAC1C,CAAC;QAED,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAoB,EAAE;YAC1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;YAED,MAAM,QAAQ,GAAG,KAAK,EAAE,GAAmB,EAA2B,EAAE,CACtE,GAAG,CAAC;YACN,MAAM,KAAK,GAAG,IAAA,iBAAM,EAAC,mBAAmB,CAAC,CAAC;YAE1C,uEAAuE;YACvE,MAAM,QAAQ,GAAG,uBAAuB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACnE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CACxB,KAAK,CAAC,GAAG,EAAE,CACT,MAAM,CAAC,gBAAgB,CACrB;gBACE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACpB,QAAQ,EAAE,EAAE;gBACZ,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,EACD,QAAQ,CACT,CACF,CACF,CACF,CAAC;YAEF,IAAI,cAAc,GAAG,kBAAkB,CACrC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CACzC,CAAC;YAEF,8EAA8E;YAC9E,MAAM,cAAc,GAAG,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC5D,IAAI,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,eAAe,GAAgB;oBACnC,GAAG,OAAO,CAAC,OAAO;oBAClB,QAAQ,EAAE,CAAC,GAAG,cAAc,CAAC;iBAC9B,CAAC;gBACF,MAAM,gBAAgB,GAAG,uBAAuB,CAC9C,eAAe,EACf,OAAO,CACR,CAAC;gBACF,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CACvC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CACxB,KAAK,CAAC,GAAG,EAAE,CACT,MAAM,CAAC,gBAAgB,CACrB;oBACE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;oBAC5B,QAAQ,EAAE,EAAE;oBACZ,cAAc,EAAE,OAAO,CAAC,cAAc;iBACvC,EACD,QAAQ,CACT,CACF,CACF,CACF,CAAC;gBACF,MAAM,cAAc,GAAG,kBAAkB,CACvC,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CACjD,CAAC;gBACF,cAAc,GAAG,kBAAkB,CAAC,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;gBACtE,uEAAuE;gBACvE,IAAI,cAAc,CAAC,MAAM,IAAI,cAAc,CAAC,aAAa,EAAE,CAAC;oBAC1D,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAW,CAAC;oBAC7C,KAAK,MAAM,eAAe,IAAI,MAAM,CAAC,MAAM,CACzC,cAAc,CAAC,aAAa,CAC7B,EAAE,CAAC;wBACF,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;4BACnD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAY,CAAC;4BACjD,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;wBACjC,CAAC;oBACH,CAAC;oBACD,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;wBACrC,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;4BACnC,OAAO,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;wBACxC,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,IAAI,CAAC;gBACV,GAAG,OAAO;gBACV,QAAQ,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;aACjE,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AA7FD,0EA6FC;AAED,+EAA+E;AAC/E,kCAAkC;AAClC,+EAA+E;AAE/E,MAAM,wBAAwB,GAAG,oBAAoB,CAAC;AAEtD,+CAA+C;AAC/C,MAAM,WAAW,GAAG,CAAC,CAAC;AAOtB;;;;;;;;GAQG;AACH,SAAgB,wBAAwB,CAAC,OAA2B;IAIlE,OAAO;QACL,OAAO;YACL,OAAO,wBAAwB,CAAC;QAClC,CAAC;QAED,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAoB,EAAE;YAC1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;YAED,MAAM,QAAQ,GAAG,KAAK,EAAE,GAAmB,EAA2B,EAAE,CACtE,GAAG,CAAC;YACN,MAAM,KAAK,GAAG,IAAA,iBAAM,EAAC,WAAW,CAAC,CAAC;YAElC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACrB,KAAK,CAAC,GAAG,EAAE,CACT,MAAM,CAAC,gBAAgB,CACrB;gBACE,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,QAAQ,EAAE,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE;gBACjC,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,EACD,QAAQ,CACT,CACF,CACF,CACF,CAAC;YAEF,MAAM,cAAc,GAAG,kBAAkB,CACvC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CACzC,CAAC;YAEF,OAAO,IAAI,CAAC;gBACV,GAAG,OAAO;gBACV,QAAQ,EAAE,kBAAkB,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;aACjE,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AA3CD,4DA2CC","sourcesContent":["import pLimit from 'p-limit';\n\nimport type {\n ChainId,\n Context,\n DataRequest,\n DataResponse,\n Middleware,\n} from '../types';\n\n// ============================================================================\n// MERGE HELPER\n// ============================================================================\n\n/**\n * Deep-merge multiple DataResponses into one.\n * Used when running balance data sources in parallel.\n *\n * @param responses - Array of DataResponse from each source.\n * @returns Single merged DataResponse.\n */\nexport function mergeDataResponses(responses: DataResponse[]): DataResponse {\n const merged: DataResponse = {};\n\n for (const response of responses) {\n if (response.assetsBalance) {\n merged.assetsBalance ??= {};\n for (const [accountId, accountBalances] of Object.entries(\n response.assetsBalance,\n )) {\n merged.assetsBalance[accountId] = {\n ...(merged.assetsBalance[accountId] ?? {}),\n ...accountBalances,\n };\n }\n }\n if (response.assetsInfo) {\n merged.assetsInfo = {\n ...(merged.assetsInfo ?? {}),\n ...response.assetsInfo,\n };\n }\n if (response.assetsPrice) {\n merged.assetsPrice = {\n ...(merged.assetsPrice ?? {}),\n ...response.assetsPrice,\n };\n }\n if (response.errors) {\n merged.errors = {\n ...(merged.errors ?? {}),\n ...response.errors,\n };\n }\n if (response.detectedAssets) {\n merged.detectedAssets = {\n ...(merged.detectedAssets ?? {}),\n ...response.detectedAssets,\n };\n }\n if (response.updateMode === 'full') {\n merged.updateMode = 'full';\n }\n }\n merged.updateMode ??= 'merge';\n\n return merged;\n}\n\n// ============================================================================\n// PARALLEL BALANCE MIDDLEWARE\n// ============================================================================\n\nconst PARALLEL_BALANCE_MIDDLEWARE_NAME = 'ParallelBalanceMiddleware';\n\n/** Max concurrent balance source calls (round 1 and fallback). */\nconst BALANCE_CONCURRENCY = 3;\n\nexport type BalanceSource = {\n getName(): string;\n /** Chains this source can fetch (e.g. from getActiveChainsSync()). Used to partition chains with no overlap. */\n getActiveChainsSync(): ChainId[];\n assetsMiddleware: Middleware;\n};\n\n/**\n * Partition request.chainIds so each chain is assigned to exactly one source\n * (by source order: first source that supports the chain gets it). Ensures no\n * chain overlap across data source calls.\n *\n * @param request - The data request with chainIds to partition.\n * @param sources - Balance sources in priority order (e.g. AccountsAPI, Snap, Rpc).\n * @returns Array of requests, one per source, each with only that source's assigned chainIds.\n */\nfunction partitionChainsBySource(\n request: DataRequest,\n sources: BalanceSource[],\n): DataRequest[] {\n const { chainIds } = request;\n const assigned = new Set<ChainId>();\n\n return sources.map((source) => {\n const supported = new Set(source.getActiveChainsSync());\n const chainsForSource = chainIds.filter(\n (id) => supported.has(id) && !assigned.has(id),\n );\n chainsForSource.forEach((id) => assigned.add(id));\n\n return {\n ...request,\n chainIds: chainsForSource,\n };\n });\n}\n\n/**\n * Collect chain IDs that failed in the first round (present in response.errors).\n * Used to run a fallback round with remaining sources.\n *\n * @param requests - Partitioned requests, one per source (same order as results).\n * @param results - Results from each source; chain IDs in requests[i] that have errors in results[i].response.errors are considered failed.\n * @returns Set of chain IDs that had errors in the first round.\n */\nfunction getFailedChainIds(\n requests: DataRequest[],\n results: { response: DataResponse }[],\n): Set<ChainId> {\n const failed = new Set<ChainId>();\n for (let i = 0; i < results.length; i++) {\n const errors = results[i].response.errors ?? {};\n for (const chainId of requests[i].chainIds) {\n if (errors[chainId]) {\n failed.add(chainId);\n }\n }\n }\n return failed;\n}\n\n/**\n * Middleware that runs multiple balance data source middlewares in parallel,\n * with no chain overlap. Chains that fail (response.errors) are re-partitioned\n * and fetched again in a fallback round so lower-priority sources can try them.\n *\n * @param sources - Array of balance sources in priority order (each with getName(), getActiveChainsSync(), assetsMiddleware).\n * @returns A single middleware that runs all sources in parallel and merges responses.\n */\nexport function createParallelBalanceMiddleware(sources: BalanceSource[]): {\n getName(): string;\n assetsMiddleware: Middleware;\n} {\n return {\n getName(): string {\n return PARALLEL_BALANCE_MIDDLEWARE_NAME;\n },\n\n assetsMiddleware: async (context, next): Promise<Context> => {\n if (sources.length === 0) {\n return next(context);\n }\n\n const noopNext = async (ctx: typeof context): Promise<typeof context> =>\n ctx;\n const limit = pLimit(BALANCE_CONCURRENCY);\n\n // Round 1: partition chains (no overlap), run with limited concurrency\n const requests = partitionChainsBySource(context.request, sources);\n const results = await Promise.all(\n sources.map((source, i) =>\n limit(() =>\n source.assetsMiddleware(\n {\n request: requests[i],\n response: {},\n getAssetsState: context.getAssetsState,\n },\n noopNext,\n ),\n ),\n ),\n );\n\n let mergedResponse = mergeDataResponses(\n results.map((result) => result.response),\n );\n\n // Fallback: chains that failed (in errors) get re-partitioned and tried again\n const failedChainIds = getFailedChainIds(requests, results);\n if (failedChainIds.size > 0) {\n const fallbackRequest: DataRequest = {\n ...context.request,\n chainIds: [...failedChainIds],\n };\n const fallbackRequests = partitionChainsBySource(\n fallbackRequest,\n sources,\n );\n const fallbackResults = await Promise.all(\n sources.map((source, i) =>\n limit(() =>\n source.assetsMiddleware(\n {\n request: fallbackRequests[i],\n response: {},\n getAssetsState: context.getAssetsState,\n },\n noopNext,\n ),\n ),\n ),\n );\n const fallbackMerged = mergeDataResponses(\n fallbackResults.map((result) => result.response),\n );\n mergedResponse = mergeDataResponses([mergedResponse, fallbackMerged]);\n // Remove errors for chains we successfully got balance for in fallback\n if (mergedResponse.errors && mergedResponse.assetsBalance) {\n const chainsWithBalance = new Set<ChainId>();\n for (const accountBalances of Object.values(\n mergedResponse.assetsBalance,\n )) {\n for (const assetId of Object.keys(accountBalances)) {\n const chainId = assetId.split('/')[0] as ChainId;\n chainsWithBalance.add(chainId);\n }\n }\n for (const chainId of failedChainIds) {\n if (chainsWithBalance.has(chainId)) {\n delete mergedResponse.errors[chainId];\n }\n }\n }\n }\n\n return next({\n ...context,\n response: mergeDataResponses([context.response, mergedResponse]),\n });\n },\n };\n}\n\n// ============================================================================\n// PARALLEL TOKEN/PRICE MIDDLEWARE\n// ============================================================================\n\nconst PARALLEL_MIDDLEWARE_NAME = 'ParallelMiddleware';\n\n/** Max concurrent token/price source calls. */\nconst CONCURRENCY = 2;\n\nexport type TokenPriceSource = {\n getName(): string;\n assetsMiddleware: Middleware;\n};\n\n/**\n * Middleware that runs multiple data source middlewares (e.g. TokenDataSource,\n * PriceDataSource) in parallel with the same request. Responses are merged so\n * that assetsInfo (token metadata) and assetsPrice are combined. Use this to\n * fetch token and price data concurrently instead of sequentially.\n *\n * @param sources - Array of sources with getName() and assetsMiddleware.\n * @returns A single middleware that runs all sources in parallel and merges responses.\n */\nexport function createParallelMiddleware(sources: TokenPriceSource[]): {\n getName(): string;\n assetsMiddleware: Middleware;\n} {\n return {\n getName(): string {\n return PARALLEL_MIDDLEWARE_NAME;\n },\n\n assetsMiddleware: async (context, next): Promise<Context> => {\n if (sources.length === 0) {\n return next(context);\n }\n\n const noopNext = async (ctx: typeof context): Promise<typeof context> =>\n ctx;\n const limit = pLimit(CONCURRENCY);\n\n const results = await Promise.all(\n sources.map((source) =>\n limit(() =>\n source.assetsMiddleware(\n {\n request: context.request,\n response: { ...context.response },\n getAssetsState: context.getAssetsState,\n },\n noopNext,\n ),\n ),\n ),\n );\n\n const mergedResponse = mergeDataResponses(\n results.map((result) => result.response),\n );\n\n return next({\n ...context,\n response: mergeDataResponses([context.response, mergedResponse]),\n });\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ChainId, DataResponse, Middleware } from "../types.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Deep-merge multiple DataResponses into one.
|
|
4
|
+
* Used when running balance data sources in parallel.
|
|
5
|
+
*
|
|
6
|
+
* @param responses - Array of DataResponse from each source.
|
|
7
|
+
* @returns Single merged DataResponse.
|
|
8
|
+
*/
|
|
9
|
+
export declare function mergeDataResponses(responses: DataResponse[]): DataResponse;
|
|
10
|
+
export type BalanceSource = {
|
|
11
|
+
getName(): string;
|
|
12
|
+
/** Chains this source can fetch (e.g. from getActiveChainsSync()). Used to partition chains with no overlap. */
|
|
13
|
+
getActiveChainsSync(): ChainId[];
|
|
14
|
+
assetsMiddleware: Middleware;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Middleware that runs multiple balance data source middlewares in parallel,
|
|
18
|
+
* with no chain overlap. Chains that fail (response.errors) are re-partitioned
|
|
19
|
+
* and fetched again in a fallback round so lower-priority sources can try them.
|
|
20
|
+
*
|
|
21
|
+
* @param sources - Array of balance sources in priority order (each with getName(), getActiveChainsSync(), assetsMiddleware).
|
|
22
|
+
* @returns A single middleware that runs all sources in parallel and merges responses.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createParallelBalanceMiddleware(sources: BalanceSource[]): {
|
|
25
|
+
getName(): string;
|
|
26
|
+
assetsMiddleware: Middleware;
|
|
27
|
+
};
|
|
28
|
+
export type TokenPriceSource = {
|
|
29
|
+
getName(): string;
|
|
30
|
+
assetsMiddleware: Middleware;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Middleware that runs multiple data source middlewares (e.g. TokenDataSource,
|
|
34
|
+
* PriceDataSource) in parallel with the same request. Responses are merged so
|
|
35
|
+
* that assetsInfo (token metadata) and assetsPrice are combined. Use this to
|
|
36
|
+
* fetch token and price data concurrently instead of sequentially.
|
|
37
|
+
*
|
|
38
|
+
* @param sources - Array of sources with getName() and assetsMiddleware.
|
|
39
|
+
* @returns A single middleware that runs all sources in parallel and merges responses.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createParallelMiddleware(sources: TokenPriceSource[]): {
|
|
42
|
+
getName(): string;
|
|
43
|
+
assetsMiddleware: Middleware;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=ParallelMiddleware.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParallelMiddleware.d.cts","sourceRoot":"","sources":["../../src/middlewares/ParallelMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,OAAO,EAGP,YAAY,EACZ,UAAU,EACX,qBAAiB;AAMlB;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,YAAY,CA8C1E;AAWD,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,IAAI,MAAM,CAAC;IAClB,gHAAgH;IAChH,mBAAmB,IAAI,OAAO,EAAE,CAAC;IACjC,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAAC;AAwDF;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG;IACzE,OAAO,IAAI,MAAM,CAAC;IAClB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CA0FA;AAWD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,IAAI,MAAM,CAAC;IAClB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG;IACrE,OAAO,IAAI,MAAM,CAAC;IAClB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAwCA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ChainId, DataResponse, Middleware } from "../types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Deep-merge multiple DataResponses into one.
|
|
4
|
+
* Used when running balance data sources in parallel.
|
|
5
|
+
*
|
|
6
|
+
* @param responses - Array of DataResponse from each source.
|
|
7
|
+
* @returns Single merged DataResponse.
|
|
8
|
+
*/
|
|
9
|
+
export declare function mergeDataResponses(responses: DataResponse[]): DataResponse;
|
|
10
|
+
export type BalanceSource = {
|
|
11
|
+
getName(): string;
|
|
12
|
+
/** Chains this source can fetch (e.g. from getActiveChainsSync()). Used to partition chains with no overlap. */
|
|
13
|
+
getActiveChainsSync(): ChainId[];
|
|
14
|
+
assetsMiddleware: Middleware;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Middleware that runs multiple balance data source middlewares in parallel,
|
|
18
|
+
* with no chain overlap. Chains that fail (response.errors) are re-partitioned
|
|
19
|
+
* and fetched again in a fallback round so lower-priority sources can try them.
|
|
20
|
+
*
|
|
21
|
+
* @param sources - Array of balance sources in priority order (each with getName(), getActiveChainsSync(), assetsMiddleware).
|
|
22
|
+
* @returns A single middleware that runs all sources in parallel and merges responses.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createParallelBalanceMiddleware(sources: BalanceSource[]): {
|
|
25
|
+
getName(): string;
|
|
26
|
+
assetsMiddleware: Middleware;
|
|
27
|
+
};
|
|
28
|
+
export type TokenPriceSource = {
|
|
29
|
+
getName(): string;
|
|
30
|
+
assetsMiddleware: Middleware;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Middleware that runs multiple data source middlewares (e.g. TokenDataSource,
|
|
34
|
+
* PriceDataSource) in parallel with the same request. Responses are merged so
|
|
35
|
+
* that assetsInfo (token metadata) and assetsPrice are combined. Use this to
|
|
36
|
+
* fetch token and price data concurrently instead of sequentially.
|
|
37
|
+
*
|
|
38
|
+
* @param sources - Array of sources with getName() and assetsMiddleware.
|
|
39
|
+
* @returns A single middleware that runs all sources in parallel and merges responses.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createParallelMiddleware(sources: TokenPriceSource[]): {
|
|
42
|
+
getName(): string;
|
|
43
|
+
assetsMiddleware: Middleware;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=ParallelMiddleware.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParallelMiddleware.d.mts","sourceRoot":"","sources":["../../src/middlewares/ParallelMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,OAAO,EAGP,YAAY,EACZ,UAAU,EACX,qBAAiB;AAMlB;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,YAAY,CA8C1E;AAWD,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,IAAI,MAAM,CAAC;IAClB,gHAAgH;IAChH,mBAAmB,IAAI,OAAO,EAAE,CAAC;IACjC,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAAC;AAwDF;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG;IACzE,OAAO,IAAI,MAAM,CAAC;IAClB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CA0FA;AAWD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,IAAI,MAAM,CAAC;IAClB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG;IACrE,OAAO,IAAI,MAAM,CAAC;IAClB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAwCA"}
|