From 48ff08e7c236eca8eb2789b1c892b08e5ee34368 Mon Sep 17 00:00:00 2001 From: Daniel Simon Date: Thu, 4 Feb 2021 20:44:31 +0700 Subject: [PATCH] lib-ethers: More implementation hiding --- .../lib-ethers.connectedliquitydeployment.md | 21 -- docs/sdk/lib-ethers.connecttoliquity.md | 4 +- ...lib-ethers.liquityconnection.addresses.md} | 4 +- ...thers.liquityconnection.deploymentdate.md} | 4 +- docs/sdk/lib-ethers.liquityconnection.md | 21 ++ ...ers.liquityconnection.signerorprovider.md} | 4 +- ...> lib-ethers.liquityconnection.version.md} | 4 +- docs/sdk/lib-ethers.md | 2 +- ....populatableethersliquity._constructor_.md | 4 +- .../lib-ethers.populatableethersliquity.md | 2 +- ...ers.readableethersliquity._constructor_.md | 4 +- docs/sdk/lib-ethers.readableethersliquity.md | 2 +- packages/dev-frontend/src/App.tsx | 4 +- .../src/components/PriceManager.tsx | 2 +- .../src/components/SystemStats.tsx | 2 +- .../dev-frontend/src/hooks/LiquityContext.tsx | 20 +- packages/lib-ethers/etc/lib-ethers.api.md | 125 ++++++---- packages/lib-ethers/index.ts | 7 +- packages/lib-ethers/src/EthersLiquity.ts | 26 +- packages/lib-ethers/src/EthersLiquityBase.ts | 8 +- .../lib-ethers/src/ObservableEthersLiquity.ts | 77 +++--- .../src/PopulatableEthersLiquity.ts | 230 +++++++++++------- .../lib-ethers/src/ReadableEthersLiquity.ts | 106 +++++--- packages/lib-ethers/src/contracts.ts | 14 +- packages/lib-ethers/test/Liquity.test.ts | 66 ++--- 25 files changed, 438 insertions(+), 325 deletions(-) delete mode 100644 docs/sdk/lib-ethers.connectedliquitydeployment.md rename docs/sdk/{lib-ethers.connectedliquitydeployment.addresses.md => lib-ethers.liquityconnection.addresses.md} (53%) rename docs/sdk/{lib-ethers.connectedliquitydeployment.deploymentdate.md => lib-ethers.liquityconnection.deploymentdate.md} (50%) create mode 100644 docs/sdk/lib-ethers.liquityconnection.md rename docs/sdk/{lib-ethers.connectedliquitydeployment.signerorprovider.md => lib-ethers.liquityconnection.signerorprovider.md} (51%) rename docs/sdk/{lib-ethers.connectedliquitydeployment.version.md => lib-ethers.liquityconnection.version.md} (52%) diff --git a/docs/sdk/lib-ethers.connectedliquitydeployment.md b/docs/sdk/lib-ethers.connectedliquitydeployment.md deleted file mode 100644 index 3b75c2e89..000000000 --- a/docs/sdk/lib-ethers.connectedliquitydeployment.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) - -## ConnectedLiquityDeployment interface - -Signature: - -```typescript -export interface ConnectedLiquityDeployment -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [addresses](./lib-ethers.connectedliquitydeployment.addresses.md) | Record<string, string> | | -| [deploymentDate](./lib-ethers.connectedliquitydeployment.deploymentdate.md) | number | | -| [signerOrProvider](./lib-ethers.connectedliquitydeployment.signerorprovider.md) | Signer \| Provider | | -| [version](./lib-ethers.connectedliquitydeployment.version.md) | string | | - diff --git a/docs/sdk/lib-ethers.connecttoliquity.md b/docs/sdk/lib-ethers.connecttoliquity.md index 2c6cdba33..90fdfb837 100644 --- a/docs/sdk/lib-ethers.connecttoliquity.md +++ b/docs/sdk/lib-ethers.connecttoliquity.md @@ -7,7 +7,7 @@ Signature: ```typescript -export declare function connectToLiquity(signerOrProvider: Signer | Provider, network?: string | number): ConnectedLiquityDeployment; +export declare function connectToLiquity(signerOrProvider: Signer | Provider, network?: string | number): LiquityConnection; ``` ## Parameters @@ -19,5 +19,5 @@ export declare function connectToLiquity(signerOrProvider: Signer | Provider, ne Returns: -[ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) +[LiquityConnection](./lib-ethers.liquityconnection.md) diff --git a/docs/sdk/lib-ethers.connectedliquitydeployment.addresses.md b/docs/sdk/lib-ethers.liquityconnection.addresses.md similarity index 53% rename from docs/sdk/lib-ethers.connectedliquitydeployment.addresses.md rename to docs/sdk/lib-ethers.liquityconnection.addresses.md index 37ef347a7..f5f525afc 100644 --- a/docs/sdk/lib-ethers.connectedliquitydeployment.addresses.md +++ b/docs/sdk/lib-ethers.liquityconnection.addresses.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) > [addresses](./lib-ethers.connectedliquitydeployment.addresses.md) +[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [LiquityConnection](./lib-ethers.liquityconnection.md) > [addresses](./lib-ethers.liquityconnection.addresses.md) -## ConnectedLiquityDeployment.addresses property +## LiquityConnection.addresses property Signature: diff --git a/docs/sdk/lib-ethers.connectedliquitydeployment.deploymentdate.md b/docs/sdk/lib-ethers.liquityconnection.deploymentdate.md similarity index 50% rename from docs/sdk/lib-ethers.connectedliquitydeployment.deploymentdate.md rename to docs/sdk/lib-ethers.liquityconnection.deploymentdate.md index ceba68c74..85fe72425 100644 --- a/docs/sdk/lib-ethers.connectedliquitydeployment.deploymentdate.md +++ b/docs/sdk/lib-ethers.liquityconnection.deploymentdate.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) > [deploymentDate](./lib-ethers.connectedliquitydeployment.deploymentdate.md) +[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [LiquityConnection](./lib-ethers.liquityconnection.md) > [deploymentDate](./lib-ethers.liquityconnection.deploymentdate.md) -## ConnectedLiquityDeployment.deploymentDate property +## LiquityConnection.deploymentDate property Signature: diff --git a/docs/sdk/lib-ethers.liquityconnection.md b/docs/sdk/lib-ethers.liquityconnection.md new file mode 100644 index 000000000..e6a883c65 --- /dev/null +++ b/docs/sdk/lib-ethers.liquityconnection.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [LiquityConnection](./lib-ethers.liquityconnection.md) + +## LiquityConnection interface + +Signature: + +```typescript +export interface LiquityConnection +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [addresses](./lib-ethers.liquityconnection.addresses.md) | Record<string, string> | | +| [deploymentDate](./lib-ethers.liquityconnection.deploymentdate.md) | number | | +| [signerOrProvider](./lib-ethers.liquityconnection.signerorprovider.md) | Signer \| Provider | | +| [version](./lib-ethers.liquityconnection.version.md) | string | | + diff --git a/docs/sdk/lib-ethers.connectedliquitydeployment.signerorprovider.md b/docs/sdk/lib-ethers.liquityconnection.signerorprovider.md similarity index 51% rename from docs/sdk/lib-ethers.connectedliquitydeployment.signerorprovider.md rename to docs/sdk/lib-ethers.liquityconnection.signerorprovider.md index 227972918..f99c13849 100644 --- a/docs/sdk/lib-ethers.connectedliquitydeployment.signerorprovider.md +++ b/docs/sdk/lib-ethers.liquityconnection.signerorprovider.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) > [signerOrProvider](./lib-ethers.connectedliquitydeployment.signerorprovider.md) +[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [LiquityConnection](./lib-ethers.liquityconnection.md) > [signerOrProvider](./lib-ethers.liquityconnection.signerorprovider.md) -## ConnectedLiquityDeployment.signerOrProvider property +## LiquityConnection.signerOrProvider property Signature: diff --git a/docs/sdk/lib-ethers.connectedliquitydeployment.version.md b/docs/sdk/lib-ethers.liquityconnection.version.md similarity index 52% rename from docs/sdk/lib-ethers.connectedliquitydeployment.version.md rename to docs/sdk/lib-ethers.liquityconnection.version.md index f30d86a2c..eea569e61 100644 --- a/docs/sdk/lib-ethers.connectedliquitydeployment.version.md +++ b/docs/sdk/lib-ethers.liquityconnection.version.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) > [version](./lib-ethers.connectedliquitydeployment.version.md) +[Home](./index.md) > [@liquity/lib-ethers](./lib-ethers.md) > [LiquityConnection](./lib-ethers.liquityconnection.md) > [version](./lib-ethers.liquityconnection.version.md) -## ConnectedLiquityDeployment.version property +## LiquityConnection.version property Signature: diff --git a/docs/sdk/lib-ethers.md b/docs/sdk/lib-ethers.md index e500c259f..4eb8cc4e9 100644 --- a/docs/sdk/lib-ethers.md +++ b/docs/sdk/lib-ethers.md @@ -30,9 +30,9 @@ | Interface | Description | | --- | --- | | [BlockPolledLiquityStoreExtraState](./lib-ethers.blockpolledliquitystoreextrastate.md) | Extra state added to [LiquityStoreState](./lib-base.liquitystorestate.md) by [BlockPolledLiquityStore](./lib-ethers.blockpolledliquitystore.md). | -| [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) | | | [EthersCallOverrides](./lib-ethers.etherscalloverrides.md) | | | [EthersTransactionOverrides](./lib-ethers.etherstransactionoverrides.md) | | +| [LiquityConnection](./lib-ethers.liquityconnection.md) | | ## Type Aliases diff --git a/docs/sdk/lib-ethers.populatableethersliquity._constructor_.md b/docs/sdk/lib-ethers.populatableethersliquity._constructor_.md index c473442ea..25175d6fb 100644 --- a/docs/sdk/lib-ethers.populatableethersliquity._constructor_.md +++ b/docs/sdk/lib-ethers.populatableethersliquity._constructor_.md @@ -9,14 +9,14 @@ Constructs a new instance of the `PopulatableEthersLiquity` class Signature: ```typescript -constructor(deployment: ConnectedLiquityDeployment, readableLiquity: ReadableLiquity, store?: LiquityStore); +constructor(connection: LiquityConnection, readableLiquity: ReadableLiquity, store?: LiquityStore); ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| deployment | [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) | | +| connection | [LiquityConnection](./lib-ethers.liquityconnection.md) | | | readableLiquity | [ReadableLiquity](./lib-base.readableliquity.md) | | | store | [LiquityStore](./lib-base.liquitystore.md) | | diff --git a/docs/sdk/lib-ethers.populatableethersliquity.md b/docs/sdk/lib-ethers.populatableethersliquity.md index 283eda106..05cfd1409 100644 --- a/docs/sdk/lib-ethers.populatableethersliquity.md +++ b/docs/sdk/lib-ethers.populatableethersliquity.md @@ -19,7 +19,7 @@ export declare class PopulatableEthersLiquity extends _PopulatableEthersLiquityB | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(deployment, readableLiquity, store)](./lib-ethers.populatableethersliquity._constructor_.md) | | Constructs a new instance of the PopulatableEthersLiquity class | +| [(constructor)(connection, readableLiquity, store)](./lib-ethers.populatableethersliquity._constructor_.md) | | Constructs a new instance of the PopulatableEthersLiquity class | ## Methods diff --git a/docs/sdk/lib-ethers.readableethersliquity._constructor_.md b/docs/sdk/lib-ethers.readableethersliquity._constructor_.md index 636d98682..9c6250cf3 100644 --- a/docs/sdk/lib-ethers.readableethersliquity._constructor_.md +++ b/docs/sdk/lib-ethers.readableethersliquity._constructor_.md @@ -9,13 +9,13 @@ Constructs a new instance of the `ReadableEthersLiquity` class Signature: ```typescript -constructor(deployment: ConnectedLiquityDeployment, userAddress?: string); +constructor(connection: LiquityConnection, userAddress?: string); ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| deployment | [ConnectedLiquityDeployment](./lib-ethers.connectedliquitydeployment.md) | | +| connection | [LiquityConnection](./lib-ethers.liquityconnection.md) | | | userAddress | string | | diff --git a/docs/sdk/lib-ethers.readableethersliquity.md b/docs/sdk/lib-ethers.readableethersliquity.md index 32d01e99c..8a2141bda 100644 --- a/docs/sdk/lib-ethers.readableethersliquity.md +++ b/docs/sdk/lib-ethers.readableethersliquity.md @@ -19,7 +19,7 @@ export declare class ReadableEthersLiquity extends _EthersLiquityBase implements | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(deployment, userAddress)](./lib-ethers.readableethersliquity._constructor_.md) | | Constructs a new instance of the ReadableEthersLiquity class | +| [(constructor)(connection, userAddress)](./lib-ethers.readableethersliquity._constructor_.md) | | Constructs a new instance of the ReadableEthersLiquity class | ## Methods diff --git a/packages/dev-frontend/src/App.tsx b/packages/dev-frontend/src/App.tsx index 52b042dfa..0028d1636 100644 --- a/packages/dev-frontend/src/App.tsx +++ b/packages/dev-frontend/src/App.tsx @@ -56,13 +56,13 @@ type LiquityFrontendProps = { }; const LiquityFrontend: React.FC = ({ loader }) => { - const { account, provider, deployment, liquity, store } = useLiquity(); + const { account, provider, connection, liquity, store } = useLiquity(); // For console tinkering ;-) Object.assign(window, { account, provider, - deployment, + connection, liquity, store, SubgraphLiquity, diff --git a/packages/dev-frontend/src/components/PriceManager.tsx b/packages/dev-frontend/src/components/PriceManager.tsx index a832760fd..22b51ca6f 100644 --- a/packages/dev-frontend/src/components/PriceManager.tsx +++ b/packages/dev-frontend/src/components/PriceManager.tsx @@ -14,7 +14,7 @@ const selectPrice = ({ price }: LiquityStoreState) => price; export const PriceManager: React.FC = () => { const { - deployment: { _priceFeedIsTestnet: canSetPrice }, + connection: { _priceFeedIsTestnet: canSetPrice }, liquity: { send: liquity } } = useLiquity(); const price = useLiquitySelector(selectPrice); diff --git a/packages/dev-frontend/src/components/SystemStats.tsx b/packages/dev-frontend/src/components/SystemStats.tsx index b248a52ab..f98598866 100644 --- a/packages/dev-frontend/src/components/SystemStats.tsx +++ b/packages/dev-frontend/src/components/SystemStats.tsx @@ -63,7 +63,7 @@ const select = ({ export const SystemStats: React.FC = ({ variant = "info", showBalances }) => { const { - deployment: { version: contractsVersion, deploymentDate } + connection: { version: contractsVersion, deploymentDate } } = useLiquity(); const { numberOfTroves, diff --git a/packages/dev-frontend/src/hooks/LiquityContext.tsx b/packages/dev-frontend/src/hooks/LiquityContext.tsx index 9717e0f1a..f8eb774ec 100644 --- a/packages/dev-frontend/src/hooks/LiquityContext.tsx +++ b/packages/dev-frontend/src/hooks/LiquityContext.tsx @@ -11,7 +11,7 @@ import { BlockPolledLiquityStore, ReadableEthersLiquity, PopulatableEthersLiquity, - ConnectedLiquityDeployment, + LiquityConnection, connectToLiquity } from "@liquity/lib-ethers"; @@ -21,7 +21,7 @@ type LiquityContextValue = { config: LiquityFrontendConfig; account: string; provider: Provider; - deployment: ConnectedLiquityDeployment; + connection: LiquityConnection; liquity: EthersLiquity; store: BlockPolledLiquityStore; }; @@ -56,7 +56,7 @@ export const LiquityProvider: React.FC = ({ const { library: provider, account, chainId } = useWeb3React(); const [config, setConfig] = useState(); - const deployment = + const connection = provider && account && chainId ? tryConnectToLiquity(provider.getSigner(account), chainId) : undefined; @@ -66,7 +66,7 @@ export const LiquityProvider: React.FC = ({ }, []); useEffect(() => { - if (config && provider && chainId && deployment) { + if (config && provider && chainId && connection) { if (isBatchedProvider(provider)) { provider.chainId = chainId; } @@ -76,7 +76,7 @@ export const LiquityProvider: React.FC = ({ if (network.name && supportedNetworks.includes(network.name) && config.infuraApiKey) { provider.openWebSocket(...wsParams(network.name, config.infuraApiKey)); - } else if (deployment._isDev) { + } else if (connection._isDev) { provider.openWebSocket(`ws://${window.location.hostname}:8546`, chainId); } @@ -85,19 +85,19 @@ export const LiquityProvider: React.FC = ({ }; } } - }, [config, provider, chainId, deployment]); + }, [config, provider, chainId, connection]); if (!config || !provider || !account || !chainId) { return <>{loader}; } - if (!deployment) { + if (!connection) { return unsupportedNetworkFallback ? <>{unsupportedNetworkFallback(chainId)} : null; } - const readable = new ReadableEthersLiquity(deployment, account); + const readable = new ReadableEthersLiquity(connection, account); const store = new BlockPolledLiquityStore(provider, account, readable, config.frontendTag); - const populatable = new PopulatableEthersLiquity(deployment, readable, store); + const populatable = new PopulatableEthersLiquity(connection, readable, store); const liquity = new EthersLiquity(readable, populatable); store.logging = true; @@ -108,7 +108,7 @@ export const LiquityProvider: React.FC = ({ config, account, provider, - deployment, + connection, liquity, store }} diff --git a/packages/lib-ethers/etc/lib-ethers.api.md b/packages/lib-ethers/etc/lib-ethers.api.md index eb409ecab..bd46726c3 100644 --- a/packages/lib-ethers/etc/lib-ethers.api.md +++ b/packages/lib-ethers/etc/lib-ethers.api.md @@ -4,18 +4,11 @@ ```ts -import { BigNumber } from '@ethersproject/bignumber'; import { BigNumberish } from '@ethersproject/bignumber'; import { BlockTag } from '@ethersproject/abstract-provider'; -import { BytesLike } from '@ethersproject/bytes'; -import { CallOverrides } from '@ethersproject/contracts'; import { CollateralGainTransferDetails } from '@liquity/lib-base'; -import { Contract } from '@ethersproject/contracts'; -import { ContractInterface } from '@ethersproject/contracts'; -import { ContractTransaction } from '@ethersproject/contracts'; import { Decimal } from '@liquity/decimal'; import { Decimalish } from '@liquity/decimal'; -import { EventFilter } from '@ethersproject/contracts'; import { FailedReceipt } from '@liquity/lib-base'; import { Fees } from '@liquity/lib-base'; import { FrontendStatus } from '@liquity/lib-base'; @@ -23,13 +16,9 @@ import { LiquidationDetails } from '@liquity/lib-base'; import { LiquityReceipt } from '@liquity/lib-base'; import { LiquityStore } from '@liquity/lib-base'; import { LiquityStoreState } from '@liquity/lib-base'; -import { Log } from '@ethersproject/abstract-provider'; -import { LogDescription } from '@ethersproject/abi'; import { LQTYStake } from '@liquity/lib-base'; import { MinedReceipt } from '@liquity/lib-base'; import { ObservableLiquity } from '@liquity/lib-base'; -import { Overrides } from '@ethersproject/contracts'; -import { PayableOverrides } from '@ethersproject/contracts'; import { PopulatableLiquity } from '@liquity/lib-base'; import { PopulatedLiquityTransaction } from '@liquity/lib-base'; import { PopulatedTransaction } from '@ethersproject/contracts'; @@ -72,25 +61,7 @@ export interface BlockPolledLiquityStoreExtraState { export type BlockPolledLiquityStoreState = LiquityStoreState; // @public (undocumented) -export interface ConnectedLiquityDeployment { - // @internal (undocumented) - readonly [brand]: unique symbol; - // (undocumented) - readonly addresses: Record; - // (undocumented) - readonly deploymentDate: number; - // @internal (undocumented) - readonly _isDev: boolean; - // @internal (undocumented) - readonly _priceFeedIsTestnet: boolean; - // (undocumented) - readonly signerOrProvider: Signer | Provider; - // (undocumented) - readonly version: string; -} - -// @public (undocumented) -export function connectToLiquity(signerOrProvider: Signer | Provider, network?: string | number): ConnectedLiquityDeployment; +export function connectToLiquity(signerOrProvider: Signer | Provider, network?: string | number): LiquityConnection; // @public (undocumented) export interface EthersCallOverrides { @@ -107,16 +78,23 @@ export class EthersLiquity extends GluedEthersLiquity { constructor(readable: ReadableEthersLiquity, populatable: PopulatableEthersLiquity); // (undocumented) static connect(signer: Signer, network?: string | number): Promise; - // Warning: (ae-forgotten-export) The symbol "_LiquityDeploymentJSON" needs to be exported by the entry point index.d.ts - // // @internal (undocumented) - static _connectToDeployment(deployment: _LiquityDeploymentJSON, signer: Signer): Promise; + static _from(connection: LiquityConnection): Promise; // (undocumented) readonly populate: PopulatableEthersLiquity; // (undocumented) readonly send: SendableEthersLiquity; } +// @internal (undocumented) +export class _EthersLiquityBase { + constructor(connection: LiquityConnection, userAddress?: string); + // (undocumented) + protected readonly _connection: LiquityConnection; + // (undocumented) + protected _requireAddress(): string; + } + // @public export type EthersPopulatedTransaction = PopulatedTransaction; @@ -141,11 +119,29 @@ export type EthersTransactionReceipt = TransactionReceipt; // @public export type EthersTransactionResponse = TransactionResponse; -// Warning: (ae-forgotten-export) The symbol "_EthersLiquityBase" needs to be exported by the entry point index.d.ts +// @public (undocumented) +export interface LiquityConnection { + // @internal (undocumented) + readonly [brand]: unique symbol; + // (undocumented) + readonly addresses: Record; + // (undocumented) + readonly deploymentDate: number; + // @internal (undocumented) + readonly _isDev: boolean; + // @internal (undocumented) + readonly _priceFeedIsTestnet: boolean; + // (undocumented) + readonly signerOrProvider: Signer | Provider; + // (undocumented) + readonly version: string; +} + +// Warning: (ae-incompatible-release-tags) The symbol "ObservableEthersLiquity" is marked as @alpha, but its signature references "_EthersLiquityBase" which is marked as @internal // // @alpha (undocumented) export class ObservableEthersLiquity extends _EthersLiquityBase implements ObservableLiquity { - constructor(deployment: ConnectedLiquityDeployment, readableLiquity: ReadableEthersLiquity, userAddress?: string); + constructor(connection: LiquityConnection, readableLiquity: ReadableEthersLiquity, userAddress?: string); // (undocumented) watchLUSDBalance(onLUSDBalanceChanged: (balance: Decimal) => void, address?: string): () => void; // (undocumented) @@ -164,11 +160,11 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser watchTroveWithoutRewards(onTroveChanged: (trove: TroveWithPendingRedistribution) => void, address?: string): () => void; } -// Warning: (ae-forgotten-export) The symbol "_PopulatableEthersLiquityBase" needs to be exported by the entry point index.d.ts +// Warning: (ae-incompatible-release-tags) The symbol "PopulatableEthersLiquity" is marked as @public, but its signature references "_PopulatableEthersLiquityBase" which is marked as @internal // // @public export class PopulatableEthersLiquity extends _PopulatableEthersLiquityBase implements PopulatableLiquity { - constructor(deployment: ConnectedLiquityDeployment, readableLiquity: ReadableLiquity, store?: LiquityStore); + constructor(connection: LiquityConnection, readableLiquity: ReadableLiquity, store?: LiquityStore); // (undocumented) adjustTrove(params: TroveAdjustmentParams, overrides?: EthersTransactionOverrides): Promise>; // (undocumented) @@ -215,20 +211,55 @@ export class PopulatableEthersLiquity extends _PopulatableEthersLiquityBase impl withdrawLUSDFromStabilityPool(amount: Decimalish, overrides?: EthersTransactionOverrides): Promise>; } +// @internal (undocumented) +export class _PopulatableEthersLiquityBase extends _EthersLiquityBase { + constructor(connection: LiquityConnection, readableLiquity: ReadableLiquity, store?: LiquityStore); + // (undocumented) + protected _findHints(trove: Trove): Promise<[string, string]>; + // (undocumented) + protected _findRedemptionHints(amount: Decimal): Promise<[string, string, string, Decimal]>; + // (undocumented) + protected readonly _readableLiquity: ReadableLiquity; + // (undocumented) + protected readonly _signer: Signer; + // (undocumented) + protected readonly _store?: LiquityStore; + // (undocumented) + protected _wrapCollateralGainTransfer(rawPopulatedTransaction: EthersPopulatedTransaction): PopulatedEthersLiquityTransaction; + // (undocumented) + protected _wrapLiquidation(rawPopulatedTransaction: EthersPopulatedTransaction): PopulatedEthersLiquityTransaction; + // (undocumented) + protected _wrapRedemption(rawPopulatedTransaction: EthersPopulatedTransaction): PopulatedEthersLiquityTransaction; + // (undocumented) + protected _wrapSimpleTransaction(rawPopulatedTransaction: EthersPopulatedTransaction): PopulatedEthersLiquityTransaction; + // (undocumented) + protected _wrapStabilityDepositTopup(change: { + depositLUSD: Decimal; + }, rawPopulatedTransaction: EthersPopulatedTransaction): PopulatedEthersLiquityTransaction; + // (undocumented) + protected _wrapStabilityDepositWithdrawal(rawPopulatedTransaction: EthersPopulatedTransaction): Promise>; + // (undocumented) + protected _wrapStabilityPoolGainsWithdrawal(rawPopulatedTransaction: EthersPopulatedTransaction): PopulatedEthersLiquityTransaction; + // (undocumented) + protected _wrapTroveChangeWithFees(params: T, rawPopulatedTransaction: EthersPopulatedTransaction): PopulatedEthersLiquityTransaction<_TroveChangeWithFees>; + // (undocumented) + protected _wrapTroveClosure(rawPopulatedTransaction: EthersPopulatedTransaction): Promise>; +} + // @public export class PopulatedEthersLiquityTransaction implements PopulatedLiquityTransaction> { - // Warning: (ae-forgotten-export) The symbol "_LiquityContracts" needs to be exported by the entry point index.d.ts - // // @internal - constructor(rawPopulatedTransaction: EthersPopulatedTransaction, parse: (rawReceipt: EthersTransactionReceipt) => T, signer: Signer, contracts: _LiquityContracts); + constructor(rawPopulatedTransaction: EthersPopulatedTransaction, parse: (rawReceipt: EthersTransactionReceipt) => T, signer: Signer, connection: LiquityConnection); readonly rawPopulatedTransaction: EthersPopulatedTransaction; // (undocumented) send(): Promise>; } +// Warning: (ae-incompatible-release-tags) The symbol "ReadableEthersLiquity" is marked as @public, but its signature references "_EthersLiquityBase" which is marked as @internal +// // @public export class ReadableEthersLiquity extends _EthersLiquityBase implements ReadableLiquity { - constructor(deployment: ConnectedLiquityDeployment, userAddress?: string); + constructor(connection: LiquityConnection, userAddress?: string); // (undocumented) getCollateralSurplusBalance(address?: string, overrides?: EthersCallOverrides): Promise; // (undocumented) @@ -320,7 +351,7 @@ export class SendableEthersLiquity implements _SendableFrom implements SentLiquityTransaction> { // @internal - constructor(rawSentTransaction: EthersTransactionResponse, parse: (rawReceipt: EthersTransactionReceipt) => T, provider: Provider, contracts: _LiquityContracts); + constructor(rawSentTransaction: EthersTransactionResponse, parse: (rawReceipt: EthersTransactionReceipt) => T, provider: Provider, connection: LiquityConnection); // (undocumented) getReceipt(): Promise>; readonly rawSentTransaction: EthersTransactionResponse; @@ -377,6 +408,16 @@ export class TransactableEthersLiquity implements _TransactableFrom; } +// @internal (undocumented) +export interface _TroveChangeWithFees { + // (undocumented) + fee: Decimal; + // (undocumented) + newTrove: Trove; + // (undocumented) + params: T; +} + // @public (undocumented) export class UnsupportedNetworkError extends Error { // @internal diff --git a/packages/lib-ethers/index.ts b/packages/lib-ethers/index.ts index aebb8ad96..70e08eec4 100644 --- a/packages/lib-ethers/index.ts +++ b/packages/lib-ethers/index.ts @@ -1,12 +1,9 @@ -export { - connectToLiquity, - ConnectedLiquityDeployment, - UnsupportedNetworkError -} from "./src/contracts"; +export { connectToLiquity, LiquityConnection, UnsupportedNetworkError } from "./src/contracts"; export * from "./src/types"; export * from "./src/ReadableEthersLiquity"; export * from "./src/ObservableEthersLiquity"; export * from "./src/PopulatableEthersLiquity"; +export * from "./src/EthersLiquityBase"; export * from "./src/EthersLiquity"; export * from "./src/BlockPolledLiquityStore"; diff --git a/packages/lib-ethers/src/EthersLiquity.ts b/packages/lib-ethers/src/EthersLiquity.ts index a45d03edf..2b28c84e3 100644 --- a/packages/lib-ethers/src/EthersLiquity.ts +++ b/packages/lib-ethers/src/EthersLiquity.ts @@ -4,12 +4,7 @@ import { Signer } from "@ethersproject/abstract-signer"; import { _glue } from "@liquity/lib-base"; -import { - ConnectedLiquityDeployment, - connectToLiquity, - _connectToDeployment, - _LiquityDeploymentJSON -} from "./contracts"; +import { LiquityConnection, connectToLiquity } from "./contracts"; import { PopulatableEthersLiquity, @@ -45,12 +40,13 @@ export class EthersLiquity extends GluedEthersLiquity { this.send = sendable; } - private static async _from(deployment: ConnectedLiquityDeployment): Promise { - assert(Signer.isSigner(deployment.signerOrProvider)); + /** @internal */ + static async _from(connection: LiquityConnection): Promise { + assert(Signer.isSigner(connection.signerOrProvider)); - const userAddress = await deployment.signerOrProvider.getAddress(); - const readable = new ReadableEthersLiquity(deployment, userAddress); - const populatable = new PopulatableEthersLiquity(deployment, readable); + const userAddress = await connection.signerOrProvider.getAddress(); + const readable = new ReadableEthersLiquity(connection, userAddress); + const populatable = new PopulatableEthersLiquity(connection, readable); return new EthersLiquity(readable, populatable); } @@ -58,12 +54,4 @@ export class EthersLiquity extends GluedEthersLiquity { static connect(signer: Signer, network: string | number = "mainnet"): Promise { return EthersLiquity._from(connectToLiquity(signer, network)); } - - /** @internal */ - static _connectToDeployment( - deployment: _LiquityDeploymentJSON, - signer: Signer - ): Promise { - return EthersLiquity._from(_connectToDeployment(deployment, signer)); - } } diff --git a/packages/lib-ethers/src/EthersLiquityBase.ts b/packages/lib-ethers/src/EthersLiquityBase.ts index 499639874..fb9a9a29b 100644 --- a/packages/lib-ethers/src/EthersLiquityBase.ts +++ b/packages/lib-ethers/src/EthersLiquityBase.ts @@ -1,12 +1,12 @@ -import { ConnectedLiquityDeployment, _LiquityContracts, _getContracts } from "./contracts"; +import { LiquityConnection } from "./contracts"; /** @internal */ export class _EthersLiquityBase { - protected readonly _contracts: _LiquityContracts; + protected readonly _connection: LiquityConnection; private readonly _userAddress?: string; - constructor(deployment: ConnectedLiquityDeployment, userAddress?: string) { - this._contracts = _getContracts(deployment); + constructor(connection: LiquityConnection, userAddress?: string) { + this._connection = connection; this._userAddress = userAddress; } diff --git a/packages/lib-ethers/src/ObservableEthersLiquity.ts b/packages/lib-ethers/src/ObservableEthersLiquity.ts index 933708ab0..b430bb820 100644 --- a/packages/lib-ethers/src/ObservableEthersLiquity.ts +++ b/packages/lib-ethers/src/ObservableEthersLiquity.ts @@ -9,7 +9,7 @@ import { TroveWithPendingRedistribution } from "@liquity/lib-base"; -import { ConnectedLiquityDeployment } from "./contracts"; +import { LiquityConnection, _getContracts } from "./contracts"; import { _EthersLiquityBase } from "./EthersLiquityBase"; import { ReadableEthersLiquity } from "./ReadableEthersLiquity"; @@ -42,11 +42,11 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser private _readableLiquity: ReadableEthersLiquity; constructor( - deployment: ConnectedLiquityDeployment, + connection: LiquityConnection, readableLiquity: ReadableEthersLiquity, userAddress?: string ) { - super(deployment, userAddress); + super(connection, userAddress); this._readableLiquity = readableLiquity; } @@ -54,22 +54,23 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser watchTotalRedistributed( onTotalRedistributedChanged: (totalRedistributed: Trove) => void ): () => void { - const etherSent = this._contracts.activePool.filters.EtherSent(); + const { activePool, defaultPool } = _getContracts(this._connection); + const etherSent = activePool.filters.EtherSent(); const redistributionListener = debounce((blockTag: number) => { this._readableLiquity.getTotalRedistributed({ blockTag }).then(onTotalRedistributedChanged); }); const etherSentListener = (toAddress: string, _amount: BigNumber, event: Event) => { - if (toAddress === this._contracts.defaultPool.address) { + if (toAddress === defaultPool.address) { redistributionListener(event); } }; - this._contracts.activePool.on(etherSent, etherSentListener); + activePool.on(etherSent, etherSentListener); return () => { - this._contracts.activePool.removeListener(etherSent, etherSentListener); + activePool.removeListener(etherSent, etherSentListener); }; } @@ -77,34 +78,34 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser onTroveChanged: (trove: TroveWithPendingRedistribution) => void, address = this._requireAddress() ): () => void { - const { TroveCreated, TroveUpdated } = this._contracts.troveManager.filters; + const { troveManager } = _getContracts(this._connection); + const { TroveCreated, TroveUpdated } = troveManager.filters; const troveEventFilters = [TroveCreated(address), TroveUpdated(address)]; const troveListener = debounce((blockTag: number) => { this._readableLiquity.getTroveWithoutRewards(address, { blockTag }).then(onTroveChanged); }); - troveEventFilters.forEach(filter => this._contracts.troveManager.on(filter, troveListener)); + troveEventFilters.forEach(filter => troveManager.on(filter, troveListener)); return () => { - troveEventFilters.forEach(filter => - this._contracts.troveManager.removeListener(filter, troveListener) - ); + troveEventFilters.forEach(filter => troveManager.removeListener(filter, troveListener)); }; } watchNumberOfTroves(onNumberOfTrovesChanged: (numberOfTroves: number) => void): () => void { - const { TroveUpdated } = this._contracts.troveManager.filters; + const { troveManager } = _getContracts(this._connection); + const { TroveUpdated } = troveManager.filters; const troveUpdated = TroveUpdated(); const troveUpdatedListener = debounce((blockTag: number) => { this._readableLiquity.getNumberOfTroves({ blockTag }).then(onNumberOfTrovesChanged); }); - this._contracts.troveManager.on(troveUpdated, troveUpdatedListener); + troveManager.on(troveUpdated, troveUpdatedListener); return () => { - this._contracts.troveManager.removeListener(troveUpdated, troveUpdatedListener); + troveManager.removeListener(troveUpdated, troveUpdatedListener); }; } @@ -117,17 +118,18 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser } watchTotal(onTotalChanged: (total: Trove) => void): () => void { - const { TroveUpdated } = this._contracts.troveManager.filters; + const { troveManager } = _getContracts(this._connection); + const { TroveUpdated } = troveManager.filters; const troveUpdated = TroveUpdated(); const totalListener = debounce((blockTag: number) => { this._readableLiquity.getTotal({ blockTag }).then(onTotalChanged); }); - this._contracts.troveManager.on(troveUpdated, totalListener); + troveManager.on(troveUpdated, totalListener); return () => { - this._contracts.troveManager.removeListener(troveUpdated, totalListener); + troveManager.removeListener(troveUpdated, totalListener); }; } @@ -135,8 +137,9 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser onStabilityDepositChanged: (deposit: StabilityDeposit) => void, address = this._requireAddress() ): () => void { - const { UserDepositChanged } = this._contracts.stabilityPool.filters; - const { EtherSent } = this._contracts.activePool.filters; + const { activePool, stabilityPool } = _getContracts(this._connection); + const { UserDepositChanged } = stabilityPool.filters; + const { EtherSent } = activePool.filters; const userDepositChanged = UserDepositChanged(address); const etherSent = EtherSent(); @@ -148,29 +151,30 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser }); const etherSentListener = (toAddress: string, _amount: BigNumber, event: Event) => { - if (toAddress === this._contracts.stabilityPool.address) { + if (toAddress === stabilityPool.address) { // Liquidation while Stability Pool has some deposits // There may be new gains depositListener(event); } }; - this._contracts.stabilityPool.on(userDepositChanged, depositListener); - this._contracts.activePool.on(etherSent, etherSentListener); + stabilityPool.on(userDepositChanged, depositListener); + activePool.on(etherSent, etherSentListener); return () => { - this._contracts.stabilityPool.removeListener(userDepositChanged, depositListener); - this._contracts.activePool.removeListener(etherSent, etherSentListener); + stabilityPool.removeListener(userDepositChanged, depositListener); + activePool.removeListener(etherSent, etherSentListener); }; } watchLUSDInStabilityPool( onLUSDInStabilityPoolChanged: (lusdInStabilityPool: Decimal) => void ): () => void { - const { Transfer } = this._contracts.lusdToken.filters; + const { lusdToken, stabilityPool } = _getContracts(this._connection); + const { Transfer } = lusdToken.filters; - const transferLUSDFromStabilityPool = Transfer(this._contracts.stabilityPool.address); - const transferLUSDToStabilityPool = Transfer(null, this._contracts.stabilityPool.address); + const transferLUSDFromStabilityPool = Transfer(stabilityPool.address); + const transferLUSDToStabilityPool = Transfer(null, stabilityPool.address); const stabilityPoolLUSDFilters = [transferLUSDFromStabilityPool, transferLUSDToStabilityPool]; @@ -178,13 +182,11 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser this._readableLiquity.getLUSDInStabilityPool({ blockTag }).then(onLUSDInStabilityPoolChanged); }); - stabilityPoolLUSDFilters.forEach(filter => - this._contracts.lusdToken.on(filter, stabilityPoolLUSDListener) - ); + stabilityPoolLUSDFilters.forEach(filter => lusdToken.on(filter, stabilityPoolLUSDListener)); return () => stabilityPoolLUSDFilters.forEach(filter => - this._contracts.lusdToken.removeListener(filter, stabilityPoolLUSDListener) + lusdToken.removeListener(filter, stabilityPoolLUSDListener) ); } @@ -192,7 +194,8 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser onLUSDBalanceChanged: (balance: Decimal) => void, address = this._requireAddress() ): () => void { - const { Transfer } = this._contracts.lusdToken.filters; + const { lusdToken } = _getContracts(this._connection); + const { Transfer } = lusdToken.filters; const transferLUSDFromUser = Transfer(address); const transferLUSDToUser = Transfer(null, address); @@ -202,13 +205,9 @@ export class ObservableEthersLiquity extends _EthersLiquityBase implements Obser this._readableLiquity.getLUSDBalance(address, { blockTag }).then(onLUSDBalanceChanged); }); - lusdTransferFilters.forEach(filter => - this._contracts.lusdToken.on(filter, lusdTransferListener) - ); + lusdTransferFilters.forEach(filter => lusdToken.on(filter, lusdTransferListener)); return () => - lusdTransferFilters.forEach(filter => - this._contracts.lusdToken.removeListener(filter, lusdTransferListener) - ); + lusdTransferFilters.forEach(filter => lusdToken.removeListener(filter, lusdTransferListener)); } } diff --git a/packages/lib-ethers/src/PopulatableEthersLiquity.ts b/packages/lib-ethers/src/PopulatableEthersLiquity.ts index 2c93b702e..482774097 100644 --- a/packages/lib-ethers/src/PopulatableEthersLiquity.ts +++ b/packages/lib-ethers/src/PopulatableEthersLiquity.ts @@ -46,7 +46,7 @@ import { EthersTransactionResponse } from "./types"; -import { ConnectedLiquityDeployment, _LiquityContracts, _priceFeedIsTestnet } from "./contracts"; +import { LiquityConnection, _getContracts, _priceFeedIsTestnet } from "./contracts"; import { logsToString } from "./parseLogs"; import { _EthersLiquityBase } from "./EthersLiquityBase"; @@ -120,26 +120,26 @@ export class SentEthersLiquityTransaction private readonly _parse: (rawReceipt: EthersTransactionReceipt) => T; private readonly _provider: Provider; - private readonly _contracts: _LiquityContracts; + private readonly _connection: LiquityConnection; /** @internal */ constructor( rawSentTransaction: EthersTransactionResponse, parse: (rawReceipt: EthersTransactionReceipt) => T, provider: Provider, - contracts: _LiquityContracts + connection: LiquityConnection ) { this.rawSentTransaction = rawSentTransaction; this._parse = parse; this._provider = provider; - this._contracts = contracts; + this._connection = connection; } private _receiptFrom(rawReceipt: EthersTransactionReceipt | null) { return rawReceipt ? rawReceipt.status ? _successfulReceipt(rawReceipt, this._parse(rawReceipt), () => - logsToString(rawReceipt, (this._contracts as unknown) as Record) + logsToString(rawReceipt, (this._connection as unknown) as Record) ) : _failedReceipt(rawReceipt) : _pendingReceipt; @@ -179,19 +179,19 @@ export class PopulatedEthersLiquityTransaction private readonly _parse: (rawReceipt: EthersTransactionReceipt) => T; private readonly _signer: Signer; - private readonly _contracts: _LiquityContracts; + private readonly _connection: LiquityConnection; /** @internal */ constructor( rawPopulatedTransaction: EthersPopulatedTransaction, parse: (rawReceipt: EthersTransactionReceipt) => T, signer: Signer, - contracts: _LiquityContracts + connection: LiquityConnection ) { this.rawPopulatedTransaction = rawPopulatedTransaction; this._parse = parse; this._signer = signer; - this._contracts = contracts; + this._connection = connection; } /** {@inheritDoc @liquity/lib-base#PopulatedLiquityTransaction.send} */ @@ -204,61 +204,66 @@ export class PopulatedEthersLiquityTransaction await this._signer.sendTransaction(this.rawPopulatedTransaction), this._parse, this._signer.provider, - this._contracts + this._connection ); } } -interface TroveChangeWithFees { +/** @internal */ +export interface _TroveChangeWithFees { params: T; newTrove: Trove; fee: Decimal; } /** @internal */ -class _PopulatableEthersLiquityBase extends _EthersLiquityBase { +export class _PopulatableEthersLiquityBase extends _EthersLiquityBase { protected readonly _readableLiquity: ReadableLiquity; protected readonly _store?: LiquityStore; protected readonly _signer: Signer; constructor( - deployment: ConnectedLiquityDeployment, + connection: LiquityConnection, readableLiquity: ReadableLiquity, store?: LiquityStore ) { - if (!Signer.isSigner(deployment.signerOrProvider)) { + if (!Signer.isSigner(connection.signerOrProvider)) { throw new Error("Must be connected through a Signer"); } - super(deployment); + super(connection); this._readableLiquity = readableLiquity; - this._signer = deployment.signerOrProvider; + this._signer = connection.signerOrProvider; this._store = store; } - protected _wrapSimpleTransaction(rawPopulatedTransaction: EthersPopulatedTransaction) { + protected _wrapSimpleTransaction( + rawPopulatedTransaction: EthersPopulatedTransaction + ): PopulatedEthersLiquityTransaction { return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, noDetails, this._signer, - this._contracts + this._connection ); } protected _wrapTroveChangeWithFees( params: T, rawPopulatedTransaction: EthersPopulatedTransaction - ) { - return new PopulatedEthersLiquityTransaction>( + ): PopulatedEthersLiquityTransaction<_TroveChangeWithFees> { + const { borrowerOperations } = _getContracts(this._connection); + + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => { - const [newTrove] = this._contracts.borrowerOperations + const [newTrove] = borrowerOperations .extractEvents(logs, "TroveUpdated") .map(({ args: { _coll, _debt } }) => new Trove(new Decimal(_coll), new Decimal(_debt))); - const [fee] = this._contracts.borrowerOperations + const [fee] = borrowerOperations .extractEvents(logs, "LUSDBorrowingFeePaid") .map(({ args: { _LUSDFee } }) => new Decimal(_LUSDFee)); @@ -270,23 +275,26 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }, this._signer, - this._contracts + this._connection ); } - protected async _wrapTroveClosure(rawPopulatedTransaction: EthersPopulatedTransaction) { + protected async _wrapTroveClosure( + rawPopulatedTransaction: EthersPopulatedTransaction + ): Promise> { + const { activePool, lusdToken } = _getContracts(this._connection); const userAddress = await this._signer.getAddress(); - return new PopulatedEthersLiquityTransaction( + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => { - const [repayLUSD] = this._contracts.lusdToken + const [repayLUSD] = lusdToken .extractEvents(logs, "Transfer") .filter(({ args: { from, to } }) => from === userAddress && to === AddressZero) .map(({ args: { value } }) => new Decimal(value)); - const [withdrawCollateral] = this._contracts.activePool + const [withdrawCollateral] = activePool .extractEvents(logs, "EtherSent") .filter(({ args: { _to } }) => _to === userAddress) .map(({ args: { _amount } }) => new Decimal(_amount)); @@ -297,20 +305,24 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }, this._signer, - this._contracts + this._connection ); } - protected _wrapLiquidation(rawPopulatedTransaction: EthersPopulatedTransaction) { - return new PopulatedEthersLiquityTransaction( + protected _wrapLiquidation( + rawPopulatedTransaction: EthersPopulatedTransaction + ): PopulatedEthersLiquityTransaction { + const { troveManager } = _getContracts(this._connection); + + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => { - const liquidatedAddresses = this._contracts.troveManager + const liquidatedAddresses = troveManager .extractEvents(logs, "TroveLiquidated") .map(({ args: { _borrower } }) => _borrower); - const [totals] = this._contracts.troveManager + const [totals] = troveManager .extractEvents(logs, "Liquidation") .map( ({ @@ -329,16 +341,20 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }, this._signer, - this._contracts + this._connection ); } - protected _wrapRedemption(rawPopulatedTransaction: EthersPopulatedTransaction) { - return new PopulatedEthersLiquityTransaction( + protected _wrapRedemption( + rawPopulatedTransaction: EthersPopulatedTransaction + ): PopulatedEthersLiquityTransaction { + const { troveManager } = _getContracts(this._connection); + + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => - this._contracts.troveManager + troveManager .extractEvents(logs, "Redemption") .map(({ args: { _ETHSent, _ETHFee, _actualLUSDAmount, _attemptedLUSDAmount } }) => ({ attemptedLUSDAmount: new Decimal(_attemptedLUSDAmount), @@ -348,22 +364,24 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }))[0], this._signer, - this._contracts + this._connection ); } private _extractStabilityPoolGainsWithdrawalDetails( logs: Log[] ): StabilityPoolGainsWithdrawalDetails { - const [newLUSDDeposit] = this._contracts.stabilityPool + const { stabilityPool } = _getContracts(this._connection); + + const [newLUSDDeposit] = stabilityPool .extractEvents(logs, "UserDepositChanged") .map(({ args: { _newDeposit } }) => new Decimal(_newDeposit)); - const [[collateralGain, lusdLoss]] = this._contracts.stabilityPool + const [[collateralGain, lusdLoss]] = stabilityPool .extractEvents(logs, "ETHGainWithdrawn") .map(({ args: { _ETH, _LUSDLoss } }) => [new Decimal(_ETH), new Decimal(_LUSDLoss)]); - const [lqtyReward] = this._contracts.stabilityPool + const [lqtyReward] = stabilityPool .extractEvents(logs, "LQTYPaidToDepositor") .map(({ args: { _LQTY } }) => new Decimal(_LQTY)); @@ -375,20 +393,22 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }; } - protected _wrapStabilityPoolGainsWithdrawal(rawPopulatedTransaction: EthersPopulatedTransaction) { - return new PopulatedEthersLiquityTransaction( + protected _wrapStabilityPoolGainsWithdrawal( + rawPopulatedTransaction: EthersPopulatedTransaction + ): PopulatedEthersLiquityTransaction { + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => this._extractStabilityPoolGainsWithdrawalDetails(logs), this._signer, - this._contracts + this._connection ); } protected _wrapStabilityDepositTopup( change: { depositLUSD: Decimal }, rawPopulatedTransaction: EthersPopulatedTransaction - ) { - return new PopulatedEthersLiquityTransaction( + ): PopulatedEthersLiquityTransaction { + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => ({ @@ -397,27 +417,25 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }), this._signer, - this._contracts + this._connection ); } protected async _wrapStabilityDepositWithdrawal( rawPopulatedTransaction: EthersPopulatedTransaction - ) { + ): Promise> { + const { stabilityPool, lusdToken } = _getContracts(this._connection); const userAddress = await this._signer.getAddress(); - return new PopulatedEthersLiquityTransaction( + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => { const gainsWithdrawalDetails = this._extractStabilityPoolGainsWithdrawalDetails(logs); - const [withdrawLUSD] = this._contracts.lusdToken + const [withdrawLUSD] = lusdToken .extractEvents(logs, "Transfer") - .filter( - ({ args: { from, to } }) => - from === this._contracts.stabilityPool.address && to === userAddress - ) + .filter(({ args: { from, to } }) => from === stabilityPool.address && to === userAddress) .map(({ args: { value } }) => new Decimal(value)); return { @@ -427,16 +445,20 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }, this._signer, - this._contracts + this._connection ); } - protected _wrapCollateralGainTransfer(rawPopulatedTransaction: EthersPopulatedTransaction) { - return new PopulatedEthersLiquityTransaction( + protected _wrapCollateralGainTransfer( + rawPopulatedTransaction: EthersPopulatedTransaction + ): PopulatedEthersLiquityTransaction { + const { borrowerOperations } = _getContracts(this._connection); + + return new PopulatedEthersLiquityTransaction( rawPopulatedTransaction, ({ logs }) => { - const [newTrove] = this._contracts.borrowerOperations + const [newTrove] = borrowerOperations .extractEvents(logs, "TroveUpdated") .map(({ args: { _coll, _debt } }) => new Trove(new Decimal(_coll), new Decimal(_debt))); @@ -447,13 +469,15 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }, this._signer, - this._contracts + this._connection ); } private async _findHintsForNominalCollateralRatio( nominalCollateralRatio: Decimal ): Promise<[string, string]> { + const { sortedTroves, hintHelpers } = _getContracts(this._connection); + const numberOfTroves = this._store?.state.numberOfTroves ?? (await this._readableLiquity.getNumberOfTroves()); @@ -462,7 +486,7 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { } if (nominalCollateralRatio.infinite) { - return [AddressZero, await this._contracts.sortedTroves.getFirst()]; + return [AddressZero, await sortedTroves.getFirst()]; } const totalNumberOfTrials = Math.ceil(10 * Math.sqrt(numberOfTroves)); @@ -478,7 +502,7 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { }, numberOfTrials: number ) => - this._contracts.hintHelpers + hintHelpers .getApproxHint(nominalCollateralRatio.bigNumber, numberOfTrials, latestRandomSeed) .then(({ latestRandomSeed, ...result }) => ({ latestRandomSeed, @@ -492,14 +516,14 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { const { hintAddress } = results.reduce((a, b) => (a.diff.lt(b.diff) ? a : b)); - return this._contracts.sortedTroves.findInsertPosition( + return sortedTroves.findInsertPosition( nominalCollateralRatio.bigNumber, hintAddress, hintAddress ); } - protected async _findHints(trove: Trove) { + protected async _findHints(trove: Trove): Promise<[string, string]> { if (trove instanceof TroveWithPendingRedistribution) { throw new Error("Rewards must be applied to this Trove"); } @@ -508,12 +532,10 @@ class _PopulatableEthersLiquityBase extends _EthersLiquityBase { } protected async _findRedemptionHints(amount: Decimal): Promise<[string, string, string, Decimal]> { + const { hintHelpers } = _getContracts(this._connection); const price = this._store?.state.price ?? (await this._readableLiquity.getPrice()); - const { - firstRedemptionHint, - partialRedemptionHintNICR - } = await this._contracts.hintHelpers.getRedemptionHints( + const { firstRedemptionHint, partialRedemptionHintNICR } = await hintHelpers.getRedemptionHints( amount.bigNumber, price.bigNumber, _redeemMaxIterations @@ -543,11 +565,11 @@ export class PopulatableEthersLiquity EthersPopulatedTransaction > { constructor( - deployment: ConnectedLiquityDeployment, + connection: LiquityConnection, readableLiquity: ReadableLiquity, store?: LiquityStore ) { - super(deployment, readableLiquity, store); + super(connection, readableLiquity, store); } /** {@inheritDoc @liquity/lib-base#PopulatableLiquity.openTrove} */ @@ -555,6 +577,8 @@ export class PopulatableEthersLiquity params: TroveCreationParams, overrides?: EthersTransactionOverrides ): Promise> { + const { borrowerOperations } = _getContracts(this._connection); + const normalized = _normalizeTroveCreation(params); const { depositCollateral, borrowLUSD } = normalized; @@ -565,7 +589,7 @@ export class PopulatableEthersLiquity return this._wrapTroveChangeWithFees( normalized, - await this._contracts.borrowerOperations.estimateAndPopulate.openTrove( + await borrowerOperations.estimateAndPopulate.openTrove( { value: depositCollateral.bigNumber, ...overrides }, compose(addGasForPotentialLastFeeOperationTimeUpdate, addGasForPotentialListTraversal), maxBorrowingRate?.bigNumber ?? 0, @@ -579,8 +603,10 @@ export class PopulatableEthersLiquity async closeTrove( overrides?: EthersTransactionOverrides ): Promise> { + const { borrowerOperations } = _getContracts(this._connection); + return this._wrapTroveClosure( - await this._contracts.borrowerOperations.estimateAndPopulate.closeTrove({ ...overrides }, id) + await borrowerOperations.estimateAndPopulate.closeTrove({ ...overrides }, id) ); } @@ -621,6 +647,8 @@ export class PopulatableEthersLiquity params: TroveAdjustmentParams, overrides?: EthersTransactionOverrides ): Promise> { + const { borrowerOperations } = _getContracts(this._connection); + const normalized = _normalizeTroveAdjustment(params); const { depositCollateral, withdrawCollateral, borrowLUSD, repayLUSD } = normalized; @@ -635,7 +663,7 @@ export class PopulatableEthersLiquity return this._wrapTroveChangeWithFees( normalized, - await this._contracts.borrowerOperations.estimateAndPopulate.adjustTrove( + await borrowerOperations.estimateAndPopulate.adjustTrove( { value: depositCollateral?.bigNumber, ...overrides }, compose( borrowLUSD ? addGasForPotentialLastFeeOperationTimeUpdate : id, @@ -654,11 +682,10 @@ export class PopulatableEthersLiquity async claimCollateralSurplus( overrides?: EthersTransactionOverrides ): Promise> { + const { borrowerOperations } = _getContracts(this._connection); + return this._wrapSimpleTransaction( - await this._contracts.borrowerOperations.estimateAndPopulate.claimCollateral( - { ...overrides }, - id - ) + await borrowerOperations.estimateAndPopulate.claimCollateral({ ...overrides }, id) ); } @@ -667,12 +694,14 @@ export class PopulatableEthersLiquity price: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { - if (!_priceFeedIsTestnet(this._contracts.priceFeed)) { + const { priceFeed } = _getContracts(this._connection); + + if (!_priceFeedIsTestnet(priceFeed)) { throw new Error("setPrice() unavailable on this deployment of Liquity"); } return this._wrapSimpleTransaction( - await this._contracts.priceFeed.estimateAndPopulate.setPrice( + await priceFeed.estimateAndPopulate.setPrice( { ...overrides }, id, Decimal.from(price).bigNumber @@ -685,9 +714,11 @@ export class PopulatableEthersLiquity address: string | string[], overrides?: EthersTransactionOverrides ): Promise> { + const { troveManager } = _getContracts(this._connection); + if (Array.isArray(address)) { return this._wrapLiquidation( - await this._contracts.troveManager.estimateAndPopulate.batchLiquidateTroves( + await troveManager.estimateAndPopulate.batchLiquidateTroves( { ...overrides }, addGasForLQTYIssuance, address @@ -695,7 +726,7 @@ export class PopulatableEthersLiquity ); } else { return this._wrapLiquidation( - await this._contracts.troveManager.estimateAndPopulate.liquidate( + await troveManager.estimateAndPopulate.liquidate( { ...overrides }, addGasForLQTYIssuance, address @@ -709,8 +740,10 @@ export class PopulatableEthersLiquity maximumNumberOfTrovesToLiquidate: number, overrides?: EthersTransactionOverrides ): Promise> { + const { troveManager } = _getContracts(this._connection); + return this._wrapLiquidation( - await this._contracts.troveManager.estimateAndPopulate.liquidateTroves( + await troveManager.estimateAndPopulate.liquidateTroves( { ...overrides }, addGasForLQTYIssuance, maximumNumberOfTrovesToLiquidate @@ -724,11 +757,12 @@ export class PopulatableEthersLiquity frontendTag = AddressZero, overrides?: EthersTransactionOverrides ): Promise> { + const { stabilityPool } = _getContracts(this._connection); const depositLUSD = Decimal.from(amount); return this._wrapStabilityDepositTopup( { depositLUSD }, - await this._contracts.stabilityPool.estimateAndPopulate.provideToSP( + await stabilityPool.estimateAndPopulate.provideToSP( { ...overrides }, addGasForLQTYIssuance, depositLUSD.bigNumber, @@ -742,8 +776,10 @@ export class PopulatableEthersLiquity amount: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { + const { stabilityPool } = _getContracts(this._connection); + return this._wrapStabilityDepositWithdrawal( - await this._contracts.stabilityPool.estimateAndPopulate.withdrawFromSP( + await stabilityPool.estimateAndPopulate.withdrawFromSP( { ...overrides }, addGasForLQTYIssuance, Decimal.from(amount).bigNumber @@ -755,8 +791,10 @@ export class PopulatableEthersLiquity async withdrawGainsFromStabilityPool( overrides?: EthersTransactionOverrides ): Promise> { + const { stabilityPool } = _getContracts(this._connection); + return this._wrapStabilityPoolGainsWithdrawal( - await this._contracts.stabilityPool.estimateAndPopulate.withdrawFromSP( + await stabilityPool.estimateAndPopulate.withdrawFromSP( { ...overrides }, addGasForLQTYIssuance, Decimal.ZERO.bigNumber @@ -768,13 +806,15 @@ export class PopulatableEthersLiquity async transferCollateralGainToTrove( overrides?: EthersTransactionOverrides ): Promise> { + const { stabilityPool } = _getContracts(this._connection); + const initialTrove = this._store?.state.trove ?? (await this._readableLiquity.getTrove()); const deposit = this._store?.state.deposit ?? (await this._readableLiquity.getStabilityDeposit()); const finalTrove = initialTrove.addCollateral(deposit.collateralGain); return this._wrapCollateralGainTransfer( - await this._contracts.stabilityPool.estimateAndPopulate.withdrawETHGainToTrove( + await stabilityPool.estimateAndPopulate.withdrawETHGainToTrove( { ...overrides }, compose(addGasForPotentialListTraversal, addGasForLQTYIssuance), ...(await this._findHints(finalTrove)) @@ -788,8 +828,10 @@ export class PopulatableEthersLiquity amount: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { + const { lusdToken } = _getContracts(this._connection); + return this._wrapSimpleTransaction( - await this._contracts.lusdToken.estimateAndPopulate.transfer( + await lusdToken.estimateAndPopulate.transfer( { ...overrides }, id, toAddress, @@ -804,8 +846,10 @@ export class PopulatableEthersLiquity amount: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { + const { lqtyToken } = _getContracts(this._connection); + return this._wrapSimpleTransaction( - await this._contracts.lqtyToken.estimateAndPopulate.transfer( + await lqtyToken.estimateAndPopulate.transfer( { ...overrides }, id, toAddress, @@ -819,6 +863,8 @@ export class PopulatableEthersLiquity amount: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { + const { troveManager } = _getContracts(this._connection); + amount = Decimal.from(amount); const [ @@ -840,7 +886,7 @@ export class PopulatableEthersLiquity const maxRedemptionRate = Decimal.min(redemptionRate.add(slippageTolerance), Decimal.ONE); return this._wrapRedemption( - await this._contracts.troveManager.estimateAndPopulate.redeemCollateral( + await troveManager.estimateAndPopulate.redeemCollateral( { ...overrides }, addGasForPotentialLastFeeOperationTimeUpdate, amount.bigNumber, @@ -859,8 +905,10 @@ export class PopulatableEthersLiquity amount: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { + const { lqtyStaking } = _getContracts(this._connection); + return this._wrapSimpleTransaction( - await this._contracts.lqtyStaking.estimateAndPopulate.stake( + await lqtyStaking.estimateAndPopulate.stake( { ...overrides }, id, Decimal.from(amount).bigNumber @@ -873,8 +921,10 @@ export class PopulatableEthersLiquity amount: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { + const { lqtyStaking } = _getContracts(this._connection); + return this._wrapSimpleTransaction( - await this._contracts.lqtyStaking.estimateAndPopulate.unstake( + await lqtyStaking.estimateAndPopulate.unstake( { ...overrides }, id, Decimal.from(amount).bigNumber @@ -894,8 +944,10 @@ export class PopulatableEthersLiquity kickbackRate: Decimalish, overrides?: EthersTransactionOverrides ): Promise> { + const { stabilityPool } = _getContracts(this._connection); + return this._wrapSimpleTransaction( - await this._contracts.stabilityPool.estimateAndPopulate.registerFrontEnd( + await stabilityPool.estimateAndPopulate.registerFrontEnd( { ...overrides }, id, Decimal.from(kickbackRate).bigNumber diff --git a/packages/lib-ethers/src/ReadableEthersLiquity.ts b/packages/lib-ethers/src/ReadableEthersLiquity.ts index a27d09417..996fdcbcd 100644 --- a/packages/lib-ethers/src/ReadableEthersLiquity.ts +++ b/packages/lib-ethers/src/ReadableEthersLiquity.ts @@ -14,7 +14,7 @@ import { import { MultiTroveGetter } from "../types"; import { EthersCallOverrides } from "./types"; import { _EthersLiquityBase } from "./EthersLiquityBase"; -import { ConnectedLiquityDeployment } from "./contracts"; +import { LiquityConnection, _getContracts } from "./contracts"; // TODO: these are constant in the contracts, so it doesn't make sense to make a call for them, // but to avoid having to update them here when we change them in the contracts, we could read @@ -36,15 +36,17 @@ const decimalify = (bigNumber: BigNumber) => new Decimal(bigNumber); * @public */ export class ReadableEthersLiquity extends _EthersLiquityBase implements ReadableLiquity { - constructor(deployment: ConnectedLiquityDeployment, userAddress?: string) { - super(deployment, userAddress); + constructor(connection: LiquityConnection, userAddress?: string) { + super(connection, userAddress); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getTotalRedistributed} */ async getTotalRedistributed(overrides?: EthersCallOverrides): Promise { + const { troveManager } = _getContracts(this._connection); + const [collateral, debt] = await Promise.all([ - this._contracts.troveManager.L_ETH({ ...overrides }).then(decimalify), - this._contracts.troveManager.L_LUSDDebt({ ...overrides }).then(decimalify) + troveManager.L_ETH({ ...overrides }).then(decimalify), + troveManager.L_LUSDDebt({ ...overrides }).then(decimalify) ]); return new Trove(collateral, debt); @@ -55,9 +57,11 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl address = this._requireAddress(), overrides?: EthersCallOverrides ): Promise { + const { troveManager } = _getContracts(this._connection); + const [trove, snapshot] = await Promise.all([ - this._contracts.troveManager.Troves(address, { ...overrides }), - this._contracts.troveManager.rewardSnapshots(address, { ...overrides }) + troveManager.Troves(address, { ...overrides }), + troveManager.rewardSnapshots(address, { ...overrides }) ]); if (trove.status === TroveStatus.active) { @@ -84,22 +88,28 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getNumberOfTroves} */ async getNumberOfTroves(overrides?: EthersCallOverrides): Promise { - return (await this._contracts.troveManager.getTroveOwnersCount({ ...overrides })).toNumber(); + const { troveManager } = _getContracts(this._connection); + + return (await troveManager.getTroveOwnersCount({ ...overrides })).toNumber(); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getPrice} */ async getPrice(overrides?: EthersCallOverrides): Promise { - return new Decimal(await this._contracts.priceFeed.callStatic.fetchPrice({ ...overrides })); + const { priceFeed } = _getContracts(this._connection); + + return new Decimal(await priceFeed.callStatic.fetchPrice({ ...overrides })); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getTotal} */ async getTotal(overrides?: EthersCallOverrides): Promise { + const { activePool, defaultPool } = _getContracts(this._connection); + const [activeCollateral, activeDebt, liquidatedCollateral, closedDebt] = await Promise.all( [ - this._contracts.activePool.getETH({ ...overrides }), - this._contracts.activePool.getLUSDDebt({ ...overrides }), - this._contracts.defaultPool.getETH({ ...overrides }), - this._contracts.defaultPool.getLUSDDebt({ ...overrides }) + activePool.getETH({ ...overrides }), + activePool.getLUSDDebt({ ...overrides }), + defaultPool.getETH({ ...overrides }), + defaultPool.getLUSDDebt({ ...overrides }) ].map(getBigNumber => getBigNumber.then(decimalify)) ); @@ -111,12 +121,14 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl address = this._requireAddress(), overrides?: EthersCallOverrides ): Promise { + const { stabilityPool } = _getContracts(this._connection); + const [initialLUSD, currentLUSD, collateralGain, lqtyReward] = await Promise.all( [ - this._contracts.stabilityPool.deposits(address, { ...overrides }).then(d => d.initialValue), - this._contracts.stabilityPool.getCompoundedLUSDDeposit(address, { ...overrides }), - this._contracts.stabilityPool.getDepositorETHGain(address, { ...overrides }), - this._contracts.stabilityPool.getDepositorLQTYGain(address, { ...overrides }) + stabilityPool.deposits(address, { ...overrides }).then(d => d.initialValue), + stabilityPool.getCompoundedLUSDDeposit(address, { ...overrides }), + stabilityPool.getDepositorETHGain(address, { ...overrides }), + stabilityPool.getDepositorLQTYGain(address, { ...overrides }) ].map(getBigNumber => getBigNumber.then(decimalify)) ); @@ -125,7 +137,9 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getLUSDInStabilityPool} */ async getLUSDInStabilityPool(overrides?: EthersCallOverrides): Promise { - return new Decimal(await this._contracts.stabilityPool.getTotalLUSDDeposits({ ...overrides })); + const { stabilityPool } = _getContracts(this._connection); + + return new Decimal(await stabilityPool.getTotalLUSDDeposits({ ...overrides })); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getLUSDBalance} */ @@ -133,7 +147,9 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl address = this._requireAddress(), overrides?: EthersCallOverrides ): Promise { - return new Decimal(await this._contracts.lusdToken.balanceOf(address, { ...overrides })); + const { lusdToken } = _getContracts(this._connection); + + return new Decimal(await lusdToken.balanceOf(address, { ...overrides })); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getLQTYBalance} */ @@ -141,7 +157,9 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl address = this._requireAddress(), overrides?: EthersCallOverrides ): Promise { - return new Decimal(await this._contracts.lqtyToken.balanceOf(address, { ...overrides })); + const { lqtyToken } = _getContracts(this._connection); + + return new Decimal(await lqtyToken.balanceOf(address, { ...overrides })); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getCollateralSurplusBalance} */ @@ -149,9 +167,9 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl address = this._requireAddress(), overrides?: EthersCallOverrides ): Promise { - return new Decimal( - await this._contracts.collSurplusPool.getCollateral(address, { ...overrides }) - ); + const { collSurplusPool } = _getContracts(this._connection); + + return new Decimal(await collSurplusPool.getCollateral(address, { ...overrides })); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getLastTroves} */ @@ -160,11 +178,11 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl numberOfTroves: number, overrides?: EthersCallOverrides ): Promise<[string, TroveWithPendingRedistribution][]> { - const troves = await this._contracts.multiTroveGetter.getMultipleSortedTroves( - -(startIdx + 1), - numberOfTroves, - { ...overrides } - ); + const { multiTroveGetter } = _getContracts(this._connection); + + const troves = await multiTroveGetter.getMultipleSortedTroves(-(startIdx + 1), numberOfTroves, { + ...overrides + }); return mapMultipleSortedTrovesToTroves(troves); } @@ -175,20 +193,22 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl numberOfTroves: number, overrides?: EthersCallOverrides ): Promise<[string, TroveWithPendingRedistribution][]> { - const troves = await this._contracts.multiTroveGetter.getMultipleSortedTroves( - startIdx, - numberOfTroves, - { ...overrides } - ); + const { multiTroveGetter } = _getContracts(this._connection); + + const troves = await multiTroveGetter.getMultipleSortedTroves(startIdx, numberOfTroves, { + ...overrides + }); return mapMultipleSortedTrovesToTroves(troves); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getFees} */ async getFees(overrides?: EthersCallOverrides): Promise { + const { troveManager } = _getContracts(this._connection); + const [lastFeeOperationTime, baseRateWithoutDecay] = await Promise.all([ - this._contracts.troveManager.lastFeeOperationTime({ ...overrides }), - this._contracts.troveManager.baseRate({ ...overrides }).then(decimalify) + troveManager.lastFeeOperationTime({ ...overrides }), + troveManager.baseRate({ ...overrides }).then(decimalify) ]); const lastFeeOperation = new Date(1000 * lastFeeOperationTime.toNumber()); @@ -201,11 +221,13 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl address = this._requireAddress(), overrides?: EthersCallOverrides ): Promise { + const { lqtyStaking } = _getContracts(this._connection); + const [stakedLQTY, collateralGain, lusdGain] = await Promise.all( [ - this._contracts.lqtyStaking.stakes(address, { ...overrides }), - this._contracts.lqtyStaking.getPendingETHGain(address, { ...overrides }), - this._contracts.lqtyStaking.getPendingLUSDGain(address, { ...overrides }) + lqtyStaking.stakes(address, { ...overrides }), + lqtyStaking.getPendingETHGain(address, { ...overrides }), + lqtyStaking.getPendingLUSDGain(address, { ...overrides }) ].map(getBigNumber => getBigNumber.then(decimalify)) ); @@ -214,7 +236,9 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getTotalStakedLQTY} */ async getTotalStakedLQTY(overrides?: EthersCallOverrides): Promise { - return new Decimal(await this._contracts.lqtyStaking.totalLQTYStaked({ ...overrides })); + const { lqtyStaking } = _getContracts(this._connection); + + return new Decimal(await lqtyStaking.totalLQTYStaked({ ...overrides })); } /** {@inheritDoc @liquity/lib-base#ReadableLiquity.getFrontendStatus} */ @@ -222,7 +246,9 @@ export class ReadableEthersLiquity extends _EthersLiquityBase implements Readabl address = this._requireAddress(), overrides?: EthersCallOverrides ): Promise { - const { registered, kickbackRate } = await this._contracts.stabilityPool.frontEnds(address, { + const { stabilityPool } = _getContracts(this._connection); + + const { registered, kickbackRate } = await stabilityPool.frontEnds(address, { ...overrides }); diff --git a/packages/lib-ethers/src/contracts.ts b/packages/lib-ethers/src/contracts.ts index aa57b0d6e..c3ac488db 100644 --- a/packages/lib-ethers/src/contracts.ts +++ b/packages/lib-ethers/src/contracts.ts @@ -212,7 +212,7 @@ declare const brand: unique symbol; const branded = (t: Omit): T => t as T; -export interface ConnectedLiquityDeployment { +export interface LiquityConnection { readonly signerOrProvider: Signer | Provider; readonly addresses: Record; @@ -230,7 +230,7 @@ export interface ConnectedLiquityDeployment { } /** @internal */ -export interface _ConnectedLiquityDeployment extends ConnectedLiquityDeployment { +export interface _LiquityConnection extends LiquityConnection { readonly addresses: _LiquityContractAddresses; readonly _contracts: _LiquityContracts; } @@ -281,7 +281,7 @@ const connectedDeploymentFrom = ( deployment: _LiquityDeploymentJSON, signerOrProvider: Signer | Provider, _contracts: _LiquityContracts -): _ConnectedLiquityDeployment => +): _LiquityConnection => branded({ ...deployment, signerOrProvider, @@ -289,8 +289,8 @@ const connectedDeploymentFrom = ( }); /** @internal */ -export const _getContracts = (deployment: ConnectedLiquityDeployment): _LiquityContracts => - (deployment as _ConnectedLiquityDeployment)._contracts; +export const _getContracts = (connection: LiquityConnection): _LiquityContracts => + (connection as _LiquityConnection)._contracts; export class UnsupportedNetworkError extends Error { readonly unsupportedNetwork: string | number; @@ -307,7 +307,7 @@ export class UnsupportedNetworkError extends Error { export const _connectToDeployment = ( deployment: _LiquityDeploymentJSON, signerOrProvider: Signer | Provider -): ConnectedLiquityDeployment => +): LiquityConnection => connectedDeploymentFrom( deployment, signerOrProvider, @@ -317,7 +317,7 @@ export const _connectToDeployment = ( export function connectToLiquity( signerOrProvider: Signer | Provider, network: string | number = "mainnet" -): ConnectedLiquityDeployment { +): LiquityConnection { if (!(network in deployments)) { throw new UnsupportedNetworkError(network); } diff --git a/packages/lib-ethers/test/Liquity.test.ts b/packages/lib-ethers/test/Liquity.test.ts index 996aa3a87..7a2a07df9 100644 --- a/packages/lib-ethers/test/Liquity.test.ts +++ b/packages/lib-ethers/test/Liquity.test.ts @@ -21,12 +21,15 @@ import { } from "@liquity/lib-base"; import { HintHelpers } from "../types"; -import { _LiquityContracts, _LiquityDeploymentJSON } from "../src/contracts"; + +import { LiquityConnection, _connectToDeployment, _LiquityDeploymentJSON } from "../src/contracts"; + import { PopulatableEthersLiquity, PopulatedEthersLiquityTransaction, _redeemMaxIterations } from "../src/PopulatableEthersLiquity"; + import { EthersLiquity } from "../src/EthersLiquity"; const provider = ethers.provider; @@ -34,6 +37,9 @@ const provider = ethers.provider; chai.use(chaiAsPromised); chai.use(chaiSpies); +const connectToDeployment = (deployment: _LiquityDeploymentJSON, signer: Signer) => + EthersLiquity._from(_connectToDeployment(deployment, signer)); + const baseRate = Fees.prototype.baseRate; let cumulativeTimeJumpSeconds = 0; @@ -83,13 +89,13 @@ describe("EthersLiquity", () => { let otherLiquities: EthersLiquity[]; const connectUsers = (users: Signer[]) => - Promise.all(users.map(user => EthersLiquity._connectToDeployment(deployment, user))); + Promise.all(users.map(user => connectToDeployment(deployment, user))); const openTroves = (users: Signer[], params: TroveCreationParams[]) => params .map((params, i) => () => Promise.all([ - EthersLiquity._connectToDeployment(deployment, users[i]), + connectToDeployment(deployment, users[i]), sendTo(users[i], params.depositCollateral).then(tx => tx.wait()) ]).then(async ([liquity]) => { await liquity.openTrove(params, { gasPrice: 0 }); @@ -116,7 +122,7 @@ describe("EthersLiquity", () => { [deployer, funder, user, ...otherUsers] = await ethers.getSigners(); deployment = await deployLiquity(deployer); - liquity = await EthersLiquity._connectToDeployment(deployment, user); + liquity = await connectToDeployment(deployment, user); expect(liquity).to.be.an.instanceOf(EthersLiquity); }); @@ -164,26 +170,32 @@ describe("EthersLiquity", () => { { diff: BigNumber.from(2), hintAddress: "dennis", latestRandomSeed: BigNumber.from(4444) } ]; - const fakeContracts = { - borrowerOperations: { - estimateAndPopulate: { - openTrove: () => ({}) - } - }, + const borrowerOperations = { + estimateAndPopulate: { + openTrove: () => ({}) + } + }; - hintHelpers: chai.spy.interface({ - getApproxHint: () => Promise.resolve(fakeHints.shift()) - }), + const hintHelpers = chai.spy.interface({ + getApproxHint: () => Promise.resolve(fakeHints.shift()) + }); - sortedTroves: chai.spy.interface({ - findInsertPosition: () => Promise.resolve(["fake insert position"]) - }) + const sortedTroves = chai.spy.interface({ + findInsertPosition: () => Promise.resolve(["fake insert position"]) + }); + + const fakeConnection = { + signerOrProvider: user, + _contracts: { + borrowerOperations, + hintHelpers, + sortedTroves + } }; const fakeLiquity = new PopulatableEthersLiquity( - (fakeContracts as unknown) as _LiquityContracts, + (fakeConnection as unknown) as LiquityConnection, (undefined as unknown) as ReadableLiquity, - (undefined as unknown) as Signer, { state: { numberOfTroves: 1000000, // 10 * sqrt(1M) / 2500 = 4 expected getApproxHint calls @@ -200,18 +212,16 @@ describe("EthersLiquity", () => { await fakeLiquity.openTrove(params); - expect(fakeContracts.hintHelpers.getApproxHint).to.have.been.called.exactly(4); - expect(fakeContracts.hintHelpers.getApproxHint).to.have.been.called.with( - nominalCollateralRatio.bigNumber - ); + expect(hintHelpers.getApproxHint).to.have.been.called.exactly(4); + expect(hintHelpers.getApproxHint).to.have.been.called.with(nominalCollateralRatio.bigNumber); // returned latestRandomSeed should be passed back on the next call - expect(fakeContracts.hintHelpers.getApproxHint).to.have.been.called.with(BigNumber.from(1111)); - expect(fakeContracts.hintHelpers.getApproxHint).to.have.been.called.with(BigNumber.from(2222)); - expect(fakeContracts.hintHelpers.getApproxHint).to.have.been.called.with(BigNumber.from(3333)); + expect(hintHelpers.getApproxHint).to.have.been.called.with(BigNumber.from(1111)); + expect(hintHelpers.getApproxHint).to.have.been.called.with(BigNumber.from(2222)); + expect(hintHelpers.getApproxHint).to.have.been.called.with(BigNumber.from(3333)); - expect(fakeContracts.sortedTroves.findInsertPosition).to.have.been.called.once; - expect(fakeContracts.sortedTroves.findInsertPosition).to.have.been.called.with( + expect(sortedTroves.findInsertPosition).to.have.been.called.once; + expect(sortedTroves.findInsertPosition).to.have.been.called.with( nominalCollateralRatio.bigNumber, "carol" ); @@ -258,7 +268,7 @@ describe("EthersLiquity", () => { }); it("should close the Trove after another user creates a Trove", async () => { - const funderLiquity = await EthersLiquity._connectToDeployment(deployment, funder); + const funderLiquity = await connectToDeployment(deployment, funder); await funderLiquity.openTrove({ depositCollateral: 1 }); const { params } = await liquity.closeTrove();