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 .github/workflows/publish-back-core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Create and publish image bridge-core

on:
push:
branches: [ main ]
branches: [ main, fee-amount-usd ]
workflow_dispatch:

env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-indexer-evm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Create and publish image indexer-evm

on:
push:
branches: [ main ]
branches: [ main, fee-amount-usd ]
workflow_dispatch:

env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-indexer-svm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Create and publish image indexer-svm

on:
push:
branches: [ main ]
branches: [ main, fee-amount-usd ]
workflow_dispatch:

env:
Expand Down
5 changes: 3 additions & 2 deletions backend/back-core/src/controllers/receipt.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ export class ReceiptController {
receipt.bridgeAddress,
[
...Object.values(stageConfig.contracts).map(c => c.startsWith("0x") ? c.toLowerCase() : c),
...Object.values(tokensConfig.bridges).flatMap(network =>
Object.values(network as Record<string, string>).map(addr =>
...Object.values(tokensConfig.bridges).flatMap(network =>
Object.values(network as Record<string, string>).map(addr =>
addr.startsWith("0x") ? addr.toLowerCase() : addr
)
)
Expand Down Expand Up @@ -164,6 +164,7 @@ export class ReceiptController {
}
}


async getReceiptIdByTransactionHash(
transactionHash: string
): Promise<string | null> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class SendSignatureController {
if (!Networks.isSupportedNetwork(networkTo)) {
throw new Error(`Network To (${networkTo}) is not supported`);
}
const { feeAmount, amountToSend } = await getFees(
const { feeAmount, feeAmountUsd, amountToSend } = await getFees(
networkFrom, networkTo, addressToUserFriendly(tokenAddress), amount, isMaxAmount
);
const timestamp = Math.floor(Date.now() / 1000);
Expand Down Expand Up @@ -97,6 +97,7 @@ export class SendSignatureController {
}

return {
feeAmountUsd,
sendPayload,
...signResult,
};
Expand Down
6 changes: 2 additions & 4 deletions backend/back-core/src/fee/bridgeFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const percentFromAmount: { [key: number]: number } = {
};


export function getBridgeFeeInNative(nativeUsdPrice: Decimal, tokenUsdPrice: Decimal, amount: Decimal, minBridgeFeeUSD: number): Decimal {
export function getBridgeFeeUSD(tokenUsdPrice: Decimal, amount: Decimal, minBridgeFeeUSD: number): Decimal {
// Get fee in USD
const amountUsd = coin2Usd(amount, tokenUsdPrice);
const feePercent = getFeePercent(amountUsd);
Expand All @@ -16,9 +16,7 @@ export function getBridgeFeeInNative(nativeUsdPrice: Decimal, tokenUsdPrice: Dec
if (feeUsd.lessThan(minBridgeFeeUSD))
feeUsd = new Decimal(minBridgeFeeUSD);


// Calculate fee in native token
return usd2Coin(feeUsd, nativeUsdPrice);
return feeUsd;
}

function getFeePercent(amountInUsdt: Decimal): number {
Expand Down
32 changes: 19 additions & 13 deletions backend/back-core/src/fee/fee.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { getTokenUSDPriceByAddress } from "./token-prices";
import { convertFromDecimals, getTokenUSDPriceByAddress } from "./token-prices";
import Decimal from "decimal.js";
import { getBridgeFeeInNative } from "./bridgeFee";
import { getBridgeFeeUSD } from "./bridgeFee";
import { stageConfig } from "../../config";
import { usd2Coin } from "./utils";


export async function getFees(
networkFrom: bigint,
networkTo: bigint,
tokenAddr: string,
amount: bigint,
isMaxAmount: boolean
): Promise<{ feeAmount: bigint; amountToSend: bigint }> {
networkFrom: bigint,
networkTo: bigint,
tokenAddr: string,
amount: bigint,
isMaxAmount: boolean
): Promise<{ feeAmountUsd: Decimal; feeAmount: bigint; amountToSend: bigint }> {

console.log("getFees called with:", {
networkFrom,
Expand All @@ -31,9 +32,9 @@ export async function getFees(

const networkFeeConfig = stageConfig.fees.networks[networkFrom.toString()];
console.log("networkFeeConfig:", networkFeeConfig);

let bridgeFeeNative = getBridgeFeeInNative(fromCoinPrice, tokenPrice, amountDecimal, networkFeeConfig.minBridgeFeeUSD);
console.log("bridgeFeeNative (initial):", bridgeFeeNative.toString());
let bridgeFeeUSD = getBridgeFeeUSD(tokenPrice, amountDecimal, networkFeeConfig.minBridgeFeeUSD);
let bridgeFeeNative = usd2Coin(bridgeFeeUSD, fromCoinPrice);

// try to calculate max amount of native coins that can be transferred considering fees
if (isMaxAmount) {
Expand All @@ -44,14 +45,19 @@ export async function getFees(
if (amountDecimal.lte(0)) {
throw new Error("Amount to send is too small");
}
bridgeFeeNative = getBridgeFeeInNative(fromCoinPrice, tokenPrice, amountDecimal, networkFeeConfig.minBridgeFeeUSD);
console.log("bridgeFeeNative (recalculated):", bridgeFeeNative.toString());
bridgeFeeUSD = getBridgeFeeUSD(tokenPrice, amountDecimal, networkFeeConfig.minBridgeFeeUSD);
}


bridgeFeeNative = usd2Coin(bridgeFeeUSD, fromCoinPrice);
bridgeFeeNative = bridgeFeeNative.ceil();
console.log("bridgeFeeNative (ceiled):", bridgeFeeNative.toString());

console.log(
`[USD] Bridge fee in USD: ${bridgeFeeUSD.toString()}`
);
const result = {
feeAmountUsd: await convertFromDecimals(bridgeFeeUSD, networkFrom.toString(), tokenAddr),
feeAmount: BigInt(bridgeFeeNative.toHex()),
amountToSend: BigInt(amountDecimal.toHex())
};
Expand Down
27 changes: 27 additions & 0 deletions backend/back-core/src/fee/token-prices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,33 @@ export async function getTokenUSDPrice(tokenSymbol: string) {
return new Decimal(price);
}

export async function convertFromDecimals(
amount: Decimal | bigint | number,
networkName: string,
tokenAddr?: string
) {
const token = tokens.getToken(networkName, tokenAddr);
if (!token)
throw new Error(`Token ${tokenAddr} not found in ${networkName} network`);
const decimals = token.denomination;
return new Decimal(typeof amount === "bigint" ? amount.toString() : amount).dividedBy(
new Decimal(10).pow(decimals)
);
}

export async function convertToDecimals(
amount: Decimal,
networkName: string,
tokenAddr?: string
) {
const token = tokens.getToken(networkName, tokenAddr);
if (!token)
throw new Error(`Token ${tokenAddr} not found in ${networkName} network`);
const decimals = token.denomination;
return new Decimal(amount).mul(
new Decimal(10).pow(decimals)
);
}

class CachedPrice {
prices: { [symbol: string]: Decimal } = {};
Expand Down
4 changes: 4 additions & 0 deletions backend/back-core/src/routes/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,10 @@ export const SendPayload = z.object({
export type SendPayload = z.infer<typeof SendPayload>;

export const sendPayloadResponseSchema = z.object({
feeAmountUsd: z.coerce.number().positive().openapi({
example: 100,
description: "Amount of fee in usd",
}),
sendPayload: SendPayload,
signedBy: z
.string()
Expand Down