@metamask-previews/assets-controllers 16.0.0-preview.e3b05ea → 17.0.0-preview.08312b7
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 +7 -1
- package/dist/CurrencyRateController.d.ts +21 -37
- package/dist/CurrencyRateController.d.ts.map +1 -1
- package/dist/CurrencyRateController.js +50 -110
- package/dist/CurrencyRateController.js.map +1 -1
- package/dist/crypto-compare.d.ts.map +1 -1
- package/dist/crypto-compare.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [17.0.0]
|
|
10
|
+
### Changed
|
|
11
|
+
- **BREAKING:** Bump dependency on `@metamask/polling-controller` to ^1.0.0
|
|
12
|
+
- Bump dependency and peer dependency on `@metamask/network-controller` to ^15.1.0
|
|
13
|
+
|
|
9
14
|
## [16.0.0]
|
|
10
15
|
### Added
|
|
11
16
|
- Add way to start and stop different polling sessions for the same network client ID by providing extra scoping data ([#1776](https://github.com/MetaMask/core/pull/1776))
|
|
@@ -334,7 +339,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
334
339
|
### Changed
|
|
335
340
|
- Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
|
|
336
341
|
|
|
337
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@
|
|
342
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@17.0.0...HEAD
|
|
343
|
+
[17.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@16.0.0...@metamask/assets-controllers@17.0.0
|
|
338
344
|
[16.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@15.0.0...@metamask/assets-controllers@16.0.0
|
|
339
345
|
[15.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@14.0.0...@metamask/assets-controllers@15.0.0
|
|
340
346
|
[14.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@13.0.0...@metamask/assets-controllers@14.0.0
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
import type { RestrictedControllerMessenger } from '@metamask/base-controller';
|
|
2
|
-
import {
|
|
2
|
+
import type { NetworkClientId, NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller';
|
|
3
|
+
import { PollingController } from '@metamask/polling-controller';
|
|
3
4
|
import type { Patch } from 'immer';
|
|
4
5
|
import { fetchExchangeRate as defaultFetchExchangeRate } from './crypto-compare';
|
|
5
6
|
/**
|
|
6
7
|
* @type CurrencyRateState
|
|
7
|
-
* @property
|
|
8
|
-
* @property
|
|
8
|
+
* @property currencyRates - Object keyed by native currency
|
|
9
|
+
* @property currencyRates.conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch
|
|
10
|
+
* @property currencyRates.conversionRate - Conversion rate from current base asset to the current currency
|
|
9
11
|
* @property currentCurrency - Currently-active ISO 4217 currency code
|
|
10
|
-
* @property nativeCurrency - Symbol for the base asset used for conversion
|
|
11
|
-
* @property pendingCurrentCurrency - The currency being switched to
|
|
12
|
-
* @property pendingNativeCurrency - The base asset currency being switched to
|
|
13
12
|
* @property usdConversionRate - Conversion rate from usd to the current currency
|
|
14
13
|
*/
|
|
15
14
|
export declare type CurrencyRateState = {
|
|
16
|
-
conversionDate: number | null;
|
|
17
|
-
conversionRate: number | null;
|
|
18
15
|
currentCurrency: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
currencyRates: Record<string, {
|
|
17
|
+
conversionDate: number | null;
|
|
18
|
+
conversionRate: number | null;
|
|
19
|
+
}>;
|
|
22
20
|
usdConversionRate: number | null;
|
|
23
21
|
};
|
|
24
22
|
declare const name = "CurrencyRateController";
|
|
@@ -30,16 +28,14 @@ export declare type GetCurrencyRateState = {
|
|
|
30
28
|
type: `${typeof name}:getState`;
|
|
31
29
|
handler: () => CurrencyRateState;
|
|
32
30
|
};
|
|
33
|
-
declare type
|
|
31
|
+
declare type AllowedActions = NetworkControllerGetNetworkClientByIdAction;
|
|
32
|
+
declare type CurrencyRateMessenger = RestrictedControllerMessenger<typeof name, GetCurrencyRateState | AllowedActions, CurrencyRateStateChange, AllowedActions['type'], never>;
|
|
34
33
|
/**
|
|
35
34
|
* Controller that passively polls on a set interval for an exchange rate from the current network
|
|
36
35
|
* asset to the user's preferred currency.
|
|
37
36
|
*/
|
|
38
|
-
export declare class CurrencyRateController extends
|
|
39
|
-
#private;
|
|
37
|
+
export declare class CurrencyRateController extends PollingController<typeof name, CurrencyRateState, CurrencyRateMessenger> {
|
|
40
38
|
private readonly mutex;
|
|
41
|
-
private intervalId?;
|
|
42
|
-
private readonly intervalDelay;
|
|
43
39
|
private readonly fetchExchangeRate;
|
|
44
40
|
private readonly includeUsdRate;
|
|
45
41
|
/**
|
|
@@ -59,20 +55,6 @@ export declare class CurrencyRateController extends BaseControllerV2<typeof name
|
|
|
59
55
|
state?: Partial<CurrencyRateState>;
|
|
60
56
|
fetchExchangeRate?: typeof defaultFetchExchangeRate;
|
|
61
57
|
});
|
|
62
|
-
/**
|
|
63
|
-
* Start polling for the currency rate.
|
|
64
|
-
*/
|
|
65
|
-
start(): Promise<void>;
|
|
66
|
-
/**
|
|
67
|
-
* Stop polling for the currency rate.
|
|
68
|
-
*/
|
|
69
|
-
stop(): void;
|
|
70
|
-
/**
|
|
71
|
-
* Prepare to discard this controller.
|
|
72
|
-
*
|
|
73
|
-
* This stops any active polling.
|
|
74
|
-
*/
|
|
75
|
-
destroy(): void;
|
|
76
58
|
/**
|
|
77
59
|
* Sets a currency to track.
|
|
78
60
|
*
|
|
@@ -80,22 +62,24 @@ export declare class CurrencyRateController extends BaseControllerV2<typeof name
|
|
|
80
62
|
*/
|
|
81
63
|
setCurrentCurrency(currentCurrency: string): Promise<void>;
|
|
82
64
|
/**
|
|
83
|
-
*
|
|
65
|
+
* Updates the exchange rate for the current currency and native currency pair.
|
|
84
66
|
*
|
|
85
|
-
* @param
|
|
67
|
+
* @param nativeCurrency - The ticker symbol for the chain.
|
|
86
68
|
*/
|
|
87
|
-
|
|
88
|
-
private stopPolling;
|
|
69
|
+
updateExchangeRate(nativeCurrency: string): Promise<void>;
|
|
89
70
|
/**
|
|
90
|
-
*
|
|
71
|
+
* Prepare to discard this controller.
|
|
72
|
+
*
|
|
73
|
+
* This stops any active polling.
|
|
91
74
|
*/
|
|
92
|
-
|
|
75
|
+
destroy(): void;
|
|
93
76
|
/**
|
|
94
77
|
* Updates exchange rate for the current currency.
|
|
95
78
|
*
|
|
79
|
+
* @param networkClientId - The network client ID used to get a ticker value.
|
|
96
80
|
* @returns The controller state.
|
|
97
81
|
*/
|
|
98
|
-
|
|
82
|
+
_executePoll(networkClientId: NetworkClientId): Promise<void>;
|
|
99
83
|
}
|
|
100
84
|
export default CurrencyRateController;
|
|
101
85
|
//# sourceMappingURL=CurrencyRateController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyRateController.d.ts","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"CurrencyRateController.d.ts","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAK/E,OAAO,KAAK,EACV,eAAe,EACf,2CAA2C,EAC5C,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EAAE,iBAAiB,IAAI,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAEjF;;;;;;;GAOG;AACH,oBAAY,iBAAiB,GAAG;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CACnB,MAAM,EACN;QACE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CACF,CAAC;IACF,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,QAAA,MAAM,IAAI,2BAA2B,CAAC;AAEtC,oBAAY,uBAAuB,GAAG;IACpC,IAAI,EAAE,GAAG,OAAO,IAAI,cAAc,CAAC;IACnC,OAAO,EAAE,CAAC,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC;CACvC,CAAC;AAEF,oBAAY,oBAAoB,GAAG;IACjC,IAAI,EAAE,GAAG,OAAO,IAAI,WAAW,CAAC;IAChC,OAAO,EAAE,MAAM,iBAAiB,CAAC;CAClC,CAAC;AAEF,aAAK,cAAc,GAAG,2CAA2C,CAAC;AAElE,aAAK,qBAAqB,GAAG,6BAA6B,CACxD,OAAO,IAAI,EACX,oBAAoB,GAAG,cAAc,EACrC,uBAAuB,EACvB,cAAc,CAAC,MAAM,CAAC,EACtB,KAAK,CACN,CAAC;AAmBF;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,iBAAiB,CAC3D,OAAO,IAAI,EACX,iBAAiB,EACjB,qBAAqB,CACtB;IACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAEnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAEhC;;;;;;;;;OASG;gBACS,EACV,cAAsB,EACtB,QAAiB,EACjB,SAAS,EACT,KAAK,EACL,iBAA4C,GAC7C,EAAE;QACD,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,qBAAqB,CAAC;QACjC,KAAK,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACnC,iBAAiB,CAAC,EAAE,OAAO,wBAAwB,CAAC;KACrD;IAYD;;;;OAIG;IACG,kBAAkB,CAAC,eAAe,EAAE,MAAM;IAahD;;;;OAIG;IACG,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgE/D;;;;OAIG;IACM,OAAO;IAKhB;;;;;OAKG;IACG,YAAY,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAOpE;AAED,eAAe,sBAAsB,CAAC"}
|
|
@@ -8,48 +8,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
14
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
15
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
16
|
-
};
|
|
17
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
18
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
19
|
-
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");
|
|
20
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
21
|
-
};
|
|
22
|
-
var _CurrencyRateController_enabled;
|
|
23
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
12
|
exports.CurrencyRateController = void 0;
|
|
25
|
-
const base_controller_1 = require("@metamask/base-controller");
|
|
26
13
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
14
|
+
const polling_controller_1 = require("@metamask/polling-controller");
|
|
27
15
|
const async_mutex_1 = require("async-mutex");
|
|
28
16
|
const crypto_compare_1 = require("./crypto-compare");
|
|
29
17
|
const name = 'CurrencyRateController';
|
|
30
18
|
const metadata = {
|
|
31
|
-
conversionDate: { persist: true, anonymous: true },
|
|
32
|
-
conversionRate: { persist: true, anonymous: true },
|
|
33
19
|
currentCurrency: { persist: true, anonymous: true },
|
|
34
|
-
|
|
35
|
-
pendingCurrentCurrency: { persist: false, anonymous: true },
|
|
36
|
-
pendingNativeCurrency: { persist: false, anonymous: true },
|
|
20
|
+
currencyRates: { persist: true, anonymous: true },
|
|
37
21
|
usdConversionRate: { persist: true, anonymous: true },
|
|
38
22
|
};
|
|
39
23
|
const defaultState = {
|
|
40
|
-
conversionDate: 0,
|
|
41
|
-
conversionRate: 0,
|
|
42
24
|
currentCurrency: 'usd',
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
25
|
+
currencyRates: {
|
|
26
|
+
ETH: {
|
|
27
|
+
conversionDate: 0,
|
|
28
|
+
conversionRate: 0,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
46
31
|
usdConversionRate: null,
|
|
47
32
|
};
|
|
48
33
|
/**
|
|
49
34
|
* Controller that passively polls on a set interval for an exchange rate from the current network
|
|
50
35
|
* asset to the user's preferred currency.
|
|
51
36
|
*/
|
|
52
|
-
class CurrencyRateController extends
|
|
37
|
+
class CurrencyRateController extends polling_controller_1.PollingController {
|
|
53
38
|
/**
|
|
54
39
|
* Creates a CurrencyRateController instance.
|
|
55
40
|
*
|
|
@@ -68,39 +53,9 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
|
|
|
68
53
|
state: Object.assign(Object.assign({}, defaultState), state),
|
|
69
54
|
});
|
|
70
55
|
this.mutex = new async_mutex_1.Mutex();
|
|
71
|
-
/**
|
|
72
|
-
* A boolean that controls whether or not network requests can be made by the controller
|
|
73
|
-
*/
|
|
74
|
-
_CurrencyRateController_enabled.set(this, void 0);
|
|
75
56
|
this.includeUsdRate = includeUsdRate;
|
|
76
|
-
this.
|
|
57
|
+
this.setIntervalLength(interval);
|
|
77
58
|
this.fetchExchangeRate = fetchExchangeRate;
|
|
78
|
-
__classPrivateFieldSet(this, _CurrencyRateController_enabled, false, "f");
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Start polling for the currency rate.
|
|
82
|
-
*/
|
|
83
|
-
start() {
|
|
84
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
-
__classPrivateFieldSet(this, _CurrencyRateController_enabled, true, "f");
|
|
86
|
-
yield this.startPolling();
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Stop polling for the currency rate.
|
|
91
|
-
*/
|
|
92
|
-
stop() {
|
|
93
|
-
__classPrivateFieldSet(this, _CurrencyRateController_enabled, false, "f");
|
|
94
|
-
this.stopPolling();
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Prepare to discard this controller.
|
|
98
|
-
*
|
|
99
|
-
* This stops any active polling.
|
|
100
|
-
*/
|
|
101
|
-
destroy() {
|
|
102
|
-
super.destroy();
|
|
103
|
-
this.stopPolling();
|
|
104
59
|
}
|
|
105
60
|
/**
|
|
106
61
|
* Sets a currency to track.
|
|
@@ -109,61 +64,31 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
|
|
|
109
64
|
*/
|
|
110
65
|
setCurrentCurrency(currentCurrency) {
|
|
111
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
-
this.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
setNativeCurrency(symbol) {
|
|
124
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
125
|
-
this.update((state) => {
|
|
126
|
-
state.pendingNativeCurrency = symbol;
|
|
127
|
-
});
|
|
128
|
-
yield this.updateExchangeRate();
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
stopPolling() {
|
|
132
|
-
if (this.intervalId) {
|
|
133
|
-
clearInterval(this.intervalId);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Starts a new polling interval.
|
|
138
|
-
*/
|
|
139
|
-
startPolling() {
|
|
140
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
141
|
-
this.stopPolling();
|
|
142
|
-
// TODO: Expose polling currency rate update errors
|
|
143
|
-
yield (0, controller_utils_1.safelyExecute)(() => __awaiter(this, void 0, void 0, function* () { return yield this.updateExchangeRate(); }));
|
|
144
|
-
this.intervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
145
|
-
yield (0, controller_utils_1.safelyExecute)(() => __awaiter(this, void 0, void 0, function* () { return yield this.updateExchangeRate(); }));
|
|
146
|
-
}), this.intervalDelay);
|
|
67
|
+
const releaseLock = yield this.mutex.acquire();
|
|
68
|
+
try {
|
|
69
|
+
this.update((state) => {
|
|
70
|
+
state.currentCurrency = currentCurrency;
|
|
71
|
+
state.currencyRates = {};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
releaseLock();
|
|
76
|
+
}
|
|
77
|
+
yield this.updateExchangeRate(currentCurrency);
|
|
147
78
|
});
|
|
148
79
|
}
|
|
149
80
|
/**
|
|
150
|
-
* Updates exchange rate for the current currency.
|
|
81
|
+
* Updates the exchange rate for the current currency and native currency pair.
|
|
151
82
|
*
|
|
152
|
-
* @
|
|
83
|
+
* @param nativeCurrency - The ticker symbol for the chain.
|
|
153
84
|
*/
|
|
154
|
-
updateExchangeRate() {
|
|
85
|
+
updateExchangeRate(nativeCurrency) {
|
|
155
86
|
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
-
if (!__classPrivateFieldGet(this, _CurrencyRateController_enabled, "f")) {
|
|
157
|
-
console.info('[CurrencyRateController] Not updating exchange rate since network requests have been disabled');
|
|
158
|
-
return this.state;
|
|
159
|
-
}
|
|
160
87
|
const releaseLock = yield this.mutex.acquire();
|
|
161
|
-
const { currentCurrency
|
|
88
|
+
const { currentCurrency, currencyRates } = this.state;
|
|
162
89
|
let conversionDate = null;
|
|
163
90
|
let conversionRate = null;
|
|
164
91
|
let usdConversionRate = null;
|
|
165
|
-
const currentCurrency = pendingCurrentCurrency !== null && pendingCurrentCurrency !== void 0 ? pendingCurrentCurrency : stateCurrentCurrency;
|
|
166
|
-
const nativeCurrency = pendingNativeCurrency !== null && pendingNativeCurrency !== void 0 ? pendingNativeCurrency : stateNativeCurrency;
|
|
167
92
|
// For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.
|
|
168
93
|
const nativeCurrencyForExchangeRate = Object.values(controller_utils_1.TESTNET_TICKER_SYMBOLS).includes(nativeCurrency)
|
|
169
94
|
? controller_utils_1.FALL_BACK_VS_CURRENCY // ETH
|
|
@@ -192,15 +117,11 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
|
|
|
192
117
|
try {
|
|
193
118
|
this.update(() => {
|
|
194
119
|
return {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
// currentCurrency is not from user input but this protects us from unexpected changes.
|
|
200
|
-
nativeCurrency,
|
|
120
|
+
currencyRates: Object.assign(Object.assign({}, currencyRates), { [nativeCurrency]: {
|
|
121
|
+
conversionDate,
|
|
122
|
+
conversionRate,
|
|
123
|
+
} }),
|
|
201
124
|
currentCurrency,
|
|
202
|
-
pendingCurrentCurrency: null,
|
|
203
|
-
pendingNativeCurrency: null,
|
|
204
125
|
usdConversionRate,
|
|
205
126
|
};
|
|
206
127
|
});
|
|
@@ -209,11 +130,30 @@ class CurrencyRateController extends base_controller_1.BaseControllerV2 {
|
|
|
209
130
|
releaseLock();
|
|
210
131
|
}
|
|
211
132
|
}
|
|
212
|
-
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Prepare to discard this controller.
|
|
137
|
+
*
|
|
138
|
+
* This stops any active polling.
|
|
139
|
+
*/
|
|
140
|
+
destroy() {
|
|
141
|
+
super.destroy();
|
|
142
|
+
this.stopAllPolling();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Updates exchange rate for the current currency.
|
|
146
|
+
*
|
|
147
|
+
* @param networkClientId - The network client ID used to get a ticker value.
|
|
148
|
+
* @returns The controller state.
|
|
149
|
+
*/
|
|
150
|
+
_executePoll(networkClientId) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientId);
|
|
153
|
+
yield this.updateExchangeRate(networkClient.configuration.ticker);
|
|
213
154
|
});
|
|
214
155
|
}
|
|
215
156
|
}
|
|
216
157
|
exports.CurrencyRateController = CurrencyRateController;
|
|
217
|
-
_CurrencyRateController_enabled = new WeakMap();
|
|
218
158
|
exports.default = CurrencyRateController;
|
|
219
159
|
//# sourceMappingURL=CurrencyRateController.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencyRateController.js","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AACA,+DAA6D;AAC7D,iEAIoC;AACpC,6CAAoC;AAGpC,qDAAiF;AAsBjF,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAoBtC,MAAM,QAAQ,GAAG;IACf,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IAClD,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IAClD,eAAe,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IACnD,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IAClD,sBAAsB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE;IAC3D,qBAAqB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE;IAC1D,iBAAiB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;CACtD,CAAC;AAEF,MAAM,YAAY,GAAG;IACnB,cAAc,EAAE,CAAC;IACjB,cAAc,EAAE,CAAC;IACjB,eAAe,EAAE,KAAK;IACtB,cAAc,EAAE,KAAK;IACrB,sBAAsB,EAAE,IAAI;IAC5B,qBAAqB,EAAE,IAAI;IAC3B,iBAAiB,EAAE,IAAI;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAa,sBAAuB,SAAQ,kCAI3C;IAgBC;;;;;;;;;OASG;IACH,YAAY,EACV,cAAc,GAAG,KAAK,EACtB,QAAQ,GAAG,MAAM,EACjB,SAAS,EACT,KAAK,EACL,iBAAiB,GAAG,kCAAwB,GAO7C;QACC,KAAK,CAAC;YACJ,IAAI;YACJ,QAAQ;YACR,SAAS;YACT,KAAK,kCAAO,YAAY,GAAK,KAAK,CAAE;SACrC,CAAC,CAAC;QA3CY,UAAK,GAAG,IAAI,mBAAK,EAAE,CAAC;QAUrC;;WAEG;QACH,kDAAS;QA+BP,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,uBAAA,IAAI,mCAAY,KAAK,MAAA,CAAC;IACxB,CAAC;IAED;;OAEG;IACG,KAAK;;YACT,uBAAA,IAAI,mCAAY,IAAI,MAAA,CAAC;YAErB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;KAAA;IAED;;OAEG;IACH,IAAI;QACF,uBAAA,IAAI,mCAAY,KAAK,MAAA,CAAC;QAEtB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACM,OAAO;QACd,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACG,kBAAkB,CAAC,eAAuB;;YAC9C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,sBAAsB,GAAG,eAAe,CAAC;YACjD,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAClC,CAAC;KAAA;IAED;;;;OAIG;IACG,iBAAiB,CAAC,MAAc;;YACpC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,qBAAqB,GAAG,MAAM,CAAC;YACvC,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAClC,CAAC;KAAA;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SAChC;IACH,CAAC;IAED;;OAEG;IACW,YAAY;;YACxB,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,mDAAmD;YAEnD,MAAM,IAAA,gCAAa,EAAC,GAAS,EAAE,gDAAC,OAAA,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAA,GAAA,CAAC,CAAC;YAEjE,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAS,EAAE;gBACvC,MAAM,IAAA,gCAAa,EAAC,GAAS,EAAE,gDAAC,OAAA,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAA,GAAA,CAAC,CAAC;YACnE,CAAC,CAAA,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACzB,CAAC;KAAA;IAED;;;;OAIG;IACG,kBAAkB;;YACtB,IAAI,CAAC,uBAAA,IAAI,uCAAS,EAAE;gBAClB,OAAO,CAAC,IAAI,CACV,+FAA+F,CAChG,CAAC;gBACF,OAAO,IAAI,CAAC,KAAK,CAAC;aACnB;YACD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,EACJ,eAAe,EAAE,oBAAoB,EACrC,cAAc,EAAE,mBAAmB,EACnC,sBAAsB,EACtB,qBAAqB,GACtB,GAAG,IAAI,CAAC,KAAK,CAAC;YAEf,IAAI,cAAc,GAAkB,IAAI,CAAC;YACzC,IAAI,cAAc,GAAkB,IAAI,CAAC;YACzC,IAAI,iBAAiB,GAAkB,IAAI,CAAC;YAC5C,MAAM,eAAe,GAAG,sBAAsB,aAAtB,sBAAsB,cAAtB,sBAAsB,GAAI,oBAAoB,CAAC;YACvE,MAAM,cAAc,GAAG,qBAAqB,aAArB,qBAAqB,cAArB,qBAAqB,GAAI,mBAAmB,CAAC;YAEpE,wFAAwF;YACxF,MAAM,6BAA6B,GAAG,MAAM,CAAC,MAAM,CACjD,yCAAsB,CACvB,CAAC,QAAQ,CAAC,cAAc,CAAC;gBACxB,CAAC,CAAC,wCAAqB,CAAC,MAAM;gBAC9B,CAAC,CAAC,cAAc,CAAC;YAEnB,IAAI;gBACF,IACE,eAAe;oBACf,cAAc;oBACd,mEAAmE;oBACnE,iEAAiE;oBACjE,oCAAoC;oBACpC,eAAe,KAAK,EAAE;oBACtB,cAAc,KAAK,EAAE,EACrB;oBACA,MAAM,yBAAyB,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAC5D,eAAe,EACf,6BAA6B,EAC7B,IAAI,CAAC,cAAc,CACpB,CAAC;oBAEF,cAAc,GAAG,yBAAyB,CAAC,cAAc,CAAC;oBAC1D,iBAAiB,GAAG,yBAAyB,CAAC,iBAAiB,CAAC;oBAChE,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;iBACpC;aACF;YAAC,OAAO,KAAK,EAAE;gBACd,IACE,CAAC,CACC,KAAK,YAAY,KAAK;oBACtB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,0CAA0C,CAAC,CACnE,EACD;oBACA,MAAM,KAAK,CAAC;iBACb;aACF;oBAAS;gBACR,IAAI;oBACF,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;wBACf,OAAO;4BACL,cAAc;4BACd,cAAc;4BACd,0EAA0E;4BAC1E,oFAAoF;4BACpF,uFAAuF;4BACvF,cAAc;4BACd,eAAe;4BACf,sBAAsB,EAAE,IAAI;4BAC5B,qBAAqB,EAAE,IAAI;4BAC3B,iBAAiB;yBAClB,CAAC;oBACJ,CAAC,CAAC,CAAC;iBACJ;wBAAS;oBACR,WAAW,EAAE,CAAC;iBACf;aACF;YACD,OAAO,IAAI,CAAC,KAAK,CAAC;QACpB,CAAC;KAAA;CACF;AAnND,wDAmNC;;AAED,kBAAe,sBAAsB,CAAC","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseControllerV2 } from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n safelyExecute,\n} from '@metamask/controller-utils';\nimport { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\n\nimport { fetchExchangeRate as defaultFetchExchangeRate } from './crypto-compare';\n\n/**\n * @type CurrencyRateState\n * @property conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property nativeCurrency - Symbol for the base asset used for conversion\n * @property pendingCurrentCurrency - The currency being switched to\n * @property pendingNativeCurrency - The base asset currency being switched to\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n conversionDate: number | null;\n conversionRate: number | null;\n currentCurrency: string;\n nativeCurrency: string;\n pendingCurrentCurrency: string | null;\n pendingNativeCurrency: string | null;\n usdConversionRate: number | null;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [CurrencyRateState, Patch[]];\n};\n\nexport type GetCurrencyRateState = {\n type: `${typeof name}:getState`;\n handler: () => CurrencyRateState;\n};\n\ntype CurrencyRateMessenger = RestrictedControllerMessenger<\n typeof name,\n GetCurrencyRateState,\n CurrencyRateStateChange,\n never,\n never\n>;\n\nconst metadata = {\n conversionDate: { persist: true, anonymous: true },\n conversionRate: { persist: true, anonymous: true },\n currentCurrency: { persist: true, anonymous: true },\n nativeCurrency: { persist: true, anonymous: true },\n pendingCurrentCurrency: { persist: false, anonymous: true },\n pendingNativeCurrency: { persist: false, anonymous: true },\n usdConversionRate: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n conversionDate: 0,\n conversionRate: 0,\n currentCurrency: 'usd',\n nativeCurrency: 'ETH',\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate: null,\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends BaseControllerV2<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay;\n\n private readonly fetchExchangeRate;\n\n private readonly includeUsdRate;\n\n /**\n * A boolean that controls whether or not network requests can be made by the controller\n */\n #enabled;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchExchangeRate = defaultFetchExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchExchangeRate?: typeof defaultFetchExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.intervalDelay = interval;\n this.fetchExchangeRate = fetchExchangeRate;\n this.#enabled = false;\n }\n\n /**\n * Start polling for the currency rate.\n */\n async start() {\n this.#enabled = true;\n\n await this.startPolling();\n }\n\n /**\n * Stop polling for the currency rate.\n */\n stop() {\n this.#enabled = false;\n\n this.stopPolling();\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n this.update((state) => {\n state.pendingCurrentCurrency = currentCurrency;\n });\n await this.updateExchangeRate();\n }\n\n /**\n * Sets a new native currency.\n *\n * @param symbol - Symbol for the base asset.\n */\n async setNativeCurrency(symbol: string) {\n this.update((state) => {\n state.pendingNativeCurrency = symbol;\n });\n await this.updateExchangeRate();\n }\n\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n private async startPolling(): Promise<void> {\n this.stopPolling();\n // TODO: Expose polling currency rate update errors\n\n await safelyExecute(async () => await this.updateExchangeRate());\n\n this.intervalId = setInterval(async () => {\n await safelyExecute(async () => await this.updateExchangeRate());\n }, this.intervalDelay);\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @returns The controller state.\n */\n async updateExchangeRate(): Promise<CurrencyRateState | void> {\n if (!this.#enabled) {\n console.info(\n '[CurrencyRateController] Not updating exchange rate since network requests have been disabled',\n );\n return this.state;\n }\n const releaseLock = await this.mutex.acquire();\n const {\n currentCurrency: stateCurrentCurrency,\n nativeCurrency: stateNativeCurrency,\n pendingCurrentCurrency,\n pendingNativeCurrency,\n } = this.state;\n\n let conversionDate: number | null = null;\n let conversionRate: number | null = null;\n let usdConversionRate: number | null = null;\n const currentCurrency = pendingCurrentCurrency ?? stateCurrentCurrency;\n const nativeCurrency = pendingNativeCurrency ?? stateNativeCurrency;\n\n // For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.\n const nativeCurrencyForExchangeRate = Object.values(\n TESTNET_TICKER_SYMBOLS,\n ).includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY // ETH\n : nativeCurrency;\n\n try {\n if (\n currentCurrency &&\n nativeCurrency &&\n // if either currency is an empty string we can skip the comparison\n // because it will result in an error from the api and ultimately\n // a null conversionRate either way.\n currentCurrency !== '' &&\n nativeCurrency !== ''\n ) {\n const fetchExchangeRateResponse = await this.fetchExchangeRate(\n currentCurrency,\n nativeCurrencyForExchangeRate,\n this.includeUsdRate,\n );\n\n conversionRate = fetchExchangeRateResponse.conversionRate;\n usdConversionRate = fetchExchangeRateResponse.usdConversionRate;\n conversionDate = Date.now() / 1000;\n }\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n )\n ) {\n throw error;\n }\n } finally {\n try {\n this.update(() => {\n return {\n conversionDate,\n conversionRate,\n // we currently allow and handle an empty string as a valid nativeCurrency\n // in cases where a user has not entered a native ticker symbol for a custom network\n // currentCurrency is not from user input but this protects us from unexpected changes.\n nativeCurrency,\n currentCurrency,\n pendingCurrentCurrency: null,\n pendingNativeCurrency: null,\n usdConversionRate,\n };\n });\n } finally {\n releaseLock();\n }\n }\n return this.state;\n }\n}\n\nexport default CurrencyRateController;\n"]}
|
|
1
|
+
{"version":3,"file":"CurrencyRateController.js","sourceRoot":"","sources":["../src/CurrencyRateController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport {\n TESTNET_TICKER_SYMBOLS,\n FALL_BACK_VS_CURRENCY,\n} from '@metamask/controller-utils';\nimport type {\n NetworkClientId,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { PollingController } from '@metamask/polling-controller';\nimport { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\n\nimport { fetchExchangeRate as defaultFetchExchangeRate } from './crypto-compare';\n\n/**\n * @type CurrencyRateState\n * @property currencyRates - Object keyed by native currency\n * @property currencyRates.conversionDate - Timestamp of conversion rate expressed in ms since UNIX epoch\n * @property currencyRates.conversionRate - Conversion rate from current base asset to the current currency\n * @property currentCurrency - Currently-active ISO 4217 currency code\n * @property usdConversionRate - Conversion rate from usd to the current currency\n */\nexport type CurrencyRateState = {\n currentCurrency: string;\n currencyRates: Record<\n string,\n {\n conversionDate: number | null;\n conversionRate: number | null;\n }\n >;\n usdConversionRate: number | null;\n};\n\nconst name = 'CurrencyRateController';\n\nexport type CurrencyRateStateChange = {\n type: `${typeof name}:stateChange`;\n payload: [CurrencyRateState, Patch[]];\n};\n\nexport type GetCurrencyRateState = {\n type: `${typeof name}:getState`;\n handler: () => CurrencyRateState;\n};\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype CurrencyRateMessenger = RestrictedControllerMessenger<\n typeof name,\n GetCurrencyRateState | AllowedActions,\n CurrencyRateStateChange,\n AllowedActions['type'],\n never\n>;\n\nconst metadata = {\n currentCurrency: { persist: true, anonymous: true },\n currencyRates: { persist: true, anonymous: true },\n usdConversionRate: { persist: true, anonymous: true },\n};\n\nconst defaultState = {\n currentCurrency: 'usd',\n currencyRates: {\n ETH: {\n conversionDate: 0,\n conversionRate: 0,\n },\n },\n usdConversionRate: null,\n};\n\n/**\n * Controller that passively polls on a set interval for an exchange rate from the current network\n * asset to the user's preferred currency.\n */\nexport class CurrencyRateController extends PollingController<\n typeof name,\n CurrencyRateState,\n CurrencyRateMessenger\n> {\n private readonly mutex = new Mutex();\n\n private readonly fetchExchangeRate;\n\n private readonly includeUsdRate;\n\n /**\n * Creates a CurrencyRateController instance.\n *\n * @param options - Constructor options.\n * @param options.includeUsdRate - Keep track of the USD rate in addition to the current currency rate.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.messenger - A reference to the messaging system.\n * @param options.state - Initial state to set on this controller.\n * @param options.fetchExchangeRate - Fetches the exchange rate from an external API. This option is primarily meant for use in unit tests.\n */\n constructor({\n includeUsdRate = false,\n interval = 180000,\n messenger,\n state,\n fetchExchangeRate = defaultFetchExchangeRate,\n }: {\n includeUsdRate?: boolean;\n interval?: number;\n messenger: CurrencyRateMessenger;\n state?: Partial<CurrencyRateState>;\n fetchExchangeRate?: typeof defaultFetchExchangeRate;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...defaultState, ...state },\n });\n this.includeUsdRate = includeUsdRate;\n this.setIntervalLength(interval);\n this.fetchExchangeRate = fetchExchangeRate;\n }\n\n /**\n * Sets a currency to track.\n *\n * @param currentCurrency - ISO 4217 currency code.\n */\n async setCurrentCurrency(currentCurrency: string) {\n const releaseLock = await this.mutex.acquire();\n try {\n this.update((state) => {\n state.currentCurrency = currentCurrency;\n state.currencyRates = {};\n });\n } finally {\n releaseLock();\n }\n await this.updateExchangeRate(currentCurrency);\n }\n\n /**\n * Updates the exchange rate for the current currency and native currency pair.\n *\n * @param nativeCurrency - The ticker symbol for the chain.\n */\n async updateExchangeRate(nativeCurrency: string): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n const { currentCurrency, currencyRates } = this.state;\n\n let conversionDate: number | null = null;\n let conversionRate: number | null = null;\n let usdConversionRate: number | null = null;\n\n // For preloaded testnets (Goerli, Sepolia) we want to fetch exchange rate for real ETH.\n const nativeCurrencyForExchangeRate = Object.values(\n TESTNET_TICKER_SYMBOLS,\n ).includes(nativeCurrency)\n ? FALL_BACK_VS_CURRENCY // ETH\n : nativeCurrency;\n\n try {\n if (\n currentCurrency &&\n nativeCurrency &&\n // if either currency is an empty string we can skip the comparison\n // because it will result in an error from the api and ultimately\n // a null conversionRate either way.\n currentCurrency !== '' &&\n nativeCurrency !== ''\n ) {\n const fetchExchangeRateResponse = await this.fetchExchangeRate(\n currentCurrency,\n nativeCurrencyForExchangeRate,\n this.includeUsdRate,\n );\n conversionRate = fetchExchangeRateResponse.conversionRate;\n usdConversionRate = fetchExchangeRateResponse.usdConversionRate;\n conversionDate = Date.now() / 1000;\n }\n } catch (error) {\n if (\n !(\n error instanceof Error &&\n error.message.includes('market does not exist for this coin pair')\n )\n ) {\n throw error;\n }\n } finally {\n try {\n this.update(() => {\n return {\n currencyRates: {\n ...currencyRates,\n [nativeCurrency]: {\n conversionDate,\n conversionRate,\n },\n },\n currentCurrency,\n usdConversionRate,\n };\n });\n } finally {\n releaseLock();\n }\n }\n }\n\n /**\n * Prepare to discard this controller.\n *\n * This stops any active polling.\n */\n override destroy() {\n super.destroy();\n this.stopAllPolling();\n }\n\n /**\n * Updates exchange rate for the current currency.\n *\n * @param networkClientId - The network client ID used to get a ticker value.\n * @returns The controller state.\n */\n async _executePoll(networkClientId: NetworkClientId): Promise<void> {\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n await this.updateExchangeRate(networkClient.configuration.ticker);\n }\n}\n\nexport default CurrencyRateController;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-compare.d.ts","sourceRoot":"","sources":["../src/crypto-compare.ts"],"names":[],"mappings":"AAyBA;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC;IACT,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC,
|
|
1
|
+
{"version":3,"file":"crypto-compare.d.ts","sourceRoot":"","sources":["../src/crypto-compare.ts"],"names":[],"mappings":"AAyBA;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC;IACT,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC,CAmCD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-compare.js","sourceRoot":"","sources":["../src/crypto-compare.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iEAAyD;AAEzD;;;;;;;;;;GAUG;AACH,SAAS,aAAa,CACpB,eAAuB,EACvB,cAAsB,EACtB,cAAwB;IAExB,OAAO,CACL,oDAAoD;QACpD,GAAG,cAAc,CAAC,WAAW,EAAE,UAAU,eAAe,CAAC,WAAW,EAAE,EAAE;QACxE,GAAG,cAAc,IAAI,eAAe,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7E,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAsB,iBAAiB,CACrC,QAAgB,EAChB,cAAsB,EACtB,cAAwB;;QAKxB,MAAM,IAAI,GAAG,MAAM,IAAA,8BAAW,EAC5B,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,cAAc,CAAC,CACxD,CAAC;
|
|
1
|
+
{"version":3,"file":"crypto-compare.js","sourceRoot":"","sources":["../src/crypto-compare.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iEAAyD;AAEzD;;;;;;;;;;GAUG;AACH,SAAS,aAAa,CACpB,eAAuB,EACvB,cAAsB,EACtB,cAAwB;IAExB,OAAO,CACL,oDAAoD;QACpD,GAAG,cAAc,CAAC,WAAW,EAAE,UAAU,eAAe,CAAC,WAAW,EAAE,EAAE;QACxE,GAAG,cAAc,IAAI,eAAe,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7E,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAsB,iBAAiB,CACrC,QAAgB,EAChB,cAAsB,EACtB,cAAwB;;QAKxB,MAAM,IAAI,GAAG,MAAM,IAAA,8BAAW,EAC5B,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,cAAc,CAAC,CACxD,CAAC;QACF;;;;;;;UAOE;QACF,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,EAAE;YAC7B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;SAC/B;QAED,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAE5D,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;YACpC,MAAM,IAAI,KAAK,CACb,wBAAwB,QAAQ,CAAC,WAAW,EAAE,KAC5C,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAC7B,EAAE,CACH,CAAC;SACH;QAED,IAAI,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;YACzD,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;SACxE;QAED,OAAO;YACL,cAAc;YACd,iBAAiB;SAClB,CAAC;IACJ,CAAC;CAAA;AA1CD,8CA0CC","sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\n\n/**\n * Get the CryptoCompare API URL for getting the conversion rate from the given native currency to\n * the given currency. Optionally, the conversion rate from the native currency to USD can also be\n * included in the response.\n *\n * @param currentCurrency - The currency to get a conversion rate for.\n * @param nativeCurrency - The native currency to convert from.\n * @param includeUSDRate - Whether or not the native currency to USD conversion rate should be\n * included in the response as well.\n * @returns The API URL for getting the conversion rate.\n */\nfunction getPricingURL(\n currentCurrency: string,\n nativeCurrency: string,\n includeUSDRate?: boolean,\n) {\n return (\n `https://min-api.cryptocompare.com/data/price?fsym=` +\n `${nativeCurrency.toUpperCase()}&tsyms=${currentCurrency.toUpperCase()}` +\n `${includeUSDRate && currentCurrency.toUpperCase() !== 'USD' ? ',USD' : ''}`\n );\n}\n\n/**\n * Fetches the exchange rate for a given currency.\n *\n * @param currency - ISO 4217 currency code.\n * @param nativeCurrency - Symbol for base asset.\n * @param includeUSDRate - Whether to add the USD rate to the fetch.\n * @returns Promise resolving to exchange rate for given currency.\n */\nexport async function fetchExchangeRate(\n currency: string,\n nativeCurrency: string,\n includeUSDRate?: boolean,\n): Promise<{\n conversionRate: number;\n usdConversionRate: number;\n}> {\n const json = await handleFetch(\n getPricingURL(currency, nativeCurrency, includeUSDRate),\n );\n /*\n Example expected error response (if pair is not found)\n {\n Response: \"Error\",\n Message: \"cccagg_or_exchange market does not exist for this coin pair (ETH-<NON_EXISTENT_TOKEN>)\",\n HasWarning: false,\n }\n */\n if (json.Response === 'Error') {\n throw new Error(json.Message);\n }\n\n const conversionRate = Number(json[currency.toUpperCase()]);\n\n const usdConversionRate = Number(json.USD);\n if (!Number.isFinite(conversionRate)) {\n throw new Error(\n `Invalid response for ${currency.toUpperCase()}: ${\n json[currency.toUpperCase()]\n }`,\n );\n }\n\n if (includeUSDRate && !Number.isFinite(usdConversionRate)) {\n throw new Error(`Invalid response for usdConversionRate: ${json.USD}`);\n }\n\n return {\n conversionRate,\n usdConversionRate,\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/assets-controllers",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "17.0.0-preview.08312b7",
|
|
4
4
|
"description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -34,14 +34,14 @@
|
|
|
34
34
|
"@ethersproject/contracts": "^5.7.0",
|
|
35
35
|
"@ethersproject/providers": "^5.7.0",
|
|
36
36
|
"@metamask/abi-utils": "^2.0.2",
|
|
37
|
-
"@metamask/approval-controller": "^4.0
|
|
37
|
+
"@metamask/approval-controller": "^4.1.0",
|
|
38
38
|
"@metamask/base-controller": "^3.2.3",
|
|
39
39
|
"@metamask/contract-metadata": "^2.3.1",
|
|
40
40
|
"@metamask/controller-utils": "^5.0.2",
|
|
41
41
|
"@metamask/eth-query": "^3.0.1",
|
|
42
42
|
"@metamask/metamask-eth-abis": "3.0.0",
|
|
43
|
-
"@metamask/network-controller": "^15.
|
|
44
|
-
"@metamask/polling-controller": "^0.
|
|
43
|
+
"@metamask/network-controller": "^15.1.0",
|
|
44
|
+
"@metamask/polling-controller": "^1.0.0",
|
|
45
45
|
"@metamask/preferences-controller": "^4.4.3",
|
|
46
46
|
"@metamask/rpc-errors": "^6.1.0",
|
|
47
47
|
"@metamask/utils": "^8.1.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"uuid": "^8.3.2"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@metamask/auto-changelog": "^3.4.
|
|
57
|
+
"@metamask/auto-changelog": "^3.4.2",
|
|
58
58
|
"@types/jest": "^27.4.1",
|
|
59
59
|
"@types/node": "^16.18.54",
|
|
60
60
|
"deepmerge": "^4.2.2",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"typescript": "~4.8.4"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
|
-
"@metamask/approval-controller": "^4.0
|
|
73
|
-
"@metamask/network-controller": "^15.
|
|
72
|
+
"@metamask/approval-controller": "^4.1.0",
|
|
73
|
+
"@metamask/network-controller": "^15.1.0",
|
|
74
74
|
"@metamask/preferences-controller": "^4.4.3"
|
|
75
75
|
},
|
|
76
76
|
"engines": {
|