@mak201010/bluefin-v2-client
Version:
The Bluefin client Library allows traders to sign, create, retrieve and listen to orders on Bluefin Exchange.
1,024 lines (1,023 loc) • 68.2 kB
JavaScript
"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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BluefinClient = void 0;
const library_sui_1 = require("@mak201010/library-sui");
const bcs_1 = require("@mysten/bcs");
const cryptography_1 = require("@mysten/sui.js/cryptography");
const verify_1 = require("@mysten/sui.js/verify");
const zklogin_1 = require("@mysten/zklogin");
const sha256_1 = require("@noble/hashes/sha256");
const utils_1 = require("../utils/utils");
const constants_1 = require("./constants");
const apiService_1 = require("./exchange/apiService");
const apiUrls_1 = require("./exchange/apiUrls");
const contractService_1 = require("./exchange/contractService");
const interactorService_1 = require("./exchange/interactorService");
const sockets_1 = require("./exchange/sockets");
const WebSocket_1 = require("./exchange/WebSocket");
class BluefinClient {
/**
* initializes the class instance
* @param _isTermAccepted boolean indicating if exchange terms and conditions are accepted
* @param _network containing network rpc url and chain id
* @param _account accepts either privateKey or AWS-KMS-SIGNER object if user intend to sign using kms
* @param _scheme signature scheme to be used
*/
constructor(_isTermAccepted, _network, _account, _scheme, _isUI, _uiSignerObject) {
this.marketSymbols = []; // to save array market symbols [DOT-PERP, SOL-PERP]
this.walletAddress = ""; // to save user's public address when connecting from UI
this.isZkLogin = false;
this.isTermAccepted = false;
this.maxSaltLimit = 2 ** 60;
// the number of decimals supported by USDC contract
this.MarginTokenPrecision = 6;
this.is_wallet_extension = false;
/**
* @description
* initializes the required objects
* @param userOnboarding boolean indicating if user onboarding is required
* @param deployment
*/
this.init = (userOnboarding = true, deployment = null, apiToken = "") => __awaiter(this, void 0, void 0, function* () {
var _a;
if (apiToken) {
this.apiService.setApiToken(apiToken);
// for socket
this.sockets.setApiToken(apiToken);
(_a = this.webSockets) === null || _a === void 0 ? void 0 : _a.setApiToken(apiToken);
}
else {
if (!this.signer) {
throw Error("Signer not initialized");
}
yield this.initContractCalls(deployment);
// for BLV contract calls
yield this.initInteractorCalls();
// onboard user if not onboarded
if (userOnboarding) {
yield this.userOnBoarding();
}
}
if (this.network.UUID) {
this.setUUID(this.network.UUID);
}
});
this.initializeWithHook = (uiSignerObject, walletAddress) => __awaiter(this, void 0, void 0, function* () {
try {
this.uiWallet = uiSignerObject;
this.signer = uiSignerObject;
this.walletAddress = walletAddress;
this.isZkLogin = false;
this.is_wallet_extension = true;
}
catch (err) {
console.log(err);
throw Error("Failed to initialize through UI");
}
});
this.initializeForZkLogin = ({ _account, walletAddress, maxEpoch, proof, decodedJWT, salt, }) => {
const keyPair = (0, library_sui_1.getKeyPairFromPvtKey)(_account, "ZkLogin");
this.signer = keyPair;
this.walletAddress = walletAddress;
this.maxEpoch = maxEpoch;
this.decodedJWT = decodedJWT;
this.proof = proof;
this.salt = salt;
this.isZkLogin = true;
this.is_wallet_extension = false;
};
/***
* Set UUID to api headers for colocation partners
*/
this.setUUID = (uuid) => {
this.apiService.setUUID(uuid);
};
/**
* @description
* initializes web3 and wallet with the given account private key
* @param keypair key pair for the account to be used for placing orders
*/
this.initializeWithKeyPair = (keypair) => __awaiter(this, void 0, void 0, function* () {
this.signer = keypair;
this.walletAddress = this.signer.toSuiAddress();
this.initOrderSigner(keypair);
});
/**
* @description
* initializes web3 and wallet with the given account private key
* @param seed seed for the account to be used for placing orders
* @param scheme signature scheme to be used
* @returns void
*/
this.initializeWithSeed = (seed, scheme) => {
switch (scheme) {
case "ED25519":
this.signer = library_sui_1.Ed25519Keypair.deriveKeypair(seed);
this.initOrderSigner(library_sui_1.Ed25519Keypair.deriveKeypair(seed));
break;
case "Secp256k1":
this.signer = library_sui_1.Secp256k1Keypair.deriveKeypair(seed);
this.initOrderSigner(library_sui_1.Secp256k1Keypair.deriveKeypair(seed));
break;
default:
throw new Error("Provided scheme is invalid");
}
};
/**
* @description
* initializes contract calls
* @param deployment (optional) The deployment json provided by deployer
*/
this.initContractCalls = (deployment) => __awaiter(this, void 0, void 0, function* () {
if (!this.signer) {
throw Error("Signer not Initialized");
}
const _deployment = deployment || (yield this.getDeploymentJson());
this.contractCalls = new contractService_1.ContractCalls(this.getSigner(), _deployment, this.provider, this.isZkLogin, this.getZkPayload(), this.walletAddress, this.is_wallet_extension);
});
/**
* @description
* initializes contract calls
* @param deployment (optional) The deployment json provided by deployer
*/
this.initInteractorCalls = () => __awaiter(this, void 0, void 0, function* () {
if (!this.signer) {
throw Error("Signer not Initialized");
}
const _deployment = yield this.getVaultConfigsForInteractor();
this.interactorCalls = new interactorService_1.InteractorCalls(this.getSigner(), _deployment, this.provider);
});
/**
* @description
* Gets the RawSigner of the client
* @returns RawSigner
* */
this.getSigner = () => {
if (!this.signer) {
throw Error("Signer not initialized");
}
return this.signer;
};
/**
* @description
* Gets the RPC Provider of the client
* @returns JsonRPCProvider
* */
this.getProvider = () => {
return this.provider;
};
/**
* Generate and receive readOnlyToken, this can only be accessed at the time of generation
* @returns readOnlyToken string
*/
this.generateReadOnlyToken = () => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.post(apiUrls_1.SERVICE_URLS.USER.GENERATE_READONLY_TOKEN, {}, { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Creates message to be signed, creates signature and authorize it from dapi
* @returns auth token
*/
this.userOnBoarding = (token) => __awaiter(this, void 0, void 0, function* () {
var _b;
let userAuthToken = token;
if (!userAuthToken) {
const signature = yield this.createOnboardingSignature();
// authorize signature created by dAPI
const authTokenResponse = yield this.authorizeSignedHash(signature);
if (!authTokenResponse.ok || !authTokenResponse.data) {
throw Error(`Authorization error: ${authTokenResponse.response.message}`);
}
userAuthToken = authTokenResponse.data.token;
}
// for api
this.apiService.setAuthToken(userAuthToken);
// this.apiService.setWalletAddress(this.getPublicAddress());
// for socket
this.sockets.setAuthToken(userAuthToken);
(_b = this.webSockets) === null || _b === void 0 ? void 0 : _b.setAuthToken(userAuthToken);
// TODO: remove this when all endpoints on frontend are integrated from client library
return userAuthToken;
});
this.getZkPayload = () => {
return {
decodedJWT: this.decodedJWT,
proof: this.proof,
salt: this.salt,
maxEpoch: this.maxEpoch,
};
};
this.createOnboardingSignature = () => __awaiter(this, void 0, void 0, function* () {
let signature;
const onboardingSignature = {
onboardingUrl: this.network.onboardingUrl,
};
if (this.uiWallet) {
signature = yield library_sui_1.OrderSigner.signPayloadUsingWallet(onboardingSignature, this.uiWallet);
}
else if (this.isZkLogin) {
signature = yield library_sui_1.OrderSigner.signPayloadUsingZKSignature({
payload: onboardingSignature,
signer: this.signer,
zkPayload: this.getZkPayload(),
});
}
else {
signature = yield this.orderSigner.signPayload(onboardingSignature);
}
return `${signature === null || signature === void 0 ? void 0 : signature.signature}${(signature === null || signature === void 0 ? void 0 : signature.publicAddress) ? signature === null || signature === void 0 ? void 0 : signature.publicAddress : signature === null || signature === void 0 ? void 0 : signature.publicKey}`;
});
/**
* @description
* Gets the wallets Public address
* @returns string
* */
this.getPublicAddress = () => {
if (!this.signer) {
Error("Signer not initialized");
}
return this.walletAddress;
};
this.parseAndShapeSignedData = ({ signature, isParsingRequired = true, }) => {
let data;
let parsedSignature = (0, cryptography_1.parseSerializedSignature)(signature);
if (isParsingRequired && parsedSignature.signatureScheme === "ZkLogin") {
//zk login signature
const { userSignature } = parsedSignature.zkLogin;
//convert user sig to b64
const convertedUserSignature = (0, bcs_1.toB64)(userSignature);
//reparse b64 converted user sig
const parsedUserSignature = (0, cryptography_1.parseSerializedSignature)(convertedUserSignature);
data = {
signature: Buffer.from(parsedSignature.signature).toString("hex") + "3",
publicKey: (0, verify_1.publicKeyFromRawBytes)(parsedUserSignature.signatureScheme, parsedUserSignature.publicKey).toBase64(),
};
}
else {
data = {
signature: Buffer.from(parsedSignature.signature).toString("hex") +
library_sui_1.SIGNER_TYPES.UI_ED25519,
publicKey: (0, verify_1.publicKeyFromRawBytes)(parsedSignature.signatureScheme, parsedSignature.publicKey).toBase64(),
};
}
return data;
};
this.signOrder = (orderToSign) => __awaiter(this, void 0, void 0, function* () {
let signature;
if (this.uiWallet) {
signature = yield library_sui_1.OrderSigner.signOrderUsingWallet(orderToSign, this.uiWallet);
}
else if (this.isZkLogin) {
signature = yield library_sui_1.OrderSigner.signOrderUsingZkSignature({
order: orderToSign,
signer: this.signer,
zkPayload: this.getZkPayload(),
});
}
else {
if (this.orderSigner.signOrder)
signature = yield this.orderSigner.signOrder(orderToSign);
else
throw Error("On of OrderSigner or uiWallet needs to be initialized before signing order ");
}
return signature;
});
/**
* @description
* Gets a signed order from the client
* @returns OrderSignatureResponse
* @param order OrderSignatureRequest
* */
this.createSignedOrder = (order, parentAddress) => __awaiter(this, void 0, void 0, function* () {
if (!this.orderSigner && !this.uiWallet && !this.isZkLogin) {
throw Error("Order Signer not initialized");
}
const orderToSign = this.createOrderToSign(order, parentAddress);
let signature;
try {
signature = yield this.signOrder(orderToSign);
}
catch (e) {
throw Error("Failed to Sign Order: User Rejected Signature");
}
const signedOrder = {
symbol: order.symbol,
price: order.price,
quantity: order.quantity,
side: order.side,
orderType: order.orderType,
triggerPrice: order.orderType === library_sui_1.ORDER_TYPE.STOP_MARKET ||
order.orderType === library_sui_1.ORDER_TYPE.STOP_LIMIT
? order.triggerPrice || 0
: 0,
postOnly: orderToSign.postOnly,
cancelOnRevert: orderToSign.cancelOnRevert,
leverage: (0, library_sui_1.toBaseNumber)(orderToSign.leverage),
reduceOnly: orderToSign.reduceOnly,
salt: Number(orderToSign.salt),
expiration: Number(orderToSign.expiration),
maker: orderToSign.maker,
orderSignature: `${signature === null || signature === void 0 ? void 0 : signature.signature}${(signature === null || signature === void 0 ? void 0 : signature.publicAddress)
? signature === null || signature === void 0 ? void 0 : signature.publicAddress
: signature === null || signature === void 0 ? void 0 : signature.publicKey}`,
orderbookOnly: orderToSign.orderbookOnly,
timeInForce: order.timeInForce || library_sui_1.TIME_IN_FORCE.GOOD_TILL_TIME,
};
return signedOrder;
});
/**
* @description
* Places a signed order on bluefin exchange
* @param params PlaceOrderRequest containing the signed order created using createSignedOrder
* @returns PlaceOrderResponse containing status and data. If status is not 201, order placement failed.
*/
this.placeSignedOrder = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.post(apiUrls_1.SERVICE_URLS.ORDERS.ORDERS, {
symbol: params.symbol,
userAddress: params.maker,
orderType: params.orderType,
price: (0, library_sui_1.toBigNumberStr)(params.price),
triggerPrice: (0, library_sui_1.toBigNumberStr)(params.triggerPrice || "0", constants_1.POST_ORDER_BASE),
quantity: (0, library_sui_1.toBigNumberStr)(params.quantity),
leverage: (0, library_sui_1.toBigNumberStr)(params.leverage),
side: params.side,
reduceOnly: params.reduceOnly,
salt: params.salt,
expiration: params.expiration,
orderSignature: params.orderSignature,
timeInForce: params.timeInForce || library_sui_1.TIME_IN_FORCE.GOOD_TILL_TIME,
orderbookOnly: true,
postOnly: params.postOnly == true,
cancelOnRevert: params.cancelOnRevert == true,
clientId: params.clientId
? `bluefin-client: ${params.clientId}`
: "bluefin-client",
}, { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Given an order payload, signs it on chain and submits to exchange for placement
* @param params PostOrderRequest
* @returns PlaceOrderResponse
*/
this.postOrder = (params) => __awaiter(this, void 0, void 0, function* () {
const signedOrder = yield this.createSignedOrder(params, params.parentAddress);
const response = yield this.placeSignedOrder(Object.assign(Object.assign({}, signedOrder), { timeInForce: params.timeInForce, postOnly: params.postOnly == true, cancelOnRevert: params.cancelOnRevert == true, clientId: params.clientId, orderbookOnly: true }));
return response;
});
/**
* @description
* Creates signature for cancelling orders
* @param params OrderCancelSignatureRequest containing market symbol and order hashes to be cancelled
* @returns generated signature string
*/
this.createOrderCancellationSignature = (params) => __awaiter(this, void 0, void 0, function* () {
// TODO: serialize correctly, this is the default method from suiet wallet docs
// const serialized = new TextEncoder().encode(JSON.stringify(params));
// return this.signer.signData(serialized);
try {
let signature;
//taking the hash of list of hashes of cancel signature
const hashOfHash = Buffer.from((0, sha256_1.sha256)(JSON.stringify(params.hashes))).toString("hex");
let payloadValue = [];
payloadValue.push(hashOfHash);
if (this.uiWallet) {
//connected via UI
signature = yield library_sui_1.OrderSigner.signPayloadUsingWallet({ orderHashes: payloadValue }, this.uiWallet);
}
else if (this.isZkLogin) {
signature = yield library_sui_1.OrderSigner.signPayloadUsingZKSignature({
payload: { orderHashes: payloadValue },
signer: this.signer,
zkPayload: {
decodedJWT: this.decodedJWT,
proof: this.proof,
salt: this.salt,
maxEpoch: this.maxEpoch,
},
});
}
else {
signature = yield this.orderSigner.signPayload({
orderHashes: payloadValue,
});
}
return `${signature === null || signature === void 0 ? void 0 : signature.signature}${(signature === null || signature === void 0 ? void 0 : signature.publicAddress)
? signature === null || signature === void 0 ? void 0 : signature.publicAddress
: signature === null || signature === void 0 ? void 0 : signature.publicKey}`;
}
catch (_c) {
throw Error("Signing cancelled by user");
}
});
/**
* @description
* Posts to exchange for cancellation of provided orders with signature
* @param params OrderCancellationRequest containing order hashes to be cancelled and cancellation signature
* @returns response from exchange server
*/
this.placeCancelOrder = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.delete(apiUrls_1.SERVICE_URLS.ORDERS.ORDERS_HASH_V2, {
symbol: params.symbol,
orderHashes: params.hashes,
cancelSignature: params.signature,
parentAddress: params.parentAddress,
fromUI: true,
}, { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Creates signature and posts order for cancellation on exchange of provided orders
* @param params OrderCancelSignatureRequest containing order hashes to be cancelled
* @returns response from exchange server
*/
this.postCancelOrder = (params) => __awaiter(this, void 0, void 0, function* () {
if (params.hashes.length <= 0) {
throw Error(`No orders to cancel`);
}
const signature = yield this.createOrderCancellationSignature(params);
const response = yield this.placeCancelOrder(Object.assign(Object.assign({}, params), { signature: signature }));
return response;
});
/**
* @description
* Cancels all open orders for a given market
* @param symbol DOT-PERP, market symbol
* @returns cancellation response
*/
this.cancelAllOpenOrders = (symbol, parentAddress) => __awaiter(this, void 0, void 0, function* () {
var _d;
const openOrders = yield this.getUserOrders({
symbol,
statuses: [
library_sui_1.ORDER_STATUS.OPEN,
library_sui_1.ORDER_STATUS.PARTIAL_FILLED,
library_sui_1.ORDER_STATUS.PENDING,
],
parentAddress,
});
const hashes = (_d = openOrders.data) === null || _d === void 0 ? void 0 : _d.map((order) => order.hash);
const response = yield this.postCancelOrder({
hashes,
symbol,
parentAddress,
});
return response;
});
/**
* @description
* Returns the USDC balance of user in USDC contract
* @returns list of User's coins in USDC contract
*/
this.getUSDCCoins = (amount, limit, cursor) => __awaiter(this, void 0, void 0, function* () {
if (amount) {
const coin = yield this.contractCalls.onChainCalls.getUSDCoinHavingBalance({
amount,
address: this.walletAddress,
currencyID: this.contractCalls.onChainCalls.getCurrencyID(),
limit,
cursor,
});
if (coin) {
coin.balance = (0, library_sui_1.usdcToBaseNumber)(coin.balance);
}
return coin;
}
const coins = yield this.contractCalls.onChainCalls.getUSDCCoins({
address: yield this.signer.toSuiAddress(),
});
coins.data.forEach((coin) => {
coin.balance = (0, library_sui_1.usdcToBaseNumber)(coin.balance);
});
return coins;
});
/**
* @description
* Returns the usdc Balance(Free Collateral) of the account in Margin Bank contract
* @param contract (optional) address of Margin Bank contract
* @returns Number representing balance of user in Margin Bank contract
*/
this.getMarginBankBalance = () => __awaiter(this, void 0, void 0, function* () {
return this.contractCalls.getMarginBankBalance();
});
/**
* @description
* Returns the usdc Balance(Free Collateral) of the account in USDC contract
* @returns Number representing balance of user in USDC contract
*/
this.getUSDCBalance = () => __awaiter(this, void 0, void 0, function* () {
return this.contractCalls.onChainCalls.getUSDCBalance({
address: this.walletAddress,
currencyID: this.contractCalls.onChainCalls.getCurrencyID(),
}, this.signer);
});
/**
* @description
* fetch user sui balance
* @param walletAddress wallet address of the user
* @returns string
* */
this.getSUIBalance = (walletAddress) => __awaiter(this, void 0, void 0, function* () {
return this.contractCalls.getSUIBalance(walletAddress);
});
/**
* @description
* Faucet function, mints 10K USDC to wallet - Only works on Testnet
* Assumes that the user wallet has native gas Tokens on Testnet
* @returns Boolean true if user is funded, false otherwise
*/
this.mintTestUSDC = (amount) => __awaiter(this, void 0, void 0, function* () {
if (this.network === constants_1.Networks.PRODUCTION_SUI) {
throw Error(`Function does not work on PRODUCTION`);
}
// mint 10000 USDC
const mintAmount = amount || 10000;
const txResponse = yield this.contractCalls.onChainCalls.mintUSDC({
amount: (0, library_sui_1.toBigNumberStr)(mintAmount, this.MarginTokenPrecision),
to: yield this.signer.toSuiAddress(),
gasBudget: 1000000000,
});
if (library_sui_1.Transaction.getStatus(txResponse) === "success") {
return true;
}
return false;
});
/**
* @description
* Updates user's leverage to given leverage
* @param symbol market symbol get information about
* @param leverage new leverage you want to change to
* @returns ResponseSchema
*/
this.adjustLeverage = (params) => __awaiter(this, void 0, void 0, function* () {
const userPosition = yield this.getUserPosition({
symbol: params.symbol,
parentAddress: params.parentAddress,
});
if (!userPosition.data) {
throw Error(`User positions data doesn't exist`);
}
const position = userPosition.data;
if (Object.keys(position).length > 0) {
//When not connected via UI
if (!this.uiWallet && !this.isZkLogin) {
const signedTx = yield this.contractCalls.adjustLeverageContractCallRawTransaction(params.leverage, params.symbol, this.getPublicAddress, params.parentAddress);
const { ok, data, response: { errorCode, message }, } = yield this.updateLeverage({
symbol: params.symbol,
leverage: params.leverage,
parentAddress: params.parentAddress,
signedTransaction: signedTx,
});
const response = { ok, data, code: errorCode, message };
//If API is successful return response else make direct contract call to update the leverage
if (response.ok) {
return response;
}
}
return yield this.contractCalls.adjustLeverageContractCall(params.leverage, params.symbol, params.parentAddress);
}
const { ok, data, response: { errorCode, message }, } = yield this.updateLeverage({
symbol: params.symbol,
leverage: params.leverage,
parentAddress: params.parentAddress,
});
const response = { ok, data, code: errorCode, message };
return response;
});
/**
* @description
* Whitelist subaccount and/or remove the already exists subaccounts for One Click Trading
* @param subAccountAddress
* @param accountsToRemove (optional)
* @returns ResponseSchema
*/
this.upsertSubAccount = (params) => __awaiter(this, void 0, void 0, function* () {
var _e, _f;
try {
const apiResponse = yield this.getExpiredAccountsFor1CT();
const signedTx = yield this.contractCalls.upsertSubAccountContractCallRawTransaction(params.subAccountAddress, (_f = (_e = apiResponse === null || apiResponse === void 0 ? void 0 : apiResponse.data) === null || _e === void 0 ? void 0 : _e.expiredSubAccounts) !== null && _f !== void 0 ? _f : []);
const request = {
subAccountAddress: params.subAccountAddress,
accountsToRemove: params.accountsToRemove,
signedTransaction: signedTx,
};
const { ok, data, response: { errorCode, message }, } = yield this.addSubAccountFor1CT(request);
const response = { ok, data, code: errorCode, message };
return response;
}
catch (error) {
throw new Error(error.message);
}
});
/**
* @description
* Add or remove margin from the open position
* @param symbol market symbol of the open position
* @param operationType operation you want to perform `Add` | `Remove` margin
* @param amount (number) amount user wants to add or remove from the position
* @returns ResponseSchema
*/
this.adjustMargin = (symbol, operationType, amount) => __awaiter(this, void 0, void 0, function* () {
return this.contractCalls.adjustMarginContractCall(symbol, operationType, amount);
});
/**
* @description
* Deposits USDC to Margin Bank contract
* @param amount amount of USDC to deposit
* @param coinID coinID of USDC coin to use
* @returns ResponseSchema
*/
this.depositToMarginBank = (amount, coinID) => __awaiter(this, void 0, void 0, function* () {
var _g, _h;
if (!amount)
throw Error(`No amount specified for deposit`);
//if CoinID provided
if (coinID)
return this.contractCalls.depositToMarginBankContractCall(amount, coinID, this.getPublicAddress);
// Check for a single coin containing enough balance
const coinHavingBalance = (_g = (yield this.contractCalls.onChainCalls.getUSDCoinHavingBalance({
amount,
address: this.walletAddress,
}, this.signer))) === null || _g === void 0 ? void 0 : _g.coinObjectId;
if (coinHavingBalance) {
return this.contractCalls.depositToMarginBankContractCall(amount, coinHavingBalance, this.getPublicAddress);
}
// Try merging users' coins if they have more than one coins
const usdcCoins = yield this.contractCalls.onChainCalls.getUSDCCoins({ address: this.walletAddress }, this.signer);
if (usdcCoins.data.length > 1) {
yield this.contractCalls.onChainCalls.mergeAllUsdcCoins(this.contractCalls.onChainCalls.getCoinType(), this.signer, this.walletAddress);
let coinHavingBalanceAfterMerge, retries = 5;
while (!coinHavingBalanceAfterMerge && retries--) {
//sleep for 1 second to merge the coins
yield new Promise((resolve) => setTimeout(resolve, 1000));
coinHavingBalanceAfterMerge = (_h = (yield this.contractCalls.onChainCalls.getUSDCoinHavingBalance({
amount,
address: this.walletAddress,
}, this.signer))) === null || _h === void 0 ? void 0 : _h.coinObjectId;
}
if (coinHavingBalanceAfterMerge) {
return this.contractCalls.depositToMarginBankContractCall(amount, coinHavingBalanceAfterMerge, this.getPublicAddress);
}
}
throw Error(`User has no coin with amount ${amount} to deposit`);
});
/**
* @description
* withdraws USDC from Margin Bank contract
* @param amount amount of USDC to withdraw
* @returns ResponseSchema
*/
this.withdrawFromMarginBank = (amount) => __awaiter(this, void 0, void 0, function* () {
if (amount) {
return this.contractCalls.withdrawFromMarginBankContractCall(amount);
}
return this.contractCalls.withdrawAllFromMarginBankContractCall();
});
/**
* @description
* Sets subaccount to wallet.
* @param publicAddress the address to add as sub account
* @param status true to add, false to remove
* @returns ResponseSchema
*/
this.setSubAccount = (publicAddress, status) => __awaiter(this, void 0, void 0, function* () {
return this.contractCalls.setSubAccount(publicAddress, status);
});
/**
* @description
* Gets Users default leverage.
* @param symbol market symbol get information about
* @returns user default leverage
*/
this.getUserDefaultLeverage = (symbol, parentAddress) => __awaiter(this, void 0, void 0, function* () {
const accData = yield this.getUserAccountData(parentAddress);
if (!accData.data) {
throw Error(`Account data does not exist`);
}
const accDataByMarket = accData.data.accountDataByMarket.filter((data) => {
return data.symbol === symbol;
});
/// found accountDataByMarket
if (accDataByMarket && accDataByMarket.length > 0) {
return (0, library_sui_1.toBaseNumber)(accDataByMarket[0].selectedLeverage);
}
/// user is new and symbol data is not present in accountDataByMarket
const exchangeInfo = yield this.getExchangeInfo(symbol);
if (!exchangeInfo.data) {
throw Error(`Provided Market Symbol(${symbol}) does not exist`);
}
return (0, library_sui_1.toBaseNumber)(exchangeInfo.data.defaultLeverage);
});
/**
* @description
* Gets Orders placed by the user. Returns the first 50 orders by default.
* @param params of type OrderRequest,
* @returns OrderResponse array
*/
this.getUserOrders = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.ORDERS, Object.assign({}, params), { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets user open position. If the market is not specified then will return first 50 open positions for 50 markets.
* @param params GetPositionRequest
* @returns GetPositionResponse
*/
this.getUserPosition = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.USER_POSITIONS, Object.assign({}, params), { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets state of orderbook for provided market. At max top 50 bids/asks are retrievable
* @param params GetOrderbookRequest
* @returns GetOrderbookResponse
*/
this.getOrderbook = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.ORDER_BOOK, params);
return response;
});
/**
* @description
* Gets user trades
* @param params GetUserTradesRequest
* @returns GetUserTradesResponse
*/
this.getUserTrades = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.USER_TRADES, Object.assign({}, params), { isAuthenticationRequired: true });
return response;
});
/**
* Gets user trades history
* @param params GetUserTradesHistoryRequest
* @returns GetUserTradesHistoryResponse
*/
this.getUserTradesHistory = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.USER_TRADES_HISTORY, Object.assign({}, params), { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets user Account Data
* @returns GetAccountDataResponse
*/
this.getUserAccountData = (parentAddress) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.ACCOUNT, { parentAddress }, { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets verification status of user account
* @param amount deposit amount
* @returns verification status of user
*/
this.verifyDeposit = (amount) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.VERIFY_DEPOSIT, { depositAmount: amount }, { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets user transaction history
* @param params GetTransactionHistoryRequest
* @returns GetUserTransactionHistoryResponse
*/
this.getUserTransactionHistory = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.USER_TRANSACTION_HISTORY, Object.assign({}, params), { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets user funding history
* @param params GetFundingHistoryRequest
* @returns GetUserTransactionHistoryResponse
*/
this.getUserFundingHistory = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.FUNDING_HISTORY, Object.assign({}, params), { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets user transfer history
* @param params GetTransferHistoryRequest
* @returns GetUserTransferHistoryResponse
*/
this.getUserTransferHistory = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.USER.TRANSFER_HISTORY, Object.assign({}, params), { isAuthenticationRequired: true });
return response;
});
/**
* @description
* Gets market funding rate
* @param symbol market symbol to fetch funding rate of
* @returns GetFundingRateResponse
*/
this.getMarketFundingRate = (symbol) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.FUNDING_RATE, {
symbol,
});
return response;
});
/**
* @description
* Gets market recent trades
* @param params GetMarketRecentTradesRequest
* @returns GetMarketRecentTradesResponse
*/
this.getMarketRecentTrades = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.RECENT_TRADE, params);
return response;
});
/**
* @description
* Gets market candle stick data
* @param params GetMarketRecentTradesRequest
* @returns DAPIKlineResponse
*/
this.getMarketCandleStickData = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.CANDLE_STICK_DATA, params);
return response;
});
/**
* @description
* Gets publicly available market info about market(s)
* @param symbol (optional) market symbol get information about, by default fetches info on all available markets
* @returns ExchangeInfo or ExchangeInfo[] in case no market was provided as input
*/
this.getExchangeInfo = (symbol) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.EXCHANGE_INFO, { symbol });
return response;
});
/**
* @description
* Gets MarketData data for market(s)
* @param symbol (optional) market symbol get information about, by default fetches info on all available markets
* @returns MarketData or MarketData[] in case no market was provided as input
*/
this.getMarketData = (symbol) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.MARKET_DATA, { symbol });
return response;
});
/**
* @description
* Gets Meta data of the market(s)
* @param symbol (optional) market symbol get information about, by default fetches info on all available markets
* @returns MarketMeta or MarketMeta[] in case no market was provided as input
*/
this.getMarketMetaInfo = (symbol) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.META, { symbol });
return response;
});
/**
* @description
* Gets Master Info of the market(s)
* @param symbol (optional) market symbol get information about, by default fetches info on all available markets
* @returns MasterInfo
*/
this.getMasterInfo = (symbol) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.MASTER_INFO, { symbol });
return response;
});
/**
* @description
* Gets the list of market symbols available on exchange
* @returns array of strings representing MARKET SYMBOLS
*/
this.getMarketSymbols = () => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.SYMBOLS);
return response;
});
/**
* @description
* Gets contract addresses of market
* @param symbol (optional) market symbol get information about, by default fetches info on all available markets
* @returns deployed contract addresses
*/
this.getContractAddresses = (symbol) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.CONTRACT_ADDRESSES, { symbol });
return response;
});
/**
* @description
* Gets status of the exchange
* @returns StatusResponse
*/
this.getExchangeStatus = () => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.STATUS);
return response;
});
/**
* @description
* Gets ticker data of any market
* @param symbol market symbol to get information about, if not provided fetches data of all markets
* @returns TickerData
*/
this.getTickerData = (symbol) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.MARKET.TICKER, { symbol });
return response;
});
/**
* Generates referral code
* @param params GenerateReferralCodeRequest
* @returns GenerateReferralCodeResponse
*/
this.generateReferralCode = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.post(apiUrls_1.SERVICE_URLS.GROWTH.GENERATE_CODE, params, { isAuthenticationRequired: true });
return response;
});
/**
* Links referred user
* @param params LinkReferredUserRequest
* @returns LinkReferredUserResponse
*/
this.affiliateLinkReferredUser = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.post(apiUrls_1.SERVICE_URLS.GROWTH.AFFILIATE_LINK_REFERRED_USER, params, { isAuthenticationRequired: true });
return response;
});
/**
* Gets referrer Info
* @param parentAddress
* @returns GetReferrerInfoResponse
*/
this.getReferrerInfo = (parentAddress) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.REFERRER_INFO, { parentAddress }, { isAuthenticationRequired: true });
return response;
});
/**
* Gets campaign details
* @returns Array of GetCampaignDetailsResponse
*/
this.getCampaignDetails = () => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.CAMPAIGN_DETAILS);
return response;
});
/**
* Gets campaign reward details
* @param campaignId
* @param parentAddress
* @returns GetCampaignRewardsResponse
*/
this.getCampaignRewards = (campaignId, parentAddress) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.CAMPAIGN_REWARDS, { campaignId, parentAddress }, { isAuthenticationRequired: true });
return response;
});
/**
* Gets affiliate payout details
* @param campaignId
* @param parentAddress
* @returns Array of GetAffiliatePayoutsResponse
*/
this.getAffiliatePayouts = (campaignId, parentAddress) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.AFFILIATE_PAYOUTS, { campaignId, parentAddress }, { isAuthenticationRequired: true });
return response;
});
/**
* Gets affiliate referree details
* @param GetAffiliateRefereeDetailsRequest
* @returns GetAffiliateRefereeDetailsResponse
*/
this.getAffiliateRefereeDetails = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.AFFILIATE_REFEREE_DETAILS, params, { isAuthenticationRequired: true });
return response;
});
/**
* Gets referree count
* @param campaignId
* @param parentAddress
* @returns GetAffiliateRefereeCountResponse
*/
this.getAffiliateRefereeCount = (campaignId, parentAddress) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.AFFILIATE_REFEREES_COUNT, { campaignId, parentAddress }, { isAuthenticationRequired: true });
return response;
});
/**
* Gets user rewards history
* @param optional params GetUserRewardsHistoryRequest
* @returns GetUserRewardsHistoryResponse
*/
this.getUserRewardsHistory = (params) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.USER_REWARDS_HISTORY, params, { isAuthenticationRequired: true });
return response;
});
/**
* Gets user rewards summary
* @returns GetUserRewardsSummaryResponse
*/
this.getUserRewardsSummary = (parentAddress) => __awaiter(this, void 0, void 0, function* () {
const response = yield this.apiService.get(apiUrls_1.SERVICE_URLS.GROWTH.USER_REWARDS_SUMMARY, { parentAddress }, { isAuthenticationRequired: true });
return response;
});
/**
* Gets rewards o