Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Commit

Permalink
fix issue of fiat currency dropdown not updating correctly (closes #418
Browse files Browse the repository at this point in the history
…) (#419)

* 1 - update selected value used in dropdown to match dropdown options by replacing with <api_key>

* 2 - simplify fiat API dropdown options and augment URL only on client side

* 3 - allow queryPrice to succeed by using the original feed_url
  • Loading branch information
nikhilsaraf committed May 11, 2020
1 parent 222edd9 commit fe19dcb
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 22 deletions.
2 changes: 1 addition & 1 deletion gui/backend/options_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (dob *dropdownOptionsBuilder) coinmarketcap(tickerCode string, currencyName
}

func (dob *dropdownOptionsBuilder) currencylayer(tickerCode string, name string) *dropdownOptionsBuilder {
value := fmt.Sprintf("http://apilayer.net/api/live?access_key=<api_key>&currencies=%s", tickerCode)
value := tickerCode
text := fmt.Sprintf("%s - %s", tickerCode, name)
return dob._leaf(value, text)
}
Expand Down
59 changes: 46 additions & 13 deletions gui/web/src/components/molecules/Form/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import PriceFeedFormula from '../PriceFeedFormula/PriceFeedFormula';
import Levels from '../Levels/Levels';
import ErrorMessage from '../ErrorMessage/ErrorMessage';
import newSecretKey from '../../../kelp-ops-api/newSecretKey';
import fetchPrice from '../../../kelp-ops-api/fetchPrice';
import SecretKey from '../SecretKey/SecretKey';

const fiatURLPrefix = "http://apilayer.net/api/live?access_key=";
const fiatURLCurrencyParam = "&currencies=";
const fiatAPIKeyPlaceholder = "<api_key>";
const currencyLayerWebsite = "https://currencylayer.com/";

class Form extends Component {
Expand Down Expand Up @@ -60,7 +60,9 @@ class Form extends Component {
this.addLevelError = this.addLevelError.bind(this);
this.clearLevelError = this.clearLevelError.bind(this);
this.makeNewFiatDataFeedURL = this.makeNewFiatDataFeedURL.bind(this);
this.extractCurrencyCodeFromFiatURL = this.extractCurrencyCodeFromFiatURL.bind(this);
this.updateFiatAPIKey = this.updateFiatAPIKey.bind(this);
this.getConfigFeedURLTransformIfFiat = this.getConfigFeedURLTransformIfFiat.bind(this);
this._emptyLevel = this._emptyLevel.bind(this);
this._triggerUpdateLevels = this._triggerUpdateLevels.bind(this);
this._fetchDotNotation = this._fetchDotNotation.bind(this);
Expand All @@ -69,6 +71,7 @@ class Form extends Component {
this._asyncRequests = {};
}

// _extractFiatAPIKey gets called when we load the config and we want to populate the fiat APIKey in the GUI
_extractFiatAPIKey(props) {
let url = null;
if (props.configData.strategy_config.data_type_a === "fiat") {
Expand All @@ -89,6 +92,19 @@ class Form extends Component {
return url.substring(fiatURLPrefix.length, url.indexOf(fiatURLCurrencyParam));
}

// getConfigFeedURLTransformIfFiat is called when loading the config value for feed URLs
// we want to load only the currencyCode
getConfigFeedURLTransformIfFiat(ab) {
let dataType = this.props.configData.strategy_config["data_type_" + ab]
let feedUrl = this.props.configData.strategy_config["data_feed_" + ab + "_url"];

if (dataType === "fiat") {
const currencyCode = this.extractCurrencyCodeFromFiatURL(feedUrl);
return currencyCode;
}
return feedUrl;
}

componentWillUnmount() {
if (this._asyncRequests["secretKey"]) {
delete this._asyncRequests["secretKey"];
Expand Down Expand Up @@ -200,9 +216,11 @@ class Form extends Component {
feedUrlValue = feedUrlValue + "/" + newValues[2];
}

// special handling for fiat feeds
// when the users selects a new fiat feed currency, wrap the currencyCode (feedUrlValue) with the fiat URL format
// so it can be saved in the config file which requires a URL.
// This leaves the UI text in the dropdown unchanged
if (dataTypeValue === "fiat") {
feedUrlValue = feedUrlValue.replace(fiatAPIKeyPlaceholder, this.state.fiatAPIKey);
feedUrlValue = this.makeNewFiatDataFeedURL(this.state.fiatAPIKey, feedUrlValue);
}

let mergeUpdateInstructions = {};
Expand Down Expand Up @@ -329,19 +347,24 @@ class Form extends Component {
});
}

makeNewFiatDataFeedURL(apiKey, oldURL) {
return fiatURLPrefix + apiKey + oldURL.substring(oldURL.indexOf(fiatURLCurrencyParam));
makeNewFiatDataFeedURL(apiKey, currencyCode) {
return fiatURLPrefix + apiKey + fiatURLCurrencyParam + currencyCode;
}

extractCurrencyCodeFromFiatURL(url) {
return url.substring(url.indexOf(fiatURLCurrencyParam) + fiatURLCurrencyParam.length);
}

// updateFiatAPIKey is called when the user upates the fiat API key in the GUI
updateFiatAPIKey(apiKey) {
if (this.props.configData.strategy_config.data_type_a === "fiat") {
const newValue = this.makeNewFiatDataFeedURL(apiKey, this.props.configData.strategy_config.data_feed_a_url);
this.props.onChange("strategy_config.data_feed_a_url", {target: {value: newValue }});
const newValue = this.makeNewFiatDataFeedURL(apiKey, this.extractCurrencyCodeFromFiatURL(this.props.configData.strategy_config.data_feed_a_url));
this.props.onChange("strategy_config.data_feed_a_url", { target: { value: newValue } });
}

if (this.props.configData.strategy_config.data_type_b === "fiat") {
const newValue = this.makeNewFiatDataFeedURL(apiKey, this.props.configData.strategy_config.data_feed_b_url);
this.props.onChange("strategy_config.data_feed_b_url", {target: {value: newValue }});
const newValue = this.makeNewFiatDataFeedURL(apiKey, this.extractCurrencyCodeFromFiatURL(this.props.configData.strategy_config.data_feed_b_url));
this.props.onChange("strategy_config.data_feed_b_url", { target: { value: newValue } });
}

this.setState({
Expand Down Expand Up @@ -863,25 +886,35 @@ class Form extends Component {
<FieldGroup groupTitle="Price Feed">
<FieldItem>
<PriceFeedAsset
baseUrl={this.props.baseUrl}
onChange={(newValues) => this.priceFeedAssetChangeHandler("a", newValues)}
title={"Numerator: current price of base asset (" + this.props.configData.trader_config.asset_code_a + ")"}
optionsMetadata={this.props.optionsMetadata}
type={this.props.configData.strategy_config.data_type_a}
feed_url={this.props.configData.strategy_config.data_feed_a_url}
feed_url={this.getConfigFeedURLTransformIfFiat("a")}
fetchPrice={fetchPrice.bind(
this,
this.props.baseUrl,
this.props.configData.strategy_config.data_type_a,
this.props.configData.strategy_config.data_feed_a_url,
)}
onLoadingPrice={() => this.setLoadingFormula()}
onNewPrice={(newPrice) => this.updateFormulaPrice("numerator", newPrice)}
readOnly={this.props.readOnly}
/>
</FieldItem>
<FieldItem>
<PriceFeedAsset
baseUrl={this.props.baseUrl}
onChange={(newValues) => this.priceFeedAssetChangeHandler("b", newValues)}
title={"Denominator: current price of quote asset (" + this.props.configData.trader_config.asset_code_b + ")"}
optionsMetadata={this.props.optionsMetadata}
type={this.props.configData.strategy_config.data_type_b}
feed_url={this.props.configData.strategy_config.data_feed_b_url}
feed_url={this.getConfigFeedURLTransformIfFiat("b")}
fetchPrice={fetchPrice.bind(
this,
this.props.baseUrl,
this.props.configData.strategy_config.data_type_b,
this.props.configData.strategy_config.data_feed_b_url,
)}
onLoadingPrice={() => this.setLoadingFormula()}
onNewPrice={(newPrice) => this.updateFormulaPrice("denominator", newPrice)}
readOnly={this.props.readOnly}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import styles from './PriceFeedAsset.module.scss';
import Label from '../../atoms/Label/Label';
import PriceFeedDisplay from '../PriceFeedDisplay/PriceFeedDisplay';
import PriceFeedSelector from '../PriceFeedSelector/PriceFeedSelector';
import fetchPrice from '../../../kelp-ops-api/fetchPrice';
import LoadingAnimation from '../../atoms/LoadingAnimation/LoadingAnimation';

class PriceFeedAsset extends Component {
Expand All @@ -20,11 +19,11 @@ class PriceFeedAsset extends Component {
}

static propTypes = {
baseUrl: PropTypes.string,
title: PropTypes.string,
type: PropTypes.string,
feed_url: PropTypes.string,
onChange: PropTypes.func,
fetchPrice: PropTypes.func,
onLoadingPrice: PropTypes.func,
onNewPrice: PropTypes.func,
optionsMetadata: PropTypes.object,
Expand All @@ -37,7 +36,6 @@ class PriceFeedAsset extends Component {

componentDidUpdate(prevProps) {
if (
prevProps.baseUrl !== this.props.baseUrl ||
prevProps.type !== this.props.type ||
prevProps.feed_url !== this.props.feed_url
) {
Expand All @@ -54,7 +52,7 @@ class PriceFeedAsset extends Component {
this.props.onLoadingPrice();

var _this = this;
let currentRequest = fetchPrice.bind(this, this.props.baseUrl, this.props.type, this.props.feed_url);
let currentRequest = this.props.fetchPrice.bind(this);
// we need to set the cached request to the current request so we always track the latest request we want processed
this._asyncRequests["price"] = currentRequest;
setTimeout(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class PriceFeedSelector extends Component {
}
selectedOption = selectedOption.subtype;
}

valuesToUpdate.push(curValue);
i++;
}
Expand All @@ -85,7 +85,7 @@ class PriceFeedSelector extends Component {
type="string"
onChange={(event) => this.changeHandler(idx, event)}
readOnly={this.props.readOnly}
/>
/>
</div>
);
} else if (metadata.type === "dropdown") {
Expand All @@ -98,7 +98,7 @@ class PriceFeedSelector extends Component {
selected={value}
onChange={(event) => this.changeHandler(idx, event)}
readOnly={this.props.readOnly}
/>
/>
</div>
);
}
Expand All @@ -124,7 +124,7 @@ class PriceFeedSelector extends Component {
}
secondComponent = this.renderComponentRecursive(idx + 1, selectedOption.subtype, innerValues);
}

return (
<div className={grid.row}>
{firstComponent}
Expand Down

0 comments on commit fe19dcb

Please sign in to comment.