UNPKG

stxcity-sdk

Version:

SDK for interacting with Stxcity

141 lines 7.14 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.sellBondingTokenHandler = void 0; const axios_1 = __importDefault(require("axios")); const connect_1 = require("@stacks/connect"); const transactions_1 = require("@stacks/transactions"); const hiroAPIHelpers_1 = __importDefault(require("../lib/hiroAPIHelpers")); const config_1 = require("../config"); const constants_1 = require("../lib/constants"); const checkValidBondingTokenHandler_1 = require("./checkValidBondingTokenHandler"); const sellBondingTokenHandler = (params, context) => __awaiter(void 0, void 0, void 0, function* () { try { // Validate input parameters const requiredFields = ['tokenAmount', 'dexContractId', 'senderAddress', 'tokenContractId', 'tokenSymbol', 'slippage']; validateInputAndThrow(params, requiredFields); // check valid token try { const isValidtoken = yield (0, checkValidBondingTokenHandler_1.checkValidBondingTokenHandler)(params.dexContractId, params.tokenContractId); if (!isValidtoken) throw new Error(config_1.MALICIOUS_TOKEN_MESSAGE); } catch (error) { throw new Error(config_1.MALICIOUS_TOKEN_MESSAGE); } // Ensure tokenAmount is a positive number if (params.tokenAmount <= 0) { throw new Error("Token amount must be a positive number."); } const tokenAmountAfterDecimals = BigInt(Math.floor(params.tokenAmount * Math.pow(10, 6))); if (tokenAmountAfterDecimals <= 0) { throw new Error("Invalid token amount provided."); } const tokenAmountAfterDecimalsCV = (0, transactions_1.uintCV)(tokenAmountAfterDecimals); const tokenAmountAfterDecimalsHex = (0, transactions_1.cvToHex)(tokenAmountAfterDecimalsCV); const dexDeployer = params.dexContractId.split(".")[0]; const dexContractName = params.dexContractId.split(".")[1]; const response = yield getSellableToken(dexDeployer, dexContractName, params.senderAddress, tokenAmountAfterDecimalsHex); // Check if the response is successful and data is available if (!response || !response.data || !response.data.result) { throw new Error("Failed to fetch sellable token information."); } const sellableInfoCV = (0, transactions_1.hexToCV)(response.data.result); const sellableInfoData = (0, transactions_1.cvToJSON)(sellableInfoCV); const sellableInfoObj = sellableInfoData.value.value; const stxReceivableVal = parseInt(sellableInfoObj["receivable-stx"].value); // Ensure stxReceivableVal is a positive number if (stxReceivableVal <= 0) { throw new Error("STX receivable value must be a positive number."); } const stxReceivable = Number(stxReceivableVal - Math.floor((stxReceivableVal * params.slippage) / 100)); // Ensure stxReceivable is a positive number after applying slippage if (stxReceivable <= 0) { throw new Error("STX receivable value after slippage must be a positive number."); } // dex will send stx to users const stxAmtWithSlip = Math.floor((stxReceivable * 96) / 100); const sendSTXPostCondition = transactions_1.Pc.principal(params.dexContractId) .willSendGte(stxAmtWithSlip) .ustx(); const contractNameForPC = validateAndUseString(params.tokenContractId); const sendFTCondition = transactions_1.Pc.principal(params.senderAddress) .willSendEq(BigInt(tokenAmountAfterDecimals)) .ft(contractNameForPC, params.tokenSymbol); const handleOnFinish = (data) => { if (data) { if (params.onFinish) { const modifiedData = Object.assign(Object.assign({}, data), { status: "Sell token successfully" }); params.onFinish(modifiedData); } } }; const handleOnCancel = () => { if (params.onCancel) { params.onCancel(); } }; yield (0, connect_1.openContractCall)({ postConditionMode: transactions_1.PostConditionMode.Deny, postConditions: [sendSTXPostCondition, sendFTCondition], contractAddress: dexDeployer, anchorMode: transactions_1.AnchorMode.OnChainOnly, appDetails: constants_1.appDetails, contractName: dexContractName, functionName: "sell", functionArgs: [ (0, transactions_1.principalCV)(params.tokenContractId), // token-x-trait (0, transactions_1.uintCV)(tokenAmountAfterDecimals), // x value ], network: context.network, onFinish: handleOnFinish, onCancel: handleOnCancel, }); } catch (error) { throw error; } }); exports.sellBondingTokenHandler = sellBondingTokenHandler; const getSellableToken = (dexDeployer, dexContractName, senderAdress, tokenAmountAfterDecimalsHex) => __awaiter(void 0, void 0, void 0, function* () { const apiURL = `${config_1.configs.STACKS_NETWORK_API_HOST}/v2/contracts/call-read/${dexDeployer}/${dexContractName}/get-sellable-stx`; const requestData = { sender: senderAdress, arguments: [tokenAmountAfterDecimalsHex], }; return axios_1.default.post(apiURL, requestData, { headers: (0, hiroAPIHelpers_1.default)(), }); }); const validateAndUseString = (inputString) => { const parts = inputString.split("."); return inputString; }; const validateInputAndThrow = (inputData, requiredFields) => { requiredFields.forEach(field => { if (!inputData.hasOwnProperty(field)) { throw new Error(`Missing required field: ${field}`); } }); Object.keys(inputData).forEach((key) => { if (inputData[key] === null || inputData[key] === undefined || inputData[key] === "") { throw new Error(`Field "${key}" cannot be null, undefined or empty`); } }); if (inputData.slippage < 0 || inputData.slippage > 100) { throw new Error("Slippage must be a number between 0 and 100."); } }; //# sourceMappingURL=sellBondingTokenHandler.js.map