@devasher/kuru-sdk
Version:
Ethers v6 SDK to interact with Kuru (forked from @kuru-labs/kuru-sdk)
263 lines • 13.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Vault = void 0;
// ============ External Imports ============
const ethers_1 = require("ethers");
const params_1 = require("./params");
// ============ Internal Imports ============
const utils_1 = require("../utils");
const Vault_json_1 = __importDefault(require("../../abi/Vault.json"));
const MarginAccount_json_1 = __importDefault(require("../../abi/MarginAccount.json"));
const IERC20_json_1 = __importDefault(require("../../abi/IERC20.json"));
const txConfig_1 = __importDefault(require("../utils/txConfig"));
class Vault {
static async deposit(providerOrSigner, ammVaultAddress, amount1, amount2, receiver) {
const vaultContract = new ethers_1.ethers.Contract(ammVaultAddress, Vault_json_1.default.abi, providerOrSigner);
const tx = await vaultContract.deposit(amount1, amount2, receiver);
const receipt = await tx.wait();
if (!receipt) {
throw new Error('Transaction failed');
}
return receipt;
}
static async withdraw(providerOrSigner, shares, receiver, owner) {
const vaultContract = new ethers_1.ethers.Contract(owner, Vault_json_1.default.abi, providerOrSigner);
const tx = await vaultContract.withdraw(shares, receiver, owner);
const receipt = await tx.wait();
if (!receipt) {
throw new Error('Transaction failed');
}
return receipt;
}
/**
* Return the shares owned by an address in a vault
* @param vaultAddress The address of vault contract
* @param signer The signer to use for the transaction
* @returns A promise resolving to the number of shares of an address in a vault
*/
static async getVaultShares(vaultAddress, userAddress, providerOrSigner) {
const vaultContract = new ethers_1.ethers.Contract(vaultAddress, Vault_json_1.default.abi, providerOrSigner);
return await vaultContract.balanceOf(userAddress, {
from: ethers_1.ZeroAddress,
});
}
/**
*
* @param vaultAddress The address of the vault contract
* @param marketAddress The address of the market contract
* @param marginAccountAddress The address of the margin account contract
* @param providerOrSigner The provider or signer to use for the transaction
* @returns A promise that resolves to an object containing token1 and token2 address and balance
*/
static async getVaultLiquidity(vaultAddress, baseAssetAddress, quoteAssetAddress, marginAccountAddress, providerOrSigner) {
const marginAccountContract = new ethers_1.ethers.Contract(marginAccountAddress, MarginAccount_json_1.default.abi, providerOrSigner);
const token1 = await marginAccountContract.getBalance(vaultAddress, baseAssetAddress, {
from: ethers_1.ZeroAddress,
});
const token2 = await marginAccountContract.getBalance(vaultAddress, quoteAssetAddress, {
from: ethers_1.ZeroAddress,
});
return {
token1: {
address: baseAssetAddress,
balance: token1,
},
token2: {
address: quoteAssetAddress,
balance: token2,
},
};
}
/**
* Calculate the amount of tokens needed to deposit for a given number of shares
* @param shares The number of shares to mint
* @param vaultAddress The address of the vault contract
* @param providerOrSigner The provider or signer to use for the transaction
* @returns A promise that resolves to an object containing amount1 and amount2
*/
static async calculateDepositForShares(shares, vaultAddress, providerOrSigner) {
const vaultContract = new ethers_1.ethers.Contract(vaultAddress, Vault_json_1.default.abi, providerOrSigner);
const [amount1, amount2] = await vaultContract.previewMint(shares, {
from: ethers_1.ZeroAddress,
});
return { amount1, amount2 };
}
/**
* Calculate the amount of tokens to be received for a given number of shares to withdraw
* @param shares The number of shares to burn
* @param vaultAddress The address of the vault contract
* @param providerOrSigner The provider or signer to use for the transaction
* @returns A promise that resolves to an object containing amount1 and amount2
*/
static async calculateWithdrawForShares(shares, vaultAddress, providerOrSigner) {
const vaultContract = new ethers_1.ethers.Contract(vaultAddress, Vault_json_1.default.abi, providerOrSigner);
const [amount1, amount2] = await vaultContract.previewRedeem(shares, {
from: ethers_1.ZeroAddress,
});
return { amount1, amount2 };
}
/**
* Calculate the number of shares to be received for a given deposit of tokens
* @param amount1 The amount of token1 to deposit
* @param amount2 The amount of token2 to deposit
* @param vaultAddress The address of the vault contract
* @param providerOrSigner The provider or signer to use for the transaction
* @returns A promise that resolves to the number of shares
*/
static async calculateSharesForDeposit(amount1, amount2, vaultAddress, providerOrSigner) {
const vaultContract = new ethers_1.ethers.Contract(vaultAddress, Vault_json_1.default.abi, providerOrSigner);
return await vaultContract.previewDeposit(amount1, amount2, {
from: ethers_1.ZeroAddress,
});
}
/**
* Calculate the amount of token2 needed for a specific amount of token1 based on current price
* @param amount1 The amount of token1
* @param marketAddress The address of the market contract
* @param providerOrSigner The provider or signer to use for the transaction
* @returns A promise that resolves to the amount of token2 needed
*/
static async calculateAmount2ForAmount1(amount1, marketAddress, marketParams, providerOrSigner) {
const vaultParams = await params_1.VaultParamFetcher.getVaultParams(providerOrSigner, marketAddress);
const price = vaultParams.vaultBestAsk;
const token1Decimals = await (0, utils_1.getTokenDecimals)(marketParams.baseAssetAddress, providerOrSigner);
const token2Decimals = await (0, utils_1.getTokenDecimals)(marketParams.quoteAssetAddress, providerOrSigner);
//amount2 = (amount1 * price * 10^token2Decimals) / (10^token1Decimals * 10^18)
return ((amount1 * BigInt(price) * BigInt((0, ethers_1.parseUnits)('1', token2Decimals))) /
(BigInt((0, ethers_1.parseUnits)('1', token1Decimals)) * BigInt((0, ethers_1.parseUnits)('1', 18))));
}
/**
* Calculate the amount of token1 needed for a specific amount of token2 based on current price
* @param amount2 The amount of token2
* @param marketAddress The address of the market contract
* @param providerOrSigner The provider or signer to use for the transaction
* @returns A promise that resolves to the amount of token1 needed
*/
static async calculateAmount1ForAmount2(amount2, marketAddress, marketParams, providerOrSigner) {
const vaultParams = await params_1.VaultParamFetcher.getVaultParams(providerOrSigner, marketAddress);
const price = vaultParams.vaultBestAsk;
const token1Decimals = await (0, utils_1.getTokenDecimals)(marketParams.baseAssetAddress, providerOrSigner);
const token2Decimals = await (0, utils_1.getTokenDecimals)(marketParams.quoteAssetAddress, providerOrSigner);
//amount1 = (amount2 * 10^token1Decimals * 10^18) / (price * 10^token2Decimals)
return ((amount2 * BigInt((0, ethers_1.parseUnits)('1', token1Decimals)) * BigInt((0, ethers_1.parseUnits)('1', 18))) /
(BigInt(price) * BigInt((0, ethers_1.parseUnits)('1', token2Decimals))));
}
/**
* Deposit tokens into the vault based on the number of shares to mint
* @param shares The number of shares to mint
* @param marketAddress The address of the market contract
* @param vaultAddress The address of the vault contract
* @param signer The signer to use for the transaction
* @param shouldApprove Whether to approve the tokens before depositing
* @returns A promise that resolves to the transaction receipt
*/
static async depositBasedOnShares(shares, marketParams, vaultAddress, signer, shouldApprove = false) {
const vaultContract = new ethers_1.ethers.Contract(vaultAddress, Vault_json_1.default.abi, signer);
const { amount1, amount2 } = await this.calculateDepositForShares(shares, vaultAddress, signer);
const token1Address = marketParams.baseAssetAddress;
const token2Address = marketParams.quoteAssetAddress;
let overrides = {};
if (token1Address === ethers_1.ZeroAddress) {
overrides = { value: amount1 };
}
else if (shouldApprove) {
const tokenContract = new ethers_1.ethers.Contract(token1Address, IERC20_json_1.default.abi, signer);
await (0, utils_1.approveToken)(tokenContract, vaultAddress, amount1, signer);
}
if (token2Address === ethers_1.ZeroAddress) {
overrides = { value: amount2 };
}
else if (shouldApprove) {
const tokenContract = new ethers_1.ethers.Contract(token2Address, IERC20_json_1.default.abi, signer);
await (0, utils_1.approveToken)(tokenContract, vaultAddress, amount2, signer);
}
const tx = await vaultContract.mint(shares, await signer.getAddress(), overrides);
const receipt = await tx.wait();
if (!receipt) {
throw new Error('Transaction failed');
}
return receipt;
}
/**
* Withdraw tokens from the vault based on the number of shares to burn
* @param shares The number of shares to burn
* @param vaultAddress The address of the vault contract
* @param signer The signer to use for the transaction
* @returns A promise that resolves to the transaction receipt
*/
static async withdrawBasedOnShares(shares, vaultAddress, signer) {
const vaultContract = new ethers_1.ethers.Contract(vaultAddress, Vault_json_1.default.abi, signer);
const tx = await vaultContract.redeem(shares, await signer.getAddress(), await signer.getAddress());
const receipt = await tx.wait();
if (!receipt) {
throw new Error('Transaction failed');
}
return receipt;
}
/**
* Deposit tokens into the vault with given amounts of token1 and token2
* @param amount1 The amount of token1 to deposit
* @param amount2 The amount of token2 to deposit
* @param marketAddress The address of the market contract
* @param vaultAddress The address of the vault contract
* @param signer The signer to use for the transaction
* @param shouldApprove Whether to approve the tokens before depositing
* @returns A promise that resolves to the transaction receipt
*/
static async depositWithAmounts(amount1, amount2, baseAssetAddress, quoteAssetAddress, vaultAddress, signer, shouldApprove = false) {
const vaultContract = new ethers_1.ethers.Contract(vaultAddress, Vault_json_1.default.abi, signer);
let overrides = {};
if (baseAssetAddress === ethers_1.ZeroAddress) {
overrides.value = amount1;
}
else if (shouldApprove) {
const tokenContract = new ethers_1.ethers.Contract(baseAssetAddress, IERC20_json_1.default.abi, signer);
await (0, utils_1.approveToken)(tokenContract, vaultAddress, amount1, signer);
}
if (quoteAssetAddress === ethers_1.ZeroAddress) {
overrides.value = amount2;
}
else if (shouldApprove) {
const tokenContract = new ethers_1.ethers.Contract(quoteAssetAddress, IERC20_json_1.default.abi, signer);
await (0, utils_1.approveToken)(tokenContract, vaultAddress, amount2, signer);
}
const tx = await vaultContract.deposit(amount1, amount2, await signer.getAddress(), overrides);
const receipt = await tx.wait();
if (!receipt) {
throw new Error('Transaction failed');
}
return receipt;
}
static async constructDepositTransaction(amount1, amount2, baseAssetAddress, quoteAssetAddress, vaultAddress, signer, txOptions) {
const address = await signer.getAddress();
const vaultInterface = new ethers_1.ethers.Interface(Vault_json_1.default.abi);
const data = vaultInterface.encodeFunctionData('deposit', [amount1, amount2, address]);
// Calculate the total value for native token deposits
const txValue = baseAssetAddress === ethers_1.ZeroAddress ? amount1 : quoteAssetAddress === ethers_1.ZeroAddress ? amount2 : BigInt(0);
return (0, txConfig_1.default)({
to: vaultAddress,
from: address,
data,
value: txValue,
txOptions,
signer,
});
}
static async constructWithdrawTransaction(shares, vaultAddress, signer, txOptions) {
const vaultInterface = new ethers_1.ethers.Interface(Vault_json_1.default.abi);
const fromAddress = await signer.getAddress();
const data = vaultInterface.encodeFunctionData('withdraw', [shares, fromAddress, fromAddress]);
return (0, txConfig_1.default)({
to: vaultAddress,
from: fromAddress,
data,
txOptions,
signer,
});
}
}
exports.Vault = Vault;
//# sourceMappingURL=vault.js.map