This is my trade code
const fireblocksSettings = require("../fireblocksSettings");
const mathOps = require("../utils/math");
var logger = require("../logger");
var transactionFactory = require("../factories/TransactionFactory");
var AggregatorService = require("./AggregatorService");
const aggregatorService = new AggregatorService();
const TransactionService = require("./TransactionService");
const appConfig = new (require(`../config.${process.env.NODE_ENV}`))();
const FireblocksSDK = require("fireblocks-sdk").FireblocksSDK;
const apiSecret = appConfig.fireblocksSecret;
const apiKey = appConfig.fireblocksKey;
const fireblocks = new FireblocksSDK(apiSecret, apiKey);
const FireblocksTransactionSchema = require("../schemas/transaction");
const ethers = require("ethers");
const {
FireblocksWeb3Provider,
ChainId,
} = require("@fireblocks/fireblocks-web3-provider");
const constants = require("../message-queue/RabbitListenerConstants");
var rabbitMqFactory = require("../messageBrokerFactory");
var messageBus = rabbitMqFactory.getBroker();
const TransactionUpdate = require("../message-queue/TransactionUpdate");
const TokenService = require("../services/TokenService");
class TradeService {
constructor(arg, securityContext, tenantId, uid) {
this.arg = arg;
logger.info("user input value is Shahid-1", arg)
this.arg.tradeCommission = mathOps.getTradeCommission(arg.amount);
this.arg.usersCut = mathOps.getUsersCut(
arg.amount,
this.arg.tradeCommission,
);
logger.info("user cut value is Shahid ", this.arg.usersCut)
this.securityContext = securityContext;
const eip1193Provider = new FireblocksWeb3Provider({
privateKey: apiSecret,
apiKey: apiKey,
vaultAccountIds: this.arg.vaultId,
chainId: ChainId.BSC,
});
this.provider = new ethers.providers.Web3Provider(eip1193Provider);
this.tenantId = tenantId;
this.auth0Id = uid;
}
securityCheck = async () => {
let doApprove = false;
let allowance = null;
let balance = null;
logger.info(
`its ${this.arg.inTokenSymbol} | ots ${this.arg.outTokenSymbol}`,
);
if (this.arg.fireblocksAssetId == fireblocksSettings.baseAssetId) {
const vaultAsset = await fireblocks.getVaultAccountAsset(
this.arg.vaultId,
this.arg.fireblocksAssetId,
);
balance = vaultAsset.total;
} else {
const signer = await this.provider.getSigner();
const signerAddress = await signer.getAddress();
const contract = new ethers.Contract(
this.arg.inTokenAddress,
fireblocksSettings.ooABI,
signer,
);
const balanceRaw = await contract.balanceOf(signerAddress);
const decimals = await contract.decimals();
balance = ethers.utils.formatUnits(
ethers.BigNumber.from(balanceRaw),
decimals,
);
allowance = ethers.utils.formatUnits(
await contract.allowance(
signerAddress,
fireblocksSettings.openOceanContractAddress,
),
decimals,
);
logger.info(
"__allowance:" +
allowance +
" balance:" +
balance +
" decimals:" +
decimals,
);
if (allowance < this.arg.amount) {
doApprove = true;
logger.info("__allowance needed");
}
}
if (balance < this.arg.amount) {
// throw new Error('Insufficient balance. Balance:'+balance+' Amount:'+this.arg.amount);
await this.saveFailedTxn();
await this.sendRabbitMessage();
throw {
type: "INSUFFICIENT_BALANCE",
message: `balance: ${balance}, amount: ${this.arg.amount}`,
};
}
this.userVaultAddress = await this.getAccountAddress(
this.arg.vaultId,
this.arg.fireblocksAssetId,
);
let gasPriceRaw = await this.provider.getGasPrice();
let gasPrice = ethers.utils.formatUnits(gasPriceRaw, "gwei");
logger.info('After Before acessing the tradeResult.data');
let tradeResult = await aggregatorService.getCryptoTradeSwapQuote({
inTokenAddress: this.arg.inTokenAddress,
outTokenAddress: this.arg.outTokenAddress,
usersCut: this.arg.usersCut,
gasPrice: gasPrice,
account: this.userVaultAddress,
});
logger.info('After accessing tradeResult.data', JSON.stringify(tradeResult.data));
if (tradeResult.data.data == "0x") {
// throw Error('Openocean does not support this transaction');
await this.saveFailedTxn();
await this.sendRabbitMessage();
throw {
type: "TRANSACTION_NOT_SUPPORTED",
message: `openocean does not support this transaction`,
};
}
let usersResponse = JSON.parse(JSON.stringify(tradeResult.data));
usersResponse.inAmount = mathOps.toDecimal(
tradeResult.data.inAmount,
tradeResult.data.inToken.decimals,
);
usersResponse.outAmount = mathOps.toDecimal(
tradeResult.data.outAmount,
tradeResult.data.outToken.decimals,
);
usersResponse.minOutAmount = mathOps.toDecimal(
tradeResult.data.minOutAmount,
tradeResult.data.outToken.decimals,
);
return { tradeResult, doApprove, usersResponse };
};
execute = async (tenantId, tradeResult, doApprove) => {
await this.getBaseAssetBalance(this.arg.vaultId);
if (!doApprove) logger.info("___allowance not needed");
if (doApprove) {
const signer = await this.provider.getSigner();
const signerAddress = await signer.getAddress();
logger.info("__signerAddress " + signerAddress);
const contract = new ethers.Contract(
this.arg.inTokenAddress,
fireblocksSettings.ooABI,
signer,
);
const balanceRaw = await contract.balanceOf(signerAddress);
console.log("balance raw is ", balanceRaw);
const decimals = await contract.decimals();
console.log("the decimal value is ", decimals);
const symbol = await contract.symbol();
console.log("the symbol is ", symbol);
logger.info(
"__approving " + symbol + "|" + decimals + "|" + this.arg.amount,
);
let approveAmount = ethers.utils.parseUnits(
this.arg.amount.toString(),
decimals,
);
let erc20 = await contract.approve(
fireblocksSettings.openOceanContractAddress,
approveAmount,
);
const receipt = await erc20.wait();
}
let transactionServiceInstance = new TransactionService(
this.securityContext,
);
let details = {
from: this.arg.inTokenSymbol,
to: this.arg.outTokenSymbol,
outAssetId: this.arg.fireblocksOutAssetId,
inTokenAmount: this.arg.usersCut,
totalAmount: this.arg.amount,
inAssetId: this.arg.fireblocksAssetId,
amountInUsd: this.arg.amountInUsd,
outTokenAmount: mathOps.toDecimal(
tradeResult.data.outAmount,
tradeResult.data.outToken.decimals,
),
minimumReceived: mathOps.toDecimal(
tradeResult.data.minOutAmount,
tradeResult.data.outToken.decimals,
),
inTokenAddress: this.arg.inTokenAddress,
};
var gasPriceRaw = await this.provider.getGasPrice();
var gasPrice = ethers.utils.formatUnits(gasPriceRaw, "gwei");
gasPrice = gasPrice;
logger.info("before calling the getCryptoTradeSwapQuote")
tradeResult = await aggregatorService.getCryptoTradeSwapQuote({
inTokenAddress: this.arg.inTokenAddress,
outTokenAddress: this.arg.outTokenAddress,
usersCut: this.arg.usersCut,
gasPrice: gasPrice,
account: this.userVaultAddress,
});
const tradeTransactionBody = transactionFactory.cryptoTradeContract(
this.arg.fireblocksAssetId,
this.arg.vaultId,
tradeResult.data.data,
this.arg.inTokenAddress === fireblocksSettings.baseContractAddress
? this.arg.usersCut
: "0",
this.arg.userId,
details,
gasPrice,
tradeResult.data.estimatedGas * 2,
);
logger.info("transcation body", JSON.stringify(tradeTransactionBody));
const tradeTxnResult = await transactionServiceInstance.create(
tradeTransactionBody,
tenantId,
this.auth0Id,
);
return tradeTxnResult;
};
getAccountAddress = async (vId, aId) => {
const depositAddresses = await fireblocks.getDepositAddresses(vId, aId);
return depositAddresses[0].address;
};
getBaseAssetBalance = async (vid) => {
let vaultAsset = await fireblocks.getVaultAccountAsset(
vid,
fireblocksSettings.baseAssetId,
);
logger.info(
`base asset balance of vaultid: ${vid} asset ${fireblocksSettings.baseAssetId}: ${vaultAsset.total}`,
);
};
saveFailedTxn = async () => {
let resultData = {
fireblocksTransactionId: "",
userId: this.arg.userId,
type: "trade",
assetSymbol: this.arg.inTokenSymbol,
CreateDate: new Date(),
CreatedBy: "",
TenantId: this.tenantId,
fromSymbol: this.arg.inTokenSymbol,
toSymbol: this.arg.outTokenSymbol,
outAssetId: this.arg.fireblocksOutAssetId,
outTokenAmount: "",
minimumReceived: "",
inTokenAmount: this.arg.usersCut,
inAssetId: this.arg.fireblocksAssetId,
amountInUsd: this.arg.amountInUsd,
totalAmount: this.arg.amount,
inTokenAddress: "",
status: "SUBMISSION_FAILED",
};
const FireblocksTransactionModel = this.securityContext.getCollection(
this.tenantId,
"FireblocksTransactions",
FireblocksTransactionSchema,
);
const fireblocksTransaction = new FireblocksTransactionModel(resultData);
const txnData = await fireblocksTransaction.save();
};
sendRabbitMessage = async () => {
var rabbitMessage = new TransactionUpdate(
"--",
"SUBMISSION_FAILED",
"SUBMISSION_FAILED",
this.auth0Id,
"TRANSACTION_STATUS_UPDATED",
this.arg.amount,
this.arg.userId,
"trade",
);
var tokenService = new TokenService(appConfig);
let token = this.securityContext.extractedToken;
let ecapToken = await tokenService.getEcapTokenFromAuth0Token(token);
messageBus.prepareChannel((ch) => {
messageBus.sendToQueue(
constants.X4T_CRYPTO_QUEUE,
ch,
ecapToken,
rabbitMessage,
);
});
};
}
module.exports = TradeService;
The function i am using
function roundDownBalance(balance) {
const roundedBalance = Math.floor(balance * 10 ** 17) / 10 ** 17;
return roundedBalance;
}
Trade commission function
const getTradeCommission = (arg) => {
return roundDownBalance((2 / 100) * arg);
};
Users cut function
const getUsersCut = (arg1) => {
let comission = (getWithdrawCommission(arg1));
return roundDownBalance(arg1 - comission);
};
do i need to update my function for this use case
https://developers.fireblocks.com/reference/balance-decimal-precision