Apex Classes:
- BitPayJson : To parse the JSON response from BitPay API
public class BitPayJson {
public String code {get;set;}
public String name {get;set;}
public Decimal rate {get;set;}
public BitPayJson(JSONParser parser) {
while (parser.nextToken() != System.JSONToken.END_OBJECT) {
if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
String text = parser.getText();
if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
if (text == 'code') {
code = parser.getText();
} else if (text == 'name') {
name = parser.getText();
} else if (text == 'rate') {
rate = parser.getDecimalValue();
} else {
System.debug(LoggingLevel.WARN, 'BitPayJson consuming unrecognized property: '+text);
}
}
}
}
}
public static List<BitPayJson> parse(String json) {
System.JSONParser parser = System.JSON.createParser(json);
return arrayOfBitPayJson(parser);
}
private static List<BitPayJson> arrayOfBitPayJson(System.JSONParser p) {
List<BitPayJson> res = new List<BitPayJson>();
if (p.getCurrentToken() == null) p.nextToken();
while (p.nextToken() != System.JSONToken.END_ARRAY) {
res.add(new BitPayJson(p));
}
return res;
}
}
2. lwcBitCurrencyConverterController
public with sharing class lwcBitCurrencyConverterController {
// Retrieve latest rates from https://bitpay.com/api/rates/
// then return payload in currency: rate
@AuraEnabled(cacheable=true)
public static Map<String, wrapBitPayJson> getRates() {
Map<String, wrapBitPayJson> rates = new Map<String, wrapBitPayJson>();
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://bitpay.com/api/rates/');
request.setMethod('GET');
HttpResponse response = http.send(request);
if (response.getStatusCode() == 200) {
// Deserialize the JSON string into collections of primitive data types.
List<BitPayJson> results = BitPayJson.parse(response.getBody());
for(BitPayJson obj : results){
rates.put(obj.code,new wrapBitPayJson(obj.code,obj.name,obj.rate));
}
// Cast the values in the 'rates' key as a map of currency to rate value
}
return rates;
}
public class wrapBitPayJson {
@AuraEnabled
public String code {get;set;}
@AuraEnabled
public String name {get;set;}
@AuraEnabled
public Decimal rate {get;set;}
public wrapBitPayJson(String code,String name,Decimal rate){
this.code = code;
this.name = name;
this.rate = rate;
}
}
}
3. lwcBitCurrencyConverterControllerTest
@isTest
class lwcBitCurrencyConverterControllerTest
{
@isTest static void getRates() {
System.Test.startTest();
System.Test.setMock(HttpCalloutMock.class, new bitpayMock());
Map<String, lwcBitCurrencyConverterController.wrapBitPayJson> rates = lwcBitCurrencyConverterController.getRates();
System.assertEquals(40660.62,rates.get('USD').rate);
System.Test.StopTest();
}
}
4. bitpayMock
@isTest
global class bitpayMock implements HttpCalloutMock {
global HTTPResponse respond(HTTPRequest request) {
HttpResponse response = new HttpResponse();
if(request.getEndPoint().contains('https://bitpay.com/api/rates/')){
String json = '[{\"code\":\"BTC\",\"name\":\"Bitcoin\",\"rate\":1},{\"code\":\"BCH\",\"name\":\"Bitcoin Cash\",\"rate\":139.04},{\"code\":\"USD\",\"name\":\"US Dollar\",\"rate\":40660.62},{\"code\":\"EUR\",\"name\":\"Eurozone Euro\",\"rate\":36939.09},{\"code\":\"GBP\",\"name\":\"Pound Sterling\",\"rate\":31012.46},{\"code\":\"JPY\",\"name\":\"Japanese Yen\",\"rate\":4810883.18},{\"code\":\"CAD\",\"name\":\"Canadian Dollar\",\"rate\":51664.77},{\"code\":\"AUD\",\"name\":\"Australian Dollar\",\"rate\":55943.56},{\"code\":\"CNY\",\"name\":\"Chinese Yuan\",\"rate\":258101.41},{\"code\":\"CHF\",\"name\":\"Swiss Franc\",\"rate\":38212.48},{\"code\":\"SEK\",\"name\":\"Swedish Krona\",\"rate\":383395},{\"code\":\"NZD\",\"name\":\"New Zealand Dollar\",\"rate\":59599.93},{\"code\":\"KRW\",\"name\":\"South Korean Won\",\"rate\":49956506.99},{\"code\":\"ETH\",\"name\":\"Ether\",\"rate\":15.07},{\"code\":\"LTC\",\"name\":\"Litecoin\",\"rate\":374.37},{\"code\":\"XRP\",\"name\":\"Ripple\",\"rate\":52710.85},{\"code\":\"AED\",\"name\":\"UAE Dirham\",\"rate\":149345.2},{\"code\":\"AFN\",\"name\":\"Afghan Afghani\",\"rate\":3571623.33},{\"code\":\"ALL\",\"name\":\"Albanian Lek\",\"rate\":4548009.55},{\"code\":\"AMD\",\"name\":\"Armenian Dram\",\"rate\":20900858.92},{\"code\":\"ANG\",\"name\":\"Netherlands Antillean Guilder\",\"rate\":73358.18},{\"code\":\"AOA\",\"name\":\"Angolan Kwanza\",\"rate\":18731127.59},{\"code\":\"ARS\",\"name\":\"Argentine Peso\",\"rate\":4449331.11},{\"code\":\"AWG\",\"name\":\"Aruban Florin\",\"rate\":73199.28},{\"code\":\"AZN\",\"name\":\"Azerbaijani Manat\",\"rate\":69123.05},{\"code\":\"BAM\",\"name\":\"Bosnia-Herzegovina Convertible Mark\",\"rate\":72291.08},{\"code\":\"BBD\",\"name\":\"Barbadian Dollar\",\"rate\":81321.24},{\"code\":\"BDT\",\"name\":\"Bangladeshi Taka\",\"rate\":3501517.47},{\"code\":\"BGN\",\"name\":\"Bulgarian Lev\",\"rate\":72253.72},{\"code\":\"BHD\",\"name\":\"Bahraini Dinar\",\"rate\":15331.94},{\"code\":\"BIF\",\"name\":\"Burundian Franc\",\"rate\":83457860.55},{\"code\":\"BMD\",\"name\":\"Bermudan Dollar\",\"rate\":40660.62},{\"code\":\"BND\",\"name\":\"Brunei Dollar\",\"rate\":55372.53},{\"code\":\"BOB\",\"name\":\"Bolivian Boliviano\",\"rate\":279838.13},{\"code\":\"BRL\",\"name\":\"Brazilian Real\",\"rate\":207552.13},{\"code\":\"BSD\",\"name\":\"Bahamian Dollar\",\"rate\":40660.62},{\"code\":\"BTN\",\"name\":\"Bhutanese Ngultrum\",\"rate\":3101930.84},{\"code\":\"BUSD\",\"name\":\"Binance USD\",\"rate\":40660.62},{\"code\":\"BWP\",\"name\":\"Botswanan Pula\",\"rate\":471925.16},{\"code\":\"BYN\",\"name\":\"Belarusian Ruble\",\"rate\":134743.84},{\"code\":\"BZD\",\"name\":\"Belize Dollar\",\"rate\":82041.62},{\"code\":\"CDF\",\"name\":\"Congolese Franc\",\"rate\":81454707.73},{\"code\":\"CLF\",\"name\":\"Chilean Unit of Account (UF)\",\"rate\":1183.35},{\"code\":\"CLP\",\"name\":\"Chilean Peso\",\"rate\":32624048.07},{\"code\":\"COP\",\"name\":\"Colombian Peso\",\"rate\":155505847.07},{\"code\":\"CRC\",\"name\":\"Costa Rican Colón\",\"rate\":26035087.43},{\"code\":\"CUP\",\"name\":\"Cuban Peso\",\"rate\":1047010.95},{\"code\":\"CVE\",\"name\":\"Cape Verdean Escudo\",\"rate\":4115871.21},{\"code\":\"CZK\",\"name\":\"Czech Koruna\",\"rate\":907029.33},{\"code\":\"DAI\",\"name\":\"Dai\",\"rate\":40670.26},{\"code\":\"DJF\",\"name\":\"Djiboutian Franc\",\"rate\":7246140.88},{\"code\":\"DKK\",\"name\":\"Danish Krone\",\"rate\":274434.66},{\"code\":\"DOGE\",\"name\":\"Dogecoin\",\"rate\":354835.67},{\"code\":\"DOP\",\"name\":\"Dominican Peso\",\"rate\":2230943.21},{\"code\":\"DZD\",\"name\":\"Algerian Dinar\",\"rate\":5801045.38},{\"code\":\"EGP\",\"name\":\"Egyptian Pound\",\"rate\":638997.9},{\"code\":\"ETB\",\"name\":\"Ethiopian Birr\",\"rate\":2088636.37},{\"code\":\"FJD\",\"name\":\"Fijian Dollar\",\"rate\":85964.68},{\"code\":\"FKP\",\"name\":\"Falkland Islands Pound\",\"rate\":31012.46},{\"code\":\"GEL\",\"name\":\"Georgian Lari\",\"rate\":129910.68},{\"code\":\"GHS\",\"name\":\"Ghanaian Cedi\",\"rate\":291197.09},{\"code\":\"GIP\",\"name\":\"Gibraltar Pound\",\"rate\":31012.46},{\"code\":\"GMD\",\"name\":\"Gambian Dalasi\",\"rate\":2168227.54},{\"code\":\"GNF\",\"name\":\"Guinean Franc\",\"rate\":363590038.09},{\"code\":\"GTQ\",\"name\":\"Guatemalan Quetzal\",\"rate\":313621.25},{\"code\":\"GUSD\",\"name\":\"Gemini US Dollar\",\"rate\":40660.62},{\"code\":\"GYD\",\"name\":\"Guyanaese Dollar\",\"rate\":8511785.77},{\"code\":\"HKD\",\"name\":\"Hong Kong Dollar\",\"rate\":318078.47},{\"code\":\"HNL\",\"name\":\"Honduran Lempira\",\"rate\":999078.79},{\"code\":\"HRK\",\"name\":\"Croatian Kuna\",\"rate\":279212.41},{\"code\":\"HTG\",\"name\":\"Haitian Gourde\",\"rate\":4299550.36},{\"code\":\"HUF\",\"name\":\"Hungarian Forint\",\"rate\":13660839.66},{\"code\":\"IDR\",\"name\":\"Indonesian Rupiah\",\"rate\":580233139.64},{\"code\":\"ILS\",\"name\":\"Israeli Shekel\",\"rate\":132416.06},{\"code\":\"INR\",\"name\":\"Indian Rupee\",\"rate\":3093114.03},{\"code\":\"IQD\",\"name\":\"Iraqi Dinar\",\"rate\":59406969.35},{\"code\":\"IRR\",\"name\":\"Iranian Rial\",\"rate\":1721977236.67},{\"code\":\"ISK\",\"name\":\"Icelandic Króna\",\"rate\":5276935.2},{\"code\":\"JEP\",\"name\":\"Jersey Pound\",\"rate\":31012.46},{\"code\":\"JMD\",\"name\":\"Jamaican Dollar\",\"rate\":6219090.79},{\"code\":\"JOD\",\"name\":\"Jordanian Dinar\",\"rate\":28828.38},{\"code\":\"KES\",\"name\":\"Kenyan Shilling\",\"rate\":4654421.12},{\"code\":\"KGS\",\"name\":\"Kyrgystani Som\",\"rate\":4061205.57},{\"code\":\"KHR\",\"name\":\"Cambodian Riel\",\"rate\":164442350.04},{\"code\":\"KMF\",\"name\":\"Comorian Franc\",\"rate\":18295251.45},{\"code\":\"KPW\",\"name\":\"North Korean Won\",\"rate\":36594557.57},{\"code\":\"KWD\",\"name\":\"Kuwaiti Dinar\",\"rate\":12359.2},{\"code\":\"KYD\",\"name\":\"Cayman Islands Dollar\",\"rate\":33919.9},{\"code\":\"KZT\",\"name\":\"Kazakhstani Tenge\",\"rate\":20743739.13},{\"code\":\"LAK\",\"name\":\"Laotian Kip\",\"rate\":467624312.49},{\"code\":\"LBP\",\"name\":\"Lebanese Pound\",\"rate\":61552562.67},{\"code\":\"LKR\",\"name\":\"Sri Lankan Rupee\",\"rate\":10786432.35},{\"code\":\"LRD\",\"name\":\"Liberian Dollar\",\"rate\":6249536.98},{\"code\":\"LSL\",\"name\":\"Lesotho Loti\",\"rate\":611212.22},{\"code\":\"LYD\",\"name\":\"Libyan Dinar\",\"rate\":189773.2},{\"code\":\"MAD\",\"name\":\"Moroccan Dirham\",\"rate\":399328.39},{\"code\":\"MDL\",\"name\":\"Moldovan Leu\",\"rate\":750966.11},{\"code\":\"MGA\",\"name\":\"Malagasy Ariary\",\"rate\":164641290.42},{\"code\":\"MKD\",\"name\":\"Macedonian Denar\",\"rate\":2277445.7},{\"code\":\"MMK\",\"name\":\"Myanma Kyat\",\"rate\":72376971.18},{\"code\":\"MNT\",\"name\":\"Mongolian Tugrik\",\"rate\":117187824.98},{\"code\":\"MOP\",\"name\":\"Macanese Pataca\",\"rate\":327907.04},{\"code\":\"MRU\",\"name\":\"Mauritanian Ouguiya\",\"rate\":1481236.04},{\"code\":\"MUR\",\"name\":\"Mauritian Rupee\",\"rate\":1803516.05},{\"code\":\"MVR\",\"name\":\"Maldivian Rufiyaa\",\"rate\":628206.57},{\"code\":\"MWK\",\"name\":\"Malawian Kwacha\",\"rate\":32838526.17},{\"code\":\"MXN\",\"name\":\"Mexican Peso\",\"rate\":841136.68},{\"code\":\"MYR\",\"name\":\"Malaysian Ringgit\",\"rate\":170672.95},{\"code\":\"MZN\",\"name\":\"Mozambican Metical\",\"rate\":2595367.34},{\"code\":\"NAD\",\"name\":\"Namibian Dollar\",\"rate\":613975.35},{\"code\":\"NGN\",\"name\":\"Nigerian Naira\",\"rate\":16915224.33},{\"code\":\"NIO\",\"name\":\"Nicaraguan Córdoba\",\"rate\":1455696.13},{\"code\":\"NOK\",\"name\":\"Norwegian Krone\",\"rate\":361345.23},{\"code\":\"NPR\",\"name\":\"Nepalese Rupee\",\"rate\":4963088.04},{\"code\":\"OMR\",\"name\":\"Omani Rial\",\"rate\":15657.51},{\"code\":\"PAB\",\"name\":\"Panamanian Balboa\",\"rate\":40660.62},{\"code\":\"PAX\",\"name\":\"Paxos Standard USD\",\"rate\":40660.62},{\"code\":\"PEN\",\"name\":\"Peruvian Nuevo Sol\",\"rate\":152106.34},{\"code\":\"PGK\",\"name\":\"Papua New Guinean Kina\",\"rate\":143423.06},{\"code\":\"PHP\",\"name\":\"Philippine Peso\",\"rate\":2122057.32},{\"code\":\"PKR\",\"name\":\"Pakistani Rupee\",\"rate\":7312386.38},{\"code\":\"PLN\",\"name\":\"Polish Zloty\",\"rate\":172534.96},{\"code\":\"PYG\",\"name\":\"Paraguayan Guarani\",\"rate\":283690477.93},{\"code\":\"QAR\",\"name\":\"Qatari Rial\",\"rate\":148738.17},{\"code\":\"RON\",\"name\":\"Romanian Leu\",\"rate\":182430.38},{\"code\":\"RSD\",\"name\":\"Serbian Dinar\",\"rate\":4339098.01},{\"code\":\"RUB\",\"name\":\"Russian Ruble\",\"rate\":4410050.75},{\"code\":\"RWF\",\"name\":\"Rwandan Franc\",\"rate\":41331098.86},{\"code\":\"SAR\",\"name\":\"Saudi Riyal\",\"rate\":152562.87},{\"code\":\"SBD\",\"name\":\"Solomon Islands Dollar\",\"rate\":327249.76},{\"code\":\"SCR\",\"name\":\"Seychellois Rupee\",\"rate\":586233.96},{\"code\":\"SDG\",\"name\":\"Sudanese Pound\",\"rate\":18175296.93},{\"code\":\"SGD\",\"name\":\"Singapore Dollar\",\"rate\":55282.58},{\"code\":\"SHP\",\"name\":\"Saint Helena Pound\",\"rate\":31012.46},{\"code\":\"SLL\",\"name\":\"Sierra Leonean Leone\",\"rate\":468721399.07},{\"code\":\"SOS\",\"name\":\"Somali Shilling\",\"rate\":23548405.59},{\"code\":\"SRD\",\"name\":\"Surinamese Dollar\",\"rate\":838239},{\"code\":\"STN\",\"name\":\"São Tomé and Príncipe Dobra\",\"rate\":916896.97},{\"code\":\"SVC\",\"name\":\"Salvadoran Colón\",\"rate\":356153.03},{\"code\":\"SYP\",\"name\":\"Syrian Pound\",\"rate\":102139476.23},{\"code\":\"SZL\",\"name\":\"Swazi Lilangeni\",\"rate\":611215.88},{\"code\":\"THB\",\"name\":\"Thai Baht\",\"rate\":1354327.9},{\"code\":\"TJS\",\"name\":\"Tajikistani Somoni\",\"rate\":530171.91},{\"code\":\"TMT\",\"name\":\"Turkmenistani Manat\",\"rate\":142312.17},{\"code\":\"TND\",\"name\":\"Tunisian Dinar\",\"rate\":120030.15},{\"code\":\"TOP\",\"name\":\"Tongan Paʻanga\",\"rate\":92721.5},{\"code\":\"TRY\",\"name\":\"Turkish Lira\",\"rate\":595303.43},{\"code\":\"TTD\",\"name\":\"Trinidad and Tobago Dollar\",\"rate\":276188.68},{\"code\":\"TWD\",\"name\":\"New Taiwan Dollar\",\"rate\":1158856.16},{\"code\":\"TZS\",\"name\":\"Tanzanian Shilling\",\"rate\":94309989.32},{\"code\":\"UAH\",\"name\":\"Ukrainian Hryvnia\",\"rate\":1199185.35},{\"code\":\"UGX\",\"name\":\"Ugandan Shilling\",\"rate\":145916226.54},{\"code\":\"USDC\",\"name\":\"Circle USD Coin\",\"rate\":40660.62},{\"code\":\"UYU\",\"name\":\"Uruguayan Peso\",\"rate\":1740841.28},{\"code\":\"UZS\",\"name\":\"Uzbekistan Som\",\"rate\":443682614},{\"code\":\"VES\",\"name\":\"Venezuelan Bolívar Soberano\",\"rate\":172291.24},{\"code\":\"VND\",\"name\":\"Vietnamese Dong\",\"rate\":930342524.95},{\"code\":\"VUV\",\"name\":\"Vanuatu Vatu\",\"rate\":4643068.75},{\"code\":\"WBTC\",\"name\":\"Wrapped BTC\",\"rate\":1},{\"code\":\"SHIB\",\"name\":\"Shiba Inu\",\"rate\":1844855695.1},{\"code\":\"WST\",\"name\":\"Samoan Tala\",\"rate\":106679.76},{\"code\":\"XAF\",\"name\":\"CFA Franc BEAC\",\"rate\":24190300.24},{\"code\":\"XAG\",\"name\":\"Silver (troy ounce)\",\"rate\":1656.05},{\"code\":\"XAU\",\"name\":\"Gold (troy ounce)\",\"rate\":21.31},{\"code\":\"XCD\",\"name\":\"East Caribbean Dollar\",\"rate\":109887.36},{\"code\":\"XPF\",\"name\":\"CFP Franc\",\"rate\":4400701.09},{\"code\":\"XOF\",\"name\":\"CFA Franc BCEAO\",\"rate\":24190300.24},{\"code\":\"YER\",\"name\":\"Yemeni Rial\",\"rate\":10175322.35},{\"code\":\"ZAR\",\"name\":\"South African Rand\",\"rate\":608735.26},{\"code\":\"ZMW\",\"name\":\"Zambian Kwacha\",\"rate\":721452.96},{\"code\":\"ZWL\",\"name\":\"Zimbabwean Dollar\",\"rate\":13092719.49}]';
response.setHeader('Content-Type', 'application/json');
response.setBody(json);
response.setStatusCode(200);
}
return response;
}
}
LWC Files:
- lwcBitcoinConverter.html
<template>
<lightning-card title="">
<div style="padding:5%">
<lightning-layout multiple-rows="true">
<lightning-layout-item size="8">
<h1><b>Bitcoin Converter</b></h1>
</lightning-layout-item>
<lightning-layout-item size="4">
<lightning-layout>
<lightning-layout-item>
<label class="slds-form-element__label" for="sel-target-currency">Currency</label>
</lightning-layout-item>
<lightning-layout-item>
<select title="Currency" label="Currency" class="slds-select"
id="sel-target-currency" name="targetCurrency"
onchange={handleOnInputChange}>
<template if:true={rates} for:each={rates} for:item="rate">
<option key={rate.value} value={rate.value}
selected={rate.selected}>{rate.label}
</option>
</template>
</select>
</lightning-layout-item>
</lightning-layout>
</lightning-layout-item>
<lightning-layout-item size="5">
<lightning-input type="number" name="amount" class="form-control is-invalid"
onchange={handleOnInputChange} onfocusout={handleOnInputChange}
value={amount} label="Bitcoin Amount">
</lightning-input>
<!-- RON: -->
<!--step="0.0000000001"-->
</lightning-layout-item>
<lightning-layout-item size="2">
</lightning-layout-item>
<lightning-layout-item size="5">
<label class="slds-form-element__label" for="txt-amount">{convertedAmount}
Amount</label>
<div class="slds-form-element__control">
<input type="number" id="txt-convertedval" class="slds-input"
name="convertedValue" value={convertedValue}
onchange={calculateBitCoinRate}/>
</div>
</lightning-layout-item>
</lightning-layout>
</div>
</lightning-card>
</template>
2. lwcBitcoinConverter.js
import { LightningElement, track } from 'lwc'
import getRates from '@salesforce/apex/lwcBitCurrencyConverterController.getRates'
export default class LwcBitcoinConverter extends LightningElement {
@track rates = [];
@track currencyOptions = [];
@track amount;
@track targetCurrency = 'USD';
@track convertedValue='';
@track convertedAmount='US Dollar'
// Fetch our rates from apex
fetchRates = () => {
getRates()
.then(data => {
for (let currency in data) {
if (data.hasOwnProperty(currency)) {
this.rates = [...this.rates, { label:data[currency].name,rate:data[currency].rate, value: data[currency].code, selected: currency === this.targetCurrency }]
}
}
})
.catch(error => console.error(error))
}
connectedCallback() {
this.fetchRates()
}
// For amount and target currency input boxes
handleOnInputChange = (e) => {
this[e.target.name] = e.target.value
this.convertedValue = null
this.calculateRate();
}
// Find our rate for that currency then do the conversion
calculateRate() {
const targetRate = this.rates.find(r => r.value === this.targetCurrency)
if (targetRate) {
this.convertedValue = this.amount * targetRate.rate
this.convertedAmount = targetRate.label;
}
}
// Find our rate for that currency then do the conversion
calculateBitCoinRate= (e) => {
this[e.target.name] = e.target.value
if(e.target.value){
const targetRate = this.rates.find(r => r.value === this.targetCurrency)
this.amount = e.target.value/targetRate.rate;
} else {
this.amount = e.target.value;
}
}
}
3. lwcBitcoinConverter.js-meta.xml
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>51.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>lwcBitcoinConverter</masterLabel>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
4. lwcBitcoinConverter.css
.dummy{
color : black;
}