Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add in GhoTokenService for totalSupply & facilitator info #444

Merged
merged 3 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ describe('GhoDiscountRateStrategyService', () => {

describe('Create new GhoDiscountRateStrategyService', () => {
it('Expects to be initialized correctly', () => {
// Create instance
const instance = new GhoDiscountRateStrategyService(
correctProvider,
DISCOUNT_RATE_STRATEGY_ADDRESS,
);

// Assert it
expect(instance).toBeInstanceOf(GhoDiscountRateStrategyService);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import BaseService from '../commons/BaseService';
import { GhoDiscountRateStrategy__factory } from './typechain/GhoDiscountRateStrategy__factory';
import type { IGhoDiscountRateStrategy } from './typechain/IGhoDiscountRateStrategy';

export interface GhoDiscountRateServiceInterface {
interface IGhoDiscountRateStrategyService {
calculateDiscountRate: (
ghoDebtTokenBalance: BigNumberish,
skAaveBalance: BigNumberish,
Expand All @@ -16,7 +16,7 @@ export interface GhoDiscountRateServiceInterface {
*/
export class GhoDiscountRateStrategyService
extends BaseService<IGhoDiscountRateStrategy>
implements GhoDiscountRateServiceInterface
implements IGhoDiscountRateStrategyService
{
readonly ghoDiscountRateStrategyAddress: string;

Expand Down
150 changes: 150 additions & 0 deletions packages/contract-helpers/src/gho/GhoTokenService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { constants, BigNumber, providers } from 'ethers';
import { valueToWei } from '../commons/utils';
import { GhoTokenService } from './GhoTokenService';
import { GhoToken } from './typechain/GhoToken';
import { GhoToken__factory } from './typechain/GhoToken__factory';
import { IGhoToken } from './typechain/IGhoToken';

jest.mock('../commons/gasStation', () => {
return {
__esModule: true,
estimateGasByNetwork: jest
.fn()
.mockImplementation(async () => Promise.resolve(BigNumber.from(1))),
estimateGas: jest.fn(async () => Promise.resolve(BigNumber.from(1))),
};
});

// Helper for contract call arguments
const convertToBN = (n: string) => valueToWei(n, 18);

describe('GhoTokenService', () => {
const GHO_TOKEN_ADDRESS = constants.AddressZero;
const correctProvider: providers.Provider = new providers.JsonRpcProvider();

// Mocking
jest
.spyOn(correctProvider, 'getGasPrice')
.mockImplementation(async () => Promise.resolve(BigNumber.from(1)));

afterEach(() => jest.clearAllMocks());

describe('Create new GhoTokenService', () => {
it('Expects to be initialized correctly', () => {
// Create Instance
const instance = new GhoTokenService(correctProvider, GHO_TOKEN_ADDRESS);

// Assert it
expect(instance).toBeInstanceOf(GhoTokenService);
});
});

describe('totalSupply', () => {
it('should return the total supply of GHO tokens', async () => {
// Create Instance
const contract = new GhoTokenService(correctProvider, GHO_TOKEN_ADDRESS);

// Setup
const mockTotalSupply = convertToBN('10000000'); // 10M

// Mock it
const spy = jest.spyOn(GhoToken__factory, 'connect').mockReturnValue({
totalSupply: async () => Promise.resolve(mockTotalSupply),
} as unknown as GhoToken);

// Call it
const result = await contract.totalSupply();

// Assert it
expect(spy).toHaveBeenCalled();
expect(spy).toBeCalledTimes(1);
expect(result).toEqual(mockTotalSupply);
});
});

describe('getFacilitatorsList', () => {
it('should return the list of facilitators as an array of addresses', async () => {
// Create instance
const contract = new GhoTokenService(correctProvider, GHO_TOKEN_ADDRESS);

// Setup
const faciliatorAddress1: string = constants.AddressZero;
const faciliatorAddress2: string = constants.AddressZero;
const mockFacilitatorsList: string[] = [
faciliatorAddress1,
faciliatorAddress2,
];

// Mock it
const spy = jest.spyOn(GhoToken__factory, 'connect').mockReturnValue({
getFacilitatorsList: async () => Promise.resolve(mockFacilitatorsList),
} as unknown as GhoToken);

// Call it
const result = await contract.getFacilitatorsList();

// Assert it
expect(spy).toHaveBeenCalled();
expect(spy).toBeCalledTimes(1);
expect(result).toEqual(mockFacilitatorsList);
});
});

describe('getFacilitator', () => {
it('should return the facilitator instance for the provided facilitator address', async () => {
// Create instance
const contract = new GhoTokenService(correctProvider, GHO_TOKEN_ADDRESS);

// Setup
const faciliatorAddress: string = constants.AddressZero;
const mockBucket: IGhoToken.BucketStruct = {
maxCapacity: convertToBN('1000'),
level: convertToBN('500'),
};
const mockFacilitator: IGhoToken.FacilitatorStruct = {
bucket: mockBucket,
label: 'Aave Facilitator',
};

// Mock it
const spy = jest.spyOn(GhoToken__factory, 'connect').mockReturnValue({
getFacilitator: async () => Promise.resolve(mockFacilitator),
} as unknown as GhoToken);

// Call it
const result = await contract.getFacilitator(faciliatorAddress);

// Assert it
expect(spy).toHaveBeenCalled();
expect(spy).toBeCalledTimes(1);
expect(result).toEqual(mockFacilitator);
});
});

describe('getFacilitatorBucket', () => {
it('should return the bucket instance for the provided facilitator address', async () => {
// Create instance
const contract = new GhoTokenService(correctProvider, GHO_TOKEN_ADDRESS);

// Setup
const faciliatorAddress: string = constants.AddressZero;
const mockBucket: IGhoToken.BucketStruct = {
maxCapacity: convertToBN('1000'),
level: convertToBN('500'),
};

// Mock it
const spy = jest.spyOn(GhoToken__factory, 'connect').mockReturnValue({
getFacilitatorBucket: async () => Promise.resolve(mockBucket),
} as unknown as GhoToken);

// Call it
const result = await contract.getFacilitatorBucket(faciliatorAddress);

// Assert it
expect(spy).toHaveBeenCalled();
expect(spy).toBeCalledTimes(1);
expect(result).toEqual(mockBucket);
});
});
});
75 changes: 75 additions & 0 deletions packages/contract-helpers/src/gho/GhoTokenService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { BigNumber, providers } from 'ethers';
import BaseService from '../commons/BaseService';
import type { GhoToken } from './typechain/GhoToken';
import { GhoToken__factory } from './typechain/GhoToken__factory';
import type { IGhoToken } from './typechain/IGhoToken';

interface IGhoTokenService {
totalSupply: () => Promise<BigNumber>;
getFacilitatorsList: () => Promise<string[]>;
getFacilitator: (
facilitatorAddress: string,
) => Promise<IGhoToken.FacilitatorStruct>;
getFacilitatorBucket: (
facilitatorAddress: string,
) => Promise<IGhoToken.BucketStruct>;
}

/**
* The service for interacting with the GhoToken.sol smart contract.
* This contract controls operations minting & burning the native GHO token as well as facilitator management.
* https://github.com/aave/gho/blob/main/src/contracts/gho/GhoToken.sol
*/
export class GhoTokenService
extends BaseService<GhoToken>
implements IGhoTokenService
{
readonly ghoTokenAddress: string;

constructor(provider: providers.Provider, ghoTokenAddress: string) {
super(provider, GhoToken__factory);
this.ghoTokenAddress = ghoTokenAddress;
}

/**
* Gets the total supply for the GHO token. This is the sum of all facilitators' current bucket levels
* @returns - A BigNumber representing the total supply of GHO
*/
public async totalSupply() {
const contract = this.getContractInstance(this.ghoTokenAddress);
const result = await contract.totalSupply();
return result;
}

/**
* Gets the full list of facilitators for the GHO token
* @returns - An array of facilitator addresses, which can be used for querying in more detail
*/
public async getFacilitatorsList() {
const contract = this.getContractInstance(this.ghoTokenAddress);
const result = await contract.getFacilitatorsList();
return result;
}

/**
* Gets the instance for a given facilitator
* @param facilitatorAddress - The address for the currently deployed contract for the facilitator being queried
* @returns - The instance of the facilitator, which contains `bucket` and `label` fields
*/
public async getFacilitator(facilitatorAddress: string) {
const contract = this.getContractInstance(this.ghoTokenAddress);
const result = await contract.getFacilitator(facilitatorAddress);
return result;
}

/**
* Gets the bucket instance for a given facilitator
* @param facilitatorAddress - The address for the currently deployed contract for the facilitator being queried
* @returns - The instance of the facilitator bucket, which contains `maxCapacity` and `level` fields
*/
public async getFacilitatorBucket(facilitatorAddress: string) {
const contract = this.getContractInstance(this.ghoTokenAddress);
const result = await contract.getFacilitatorBucket(facilitatorAddress);
return result;
}
}
Loading