@metamask-previews/ai-controllers 0.0.0-preview-a196307b6 → 0.0.0-preview-bbc71c9d5
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 +13 -2
- package/dist/AiDigestController.cjs +10 -81
- package/dist/AiDigestController.cjs.map +1 -1
- package/dist/AiDigestController.d.cts +2 -27
- package/dist/AiDigestController.d.cts.map +1 -1
- package/dist/AiDigestController.d.mts +2 -27
- package/dist/AiDigestController.d.mts.map +1 -1
- package/dist/AiDigestController.mjs +11 -82
- package/dist/AiDigestController.mjs.map +1 -1
- package/dist/AiDigestService.cjs +28 -14
- package/dist/AiDigestService.cjs.map +1 -1
- package/dist/AiDigestService.d.cts +3 -3
- package/dist/AiDigestService.d.cts.map +1 -1
- package/dist/AiDigestService.d.mts +3 -3
- package/dist/AiDigestService.d.mts.map +1 -1
- package/dist/AiDigestService.mjs +28 -14
- package/dist/AiDigestService.mjs.map +1 -1
- package/dist/ai-digest-constants.cjs +2 -1
- package/dist/ai-digest-constants.cjs.map +1 -1
- package/dist/ai-digest-constants.d.cts +2 -1
- package/dist/ai-digest-constants.d.cts.map +1 -1
- package/dist/ai-digest-constants.d.mts +2 -1
- package/dist/ai-digest-constants.d.mts.map +1 -1
- package/dist/ai-digest-constants.mjs +2 -1
- package/dist/ai-digest-constants.mjs.map +1 -1
- package/dist/ai-digest-types.cjs.map +1 -1
- package/dist/ai-digest-types.d.cts +4 -28
- package/dist/ai-digest-types.d.cts.map +1 -1
- package/dist/ai-digest-types.d.mts +4 -28
- package/dist/ai-digest-types.d.mts.map +1 -1
- package/dist/ai-digest-types.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -11,7 +11,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
11
|
|
|
12
12
|
- Initial release ([#7693](https://github.com/MetaMask/core/pull/7693))
|
|
13
13
|
- Add `AiDigestController` for fetching and caching AI-generated asset digests ([#7746](https://github.com/MetaMask/core/pull/7746))
|
|
14
|
-
- Add Market Insights support to `AiDigestController` with `fetchMarketInsights`
|
|
15
|
-
- Add `
|
|
14
|
+
- Add Market Insights support to `AiDigestController` with `fetchMarketInsights` action ([#7930](https://github.com/MetaMask/core/pull/7930))
|
|
15
|
+
- Add `searchDigest` method to `AiDigestService` for calling the GET endpoint (currently mocked) ([#7930](https://github.com/MetaMask/core/pull/7930))
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Validate `searchDigest` API responses and throw when the payload does not match the expected `MarketInsightsReport` shape.
|
|
20
|
+
- Normalize `searchDigest` responses from either direct report payloads or `digest` envelope payloads.
|
|
21
|
+
|
|
22
|
+
### Removed
|
|
23
|
+
|
|
24
|
+
- Remove legacy digest APIs and digest cache from `AiDigestController` and `AiDigestService`; only market insights APIs remain.
|
|
25
|
+
- Removes `fetchDigest`, `clearDigest`, and `clearAllDigests` actions from the controller action surface.
|
|
26
|
+
- Removes `DigestData`/`DigestEntry` types and the `digests` state branch.
|
|
16
27
|
|
|
17
28
|
[Unreleased]: https://github.com/MetaMask/core/
|
|
@@ -10,25 +10,19 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
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
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _AiDigestController_instances, _AiDigestController_digestService, _AiDigestController_registerMessageHandlers,
|
|
13
|
+
var _AiDigestController_instances, _AiDigestController_digestService, _AiDigestController_registerMessageHandlers, _AiDigestController_evictStaleCachedEntries;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.AiDigestController = exports.getDefaultAiDigestControllerState = void 0;
|
|
16
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
17
|
+
const utils_1 = require("@metamask/utils");
|
|
17
18
|
const ai_digest_constants_1 = require("./ai-digest-constants.cjs");
|
|
18
19
|
function getDefaultAiDigestControllerState() {
|
|
19
20
|
return {
|
|
20
|
-
digests: {},
|
|
21
21
|
marketInsights: {},
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
exports.getDefaultAiDigestControllerState = getDefaultAiDigestControllerState;
|
|
25
25
|
const aiDigestControllerMetadata = {
|
|
26
|
-
digests: {
|
|
27
|
-
persist: true,
|
|
28
|
-
includeInDebugSnapshot: true,
|
|
29
|
-
includeInStateLogs: true,
|
|
30
|
-
usedInUi: true,
|
|
31
|
-
},
|
|
32
26
|
marketInsights: {
|
|
33
27
|
persist: true,
|
|
34
28
|
includeInDebugSnapshot: true,
|
|
@@ -52,36 +46,6 @@ class AiDigestController extends base_controller_1.BaseController {
|
|
|
52
46
|
__classPrivateFieldSet(this, _AiDigestController_digestService, digestService, "f");
|
|
53
47
|
__classPrivateFieldGet(this, _AiDigestController_instances, "m", _AiDigestController_registerMessageHandlers).call(this);
|
|
54
48
|
}
|
|
55
|
-
async fetchDigest(assetId) {
|
|
56
|
-
const existingDigest = this.state.digests[assetId];
|
|
57
|
-
if (existingDigest) {
|
|
58
|
-
const age = Date.now() - existingDigest.fetchedAt;
|
|
59
|
-
if (age < ai_digest_constants_1.CACHE_DURATION_MS) {
|
|
60
|
-
return existingDigest.data;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const data = await __classPrivateFieldGet(this, _AiDigestController_digestService, "f").fetchDigest(assetId);
|
|
64
|
-
const entry = {
|
|
65
|
-
asset: assetId,
|
|
66
|
-
fetchedAt: Date.now(),
|
|
67
|
-
data,
|
|
68
|
-
};
|
|
69
|
-
this.update((state) => {
|
|
70
|
-
state.digests[assetId] = entry;
|
|
71
|
-
__classPrivateFieldGet(this, _AiDigestController_instances, "m", _AiDigestController_evictStaleEntries).call(this, state);
|
|
72
|
-
});
|
|
73
|
-
return data;
|
|
74
|
-
}
|
|
75
|
-
clearDigest(assetId) {
|
|
76
|
-
this.update((state) => {
|
|
77
|
-
delete state.digests[assetId];
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
clearAllDigests() {
|
|
81
|
-
this.update((state) => {
|
|
82
|
-
state.digests = {};
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
49
|
/**
|
|
86
50
|
* Fetches market insights for a given CAIP-19 asset identifier.
|
|
87
51
|
* Returns cached data if still fresh, otherwise calls the service.
|
|
@@ -90,6 +54,9 @@ class AiDigestController extends base_controller_1.BaseController {
|
|
|
90
54
|
* @returns The market insights report, or `null` if none exists.
|
|
91
55
|
*/
|
|
92
56
|
async fetchMarketInsights(caip19Id) {
|
|
57
|
+
if (!(0, utils_1.isCaipAssetType)(caip19Id)) {
|
|
58
|
+
throw new Error(ai_digest_constants_1.AiDigestControllerErrorMessage.INVALID_CAIP_ASSET_TYPE);
|
|
59
|
+
}
|
|
93
60
|
const existing = this.state.marketInsights[caip19Id];
|
|
94
61
|
if (existing) {
|
|
95
62
|
const age = Date.now() - existing.fetchedAt;
|
|
@@ -97,7 +64,7 @@ class AiDigestController extends base_controller_1.BaseController {
|
|
|
97
64
|
return existing.data;
|
|
98
65
|
}
|
|
99
66
|
}
|
|
100
|
-
const data = await __classPrivateFieldGet(this, _AiDigestController_digestService, "f").
|
|
67
|
+
const data = await __classPrivateFieldGet(this, _AiDigestController_digestService, "f").searchDigest(caip19Id);
|
|
101
68
|
if (data === null) {
|
|
102
69
|
// No insights available for this asset — clear any stale cache entry
|
|
103
70
|
this.update((state) => {
|
|
@@ -112,55 +79,17 @@ class AiDigestController extends base_controller_1.BaseController {
|
|
|
112
79
|
};
|
|
113
80
|
this.update((state) => {
|
|
114
81
|
state.marketInsights[caip19Id] = entry;
|
|
115
|
-
__classPrivateFieldGet(this, _AiDigestController_instances, "m",
|
|
82
|
+
__classPrivateFieldGet(this, _AiDigestController_instances, "m", _AiDigestController_evictStaleCachedEntries).call(this, state.marketInsights);
|
|
116
83
|
});
|
|
117
84
|
return data;
|
|
118
85
|
}
|
|
119
|
-
/**
|
|
120
|
-
* Clears the cached market insights for a specific CAIP-19 asset.
|
|
121
|
-
*
|
|
122
|
-
* @param caip19Id - The CAIP-19 identifier.
|
|
123
|
-
*/
|
|
124
|
-
clearMarketInsights(caip19Id) {
|
|
125
|
-
this.update((state) => {
|
|
126
|
-
delete state.marketInsights[caip19Id];
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
86
|
}
|
|
130
87
|
exports.AiDigestController = AiDigestController;
|
|
131
88
|
_AiDigestController_digestService = new WeakMap(), _AiDigestController_instances = new WeakSet(), _AiDigestController_registerMessageHandlers = function _AiDigestController_registerMessageHandlers() {
|
|
132
|
-
this.messenger.registerActionHandler(`${ai_digest_constants_1.controllerName}:fetchDigest`, this.fetchDigest.bind(this));
|
|
133
|
-
this.messenger.registerActionHandler(`${ai_digest_constants_1.controllerName}:clearDigest`, this.clearDigest.bind(this));
|
|
134
|
-
this.messenger.registerActionHandler(`${ai_digest_constants_1.controllerName}:clearAllDigests`, this.clearAllDigests.bind(this));
|
|
135
89
|
this.messenger.registerActionHandler(`${ai_digest_constants_1.controllerName}:fetchMarketInsights`, this.fetchMarketInsights.bind(this));
|
|
136
|
-
|
|
137
|
-
}, _AiDigestController_evictStaleEntries = function _AiDigestController_evictStaleEntries(state) {
|
|
138
|
-
const now = Date.now();
|
|
139
|
-
const entries = Object.entries(state.digests);
|
|
140
|
-
const keysToDelete = [];
|
|
141
|
-
const freshEntries = [];
|
|
142
|
-
for (const [key, entry] of entries) {
|
|
143
|
-
if (now - entry.fetchedAt >= ai_digest_constants_1.CACHE_DURATION_MS) {
|
|
144
|
-
keysToDelete.push(key);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
freshEntries.push([key, entry]);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
// Evict oldest entries if over max cache size
|
|
151
|
-
if (freshEntries.length > ai_digest_constants_1.MAX_CACHE_ENTRIES) {
|
|
152
|
-
freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);
|
|
153
|
-
const entriesToRemove = freshEntries.length - ai_digest_constants_1.MAX_CACHE_ENTRIES;
|
|
154
|
-
for (let i = 0; i < entriesToRemove; i++) {
|
|
155
|
-
keysToDelete.push(freshEntries[i][0]);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
for (const key of keysToDelete) {
|
|
159
|
-
delete state.digests[key];
|
|
160
|
-
}
|
|
161
|
-
}, _AiDigestController_evictStaleMarketInsightsEntries = function _AiDigestController_evictStaleMarketInsightsEntries(state) {
|
|
90
|
+
}, _AiDigestController_evictStaleCachedEntries = function _AiDigestController_evictStaleCachedEntries(cache) {
|
|
162
91
|
const now = Date.now();
|
|
163
|
-
const entries = Object.entries(
|
|
92
|
+
const entries = Object.entries(cache);
|
|
164
93
|
const keysToDelete = [];
|
|
165
94
|
const freshEntries = [];
|
|
166
95
|
for (const [key, entry] of entries) {
|
|
@@ -179,7 +108,7 @@ _AiDigestController_digestService = new WeakMap(), _AiDigestController_instances
|
|
|
179
108
|
}
|
|
180
109
|
}
|
|
181
110
|
for (const key of keysToDelete) {
|
|
182
|
-
delete
|
|
111
|
+
delete cache[key];
|
|
183
112
|
}
|
|
184
113
|
};
|
|
185
114
|
//# sourceMappingURL=AiDigestController.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestController.cjs","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n StateMetadata,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport {\n controllerName,\n CACHE_DURATION_MS,\n MAX_CACHE_ENTRIES,\n} from './ai-digest-constants';\nimport type {\n AiDigestControllerState,\n DigestEntry,\n DigestService,\n DigestData,\n MarketInsightsReport,\n MarketInsightsEntry,\n} from './ai-digest-types';\n\nexport type AiDigestControllerFetchDigestAction = {\n type: `${typeof controllerName}:fetchDigest`;\n handler: AiDigestController['fetchDigest'];\n};\n\nexport type AiDigestControllerClearDigestAction = {\n type: `${typeof controllerName}:clearDigest`;\n handler: AiDigestController['clearDigest'];\n};\n\nexport type AiDigestControllerClearAllDigestsAction = {\n type: `${typeof controllerName}:clearAllDigests`;\n handler: AiDigestController['clearAllDigests'];\n};\n\nexport type AiDigestControllerFetchMarketInsightsAction = {\n type: `${typeof controllerName}:fetchMarketInsights`;\n handler: AiDigestController['fetchMarketInsights'];\n};\n\nexport type AiDigestControllerClearMarketInsightsAction = {\n type: `${typeof controllerName}:clearMarketInsights`;\n handler: AiDigestController['clearMarketInsights'];\n};\n\nexport type AiDigestControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerActions =\n | AiDigestControllerFetchDigestAction\n | AiDigestControllerClearDigestAction\n | AiDigestControllerClearAllDigestsAction\n | AiDigestControllerFetchMarketInsightsAction\n | AiDigestControllerClearMarketInsightsAction\n | AiDigestControllerGetStateAction;\n\nexport type AiDigestControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerEvents = AiDigestControllerStateChangeEvent;\n\nexport type AiDigestControllerMessenger = Messenger<\n typeof controllerName,\n AiDigestControllerActions,\n AiDigestControllerEvents\n>;\n\nexport type AiDigestControllerOptions = {\n messenger: AiDigestControllerMessenger;\n state?: Partial<AiDigestControllerState>;\n digestService: DigestService;\n};\n\nexport function getDefaultAiDigestControllerState(): AiDigestControllerState {\n return {\n digests: {},\n marketInsights: {},\n };\n}\n\nconst aiDigestControllerMetadata: StateMetadata<AiDigestControllerState> = {\n digests: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n marketInsights: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n};\n\nexport class AiDigestController extends BaseController<\n typeof controllerName,\n AiDigestControllerState,\n AiDigestControllerMessenger\n> {\n readonly #digestService: DigestService;\n\n constructor({ messenger, state, digestService }: AiDigestControllerOptions) {\n super({\n name: controllerName,\n metadata: aiDigestControllerMetadata,\n state: {\n ...getDefaultAiDigestControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#digestService = digestService;\n this.#registerMessageHandlers();\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchDigest`,\n this.fetchDigest.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:clearDigest`,\n this.clearDigest.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:clearAllDigests`,\n this.clearAllDigests.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:fetchMarketInsights`,\n this.fetchMarketInsights.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:clearMarketInsights`,\n this.clearMarketInsights.bind(this),\n );\n }\n\n async fetchDigest(assetId: string): Promise<DigestData> {\n const existingDigest = this.state.digests[assetId];\n if (existingDigest) {\n const age = Date.now() - existingDigest.fetchedAt;\n if (age < CACHE_DURATION_MS) {\n return existingDigest.data;\n }\n }\n\n const data = await this.#digestService.fetchDigest(assetId);\n\n const entry: DigestEntry = {\n asset: assetId,\n fetchedAt: Date.now(),\n data,\n };\n\n this.update((state) => {\n state.digests[assetId] = entry;\n this.#evictStaleEntries(state);\n });\n\n return data;\n }\n\n clearDigest(assetId: string): void {\n this.update((state) => {\n delete state.digests[assetId];\n });\n }\n\n clearAllDigests(): void {\n this.update((state) => {\n state.digests = {};\n });\n }\n\n /**\n * Fetches market insights for a given CAIP-19 asset identifier.\n * Returns cached data if still fresh, otherwise calls the service.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if none exists.\n */\n async fetchMarketInsights(\n caip19Id: string,\n ): Promise<MarketInsightsReport | null> {\n const existing = this.state.marketInsights[caip19Id];\n if (existing) {\n const age = Date.now() - existing.fetchedAt;\n if (age < CACHE_DURATION_MS) {\n return existing.data;\n }\n }\n\n const data = await this.#digestService.searchDigests(caip19Id);\n\n if (data === null) {\n // No insights available for this asset — clear any stale cache entry\n this.update((state) => {\n delete state.marketInsights[caip19Id];\n });\n return null;\n }\n\n const entry: MarketInsightsEntry = {\n caip19Id,\n fetchedAt: Date.now(),\n data,\n };\n\n this.update((state) => {\n state.marketInsights[caip19Id] = entry;\n this.#evictStaleMarketInsightsEntries(state);\n });\n\n return data;\n }\n\n /**\n * Clears the cached market insights for a specific CAIP-19 asset.\n *\n * @param caip19Id - The CAIP-19 identifier.\n */\n clearMarketInsights(caip19Id: string): void {\n this.update((state) => {\n delete state.marketInsights[caip19Id];\n });\n }\n\n /**\n * Evicts stale (TTL expired) and oldest entries (FIFO) if cache exceeds max size.\n *\n * @param state - The current controller state to evict entries from.\n */\n #evictStaleEntries(state: AiDigestControllerState): void {\n const now = Date.now();\n const entries = Object.entries(state.digests);\n const keysToDelete: string[] = [];\n const freshEntries: [string, DigestEntry][] = [];\n\n for (const [key, entry] of entries) {\n if (now - entry.fetchedAt >= CACHE_DURATION_MS) {\n keysToDelete.push(key);\n } else {\n freshEntries.push([key, entry]);\n }\n }\n\n // Evict oldest entries if over max cache size\n if (freshEntries.length > MAX_CACHE_ENTRIES) {\n freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);\n const entriesToRemove = freshEntries.length - MAX_CACHE_ENTRIES;\n for (let i = 0; i < entriesToRemove; i++) {\n keysToDelete.push(freshEntries[i][0]);\n }\n }\n\n for (const key of keysToDelete) {\n delete state.digests[key];\n }\n }\n\n /**\n * Evicts stale and oldest market insights entries if cache exceeds max size.\n *\n * @param state - The current controller state to evict entries from.\n */\n #evictStaleMarketInsightsEntries(state: AiDigestControllerState): void {\n const now = Date.now();\n const entries = Object.entries(state.marketInsights);\n const keysToDelete: string[] = [];\n const freshEntries: [string, MarketInsightsEntry][] = [];\n\n for (const [key, entry] of entries) {\n if (now - entry.fetchedAt >= CACHE_DURATION_MS) {\n keysToDelete.push(key);\n } else {\n freshEntries.push([key, entry]);\n }\n }\n\n if (freshEntries.length > MAX_CACHE_ENTRIES) {\n freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);\n const entriesToRemove = freshEntries.length - MAX_CACHE_ENTRIES;\n for (let i = 0; i < entriesToRemove; i++) {\n keysToDelete.push(freshEntries[i][0]);\n }\n }\n\n for (const key of keysToDelete) {\n delete state.marketInsights[key];\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AiDigestController.cjs","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n StateMetadata,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { isCaipAssetType } from '@metamask/utils';\n\nimport {\n AiDigestControllerErrorMessage,\n controllerName,\n CACHE_DURATION_MS,\n MAX_CACHE_ENTRIES,\n} from './ai-digest-constants';\nimport type {\n AiDigestControllerState,\n DigestService,\n MarketInsightsReport,\n MarketInsightsEntry,\n} from './ai-digest-types';\n\nexport type AiDigestControllerFetchMarketInsightsAction = {\n type: `${typeof controllerName}:fetchMarketInsights`;\n handler: AiDigestController['fetchMarketInsights'];\n};\n\nexport type AiDigestControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerActions =\n | AiDigestControllerFetchMarketInsightsAction\n | AiDigestControllerGetStateAction;\n\nexport type AiDigestControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerEvents = AiDigestControllerStateChangeEvent;\n\nexport type AiDigestControllerMessenger = Messenger<\n typeof controllerName,\n AiDigestControllerActions,\n AiDigestControllerEvents\n>;\n\nexport type AiDigestControllerOptions = {\n messenger: AiDigestControllerMessenger;\n state?: Partial<AiDigestControllerState>;\n digestService: DigestService;\n};\n\nexport function getDefaultAiDigestControllerState(): AiDigestControllerState {\n return {\n marketInsights: {},\n };\n}\n\nconst aiDigestControllerMetadata: StateMetadata<AiDigestControllerState> = {\n marketInsights: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n};\n\nexport class AiDigestController extends BaseController<\n typeof controllerName,\n AiDigestControllerState,\n AiDigestControllerMessenger\n> {\n readonly #digestService: DigestService;\n\n constructor({ messenger, state, digestService }: AiDigestControllerOptions) {\n super({\n name: controllerName,\n metadata: aiDigestControllerMetadata,\n state: {\n ...getDefaultAiDigestControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#digestService = digestService;\n this.#registerMessageHandlers();\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchMarketInsights`,\n this.fetchMarketInsights.bind(this),\n );\n }\n\n /**\n * Fetches market insights for a given CAIP-19 asset identifier.\n * Returns cached data if still fresh, otherwise calls the service.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if none exists.\n */\n async fetchMarketInsights(\n caip19Id: string,\n ): Promise<MarketInsightsReport | null> {\n if (!isCaipAssetType(caip19Id)) {\n throw new Error(AiDigestControllerErrorMessage.INVALID_CAIP_ASSET_TYPE);\n }\n\n const existing = this.state.marketInsights[caip19Id];\n if (existing) {\n const age = Date.now() - existing.fetchedAt;\n if (age < CACHE_DURATION_MS) {\n return existing.data;\n }\n }\n\n const data = await this.#digestService.searchDigest(caip19Id);\n\n if (data === null) {\n // No insights available for this asset — clear any stale cache entry\n this.update((state) => {\n delete state.marketInsights[caip19Id];\n });\n return null;\n }\n\n const entry: MarketInsightsEntry = {\n caip19Id,\n fetchedAt: Date.now(),\n data,\n };\n\n this.update((state) => {\n state.marketInsights[caip19Id] = entry;\n this.#evictStaleCachedEntries(state.marketInsights);\n });\n\n return data;\n }\n\n /**\n * Evicts stale (TTL expired) and oldest entries (FIFO) if cache exceeds max size.\n *\n * @param cache - The cache record to evict entries from.\n */\n #evictStaleCachedEntries<EntryType extends { fetchedAt: number }>(\n cache: Record<string, EntryType>,\n ): void {\n const now = Date.now();\n const entries = Object.entries(cache);\n const keysToDelete: string[] = [];\n const freshEntries: [string, EntryType][] = [];\n\n for (const [key, entry] of entries) {\n if (now - entry.fetchedAt >= CACHE_DURATION_MS) {\n keysToDelete.push(key);\n } else {\n freshEntries.push([key, entry]);\n }\n }\n\n if (freshEntries.length > MAX_CACHE_ENTRIES) {\n freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);\n const entriesToRemove = freshEntries.length - MAX_CACHE_ENTRIES;\n for (let i = 0; i < entriesToRemove; i++) {\n keysToDelete.push(freshEntries[i][0]);\n }\n }\n\n for (const key of keysToDelete) {\n delete cache[key];\n }\n }\n}\n"]}
|
|
@@ -2,29 +2,13 @@ import type { ControllerStateChangeEvent, ControllerGetStateAction } from "@meta
|
|
|
2
2
|
import { BaseController } from "@metamask/base-controller";
|
|
3
3
|
import type { Messenger } from "@metamask/messenger";
|
|
4
4
|
import { controllerName } from "./ai-digest-constants.cjs";
|
|
5
|
-
import type { AiDigestControllerState, DigestService,
|
|
6
|
-
export type AiDigestControllerFetchDigestAction = {
|
|
7
|
-
type: `${typeof controllerName}:fetchDigest`;
|
|
8
|
-
handler: AiDigestController['fetchDigest'];
|
|
9
|
-
};
|
|
10
|
-
export type AiDigestControllerClearDigestAction = {
|
|
11
|
-
type: `${typeof controllerName}:clearDigest`;
|
|
12
|
-
handler: AiDigestController['clearDigest'];
|
|
13
|
-
};
|
|
14
|
-
export type AiDigestControllerClearAllDigestsAction = {
|
|
15
|
-
type: `${typeof controllerName}:clearAllDigests`;
|
|
16
|
-
handler: AiDigestController['clearAllDigests'];
|
|
17
|
-
};
|
|
5
|
+
import type { AiDigestControllerState, DigestService, MarketInsightsReport } from "./ai-digest-types.cjs";
|
|
18
6
|
export type AiDigestControllerFetchMarketInsightsAction = {
|
|
19
7
|
type: `${typeof controllerName}:fetchMarketInsights`;
|
|
20
8
|
handler: AiDigestController['fetchMarketInsights'];
|
|
21
9
|
};
|
|
22
|
-
export type AiDigestControllerClearMarketInsightsAction = {
|
|
23
|
-
type: `${typeof controllerName}:clearMarketInsights`;
|
|
24
|
-
handler: AiDigestController['clearMarketInsights'];
|
|
25
|
-
};
|
|
26
10
|
export type AiDigestControllerGetStateAction = ControllerGetStateAction<typeof controllerName, AiDigestControllerState>;
|
|
27
|
-
export type AiDigestControllerActions =
|
|
11
|
+
export type AiDigestControllerActions = AiDigestControllerFetchMarketInsightsAction | AiDigestControllerGetStateAction;
|
|
28
12
|
export type AiDigestControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, AiDigestControllerState>;
|
|
29
13
|
export type AiDigestControllerEvents = AiDigestControllerStateChangeEvent;
|
|
30
14
|
export type AiDigestControllerMessenger = Messenger<typeof controllerName, AiDigestControllerActions, AiDigestControllerEvents>;
|
|
@@ -37,9 +21,6 @@ export declare function getDefaultAiDigestControllerState(): AiDigestControllerS
|
|
|
37
21
|
export declare class AiDigestController extends BaseController<typeof controllerName, AiDigestControllerState, AiDigestControllerMessenger> {
|
|
38
22
|
#private;
|
|
39
23
|
constructor({ messenger, state, digestService }: AiDigestControllerOptions);
|
|
40
|
-
fetchDigest(assetId: string): Promise<DigestData>;
|
|
41
|
-
clearDigest(assetId: string): void;
|
|
42
|
-
clearAllDigests(): void;
|
|
43
24
|
/**
|
|
44
25
|
* Fetches market insights for a given CAIP-19 asset identifier.
|
|
45
26
|
* Returns cached data if still fresh, otherwise calls the service.
|
|
@@ -48,11 +29,5 @@ export declare class AiDigestController extends BaseController<typeof controller
|
|
|
48
29
|
* @returns The market insights report, or `null` if none exists.
|
|
49
30
|
*/
|
|
50
31
|
fetchMarketInsights(caip19Id: string): Promise<MarketInsightsReport | null>;
|
|
51
|
-
/**
|
|
52
|
-
* Clears the cached market insights for a specific CAIP-19 asset.
|
|
53
|
-
*
|
|
54
|
-
* @param caip19Id - The CAIP-19 identifier.
|
|
55
|
-
*/
|
|
56
|
-
clearMarketInsights(caip19Id: string): void;
|
|
57
32
|
}
|
|
58
33
|
//# sourceMappingURL=AiDigestController.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestController.d.cts","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,wBAAwB,EACzB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;
|
|
1
|
+
{"version":3,"file":"AiDigestController.d.cts","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,wBAAwB,EACzB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAGrD,OAAO,EAEL,cAAc,EAGf,kCAA8B;AAC/B,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EAErB,8BAA0B;AAE3B,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,GAAG,OAAO,cAAc,sBAAsB,CAAC;IACrD,OAAO,EAAE,kBAAkB,CAAC,qBAAqB,CAAC,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,wBAAwB,CACrE,OAAO,cAAc,EACrB,uBAAuB,CACxB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC,2CAA2C,GAC3C,gCAAgC,CAAC;AAErC,MAAM,MAAM,kCAAkC,GAAG,0BAA0B,CACzE,OAAO,cAAc,EACrB,uBAAuB,CACxB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,kCAAkC,CAAC;AAE1E,MAAM,MAAM,2BAA2B,GAAG,SAAS,CACjD,OAAO,cAAc,EACrB,yBAAyB,EACzB,wBAAwB,CACzB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,2BAA2B,CAAC;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACzC,aAAa,EAAE,aAAa,CAAC;CAC9B,CAAC;AAEF,wBAAgB,iCAAiC,IAAI,uBAAuB,CAI3E;AAWD,qBAAa,kBAAmB,SAAQ,cAAc,CACpD,OAAO,cAAc,EACrB,uBAAuB,EACvB,2BAA2B,CAC5B;;gBAGa,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,yBAAyB;IAsB1E;;;;;;OAMG;IACG,mBAAmB,CACvB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;CAsExC"}
|
|
@@ -2,29 +2,13 @@ import type { ControllerStateChangeEvent, ControllerGetStateAction } from "@meta
|
|
|
2
2
|
import { BaseController } from "@metamask/base-controller";
|
|
3
3
|
import type { Messenger } from "@metamask/messenger";
|
|
4
4
|
import { controllerName } from "./ai-digest-constants.mjs";
|
|
5
|
-
import type { AiDigestControllerState, DigestService,
|
|
6
|
-
export type AiDigestControllerFetchDigestAction = {
|
|
7
|
-
type: `${typeof controllerName}:fetchDigest`;
|
|
8
|
-
handler: AiDigestController['fetchDigest'];
|
|
9
|
-
};
|
|
10
|
-
export type AiDigestControllerClearDigestAction = {
|
|
11
|
-
type: `${typeof controllerName}:clearDigest`;
|
|
12
|
-
handler: AiDigestController['clearDigest'];
|
|
13
|
-
};
|
|
14
|
-
export type AiDigestControllerClearAllDigestsAction = {
|
|
15
|
-
type: `${typeof controllerName}:clearAllDigests`;
|
|
16
|
-
handler: AiDigestController['clearAllDigests'];
|
|
17
|
-
};
|
|
5
|
+
import type { AiDigestControllerState, DigestService, MarketInsightsReport } from "./ai-digest-types.mjs";
|
|
18
6
|
export type AiDigestControllerFetchMarketInsightsAction = {
|
|
19
7
|
type: `${typeof controllerName}:fetchMarketInsights`;
|
|
20
8
|
handler: AiDigestController['fetchMarketInsights'];
|
|
21
9
|
};
|
|
22
|
-
export type AiDigestControllerClearMarketInsightsAction = {
|
|
23
|
-
type: `${typeof controllerName}:clearMarketInsights`;
|
|
24
|
-
handler: AiDigestController['clearMarketInsights'];
|
|
25
|
-
};
|
|
26
10
|
export type AiDigestControllerGetStateAction = ControllerGetStateAction<typeof controllerName, AiDigestControllerState>;
|
|
27
|
-
export type AiDigestControllerActions =
|
|
11
|
+
export type AiDigestControllerActions = AiDigestControllerFetchMarketInsightsAction | AiDigestControllerGetStateAction;
|
|
28
12
|
export type AiDigestControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, AiDigestControllerState>;
|
|
29
13
|
export type AiDigestControllerEvents = AiDigestControllerStateChangeEvent;
|
|
30
14
|
export type AiDigestControllerMessenger = Messenger<typeof controllerName, AiDigestControllerActions, AiDigestControllerEvents>;
|
|
@@ -37,9 +21,6 @@ export declare function getDefaultAiDigestControllerState(): AiDigestControllerS
|
|
|
37
21
|
export declare class AiDigestController extends BaseController<typeof controllerName, AiDigestControllerState, AiDigestControllerMessenger> {
|
|
38
22
|
#private;
|
|
39
23
|
constructor({ messenger, state, digestService }: AiDigestControllerOptions);
|
|
40
|
-
fetchDigest(assetId: string): Promise<DigestData>;
|
|
41
|
-
clearDigest(assetId: string): void;
|
|
42
|
-
clearAllDigests(): void;
|
|
43
24
|
/**
|
|
44
25
|
* Fetches market insights for a given CAIP-19 asset identifier.
|
|
45
26
|
* Returns cached data if still fresh, otherwise calls the service.
|
|
@@ -48,11 +29,5 @@ export declare class AiDigestController extends BaseController<typeof controller
|
|
|
48
29
|
* @returns The market insights report, or `null` if none exists.
|
|
49
30
|
*/
|
|
50
31
|
fetchMarketInsights(caip19Id: string): Promise<MarketInsightsReport | null>;
|
|
51
|
-
/**
|
|
52
|
-
* Clears the cached market insights for a specific CAIP-19 asset.
|
|
53
|
-
*
|
|
54
|
-
* @param caip19Id - The CAIP-19 identifier.
|
|
55
|
-
*/
|
|
56
|
-
clearMarketInsights(caip19Id: string): void;
|
|
57
32
|
}
|
|
58
33
|
//# sourceMappingURL=AiDigestController.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestController.d.mts","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,wBAAwB,EACzB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;
|
|
1
|
+
{"version":3,"file":"AiDigestController.d.mts","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,wBAAwB,EACzB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAGrD,OAAO,EAEL,cAAc,EAGf,kCAA8B;AAC/B,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EAErB,8BAA0B;AAE3B,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,GAAG,OAAO,cAAc,sBAAsB,CAAC;IACrD,OAAO,EAAE,kBAAkB,CAAC,qBAAqB,CAAC,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,wBAAwB,CACrE,OAAO,cAAc,EACrB,uBAAuB,CACxB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC,2CAA2C,GAC3C,gCAAgC,CAAC;AAErC,MAAM,MAAM,kCAAkC,GAAG,0BAA0B,CACzE,OAAO,cAAc,EACrB,uBAAuB,CACxB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,kCAAkC,CAAC;AAE1E,MAAM,MAAM,2BAA2B,GAAG,SAAS,CACjD,OAAO,cAAc,EACrB,yBAAyB,EACzB,wBAAwB,CACzB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,2BAA2B,CAAC;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACzC,aAAa,EAAE,aAAa,CAAC;CAC9B,CAAC;AAEF,wBAAgB,iCAAiC,IAAI,uBAAuB,CAI3E;AAWD,qBAAa,kBAAmB,SAAQ,cAAc,CACpD,OAAO,cAAc,EACrB,uBAAuB,EACvB,2BAA2B,CAC5B;;gBAGa,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,yBAAyB;IAsB1E;;;;;;OAMG;IACG,mBAAmB,CACvB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;CAsExC"}
|
|
@@ -9,22 +9,16 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
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
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _AiDigestController_instances, _AiDigestController_digestService, _AiDigestController_registerMessageHandlers,
|
|
12
|
+
var _AiDigestController_instances, _AiDigestController_digestService, _AiDigestController_registerMessageHandlers, _AiDigestController_evictStaleCachedEntries;
|
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
|
14
|
-
import {
|
|
14
|
+
import { isCaipAssetType } from "@metamask/utils";
|
|
15
|
+
import { AiDigestControllerErrorMessage, controllerName, CACHE_DURATION_MS, MAX_CACHE_ENTRIES } from "./ai-digest-constants.mjs";
|
|
15
16
|
export function getDefaultAiDigestControllerState() {
|
|
16
17
|
return {
|
|
17
|
-
digests: {},
|
|
18
18
|
marketInsights: {},
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
const aiDigestControllerMetadata = {
|
|
22
|
-
digests: {
|
|
23
|
-
persist: true,
|
|
24
|
-
includeInDebugSnapshot: true,
|
|
25
|
-
includeInStateLogs: true,
|
|
26
|
-
usedInUi: true,
|
|
27
|
-
},
|
|
28
22
|
marketInsights: {
|
|
29
23
|
persist: true,
|
|
30
24
|
includeInDebugSnapshot: true,
|
|
@@ -48,36 +42,6 @@ export class AiDigestController extends BaseController {
|
|
|
48
42
|
__classPrivateFieldSet(this, _AiDigestController_digestService, digestService, "f");
|
|
49
43
|
__classPrivateFieldGet(this, _AiDigestController_instances, "m", _AiDigestController_registerMessageHandlers).call(this);
|
|
50
44
|
}
|
|
51
|
-
async fetchDigest(assetId) {
|
|
52
|
-
const existingDigest = this.state.digests[assetId];
|
|
53
|
-
if (existingDigest) {
|
|
54
|
-
const age = Date.now() - existingDigest.fetchedAt;
|
|
55
|
-
if (age < CACHE_DURATION_MS) {
|
|
56
|
-
return existingDigest.data;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
const data = await __classPrivateFieldGet(this, _AiDigestController_digestService, "f").fetchDigest(assetId);
|
|
60
|
-
const entry = {
|
|
61
|
-
asset: assetId,
|
|
62
|
-
fetchedAt: Date.now(),
|
|
63
|
-
data,
|
|
64
|
-
};
|
|
65
|
-
this.update((state) => {
|
|
66
|
-
state.digests[assetId] = entry;
|
|
67
|
-
__classPrivateFieldGet(this, _AiDigestController_instances, "m", _AiDigestController_evictStaleEntries).call(this, state);
|
|
68
|
-
});
|
|
69
|
-
return data;
|
|
70
|
-
}
|
|
71
|
-
clearDigest(assetId) {
|
|
72
|
-
this.update((state) => {
|
|
73
|
-
delete state.digests[assetId];
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
clearAllDigests() {
|
|
77
|
-
this.update((state) => {
|
|
78
|
-
state.digests = {};
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
45
|
/**
|
|
82
46
|
* Fetches market insights for a given CAIP-19 asset identifier.
|
|
83
47
|
* Returns cached data if still fresh, otherwise calls the service.
|
|
@@ -86,6 +50,9 @@ export class AiDigestController extends BaseController {
|
|
|
86
50
|
* @returns The market insights report, or `null` if none exists.
|
|
87
51
|
*/
|
|
88
52
|
async fetchMarketInsights(caip19Id) {
|
|
53
|
+
if (!isCaipAssetType(caip19Id)) {
|
|
54
|
+
throw new Error(AiDigestControllerErrorMessage.INVALID_CAIP_ASSET_TYPE);
|
|
55
|
+
}
|
|
89
56
|
const existing = this.state.marketInsights[caip19Id];
|
|
90
57
|
if (existing) {
|
|
91
58
|
const age = Date.now() - existing.fetchedAt;
|
|
@@ -93,7 +60,7 @@ export class AiDigestController extends BaseController {
|
|
|
93
60
|
return existing.data;
|
|
94
61
|
}
|
|
95
62
|
}
|
|
96
|
-
const data = await __classPrivateFieldGet(this, _AiDigestController_digestService, "f").
|
|
63
|
+
const data = await __classPrivateFieldGet(this, _AiDigestController_digestService, "f").searchDigest(caip19Id);
|
|
97
64
|
if (data === null) {
|
|
98
65
|
// No insights available for this asset — clear any stale cache entry
|
|
99
66
|
this.update((state) => {
|
|
@@ -108,54 +75,16 @@ export class AiDigestController extends BaseController {
|
|
|
108
75
|
};
|
|
109
76
|
this.update((state) => {
|
|
110
77
|
state.marketInsights[caip19Id] = entry;
|
|
111
|
-
__classPrivateFieldGet(this, _AiDigestController_instances, "m",
|
|
78
|
+
__classPrivateFieldGet(this, _AiDigestController_instances, "m", _AiDigestController_evictStaleCachedEntries).call(this, state.marketInsights);
|
|
112
79
|
});
|
|
113
80
|
return data;
|
|
114
81
|
}
|
|
115
|
-
/**
|
|
116
|
-
* Clears the cached market insights for a specific CAIP-19 asset.
|
|
117
|
-
*
|
|
118
|
-
* @param caip19Id - The CAIP-19 identifier.
|
|
119
|
-
*/
|
|
120
|
-
clearMarketInsights(caip19Id) {
|
|
121
|
-
this.update((state) => {
|
|
122
|
-
delete state.marketInsights[caip19Id];
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
82
|
}
|
|
126
83
|
_AiDigestController_digestService = new WeakMap(), _AiDigestController_instances = new WeakSet(), _AiDigestController_registerMessageHandlers = function _AiDigestController_registerMessageHandlers() {
|
|
127
|
-
this.messenger.registerActionHandler(`${controllerName}:fetchDigest`, this.fetchDigest.bind(this));
|
|
128
|
-
this.messenger.registerActionHandler(`${controllerName}:clearDigest`, this.clearDigest.bind(this));
|
|
129
|
-
this.messenger.registerActionHandler(`${controllerName}:clearAllDigests`, this.clearAllDigests.bind(this));
|
|
130
84
|
this.messenger.registerActionHandler(`${controllerName}:fetchMarketInsights`, this.fetchMarketInsights.bind(this));
|
|
131
|
-
|
|
132
|
-
}, _AiDigestController_evictStaleEntries = function _AiDigestController_evictStaleEntries(state) {
|
|
133
|
-
const now = Date.now();
|
|
134
|
-
const entries = Object.entries(state.digests);
|
|
135
|
-
const keysToDelete = [];
|
|
136
|
-
const freshEntries = [];
|
|
137
|
-
for (const [key, entry] of entries) {
|
|
138
|
-
if (now - entry.fetchedAt >= CACHE_DURATION_MS) {
|
|
139
|
-
keysToDelete.push(key);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
freshEntries.push([key, entry]);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// Evict oldest entries if over max cache size
|
|
146
|
-
if (freshEntries.length > MAX_CACHE_ENTRIES) {
|
|
147
|
-
freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);
|
|
148
|
-
const entriesToRemove = freshEntries.length - MAX_CACHE_ENTRIES;
|
|
149
|
-
for (let i = 0; i < entriesToRemove; i++) {
|
|
150
|
-
keysToDelete.push(freshEntries[i][0]);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
for (const key of keysToDelete) {
|
|
154
|
-
delete state.digests[key];
|
|
155
|
-
}
|
|
156
|
-
}, _AiDigestController_evictStaleMarketInsightsEntries = function _AiDigestController_evictStaleMarketInsightsEntries(state) {
|
|
85
|
+
}, _AiDigestController_evictStaleCachedEntries = function _AiDigestController_evictStaleCachedEntries(cache) {
|
|
157
86
|
const now = Date.now();
|
|
158
|
-
const entries = Object.entries(
|
|
87
|
+
const entries = Object.entries(cache);
|
|
159
88
|
const keysToDelete = [];
|
|
160
89
|
const freshEntries = [];
|
|
161
90
|
for (const [key, entry] of entries) {
|
|
@@ -174,7 +103,7 @@ _AiDigestController_digestService = new WeakMap(), _AiDigestController_instances
|
|
|
174
103
|
}
|
|
175
104
|
}
|
|
176
105
|
for (const key of keysToDelete) {
|
|
177
|
-
delete
|
|
106
|
+
delete cache[key];
|
|
178
107
|
}
|
|
179
108
|
};
|
|
180
109
|
//# sourceMappingURL=AiDigestController.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestController.mjs","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n StateMetadata,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport {\n controllerName,\n CACHE_DURATION_MS,\n MAX_CACHE_ENTRIES,\n} from './ai-digest-constants';\nimport type {\n AiDigestControllerState,\n DigestEntry,\n DigestService,\n DigestData,\n MarketInsightsReport,\n MarketInsightsEntry,\n} from './ai-digest-types';\n\nexport type AiDigestControllerFetchDigestAction = {\n type: `${typeof controllerName}:fetchDigest`;\n handler: AiDigestController['fetchDigest'];\n};\n\nexport type AiDigestControllerClearDigestAction = {\n type: `${typeof controllerName}:clearDigest`;\n handler: AiDigestController['clearDigest'];\n};\n\nexport type AiDigestControllerClearAllDigestsAction = {\n type: `${typeof controllerName}:clearAllDigests`;\n handler: AiDigestController['clearAllDigests'];\n};\n\nexport type AiDigestControllerFetchMarketInsightsAction = {\n type: `${typeof controllerName}:fetchMarketInsights`;\n handler: AiDigestController['fetchMarketInsights'];\n};\n\nexport type AiDigestControllerClearMarketInsightsAction = {\n type: `${typeof controllerName}:clearMarketInsights`;\n handler: AiDigestController['clearMarketInsights'];\n};\n\nexport type AiDigestControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerActions =\n | AiDigestControllerFetchDigestAction\n | AiDigestControllerClearDigestAction\n | AiDigestControllerClearAllDigestsAction\n | AiDigestControllerFetchMarketInsightsAction\n | AiDigestControllerClearMarketInsightsAction\n | AiDigestControllerGetStateAction;\n\nexport type AiDigestControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerEvents = AiDigestControllerStateChangeEvent;\n\nexport type AiDigestControllerMessenger = Messenger<\n typeof controllerName,\n AiDigestControllerActions,\n AiDigestControllerEvents\n>;\n\nexport type AiDigestControllerOptions = {\n messenger: AiDigestControllerMessenger;\n state?: Partial<AiDigestControllerState>;\n digestService: DigestService;\n};\n\nexport function getDefaultAiDigestControllerState(): AiDigestControllerState {\n return {\n digests: {},\n marketInsights: {},\n };\n}\n\nconst aiDigestControllerMetadata: StateMetadata<AiDigestControllerState> = {\n digests: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n marketInsights: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n};\n\nexport class AiDigestController extends BaseController<\n typeof controllerName,\n AiDigestControllerState,\n AiDigestControllerMessenger\n> {\n readonly #digestService: DigestService;\n\n constructor({ messenger, state, digestService }: AiDigestControllerOptions) {\n super({\n name: controllerName,\n metadata: aiDigestControllerMetadata,\n state: {\n ...getDefaultAiDigestControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#digestService = digestService;\n this.#registerMessageHandlers();\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchDigest`,\n this.fetchDigest.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:clearDigest`,\n this.clearDigest.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:clearAllDigests`,\n this.clearAllDigests.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:fetchMarketInsights`,\n this.fetchMarketInsights.bind(this),\n );\n this.messenger.registerActionHandler(\n `${controllerName}:clearMarketInsights`,\n this.clearMarketInsights.bind(this),\n );\n }\n\n async fetchDigest(assetId: string): Promise<DigestData> {\n const existingDigest = this.state.digests[assetId];\n if (existingDigest) {\n const age = Date.now() - existingDigest.fetchedAt;\n if (age < CACHE_DURATION_MS) {\n return existingDigest.data;\n }\n }\n\n const data = await this.#digestService.fetchDigest(assetId);\n\n const entry: DigestEntry = {\n asset: assetId,\n fetchedAt: Date.now(),\n data,\n };\n\n this.update((state) => {\n state.digests[assetId] = entry;\n this.#evictStaleEntries(state);\n });\n\n return data;\n }\n\n clearDigest(assetId: string): void {\n this.update((state) => {\n delete state.digests[assetId];\n });\n }\n\n clearAllDigests(): void {\n this.update((state) => {\n state.digests = {};\n });\n }\n\n /**\n * Fetches market insights for a given CAIP-19 asset identifier.\n * Returns cached data if still fresh, otherwise calls the service.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if none exists.\n */\n async fetchMarketInsights(\n caip19Id: string,\n ): Promise<MarketInsightsReport | null> {\n const existing = this.state.marketInsights[caip19Id];\n if (existing) {\n const age = Date.now() - existing.fetchedAt;\n if (age < CACHE_DURATION_MS) {\n return existing.data;\n }\n }\n\n const data = await this.#digestService.searchDigests(caip19Id);\n\n if (data === null) {\n // No insights available for this asset — clear any stale cache entry\n this.update((state) => {\n delete state.marketInsights[caip19Id];\n });\n return null;\n }\n\n const entry: MarketInsightsEntry = {\n caip19Id,\n fetchedAt: Date.now(),\n data,\n };\n\n this.update((state) => {\n state.marketInsights[caip19Id] = entry;\n this.#evictStaleMarketInsightsEntries(state);\n });\n\n return data;\n }\n\n /**\n * Clears the cached market insights for a specific CAIP-19 asset.\n *\n * @param caip19Id - The CAIP-19 identifier.\n */\n clearMarketInsights(caip19Id: string): void {\n this.update((state) => {\n delete state.marketInsights[caip19Id];\n });\n }\n\n /**\n * Evicts stale (TTL expired) and oldest entries (FIFO) if cache exceeds max size.\n *\n * @param state - The current controller state to evict entries from.\n */\n #evictStaleEntries(state: AiDigestControllerState): void {\n const now = Date.now();\n const entries = Object.entries(state.digests);\n const keysToDelete: string[] = [];\n const freshEntries: [string, DigestEntry][] = [];\n\n for (const [key, entry] of entries) {\n if (now - entry.fetchedAt >= CACHE_DURATION_MS) {\n keysToDelete.push(key);\n } else {\n freshEntries.push([key, entry]);\n }\n }\n\n // Evict oldest entries if over max cache size\n if (freshEntries.length > MAX_CACHE_ENTRIES) {\n freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);\n const entriesToRemove = freshEntries.length - MAX_CACHE_ENTRIES;\n for (let i = 0; i < entriesToRemove; i++) {\n keysToDelete.push(freshEntries[i][0]);\n }\n }\n\n for (const key of keysToDelete) {\n delete state.digests[key];\n }\n }\n\n /**\n * Evicts stale and oldest market insights entries if cache exceeds max size.\n *\n * @param state - The current controller state to evict entries from.\n */\n #evictStaleMarketInsightsEntries(state: AiDigestControllerState): void {\n const now = Date.now();\n const entries = Object.entries(state.marketInsights);\n const keysToDelete: string[] = [];\n const freshEntries: [string, MarketInsightsEntry][] = [];\n\n for (const [key, entry] of entries) {\n if (now - entry.fetchedAt >= CACHE_DURATION_MS) {\n keysToDelete.push(key);\n } else {\n freshEntries.push([key, entry]);\n }\n }\n\n if (freshEntries.length > MAX_CACHE_ENTRIES) {\n freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);\n const entriesToRemove = freshEntries.length - MAX_CACHE_ENTRIES;\n for (let i = 0; i < entriesToRemove; i++) {\n keysToDelete.push(freshEntries[i][0]);\n }\n }\n\n for (const key of keysToDelete) {\n delete state.marketInsights[key];\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AiDigestController.mjs","sourceRoot":"","sources":["../src/AiDigestController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n StateMetadata,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { isCaipAssetType } from '@metamask/utils';\n\nimport {\n AiDigestControllerErrorMessage,\n controllerName,\n CACHE_DURATION_MS,\n MAX_CACHE_ENTRIES,\n} from './ai-digest-constants';\nimport type {\n AiDigestControllerState,\n DigestService,\n MarketInsightsReport,\n MarketInsightsEntry,\n} from './ai-digest-types';\n\nexport type AiDigestControllerFetchMarketInsightsAction = {\n type: `${typeof controllerName}:fetchMarketInsights`;\n handler: AiDigestController['fetchMarketInsights'];\n};\n\nexport type AiDigestControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerActions =\n | AiDigestControllerFetchMarketInsightsAction\n | AiDigestControllerGetStateAction;\n\nexport type AiDigestControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AiDigestControllerState\n>;\n\nexport type AiDigestControllerEvents = AiDigestControllerStateChangeEvent;\n\nexport type AiDigestControllerMessenger = Messenger<\n typeof controllerName,\n AiDigestControllerActions,\n AiDigestControllerEvents\n>;\n\nexport type AiDigestControllerOptions = {\n messenger: AiDigestControllerMessenger;\n state?: Partial<AiDigestControllerState>;\n digestService: DigestService;\n};\n\nexport function getDefaultAiDigestControllerState(): AiDigestControllerState {\n return {\n marketInsights: {},\n };\n}\n\nconst aiDigestControllerMetadata: StateMetadata<AiDigestControllerState> = {\n marketInsights: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: true,\n },\n};\n\nexport class AiDigestController extends BaseController<\n typeof controllerName,\n AiDigestControllerState,\n AiDigestControllerMessenger\n> {\n readonly #digestService: DigestService;\n\n constructor({ messenger, state, digestService }: AiDigestControllerOptions) {\n super({\n name: controllerName,\n metadata: aiDigestControllerMetadata,\n state: {\n ...getDefaultAiDigestControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#digestService = digestService;\n this.#registerMessageHandlers();\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchMarketInsights`,\n this.fetchMarketInsights.bind(this),\n );\n }\n\n /**\n * Fetches market insights for a given CAIP-19 asset identifier.\n * Returns cached data if still fresh, otherwise calls the service.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if none exists.\n */\n async fetchMarketInsights(\n caip19Id: string,\n ): Promise<MarketInsightsReport | null> {\n if (!isCaipAssetType(caip19Id)) {\n throw new Error(AiDigestControllerErrorMessage.INVALID_CAIP_ASSET_TYPE);\n }\n\n const existing = this.state.marketInsights[caip19Id];\n if (existing) {\n const age = Date.now() - existing.fetchedAt;\n if (age < CACHE_DURATION_MS) {\n return existing.data;\n }\n }\n\n const data = await this.#digestService.searchDigest(caip19Id);\n\n if (data === null) {\n // No insights available for this asset — clear any stale cache entry\n this.update((state) => {\n delete state.marketInsights[caip19Id];\n });\n return null;\n }\n\n const entry: MarketInsightsEntry = {\n caip19Id,\n fetchedAt: Date.now(),\n data,\n };\n\n this.update((state) => {\n state.marketInsights[caip19Id] = entry;\n this.#evictStaleCachedEntries(state.marketInsights);\n });\n\n return data;\n }\n\n /**\n * Evicts stale (TTL expired) and oldest entries (FIFO) if cache exceeds max size.\n *\n * @param cache - The cache record to evict entries from.\n */\n #evictStaleCachedEntries<EntryType extends { fetchedAt: number }>(\n cache: Record<string, EntryType>,\n ): void {\n const now = Date.now();\n const entries = Object.entries(cache);\n const keysToDelete: string[] = [];\n const freshEntries: [string, EntryType][] = [];\n\n for (const [key, entry] of entries) {\n if (now - entry.fetchedAt >= CACHE_DURATION_MS) {\n keysToDelete.push(key);\n } else {\n freshEntries.push([key, entry]);\n }\n }\n\n if (freshEntries.length > MAX_CACHE_ENTRIES) {\n freshEntries.sort((a, b) => a[1].fetchedAt - b[1].fetchedAt);\n const entriesToRemove = freshEntries.length - MAX_CACHE_ENTRIES;\n for (let i = 0; i < entriesToRemove; i++) {\n keysToDelete.push(freshEntries[i][0]);\n }\n }\n\n for (const key of keysToDelete) {\n delete cache[key];\n }\n }\n}\n"]}
|
package/dist/AiDigestService.cjs
CHANGED
|
@@ -14,22 +14,33 @@ var _AiDigestService_baseUrl;
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.AiDigestService = void 0;
|
|
16
16
|
const ai_digest_constants_1 = require("./ai-digest-constants.cjs");
|
|
17
|
+
const isObject = (value) => typeof value === 'object' && value !== null;
|
|
18
|
+
const isMarketInsightsReport = (value) => {
|
|
19
|
+
if (!isObject(value)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return ((value.version === undefined || typeof value.version === 'string') &&
|
|
23
|
+
typeof value.asset === 'string' &&
|
|
24
|
+
typeof value.generatedAt === 'string' &&
|
|
25
|
+
typeof value.headline === 'string' &&
|
|
26
|
+
typeof value.summary === 'string' &&
|
|
27
|
+
Array.isArray(value.trends) &&
|
|
28
|
+
Array.isArray(value.sources));
|
|
29
|
+
};
|
|
30
|
+
const getNormalizedMarketInsightsReport = (value) => {
|
|
31
|
+
if (isMarketInsightsReport(value)) {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
if (isObject(value) && isMarketInsightsReport(value.digest)) {
|
|
35
|
+
return value.digest;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
};
|
|
17
39
|
class AiDigestService {
|
|
18
40
|
constructor(config) {
|
|
19
41
|
_AiDigestService_baseUrl.set(this, void 0);
|
|
20
42
|
__classPrivateFieldSet(this, _AiDigestService_baseUrl, config.baseUrl, "f");
|
|
21
43
|
}
|
|
22
|
-
async fetchDigest(assetId) {
|
|
23
|
-
const response = await fetch(`${__classPrivateFieldGet(this, _AiDigestService_baseUrl, "f")}/digests/assets/${encodeURIComponent(assetId)}/latest`);
|
|
24
|
-
if (!response.ok) {
|
|
25
|
-
throw new Error(`${ai_digest_constants_1.AiDigestControllerErrorMessage.API_REQUEST_FAILED}: ${response.status}`);
|
|
26
|
-
}
|
|
27
|
-
const data = await response.json();
|
|
28
|
-
if (!data.success) {
|
|
29
|
-
throw new Error(data.error ?? ai_digest_constants_1.AiDigestControllerErrorMessage.API_RETURNED_ERROR);
|
|
30
|
-
}
|
|
31
|
-
return data;
|
|
32
|
-
}
|
|
33
44
|
/**
|
|
34
45
|
* Search for market insights by CAIP-19 asset identifier.
|
|
35
46
|
*
|
|
@@ -38,7 +49,7 @@ class AiDigestService {
|
|
|
38
49
|
* @param caip19Id - The CAIP-19 identifier of the asset.
|
|
39
50
|
* @returns The market insights report, or `null` if none exists (404).
|
|
40
51
|
*/
|
|
41
|
-
async
|
|
52
|
+
async searchDigest(caip19Id) {
|
|
42
53
|
const response = await fetch(`${__classPrivateFieldGet(this, _AiDigestService_baseUrl, "f")}/digests?caipAssetType=${encodeURIComponent(caip19Id)}`);
|
|
43
54
|
if (response.status === 404) {
|
|
44
55
|
return null;
|
|
@@ -46,8 +57,11 @@ class AiDigestService {
|
|
|
46
57
|
if (!response.ok) {
|
|
47
58
|
throw new Error(`${ai_digest_constants_1.AiDigestControllerErrorMessage.API_REQUEST_FAILED}: ${response.status}`);
|
|
48
59
|
}
|
|
49
|
-
const
|
|
50
|
-
|
|
60
|
+
const report = getNormalizedMarketInsightsReport(await response.json());
|
|
61
|
+
if (!report) {
|
|
62
|
+
throw new Error(ai_digest_constants_1.AiDigestControllerErrorMessage.API_INVALID_RESPONSE);
|
|
63
|
+
}
|
|
64
|
+
return report;
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
67
|
exports.AiDigestService = AiDigestService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestService.cjs","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"AiDigestService.cjs","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAEA,mEAAuE;AAOvE,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAE9C,MAAM,sBAAsB,GAAG,CAC7B,KAAc,EACiB,EAAE;IACjC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC;QAClE,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;QAC/B,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ;QACrC,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAClC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QACjC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;QAC3B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAC7B,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iCAAiC,GAAG,CACxC,KAAc,EACe,EAAE;IAC/B,IAAI,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAa,eAAe;IAG1B,YAAY,MAA6B;QAFhC,2CAAiB;QAGxB,uBAAA,IAAI,4BAAY,MAAM,CAAC,OAAO,MAAA,CAAC;IACjC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAChB,QAAuB;QAEvB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,GAAG,uBAAA,IAAI,gCAAS,0BAA0B,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CACzE,CAAC;QAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,GAAG,oDAA8B,CAAC,kBAAkB,KAAK,QAAQ,CAAC,MAAM,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,iCAAiC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,oDAA8B,CAAC,oBAAoB,CAAC,CAAC;QACvE,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAxCD,0CAwCC","sourcesContent":["import type { CaipAssetType } from '@metamask/utils';\n\nimport { AiDigestControllerErrorMessage } from './ai-digest-constants';\nimport type { DigestService, MarketInsightsReport } from './ai-digest-types';\n\nexport type AiDigestServiceConfig = {\n baseUrl: string;\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null;\n\nconst isMarketInsightsReport = (\n value: unknown,\n): value is MarketInsightsReport => {\n if (!isObject(value)) {\n return false;\n }\n\n return (\n (value.version === undefined || typeof value.version === 'string') &&\n typeof value.asset === 'string' &&\n typeof value.generatedAt === 'string' &&\n typeof value.headline === 'string' &&\n typeof value.summary === 'string' &&\n Array.isArray(value.trends) &&\n Array.isArray(value.sources)\n );\n};\n\nconst getNormalizedMarketInsightsReport = (\n value: unknown,\n): MarketInsightsReport | null => {\n if (isMarketInsightsReport(value)) {\n return value;\n }\n\n if (isObject(value) && isMarketInsightsReport(value.digest)) {\n return value.digest;\n }\n\n return null;\n};\n\nexport class AiDigestService implements DigestService {\n readonly #baseUrl: string;\n\n constructor(config: AiDigestServiceConfig) {\n this.#baseUrl = config.baseUrl;\n }\n\n /**\n * Search for market insights by CAIP-19 asset identifier.\n *\n * Calls `GET ${this.#baseUrl}/digests?caipAssetType=${encodeURIComponent(caip19Id)}`.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if none exists (404).\n */\n async searchDigest(\n caip19Id: CaipAssetType,\n ): Promise<MarketInsightsReport | null> {\n const response = await fetch(\n `${this.#baseUrl}/digests?caipAssetType=${encodeURIComponent(caip19Id)}`,\n );\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n throw new Error(\n `${AiDigestControllerErrorMessage.API_REQUEST_FAILED}: ${response.status}`,\n );\n }\n\n const report = getNormalizedMarketInsightsReport(await response.json());\n\n if (!report) {\n throw new Error(AiDigestControllerErrorMessage.API_INVALID_RESPONSE);\n }\n\n return report;\n }\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CaipAssetType } from "@metamask/utils";
|
|
2
|
+
import type { DigestService, MarketInsightsReport } from "./ai-digest-types.cjs";
|
|
2
3
|
export type AiDigestServiceConfig = {
|
|
3
4
|
baseUrl: string;
|
|
4
5
|
};
|
|
5
6
|
export declare class AiDigestService implements DigestService {
|
|
6
7
|
#private;
|
|
7
8
|
constructor(config: AiDigestServiceConfig);
|
|
8
|
-
fetchDigest(assetId: string): Promise<DigestData>;
|
|
9
9
|
/**
|
|
10
10
|
* Search for market insights by CAIP-19 asset identifier.
|
|
11
11
|
*
|
|
@@ -14,6 +14,6 @@ export declare class AiDigestService implements DigestService {
|
|
|
14
14
|
* @param caip19Id - The CAIP-19 identifier of the asset.
|
|
15
15
|
* @returns The market insights report, or `null` if none exists (404).
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
searchDigest(caip19Id: CaipAssetType): Promise<MarketInsightsReport | null>;
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=AiDigestService.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestService.d.cts","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AiDigestService.d.cts","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAGrD,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,8BAA0B;AAE7E,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAqCF,qBAAa,eAAgB,YAAW,aAAa;;gBAGvC,MAAM,EAAE,qBAAqB;IAIzC;;;;;;;OAOG;IACG,YAAY,CAChB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;CAuBxC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CaipAssetType } from "@metamask/utils";
|
|
2
|
+
import type { DigestService, MarketInsightsReport } from "./ai-digest-types.mjs";
|
|
2
3
|
export type AiDigestServiceConfig = {
|
|
3
4
|
baseUrl: string;
|
|
4
5
|
};
|
|
5
6
|
export declare class AiDigestService implements DigestService {
|
|
6
7
|
#private;
|
|
7
8
|
constructor(config: AiDigestServiceConfig);
|
|
8
|
-
fetchDigest(assetId: string): Promise<DigestData>;
|
|
9
9
|
/**
|
|
10
10
|
* Search for market insights by CAIP-19 asset identifier.
|
|
11
11
|
*
|
|
@@ -14,6 +14,6 @@ export declare class AiDigestService implements DigestService {
|
|
|
14
14
|
* @param caip19Id - The CAIP-19 identifier of the asset.
|
|
15
15
|
* @returns The market insights report, or `null` if none exists (404).
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
searchDigest(caip19Id: CaipAssetType): Promise<MarketInsightsReport | null>;
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=AiDigestService.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestService.d.mts","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AiDigestService.d.mts","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAGrD,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,8BAA0B;AAE7E,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAqCF,qBAAa,eAAgB,YAAW,aAAa;;gBAGvC,MAAM,EAAE,qBAAqB;IAIzC;;;;;;;OAOG;IACG,YAAY,CAChB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;CAuBxC"}
|
package/dist/AiDigestService.mjs
CHANGED
|
@@ -11,22 +11,33 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
11
11
|
};
|
|
12
12
|
var _AiDigestService_baseUrl;
|
|
13
13
|
import { AiDigestControllerErrorMessage } from "./ai-digest-constants.mjs";
|
|
14
|
+
const isObject = (value) => typeof value === 'object' && value !== null;
|
|
15
|
+
const isMarketInsightsReport = (value) => {
|
|
16
|
+
if (!isObject(value)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return ((value.version === undefined || typeof value.version === 'string') &&
|
|
20
|
+
typeof value.asset === 'string' &&
|
|
21
|
+
typeof value.generatedAt === 'string' &&
|
|
22
|
+
typeof value.headline === 'string' &&
|
|
23
|
+
typeof value.summary === 'string' &&
|
|
24
|
+
Array.isArray(value.trends) &&
|
|
25
|
+
Array.isArray(value.sources));
|
|
26
|
+
};
|
|
27
|
+
const getNormalizedMarketInsightsReport = (value) => {
|
|
28
|
+
if (isMarketInsightsReport(value)) {
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
if (isObject(value) && isMarketInsightsReport(value.digest)) {
|
|
32
|
+
return value.digest;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
};
|
|
14
36
|
export class AiDigestService {
|
|
15
37
|
constructor(config) {
|
|
16
38
|
_AiDigestService_baseUrl.set(this, void 0);
|
|
17
39
|
__classPrivateFieldSet(this, _AiDigestService_baseUrl, config.baseUrl, "f");
|
|
18
40
|
}
|
|
19
|
-
async fetchDigest(assetId) {
|
|
20
|
-
const response = await fetch(`${__classPrivateFieldGet(this, _AiDigestService_baseUrl, "f")}/digests/assets/${encodeURIComponent(assetId)}/latest`);
|
|
21
|
-
if (!response.ok) {
|
|
22
|
-
throw new Error(`${AiDigestControllerErrorMessage.API_REQUEST_FAILED}: ${response.status}`);
|
|
23
|
-
}
|
|
24
|
-
const data = await response.json();
|
|
25
|
-
if (!data.success) {
|
|
26
|
-
throw new Error(data.error ?? AiDigestControllerErrorMessage.API_RETURNED_ERROR);
|
|
27
|
-
}
|
|
28
|
-
return data;
|
|
29
|
-
}
|
|
30
41
|
/**
|
|
31
42
|
* Search for market insights by CAIP-19 asset identifier.
|
|
32
43
|
*
|
|
@@ -35,7 +46,7 @@ export class AiDigestService {
|
|
|
35
46
|
* @param caip19Id - The CAIP-19 identifier of the asset.
|
|
36
47
|
* @returns The market insights report, or `null` if none exists (404).
|
|
37
48
|
*/
|
|
38
|
-
async
|
|
49
|
+
async searchDigest(caip19Id) {
|
|
39
50
|
const response = await fetch(`${__classPrivateFieldGet(this, _AiDigestService_baseUrl, "f")}/digests?caipAssetType=${encodeURIComponent(caip19Id)}`);
|
|
40
51
|
if (response.status === 404) {
|
|
41
52
|
return null;
|
|
@@ -43,8 +54,11 @@ export class AiDigestService {
|
|
|
43
54
|
if (!response.ok) {
|
|
44
55
|
throw new Error(`${AiDigestControllerErrorMessage.API_REQUEST_FAILED}: ${response.status}`);
|
|
45
56
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
57
|
+
const report = getNormalizedMarketInsightsReport(await response.json());
|
|
58
|
+
if (!report) {
|
|
59
|
+
throw new Error(AiDigestControllerErrorMessage.API_INVALID_RESPONSE);
|
|
60
|
+
}
|
|
61
|
+
return report;
|
|
48
62
|
}
|
|
49
63
|
}
|
|
50
64
|
_AiDigestService_baseUrl = new WeakMap();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiDigestService.mjs","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"AiDigestService.mjs","sourceRoot":"","sources":["../src/AiDigestService.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,OAAO,EAAE,8BAA8B,EAAE,kCAA8B;AAOvE,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAE9C,MAAM,sBAAsB,GAAG,CAC7B,KAAc,EACiB,EAAE;IACjC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC;QAClE,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;QAC/B,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ;QACrC,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAClC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QACjC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;QAC3B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAC7B,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iCAAiC,GAAG,CACxC,KAAc,EACe,EAAE;IAC/B,IAAI,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,OAAO,eAAe;IAG1B,YAAY,MAA6B;QAFhC,2CAAiB;QAGxB,uBAAA,IAAI,4BAAY,MAAM,CAAC,OAAO,MAAA,CAAC;IACjC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAChB,QAAuB;QAEvB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,GAAG,uBAAA,IAAI,gCAAS,0BAA0B,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CACzE,CAAC;QAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,GAAG,8BAA8B,CAAC,kBAAkB,KAAK,QAAQ,CAAC,MAAM,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,iCAAiC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,oBAAoB,CAAC,CAAC;QACvE,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["import type { CaipAssetType } from '@metamask/utils';\n\nimport { AiDigestControllerErrorMessage } from './ai-digest-constants';\nimport type { DigestService, MarketInsightsReport } from './ai-digest-types';\n\nexport type AiDigestServiceConfig = {\n baseUrl: string;\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null;\n\nconst isMarketInsightsReport = (\n value: unknown,\n): value is MarketInsightsReport => {\n if (!isObject(value)) {\n return false;\n }\n\n return (\n (value.version === undefined || typeof value.version === 'string') &&\n typeof value.asset === 'string' &&\n typeof value.generatedAt === 'string' &&\n typeof value.headline === 'string' &&\n typeof value.summary === 'string' &&\n Array.isArray(value.trends) &&\n Array.isArray(value.sources)\n );\n};\n\nconst getNormalizedMarketInsightsReport = (\n value: unknown,\n): MarketInsightsReport | null => {\n if (isMarketInsightsReport(value)) {\n return value;\n }\n\n if (isObject(value) && isMarketInsightsReport(value.digest)) {\n return value.digest;\n }\n\n return null;\n};\n\nexport class AiDigestService implements DigestService {\n readonly #baseUrl: string;\n\n constructor(config: AiDigestServiceConfig) {\n this.#baseUrl = config.baseUrl;\n }\n\n /**\n * Search for market insights by CAIP-19 asset identifier.\n *\n * Calls `GET ${this.#baseUrl}/digests?caipAssetType=${encodeURIComponent(caip19Id)}`.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if none exists (404).\n */\n async searchDigest(\n caip19Id: CaipAssetType,\n ): Promise<MarketInsightsReport | null> {\n const response = await fetch(\n `${this.#baseUrl}/digests?caipAssetType=${encodeURIComponent(caip19Id)}`,\n );\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n throw new Error(\n `${AiDigestControllerErrorMessage.API_REQUEST_FAILED}: ${response.status}`,\n );\n }\n\n const report = getNormalizedMarketInsightsReport(await response.json());\n\n if (!report) {\n throw new Error(AiDigestControllerErrorMessage.API_INVALID_RESPONSE);\n }\n\n return report;\n }\n}\n"]}
|
|
@@ -6,6 +6,7 @@ exports.CACHE_DURATION_MS = 10 * 60 * 1000; // 10 minutes
|
|
|
6
6
|
exports.MAX_CACHE_ENTRIES = 50;
|
|
7
7
|
exports.AiDigestControllerErrorMessage = {
|
|
8
8
|
API_REQUEST_FAILED: 'API request failed',
|
|
9
|
-
|
|
9
|
+
API_INVALID_RESPONSE: 'API returned invalid response',
|
|
10
|
+
INVALID_CAIP_ASSET_TYPE: 'Invalid CAIP asset type',
|
|
10
11
|
};
|
|
11
12
|
//# sourceMappingURL=ai-digest-constants.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-constants.cjs","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG,oBAAoB,CAAC;AAEtC,QAAA,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAEjD,QAAA,iBAAiB,GAAG,EAAE,CAAC;AAEvB,QAAA,8BAA8B,GAAG;IAC5C,kBAAkB,EAAE,oBAAoB;IACxC,
|
|
1
|
+
{"version":3,"file":"ai-digest-constants.cjs","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG,oBAAoB,CAAC;AAEtC,QAAA,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAEjD,QAAA,iBAAiB,GAAG,EAAE,CAAC;AAEvB,QAAA,8BAA8B,GAAG;IAC5C,kBAAkB,EAAE,oBAAoB;IACxC,oBAAoB,EAAE,+BAA+B;IACrD,uBAAuB,EAAE,yBAAyB;CAC1C,CAAC","sourcesContent":["export const controllerName = 'AiDigestController';\n\nexport const CACHE_DURATION_MS = 10 * 60 * 1000; // 10 minutes\n\nexport const MAX_CACHE_ENTRIES = 50;\n\nexport const AiDigestControllerErrorMessage = {\n API_REQUEST_FAILED: 'API request failed',\n API_INVALID_RESPONSE: 'API returned invalid response',\n INVALID_CAIP_ASSET_TYPE: 'Invalid CAIP asset type',\n} as const;\n"]}
|
|
@@ -3,6 +3,7 @@ export declare const CACHE_DURATION_MS: number;
|
|
|
3
3
|
export declare const MAX_CACHE_ENTRIES = 50;
|
|
4
4
|
export declare const AiDigestControllerErrorMessage: {
|
|
5
5
|
readonly API_REQUEST_FAILED: "API request failed";
|
|
6
|
-
readonly
|
|
6
|
+
readonly API_INVALID_RESPONSE: "API returned invalid response";
|
|
7
|
+
readonly INVALID_CAIP_ASSET_TYPE: "Invalid CAIP asset type";
|
|
7
8
|
};
|
|
8
9
|
//# sourceMappingURL=ai-digest-constants.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-constants.d.cts","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,uBAAuB,CAAC;AAEnD,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAEhD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,eAAO,MAAM,8BAA8B
|
|
1
|
+
{"version":3,"file":"ai-digest-constants.d.cts","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,uBAAuB,CAAC;AAEnD,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAEhD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,eAAO,MAAM,8BAA8B;;;;CAIjC,CAAC"}
|
|
@@ -3,6 +3,7 @@ export declare const CACHE_DURATION_MS: number;
|
|
|
3
3
|
export declare const MAX_CACHE_ENTRIES = 50;
|
|
4
4
|
export declare const AiDigestControllerErrorMessage: {
|
|
5
5
|
readonly API_REQUEST_FAILED: "API request failed";
|
|
6
|
-
readonly
|
|
6
|
+
readonly API_INVALID_RESPONSE: "API returned invalid response";
|
|
7
|
+
readonly INVALID_CAIP_ASSET_TYPE: "Invalid CAIP asset type";
|
|
7
8
|
};
|
|
8
9
|
//# sourceMappingURL=ai-digest-constants.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-constants.d.mts","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,uBAAuB,CAAC;AAEnD,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAEhD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,eAAO,MAAM,8BAA8B
|
|
1
|
+
{"version":3,"file":"ai-digest-constants.d.mts","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,uBAAuB,CAAC;AAEnD,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAEhD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,eAAO,MAAM,8BAA8B;;;;CAIjC,CAAC"}
|
|
@@ -3,6 +3,7 @@ export const CACHE_DURATION_MS = 10 * 60 * 1000; // 10 minutes
|
|
|
3
3
|
export const MAX_CACHE_ENTRIES = 50;
|
|
4
4
|
export const AiDigestControllerErrorMessage = {
|
|
5
5
|
API_REQUEST_FAILED: 'API request failed',
|
|
6
|
-
|
|
6
|
+
API_INVALID_RESPONSE: 'API returned invalid response',
|
|
7
|
+
INVALID_CAIP_ASSET_TYPE: 'Invalid CAIP asset type',
|
|
7
8
|
};
|
|
8
9
|
//# sourceMappingURL=ai-digest-constants.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-constants.mjs","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAEnD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAE9D,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAEpC,MAAM,CAAC,MAAM,8BAA8B,GAAG;IAC5C,kBAAkB,EAAE,oBAAoB;IACxC,
|
|
1
|
+
{"version":3,"file":"ai-digest-constants.mjs","sourceRoot":"","sources":["../src/ai-digest-constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAAC;AAEnD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AAE9D,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAEpC,MAAM,CAAC,MAAM,8BAA8B,GAAG;IAC5C,kBAAkB,EAAE,oBAAoB;IACxC,oBAAoB,EAAE,+BAA+B;IACrD,uBAAuB,EAAE,yBAAyB;CAC1C,CAAC","sourcesContent":["export const controllerName = 'AiDigestController';\n\nexport const CACHE_DURATION_MS = 10 * 60 * 1000; // 10 minutes\n\nexport const MAX_CACHE_ENTRIES = 50;\n\nexport const AiDigestControllerErrorMessage = {\n API_REQUEST_FAILED: 'API request failed',\n API_INVALID_RESPONSE: 'API returned invalid response',\n INVALID_CAIP_ASSET_TYPE: 'Invalid CAIP asset type',\n} as const;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-types.cjs","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"ai-digest-types.cjs","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CaipAssetType } from '@metamask/utils';\n\n// ---------------------------------------------------------------------------\n// Market Insights types\n// ---------------------------------------------------------------------------\n\n/**\n * A news article referenced by a market insight trend.\n */\nexport type MarketInsightsArticle = {\n /** Article title */\n title: string;\n /** Full URL to the article */\n url: string;\n /** Source domain name (e.g. \"coindesk.com\") */\n source: string;\n /** ISO date string */\n date: string;\n};\n\n/**\n * A social media post referenced by a market insight trend.\n */\nexport type MarketInsightsTweet = {\n /** Summary of the tweet content */\n contentSummary: string;\n /** Full URL to the tweet */\n url: string;\n /** Author handle (e.g. \"@saylordocs\") */\n author: string;\n /** ISO date string */\n date: string;\n};\n\n/**\n * A key market trend identified in the insights report.\n */\nexport type MarketInsightsTrend = {\n /** Trend title (e.g. \"Institutions Buying the Dip\") */\n title: string;\n /** Detailed description of the trend */\n description: string;\n /** Category of the trend */\n category: 'macro' | 'technical' | 'social' | string;\n /** Impact direction */\n impact: 'positive' | 'negative' | 'neutral' | string;\n /** Related news articles */\n articles: MarketInsightsArticle[];\n /** Related social media posts */\n tweets: MarketInsightsTweet[];\n};\n\n/**\n * A data source used to generate the market insights report.\n */\nexport type MarketInsightsSource = {\n /** Source name (e.g. \"CoinDesk\") */\n name: string;\n /** Source URL */\n url: string;\n /** Source type */\n type: 'news' | 'data' | 'social' | string;\n};\n\n/**\n * AI-generated market insights report for a crypto asset.\n * Returned by `GET /digests?caipAssetType=<caip19Id>`.\n */\nexport type MarketInsightsReport = {\n /** API version */\n version?: string;\n /** Asset symbol (lowercase, e.g. \"btc\") */\n asset: string;\n /** ISO date string when the report was generated */\n generatedAt: string;\n /** Main headline */\n headline: string;\n /** Summary paragraph */\n summary: string;\n /** Key market trends */\n trends: MarketInsightsTrend[];\n /** Data sources used to generate the report */\n sources: MarketInsightsSource[];\n};\n\n/**\n * A cached market insights entry.\n */\nexport type MarketInsightsEntry = {\n /** CAIP-19 asset identifier */\n caip19Id: CaipAssetType;\n /** Timestamp when the entry was fetched */\n fetchedAt: number;\n /** The market insights report data */\n data: MarketInsightsReport;\n};\n\n// ---------------------------------------------------------------------------\n// Controller state\n// ---------------------------------------------------------------------------\n\nexport type AiDigestControllerState = {\n marketInsights: Record<string, MarketInsightsEntry>;\n};\n\n// ---------------------------------------------------------------------------\n// Service interface\n// ---------------------------------------------------------------------------\n\nexport type DigestService = {\n /**\n * Search for market insights by CAIP-19 asset identifier.\n * Calls `GET /digests?caipAssetType=<caip19Id>`.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if no insights exist (404).\n */\n searchDigest(caip19Id: CaipAssetType): Promise<MarketInsightsReport | null>;\n};\n"]}
|
|
@@ -1,26 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Response from the digest API.
|
|
3
|
-
*/
|
|
4
|
-
export type DigestData = {
|
|
5
|
-
id: string;
|
|
6
|
-
assetId: string;
|
|
7
|
-
assetSymbol?: string;
|
|
8
|
-
digest: string;
|
|
9
|
-
generatedAt: string;
|
|
10
|
-
processingTime: number;
|
|
11
|
-
success: boolean;
|
|
12
|
-
error?: string;
|
|
13
|
-
createdAt: string;
|
|
14
|
-
updatedAt: string;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* A cached digest entry. Only successful fetches are stored.
|
|
18
|
-
*/
|
|
19
|
-
export type DigestEntry = {
|
|
20
|
-
asset: string;
|
|
21
|
-
fetchedAt: number;
|
|
22
|
-
data: DigestData;
|
|
23
|
-
};
|
|
1
|
+
import type { CaipAssetType } from "@metamask/utils";
|
|
24
2
|
/**
|
|
25
3
|
* A news article referenced by a market insight trend.
|
|
26
4
|
*/
|
|
@@ -81,7 +59,7 @@ export type MarketInsightsSource = {
|
|
|
81
59
|
*/
|
|
82
60
|
export type MarketInsightsReport = {
|
|
83
61
|
/** API version */
|
|
84
|
-
version
|
|
62
|
+
version?: string;
|
|
85
63
|
/** Asset symbol (lowercase, e.g. "btc") */
|
|
86
64
|
asset: string;
|
|
87
65
|
/** ISO date string when the report was generated */
|
|
@@ -100,18 +78,16 @@ export type MarketInsightsReport = {
|
|
|
100
78
|
*/
|
|
101
79
|
export type MarketInsightsEntry = {
|
|
102
80
|
/** CAIP-19 asset identifier */
|
|
103
|
-
caip19Id:
|
|
81
|
+
caip19Id: CaipAssetType;
|
|
104
82
|
/** Timestamp when the entry was fetched */
|
|
105
83
|
fetchedAt: number;
|
|
106
84
|
/** The market insights report data */
|
|
107
85
|
data: MarketInsightsReport;
|
|
108
86
|
};
|
|
109
87
|
export type AiDigestControllerState = {
|
|
110
|
-
digests: Record<string, DigestEntry>;
|
|
111
88
|
marketInsights: Record<string, MarketInsightsEntry>;
|
|
112
89
|
};
|
|
113
90
|
export type DigestService = {
|
|
114
|
-
fetchDigest(assetId: string): Promise<DigestData>;
|
|
115
91
|
/**
|
|
116
92
|
* Search for market insights by CAIP-19 asset identifier.
|
|
117
93
|
* Calls `GET /digests?caipAssetType=<caip19Id>`.
|
|
@@ -119,6 +95,6 @@ export type DigestService = {
|
|
|
119
95
|
* @param caip19Id - The CAIP-19 identifier of the asset.
|
|
120
96
|
* @returns The market insights report, or `null` if no insights exist (404).
|
|
121
97
|
*/
|
|
122
|
-
|
|
98
|
+
searchDigest(caip19Id: CaipAssetType): Promise<MarketInsightsReport | null>;
|
|
123
99
|
};
|
|
124
100
|
//# sourceMappingURL=ai-digest-types.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-types.d.cts","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ai-digest-types.d.cts","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAMrD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,QAAQ,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpD,uBAAuB;IACvB,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IACrD,4BAA4B;IAC5B,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,iCAAiC;IACjC,MAAM,EAAE,mBAAmB,EAAE,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,kBAAkB;IAClB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC3C,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,kBAAkB;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,+CAA+C;IAC/C,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,+BAA+B;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,IAAI,EAAE,oBAAoB,CAAC;CAC5B,CAAC;AAMF,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACrD,CAAC;AAMF,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;;OAMG;IACH,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;CAC7E,CAAC"}
|
|
@@ -1,26 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Response from the digest API.
|
|
3
|
-
*/
|
|
4
|
-
export type DigestData = {
|
|
5
|
-
id: string;
|
|
6
|
-
assetId: string;
|
|
7
|
-
assetSymbol?: string;
|
|
8
|
-
digest: string;
|
|
9
|
-
generatedAt: string;
|
|
10
|
-
processingTime: number;
|
|
11
|
-
success: boolean;
|
|
12
|
-
error?: string;
|
|
13
|
-
createdAt: string;
|
|
14
|
-
updatedAt: string;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* A cached digest entry. Only successful fetches are stored.
|
|
18
|
-
*/
|
|
19
|
-
export type DigestEntry = {
|
|
20
|
-
asset: string;
|
|
21
|
-
fetchedAt: number;
|
|
22
|
-
data: DigestData;
|
|
23
|
-
};
|
|
1
|
+
import type { CaipAssetType } from "@metamask/utils";
|
|
24
2
|
/**
|
|
25
3
|
* A news article referenced by a market insight trend.
|
|
26
4
|
*/
|
|
@@ -81,7 +59,7 @@ export type MarketInsightsSource = {
|
|
|
81
59
|
*/
|
|
82
60
|
export type MarketInsightsReport = {
|
|
83
61
|
/** API version */
|
|
84
|
-
version
|
|
62
|
+
version?: string;
|
|
85
63
|
/** Asset symbol (lowercase, e.g. "btc") */
|
|
86
64
|
asset: string;
|
|
87
65
|
/** ISO date string when the report was generated */
|
|
@@ -100,18 +78,16 @@ export type MarketInsightsReport = {
|
|
|
100
78
|
*/
|
|
101
79
|
export type MarketInsightsEntry = {
|
|
102
80
|
/** CAIP-19 asset identifier */
|
|
103
|
-
caip19Id:
|
|
81
|
+
caip19Id: CaipAssetType;
|
|
104
82
|
/** Timestamp when the entry was fetched */
|
|
105
83
|
fetchedAt: number;
|
|
106
84
|
/** The market insights report data */
|
|
107
85
|
data: MarketInsightsReport;
|
|
108
86
|
};
|
|
109
87
|
export type AiDigestControllerState = {
|
|
110
|
-
digests: Record<string, DigestEntry>;
|
|
111
88
|
marketInsights: Record<string, MarketInsightsEntry>;
|
|
112
89
|
};
|
|
113
90
|
export type DigestService = {
|
|
114
|
-
fetchDigest(assetId: string): Promise<DigestData>;
|
|
115
91
|
/**
|
|
116
92
|
* Search for market insights by CAIP-19 asset identifier.
|
|
117
93
|
* Calls `GET /digests?caipAssetType=<caip19Id>`.
|
|
@@ -119,6 +95,6 @@ export type DigestService = {
|
|
|
119
95
|
* @param caip19Id - The CAIP-19 identifier of the asset.
|
|
120
96
|
* @returns The market insights report, or `null` if no insights exist (404).
|
|
121
97
|
*/
|
|
122
|
-
|
|
98
|
+
searchDigest(caip19Id: CaipAssetType): Promise<MarketInsightsReport | null>;
|
|
123
99
|
};
|
|
124
100
|
//# sourceMappingURL=ai-digest-types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-types.d.mts","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ai-digest-types.d.mts","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAMrD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,QAAQ,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpD,uBAAuB;IACvB,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IACrD,4BAA4B;IAC5B,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,iCAAiC;IACjC,MAAM,EAAE,mBAAmB,EAAE,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,kBAAkB;IAClB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC3C,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,kBAAkB;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,+CAA+C;IAC/C,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,+BAA+B;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,IAAI,EAAE,oBAAoB,CAAC;CAC5B,CAAC;AAMF,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACrD,CAAC;AAMF,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;;OAMG;IACH,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;CAC7E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-digest-types.mjs","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"ai-digest-types.mjs","sourceRoot":"","sources":["../src/ai-digest-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CaipAssetType } from '@metamask/utils';\n\n// ---------------------------------------------------------------------------\n// Market Insights types\n// ---------------------------------------------------------------------------\n\n/**\n * A news article referenced by a market insight trend.\n */\nexport type MarketInsightsArticle = {\n /** Article title */\n title: string;\n /** Full URL to the article */\n url: string;\n /** Source domain name (e.g. \"coindesk.com\") */\n source: string;\n /** ISO date string */\n date: string;\n};\n\n/**\n * A social media post referenced by a market insight trend.\n */\nexport type MarketInsightsTweet = {\n /** Summary of the tweet content */\n contentSummary: string;\n /** Full URL to the tweet */\n url: string;\n /** Author handle (e.g. \"@saylordocs\") */\n author: string;\n /** ISO date string */\n date: string;\n};\n\n/**\n * A key market trend identified in the insights report.\n */\nexport type MarketInsightsTrend = {\n /** Trend title (e.g. \"Institutions Buying the Dip\") */\n title: string;\n /** Detailed description of the trend */\n description: string;\n /** Category of the trend */\n category: 'macro' | 'technical' | 'social' | string;\n /** Impact direction */\n impact: 'positive' | 'negative' | 'neutral' | string;\n /** Related news articles */\n articles: MarketInsightsArticle[];\n /** Related social media posts */\n tweets: MarketInsightsTweet[];\n};\n\n/**\n * A data source used to generate the market insights report.\n */\nexport type MarketInsightsSource = {\n /** Source name (e.g. \"CoinDesk\") */\n name: string;\n /** Source URL */\n url: string;\n /** Source type */\n type: 'news' | 'data' | 'social' | string;\n};\n\n/**\n * AI-generated market insights report for a crypto asset.\n * Returned by `GET /digests?caipAssetType=<caip19Id>`.\n */\nexport type MarketInsightsReport = {\n /** API version */\n version?: string;\n /** Asset symbol (lowercase, e.g. \"btc\") */\n asset: string;\n /** ISO date string when the report was generated */\n generatedAt: string;\n /** Main headline */\n headline: string;\n /** Summary paragraph */\n summary: string;\n /** Key market trends */\n trends: MarketInsightsTrend[];\n /** Data sources used to generate the report */\n sources: MarketInsightsSource[];\n};\n\n/**\n * A cached market insights entry.\n */\nexport type MarketInsightsEntry = {\n /** CAIP-19 asset identifier */\n caip19Id: CaipAssetType;\n /** Timestamp when the entry was fetched */\n fetchedAt: number;\n /** The market insights report data */\n data: MarketInsightsReport;\n};\n\n// ---------------------------------------------------------------------------\n// Controller state\n// ---------------------------------------------------------------------------\n\nexport type AiDigestControllerState = {\n marketInsights: Record<string, MarketInsightsEntry>;\n};\n\n// ---------------------------------------------------------------------------\n// Service interface\n// ---------------------------------------------------------------------------\n\nexport type DigestService = {\n /**\n * Search for market insights by CAIP-19 asset identifier.\n * Calls `GET /digests?caipAssetType=<caip19Id>`.\n *\n * @param caip19Id - The CAIP-19 identifier of the asset.\n * @returns The market insights report, or `null` if no insights exist (404).\n */\n searchDigest(caip19Id: CaipAssetType): Promise<MarketInsightsReport | null>;\n};\n"]}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AASA,+DAG8B;AAF5B,wHAAA,kBAAkB,OAAA;AAClB,uIAAA,iCAAiC,OAAA;AAInC,yDAAoD;AAA3C,kHAAA,eAAe,OAAA;AAaxB,iEAK+B;AAJ7B,6HAAA,cAAc,OAA0B;AACxC,wHAAA,iBAAiB,OAAA;AACjB,wHAAA,iBAAiB,OAAA;AACjB,qIAAA,8BAA8B,OAAA","sourcesContent":["export type {\n AiDigestControllerActions,\n AiDigestControllerEvents,\n AiDigestControllerFetchMarketInsightsAction,\n AiDigestControllerGetStateAction,\n AiDigestControllerMessenger,\n AiDigestControllerOptions,\n AiDigestControllerStateChangeEvent,\n} from './AiDigestController';\nexport {\n AiDigestController,\n getDefaultAiDigestControllerState,\n} from './AiDigestController';\n\nexport type { AiDigestServiceConfig } from './AiDigestService';\nexport { AiDigestService } from './AiDigestService';\n\nexport type {\n AiDigestControllerState,\n DigestService,\n MarketInsightsArticle,\n MarketInsightsTweet,\n MarketInsightsTrend,\n MarketInsightsSource,\n MarketInsightsReport,\n MarketInsightsEntry,\n} from './ai-digest-types';\n\nexport {\n controllerName as aiDigestControllerName,\n CACHE_DURATION_MS,\n MAX_CACHE_ENTRIES,\n AiDigestControllerErrorMessage,\n} from './ai-digest-constants';\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type { AiDigestControllerActions,
|
|
1
|
+
export type { AiDigestControllerActions, AiDigestControllerEvents, AiDigestControllerFetchMarketInsightsAction, AiDigestControllerGetStateAction, AiDigestControllerMessenger, AiDigestControllerOptions, AiDigestControllerStateChangeEvent, } from "./AiDigestController.cjs";
|
|
2
2
|
export { AiDigestController, getDefaultAiDigestControllerState, } from "./AiDigestController.cjs";
|
|
3
3
|
export type { AiDigestServiceConfig } from "./AiDigestService.cjs";
|
|
4
4
|
export { AiDigestService } from "./AiDigestService.cjs";
|
|
5
|
-
export type { AiDigestControllerState,
|
|
5
|
+
export type { AiDigestControllerState, DigestService, MarketInsightsArticle, MarketInsightsTweet, MarketInsightsTrend, MarketInsightsSource, MarketInsightsReport, MarketInsightsEntry, } from "./ai-digest-types.cjs";
|
|
6
6
|
export { controllerName as aiDigestControllerName, CACHE_DURATION_MS, MAX_CACHE_ENTRIES, AiDigestControllerErrorMessage, } from "./ai-digest-constants.cjs";
|
|
7
7
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,yBAAyB,EACzB,
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,2CAA2C,EAC3C,gCAAgC,EAChC,2BAA2B,EAC3B,yBAAyB,EACzB,kCAAkC,GACnC,iCAA6B;AAC9B,OAAO,EACL,kBAAkB,EAClB,iCAAiC,GAClC,iCAA6B;AAE9B,YAAY,EAAE,qBAAqB,EAAE,8BAA0B;AAC/D,OAAO,EAAE,eAAe,EAAE,8BAA0B;AAEpD,YAAY,EACV,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,8BAA0B;AAE3B,OAAO,EACL,cAAc,IAAI,sBAAsB,EACxC,iBAAiB,EACjB,iBAAiB,EACjB,8BAA8B,GAC/B,kCAA8B"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type { AiDigestControllerActions,
|
|
1
|
+
export type { AiDigestControllerActions, AiDigestControllerEvents, AiDigestControllerFetchMarketInsightsAction, AiDigestControllerGetStateAction, AiDigestControllerMessenger, AiDigestControllerOptions, AiDigestControllerStateChangeEvent, } from "./AiDigestController.mjs";
|
|
2
2
|
export { AiDigestController, getDefaultAiDigestControllerState, } from "./AiDigestController.mjs";
|
|
3
3
|
export type { AiDigestServiceConfig } from "./AiDigestService.mjs";
|
|
4
4
|
export { AiDigestService } from "./AiDigestService.mjs";
|
|
5
|
-
export type { AiDigestControllerState,
|
|
5
|
+
export type { AiDigestControllerState, DigestService, MarketInsightsArticle, MarketInsightsTweet, MarketInsightsTrend, MarketInsightsSource, MarketInsightsReport, MarketInsightsEntry, } from "./ai-digest-types.mjs";
|
|
6
6
|
export { controllerName as aiDigestControllerName, CACHE_DURATION_MS, MAX_CACHE_ENTRIES, AiDigestControllerErrorMessage, } from "./ai-digest-constants.mjs";
|
|
7
7
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,yBAAyB,EACzB,
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,2CAA2C,EAC3C,gCAAgC,EAChC,2BAA2B,EAC3B,yBAAyB,EACzB,kCAAkC,GACnC,iCAA6B;AAC9B,OAAO,EACL,kBAAkB,EAClB,iCAAiC,GAClC,iCAA6B;AAE9B,YAAY,EAAE,qBAAqB,EAAE,8BAA0B;AAC/D,OAAO,EAAE,eAAe,EAAE,8BAA0B;AAEpD,YAAY,EACV,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,8BAA0B;AAE3B,OAAO,EACL,cAAc,IAAI,sBAAsB,EACxC,iBAAiB,EACjB,iBAAiB,EACjB,8BAA8B,GAC/B,kCAA8B"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,kBAAkB,EAClB,iCAAiC,EAClC,iCAA6B;AAG9B,OAAO,EAAE,eAAe,EAAE,8BAA0B;AAapD,OAAO,EACL,cAAc,IAAI,sBAAsB,EACxC,iBAAiB,EACjB,iBAAiB,EACjB,8BAA8B,EAC/B,kCAA8B","sourcesContent":["export type {\n AiDigestControllerActions,\n AiDigestControllerEvents,\n AiDigestControllerFetchMarketInsightsAction,\n AiDigestControllerGetStateAction,\n AiDigestControllerMessenger,\n AiDigestControllerOptions,\n AiDigestControllerStateChangeEvent,\n} from './AiDigestController';\nexport {\n AiDigestController,\n getDefaultAiDigestControllerState,\n} from './AiDigestController';\n\nexport type { AiDigestServiceConfig } from './AiDigestService';\nexport { AiDigestService } from './AiDigestService';\n\nexport type {\n AiDigestControllerState,\n DigestService,\n MarketInsightsArticle,\n MarketInsightsTweet,\n MarketInsightsTrend,\n MarketInsightsSource,\n MarketInsightsReport,\n MarketInsightsEntry,\n} from './ai-digest-types';\n\nexport {\n controllerName as aiDigestControllerName,\n CACHE_DURATION_MS,\n MAX_CACHE_ENTRIES,\n AiDigestControllerErrorMessage,\n} from './ai-digest-constants';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/ai-controllers",
|
|
3
|
-
"version": "0.0.0-preview-
|
|
3
|
+
"version": "0.0.0-preview-bbc71c9d5",
|
|
4
4
|
"description": "A collection of AI-related controllers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@metamask/base-controller": "^9.0.0",
|
|
52
|
-
"@metamask/messenger": "^0.3.0"
|
|
52
|
+
"@metamask/messenger": "^0.3.0",
|
|
53
|
+
"@metamask/utils": "^11.9.0"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@metamask/auto-changelog": "^3.4.4",
|