diff --git a/apps/contracts/src/tests/strategy.ts b/apps/contracts/src/tests/strategy.ts index 18c86af..d916404 100644 --- a/apps/contracts/src/tests/strategy.ts +++ b/apps/contracts/src/tests/strategy.ts @@ -29,11 +29,13 @@ export async function checkUserBalance(contractAddress: string, userPublicKey: s contractAddress, methodName, [userAddress], - source ? source : Keypair.random() + source ? source : Keypair.random(), + true ); // Convert the result to a native JavaScript number - const balance = scValToNative(result.returnValue) as number; + console.log(result.result.retval) + const balance = scValToNative(result.result.retval) as number; console.log(`Balance for user ${userPublicKey}:`, balance); return balance; diff --git a/apps/contracts/src/tests/testOnlyVault.ts b/apps/contracts/src/tests/testOnlyVault.ts index 3975d07..244a806 100644 --- a/apps/contracts/src/tests/testOnlyVault.ts +++ b/apps/contracts/src/tests/testOnlyVault.ts @@ -1,4 +1,129 @@ -import { depositToVault } from "./vault.js"; +import { + Address, + Asset, + Keypair, + nativeToScVal, + scValToNative, + xdr +} from "@stellar/stellar-sdk"; +import { randomBytes } from "crypto"; +import { AddressBook } from "../utils/address_book.js"; +import { airdropAccount, invokeContract, invokeCustomContract } from "../utils/contract.js"; +import { config } from "../utils/env_config.js"; +import { depositToVault} from "./vault.js"; +import { checkUserBalance } from "./strategy.js"; +const soroswapUSDC = new Address("CAAFIHB4I7WQMJMKC22CZVQNNX7EONWSOMT6SUXK6I3G3F6J4XFRWNDI"); + +const network = process.argv[2]; +const addressBook = AddressBook.loadFromFile(network); +const hodl_strategy = addressBook.getContractId("hodl_strategy"); +const fixed_apr_strategy = addressBook.getContractId("fixed_apr_strategy"); +const xlm: Asset = Asset.native() + +const loadedConfig = config(network); // modify the address to the deployed vault -await depositToVault("CBUTM5B7CG7ISTX5PD5XMDDMSTKFRGVXNKRMZO3TZW5IFGHN5274JJY7", [986754321]); +export async function deployVault(addressBook: AddressBook) { + if (network !== "mainnet") await airdropAccount(loadedConfig.admin); + let account = await loadedConfig.horizonRpc.loadAccount( + loadedConfig.admin.publicKey() + ); + console.log("publicKey", loadedConfig.admin.publicKey()); + let balance = account.balances.filter((item) => item.asset_type === "native"); + console.log("Current Admin account balance:", balance[0].balance); + + console.log("-------------------------------------------------------"); + console.log("Create Vault on Factory"); + console.log("-------------------------------------------------------"); + + console.log("Setting Emergengy Manager, Fee Receiver and Manager accounts"); + const emergencyManager = loadedConfig.getUser("DEFINDEX_EMERGENCY_MANAGER_SECRET_KEY"); + if (network !== "mainnet") await airdropAccount(emergencyManager); + + const feeReceiver = loadedConfig.getUser("DEFINDEX_FEE_RECEIVER_SECRET_KEY"); + if (network !== "mainnet") await airdropAccount(feeReceiver); + + const manager = loadedConfig.getUser("DEFINDEX_MANAGER_SECRET_KEY"); + if (network !== "mainnet") await airdropAccount(manager); + + const assets = [ + { + address: soroswapUSDC, + strategies: [ + { + name: "Hodl Strategy", + address: addressBook.getContractId("hodl_strategy"), + paused: false + } + ] + } + ]; + + const assetAllocations = assets.map((asset) => { + return xdr.ScVal.scvMap([ + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("address"), + val: asset.address.toScVal(), + }), + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("strategies"), + val: xdr.ScVal.scvVec( + asset.strategies.map((strategy) => + xdr.ScVal.scvMap([ + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("address"), + val: new Address(strategy.address).toScVal(), + }), + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("name"), + val: nativeToScVal(strategy.name, { type: "string" }), + }), + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("paused"), + val: nativeToScVal(false, { type: "bool" }), + }), + ]) + ) + ), + }), + ]); + }); + + const createDeFindexParams: xdr.ScVal[] = [ + new Address(emergencyManager.publicKey()).toScVal(), + new Address(feeReceiver.publicKey()).toScVal(), + nativeToScVal(100, { type: "u32" }), + nativeToScVal("HODL FIXED Vault", { type: "string" }), + nativeToScVal("HDFXVLT", { type: "string" }), + new Address(manager.publicKey()).toScVal(), + xdr.ScVal.scvVec(assetAllocations), + nativeToScVal(randomBytes(32)), + ]; + + const result = await invokeContract( + 'defindex_factory', + addressBook, + 'create_defindex_vault', + createDeFindexParams, + loadedConfig.admin + ); + + console.log('🚀 « DeFindex Vault created with address:', scValToNative(result.returnValue)); + return scValToNative(result.returnValue); +} +const testUser = Keypair.random(); +if (network !== "mainnet") await airdropAccount(testUser); +const initialAmount = 10000_0_000_000; + +const mintToken = async () => { + await invokeCustomContract( + soroswapUSDC.toString(), + "mint", + [new Address(testUser.publicKey()).toScVal(), nativeToScVal(initialAmount, { type: "i128" })], + loadedConfig.getUser("SOROSWAP_MINT_SECRET_KEY") + ) +} + +await mintToken(); +const vaultAddress = await deployVault(addressBook); +await depositToVault(vaultAddress, [986754321], testUser); \ No newline at end of file diff --git a/apps/contracts/src/tests/testTwoStrategiesVault.ts b/apps/contracts/src/tests/testTwoStrategiesVault.ts index d8f22be..1d58fb7 100644 --- a/apps/contracts/src/tests/testTwoStrategiesVault.ts +++ b/apps/contracts/src/tests/testTwoStrategiesVault.ts @@ -10,7 +10,8 @@ import { randomBytes } from "crypto"; import { AddressBook } from "../utils/address_book.js"; import { airdropAccount, invokeContract, invokeCustomContract } from "../utils/contract.js"; import { config } from "../utils/env_config.js"; -import { ActionType, AssetInvestmentAllocation, depositToVault, getVaultBalanceInStrategy, Instruction, investVault, rebalanceVault, fetchParsedCurrentIdleFunds, fetchCurrentInvestedFunds } from "./vault.js"; +import { ActionType, AssetInvestmentAllocation, depositToVault, Instruction, investVault, rebalanceVault, fetchParsedCurrentIdleFunds, fetchCurrentInvestedFunds } from "./vault.js"; +import { checkUserBalance } from "./strategy.js"; const soroswapUSDC = new Address("CAAFIHB4I7WQMJMKC22CZVQNNX7EONWSOMT6SUXK6I3G3F6J4XFRWNDI"); @@ -138,7 +139,6 @@ const mintToken = async () => { } await mintToken(); - // Step 1: Deposit to vault and capture initial balances const { user, balanceBefore: depositBalanceBefore, result: depositResult, balanceAfter: depositBalanceAfter, status: depositStatus } = await depositToVault(deployedVault, [initialAmount], testUser); @@ -149,12 +149,11 @@ console.log(" -- ") console.log(" -- ") - const idleFundsAfterDeposit = await fetchParsedCurrentIdleFunds(deployedVault, user); const investedFundsAfterDeposit = await fetchCurrentInvestedFunds(deployedVault, user); -const hodlBalanceBeforeInvest = await getVaultBalanceInStrategy(hodl_strategy, deployedVault, user); -const fixedBalanceBeforeInvest = await getVaultBalanceInStrategy(fixed_apr_strategy, deployedVault, user); +const hodlBalanceBeforeInvest = await checkUserBalance(hodl_strategy, deployedVault, user); +const fixedBalanceBeforeInvest = await checkUserBalance(fixed_apr_strategy, deployedVault, user); // Step 2: Invest in vault idle funds const investParams: AssetInvestmentAllocation[] = [ @@ -180,8 +179,8 @@ console.log('🚀 « investResult:', investResult); const idleFundsAfterInvest = await fetchParsedCurrentIdleFunds(deployedVault, user); const investedFundsAfterInvest = await fetchCurrentInvestedFunds(deployedVault, user); -const afterInvestHodlBalance = await getVaultBalanceInStrategy(hodl_strategy, deployedVault, user); -const afterInvestFixedBalance = await getVaultBalanceInStrategy(fixed_apr_strategy, deployedVault, user); +const afterInvestHodlBalance = await checkUserBalance(hodl_strategy, deployedVault, user); +const afterInvestFixedBalance = await checkUserBalance(fixed_apr_strategy, deployedVault, user); // 10000 USDC -> Total Balance // 1500 USDC -> Hodl Strategy @@ -218,13 +217,12 @@ console.log('🚀 « rebalanceParams:', rebalanceParams); // 3500 USDC -> Idle const rebalanceResult = await rebalanceVault(deployedVault, rebalanceParams, manager); -console.log('🚀 « rebalanceResult:', rebalanceResult) const idleFundsAfterRebalance = await fetchParsedCurrentIdleFunds(deployedVault, user); const investedFundsAfterRebalance = await fetchCurrentInvestedFunds(deployedVault, user); -const afterRebalanceHodlBalance = await getVaultBalanceInStrategy(hodl_strategy, deployedVault, user); -const afterRebalanceFixedBalance = await getVaultBalanceInStrategy(fixed_apr_strategy, deployedVault, user); +const afterRebalanceHodlBalance = await checkUserBalance(hodl_strategy, deployedVault, user); +const afterRebalanceFixedBalance = await checkUserBalance(fixed_apr_strategy, deployedVault, user); console.table({ hodlStrategy: { diff --git a/apps/contracts/src/tests/vault.ts b/apps/contracts/src/tests/vault.ts index 4260782..223385a 100644 --- a/apps/contracts/src/tests/vault.ts +++ b/apps/contracts/src/tests/vault.ts @@ -21,9 +21,10 @@ import { airdropAccount, invokeCustomContract } from "../utils/contract.js"; const network = process.argv[2]; -export async function depositToVault(deployedVault: string, amount: number[], user?: Keypair, ) { +export async function depositToVault(deployedVault: string, amount: number[], user?: Keypair, invest?: boolean) { // Create and fund a new user account if not provided const newUser = user ? user : Keypair.random(); + const investBool = invest ? invest : false; console.log('🚀 ~ depositToVault ~ newUser.publicKey():', newUser.publicKey()); console.log('🚀 ~ depositToVault ~ newUser.secret():', newUser.secret()); @@ -41,7 +42,8 @@ export async function depositToVault(deployedVault: string, amount: number[], us const depositParams: xdr.ScVal[] = [ xdr.ScVal.scvVec(amountsDesired.map((amount) => nativeToScVal(amount, { type: "i128" }))), xdr.ScVal.scvVec(amountsMin.map((min) => nativeToScVal(min, { type: "i128" }))), - (new Address(newUser.publicKey())).toScVal() + (new Address(newUser.publicKey())).toScVal(), + xdr.ScVal.scvBool(investBool) ]; try { @@ -102,7 +104,6 @@ export async function getDfTokenBalance(deployedVault: string, userPublicKey: st source ? source : Keypair.random(), // No specific source is needed as we are just querying the balance true // Set to simulate mode if testing on an uncommitted transaction ); - const balance = scValToNative(result.result.retval) return balance; } catch (error) { @@ -184,19 +185,19 @@ export async function withdrawFromVault(deployedVault: string, withdrawAmount: n */ export async function fetchCurrentIdleFunds(deployedVault: string, user: Keypair): Promise> { try { - const result = await invokeCustomContract(deployedVault, "fetch_current_idle_funds", [], user); - return result.map(scValToNative); // Convert result to native format if needed + const result = await invokeCustomContract(deployedVault, "fetch_current_idle_funds", [], user, false); + const parsedResult = scValToNative(result.returnValue); + return parsedResult; // Convert result to native format if needed } catch (error) { console.error("❌ Failed to fetch current idle funds:", error); throw error; } } -export async function fetchParsedCurrentIdleFunds(deployedVault: string, user: Keypair) { +export async function fetchParsedCurrentIdleFunds(deployedVault: string, user: Keypair): Promise<{ address: string, amount: bigint }[]> { try { - const res = await invokeCustomContract(deployedVault, "fetch_current_idle_funds", [], user); - const funds = scValToNative(res.returnValue); - const mappedFunds = Object.entries(funds).map(([key, value]) => ({ + const res = await fetchCurrentIdleFunds(deployedVault, user); + const mappedFunds = Object.entries(res).map(([key, value]) => ({ address: key, amount: value, })); @@ -453,17 +454,6 @@ function mapSwapDetailsExactOut(details: SwapDetailsExactOut) { ]; } -export async function getVaultBalanceInStrategy(strategyAddress: string, vaultAddress: string, user: Keypair) { - const address = new Address(vaultAddress); - try { - const res = await invokeCustomContract(strategyAddress, "balance",[address.toScVal()],user) - return scValToNative(res.returnValue); - } catch (error) { - console.error('🔴 « error:', error); - return 0; - } - } - export async function fetchCurrentInvestedFunds(deployedVault:string, user:Keypair) { try { const res = await invokeCustomContract(deployedVault, "fetch_current_invested_funds", [], user);