@firefly-exchange/library-sui
Version:
Sui library housing helper methods, classes to interact with Bluefin protocol(s) deployed on Sui
165 lines (164 loc) • 6.94 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const bcs_1 = require("@mysten/bcs");
const constants_1 = require("../../constants");
const library_1 = require("../../library");
const types_1 = require("../../types");
class Account {
/**
* Fetches the account details from on-chain from provided internal data store
* @param suiClient Sui Client
* @param storeID The id/address of the internal store
* @param account The address of user to be fetched
* @returns
*/
static async getAccount(suiClient, storeID, account) {
const objDetails = await suiClient.getObject({
id: storeID,
options: { showContent: true }
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const userTable = objDetails.data.content.fields.accounts.fields.id.id;
try {
const userData = await suiClient.getDynamicFieldObject({
parentId: userTable,
name: {
type: "address",
value: account
}
});
// parse the account
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const fields = userData.data.content.fields.value.fields;
return {
address: fields.address,
assets: fields.assets.map(asset => asset.fields),
crossPositions: fields.cross_positions.map(position => Account.mapPosition(position.fields)),
isolatedPositions: fields.isolated_positions.map(position => Account.mapPosition(position.fields)),
authorized: fields.authorized
};
}
catch (e) {
return {
address: account,
assets: [],
crossPositions: [],
isolatedPositions: [],
authorized: []
};
}
}
/**
* Fetches the user assets from on-chain from provided internal data store
* @param suiClient Sui Client
* @param storeID The id/address of the internal store
* @param account The address of user to be fetched
* @returns Array of Deposited Assets
*/
static async getAccountAssets(suiClient, storeID, account) {
const data = await Account.getAccount(suiClient, storeID, account);
return data.assets;
}
/**
* Fetches the user margin from on-chain from provided internal data store
* @param suiClient Sui Client
* @param storeID The id/address of the internal store
* @param account The address of user to be fetched
* @returns The margin of the account in base number
*/
static async getAccountMargin(suiClient, storeID, account) {
const data = await Account.getAccount(suiClient, storeID, account);
return data.assets.length > 0
? (0, library_1.toBaseNumber)(data.assets[0].quantity, constants_1.USDC_BASE_DECIMALS, constants_1.SUI_NATIVE_BASE)
: 0;
}
/**
* Returns the margin user has available for withdrawal on-chain
* @param suiClient Sui Client
* @param parser The deployment config parser
* @param account The account address for which to query withdrawable balance
* @param asset The name of the asset that is to be queried
* @returns The user available margin for withdraw in base number
*/
static async getWithdrawableAssets(suiClient, parser, account, asset) {
const txb = new types_1.TransactionBlock();
txb.moveCall({
arguments: [
txb.object(parser.getInternalDataStore()),
txb.pure.address(account),
txb.pure.string(asset)
],
target: `${parser.getPackageId()}::margining_engine::get_withdrawable_assets`
});
try {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const [availableMargin] = (await suiClient.devInspectTransactionBlock({
sender: account,
transactionBlock: txb
// eslint-disable-next-line @typescript-eslint/no-unused-vars
})).results[0].returnValues.map(([bytes, _]) => (0, library_1.bigNumber)(bcs_1.bcs.u64().parse(Uint8Array.from(bytes))));
return (0, library_1.toBaseNumber)(availableMargin, 3, constants_1.SUI_NATIVE_BASE);
}
catch (e) {
return 0;
}
}
/**
* Fetches the user positions from on-chain from provided internal data store
* @param suiClient Sui Client
* @param storeID The id/address of the internal store
* @param account The address of user to be fetched
* @returns
*/
static async getAccountCrossPositions(suiClient, storeID, account) {
const data = await Account.getAccount(suiClient, storeID, account);
return data.crossPositions;
}
/**
* Fetches the user position for provided perpetual from on-chain from provided internal data store
* @param suiClient Sui Client
* @param storeID The id/address of the internal store
* @param account The address of user to be fetched (address_1)
* @param perpetual The address of the perpetual for which to fetch the position
* @returns Position of the user on provided perp
*/
static async getAccountCrossPositionForPerpetual(suiClient, storeID, account, perpetual) {
const data = await Account.getAccount(suiClient, storeID, account);
for (const position of data.crossPositions) {
if (position.perpetual == perpetual)
return position;
}
throw `Account ${account} has not position on perpetual: ${perpetual}`;
}
/**
* Fetches the list of accounts/address that are authorized for given account
* @param suiClient Sui Client
* @param storeID The id/address of the internal store
* @param account The address of user to be fetched (address_1)
* @returns list of addresses
*/
static async getAuthorizedAccounts(suiClient, storeID, account) {
const data = await Account.getAccount(suiClient, storeID, account);
return data.authorized;
}
/**
* Method to parse the position
* @param fields the position fields
* @returns IPosition
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static mapPosition(fields) {
const position = { ...fields };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const fundingFields = position.funding.fields;
position.funding = {
timestamp: fundingFields.timestamp,
rate: {
value: fundingFields.rate.fields.value,
sign: fundingFields.rate.fields.sign
}
};
return position;
}
}
exports.default = Account;
;