Skip to content

Commit

Permalink
feat: ⚡ update the vesting function and integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
sadiabbasi committed Dec 11, 2024
1 parent 584b6bd commit afdd74e
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 35 deletions.
64 changes: 48 additions & 16 deletions src/sdk/services/blockchain/contracts/VestingContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,15 +340,39 @@ export class VestingContract {
return vestingCategory;
}

async getUnlockableBalance(
account: NameType
): Promise<{ unlockable: number; locked: number; totalVested: number }> {
getVestingPeriod(categoryId: number): string {
const vestingCategory = vestingCategories.get(categoryId);

if (!vestingCategory) {
throw new Error(`Vesting category ${categoryId} not found`);
}

const vestingPeriod = vestingCategory.vestingPeriod;

// Convert to seconds for categories 999 and 998, otherwise to years
if (categoryId === 999 || categoryId === 998) {
return `${(vestingPeriod / MICROSECONDS_PER_SECOND).toFixed(2)}`;
} else {
return `${(vestingPeriod / MICROSECONDS_PER_DAY).toFixed(2)}`;
}
}

async getVestingAllocations(account: NameType): Promise<{
totalAllocation: number;
unlockable: number;
allocationsDetails: {
totalAllocation: number;
locked: number;
vestingStart: Date;
vestingPeriod: string;
unlockAtVestingStart: number;
}[];
}> {
const allocations = await this.getAllocations(account); // Fetch all allocations for the account
let totalUnlockable = 0;
let totalLocked = 0;
let totalVested = 0;

let totalAllocation = 0;
const currentTime = new Date();
const allocationsDetails = [];

for (const allocation of allocations) {
const tokensAllocated = parseFloat(allocation.tokens_allocated.split(' ')[0]);
Expand All @@ -365,15 +389,15 @@ export class VestingContract {
// Get the vesting category for `tge_unlock` details
const vestingCategory = this.getVestingCategory(allocation.vesting_category_type);

if (currentTime >= cliffEnd) {
let claimable = 0;
let claimable = 0;

if (currentTime >= cliffEnd) {
if (currentTime >= vestingEnd) {
// Vesting period complete, all tokens are unlockable
claimable = tokensAllocated;
} else {
// Calculate the percentage of the vesting period that has passed
const timeSinceVestingStart = (currentTime.getTime() - vestingStart.getTime()) / 1000; // Convert ms to seconds
const timeSinceVestingStart = (currentTime.getTime() - vestingStart.getTime()) / 1000;
const vestingDuration = (vestingEnd.getTime() - vestingStart.getTime()) / 1000;
const vestingProgress = Math.min(timeSinceVestingStart / vestingDuration, 1.0); // Ensure it doesn't exceed 100%

Expand All @@ -385,19 +409,27 @@ export class VestingContract {

// Subtract already claimed tokens
totalUnlockable += claimable - tokensClaimed;
totalLocked += tokensAllocated - claimable;
} else {
// All tokens are locked if cliff period hasn't ended
totalLocked += tokensAllocated;
}

totalVested += tokensAllocated;
const locked = tokensAllocated * (1 - vestingCategory.tgeUnlock) * 0.3; // Assuming "30% of total" locked
const unlockAtVestingStart = tokensAllocated * vestingCategory.tgeUnlock;

totalAllocation += tokensAllocated;

// Add allocation details
allocationsDetails.push({
totalAllocation: tokensAllocated,
locked,
vestingStart,
unlockAtVestingStart,
vestingPeriod: this.getVestingPeriod(allocation.vesting_category_type),
});
}

return {
totalAllocation,
unlockable: totalUnlockable,
locked: totalLocked,
totalVested: totalVested,
allocationsDetails,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -713,43 +713,65 @@ describe('VestingContract class', () => {
}
});

test('Successfully get unlockable, locked, and total vested balance', async () => {
expect.assertions(11);

test('Successfully get unlockable, locked, and total allocations', async () => {
expect.assertions(22);
// Assign tokens to the account with a specific vesting category
const trx = await vestingContract.assignTokens('coinsale.tmy', accountName, '2.000000 LEOS', 999, signer);

expect(trx.processed.receipt.status).toBe('executed');

// Check balances before cliff period ends
let balances = await vestingContract.getUnlockableBalance(accountName);
let balances = await vestingContract.getVestingAllocations(accountName);

expect(balances.totalAllocation).toBe(2);
expect(balances.unlockable).toBe(0);
expect(balances.locked).toBe(2);
expect(balances.totalVested).toBe(2);

expect(balances.allocationsDetails.length).toBe(1);
expect(balances.allocationsDetails[0].totalAllocation).toBe(2);
expect(balances.allocationsDetails[0].locked).toBe(2);
expect(balances.allocationsDetails[0].unlockAtVestingStart).toBe(0);

// Wait until after the cliff period ends
const allocations = await vestingContract.getAllocations(accountName);
const vestingPeriod = VestingContract.calculateVestingPeriod(settings, allocations[0]);

await sleepUntil(addSeconds(vestingPeriod.cliffEnd, 1));

// Check balances during vesting period
balances = await vestingContract.getUnlockableBalance(accountName);
balances = await vestingContract.getVestingAllocations(accountName);
expect(balances.totalAllocation).toBe(2);
expect(balances.unlockable).toBeGreaterThan(0);
expect(balances.unlockable).toBeLessThan(2);
expect(balances.locked).toBeLessThan(2);
expect(balances.totalVested).toBe(2);


// Wait until after the vesting period ends
await sleepUntil(addSeconds(vestingPeriod.vestingEnd, 1));

// Check balances after vesting period ends
balances = await vestingContract.getUnlockableBalance(accountName);
balances = await vestingContract.getVestingAllocations(accountName);
expect(balances.totalAllocation).toBe(2);
expect(balances.unlockable).toBe(2);
expect(balances.locked).toBe(0);
expect(balances.totalVested).toBe(2);
});
expect(balances.allocationsDetails[0].totalAllocation).toBe(2);
expect(balances.allocationsDetails[0].locked).toBe(0);
expect(balances.allocationsDetails[0].unlockAtVestingStart).toBe(0);

// Withdraw all unlockable tokens
await vestingContract.withdraw(accountName, accountSigner);

// Check balances after withdrawal
balances = await vestingContract.getVestingAllocations(accountName);
expect(balances.totalAllocation).toBe(2);
expect(balances.unlockable).toBe(0);
expect(balances.allocationsDetails[0].totalAllocation).toBe(2);
expect(balances.allocationsDetails[0].locked).toBe(0);
expect(balances.allocationsDetails[0].unlockAtVestingStart).toBe(0);

const trx2 = await vestingContract.assignTokens('coinsale.tmy', accountName, '2.000000 LEOS', 999, signer);

expect(trx2.processed.receipt.status).toBe('executed');
balances = await vestingContract.getVestingAllocations(accountName);
expect(balances.allocationsDetails.length).toBe(2);

});

});

Expand Down

0 comments on commit afdd74e

Please sign in to comment.