Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/grid_client/scripts/currency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function yearlyUSD(hourlyUSD) {
}
async function main() {
const grid = await getClient();
const rate = await grid.tfclient.tftPrice.get();
const rate = await grid.tfclient.tftPrice.getTFTBillingRateUSD();
const decimals = 3;
currency = new TFTUSDConversionService(rate, decimals);

Expand Down
3 changes: 2 additions & 1 deletion packages/grid_client/src/clients/tf-grid/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Decimal } from "decimal.js";
import { bytesToGB, formatErrorMessage } from "../../helpers";
import { calculator, ContractStates, currency } from "../../modules";
import { Graphql } from "../graphql/client";
import { TFTPrice } from "./tftPrice";

export type DiscountLevel = "None" | "Default" | "Bronze" | "Silver" | "Gold";

Expand Down Expand Up @@ -387,7 +388,7 @@ class TFContracts extends Contracts {
*/
private async convertToTFT(USD: Decimal) {
try {
const tftPrice = (await this.client.tftPrice.get()) ?? 0;
const tftPrice = await (this.client.tftPrice as TFTPrice).getTFTBillingRateUSD();
const tft = new currency(tftPrice, 15).convertUSDtoTFT({ amount: USD.toNumber() });
return new Decimal(tft);
} catch (error) {
Expand Down
5 changes: 5 additions & 0 deletions packages/grid_client/src/clients/tf-grid/tftPrice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ class TFTPrice extends QueryTFTPrice {
const priceInMili = await super.get();
return priceInMili / 1000;
}

async getTFTBillingRateUSD(): Promise<number> {
const priceInMili = await super.getTFTBillingRateMUSD();
return priceInMili / 1000;
}
}

export { TFTPrice };
8 changes: 6 additions & 2 deletions packages/grid_client/src/modules/calculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,12 @@ class Calculator {
@expose
@validateInput
async tftPrice(): Promise<number> {
const pricing = await this.client.tftPrice.get();
return this.client instanceof TFClient ? pricing : pricing / 1000;
if (this.client instanceof TFClient) {
return await this.client.tftPrice.getTFTBillingRateUSD();
} else {
const pricing = await this.client.tftPrice.getTFTBillingRateMUSD();
return pricing / 1000;
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/weblets/tf_contracts_list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ async function getTotalCost() {
loadingTotalCost.value = true;
const res = await gridProxyClient.twins.getConsumption(profileManager.profile!.twinId);
totalTFT.value = +(res.last_hour_consumption || 0).toFixed(3);
const tftPrice = await queryClient.tftPrice.get();
const tftPrice = await queryClient.tftPrice.getTFTBillingRateMUSD();
totalCostUSD.value = +(totalTFT.value * (tftPrice / 1000)).toFixed(3);
} catch (error: any) {
totalTFT.value = 0;
Expand Down
40 changes: 40 additions & 0 deletions packages/tfchain_client/src/tft_price.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,46 @@ class QueryTFTPrice {
const res = await this.client.api.query.tftPriceModule.tftPrice();
return res.toPrimitive() as number;
}

@checkConnection
async getTFTBillingRateMUSD(): Promise<number> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The uppercase M sounds like it's millions not milli

Suggested change
async getTFTBillingRateMUSD(): Promise<number> {
async getTFTBillingRatemUSD(): Promise<number> {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The capital 'M' in MUSD was used strictly to adhere to camel case convention. Within this repo, we exclusively deal with standard USD and milli-USD; we do not use the Mega prefix anywhere. Therefore, the limited scope of our units ensures there is no ambiguity for the reader.

const [minRes, maxRes, avgRes] = await Promise.all([
this.client.api.query.tftPriceModule.minTftPrice(),
this.client.api.query.tftPriceModule.maxTftPrice(),
this.client.api.query.tftPriceModule.averageTftPrice(),
]);

const minPrice = minRes.toPrimitive();
const maxPrice = maxRes.toPrimitive();
const averagePrice = avgRes.toPrimitive();

if (typeof minPrice !== "number" || isNaN(minPrice)) {
throw new Error("Failed to retrieve minimum TFT price: invalid value returned");
}
if (typeof maxPrice !== "number" || isNaN(maxPrice)) {
throw new Error("Failed to retrieve maximum TFT price: invalid value returned");
}
if (typeof averagePrice !== "number" || isNaN(averagePrice)) {
throw new Error("Failed to retrieve average TFT price: invalid value returned");
}

// Clamp the average between the configured bounds, matching on-chain billing logic
return this.clampTFTPrice(averagePrice, minPrice, maxPrice);
}

/**
* tft_price = max(AverageTftPrice, MinTftPrice) then min(_, MaxTftPrice)
*/
private clampTFTPrice(avg: number, min: number, max: number): number {
let rate = avg;
if (rate < min) {
rate = min;
}
if (rate > max) {
rate = max;
}
return rate;
}
}

export { QueryTFTPrice };
Loading