Skip to content

Commit

Permalink
Merge pull request #246 from paltalabs/fix/balancesReadingSubmitting
Browse files Browse the repository at this point in the history
🩹 Fix blance reading submitting tx
  • Loading branch information
chopan123 authored Dec 2, 2024
2 parents 437d309 + 82b6939 commit 6a91a78
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 34 deletions.
6 changes: 4 additions & 2 deletions apps/contracts/src/tests/strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
129 changes: 127 additions & 2 deletions apps/contracts/src/tests/testOnlyVault.ts
Original file line number Diff line number Diff line change
@@ -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);
18 changes: 8 additions & 10 deletions apps/contracts/src/tests/testTwoStrategiesVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -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);
Expand All @@ -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[] = [
Expand All @@ -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
Expand Down Expand Up @@ -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: {
Expand Down
30 changes: 10 additions & 20 deletions apps/contracts/src/tests/vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -184,19 +185,19 @@ export async function withdrawFromVault(deployedVault: string, withdrawAmount: n
*/
export async function fetchCurrentIdleFunds(deployedVault: string, user: Keypair): Promise<Map<Address, bigint>> {
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,
}));
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 6a91a78

Please sign in to comment.