UNPKG

aftermath-ts-sdk

Version:
757 lines (756 loc) 43.3 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SuiFrensApi = void 0; const transactions_1 = require("@mysten/sui/transactions"); const bcs_1 = require("@mysten/sui/bcs"); const coin_1 = require("../../coin/coin"); const helpers_1 = require("../../../general/utils/helpers"); const utils_1 = require("../../../general/utils"); const eventsApiHelpers_1 = require("../../../general/apiHelpers/eventsApiHelpers"); const sui_1 = require("../../sui/sui"); const suiFrens_1 = require("../suiFrens"); class SuiFrensApi { // ========================================================================= // Constructor // ========================================================================= constructor(Provider) { this.Provider = Provider; // ========================================================================= // Public Methods // ========================================================================= // ========================================================================= // Inspections // ========================================================================= this.fetchMixingLimitsAndLastEpochMixeds = (inputs) => __awaiter(this, void 0, void 0, function* () { const tx = new transactions_1.Transaction(); this.devInspectMixLimitAndLastEpochMixedMulTx(Object.assign(Object.assign({}, inputs), { tx })); const [mixLimitBytes, lastEpochMixedBytes] = yield this.Provider.Inspections().fetchAllBytesFromTxOutput({ tx, }); const mixLimits = bcs_1.bcs .vector(bcs_1.bcs.option(bcs_1.bcs.u8())) .parse(new Uint8Array(mixLimitBytes)); const lastEpochMixeds = bcs_1.bcs .vector(bcs_1.bcs.option(bcs_1.bcs.u64())) .parse(new Uint8Array(lastEpochMixedBytes)); return mixLimits.map((mixLimit, index) => ({ mixLimit: mixLimit === null || mixLimit === undefined ? undefined : BigInt(mixLimit), lastEpochMixed: lastEpochMixeds[index] === undefined ? undefined : BigInt(lastEpochMixeds[index]), })); }); this.fetchMixingLimit = (inputs) => __awaiter(this, void 0, void 0, function* () { // TODO: handle bullshark types more cleanly if (inputs.suiFrenType === this.objectTypes.bullshark) return undefined; const tx = new transactions_1.Transaction(); this.mixingLimitTx(Object.assign({ tx }, inputs)); const bytes = yield this.Provider.Inspections().fetchFirstBytesFromTxOutput({ tx, }); const unwrapped = bcs_1.bcs.option(bcs_1.bcs.u8()).parse(new Uint8Array(bytes)); return unwrapped === null || unwrapped === undefined ? undefined : BigInt(unwrapped); }); this.fetchLastEpochMixed = (inputs) => __awaiter(this, void 0, void 0, function* () { // TODO: handle bullshark types more cleanly if (inputs.suiFrenType === this.objectTypes.bullshark) return undefined; const tx = new transactions_1.Transaction(); this.lastEpochMixedTx(Object.assign({ tx }, inputs)); const bytes = yield this.Provider.Inspections().fetchFirstBytesFromTxOutput({ tx, }); const unwrapped = bcs_1.bcs.option(bcs_1.bcs.u64()).parse(new Uint8Array(bytes)); return unwrapped === null || unwrapped === undefined ? undefined : BigInt(unwrapped); }); this.fetchStakedSuiFrenMetadataIds = (inputs) => __awaiter(this, void 0, void 0, function* () { const { suiFrenIds } = inputs; const tx = new transactions_1.Transaction(); this.devInspectMetadataObjectIdMulTx({ tx, suiFrenIds }); const idBytes = yield this.Provider.Inspections().fetchFirstBytesFromTxOutput({ tx, }); const stakedSuiFrenMetadataIds = bcs_1.bcs .vector(bcs_1.bcs.Address) .parse(new Uint8Array(idBytes)); return stakedSuiFrenMetadataIds; }); // ========================================================================= // Events // ========================================================================= this.fetchHarvestSuiFrenFeesEvents = (inputs) => this.Provider.Events().fetchCastEventsWithCursor(Object.assign(Object.assign({}, inputs), { query: { MoveEventType: this.eventTypes.harvestSuiFrenFees, }, eventFromEventOnChain: utils_1.Casting.suiFrens.harvestSuiFrenFeesEventFromOnChain })); this.fetchMixSuiFrensEvents = (inputs) => this.Provider.Events().fetchCastEventsWithCursor(Object.assign(Object.assign({}, inputs), { query: { MoveEventType: this.eventTypes.mixSuiFrens, }, eventFromEventOnChain: utils_1.Casting.suiFrens.mixSuiFrensEventFromOnChain })); this.fetchStakeSuiFrenEvents = (inputs) => this.Provider.Events().fetchCastEventsWithCursor(Object.assign(Object.assign({}, inputs), { query: { MoveEventType: this.eventTypes.stakeSuiFren, }, eventFromEventOnChain: utils_1.Casting.suiFrens.stakeSuiFrenEventFromOnChain })); this.fetchUnstakeSuiFrenEvents = (inputs) => this.Provider.Events().fetchCastEventsWithCursor(Object.assign(Object.assign({}, inputs), { query: { MoveEventType: this.eventTypes.unstakeSuiFren, }, eventFromEventOnChain: utils_1.Casting.suiFrens.unstakeSuiFrenEventFromOnChain })); // ========================================================================= // Objects // ========================================================================= // ========================================================================= // CapyLabsApp Object // ========================================================================= this.fetchCapyLabsApp = () => __awaiter(this, void 0, void 0, function* () { return this.Provider.Objects().fetchCastObject({ objectId: this.addresses.objects.capyLabsApp, objectFromSuiObjectResponse: utils_1.Casting.suiFrens.capyLabsAppObjectFromSuiObjectResponse, }); }); this.fetchSuiFrenVaultStateV1Object = () => __awaiter(this, void 0, void 0, function* () { return this.Provider.Objects().fetchCastObject({ objectId: this.addresses.objects.suiFrensVaultStateV1, objectFromSuiObjectResponse: utils_1.Casting.suiFrens.suiFrenVaultStateV1ObjectFromSuiObjectResponse, }); }); // ========================================================================= // SuiFren Objects // ========================================================================= this.fetchSuiFrens = (inputs) => __awaiter(this, void 0, void 0, function* () { const { suiFrenIds } = inputs; const partialSuiFrens = yield this.Provider.Objects().fetchCastObjectBatch({ objectIds: suiFrenIds, objectFromSuiObjectResponse: utils_1.Casting.suiFrens.partialSuiFrenObjectFromSuiObjectResponse, options: { showDisplay: true, showType: true, showContent: true, }, }); return this.fetchCompletePartialSuiFrenObjects({ partialSuiFrens, isStaked: false, }); }); this.fetchOwnedSuiFrens = (inputs) => __awaiter(this, void 0, void 0, function* () { const { walletAddress } = inputs; const [partialSuiFrenNonBullsharks, partialSuiFrenBullsharks] = yield Promise.all([ this.Provider.Objects().fetchCastObjectsOwnedByAddressOfType({ walletAddress, objectType: this.objectTypes.suiFren, objectFromSuiObjectResponse: utils_1.Casting.suiFrens .partialSuiFrenObjectFromSuiObjectResponse, withDisplay: true, }), this.fetchOwnedPartialSuiFrenBullsharks(inputs), ]); const suiFrens = yield this.fetchCompletePartialSuiFrenObjects({ partialSuiFrens: [ ...partialSuiFrenNonBullsharks, ...partialSuiFrenBullsharks, ], isStaked: false, }); return suiFrens; }); this.fetchStakedSuiFrens = (inputs) => __awaiter(this, void 0, void 0, function* () { const { stakedSuiFrenIds } = inputs; const stakedSuiFrenData = yield this.Provider.Objects().fetchCastObjectBatch({ objectIds: stakedSuiFrenIds, objectFromSuiObjectResponse: utils_1.Casting.suiFrens .partialSuiFrenAndStakedSuiFrenMetadataV1ObjectFromSuiObjectResponse, options: { showDisplay: true, showType: true, showContent: true, }, }); const suiFrens = yield this.fetchCompletePartialSuiFrenObjects({ partialSuiFrens: stakedSuiFrenData.map((data) => data.partialSuiFren), isStaked: true, }); return suiFrens.map((suiFren, index) => ({ suiFren, metadata: stakedSuiFrenData[index].stakedSuiFrenMetadata, })); }); this.fetchStakedSuiFrensDynamicFields = (inputs) => { return this.Provider.DynamicFields().fetchCastDynamicFieldsOfTypeWithCursor(Object.assign(Object.assign({}, inputs), { parentObjectId: this.addresses.objects.suiFrensVaultStateV1MetadataTable, objectsFromObjectIds: (stakedSuiFrenIds) => this.fetchStakedSuiFrens({ stakedSuiFrenIds }), dynamicFieldType: this.objectTypes.stakedSuiFrenMetadataV1 })); }; // ========================================================================= // Accessories // ========================================================================= this.fetchAccessoriesForSuiFren = (inputs) => __awaiter(this, void 0, void 0, function* () { return yield this.Provider.DynamicFields().fetchCastAllDynamicFieldsOfType({ parentObjectId: inputs.suiFrenId, objectsFromObjectIds: (objectIds) => this.fetchAccessories({ objectIds }), dynamicFieldType: this.objectTypes.suiFrenAccessory, }); }); this.fetchOwnedAccessories = (inputs) => __awaiter(this, void 0, void 0, function* () { const { walletAddress } = inputs; return yield this.Provider.Objects().fetchCastObjectsOwnedByAddressOfType({ walletAddress, objectType: this.objectTypes.suiFrenAccessory, objectFromSuiObjectResponse: utils_1.Casting.suiFrens.accessoryObjectFromSuiObjectResponse, withDisplay: true, }); }); this.fetchAccessories = (inputs) => __awaiter(this, void 0, void 0, function* () { const { objectIds } = inputs; return this.Provider.Objects().fetchCastObjectBatch({ objectIds, objectFromSuiObjectResponse: utils_1.Casting.suiFrens.accessoryObjectFromSuiObjectResponse, options: { showDisplay: true, showType: true, showContent: true, }, }); }); // ========================================================================= // Staked SuiFren Objects // ========================================================================= // TODO: handle sorting this.fetchStakedSuiFrensDynamicFieldsWithFilters = (inputs) => __awaiter(this, void 0, void 0, function* () { var _a; const { attributes } = inputs; const defaultLimit = 25; const limit = (_a = inputs.limit) !== null && _a !== void 0 ? _a : defaultLimit; const isComplete = (data) => { return (this.filterSuiFrensWithAttributes({ suiFrens: data.map((info) => info.suiFren), attributes, }).length >= limit); }; const suiFrensWithCursor = yield this.Provider.DynamicFields().fetchDynamicFieldsUntil(Object.assign(Object.assign({}, inputs), { fetchFunc: (data) => this.fetchStakedSuiFrensDynamicFields(data), isComplete })); const filteredSuiFrens = this.filterSuiFrensWithAttributes({ suiFrens: suiFrensWithCursor.dynamicFieldObjects.map((data) => data.suiFren), attributes, }); const dynamicFieldObjects = suiFrensWithCursor.dynamicFieldObjects.filter((data) => filteredSuiFrens .slice(0, limit) .some((suiFren) => suiFren.objectId === data.suiFren.objectId)); const resizedSuiFrensWithCursor = { nextCursor: limit < filteredSuiFrens.length ? filteredSuiFrens[limit].objectId : suiFrensWithCursor.nextCursor, dynamicFieldObjects, }; return resizedSuiFrensWithCursor; }); this.fetchOwnedStakedSuiFrens = (inputs) => __awaiter(this, void 0, void 0, function* () { const { walletAddress } = inputs; const stakedPositions = yield this.Provider.Objects().fetchCastObjectsOwnedByAddressOfType({ walletAddress, objectType: this.objectTypes.stakedSuiFrenPosition, objectFromSuiObjectResponse: utils_1.Casting.suiFrens.stakedSuiFrenPositionFromSuiObjectResponse, }); const stakedSuiFrenIds = yield this.fetchStakedSuiFrenMetadataIds({ suiFrenIds: stakedPositions.map((position) => position.suiFrenId), }); const stakedSuiFrens = yield this.fetchStakedSuiFrens({ stakedSuiFrenIds, }); return stakedSuiFrens.map((data, index) => (Object.assign(Object.assign({}, data), { position: stakedPositions[index] }))); }); // ========================================================================= // Transaction Commands // ========================================================================= // ========================================================================= // Inspections // ========================================================================= this.devInspectMetadataObjectIdMulTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "dev_inspect_metadata_object_id_mul"), typeArguments: [], arguments: [ tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.pure(bcs_1.bcs.vector(bcs_1.bcs.Address).serialize(inputs.suiFrenIds)), // suifren_ids ], }); }; this.devInspectMixLimitAndLastEpochMixedMulTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVaultCapyLabsExtension, SuiFrensApi.constants.moduleNames.suiFrensVaultCapyLabsExtension .capyLabs, "dev_inspect_mixing_limit_and_last_epoch_mixed_mul"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVaultCapyLabsExtension), // SuiFrensVaultCapyLabsExt tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.pure(bcs_1.bcs.vector(bcs_1.bcs.Address).serialize(inputs.suiFrenIds)), // suifren_ids ], }); }; this.mixingLimitTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrens, SuiFrensApi.constants.moduleNames.capyLabs.capyLabs, "mixing_limit"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(inputs.suiFrenId), // SuiFren ], }); }; this.lastEpochMixedTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrens, SuiFrensApi.constants.moduleNames.capyLabs.capyLabs, "last_epoch_mixed"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(inputs.suiFrenId), // SuiFren ], }); }; // ========================================================================= // Mixing Transaction Commands // ========================================================================= this.mixAndKeepTx = (inputs) => { const { tx, suiPaymentCoinId } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVaultCapyLabsExtension, SuiFrensApi.constants.moduleNames.suiFrensVaultCapyLabsExtension .capyLabs, "mix_and_keep"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVaultCapyLabsExtension), // SuiFrensVaultCapyLabsExt tx.object(this.addresses.objects.capyLabsApp), // CapyLabsApp tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.parentOneId), // SuiFren tx.object(inputs.parentTwoId), // SuiFren typeof suiPaymentCoinId === "string" ? tx.object(suiPaymentCoinId) : suiPaymentCoinId, // Coin tx.object(sui_1.Sui.constants.addresses.suiClockId), // Clock ], }); }; this.mixWithStakedAndKeepTx = (inputs) => { const { tx, suiPaymentCoinId } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVaultCapyLabsExtension, SuiFrensApi.constants.moduleNames.suiFrensVaultCapyLabsExtension .capyLabs, "mix_with_staked_and_keep"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVaultCapyLabsExtension), // SuiFrensVaultCapyLabsExt tx.object(this.addresses.objects.capyLabsApp), // CapyLabsApp tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.nonStakedParentId), // SuiFren tx.object(inputs.stakedParentId), // SuiFren typeof suiPaymentCoinId === "string" ? tx.object(suiPaymentCoinId) : suiPaymentCoinId, // Coin tx.object(sui_1.Sui.constants.addresses.suiClockId), // Clock ], }); }; this.mixStakedWithStakedAndKeepTx = (inputs) => { const { tx, suiPaymentCoinId } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVaultCapyLabsExtension, SuiFrensApi.constants.moduleNames.suiFrensVaultCapyLabsExtension .capyLabs, "mix_staked_with_staked_and_keep"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVaultCapyLabsExtension), // SuiFrensVaultCapyLabsExt tx.object(this.addresses.objects.capyLabsApp), // CapyLabsApp tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.parentOneId), // SuiFren tx.object(inputs.parentTwoId), // SuiFren typeof suiPaymentCoinId === "string" ? tx.object(suiPaymentCoinId) : suiPaymentCoinId, // Coin tx.object(sui_1.Sui.constants.addresses.suiClockId), // Clock ], }); }; // ========================================================================= // Staking Transaction Commands // ========================================================================= this.stakeAndKeepTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVaultCapyLabsExtension, SuiFrensApi.constants.moduleNames.suiFrensVaultCapyLabsExtension .capyLabs, "stake_and_keep"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVaultCapyLabsExtension), // SuiFrensVaultCapyLabsExt tx.object(this.addresses.objects.capyLabsApp), // CapyLabsApp tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.suiFrenId), // SuiFren tx.pure.bool(inputs.autoStakeFees), tx.pure.u64(inputs.baseFee), tx.pure.u64(inputs.feeIncrementPerMix), tx.pure.u8(Number(inputs.minRemainingMixesToKeep)), ], }); }; this.unstakeAndKeepTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVaultCapyLabsExtension, SuiFrensApi.constants.moduleNames.suiFrensVaultCapyLabsExtension .capyLabs, "unstake_and_keep"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVaultCapyLabsExtension), // SuiFrensVaultCapyLabsExt tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.stakedPositionId), // StakedPosition ], }); }; // ========================================================================= // Fee Harvest Transaction Commands // ========================================================================= this.beginHarvestTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "begin_harvest"), typeArguments: [], arguments: [], }); }; this.harvestTx = (inputs) => { const { tx, harvestFeesEventMetadataId } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "harvest"), typeArguments: [], arguments: [ tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.stakedPositionId), // StakedPosition typeof harvestFeesEventMetadataId === "string" ? tx.object(harvestFeesEventMetadataId) : harvestFeesEventMetadataId, // HarvestedFeesEventMetadata ], }); }; this.endHarvestTx = (inputs) => { const { tx, harvestFeesEventMetadataId } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "end_harvest"), typeArguments: [], arguments: [ typeof harvestFeesEventMetadataId === "string" ? tx.object(harvestFeesEventMetadataId) : harvestFeesEventMetadataId, // HarvestedFeesEventMetadata ], }); }; // ========================================================================= // Accessory Transaction Commands // ========================================================================= this.addAccessoryTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "add_accessory"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.suiFrenId), // suifren_id tx.object(inputs.accessoryId), // Accessory ], }); }; this.addAccessoryToOwnedSuiFrenTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "add_accessory_to_owned_suifren"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(inputs.suiFrenId), // suifren_id tx.object(inputs.accessoryId), // Accessory ], }); }; this.removeAccessoryAndKeepTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "remove_accessory_and_keep"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(this.addresses.objects.suiFrensVault), // SuiFrenVault tx.object(inputs.stakedPositionId), // StakedPosition tx.object(inputs.accessoryType), // String ], }); }; this.removeAccessoryFromOwnedSuiFrenAndKeepTx = (inputs) => { const { tx } = inputs; return tx.moveCall({ target: helpers_1.Helpers.transactions.createTxTarget(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.vault, "remove_accessory_from_owned_suifren_and_keep"), typeArguments: [inputs.suiFrenType], arguments: [ tx.object(inputs.suiFrenId), // SuiFren tx.object(inputs.accessoryType), // String ], }); }; // ========================================================================= // Transactions // ========================================================================= // ========================================================================= // Staking Transactions // ========================================================================= this.fetchStakeTx = helpers_1.Helpers.transactions.createBuildTxFunc((inputs) => this.stakeAndKeepTx(Object.assign(Object.assign({}, inputs), { autoStakeFees: true }))); this.fetchUnstakeTx = helpers_1.Helpers.transactions.createBuildTxFunc(this.unstakeAndKeepTx); // ========================================================================= // Mixing Transactions // ========================================================================= this.fetchBuildMixTx = (inputs) => __awaiter(this, void 0, void 0, function* () { const { walletAddress, suiFrenParentOne, suiFrenParentTwo, suiFrenType, baseFee, isSponsoredTx, } = inputs; const tx = new transactions_1.Transaction(); tx.setSender(walletAddress); const totalFee = baseFee + suiFrens_1.SuiFrens.calcTotalInternalMixFee({ mixFee1: suiFrenParentOne.mixFee, mixFee2: suiFrenParentTwo.mixFee, }); const suiPaymentCoinId = yield this.Provider.Coin().fetchCoinWithAmountTx({ tx, walletAddress, coinType: coin_1.Coin.constants.suiCoinType, coinAmount: totalFee, isSponsoredTx, }); const isParentOneStaked = suiFrenParentOne.mixFee !== undefined; const isParentTwoStaked = suiFrenParentTwo.mixFee !== undefined; const parentOneId = suiFrenParentOne.objectId; const parentTwoId = suiFrenParentTwo.objectId; if (isParentOneStaked && isParentTwoStaked) { // both staked this.mixStakedWithStakedAndKeepTx({ tx, parentOneId, parentTwoId, suiPaymentCoinId, suiFrenType, }); } else if (!isParentOneStaked && !isParentTwoStaked) { // neither staked this.mixAndKeepTx({ tx, parentOneId, parentTwoId, suiPaymentCoinId, suiFrenType, }); } else { // only one staked const [nonStakedParentId, stakedParentId] = isParentOneStaked ? [parentTwoId, parentOneId] : [parentOneId, parentTwoId]; this.mixWithStakedAndKeepTx({ tx, nonStakedParentId, stakedParentId, suiPaymentCoinId, suiFrenType, }); } return tx; }); // ========================================================================= // Fee Harvesting Transactions // ========================================================================= this.fetchBuildHarvestFeesTx = (inputs) => __awaiter(this, void 0, void 0, function* () { const { stakedPositionIds } = inputs; const tx = new transactions_1.Transaction(); tx.setSender(inputs.walletAddress); const harvestFeesEventMetadataId = this.beginHarvestTx({ tx }); let harvestedCoins = []; for (const stakedPositionId of stakedPositionIds) { const harvestedCoin = this.harvestTx({ tx, stakedPositionId, harvestFeesEventMetadataId, }); harvestedCoins.push(harvestedCoin); } // TODO: move this merging & transferring behaviour to coins api helpers ? const coinToTransfer = harvestedCoins[0]; if (harvestedCoins.length > 1) tx.mergeCoins(coinToTransfer, harvestedCoins.slice(1)); tx.transferObjects([coinToTransfer], inputs.walletAddress); this.endHarvestTx({ tx, harvestFeesEventMetadataId }); return tx; }); // ========================================================================= // Accessory Transactions // ========================================================================= this.fetchBuildAddAccessoryTx = (inputs) => { if (inputs.isOwned) { return helpers_1.Helpers.transactions.createBuildTxFunc(this.addAccessoryToOwnedSuiFrenTx)(inputs); } return helpers_1.Helpers.transactions.createBuildTxFunc(this.addAccessoryTx)(inputs); }; this.fetchBuildRemoveAccessoryTx = (inputs) => { if ("suiFrenId" in inputs) { return helpers_1.Helpers.transactions.createBuildTxFunc(this.removeAccessoryFromOwnedSuiFrenAndKeepTx)(inputs); } return helpers_1.Helpers.transactions.createBuildTxFunc(this.removeAccessoryAndKeepTx)(inputs); }; // ========================================================================= // Stats // ========================================================================= this.fetchSuiFrenStats = () => __awaiter(this, void 0, void 0, function* () { const [suiFrenVault, mixSuiFrenEventsWithinTime] = yield Promise.all([ this.fetchSuiFrenVaultStateV1Object(), this.Provider.Events().fetchEventsWithinTime({ fetchEventsFunc: this.fetchMixSuiFrensEvents, timeUnit: "hour", time: 24, }), ]); const mixingFees24hr = helpers_1.Helpers.sumBigInt(mixSuiFrenEventsWithinTime.map((event) => event.fee)); return { totalMixes: suiFrenVault.totalMixes, currentTotalStaked: suiFrenVault.stakedSuiFrens, mixingVolume24hr: mixSuiFrenEventsWithinTime.length, mixingFees24hr, }; }); // ========================================================================= // SuiFren Attribute Filtering // ========================================================================= this.filterSuiFrensWithAttributes = (inputs) => { const { suiFrens, attributes } = inputs; if (Object.keys(attributes).length <= 0) return suiFrens; return suiFrens.filter((suiFren) => Object.entries(attributes).every(([key1, val1]) => Object.entries(suiFren.attributes).some(([key2, val2]) => key1.toLowerCase() === key2.toLowerCase() && val1.toLowerCase() === val2.toLowerCase()))); }; // ========================================================================= // Helpers // ========================================================================= // TODO: remove or update // public isSuiFrenObjectType = (suiObjectInfo: SuiObjectInfo): boolean => // suiObjectInfo.type === this.objectTypes.suiFren; // ========================================================================= // Private Methods // ========================================================================= // ========================================================================= // Helpers // ========================================================================= this.fetchCompletePartialSuiFrenObjects = (inputs) => __awaiter(this, void 0, void 0, function* () { const { partialSuiFrens, isStaked } = inputs; if (!isStaked) { return Promise.all(partialSuiFrens.map((partialSuiFren) => this.fetchNonStakedCompletePartialSuiFrenObject({ partialSuiFren, }))); } if (partialSuiFrens.length <= 0) return []; const [partialSuiFrenBullsharks, partialSuiFrenNonBullsharks] = helpers_1.Helpers.bifilter(partialSuiFrens, (partialSuiFren) => partialSuiFren.objectType.includes(this.objectTypes.bullshark)); // TODO: handle different suifren types const bullsharkDynamicFields = partialSuiFrenBullsharks.map(() => ({ mixLimit: undefined, lastEpochMixed: undefined, })); const nonBullsharkDynamicFields = yield this.fetchMixingLimitsAndLastEpochMixeds({ suiFrenIds: partialSuiFrenNonBullsharks.map((suiFren) => suiFren.objectId), suiFrenType: coin_1.Coin.getInnerCoinType(partialSuiFrenNonBullsharks[0].objectType), }); const suiFrenBullsharks = bullsharkDynamicFields.map((data, index) => (Object.assign(Object.assign({}, partialSuiFrenBullsharks[index]), data))); const suiFrenNonBullsharks = nonBullsharkDynamicFields.map((data, index) => (Object.assign(Object.assign({}, partialSuiFrenNonBullsharks[index]), data))); return [...suiFrenBullsharks, ...suiFrenNonBullsharks]; }); this.fetchNonStakedCompletePartialSuiFrenObject = (inputs) => __awaiter(this, void 0, void 0, function* () { const { partialSuiFren } = inputs; const suiFrenId = partialSuiFren.objectId; // TODO: move inner coin type func to general func in helpers const suiFrenType = coin_1.Coin.getInnerCoinType(partialSuiFren.objectType); const [mixLimit, lastEpochMixed] = yield Promise.all([ this.fetchMixingLimit({ suiFrenId, suiFrenType }), this.fetchLastEpochMixed({ suiFrenId, suiFrenType }), ]); return Object.assign(Object.assign({}, partialSuiFren), { mixLimit, lastEpochMixed }); }); // TODO: refactor to use NftsApi class this.fetchOwnedPartialSuiFrenBullsharks = (inputs) => __awaiter(this, void 0, void 0, function* () { const kioskOwnerCaps = yield this.Provider.Nfts().fetchOwnedKioskOwnerCaps(inputs); const allBullsharks = yield Promise.all(kioskOwnerCaps.map((kioskOwnerCap) => this.Provider.DynamicFields().fetchCastAllDynamicFieldsOfType({ parentObjectId: kioskOwnerCap.kioskObjectId, objectsFromObjectIds: (suiFrenIds) => this.fetchSuiFrens({ suiFrenIds }), dynamicFieldType: (fieldType) => fieldType.includes(this.objectTypes.suiFren) && fieldType.includes(this.objectTypes.bullshark), }))); const bullsharks = allBullsharks.reduce((acc, bullsharks) => [...acc, ...bullsharks], []); return bullsharks; }); // ========================================================================= // Event Types // ========================================================================= this.harvestSuiFrenFeesEventType = () => eventsApiHelpers_1.EventsApiHelpers.createEventType(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.events, SuiFrensApi.constants.eventNames.suiFrensVault.harvestSuiFrenFees); this.mixSuiFrensEventType = () => eventsApiHelpers_1.EventsApiHelpers.createEventType(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.events, SuiFrensApi.constants.eventNames.suiFrensVault.mixSuiFrens); this.stakeSuiFrenEventType = () => eventsApiHelpers_1.EventsApiHelpers.createEventType(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.events, SuiFrensApi.constants.eventNames.suiFrensVault.stakeSuiFren); this.unstakeSuiFrenEventType = () => eventsApiHelpers_1.EventsApiHelpers.createEventType(this.addresses.packages.suiFrensVault, SuiFrensApi.constants.moduleNames.suiFrensVault.events, SuiFrensApi.constants.eventNames.suiFrensVault.unstakeSuiFren); const addresses = this.Provider.addresses.suiFrens; if (!addresses) throw new Error("not all required addresses have been set in provider"); this.addresses = addresses; this.objectTypes = { // suiFrens suiFren: `${addresses.packages.suiFrens}::${SuiFrensApi.constants.moduleNames.suiFrens.suiFrens}::SuiFren`, capy: `${addresses.packages.suiFrens}::capy::Capy`, bullshark: `${addresses.packages.suiFrensBullshark}::bullshark::Bullshark`, // accessories suiFrenAccessory: `${addresses.packages.accessories}::${SuiFrensApi.constants.moduleNames.accessories.accessories}::Accessory`, // staking stakedSuiFrenPosition: `${addresses.packages.suiFrensVault}::${SuiFrensApi.constants.moduleNames.suiFrensVault.stakedPosition}::StakedPosition`, stakedSuiFrenMetadataV1: `${addresses.packages.suiFrensVault}::${SuiFrensApi.constants.moduleNames.suiFrensVault.vaultState}::StakedSuiFrenMetadataV1`, }; this.eventTypes = { harvestSuiFrenFees: this.harvestSuiFrenFeesEventType(), mixSuiFrens: this.mixSuiFrensEventType(), stakeSuiFren: this.stakeSuiFrenEventType(), unstakeSuiFren: this.unstakeSuiFrenEventType(), }; } } exports.SuiFrensApi = SuiFrensApi; // ========================================================================= // Constants // ========================================================================= SuiFrensApi.constants = { moduleNames: { suiFrens: { suiFrens: "suifrens", }, accessories: { accessories: "accessories", }, capyLabs: { capyLabs: "capy_labs", }, suiFrensVault: { vault: "vault", vaultState: "vault_state", events: "events", stakedPosition: "staked_position", }, suiFrensVaultCapyLabsExtension: { capyLabs: "capy_labs", }, }, eventNames: { suiFrensVault: { mixSuiFrens: "MixedSuiFrenEvent", stakeSuiFren: "StakedSuiFrenEvent", unstakeSuiFren: "UnstakedSuiFrenEvent", harvestSuiFrenFees: "HarvestedFeesEvent", }, }, };