Skip to content
This repository has been archived by the owner on Jun 28, 2024. It is now read-only.

[WIP] Staking contracts added #22

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
6 changes: 5 additions & 1 deletion src/eulerAbis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import swapHubJson from "@eulerxyz/euler-interfaces/abis/modules/SwapHub.json";
import eulStakesJson from "@eulerxyz/euler-interfaces/abis/mining/EulStakes.json";
import eulDistributorJson from "@eulerxyz/euler-interfaces/abis/mining/EulDistributor.json";
import eulerGeneralViewJson from "@eulerxyz/euler-interfaces/abis/views/EulerGeneralView.json";
import rewardsDistributionJson from "@eulerxyz/euler-interfaces/abis/staking/RewardsDistribution.json";
import stakingRewardsJson from "@eulerxyz/euler-interfaces/abis/staking/StakingRewards.json";

export const eul = eulJson.abi;
export const euler = eulerJson.abi;
Expand All @@ -24,4 +26,6 @@ export const swap = swapJson.abi;
export const swapHub = swapHubJson.abi;
export const eulStakes = eulStakesJson.abi;
export const eulDistributor = eulDistributorJson.abi;
export const eulerGeneralView = eulerGeneralViewJson.abi;
export const eulerGeneralView = eulerGeneralViewJson.abi;
export const rewardsDistribution = rewardsDistributionJson.abi;
export const stakingRewards = stakingRewardsJson.abi;
87 changes: 68 additions & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
TokenType,
UnderlyingToTokenCache,
SimulateBatchOpts,
StakingConfig,
} from "./types";
import {
EulContract,
Expand All @@ -45,25 +46,35 @@ import {
EulerGeneralViewContract,
} from "./eulerTypes";

const WETH_MAINNET = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
const WETH_ROPSTEN = "0xc778417e063141139fce010982780140aa0cd5ab";
const WETH_GOERLI = "0xa3401DFdBd584E918f59fD1C3a558467E373DacC";

const DEFAULT_PERMIT_DEADLINE_SECONDS = 60 * 60;
const LIQUIDITY_CHECK_ERRORS = [
"e/collateral-violation",
"e/borrow-isolation-violation",
];

const EULER_ADDRESSES: { [key: number]: any } = {
1: addressesMainnet,
3: addressesRopsten,
5: addressesGoerli,
}

const REFERENCE_ASSET: { [key: number]: string } = {
1: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
3: "0xc778417e063141139fce010982780140aa0cd5ab",
5: "0xa3401DFdBd584E918f59fD1C3a558467E373DacC",
}

class Euler {
readonly chainId: number;
readonly contracts: Contracts;
readonly abis: { [contractName: string]: ContractInterface };
readonly addresses: EulerAddresses;
readonly eulTokenConfig: TokenWithPermit;
readonly stakingConfig?: StakingConfig;
readonly referenceAsset: string;

private _tokenCache: TokenCache;
private _contractCache: { [key: string]: Contract } = {};
private _underlyingToTokenCache: UnderlyingToTokenCache;
private _signerOrProvider?: SignerOrProvider;

Expand All @@ -79,6 +90,7 @@ class Euler {
[TokenType.PToken]: {},
[TokenType.ERC20]: {},
};
this._contractCache = {};
this._underlyingToTokenCache = {};
this._signerOrProvider = signerOrProvider;

Expand All @@ -95,26 +107,31 @@ class Euler {
this.addresses = networkConfig.addresses;
this.referenceAsset = networkConfig.referenceAsset;
this.eulTokenConfig = networkConfig.eul;
} else if (this.chainId === 1) {
const { eul: eulConfig, ...addresses } = addressesMainnet;
this.eulTokenConfig = eulConfig;
this.addresses = addresses as any;
this.stakingConfig = networkConfig.staking;
} else {
if (!EULER_ADDRESSES[this.chainId]) {
throw new Error("Unknown configuration");
}

this.referenceAsset = WETH_MAINNET;
} else if (this.chainId === 3) {
const { eul: eulConfig, ...addresses } = addressesRopsten;
this.eulTokenConfig = eulConfig;
this.addresses = addresses as any;
const {
eul: eulConfig,
staking: stakingConfig,
...addresses
} = EULER_ADDRESSES[this.chainId];

this.referenceAsset = WETH_ROPSTEN;
} else if (this.chainId === 5) {
const { eul: eulConfig, ...addresses } = addressesGoerli;
this.eulTokenConfig = eulConfig;
this.stakingConfig = stakingConfig;
this.addresses = addresses as any;
this.referenceAsset = REFERENCE_ASSET[this.chainId];
}

this.referenceAsset = WETH_GOERLI;
} else {
throw new Error("Unknown configuration");
// make sure all addresses are lowercase
if (this.stakingConfig?.stakingRewards) {
this.stakingConfig.stakingRewards = Object.keys(this.stakingConfig.stakingRewards)
.reduce((acc: { [key: string]: string }, key: string) => ({
...acc,
[key.toLowerCase()]: (this.stakingConfig?.stakingRewards?.[key] || "").toLowerCase(),
}), {});
}

this.abis = eulerAbis;
Expand Down Expand Up @@ -199,6 +216,13 @@ class Euler {
return this._getToken(address, TokenType.PToken) as PTokenContract;
}

stakingRewards(eTokenAddress: string) {
const address = this.stakingConfig?.stakingRewards?.[eTokenAddress] || "";
validateAddress(eTokenAddress);
validateAddress(address);
return this._getContract(address, this.abis.stakingRewards) as Contract;
}

eTokenOf(underlyingAddress: string) {
validateAddress(underlyingAddress);
return this._getTokenOf(
Expand Down Expand Up @@ -478,6 +502,22 @@ class Euler {
return this[type](this._underlyingToTokenCache[underlyingAddress][type]);
}

private _getContract(address: string, abi: ethers.ContractInterface) {
if (!this._contractCache[address]) {
this._contractCache[address] = new ethers.Contract(
address,
abi,
typeof this._signerOrProvider === "string"
? undefined
: this._signerOrProvider
);
}

return this._signerOrProvider
? this._contractCache[address].connect(this._signerOrProvider)
: this._contractCache[address];
}

private _batchItemToContract(item: BatchItem) {
if (item.contract instanceof ethers.Contract) return item.contract;
if (this.contracts[item.contract]) return this.contracts[item.contract];
Expand Down Expand Up @@ -523,6 +563,15 @@ class Euler {
? undefined
: this._signerOrProvider
) as EulContract,
...this.stakingConfig?.rewardsDistribution && {
rewardsDistribution: new Contract(
this.stakingConfig.rewardsDistribution,
this.abis.rewardsDistribution,
typeof this._signerOrProvider === "string"
? undefined
: this._signerOrProvider
) as Contract,
},
};
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ export type EulerAddresses = {
[contractName: string]: string;
};

export type StakingConfig = {
rewardsDistribution?: string;
stakingRewards?: {[key: string]: string};
}

export type EulerABIs = {
euler: ContractInterface;
exec: ContractInterface;
Expand All @@ -92,6 +97,7 @@ export type NetworkConfig = {
addresses: EulerAddresses;
referenceAsset: string;
eul: TokenWithPermit;
staking?: StakingConfig;
};

export type SignerOrProvider = providers.Provider | Signer | string;
Expand Down