@admin-jigsaw/jigsaw-sdk
Version:
Returns predefined data for Jigsaw platform and exposes functionality to retrieve the necessary data
194 lines (193 loc) • 9.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.JigsawClient = void 0;
const viem_1 = require("viem");
const chains_1 = require("viem/chains");
const strategyManagerAbi_1 = require("./contracts/strategyManagerAbi");
const strategyAbi_1 = require("./contracts/strategyAbi");
const pendle_utils_1 = require("./utils/pendle.utils");
const pendle_1 = require("./lib/pendle");
const protocols_utils_1 = require("./utils/protocols.utils");
const chains_2 = require("./constants/chains");
const strategiesSharedConstants_1 = require("./constants/strategiesSharedConstants");
class JigsawClient {
constructor(rpcUrl, chainId) {
const chain = (0, viem_1.extractChain)({
chains: [chains_1.mainnet, chains_1.sonic],
id: chainId, // Allow any chainId, will throw an error if unsupported
});
const transport = rpcUrl ? (0, viem_1.http)(rpcUrl) : (0, viem_1.http)();
this.client = (0, viem_1.createPublicClient)({ chain, transport });
}
/**
* Fetches user strategies based on holding address and optional asset symbol.
* @param holdingAddress The address of the user's holding contract.
* @param assetSymbol Optional filter for asset symbol.
* @returns A list of strategies.
*/
async getUserStrategies(holdingAddress, assetSymbol) {
try {
const chainConfig = (0, chains_2.getChainConfig)(this.client.chain?.id || chains_1.mainnet.id);
const data = await this.client.readContract({
address: chainConfig.constants.strategyManagerAddress,
abi: strategyManagerAbi_1.strategyManagerAbi,
functionName: "getHoldingToStrategy",
args: [holdingAddress],
});
if (!Array.isArray(data))
return [];
// If no asset symbol specified, return all strategy addresses
if (!assetSymbol) {
return data;
}
// Filter strategies based on the symbol
return data.filter((strategyAddress) => {
const lowerSymbol = assetSymbol.toLowerCase();
if (chainConfig.strategies === null)
return false;
// Check AAVE strategies
if (chainConfig.strategies.aave?.aaveStrategies) {
const aaveStrategy = Object.entries(chainConfig.strategies.aave.aaveStrategies).find(([symbol, strat]) => symbol.toLowerCase() === lowerSymbol &&
(0, viem_1.getAddress)(strat.stratAddress) === (0, viem_1.getAddress)(strategyAddress));
if (aaveStrategy)
return true;
}
// Check DINERO strategies
if (chainConfig.strategies.dinero) {
const dineroStrategy = Object.entries(chainConfig.strategies.dinero).find(([symbol, strat]) => symbol.toLowerCase() === lowerSymbol &&
(0, viem_1.getAddress)(strat.stratAddress) === (0, viem_1.getAddress)(strategyAddress));
if (dineroStrategy)
return true;
}
// Check RESERVOIR strategies
if (chainConfig.strategies.reservoir) {
const reservoirStrategy = Object.entries(chainConfig.strategies.reservoir).find(([symbol, strat]) => symbol.toLowerCase() === lowerSymbol &&
(0, viem_1.getAddress)(strat.stratAddress) === (0, viem_1.getAddress)(strategyAddress));
if (reservoirStrategy)
return true;
}
// Check PENDLE strategies
if (chainConfig.strategies.pendle?.strategies) {
const pendleStrategy = Object.entries(chainConfig.strategies.pendle.strategies).find(([symbol, strategies]) => {
if (symbol.toLowerCase() !== lowerSymbol)
return false;
return strategies.some((strategy) => (0, viem_1.getAddress)(strategy.stratAddress) ===
(0, viem_1.getAddress)(strategyAddress));
});
if (pendleStrategy)
return true;
}
return false;
});
}
catch (error) {
console.error("Failed to fetch user strategies:", error);
return [];
}
}
/**
* Fetches liquidation call data for user strategies, optionally filtered by asset symbol.
* @param holdingAddress User's holding contract address.
* @param assetSymbol Optional filter for asset symbol.
* @param pendleSlippage Optional slippage parameter for Pendle strategies.
* @returns Object with arrays of strategy addresses and corresponding call data strings.
*/
async getUserLiquidationInfo(holdingAddress, assetSymbol, pendleSlippage) {
try {
// Get all strategies for this holding address
const strategies = await this.getUserStrategies(holdingAddress, assetSymbol);
if (!strategies.length) {
return { strategies: [], strategiesData: [] };
}
// Generate calldata for each strategy, maintaining array correspondence
const callDataPromises = strategies.map(async (strategyAddress) => {
try {
const protocolName = (0, protocols_utils_1.getProtocolByStrategy)(strategyAddress, this.client.chain?.id || chains_1.mainnet.id);
// Only generate callData for Pendle strategies
if (protocolName === strategiesSharedConstants_1.PROTOCOLS_DATA.PENDLE.name) {
const multicallResults = await this.client.multicall({
contracts: [
{
address: strategyAddress,
abi: strategyAbi_1.strategyAbi,
functionName: "recipients",
args: [holdingAddress],
},
{
address: strategyAddress,
abi: strategyAbi_1.strategyAbi,
functionName: "tokenIn",
args: [],
},
],
});
const totalSharesRaw = multicallResults[0]?.result
? (multicallResults[0].result[1] ?? BigInt(0))
: BigInt(0);
const tokenAddress = multicallResults[1]?.result ?? null;
const pendleMarket = (0, pendle_utils_1.getPendleMarketByStrategy)(strategyAddress, this.client.chain?.id || chains_1.mainnet.id);
if (!pendleMarket || !tokenAddress)
return "";
const resp = await (0, pendle_1.removeLiquiditySingleToken)(tokenAddress, totalSharesRaw.toString(), pendleMarket, holdingAddress, pendleSlippage, this.client.chain?.id || chains_1.mainnet.id);
return await (0, pendle_utils_1.generatePendleRemoveLiquidityDataString)(resp);
}
// For non-Pendle strategies, return empty string but maintain array correspondence
return viem_1.zeroAddress;
}
catch (error) {
console.error(`Error processing strategy ${strategyAddress}:`, error);
// Return empty string on error, but maintain array correspondence
return viem_1.zeroAddress;
}
});
// Resolve all promises while maintaining strategy-callData correspondence
const strategiesData = await Promise.all(callDataPromises);
return {
strategies,
strategiesData,
};
}
catch (error) {
console.error("Failed to fetch liquidation info:", error);
return { strategies: [], strategiesData: [] };
}
}
/**
* Fetches the current gas fee in Ether.
* @returns The gas price as a formatted string.
*/
async getCurrentGasFee() {
try {
const gasPrice = await this.client.getGasPrice();
const priceInEth = (0, viem_1.formatEther)(gasPrice);
console.log(`Current gas price is ${priceInEth}`);
return priceInEth;
}
catch (error) {
console.error("Failed to fetch gas price:", error);
return "0";
}
}
/**
* Retrieves information about a specific strategy.
* @param strategyAddress Strategy contract address.
* @returns StrategyInfo object or null.
*/
async getStrategyInfo(strategyAddress) {
try {
const chainConfig = (0, chains_2.getChainConfig)(this.client.chain?.id || chains_1.mainnet.id);
const strategyInfo = (await this.client.readContract({
address: chainConfig.constants.strategyManagerAddress,
abi: strategyManagerAbi_1.strategyManagerAbi,
functionName: "strategyInfo",
args: [strategyAddress],
}));
return strategyInfo ?? null;
}
catch (error) {
console.error("Failed to fetch strategy info:", error);
return null;
}
}
}
exports.JigsawClient = JigsawClient;