aftermath-ts-sdk
Version:
Aftermath TypeScript SDK
534 lines (533 loc) • 20 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());
});
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Pools = void 0;
const pool_1 = require("./pool");
const coin_1 = require("../../packages/coin/coin");
const caller_1 = require("../../general/utils/caller");
const helpers_1 = require("../../general/utils/helpers");
const fixedUtils_1 = require("../../general/utils/fixedUtils");
/**
* The `Pools` class provides a high-level interface for interacting with
* Aftermath Finance liquidity pools. It allows fetching individual or multiple
* pools, managing liquidity pool tokens (LP tokens), and creating new pools
* if you have the required privileges.
*
* @example
* ```typescript
* const afSdk = new Aftermath("MAINNET");
* await afSdk.init(); // initialize provider
*
* const pools = afSdk.Pools();
*
* // Fetch a single pool
* const pool = await pools.getPool({ objectId: "0x<poolId>" });
*
* // Fetch multiple pools
* const poolArray = await pools.getPools({ objectIds: ["0x<id1>", "0x<id2>"] });
* ```
*/
class Pools extends caller_1.Caller {
// =========================================================================
// Constructor
// =========================================================================
/**
* Creates a new `Pools` instance for querying and managing AMM pools on Aftermath.
*
* @param config - Optional configuration object specifying network or access token.
* @param Provider - An optional `AftermathApi` instance providing advanced transaction building.
*/
constructor(config, Provider) {
super(config, "pools");
this.Provider = Provider;
// =========================================================================
// Inspections
// =========================================================================
/**
* Retrieves the on-chain pool object ID corresponding to a specific LP coin type.
*
* @param inputs - Contains the `lpCoinType` string.
* @returns The pool object ID if it exists.
*
* @example
* ```typescript
* const poolId = await pools.getPoolObjectIdForLpCoinType({
* lpCoinType: "0x<lpCoinType>"
* });
* console.log(poolId);
* ```
*/
this.getPoolObjectIdForLpCoinType = (inputs) => {
return this.getPoolObjectIdsForLpCoinTypes({
lpCoinTypes: [inputs.lpCoinType],
});
};
/**
* Checks if a given coin type is recognized as an LP coin.
* Internally calls `getPoolObjectIdForLpCoinType`.
*
* @param inputs - Contains the `lpCoinType` to check.
* @returns `true` if the coin is an LP token, `false` otherwise.
*/
this.isLpCoinType = (inputs) => __awaiter(this, void 0, void 0, function* () {
try {
yield this.getPoolObjectIdForLpCoinType(inputs);
return true;
}
catch (e) {
return false;
}
});
/**
* Retrieves the total volume across all pools in the last 24 hours.
*
* @returns A promise resolving to a numeric volume (e.g., in USD).
*
* @example
* ```typescript
* const totalVol24 = await pools.getTotalVolume24hrs();
* console.log("Protocol-wide 24h volume:", totalVol24);
* ```
*/
this.getTotalVolume24hrs = () => __awaiter(this, void 0, void 0, function* () {
return this.fetchApi("volume-24hrs");
});
// =========================================================================
// Private Helpers
// =========================================================================
/**
* Provides a typed reference to the `Pools` part of the `AftermathApi`,
* throwing an error if not defined.
*/
this.useProvider = () => {
var _b;
const provider = (_b = this.Provider) === null || _b === void 0 ? void 0 : _b.Pools();
if (!provider)
throw new Error("missing AftermathApi Provider");
return provider;
};
}
// =========================================================================
// Class Objects
// =========================================================================
// =========================================================================
// Pool Class
// =========================================================================
/**
* Fetches a single pool by its on-chain `objectId` and returns a new `Pool` instance.
*
* @param inputs - An object containing `objectId`.
* @returns A promise that resolves to a `Pool` instance.
*
* @example
* ```typescript
* const pool = await pools.getPool({ objectId: "0x<poolId>" });
* console.log(pool.pool.lpCoinType, pool.pool.name);
* ```
*/
getPool(inputs) {
return __awaiter(this, void 0, void 0, function* () {
const pool = yield this.fetchApi(inputs.objectId);
return new pool_1.Pool(pool, this.config, this.Provider);
});
}
/**
* Fetches multiple pools by their on-chain `objectIds` and returns an array of `Pool` instances.
*
* @param inputs - An object containing an array of `objectIds`.
* @returns A promise that resolves to an array of `Pool` instances.
*
* @example
* ```typescript
* const poolArray = await pools.getPools({ objectIds: ["0x<id1>", "0x<id2>"] });
* console.log(poolArray.length);
* ```
*/
getPools(inputs) {
return __awaiter(this, void 0, void 0, function* () {
const pools = yield this.fetchApi("", {
poolIds: inputs.objectIds,
});
return pools.map((pool) => new pool_1.Pool(pool, this.config, this.Provider));
});
}
/**
* Retrieves all pools recognized by the Aftermath API, returning an array of `Pool` objects.
*
* @returns An array of `Pool` instances.
*
* @example
* ```typescript
* const allPools = await pools.getAllPools();
* console.log(allPools.map(p => p.pool.name));
* ```
*/
getAllPools() {
return __awaiter(this, void 0, void 0, function* () {
const pools = yield this.fetchApi("", {});
return pools.map((pool) => new pool_1.Pool(pool, this.config, this.Provider));
});
}
/**
* Fetches information about all owned LP coins for a given wallet address.
* This indicates the user's liquidity positions across multiple pools.
*
* @param inputs - An object containing the `walletAddress`.
* @returns A `PoolLpInfo` object summarizing the user's LP balances.
*
* @example
* ```typescript
* const lpCoins = await pools.getOwnedLpCoins({ walletAddress: "0x<address>" });
* console.log(lpCoins);
* ```
*/
getOwnedLpCoins(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.fetchApi("owned-lp-coins", inputs);
});
}
// =========================================================================
// Transactions
// =========================================================================
/**
* Constructs or fetches a transaction to publish a new LP coin package,
* typically used by advanced users or devs establishing new liquidity pools.
*
* @param inputs - Includes the user `walletAddress` and the `lpCoinDecimals`.
* @returns A transaction object (or data) that can be signed and published to Sui.
*
* @example
* ```typescript
* const publishTx = await pools.getPublishLpCoinTransaction({
* walletAddress: "0x<address>",
* lpCoinDecimals: 9
* });
* ```
*/
getPublishLpCoinTransaction(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.useProvider().buildPublishLpCoinTx(inputs);
});
}
/**
* Constructs a transaction to create a brand new pool on-chain, given coin types,
* initial weights, fees, and possible DAO fee info.
*
* @param inputs - The body describing how to form the new pool.
* @returns A transaction object that can be signed and executed.
*
* @example
* ```typescript
* const createPoolTx = await pools.getCreatePoolTransaction({
* walletAddress: "0x<address>",
* lpCoinType: "0x<lpCoin>",
* lpCoinMetadata: {
* name: "MyPool LP",
* symbol: "MYPLP"
* },
* coinsInfo: [
* {
* coinType: "0x<coinA>",
* weight: 0.5,
* decimals: 9,
* tradeFeeIn: 0.003,
* initialDeposit: 1_000_000_000n
* },
* // ...
* ],
* poolName: "My Weighted Pool",
* createPoolCapId: "0x<capId>",
* respectDecimals: true,
* });
* ```
*/
getCreatePoolTransaction(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.fetchApiTransaction("transactions/create-pool", inputs);
});
}
/**
* Retrieves multiple pool object IDs given an array of LP coin types.
* If a given LP coin type has no associated pool, it might return `undefined`.
*
* @param inputs - Contains an array of `lpCoinTypes`.
* @returns An array of `ObjectId | undefined` of matching length.
*
* @example
* ```typescript
* const poolIds = await pools.getPoolObjectIdsForLpCoinTypes({
* lpCoinTypes: ["0x<lpCoinA>", "0x<lpCoinB>"]
* });
* console.log(poolIds);
* ```
*/
getPoolObjectIdsForLpCoinTypes(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.fetchApi("pool-object-ids", inputs);
});
}
/**
* Retrieves the total value locked (TVL) across all or specific pool IDs.
*
* @param inputs - Optionally provide an array of specific `poolIds`. If omitted, returns global TVL.
* @returns A promise resolving to a numeric TVL (e.g., in USD).
*
* @example
* ```typescript
* const allTvl = await pools.getTVL();
* const subsetTvl = await pools.getTVL({ poolIds: ["0x<id1>", "0x<id2>"] });
* ```
*/
getTVL(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.fetchApi("tvl", inputs !== null && inputs !== void 0 ? inputs : {});
});
}
/**
* Fetches an array of `PoolStats` objects for a given set of pools,
* including volume, fees, TVL, and other metrics.
*
* @param inputs - Must include an array of `poolIds`.
* @returns An array of `PoolStats` in matching order.
*
* @example
* ```typescript
* const stats = await pools.getPoolsStats({ poolIds: ["0x<id1>", "0x<id2>"] });
* console.log(stats[0].volume, stats[1].tvl);
* ```
*/
getPoolsStats(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.fetchApi("stats", inputs);
});
}
/**
* Returns all DAO fee pool owner capabilities owned by a particular user.
* This is used to see which pools' DAO fees the user can update.
*
* @param inputs - An object with user `walletAddress`.
* @returns Data about each `DaoFeePoolOwnerCapObject` the user owns.
*
* @example
* ```typescript
* const daoCaps = await pools.getOwnedDaoFeePoolOwnerCaps({
* walletAddress: "0x<address>"
* });
* console.log(daoCaps);
* ```
*/
getOwnedDaoFeePoolOwnerCaps(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.useProvider().fetchOwnedDaoFeePoolOwnerCaps(inputs);
});
}
// =========================================================================
// Events
// =========================================================================
/**
* Fetches user-specific interaction events (deposits, withdrawals) across pools,
* optionally with pagination.
*
* @param inputs - An object containing `walletAddress`, plus optional pagination (`cursor`, `limit`).
* @returns An event set with a cursor for further queries if available.
*
* @example
* ```typescript
* const userEvents = await pools.getInteractionEvents({
* walletAddress: "0x...",
* limit: 10,
* });
* console.log(userEvents.events, userEvents.nextCursor);
* ```
*/
getInteractionEvents(inputs) {
return __awaiter(this, void 0, void 0, function* () {
return this.fetchApiIndexerEvents("interaction-events-by-user", inputs);
});
}
}
exports.Pools = Pools;
_a = Pools;
// =========================================================================
// Constants
// =========================================================================
/**
* Static constants relevant to the pool logic, such as protocol fees,
* referral percentages, and bounds for trading/withdrawal percentages.
*/
Pools.constants = {
/**
* Protocol fee structure: `totalProtocol` is the fraction of trades
* that is taken as a fee, which is split among `treasury`, `insuranceFund`,
* and `devWallet` in the given proportions.
*/
feePercentages: {
/**
* The total fraction (as a decimal) of trades charged by the protocol.
* e.g., 0.00005 => 0.005%.
*/
totalProtocol: 0.00005,
/**
* The fraction of `totalProtocol` allocated to the treasury.
*/
treasury: 0.5,
/**
* The fraction of `totalProtocol` allocated to the insurance fund.
*/
insuranceFund: 0.3,
/**
* The fraction of `totalProtocol` allocated to the dev wallet.
*/
devWallet: 0.2,
},
/**
* Referral fee structures, applying a discount/rebate to the user and
* referrer, taken from the treasury portion of protocol fees.
*/
referralPercentages: {
/**
* The fraction of the treasury portion that discounts the user's fee.
*/
discount: 0.05,
/**
* The fraction of the treasury portion that acts as a rebate to the referrer.
*/
rebate: 0.05,
},
/**
* Various bounds used to prevent extreme trades or invalid pool configurations.
*/
bounds: {
/**
* Maximum number of distinct coins allowed in a single pool.
*/
maxCoinsInPool: 8,
/**
* Maximum fraction (decimal) of a pool's balance that can be traded at once.
*/
maxTradePercentageOfPoolBalance: 0.3,
/**
* Maximum fraction (decimal) of a pool's balance that can be withdrawn at once.
*/
maxWithdrawPercentageOfPoolBalance: 0.3,
/**
* Minimum and maximum swap fees (0.01% to 10%).
*/
minSwapFee: 0.0001,
maxSwapFee: 0.1,
/**
* Minimum and maximum coin weight for weighted pools (1% to 99%).
*/
minWeight: 0.01,
maxWeight: 0.99,
/**
* Minimum and maximum DAO fee (0% to 100%).
*/
minDaoFee: 0,
maxDaoFee: 1,
},
/**
* Default parameter(s) used in the absence of explicit user or code settings.
*/
defaults: {
/**
* Default decimals for LP coins if none are specified.
*/
lpCoinDecimals: 9,
},
};
// =========================================================================
// Fees
// =========================================================================
/**
* Returns how much coin remains **after** applying the protocol fees
* (and referral discount if `withReferral` is `true`).
*
* @param inputs - The original `amount` and an optional referral flag.
* @returns The post-fee (net) amount as a bigint.
*
* @example
* ```typescript
* const netAmount = Pools.getAmountWithProtocolFees({ amount: 1_000_000n });
* ```
*/
Pools.getAmountWithProtocolFees = (inputs) => {
const referralDiscount = inputs.withReferral
? _a.constants.feePercentages.totalProtocol *
_a.constants.feePercentages.treasury *
_a.constants.referralPercentages.discount
: 0;
return BigInt(Math.floor(Number(inputs.amount) *
(1 -
(_a.constants.feePercentages.totalProtocol -
referralDiscount))));
};
/**
* The inverse calculation: given a net amount (post-fees), figure out
* the original gross amount. Used when we already have fees subtracted
* but need to restore an original quantity.
*
* @param inputs - The net `amount` after fees, plus an optional referral flag.
* @returns The original gross amount as a bigint.
*/
Pools.getAmountWithoutProtocolFees = (inputs) => {
const referralDiscount = inputs.withReferral
? _a.constants.feePercentages.totalProtocol *
_a.constants.feePercentages.treasury *
_a.constants.referralPercentages.discount
: 0;
return BigInt(Math.floor(Number(inputs.amount) *
(1 /
(1 -
(_a.constants.feePercentages.totalProtocol -
referralDiscount)))));
};
/**
* A helper to transform a user-provided slippage fraction, e.g. 0.01,
* into a 1 - slippage format, if needed for certain math operations.
*
* @param slippage - The decimal fraction of slippage tolerance, e.g. 0.01 => 1%.
* @returns A big integer representing `1 - slippage` in a fixed context.
*/
Pools.normalizeInvertSlippage = (slippage) => fixedUtils_1.FixedUtils.directUncast(1 - slippage);
// =========================================================================
// Display
// =========================================================================
/**
* Produces a user-friendly string for an LP coin type, e.g. "Sui Coin LP"
* by analyzing the coin type symbol. Typically used in UIs or logs.
*
* @param lpCoinType - The coin type for the LP token.
* @returns A string representation for display, e.g. "Af_lp_abc" => "Abc LP".
*/
Pools.displayLpCoinType = (lpCoinType) => coin_1.Coin.getCoinTypeSymbol(lpCoinType)
.toLowerCase()
.replace("af_lp_", "")
.split("_")
.map((word) => helpers_1.Helpers.capitalizeOnlyFirstLetter(word))
.join(" ") + " LP";
// =========================================================================
// Helpers
// =========================================================================
/**
* A quick heuristic check to see if the given `lpCoinType` string
* might represent an Aftermath LP token. This is not a full on-chain validation.
*
* @param inputs - An object containing `lpCoinType`.
* @returns `true` if it matches a known pattern; otherwise `false`.
*/
Pools.isPossibleLpCoinType = (inputs) => {
const { lpCoinType } = inputs;
return (lpCoinType.split("::").length === 3 &&
lpCoinType.split("::")[1].includes("af_lp") &&
lpCoinType.split("::")[2].includes("AF_LP"));
};