UNPKG

@firefly-exchange/library-sui

Version:

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

344 lines (343 loc) 14.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.OnChainCalls = void 0; const utils_1 = require("@mysten/sui/utils"); const classes_1 = require("../classes"); const library_1 = require("../library"); const clmm_1 = require("../spot/clmm"); const types_1 = require("../types"); class OnChainCalls { constructor(_suiClient, _contracts, options) { this.suiClient = _suiClient; this.contracts = _contracts; this.spotContracts = options?.spotContracts; this.signerConfig = { signer: options?.signer, address: options?.address || options?.signer?.toSuiAddress(), isUIWallet: options?.isUIWallet == true }; } /** * Returns the vaults of provided name * @param name Name of the vault(s) to look for * @returns Array of vaults */ getVaultByName(name) { return this.contracts.Vaults.filter(vault => vault.name == name); } /** * Fetches the state of vault from chain * @param id * @returns */ async getVaultFromChain(id) { const vault = await this.suiClient.getObject({ id, options: { showContent: true } }); const fields = (vault.data?.content).fields; delete fields.id; fields.id = id; return fields; } /** * Returns all positions opened using the funds of provided vault * @param vault The id of the vault * @returns array of positions */ async getVaultPositions(vault) { const dynamicFieldObject = await this.suiClient.getDynamicFieldObject({ parentId: vault, name: { type: "0x1::string::String", value: "positions" } }); const vector = (dynamicFieldObject.data?.content).fields.value; return vector.map(v => { return { owner: vault, pool_id: v.fields.pool_id, position_id: v.fields.id.id, lower_tick: Number((0, clmm_1.asIntN)(BigInt(v.fields.lower_tick.fields.bits)).toString()), upper_tick: Number((0, clmm_1.asIntN)(BigInt(v.fields.upper_tick.fields.bits)).toString()), liquidity: Number(v.fields.liquidity), fee_growth_coin_a: Number(v.fields.fee_growth_coin_a), fee_growth_coin_b: Number(v.fields.fee_growth_coin_b), fee_rate: Number(v.fields.fee_rate), token_a_fee: Number(v.fields.token_a_fee), token_b_fee: Number(v.fields.token_b_fee) }; }); } /** * Returns the current available reserves of each token that vault holds * @param vault The id of the vault * @returns Array of coin reserves */ async getVaultReserves(vault) { let cursor = undefined; let hasNextPage = true; let dynamicFields = []; while (hasNextPage) { const resp = await this.suiClient.getDynamicFields({ parentId: vault }); hasNextPage = resp.hasNextPage; cursor = resp.nextCursor; dynamicFields = dynamicFields.concat(resp.data); } const reserves = await Promise.all(dynamicFields .filter(df => df.name.value != "positions") .map(async (df) => { const dynamicFieldObject = await this.suiClient.getDynamicFieldObject({ parentId: vault, name: df.name }); const fields = (dynamicFieldObject.data?.content).fields; return { id: fields.id.id, coinType: fields.name, value: Number(fields.value) }; })); return reserves; } /** * @notice Allows caller to create a vault. Any one is allowed to create a vault. * @param args CreateVaultArgs * @param options: OnChain params call * Returns OnChainCallResponse */ async createVault(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(this.contracts.ProtocolConfig), txBlock.object(this.contracts.VaultStore), txBlock.pure.address(args.manager || this.signerConfig.address), txBlock.pure.string(args.name), txBlock.pure.u8(args.type || 1), txBlock.pure.vector("address", args.users || []) ], target: `${this.contracts.CurrentPackage}::vault::create_vault` }); return this.setAndExecute(txBlock, options); } /** * @notice Allows caller to deposit funds into the vault for its users to use * @param args FundVaultArgs * @param options: OnChain params call * Returns OnChainCallResponse */ async provideFunds(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); // create coin of provided balance const [splitCoin, mergeCoin] = await classes_1.CoinUtils.createCoinWithBalance(this.suiClient, txBlock, args.amount, args.coinType, this.signerConfig.address); txBlock.moveCall({ arguments: [ txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.object(splitCoin) ], target: `${this.contracts.CurrentPackage}::vault::provide_funds`, typeArguments: [args.coinType] }); if (mergeCoin) { txBlock.transferObjects([mergeCoin], this.signerConfig.address); } return this.setAndExecute(txBlock, options); } /** * @notice Allows vault manager to withdraw funds from the vault * @param args WithdrawFundArgs * @param options: OnChain params call * Returns OnChainCallResponse */ async withdrawFunds(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.pure.u64((0, library_1.bigNumber)(args.amount).toFixed(0)) ], target: `${this.contracts.CurrentPackage}::vault::withdraw_funds`, typeArguments: [args.coinType] }); return this.setAndExecute(txBlock, options); } /** * @notice Allows vault manager to add/whitelist or remove/blacklist users from the vault * @param args UpdateUsersArgs * @param options: OnChain params call * Returns OnChainCallResponse */ async updateUsers(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.pure.vector("address", args.users) ], target: `${this.contracts.CurrentPackage}::vault::${args.add ? "add_users" : "remove_users"}` }); return this.setAndExecute(txBlock, options); } /** * Allows caller to open a position for the provided pool for given ticks * using the specified vault funds * @param args OpenPositionArgs * @param options IOnChainCallOptionalParams * @returns Onchain call response */ async openPosition(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.object(this.spotContracts.GlobalConfig), txBlock.object(args.pool.id), txBlock.pure.u32(args.lowerTickBits), txBlock.pure.u32(args.upperTickBits) ], target: `${this.contracts.CurrentPackage}::spot::open_position`, typeArguments: [args.pool.coin_a.address, args.pool.coin_b.address] }); return this.setAndExecute(txBlock, options); } /** * Allows caller to provide liquidity to a position opened using the vault on bluefin spot protocol * @param args Provide liquidity arguments * @param options IOnChainCallOptionalParams * @returns Onchain call response */ async provideLiquidity(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(utils_1.SUI_CLOCK_OBJECT_ID), txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.object(this.spotContracts.GlobalConfig), txBlock.object(args.pool.id), txBlock.pure.id(args.position), txBlock.pure.u64((0, library_1.bigNumber)(args.amount).toFixed(0)), txBlock.pure.u64((0, library_1.bigNumber)(args.coinAMax).toFixed(0)), txBlock.pure.u64((0, library_1.bigNumber)(args.coinBMax).toFixed(0)), txBlock.pure.bool(args.isFixedA) ], target: `${this.contracts.CurrentPackage}::spot::provide_liquidity_with_fixed_amount`, typeArguments: [args.pool.coin_a.address, args.pool.coin_b.address] }); return this.setAndExecute(txBlock, options); } /** * Allows caller to remove liquidity from a position opened using the vault on bluefin spot protocol * @param args Remove liquidity arguments * @param options IOnChainCallOptionalParams * @returns Onchain call response */ async removeLiquidity(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(utils_1.SUI_CLOCK_OBJECT_ID), txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.object(this.spotContracts.GlobalConfig), txBlock.object(args.pool.id), txBlock.pure.id(args.position), txBlock.pure.u128((0, library_1.bigNumber)(args.liquidity).toFixed(0)), txBlock.pure.u64((0, library_1.bigNumber)(args.coinAMin).toFixed(0)), txBlock.pure.u64((0, library_1.bigNumber)(args.coinBMin).toFixed(0)) ], target: `${this.contracts.CurrentPackage}::spot::remove_liquidity`, typeArguments: [args.pool.coin_a.address, args.pool.coin_b.address] }); return this.setAndExecute(txBlock, options); } /** * Allows caller to collect any fee accrued in the position opened on bluefin spot pools using vault funds * @param args Collect Fee Arguments * @param options IOnChainCallOptionalParams * @returns Onchain call response */ async collectFee(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(utils_1.SUI_CLOCK_OBJECT_ID), txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.object(this.spotContracts.GlobalConfig), txBlock.object(args.pool.id), txBlock.pure.id(args.position), txBlock.pure.address(args.destination) ], target: `${this.contracts.CurrentPackage}::spot::collect_fee`, typeArguments: [args.pool.coin_a.address, args.pool.coin_b.address] }); return this.setAndExecute(txBlock, options); } /** * Allows caller to collect the rewards accrued of given coin type on a position opened on bluefin spot pools * @param args Collect Reward Arguments * @param options IOnChainCallOptionalParams * @returns Onchain call response */ async collectReward(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(utils_1.SUI_CLOCK_OBJECT_ID), txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.object(this.spotContracts.GlobalConfig), txBlock.object(args.pool.id), txBlock.pure.id(args.position), txBlock.pure.address(args.destination) ], target: `${this.contracts.CurrentPackage}::spot::collect_reward`, typeArguments: [ args.pool.coin_a.address, args.pool.coin_b.address, args.rewardCoinType ] }); return this.setAndExecute(txBlock, options); } /** * Allows caller to close a position on bluefin spot protocol * @param args Close Position Arguments * @param options IOnChainCallOptionalParams * @returns Onchain call response */ async closePosition(args, options) { const txBlock = options?.txb || new types_1.TransactionBlock(); txBlock.moveCall({ arguments: [ txBlock.object(utils_1.SUI_CLOCK_OBJECT_ID), txBlock.object(this.contracts.ProtocolConfig), txBlock.object(args.vault), txBlock.object(this.spotContracts.GlobalConfig), txBlock.object(args.pool.id), txBlock.pure.id(args.position), txBlock.pure.address(args.destination) ], target: `${this.contracts.CurrentPackage}::spot::close_position`, typeArguments: [args.pool.coin_a.address, args.pool.coin_b.address] }); return this.setAndExecute(txBlock, options); } async setAndExecute(txBlock, options) { if (options?.gasBudget) txBlock.setGasBudget(options.gasBudget); if (options?.sender) txBlock.setSenderIfNotSet(options.sender); return classes_1.SuiBlocks.execCall(txBlock, this.suiClient, this.signerConfig.signer, options?.dryRun, this.signerConfig.isUIWallet); } } exports.OnChainCalls = OnChainCalls;