Skip to content

Commit

Permalink
Merge pull request #254 from zikriya/feature/feeManagement
Browse files Browse the repository at this point in the history
Fee management with new flow
  • Loading branch information
zikriya committed May 13, 2024
2 parents 29b9282 + b49f0dd commit 07d9608
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 98 deletions.
10 changes: 9 additions & 1 deletion app/controllers/api/v1/gasFees.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
let asyncMiddleware = require("../../../lib/response/asyncMiddleware");
import { convertIntoFeeDistributionObject } from "../../../lib/middlewares/helpers/feeDistribution/feeDistributionHelper";
import {
gasEstimationValidation,
destinationGasEstimation,
Expand All @@ -7,7 +8,7 @@ import {
import { isSameNetworksSwap } from "../../../lib/middlewares/helpers/multiSwapHelper";

module.exports = function (router: any) {
router.get(
router.post(
"/estimation",
asyncMiddleware(async (req: any, res: any) => {
let destinationGasPrices;
Expand All @@ -16,6 +17,13 @@ module.exports = function (router: any) {
req?.query?.destinationNetworkChainId
);
gasEstimationValidation(req);
req.body.feeDistribution = convertIntoFeeDistributionObject(
req.body.feeDistribution,
req.query.sourceAmountIn,
req.query.sourceAmountOut,
req.body.originalDestinationAmountIn,
req.body.originalDestinationAmountOut
);
if (!isSameNetworks) {
destinationGasPrices = await destinationGasEstimation(req);
}
Expand Down
10 changes: 9 additions & 1 deletion app/controllers/api/v1/multiswap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
let asyncMiddleware = require("../../../lib/response/asyncMiddleware");
import { convertIntoFeeDistributionObject } from "../../../lib/middlewares/helpers/feeDistribution/feeDistributionHelper";
import {
getQuoteAndTokenTypeInformation,
getSwapSigned,
Expand Down Expand Up @@ -26,10 +27,17 @@ module.exports = function (router: any) {
})
);

router.get(
router.post(
"/swap/signed",
asyncMiddleware(async (req: any, res: any) => {
swapSignedValidation(req);
req.body.feeDistribution = convertIntoFeeDistributionObject(
req.body.feeDistribution,
req.query.sourceAmountIn,
req.query.sourceAmountOut,
req.query.destinationAmountIn,
req.query.destinationAmountOut
);
if (
req.query.sourceNetworkChainId == req.query.destinationNetworkChainId
) {
Expand Down
5 changes: 5 additions & 0 deletions app/interfaces/feeDistributionInterface.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
export interface FeeDistribution {
feeAllocations: any[];
totalPlatformFee: string;
sourceAmountIn: string;
sourceAmountOut: string;
destinationAmountIn: string;
destinationAmountOut: string;
salt: string;
expiry: number;
signature: string;
Expand Down
2 changes: 1 addition & 1 deletion app/lib/httpCalls/multiSwapAxiosHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const getFeeDistributionDataByReferralCode = async (code: string) => {
if ((global as any as any).utils.IS_LOCAL_ENV) {
baseUrl = localHostUrl;
}
let url = `${baseUrl}/community-member/multiSwap/referrals/fee-distribution?code=${code}`;
let url = `${baseUrl}/referrals/fee-distribution?code=${code}`;
let res = await axios.get(url, config);
console.log("res?.data?.body?.feeDistribution", res?.data?.body);
return res?.data?.body?.feeDistribution;
Expand Down
112 changes: 90 additions & 22 deletions app/lib/middlewares/helpers/feeDistribution/feeDistributionHelper.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,113 @@
var { Big } = require("big.js");
import { FeeDistribution } from "../../../../interfaces/feeDistributionInterface";
import {
getFeeDistributionSignature,
getSaltAndExpiryData,
} from "../feeDistribution/feeDistributionSignatureHelper";
import { getFeeDistributionDataByReferralCode } from "../../../httpCalls/multiSwapAxiosHelper";

export async function getFeeDistributionData(
referralCode: string,
network: any
export async function getFeeDistributionObject(
feeDistribution: FeeDistribution,
network: any,
sourceAmountIn: string,
sourceAmountOut: string,
destinationAmountIn: string,
destinationAmountOut: string
): Promise<FeeDistribution> {
let data: FeeDistribution = {
feeAllocations: [],
salt: "",
expiry: 0,
signature: "",
};
try {
const feeDistribution = await getFeeDistributionDataByReferralCode(
referralCode
);
const feeAllocations = feeDistribution ? [feeDistribution] : [];
const { salt, expiry } = await getSaltAndExpiryData();
const { salt, expiry } = getSaltAndExpiryData();
console.log({ salt, expiry });
const signature = await getFeeDistributionSignature(
network.foundryTokenAddress,
network,
network.fiberRouter,
feeAllocations,
feeDistribution,
salt,
expiry
expiry,
sourceAmountIn,
sourceAmountOut,
destinationAmountIn,
destinationAmountOut
);
console.log("feeDistribution signature", signature);
feeDistribution.salt = salt;
feeDistribution.expiry = expiry;
feeDistribution.signature = signature;
} catch (e) {
console.error(e);
}
console.log("getFeeDistributionObject", feeDistribution);
return feeDistribution;
}

export async function getDataAfterCutDistributionFee(
referralCode: string,
decimalAmount: any
): Promise<any> {
let amountAfterCut = decimalAmount;
let totalPlatformFee = "0";
let feeAllocations: any = [];
let data: FeeDistribution = {
feeAllocations: [],
totalPlatformFee: "",
sourceAmountIn: "",
sourceAmountOut: "",
destinationAmountIn: "",
destinationAmountOut: "",
salt: "",
expiry: 0,
signature: "",
};
try {
const response = await getFeeDistributionDataByReferralCode(referralCode);
if (response?.rateInBps && response?.recipient) {
const rateInBps = response?.rateInBps;
const rate = Number(rateInBps) / 100;
console.log("rate", rate);
amountAfterCut = await (
global as any
).commonFunctions.addSlippageInDecimal(decimalAmount, rate);
totalPlatformFee = Big(decimalAmount)
.minus(Big(amountAfterCut))
.toString();
feeAllocations.push({
recipient: response?.recipient,
platformFee: totalPlatformFee?.toString(),
});
}
data = {
feeAllocations: feeAllocations,
salt: salt,
expiry: expiry,
signature: signature,
totalPlatformFee: totalPlatformFee,
sourceAmountIn: "",
sourceAmountOut: "",
destinationAmountIn: "",
destinationAmountOut: "",
salt: "",
expiry: 0,
signature: "",
};
} catch (e) {
console.error(e);
}
console.log("getFeeDistributionData", data);
return data;
return {
amountAfterCut: amountAfterCut,
data: data,
};
}

export function convertIntoFeeDistributionObject(
feeDistribution: FeeDistribution,
sourceAmountIn: string,
sourceAmountOut: string,
destinationAmountIn: string,
destinationAmountOut: string
): FeeDistribution {
try {
feeDistribution.sourceAmountIn = sourceAmountIn;
feeDistribution.sourceAmountOut = sourceAmountOut;
feeDistribution.destinationAmountIn = destinationAmountIn;
feeDistribution.destinationAmountOut = destinationAmountOut;
} catch (e) {
console.error(e);
}
return feeDistribution;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import Web3 from "web3";
import crypto from "crypto";
import { ethers } from "ethers";
import { _TypedDataEncoder } from "ethers/lib/utils";
import { FeeDistribution } from "../../../../interfaces/feeDistributionInterface";
const CONTRACT_NAME = "FEE_DISTRIBUTOR";
const CONTRACT_VERSION = "000.001";

export const getSaltAndExpiryData = async () => {
export const getSaltAndExpiryData = () => {
const salt = Web3.utils.keccak256(crypto.randomBytes(512).toString("hex"));
const expiry = getExpiry();
return { salt, expiry };
Expand All @@ -16,10 +17,27 @@ export const getFeeDistributionSignature = async (
token: string,
network: any,
fiberRouterContractAddress: any,
feeAllocations: any[],
feeDistribution: FeeDistribution,
salt: any,
expiry: any
expiry: any,
sourceAmountIn: string,
sourceAmountOut: string,
destinationAmountIn: string,
destinationAmountOut: string
) => {
console.log("feeAllocations", feeDistribution?.feeAllocations);
console.log("totalPlatformFee", feeDistribution?.totalPlatformFee);
console.log(
"sourceAmountIn:",
sourceAmountIn,
"sourceAmountOut:",
sourceAmountOut,
"destinationAmountIn:",
destinationAmountIn,
"destinationAmountOut:",
destinationAmountOut
);

const domain = {
name: CONTRACT_NAME,
version: CONTRACT_VERSION,
Expand All @@ -29,25 +47,34 @@ export const getFeeDistributionSignature = async (
const types = {
FeeAllocation: [
{ name: "recipient", type: "address" },
{ name: "rateInBps", type: "uint16" },
{ name: "platformFee", type: "uint256" },
],
DistributeFees: [
{ name: "token", type: "address" },
{ name: "feeAllocations", type: "FeeAllocation[]" },
{ name: "totalPlatformFee", type: "uint256" },
{ name: "sourceAmountIn", type: "uint256" },
{ name: "sourceAmountOut", type: "uint256" },
{ name: "destinationAmountIn", type: "uint256" },
{ name: "destinationAmountOut", type: "uint256" },
{ name: "salt", type: "bytes32" },
{ name: "expiry", type: "uint256" },
],
};
const values = {
token: token,
feeAllocations: feeAllocations,
feeAllocations: feeDistribution?.feeAllocations,
totalPlatformFee: feeDistribution?.totalPlatformFee,
sourceAmountIn: sourceAmountIn,
sourceAmountOut: sourceAmountOut,
destinationAmountIn: destinationAmountIn,
destinationAmountOut: destinationAmountOut,
salt: salt,
expiry: expiry,
};
var wallet = new ethers.Wallet((global as any).environment.PRI_KEY);
const signer = wallet.connect(network?.provider);
const signature = await signer._signTypedData(domain, types, values);
console.log("getFeeDistributionSignature", signature);
return signature;
};

Expand Down
38 changes: 22 additions & 16 deletions app/lib/middlewares/helpers/multiSwapHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export const getQuoteAndTokenTypeInformation = async function (req: any) {
let gasEstimationDestinationAmount = req.query.gasEstimationDestinationAmount;
let sourceSlippage = req.query.sourceSlippage;
let destinationSlippage = req.query.destinationSlippage;
let referralCode = req.query.referralCode;

if (
isSameNetworksSwap(
req.query.sourceNetworkChainId,
Expand Down Expand Up @@ -55,7 +57,8 @@ export const getQuoteAndTokenTypeInformation = async function (req: any) {
destinationWalletAddress,
gasEstimationDestinationAmount,
sourceSlippage,
destinationSlippage
destinationSlippage,
referralCode
);
}
let data: any = await getResponseForQuoteAndTokenTypeInformation(
Expand All @@ -75,7 +78,8 @@ export const getSwapSigned = async function (req: any) {
req.query.destinationNetworkChainId,
req.query.sourceAmount,
req.query.destinationWalletAddress,
req.query
req.query,
req.body
);
return data;
};
Expand Down Expand Up @@ -198,12 +202,16 @@ export const swapSignedValidation = function (req: any) {
) {
throw "sourceWalletAddress & sourceTokenContractAddress & sourceNetworkChainId & sourceAmount & destinationTokenContractAddress & destinationNetworkChainId & sourceAssetType & destinationAssetType are missing";
}
if (
req.query.sourceNetworkChainId != req.query.destinationNetworkChainId &&
!req.query.gasPrice
) {
const isSameNetworkSwap = isSameNetworksSwap(
req.query.sourceNetworkChainId,
req.query.destinationNetworkChainId
);
if (!isSameNetworkSwap && !req.query.gasPrice) {
throw "gasPrice is missing";
}
if (!isSameNetworkSwap && !req.body.feeDistribution) {
throw "feeDistribution is missing";
}
};

export const withdrawSignedValidation = function (req: any) {
Expand Down Expand Up @@ -246,33 +254,30 @@ const getResponseForQuoteAndTokenTypeInformation = async function (
: categorizedInfo?.destination?.amount;
let sourceCallData = "";
let destinationCallData = "";
let sourceBridgeAmount = "";
if (categorizedInfo?.source?.callData) {
sourceCallData = categorizedInfo?.source?.callData;
}
if (categorizedInfo?.destination?.callData) {
destinationCallData = categorizedInfo?.destination?.callData;
}
if (categorizedInfo?.source?.bridgeAmount) {
sourceBridgeAmount = categorizedInfo?.source?.bridgeAmount;
}

let sourceTokenCategorizedInfo: any = {};
sourceTokenCategorizedInfo.type = categorizedInfo.source.type;
sourceTokenCategorizedInfo.sourceAmount = req.query.sourceAmount;
sourceTokenCategorizedInfo.sourceBridgeAmount = sourceBridgeAmount;
sourceTokenCategorizedInfo.sourceAmountIn =
categorizedInfo?.source?.sourceAmountIn;
sourceTokenCategorizedInfo.sourceAmountOut =
categorizedInfo?.source?.sourceAmountOut;
sourceTokenCategorizedInfo.sourceOneInchData = sourceCallData;

let destinationTokenCategorizedInfo: any = {};
destinationTokenCategorizedInfo.type = categorizedInfo.destination.type;
destinationTokenCategorizedInfo.destinationAmount = destinationAmount;
destinationTokenCategorizedInfo.minDestinationAmount = minDestinationAmount;
destinationTokenCategorizedInfo.destinationAmountIn =
categorizedInfo?.destination?.bridgeAmountIn;
destinationTokenCategorizedInfo.destinationAmountOut = categorizedInfo
?.destination?.bridgeAmountOut
? categorizedInfo?.destination?.bridgeAmountOut
: "";
categorizedInfo?.destination?.destinationAmountIn;
destinationTokenCategorizedInfo.destinationAmountOut =
categorizedInfo?.destination?.destinationAmountOut;
destinationTokenCategorizedInfo.destinationOneInchData =
destinationCallData;
data.sourceSlippage = await getSlippage(req.query.sourceSlippage);
Expand All @@ -281,6 +286,7 @@ const getResponseForQuoteAndTokenTypeInformation = async function (
data.sourceTokenCategorizedInfo = sourceTokenCategorizedInfo;
data.destinationTokenCategorizedInfo = destinationTokenCategorizedInfo;
data.isCCTP = categorizedInfo?.isCCTP ? categorizedInfo?.isCCTP : false;
data.feeDistribution = categorizedInfo?.feeDistribution;
}
console.log("getTokenCategorizedInformation response", data);
return data;
Expand Down
Loading

0 comments on commit 07d9608

Please sign in to comment.