UNPKG

@firefly-exchange/library-sui

Version:

Sui library housing helper methods, classes to interact with Bluefin protocol(s) deployed on Sui

538 lines (537 loc) 28.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RequestsBuilder = void 0; const constants_1 = require("../constants"); const blake2b_1 = require("@noble/hashes/blake2b"); const library_1 = require("../library"); const utils_1 = require("./utils"); const bcs_1 = require("./utils/bcs"); const enums_1 = require("./enums"); class RequestsBuilder { /** * Class constructor * @param _deployment the deployment config * @param _signer the wallet/signer * @param _walletAddress (optional) the wallet/signer address */ constructor(_deployment, _signer, _walletAddress) { this.parser = new utils_1.DeploymentParser(_deployment); this.signer = _signer; this.walletAddress = _walletAddress || _signer?.toSuiAddress(); } /** * Create a withdrawal request for user to submit to bluefin gateway * @param assetSymbol name of the asset to be withdrawn * @param amountE9 amount to be withdrawn. Should be in 9 decimal places * @param options Optional params: * - salt: A random number to make the withdrawal payload unique for the user * - account: The address of the account performing the withdraw * - assetBankID: The address of the asset bank. By default fetches the asset bank of the provided asset symbol * - eds: The id of the External Data store * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async withdrawal(assetSymbol, amountE9, options) { const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.WITHDRAWAL, eds: options?.eds || this.parser.getExternalDataStore(), assetSymbol, account: options?.account || this.walletAddress, amount: (0, library_1.bigNumber)(amountE9).toFixed(0), salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.Withdrawal); // sign the payload const signature = await utils_1.Signature.signRequest(options?.signer || this.signer, new TextEncoder().encode(JSON.stringify(rawData, null, 2))); return { rawData, serializedData, signature }; } /** * Creates an authorized user request for user to submit to bluefin gateway * @param user The address of the account to be authorized or unauthorized * @param status a boolean indicating if the users are to be authorized or not * @param options Optional params: * - signer: The signer that will be signing the payload * - account: The account for which to authorize users - defaults to `this.walletAddress` * - ids: The internal data store id * - salt: A random number to make the payload unique * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async authorizeUser(user, status, options) { const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.AUTHORIZE_ACCOUNT, ids: options?.ids || this.parser.getInternalDataStore(), account: options?.account || this.walletAddress, user, status, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.AuthorizeUser); // sign the payload const signature = await utils_1.Signature.signRequest(options?.signer || this.signer, new TextEncoder().encode(JSON.stringify(rawData, null, 2))); return { rawData, serializedData, signature }; } /** * Creates a signed order * @param orderParams Params for order creation * @param options Optional params * - signer: the signer of the order * - ids: The id of internal data store * @returns IRequestPayload */ async createSignedOrder(orderParams, options) { const signer = options?.signer || this.signer; const ids = orderParams?.ids || this.parser.getInternalDataStore(); const account = orderParams.account || signer.toSuiAddress(); // build order const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.ORDER, ids, account, market: orderParams.market || "ETH-PERP", price: (0, library_1.toBigNumberStr)(orderParams.price != undefined ? orderParams.price : 3500, constants_1.SUI_NATIVE_BASE), quantity: (0, library_1.toBigNumberStr)(orderParams.quantity != undefined ? orderParams.quantity : 0.1, constants_1.SUI_NATIVE_BASE), leverage: (0, library_1.toBigNumberStr)(orderParams.leverage != undefined ? orderParams.leverage : 0, constants_1.SUI_NATIVE_BASE), side: orderParams.side || "LONG", positionType: orderParams.positionType || enums_1.POSITION_TYPES.CROSS, expiration: String(orderParams.expiration || 2037603360000), salt: String(orderParams.salt || (0, utils_1.generateSalt)()), signedAt: String(orderParams.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.Order); // this is the order hash const hash = Buffer.from((0, blake2b_1.blake2b)((0, library_1.hexStrToUint8)(serializedData), { dkLen: 32 })).toString("hex"); // sign the payload const signature = await utils_1.Signature.signRequest(options?.signer || this.signer, new TextEncoder().encode(JSON.stringify(rawData, null, 2))); return { rawData: { ...rawData, hash, signature }, serializedData, signature }; } /** * Create a liquidation request for user to submit to bluefin gateway * @param liquidatee: The address of the account to be liquidated * @param market: The symbol of the market/perpetual for which to liquidate user's position * @param positionType: The type of position being liquidated * @param assumeAs: The position to be assumed as isolated or cross * @param quantityE9: The amount to be liquidated * @param options Optional params: * - signer: The signer to be used to sign the payload. Defaults to signer of the class (this.signer) * - liquidator: The address of the liquidator. Defaults to the signer address * - allOrNothing: True if the complete specified amount must be liquidated, false otherwise. Defaults to False * - salt: A random number to make the payload unique * - expiry: The timestamp till which the signed liquidation is valid * - leverageE9: If assuming as an isolated position, specify the leverage. Defaults to 1 for isolated position, and passed as 0 for cross. * - ids: The internal data store id/address * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async createSignedLiquidation(liquidatee, market, positionType, assumeAs, quantityE9, options) { const signer = options?.signer || this.signer; const liquidator = options?.liquidator || signer.toSuiAddress(); const allOrNothing = options?.allOrNothing == true; const leverageE9 = assumeAs == enums_1.ASSUME_AS.CROSS ? 0 : options?.leverageE9 || constants_1.BIGNUMBER_BASE_ON_CHAIN; const expiry = options?.expiry || 2037603360000; const salt = options?.salt || (0, utils_1.generateSalt)(); const ids = options?.ids || this.parser.getInternalDataStore(); // build liquidate request payload const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.LIQUIDATE, ids, liquidatee, liquidator, market, quantity: (0, library_1.bigNumber)(quantityE9).toFixed(0), isolated: positionType == enums_1.POSITION_TYPES.ISOLATED, assumeAsCross: assumeAs == enums_1.ASSUME_AS.CROSS, allOrNothing, leverage: (0, library_1.bigNumber)(leverageE9).toFixed(0), expiry: String(expiry), salt: String(salt), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.Liquidate); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create an ADL request for user to submit to bluefin gateway * @param maker: The address of the account to be deleveraged (bankrupt) * @param taker: The address of the account to be deleveraged against +Pnl * @param market: The symbol of the market/perpetual for which to liquidate user's position * @param makerPositionType: The type of maker position being deleveraged * @param takerPositionType: The type of taker position being deleveraged * @param quantityE9: The amount to be deleveraged * @param options Optional params: * - signer: The signer to be used to sign the payload. Defaults to signer of the class (this.signer) * - salt: A random number to make the payload unique * - expiry: The timestamp till which the signed adl is valid * - ids: The internal data store id/address * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async createSignedADL(maker, taker, makerPositionType, takerPositionType, market, quantityE9, options) { const signer = options?.signer || this.signer; const expiry = options?.expiry || 2037603360000; const salt = options?.salt || (0, utils_1.generateSalt)(); const ids = options?.ids || this.parser.getInternalDataStore(); // build liquidate request payload const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.DELEVERAGE, ids, maker, taker, makerIsolated: makerPositionType == enums_1.POSITION_TYPES.ISOLATED, takerIsolated: takerPositionType == enums_1.POSITION_TYPES.ISOLATED, market, quantity: (0, library_1.bigNumber)(quantityE9).toFixed(0), expiry: String(expiry), salt: String(salt), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.Deleverage); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create a adjust margin request for user to submit to bluefin gateway * @param marketAddress The address of the market/perpetual for which to adjust the margin * @param amountE9 The amount to be added/withdrawn from isolated position * @param options Optional params: * - account: The account address for which margin to be adjusted. The account defaults to `this.walletAddress` * - signer: The signer to be used to sign the payload. Defaults to signer of the class `this.signer` * - salt: A random number to make the payload unique * - ids: The internal data store id/address * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async adjustMargin(market, add, amountE9, options) { const signer = options?.signer || this.signer; const account = options?.account || this.walletAddress; const ids = options?.ids || this.parser.getInternalDataStore(); // build adjust margin request payload const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.ADJUST_MARGIN, ids, account, market, add, amount: (0, library_1.bigNumber)(amountE9).toFixed(0), salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.AdjustMargin); // sign the payload const signature = await utils_1.Signature.signRequest(signer, new TextEncoder().encode(JSON.stringify(rawData, null, 2))); return { rawData, serializedData, signature }; } /** * Create a adjust leverage request for user to submit to bluefin gateway * @param market The symbol of the market/perpetual for which to adjust the leverage * @param leverage The new leverage to be used * @param options Optional params: * - account: The account address for which margin to be adjusted. The account defaults to `this.walletAddress` * - signer: The signer to be used to sign the payload. Defaults to signer of the class `this.signer` * - salt: A random number to make the payload unique * - ids: The internal data store id/address * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async adjustLeverage(market, leverage, options) { const signer = options?.signer || this.signer; const account = options?.account || this.walletAddress; const ids = options?.ids || this.parser.getInternalDataStore(); // build adjust leverage request payload const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.ADJUST_LEVERAGE, ids, account, market, leverage: (0, library_1.bigNumber)(leverage).toFixed(0), salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.AdjustLeverage); // sign the payload const signature = await utils_1.Signature.signRequest(signer, new TextEncoder().encode(JSON.stringify(rawData, null, 2))); return { rawData, serializedData, signature }; } /** * Create a set funding rate request payload for the funding rate operator to submit to bluefin gateway * @param marketsFundingRates The funding rate of each market/perpetual along with the market address * @param options Optional params: * - signer: The signer to be used to sign the payload. Defaults to signer of the class `this.signer` * - salt: A random number to make the payload unique * - timestamp: The timestamp in seconds for which the funding rate is being set. * This should be hourly timestamp. If not provided the method takes current * time and rounds it up/down to closest hour mark * - ids: The internal data store id/address * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async setFundingRate(marketsFundingRates, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); const timestamp = options?.timestamp || new Date(3600000 * (1 + Math.round(Date.now() / 3600000))).getTime(); const fundingRates = marketsFundingRates.map(mfr => bcs_1.BCSUtils.getSerializedDataBytes(mfr, bcs_1.MarketFundingRate)); // build withdrawal request payload const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.SET_FUNDING_RATE, ids, timestamp: String(timestamp), marketFundingRates: fundingRates, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.SetFundingRate); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create bcs serialized payload for applying funding rate * @param accounts The array of account addresses to which to apply funding rate * @param options Optional params: * - ids: The address/id of the internal data store - This makes sure that a payload * signed for testnet can not be executed on mainnet * - salt: A random number to make the payload unique * - timestamp: The timestamp in seconds for which the funding rate is to be applied * This should be hourly timestamp. If not provided the method takes current * time and rounds it up/down to closest hour mark * - market: If provided, the FR request is created to be applied to provided market * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async applyFundingRate(accounts, options) { const timestamp = options?.timestamp || new Date(3600000 * (1 + Math.round(Date.now() / 3600000))).getTime() / 1000; const ids = options?.ids || this.parser.getInternalDataStore(); const rawData = { ids, timestamp: String(timestamp), accounts, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()), market: options?.market || "" }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.ApplyFundingRate); return { rawData, serializedData, signature: undefined }; } /** * Creates a prune table payload and signs it * @param hashes The list of hashes that are to be pruned * @param table_index The table type (index) from which the hashes are to be pruned * @param options Optional params: * - signer: The signer to be used to sign the payload. Defaults to signer of the class `this.signer` * - salt: A random number to make the payload unique * - ids: The address/id of the internal data store - This makes sure that a payload * signed for testnet can not be executed on mainnet * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async pruneTable(hashes, table_index, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); // build withdrawal request payload const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.PRUNING_TABLE, ids, hashes, table_index, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.PruneTable); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create an authorize bankrupt liquidator payload to submit to api gateway * @param status The address of the account to be authorized or unauthorized * @param authorized a boolean indicating if the users are to be authorized or not * @param options Optional params: * - signer: The signer that will be signing the payload * - ids: The internal data store id * - salt: A random number to make the payload unique * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async authorizeLiquidator(account, authorized, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); // build withdrawal request payload const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.AUTHORIZE_LIQUIDATOR, account, ids: ids, authorized, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.authorizeLiquidator); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Creates a signed payload for setting tier of an account * @param status The address of the account to be authorized or unauthorized * @param makerFee The maker side fee percentage * @param takerFee The taker side fee percentage * @param applied True if the fee tier is to be applied * @param options Optional params: * - signer: The signer that will be signing the payload * - ids: The internal data store id * - salt: A random number to make the payload unique * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async setFeeTier(account, makerFee, takerFee, applied, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); const makerFeeNumber = (0, library_1.bigNumber)(makerFee).toFixed(0); const takerFeeNumber = (0, library_1.bigNumber)(takerFee).toFixed(0); const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.SET_FEE_TIER, account, ids: ids, makerFee: makerFeeNumber, takerFee: takerFeeNumber, applied, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.FeeTier); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create a set account type signed payload * @param account The address for which to set type * @param type The account type Institution or Retail * @param options Optional params: * - signer: The signer that will be signing the payload * - ids: The internal data store id * - salt: A random number to make the payload unique * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async setAccountType(account, type, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.SET_ACCOUNT_TYPE, ids: ids, account, isInstitution: type == enums_1.ACCOUNT_TYPE.INSTITUTION, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.AccountType); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create a set gas fee signed payload * @param amount The new gas fee amount (in 1e9) * @param options Optional params: * - signer: The signer that will be signing the payload * - ids: The internal data store id * - salt: A random number to make the payload unique * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async setGasFee(amount, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.SET_GAS_FEE, ids: ids, amount: (0, library_1.bigNumber)(amount).toFixed(0), salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.GasFee); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create a set gas pool signed payload * @param pool The new gas pool address * @param options Optional params: * - signer: The signer that will be signing the payload * - ids: The internal data store id * - salt: A random number to make the payload unique * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async setGasPool(pool, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.SET_GAS_POOL, ids: ids, pool, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.GasPool); // sign the payload const signature = await utils_1.Signature.signRequest(signer, (0, library_1.hexStrToUint8)(serializedData)); return { rawData, serializedData, signature }; } /** * Create signed payload for closing position of a delisted market * @param market Market name for which to close the position * @param positionType The type of position being closed ISOLATED or CROSS * @param options Optional params: * - account: The address of the account for which the position is being closed * - signer: The signer that will be signing the payload * - ids: The internal data store id * - salt: A random number to make the payload unique * - signedAt: The timestamp in seconds at which the payload is signed * @returns IRequestPayload */ async closePosition(market, positionType, options) { const signer = options?.signer || this.signer; const ids = options?.ids || this.parser.getInternalDataStore(); const account = options?.account || signer.toSuiAddress(); const rawData = { type: enums_1.PAYLOAD_REQUEST_TYPE.CLOSE_POSITION, ids: ids, account, market, isolated: positionType == enums_1.POSITION_TYPES.ISOLATED, salt: String(options?.salt || (0, utils_1.generateSalt)()), signedAt: String(options?.signedAt || Date.now()) }; // serialize the payload const serializedData = bcs_1.BCSUtils.getSerializedDataHex(rawData, bcs_1.ClosePosition); // sign the payload const signature = await utils_1.Signature.signRequest(signer, new TextEncoder().encode(JSON.stringify(rawData, null, 2))); return { rawData, serializedData, signature }; } } exports.RequestsBuilder = RequestsBuilder;