Add currency settings, Settings service, and dialog to select fiat currency. Add support for non Official currencies like DOGE when using rates.
This commit is contained in:
@@ -6,6 +6,8 @@ import {
|
||||
} from '@generalprotocols/oracle-client';
|
||||
|
||||
import { type RatesEventMap, BaseRates } from './base-rates.js';
|
||||
import { type OffCallback } from '../event-emitter.js';
|
||||
import { SettingsService } from '../../services/settings.js';
|
||||
|
||||
// Add the Oracle Price Message to our Events for this Adapter.
|
||||
export type RatesOracleEventMap = RatesEventMap & {
|
||||
@@ -22,22 +24,34 @@ export class RatesOracle extends BaseRates<RatesOracleEventMap> {
|
||||
* @param client The underlying oracle client. If not provided, a new client will be created.
|
||||
* @returns The rates oracle.
|
||||
*/
|
||||
static async from(client?: OracleClient) {
|
||||
const ratesOracle = new RatesOracle(client ?? (await OracleClient.from()));
|
||||
static async from(
|
||||
client?: OracleClient,
|
||||
settings: SettingsService = new SettingsService(),
|
||||
) {
|
||||
const ratesOracle = new RatesOracle(
|
||||
client ?? (await OracleClient.from()),
|
||||
settings,
|
||||
);
|
||||
|
||||
return ratesOracle;
|
||||
}
|
||||
|
||||
private client: OracleClient;
|
||||
private settings: SettingsService;
|
||||
private oracles: OracleMetadataMap;
|
||||
|
||||
private started: boolean = false;
|
||||
private targetNumeratorUnitCode: string;
|
||||
private targetDenominatorUnitCode: string = 'BCH';
|
||||
private unsubscribeFromSettings: OffCallback | null = null;
|
||||
|
||||
private constructor(client: OracleClient) {
|
||||
private constructor(client: OracleClient, settings: SettingsService) {
|
||||
super();
|
||||
|
||||
this.client = client;
|
||||
this.settings = settings;
|
||||
this.oracles = {};
|
||||
this.targetNumeratorUnitCode = settings.getCurrency().toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +62,10 @@ export class RatesOracle extends BaseRates<RatesOracleEventMap> {
|
||||
return;
|
||||
}
|
||||
this.started = true;
|
||||
this.unsubscribeFromSettings = this.settings.on(
|
||||
'settings-updated',
|
||||
this.handleSettingsUpdated.bind(this),
|
||||
);
|
||||
|
||||
// Create event listeners for the client.
|
||||
this.client.setOnMetadataMessage(this.handleMetadataMessage.bind(this));
|
||||
@@ -71,6 +89,8 @@ export class RatesOracle extends BaseRates<RatesOracleEventMap> {
|
||||
return;
|
||||
}
|
||||
this.started = false;
|
||||
this.unsubscribeFromSettings?.();
|
||||
this.unsubscribeFromSettings = null;
|
||||
|
||||
// Remove event listeners by setting them to empty functions.
|
||||
this.client.setOnMetadataMessage(() => {});
|
||||
@@ -85,6 +105,12 @@ export class RatesOracle extends BaseRates<RatesOracleEventMap> {
|
||||
* @returns A set of pairs.
|
||||
*/
|
||||
async listPairs() {
|
||||
// If metadata has not arrived yet but the client is running, query once so
|
||||
// callers (like the currency picker) can still discover available pairs.
|
||||
if (Object.keys(this.oracles).length === 0 && this.started) {
|
||||
this.oracles = await this.client.getMetadataMap();
|
||||
}
|
||||
|
||||
return new Set(
|
||||
Object.values(this.oracles).map((oracle) => {
|
||||
return `${oracle.SOURCE_NUMERATOR_UNIT_CODE}/${oracle.SOURCE_DENOMINATOR_UNIT_CODE}`;
|
||||
@@ -157,14 +183,48 @@ export class RatesOracle extends BaseRates<RatesOracleEventMap> {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceNumeratorUnitCode = oracle.SOURCE_NUMERATOR_UNIT_CODE.toUpperCase();
|
||||
const sourceDenominatorUnitCode = oracle.SOURCE_DENOMINATOR_UNIT_CODE.toUpperCase();
|
||||
|
||||
// Only emit the pair currently selected in settings.
|
||||
if (
|
||||
sourceNumeratorUnitCode !== this.targetNumeratorUnitCode ||
|
||||
sourceDenominatorUnitCode !== this.targetDenominatorUnitCode
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale the price
|
||||
const priceValue = message.priceValue / oracle.ATTESTATION_SCALING;
|
||||
|
||||
this.emit('rateUpdated', {
|
||||
numeratorUnitCode: oracle.SOURCE_NUMERATOR_UNIT_CODE,
|
||||
denominatorUnitCode: oracle.SOURCE_DENOMINATOR_UNIT_CODE,
|
||||
numeratorUnitCode: sourceNumeratorUnitCode,
|
||||
denominatorUnitCode: sourceDenominatorUnitCode,
|
||||
price: priceValue,
|
||||
oraclePriceMessage: message,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks updates to settings and switches the actively emitted fiat pair.
|
||||
*/
|
||||
private handleSettingsUpdated(
|
||||
event: {
|
||||
key: 'currency' | 'default-mnemonic';
|
||||
value: string | undefined;
|
||||
},
|
||||
) {
|
||||
if (event.key !== 'currency' || !event.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.targetNumeratorUnitCode = event.value.toUpperCase();
|
||||
|
||||
// Refresh so listeners get the latest value for the new currency quickly.
|
||||
if (this.started) {
|
||||
this.refreshPrices().catch((error) => {
|
||||
console.error('Error refreshing prices after currency update:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user