Skip to content

Commit

Permalink
Add guards to make sure teh provider is initialized when required
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielSchiavini committed Sep 17, 2024
1 parent 3219f28 commit 85dab05
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 10 deletions.
7 changes: 7 additions & 0 deletions src/boosting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const getCrv = async (...addresses: string[] | string[][]): Promise<IDict

export const getLockedAmountAndUnlockTime = async (...addresses: string[] | string[][]):
Promise<IDict<{ lockedAmount: string, unlockTime: number }> | { lockedAmount: string, unlockTime: number }> => {
if(!curve.multicallProvider) throw Error("Cannot get lockedAmountAndUnlockTime without a provider");

addresses = _prepareAddresses(addresses);
const veContract = curve.contracts[curve.constants.ALIASES.voting_escrow].multicallContract;
const contractCalls = addresses.map((address: string) => veContract.locked(address));
Expand All @@ -47,6 +49,8 @@ export const getLockedAmountAndUnlockTime = async (...addresses: string[] | stri
}

export const getVeCrv = async (...addresses: string[] | string[][]): Promise<IDict<string> | string> => {
if (!curve.multicallProvider) throw Error("Cannot get veCrv without a provider");

addresses = _prepareAddresses(addresses);

const veContract = curve.contracts[curve.constants.ALIASES.voting_escrow].multicallContract;
Expand All @@ -63,6 +67,8 @@ export const getVeCrv = async (...addresses: string[] | string[][]): Promise<IDi
}

export const getVeCrvPct = async (...addresses: string[] | string[][]): Promise<IDict<string> | string> => {
if (!curve.multicallProvider) throw Error("Cannot get veCrvPct without a provider");

addresses = _prepareAddresses(addresses);

const veContract = curve.contracts[curve.constants.ALIASES.voting_escrow].multicallContract;
Expand Down Expand Up @@ -300,6 +306,7 @@ export const lastBlockSent = async (chainId: IChainId): Promise<number> => {
}

export const blockToSend = async (): Promise<number> => {
if (!curve.provider) throw Error("Cannot get blockToSend without a provider");
if (curve.chainId !== 1) throw Error("blockToSend method is on ethereum network only");
return (await curve.provider.getBlockNumber()) - 128;
}
Expand Down
10 changes: 8 additions & 2 deletions src/curve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ const OLD_CHAINS = [1, 10, 56, 100, 137, 250, 1284, 2222, 8453, 42161, 42220, 43
export type ContractItem = { contract: Contract, multicallContract: MulticallContract, abi: Abi };

class Curve implements ICurve {
provider: ethers.BrowserProvider | ethers.JsonRpcProvider;
multicallProvider: MulticallProvider;
provider: ethers.BrowserProvider | ethers.JsonRpcProvider | null;
multicallProvider: MulticallProvider | null;
signer: ethers.Signer | null;
signerAddress: string;
chainId: IChainId;
Expand All @@ -432,6 +432,7 @@ class Curve implements ICurve {
constantOptions: { gasLimit?: number };
options: { gasPrice?: number | bigint, maxFeePerGas?: number | bigint, maxPriorityFeePerGas?: number | bigint };
L1WeightedGasPrice?: number;
// note: these "constants" are actually modified during runtime
constants: {
NATIVE_TOKEN: { symbol: string, wrappedSymbol: string, address: string, wrappedAddress: string },
NETWORK_NAME: INetworkName,
Expand Down Expand Up @@ -800,6 +801,9 @@ class Curve implements ICurve {
const proxyHandler: ProxyHandler<any> = {
get: function(target: any, name: string) {
if(name === 'contract') {
if (!curveInstance.provider) {
throw Error("Can't init contract without provider");
}
return curveInstance.initContract(target['address'], target['abi'], curveInstance.signer || curveInstance.provider)
} else if(name === 'multicallContract') {
return curveInstance.initMulticallContract(target['address'], target['abi'])
Expand Down Expand Up @@ -1065,6 +1069,7 @@ class Curve implements ICurve {
]
};

// note: these "constants" are actually modified during runtime
getPoolsData = (): IDict<IPoolData> => ({
...this.constants.POOLS_DATA,
...this.constants.FACTORY_POOLS_DATA,
Expand Down Expand Up @@ -1092,6 +1097,7 @@ class Curve implements ICurve {
}

async updateFeeData(): Promise<void> {
if (!this.provider) throw Error("Can't update fee data without provider");
const feeData = await this.provider.getFeeData();
if (feeData.maxFeePerGas === null || feeData.maxPriorityFeePerGas === null) {
delete this.options.maxFeePerGas;
Expand Down
15 changes: 10 additions & 5 deletions src/dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import feeDistributorViewABI from "./constants/abis/fee_distributor_view.json" a

export const crvSupplyStats = async (): Promise<{ circulating: string, locked: string, total: string, veCrv: string, averageLockTime: string }> => {
if (curve.chainId !== 1) throw Error("Ethereum-only method")
if (!curve.multicallProvider) throw Error("Cannot get crvSupplyStats without a provider");

const crvContract = curve.contracts[curve.constants.ALIASES.crv].multicallContract;
const veContract = curve.contracts[curve.constants.ALIASES.voting_escrow].multicallContract;
const csContract = curve.contracts[curve.constants.ALIASES.circulating_supply].multicallContract;
Expand Down Expand Up @@ -54,6 +56,8 @@ export const userCrv = async (address = ""): Promise<string> => {

export const userVeCrv = async (address = ""): Promise<{ veCrv: string, veCrvPct: string, lockedCrv: string, unlockTime: number }> => {
if (curve.chainId !== 1) throw Error("Ethereum-only method")
if (!curve.multicallProvider) throw Error("Cannot get userVeCrv without a provider");

address = _getAddress(address);
const contract = curve.contracts[curve.constants.ALIASES.voting_escrow].multicallContract;
const [_veCrv, _veCrvTotal, _locked] = await curve.multicallProvider.all([
Expand Down Expand Up @@ -214,11 +218,6 @@ export const claimFees = async (address = ""): Promise<string> => {

// ----------------- Gauge weights -----------------

const _extractNetworkFromPoolUrl = (poolUrl: string): string => {
if (!poolUrl) return "unknown";
return poolUrl.split("/")[4]
}

export const getVotingGaugeList = async (): Promise<IVotingGauge[]> => {
if (curve.chainId !== 1) throw Error("Ethereum-only method")
const gaugeData = Object.values(await _getAllGauges());
Expand All @@ -243,6 +242,8 @@ export const getVotingGaugeList = async (): Promise<IVotingGauge[]> => {

export const userGaugeVotes = async (address = ""): Promise<{ gauges: IGaugeUserVote[], powerUsed: string, veCrvUsed: string } > => {
if (curve.chainId !== 1) throw Error("Ethereum-only method")
if (!curve.multicallProvider) throw Error("Cannot get userGaugeVotes without a provider");

address = _getAddress(address);
const gcMulticallContract = curve.contracts[curve.constants.ALIASES.gauge_controller].multicallContract;
const veMulticallContract = curve.contracts[curve.constants.ALIASES.voting_escrow]. multicallContract;
Expand Down Expand Up @@ -296,6 +297,8 @@ export const voteForGaugeNextTime = async (gauge: string): Promise<number> => {

const _voteForGauge = async (gauge: string, power: number | string, estimateGas: boolean): Promise<string | number | number[]> => {
if (curve.chainId !== 1) throw Error("Ethereum-only method")
if (!curve.multicallProvider) throw Error("Cannot voteForGauge without a provider");

const gcContract = curve.contracts[curve.constants.ALIASES.gauge_controller].contract;
const gcMulticallContract = curve.contracts[curve.constants.ALIASES.gauge_controller].multicallContract;
const _power = parseUnits(power, 2);
Expand Down Expand Up @@ -337,6 +340,8 @@ export const getProposal = async (type: "PARAMETER" | "OWNERSHIP", id: number):

export const userProposalVotes = async (address = ""): Promise<IDaoProposalUserListItem[]> => {
if (curve.chainId !== 1) throw Error("Ethereum-only method")
if (!curve.multicallProvider) throw Error("Cannot get userProposalVotes without a provider");

address = _getAddress(address);
const proposalList = await _getDaoProposalList();
const calls = [];
Expand Down
8 changes: 8 additions & 0 deletions src/factory/factory-crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ async function getRecentlyCreatedCryptoPoolId(this: ICurve, swapAddress: string)
}

async function getCryptoFactoryIdsAndSwapAddresses(this: ICurve, fromIdx = 0): Promise<[string[], string[]]> {
if (!this.multicallProvider) throw Error("Cannot get crypto factory ids and swap addresses without a provider");

const factoryContract = this.contracts[this.constants.ALIASES.crypto_factory].contract;
const factoryMulticallContract = this.contracts[this.constants.ALIASES.crypto_factory].multicallContract;

Expand Down Expand Up @@ -51,6 +53,8 @@ function _handleCoinAddresses(this: ICurve, coinAddresses: string[][]): string[]
}

async function _getLpTokenMap(this: ICurve,factorySwapAddresses: string[]): Promise<Record<string, string>> {
if (!this.multicallProvider) throw Error("Cannot get lp token map without a provider");

const factoryMulticallContract = this.contracts[this.constants.ALIASES.crypto_factory].multicallContract;

const LpTokenMap: Record<string, string> = {}
Expand All @@ -71,6 +75,8 @@ async function _getLpTokenMap(this: ICurve,factorySwapAddresses: string[]): Prom
}

async function getPoolsData(this: ICurve, factorySwapAddresses: string[]): Promise<[string[], string[], string[], string[][]]> {
if (!this.multicallProvider) throw Error("Cannot get pools data without a provider");

const factoryMulticallContract = this.contracts[this.constants.ALIASES.crypto_factory].multicallContract;
const isChildGaugeFactoryNull = curve.chainId !== 1 && this.constants.ALIASES.child_gauge_factory === curve.constants.ZERO_ADDRESS;
const isChildGaugeFactoryOldNull = !("child_gauge_factory_old" in this.constants.ALIASES);
Expand Down Expand Up @@ -172,6 +178,8 @@ async function getCoinsData(
existingCoinAddrNameDict: IDict<string>,
existingCoinAddrDecimalsDict: IDict<number>
): Promise<[string[], string[], IDict<string>, IDict<number>]> {
if (!this.multicallProvider) throw Error("Cannot get coins data without a provider");

const flattenedCoinAddresses = Array.from(new Set(deepFlatten(coinAddresses)));
const newCoinAddresses = [];
const coinAddrNamesDict: IDict<string> = {};
Expand Down
8 changes: 7 additions & 1 deletion src/factory/factory-tricrypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ async function getRecentlyCreatedCryptoPoolId(this: ICurve, swapAddress: string)
}

async function getCryptoFactoryIdsAndSwapAddresses(this: ICurve, fromIdx = 0): Promise<[string[], string[]]> {
if (!this.multicallProvider) throw Error("Cannot get crypto factory ids and swap addresses without a provider");

const factoryContract = this.contracts[this.constants.ALIASES.tricrypto_factory].contract;
const factoryMulticallContract = this.contracts[this.constants.ALIASES.tricrypto_factory].multicallContract;

Expand Down Expand Up @@ -51,6 +53,8 @@ function _handleCoinAddresses(this: ICurve, coinAddresses: string[][]): string[]
}

async function getPoolsData(this: ICurve, factorySwapAddresses: string[]): Promise<[string[], string[], string[][], string[]]> {
if (!this.multicallProvider) throw Error("Cannot get pools data without a provider");

const factoryMulticallContract = this.contracts[this.constants.ALIASES.tricrypto_factory].multicallContract;
const isChildGaugeFactoryNull = curve.chainId !== 1 && this.constants.ALIASES.child_gauge_factory === curve.constants.ZERO_ADDRESS;
const isChildGaugeFactoryOldNull = !("child_gauge_factory_old" in this.constants.ALIASES);
Expand Down Expand Up @@ -99,7 +103,7 @@ function setCryptoFactorySwapContracts(this: ICurve, factorySwapAddresses: strin
}

function setCryptoFactoryGaugeContracts(this: ICurve, factoryGaugeAddresses: string[]): void {
factoryGaugeAddresses.filter((addr) => addr !== curve.constants.ZERO_ADDRESS).forEach((addr, i) => {
factoryGaugeAddresses.filter((addr) => addr !== curve.constants.ZERO_ADDRESS).forEach((addr) => {
this.setContract(addr, this.chainId === 1 ? factoryGaugeABI : gaugeChildABI);
});
}
Expand Down Expand Up @@ -140,6 +144,8 @@ async function getCoinsData(
existingCoinAddrNameDict: IDict<string>,
existingCoinAddrDecimalsDict: IDict<number>
): Promise<[string[], string[], IDict<string>, IDict<number>]> {
if (!this.multicallProvider) throw Error("Cannot get coins data without a provider");

const flattenedCoinAddresses = Array.from(new Set(deepFlatten(coinAddresses)));
const newCoinAddresses = [];
const coinAddrNamesDict: IDict<string> = {};
Expand Down
6 changes: 6 additions & 0 deletions src/factory/factory-twocrypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ async function getRecentlyCreatedCryptoPoolId(this: ICurve, swapAddress: string)
}

async function getTwocryptoFactoryIdsAndSwapAddresses(this: ICurve, fromIdx = 0): Promise<[string[], string[]]> {
if (!this.multicallProvider) throw Error("Cannot get twocrypto factory ids and swap addresses without a provider");

const factoryContract = this.contracts[this.constants.ALIASES.twocrypto_factory].contract;
const factoryMulticallContract = this.contracts[this.constants.ALIASES.twocrypto_factory].multicallContract;

Expand Down Expand Up @@ -49,6 +51,8 @@ function _handleCoinAddresses(this: ICurve, coinAddresses: string[][]): string[]
}

async function getPoolsData(this: ICurve, factorySwapAddresses: string[]): Promise<[string[], string[], string[][]]> {
if(!this.multicallProvider) throw Error("Cannot get pools data without a provider");

const factoryMulticallContract = this.contracts[this.constants.ALIASES.twocrypto_factory].multicallContract;
const isChildGaugeFactoryNull = curve.chainId !== 1 && this.constants.ALIASES.child_gauge_factory === curve.constants.ZERO_ADDRESS;
const isChildGaugeFactoryOldNull = !("child_gauge_factory_old" in this.constants.ALIASES);
Expand Down Expand Up @@ -140,6 +144,8 @@ async function getCoinsData(
existingCoinAddrNameDict: IDict<string>,
existingCoinAddrDecimalsDict: IDict<number>
): Promise<[string[], string[], IDict<string>, IDict<number>]> {
if (!this.multicallProvider) throw Error("Cannot get coins data without a provider");

const flattenedCoinAddresses = Array.from(new Set(deepFlatten(coinAddresses)));
const newCoinAddresses = [];
const coinAddrNamesDict: IDict<string> = {};
Expand Down
8 changes: 8 additions & 0 deletions src/factory/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export const BLACK_LIST: { [index: number]: any } = {
const deepFlatten = (arr: any[]): any[] => [].concat(...arr.map((v) => (Array.isArray(v) ? deepFlatten(v) : v)));

export async function getBasePools(this: ICurve, factoryAddress: string, rawSwapAddresses: string[], tmpPools: IPoolDataShort[]): Promise<{ids: string[], addresses: string[]}> {
if(!this.multicallProvider) throw Error("Cannot get base pools without a provider");

const factoryMulticallContract = this.contracts[factoryAddress].multicallContract;

const calls = [];
Expand Down Expand Up @@ -69,6 +71,8 @@ async function getRecentlyCreatedPoolId(this: ICurve, swapAddress: string, facto
}

async function getFactoryIdsAndSwapAddresses(this: ICurve, fromIdx = 0, factoryAddress: string): Promise<[string[], string[]]> {
if(!this.multicallProvider) throw Error("Cannot get factory ids and swap addresses without a provider");

const factoryContract = this.contracts[factoryAddress].contract;
const factoryMulticallContract = this.contracts[factoryAddress].multicallContract;

Expand Down Expand Up @@ -112,6 +116,8 @@ function _handleCoinAddresses(this: ICurve, coinAddresses: string[][]): string[]
}

async function getPoolsData(this: ICurve, factorySwapAddresses: string[], factoryAddress: string): Promise<[string[], string[], string[], REFERENCE_ASSET[], string[], string[], boolean[], string[][]]> {
if (!this.multicallProvider) throw Error("Cannot get pools data without a provider");

const factoryMulticallContract = this.contracts[factoryAddress].multicallContract;
const isChildGaugeFactoryNull = curve.chainId !== 1 && this.constants.ALIASES.child_gauge_factory === curve.constants.ZERO_ADDRESS;
const isChildGaugeFactoryOldNull = !("child_gauge_factory_old" in this.constants.ALIASES);
Expand Down Expand Up @@ -211,6 +217,8 @@ async function getCoinsData(
existingCoinAddrNameDict: IDict<string>,
existingCoinAddrDecimalsDict: IDict<number>
): Promise<[IDict<string>, IDict<number>]> {
if(!this.multicallProvider) throw Error("Cannot get coins data without a provider");

const flattenedCoinAddresses = Array.from(new Set(deepFlatten(coinAddresses)));
const newCoinAddresses = [];
const coinAddrNamesDict: IDict<string> = {};
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ export interface IPoolData {
}

export interface ICurve {
provider: ethers.BrowserProvider | ethers.JsonRpcProvider,
multicallProvider: MulticallProvider,
provider: ethers.BrowserProvider | ethers.JsonRpcProvider | null,
multicallProvider: MulticallProvider | null,
signer: ethers.Signer | null,
signerAddress: string,
chainId: number,
Expand Down
Loading

0 comments on commit 85dab05

Please sign in to comment.