From 47e99bdbb42c14d3185c23202e8c3bce30c7ad86 Mon Sep 17 00:00:00 2001 From: Ryan Goree Date: Thu, 7 Nov 2024 20:18:19 -0600 Subject: [PATCH] Revert hyperdrive-js-core --- packages/hyperdrive-js-core/package.json | 51 +- packages/hyperdrive-js-core/src/base/types.ts | 91 +++ .../src/checkpoint/types.ts | 10 +- .../src/drift/ContractClient.ts | 32 - .../src/drift/ReadWriteClient.ts | 20 - .../src/errors/BlockNotFoundError.ts | 2 +- .../src/errors/HyperdriveSdkError.ts | 13 +- .../src/evm-client/contractFactory.ts | 27 + .../evm-client/syncCacheWithTransaction.ts | 85 +++ .../utils/getBlockFromReadOptions.ts | 13 + .../utils}/getBlockOrThrow.ts | 15 +- .../evm-client/utils/isReadWriteContract.ts | 12 + .../src/exports/contract.ts | 5 + .../hyperdrive-js-core/src/exports/errors.ts | 3 + .../src/exports/factory/index.ts | 2 + .../src/exports/factory/model.ts | 5 + .../src/exports/factory/rest.ts | 1 + .../src/exports/hyperdrive/index.ts | 2 + .../src/exports/hyperdrive/model.ts | 40 ++ .../src/exports/hyperdrive/rest.ts | 34 + .../hyperdrive-js-core/src/exports/index.ts | 173 +---- .../hyperdrive-js-core/src/exports/model.ts | 10 + .../src/exports/registry/index.ts | 2 + .../src/exports/registry/model.ts | 8 + .../src/exports/registry/rest.ts | 1 + .../src/exports/token/index.ts | 2 + .../src/exports/token/model.ts | 34 + .../src/exports/token/rest.ts | 19 + .../hyperdrive-js-core/src/exports/utils.ts | 13 + .../src/exports/v1.0.14/hyperdrive/index.ts | 1 + .../hyperdrive/model.ts} | 3 + .../src/exports/v1.0.14/index.ts | 1 + .../src/factory/ReadFactory.ts | 26 +- .../src/factory/ReadWriteFactory.ts | 26 +- .../hyperdrive/base/ReadHyperdrive.test.ts | 623 ++++++++++-------- .../src/hyperdrive/base/ReadHyperdrive.ts | 138 ++-- .../hyperdrive/base/ReadWriteHyperdrive.ts | 154 ++--- .../base/testing/setupReadHyperdrive.ts | 37 +- .../base/v1.0.14/ReadHyperdrive_v1_0_14.ts | 2 +- .../erc4626/ReadErc4626Hyperdrive.ts | 10 +- .../erc4626/ReadMockErc4626Hyperdrive.ts | 16 +- .../erc4626/ReadWriteErc4626Hyperdrive.ts | 14 +- .../erc4626/ReadWriteMockErc4626Hyperdrive.ts | 14 +- .../hyperdrive/ezeth/ReadEzEthHyperdrive.ts | 29 +- .../ezeth/ReadWriteEzEthHyperdrive.ts | 24 +- .../src/hyperdrive/getHyperdrive.ts | 101 --- .../hyperdrive/lseth/ReadLsEthHyperdrive.ts | 15 +- .../lseth/ReadWriteLsEthHyperdrive.ts | 17 +- .../metamorpho/ReadMetaMorphoHyperdrive.ts | 56 ++ .../ReadWriteMetaMorphoHyperdrive.ts | 26 + .../src/hyperdrive/metamorpho/abi.ts | 61 ++ .../ReadMetaMorphoHyperdrive_v1_0_14.ts | 6 + .../src/hyperdrive/reth/ReadREthHyperdrive.ts | 15 +- .../reth/ReadWriteREthHyperdrive.ts | 11 +- .../hyperdrive/steth/ReadStEthHyperdrive.ts | 32 +- .../steth/ReadWriteStEthHyperdrive.ts | 31 +- .../ReadClient.ts => model/ReadModel.ts} | 49 +- .../src/model/ReadWriteModel.ts | 33 + packages/hyperdrive-js-core/src/pool/types.ts | 2 +- .../src/registry/ReadRegistry.ts | 41 +- .../src/registry/ReadWriteRegistry.ts | 37 +- .../hyperdrive-js-core/src/registry/types.ts | 9 +- .../hyperdrive-js-core/src/token/ReadToken.ts | 6 +- .../src/token/ReadWriteToken.ts | 10 +- .../src/token/erc20/ReadErc20.ts | 28 +- .../src/token/erc20/ReadWriteErc20.ts | 27 +- .../src/token/erc4626/ReadErc4626.ts | 16 +- .../src/token/erc4626/ReadMockErc4626.ts | 16 +- .../src/token/erc4626/ReadWriteErc4626.ts | 4 +- .../src/token/erc4626/ReadWriteMockErc4626.ts | 7 +- .../src/token/eth/ReadEth.ts | 13 +- .../src/token/eth/ReadWriteEth.ts | 8 +- .../src/token/lseth/ReadLsEth.ts | 14 +- .../src/token/lseth/ReadWriteLsEth.ts | 4 +- .../src/token/reth/ReadREth.ts | 14 +- .../src/token/reth/ReadWriteREth.ts | 4 +- .../src/token/steth/ReadStEth.ts | 16 +- .../src/token/steth/ReadWriteStEth.ts | 4 +- packages/hyperdrive-js-core/tsup.config.ts | 41 +- yarn.lock | 19 +- 80 files changed, 1534 insertions(+), 1102 deletions(-) delete mode 100644 packages/hyperdrive-js-core/src/drift/ContractClient.ts delete mode 100644 packages/hyperdrive-js-core/src/drift/ReadWriteClient.ts create mode 100644 packages/hyperdrive-js-core/src/evm-client/contractFactory.ts create mode 100644 packages/hyperdrive-js-core/src/evm-client/syncCacheWithTransaction.ts create mode 100644 packages/hyperdrive-js-core/src/evm-client/utils/getBlockFromReadOptions.ts rename packages/hyperdrive-js-core/src/{drift => evm-client/utils}/getBlockOrThrow.ts (61%) create mode 100644 packages/hyperdrive-js-core/src/evm-client/utils/isReadWriteContract.ts create mode 100644 packages/hyperdrive-js-core/src/exports/contract.ts create mode 100644 packages/hyperdrive-js-core/src/exports/errors.ts create mode 100644 packages/hyperdrive-js-core/src/exports/factory/index.ts create mode 100644 packages/hyperdrive-js-core/src/exports/factory/model.ts create mode 100644 packages/hyperdrive-js-core/src/exports/factory/rest.ts create mode 100644 packages/hyperdrive-js-core/src/exports/hyperdrive/index.ts create mode 100644 packages/hyperdrive-js-core/src/exports/hyperdrive/model.ts create mode 100644 packages/hyperdrive-js-core/src/exports/hyperdrive/rest.ts create mode 100644 packages/hyperdrive-js-core/src/exports/model.ts create mode 100644 packages/hyperdrive-js-core/src/exports/registry/index.ts create mode 100644 packages/hyperdrive-js-core/src/exports/registry/model.ts create mode 100644 packages/hyperdrive-js-core/src/exports/registry/rest.ts create mode 100644 packages/hyperdrive-js-core/src/exports/token/index.ts create mode 100644 packages/hyperdrive-js-core/src/exports/token/model.ts create mode 100644 packages/hyperdrive-js-core/src/exports/token/rest.ts create mode 100644 packages/hyperdrive-js-core/src/exports/utils.ts create mode 100644 packages/hyperdrive-js-core/src/exports/v1.0.14/hyperdrive/index.ts rename packages/hyperdrive-js-core/src/exports/{v1.0.14.ts => v1.0.14/hyperdrive/model.ts} (92%) create mode 100644 packages/hyperdrive-js-core/src/exports/v1.0.14/index.ts delete mode 100644 packages/hyperdrive-js-core/src/hyperdrive/getHyperdrive.ts create mode 100644 packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadMetaMorphoHyperdrive.ts create mode 100644 packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadWriteMetaMorphoHyperdrive.ts create mode 100644 packages/hyperdrive-js-core/src/hyperdrive/metamorpho/abi.ts create mode 100644 packages/hyperdrive-js-core/src/hyperdrive/metamorpho/v1.0.14/ReadMetaMorphoHyperdrive_v1_0_14.ts rename packages/hyperdrive-js-core/src/{drift/ReadClient.ts => model/ReadModel.ts} (51%) create mode 100644 packages/hyperdrive-js-core/src/model/ReadWriteModel.ts diff --git a/packages/hyperdrive-js-core/package.json b/packages/hyperdrive-js-core/package.json index 6f520313f..e33b074d3 100644 --- a/packages/hyperdrive-js-core/package.json +++ b/packages/hyperdrive-js-core/package.json @@ -11,18 +11,17 @@ "typecheck": "tsc --noEmit" }, "peerDependencies": { - "@delvtech/drift": "^0.0.1-beta.11" + "@delvtech/evm-client": "^0.5.1" }, "dependencies": { "@delvtech/fixed-point-wasm": "^0.0.6", "@delvtech/hyperdrive-artifacts": "^1.0.18", "@delvtech/hyperdrive-wasm": "^0.15.3", "lodash.groupby": "^4.6.0", - "lodash.mapvalues": "^4.6.0", - "semver": "^7.6.3" + "lodash.mapvalues": "^4.6.0" }, "devDependencies": { - "@delvtech/drift": "^0.0.1-beta.11", + "@delvtech/evm-client": "^0.5.1", "@hyperdrive/eslint-config": "*", "@hyperdrive/prettier-config": "*", "@hyperdrive/tsconfig": "*", @@ -48,13 +47,47 @@ "exports": { ".": { "types": "./dist/index.d.ts", - "default": "./dist/index.js", - "require": "./dist/index.cjs" + "default": "./dist/index.js" + }, + "./factory/*": { + "types": "./dist/factory/*.d.ts", + "default": "./dist/factory/*.js" + }, + "./hyperdrive/*": { + "types": "./dist/hyperdrive/*.d.ts", + "default": "./dist/hyperdrive/*.js" + }, + "./registry/*": { + "types": "./dist/registry/*.d.ts", + "default": "./dist/registry/*.js" + }, + "./token/*": { + "types": "./dist/token/*.d.ts", + "default": "./dist/token/*.js" + }, + "./contract": { + "types": "./dist/contract.d.ts", + "default": "./dist/contract.js" + }, + "./errors": { + "types": "./dist/errors.d.ts", + "default": "./dist/errors.js" + }, + "./model": { + "types": "./dist/model.d.ts", + "default": "./dist/model.js" + }, + "./utils": { + "types": "./dist/utils.d.ts", + "default": "./dist/utils.js" }, "./v1.0.14": { - "types": "./dist/v1.0.14.d.ts", - "default": "./dist/v1.0.14.js", - "require": "./dist/v1.0.14.cjs" + "types": "./dist/v1.0.14/index.d.ts", + "default": "./dist/v1.0.14/index.js" + }, + "./v1.0.14/*": { + "types": "./dist/v1.0.14/*.d.ts", + "default": "./dist/v1.0.14/*.js" }, "./package.json": "./package.json" }, diff --git a/packages/hyperdrive-js-core/src/base/types.ts b/packages/hyperdrive-js-core/src/base/types.ts index 13e33b13b..f00061a6a 100644 --- a/packages/hyperdrive-js-core/src/base/types.ts +++ b/packages/hyperdrive-js-core/src/base/types.ts @@ -1,3 +1,11 @@ +/** + * Combines members of an intersection into a readable type. + * @see https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg + */ +export type Prettify = { + [K in keyof T]: T[K]; +} & unknown; + /** * A generic constructor type. */ @@ -5,3 +13,86 @@ export type Constructor< TInstanceType = any, TArgs extends any[] = any[], > = new (...args: TArgs) => TInstanceType; + +/** + * Overrides properties of `T` with properties of `U`. + */ +export type Override = Prettify & U>; + +/** + * Convert members of a union to an intersection. + * + * @example + * ```ts + * type Union = { a: number } | { b: string }; + * type Intersection = UnionToIntersection; + * // { a: number } & { b: string } + * ``` + * + * @privateRemarks + * This works by taking advantage of [distributive conditional + * types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types), + * which allows conditional types to be applied to each member of a union type + * individually, and [contravarience in function argument + * types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html#strict-function-types). + * + * The conditional type `T extends any ? (x: T) => any : never` is used to + * create a function type for each member of the union that takes the member as + * an argument. + * + * Then, the union of function types is checked to see if it can be assigned to + * a single function type with an inferred argument type. TypeScript infers the + * argument type as the intersection of the union members since it's the only + * argument type that satisfies all members of the function type union. + */ +type UnionToIntersection = ( + T extends any ? (member: T) => any : never +) extends (member: infer R) => any + ? R + : never; + +/** + * Merge the keys of a union or intersection of objects into a single type. + * + * @example + * ```ts + * type GetBlockOptions = { + * includeTransactions?: boolean | undefined + * } & ( + * | { + * blockHash?: string | undefined; + * blockNumber?: never | undefined; + * blockTag?: never | undefined; + * } + * | { + * blockHash?: never | undefined; + * blockNumber?: bigint | undefined; + * blockTag?: never | undefined; + * } + * | { + * blockHash?: never | undefined; + * blockNumber?: never | undefined; + * blockTag?: string | undefined; + * } + * ) + * + * type Merged = MergeKeys; + * // { + * // includeTransactions?: boolean | undefined; + * // blockHash?: string | undefined; + * // blockNumber?: bigint | undefined; + * // blockTag?: string | undefined; + * // } + * ``` + */ +export type MergeKeys = + UnionToIntersection extends infer I + ? { + // Each key of the intersection is first checked against the union type, + // T. If it exists in every member of T, then T[K] will be a union of + // the value types. Otherwise, I[K] is used. I[K] is the value type of + // the key in the intersection which will be `never` for keys with + // conflicting value types. + [K in keyof I]: K extends keyof T ? T[K] : I[K]; + } + : never; diff --git a/packages/hyperdrive-js-core/src/checkpoint/types.ts b/packages/hyperdrive-js-core/src/checkpoint/types.ts index 12189c98b..2f3124768 100644 --- a/packages/hyperdrive-js-core/src/checkpoint/types.ts +++ b/packages/hyperdrive-js-core/src/checkpoint/types.ts @@ -1,18 +1,18 @@ import { - ContractEvent, ContractReadOptions, + Event, FunctionReturn, - Pretty, -} from "@delvtech/drift"; +} from "@delvtech/evm-client"; +import { Prettify } from "src/base/types"; import { HyperdriveAbi } from "src/hyperdrive/base/abi"; -export type Checkpoint = Pretty< +export type Checkpoint = Prettify< { checkpointTime: bigint; } & FunctionReturn >; -export type CheckpointEvent = ContractEvent; +export type CheckpointEvent = Event; export type GetCheckpointTimeParams = ( | { diff --git a/packages/hyperdrive-js-core/src/drift/ContractClient.ts b/packages/hyperdrive-js-core/src/drift/ContractClient.ts deleted file mode 100644 index 735b64c52..000000000 --- a/packages/hyperdrive-js-core/src/drift/ContractClient.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SimpleCache } from "@delvtech/drift"; -import { Address } from "abitype"; -import { ReadClientOptions } from "src/drift/ReadClient"; -import { ReadWriteClientOptions } from "src/drift/ReadWriteClient"; - -/** - * Additional options required for clients that represent a specific contract. - */ -export interface ContractClientOptions { - /** - * The address of the contract. - */ - address: Address; - - /** - * The cache to use for the contract. - */ - cache?: SimpleCache; - - /** - * The namespace to use for the cache. - */ - cacheNamespace?: PropertyKey; -} - -export interface ReadContractClientOptions - extends ReadClientOptions, - ContractClientOptions {} - -export interface ReadWriteContractClientOptions - extends ReadWriteClientOptions, - ContractClientOptions {} diff --git a/packages/hyperdrive-js-core/src/drift/ReadWriteClient.ts b/packages/hyperdrive-js-core/src/drift/ReadWriteClient.ts deleted file mode 100644 index fe7cefb63..000000000 --- a/packages/hyperdrive-js-core/src/drift/ReadWriteClient.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Drift, ReadWriteAdapter } from "@delvtech/drift"; -import { ReadClient, ReadClientOptions } from "src/drift/ReadClient"; - -/** - * The base options required for all read-write clients. - */ -export interface ReadWriteClientOptions extends ReadClientOptions { - drift: Drift; -} - -/** - * A base class for read-write clients. - */ -export class ReadWriteClient extends ReadClient { - declare drift: Drift; - - constructor(options: ReadWriteClientOptions) { - super(options); - } -} diff --git a/packages/hyperdrive-js-core/src/errors/BlockNotFoundError.ts b/packages/hyperdrive-js-core/src/errors/BlockNotFoundError.ts index 62f20885d..7c6279a53 100644 --- a/packages/hyperdrive-js-core/src/errors/BlockNotFoundError.ts +++ b/packages/hyperdrive-js-core/src/errors/BlockNotFoundError.ts @@ -1,4 +1,4 @@ -import { NetworkGetBlockOptions } from "@delvtech/drift"; +import { NetworkGetBlockOptions } from "@delvtech/evm-client"; import { HyperdriveSdkError } from "./HyperdriveSdkError"; export class BlockNotFoundError extends HyperdriveSdkError { diff --git a/packages/hyperdrive-js-core/src/errors/HyperdriveSdkError.ts b/packages/hyperdrive-js-core/src/errors/HyperdriveSdkError.ts index 34c045c60..c83978911 100644 --- a/packages/hyperdrive-js-core/src/errors/HyperdriveSdkError.ts +++ b/packages/hyperdrive-js-core/src/errors/HyperdriveSdkError.ts @@ -1,11 +1,6 @@ -import { DriftError } from "@delvtech/drift"; - -export class HyperdriveSdkError extends DriftError { - constructor(message: string, options?: ErrorOptions) { - super(message, { - ...options, - prefix: "ᛋ ", - name: "Hyperdrive SDK Error", - }); +export class HyperdriveSdkError extends Error { + constructor(...[message, options]: Parameters) { + super(message, options); + this.name = "HyperdriveSdkError"; } } diff --git a/packages/hyperdrive-js-core/src/evm-client/contractFactory.ts b/packages/hyperdrive-js-core/src/evm-client/contractFactory.ts new file mode 100644 index 000000000..1c670754e --- /dev/null +++ b/packages/hyperdrive-js-core/src/evm-client/contractFactory.ts @@ -0,0 +1,27 @@ +import { + CachedReadContract, + CachedReadWriteContract, + SimpleCache, +} from "@delvtech/evm-client"; +import { Abi } from "abitype"; + +export interface ContractFactoryOptions { + abi: TAbi; + address: `0x${string}`; + cache?: SimpleCache; + namespace?: string; +} + +/** + * A factory function that creates a `CachedReadContract` instance. + */ +export type ReadContractFactory = ( + options: ContractFactoryOptions, +) => CachedReadContract; + +/** + * A factory function that creates a `CachedReadWriteContract` instance. + */ +export type ReadWriteContractFactory = ( + options: ContractFactoryOptions, +) => CachedReadWriteContract; diff --git a/packages/hyperdrive-js-core/src/evm-client/syncCacheWithTransaction.ts b/packages/hyperdrive-js-core/src/evm-client/syncCacheWithTransaction.ts new file mode 100644 index 000000000..efa681d87 --- /dev/null +++ b/packages/hyperdrive-js-core/src/evm-client/syncCacheWithTransaction.ts @@ -0,0 +1,85 @@ +import { + CachedReadWriteContract, + ContractReadOptions, + FunctionArgs, + FunctionName, +} from "@delvtech/evm-client"; +import { Abi } from "abitype"; + +/** + * Clears the cache and calls the transaction handlers provided to a "Write" + * method on any CachedReadWriteContract class. + * + * This decorator accepts an argument of cache keys to clear. By default it will + * clear the entire cache. + * + * @example + * ```ts + * class ReadWriteFooBar extends CachedReadWriteContract { + * + * // Listen for tx complete and clear the entire cache + * @syncCacheWithTransaction() + * setFoo() { + * return this.contract.write("setFoo", []); + * } + * + * // Listen for tx complete and clear a partial or specific cache entry + * @syncCacheWithTransaction({ cacheEntries: [{ functionName: "getBar" }]}) + * setBar() { + * return this.contract.write("setBar", []); + * } + * } + * ``` + * + * @internal + */ +export function syncCacheWithTransaction(options?: { + cacheEntries?: { + functionName?: FunctionName; + args?: FunctionArgs>; + options?: ContractReadOptions; + }[]; +}) { + return function ( + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any + target: any, + propertyKey: string, + descriptor: PropertyDescriptor, + ): void { + const originalMethod = descriptor.value; + + // Wrap the original method in a function that does the transaction + // side-effects we want after the tx completes + // eslint-disable-next-line @typescript-eslint/no-explicit-any + descriptor.value = async function (...args: any[]) { + // Access the target class instance from within a decorator + // @ts-expect-error The `this` keyword will be the target class instance + const network = this.network; + // @ts-expect-error The `this` keyword will be the target class instance + const contract = this.contract as CachedReadWriteContract; + + // call the original function and await the hash + const hash = await originalMethod.apply(this, args); + + // Dont await this part, we want it to happen in the background once the + // tx is completed + network.waitForTransaction(hash).then(() => { + if (options?.cacheEntries) { + options.cacheEntries.forEach((cacheKey) => { + return contract.deleteReadsMatching( + cacheKey.functionName, + cacheKey.args, + cacheKey.options, + ); + }); + } else { + contract.clearCache(); + } + args[0]?.onTransactionCompleted?.(hash); + }); + + // Return the original method's result hash + return hash; + }; + }; +} diff --git a/packages/hyperdrive-js-core/src/evm-client/utils/getBlockFromReadOptions.ts b/packages/hyperdrive-js-core/src/evm-client/utils/getBlockFromReadOptions.ts new file mode 100644 index 000000000..d5119604d --- /dev/null +++ b/packages/hyperdrive-js-core/src/evm-client/utils/getBlockFromReadOptions.ts @@ -0,0 +1,13 @@ +import { BlockTag, ContractReadOptions } from "@delvtech/evm-client"; + +// TODO: Move this to @delvtech/evm-client +export type BlockLike = BlockTag | bigint; + +/** + * Extracts a block number or block tag from a `ContractReadOptions` object. + */ +export function getBlockFromReadOptions( + options?: ContractReadOptions, +): BlockLike | undefined { + return options?.blockNumber || options?.blockTag; +} diff --git a/packages/hyperdrive-js-core/src/drift/getBlockOrThrow.ts b/packages/hyperdrive-js-core/src/evm-client/utils/getBlockOrThrow.ts similarity index 61% rename from packages/hyperdrive-js-core/src/drift/getBlockOrThrow.ts rename to packages/hyperdrive-js-core/src/evm-client/utils/getBlockOrThrow.ts index d354c93ca..7343d180a 100644 --- a/packages/hyperdrive-js-core/src/drift/getBlockOrThrow.ts +++ b/packages/hyperdrive-js-core/src/evm-client/utils/getBlockOrThrow.ts @@ -1,13 +1,6 @@ -import { - Block, - ContractReadOptions, - Drift, - GetBlockParams, -} from "@delvtech/drift"; +import { Block, Network, NetworkGetBlockOptions } from "@delvtech/evm-client"; import { BlockNotFoundError } from "src/errors/BlockNotFoundError"; -export type GetBlockOrThrowParams = GetBlockParams & ContractReadOptions; - /** * A utility that tries to fetch a block from a given network and throws an * error if no block is found. Useful for unified error handling when fetching @@ -15,10 +8,10 @@ export type GetBlockOrThrowParams = GetBlockParams & ContractReadOptions; * @throws `BlockNotFoundError` */ export async function getBlockOrThrow( - drift: Drift, - options?: GetBlockOrThrowParams, + network: Network, + options?: NetworkGetBlockOptions, ): Promise { - const fetched = await drift.getBlock(options); + const fetched = await network.getBlock(options); if (!fetched) { throw new BlockNotFoundError(options); } diff --git a/packages/hyperdrive-js-core/src/evm-client/utils/isReadWriteContract.ts b/packages/hyperdrive-js-core/src/evm-client/utils/isReadWriteContract.ts new file mode 100644 index 000000000..26057a907 --- /dev/null +++ b/packages/hyperdrive-js-core/src/evm-client/utils/isReadWriteContract.ts @@ -0,0 +1,12 @@ +import { + CachedReadContract, + CachedReadWriteContract, +} from "@delvtech/evm-client"; + +// TODO: Consider better type checking if more use cases arise, possibly with a +// library like zod. +export function isReadWriteContract( + contract: CachedReadContract | CachedReadWriteContract, +): contract is CachedReadWriteContract { + return "write" in contract; +} diff --git a/packages/hyperdrive-js-core/src/exports/contract.ts b/packages/hyperdrive-js-core/src/exports/contract.ts new file mode 100644 index 000000000..0d319d3e3 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/contract.ts @@ -0,0 +1,5 @@ +export type { + ContractFactoryOptions, + ReadContractFactory, + ReadWriteContractFactory, +} from "src/evm-client/contractFactory"; diff --git a/packages/hyperdrive-js-core/src/exports/errors.ts b/packages/hyperdrive-js-core/src/exports/errors.ts new file mode 100644 index 000000000..d12be0f93 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/errors.ts @@ -0,0 +1,3 @@ +export { BlockNotFoundError } from "src/errors/BlockNotFoundError"; +export { HyperdriveSdkError } from "src/errors/HyperdriveSdkError"; +export { MethodNotImplementedError } from "src/errors/MethodNotImplementedError"; diff --git a/packages/hyperdrive-js-core/src/exports/factory/index.ts b/packages/hyperdrive-js-core/src/exports/factory/index.ts new file mode 100644 index 000000000..29cd2058f --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/factory/index.ts @@ -0,0 +1,2 @@ +export * from "./model"; +export * from "./rest"; diff --git a/packages/hyperdrive-js-core/src/exports/factory/model.ts b/packages/hyperdrive-js-core/src/exports/factory/model.ts new file mode 100644 index 000000000..bdbe55aea --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/factory/model.ts @@ -0,0 +1,5 @@ +export { ReadFactory, type ReadFactoryOptions } from "src/factory/ReadFactory"; +export { + ReadWriteFactory, + type ReadWriteFactoryOptions, +} from "src/factory/ReadWriteFactory"; diff --git a/packages/hyperdrive-js-core/src/exports/factory/rest.ts b/packages/hyperdrive-js-core/src/exports/factory/rest.ts new file mode 100644 index 000000000..05e2b407a --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/factory/rest.ts @@ -0,0 +1 @@ +export { factoryAbi, type FactoryAbi } from "src/factory/abi"; diff --git a/packages/hyperdrive-js-core/src/exports/hyperdrive/index.ts b/packages/hyperdrive-js-core/src/exports/hyperdrive/index.ts new file mode 100644 index 000000000..29cd2058f --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/hyperdrive/index.ts @@ -0,0 +1,2 @@ +export * from "./model"; +export * from "./rest"; diff --git a/packages/hyperdrive-js-core/src/exports/hyperdrive/model.ts b/packages/hyperdrive-js-core/src/exports/hyperdrive/model.ts new file mode 100644 index 000000000..a0cfcf284 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/hyperdrive/model.ts @@ -0,0 +1,40 @@ +export { + ReadHyperdrive, + type ReadHyperdriveOptions, +} from "src/hyperdrive/base/ReadHyperdrive"; +export { + ReadWriteHyperdrive, + type ReadWriteHyperdriveOptions, +} from "src/hyperdrive/base/ReadWriteHyperdrive"; + +// erc-4626 +export { ReadErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadErc4626Hyperdrive"; +export { ReadMockErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadMockErc4626Hyperdrive"; +export { ReadWriteErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadWriteErc4626Hyperdrive"; +export { ReadWriteMockErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadWriteMockErc4626Hyperdrive"; + +// ezeth +export { ReadEzEthHyperdrive } from "src/hyperdrive/ezeth/ReadEzEthHyperdrive"; +export { ReadWriteEzEthHyperdrive } from "src/hyperdrive/ezeth/ReadWriteEzEthHyperdrive"; + +// lseth +export { ReadLsEthHyperdrive } from "src/hyperdrive/lseth/ReadLsEthHyperdrive"; +export { ReadWriteLsEthHyperdrive } from "src/hyperdrive/lseth/ReadWriteLsEthHyperdrive"; + +// morpho +export { ReadMetaMorphoHyperdrive } from "src/hyperdrive/metamorpho/ReadMetaMorphoHyperdrive"; +export { ReadWriteMetaMorphoHyperdrive } from "src/hyperdrive/metamorpho/ReadWriteMetaMorphoHyperdrive"; + +// reth +export { ReadREthHyperdrive } from "src/hyperdrive/reth/ReadREthHyperdrive"; +export { ReadWriteREthHyperdrive } from "src/hyperdrive/reth/ReadWriteREthHyperdrive"; + +// steth +export { + ReadStEthHyperdrive, + type ReadStEthHyperdriveOptions, +} from "src/hyperdrive/steth/ReadStEthHyperdrive"; +export { + ReadWriteStEthHyperdrive, + type ReadWriteStEthHyperdriveOptions, +} from "src/hyperdrive/steth/ReadWriteStEthHyperdrive"; diff --git a/packages/hyperdrive-js-core/src/exports/hyperdrive/rest.ts b/packages/hyperdrive-js-core/src/exports/hyperdrive/rest.ts new file mode 100644 index 000000000..55a51a6e8 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/hyperdrive/rest.ts @@ -0,0 +1,34 @@ +export { hyperdriveAbi, type HyperdriveAbi } from "src/hyperdrive/base/abi"; + +// ezeth +export { + ezEthHyperdriveAbi, + type EzEthHyperdriveAbi, +} from "src/hyperdrive/ezeth/abi"; + +// morpho +export { + metaMorphoSnippetsABI, + type MetaMorphoSnippetsABI, +} from "src/hyperdrive/metamorpho/abi"; + +// pool +export type { PoolConfig, PoolInfo } from "src/pool/types"; + +// shorts +export type { ClosedShort, OpenShort, Short } from "src/shorts/types"; + +// longs +export { calculateAprFromPrice } from "src/hyperdrive/utils/calculateAprFromPrice"; +export { calculateMatureLongYieldAfterFees } from "src/longs/calculateMatureLongYieldAfterFees"; +export type { + ClosedLong, + Long, + OpenLongPositionReceived, +} from "src/longs/types"; + +// lp +export type { ClosedLpShares } from "src/lp/ClosedLpShares"; + +// withdrawal shares +export type { RedeemedWithdrawalShares } from "src/withdrawalShares/RedeemedWithdrawalShares"; diff --git a/packages/hyperdrive-js-core/src/exports/index.ts b/packages/hyperdrive-js-core/src/exports/index.ts index 130e054af..8fd78ac3a 100644 --- a/packages/hyperdrive-js-core/src/exports/index.ts +++ b/packages/hyperdrive-js-core/src/exports/index.ts @@ -1,165 +1,8 @@ -// Hyperdrive // - -export { - getHyperdrive, - type Hyperdrive, - type HyperdriveOptions, -} from "src/hyperdrive/getHyperdrive"; - -export { hyperdriveAbi, type HyperdriveAbi } from "src/hyperdrive/base/abi"; -export { - ReadHyperdrive, - type ReadHyperdriveOptions, -} from "src/hyperdrive/base/ReadHyperdrive"; -export { - ReadWriteHyperdrive, - type ReadWriteHyperdriveOptions, -} from "src/hyperdrive/base/ReadWriteHyperdrive"; - -// erc-4626 -export { ReadErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadErc4626Hyperdrive"; -export { ReadMockErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadMockErc4626Hyperdrive"; -export { ReadWriteErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadWriteErc4626Hyperdrive"; -export { ReadWriteMockErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadWriteMockErc4626Hyperdrive"; - -// ezeth -export { - ezEthHyperdriveAbi, - type EzEthHyperdriveAbi, -} from "src/hyperdrive/ezeth/abi"; -export { ReadEzEthHyperdrive } from "src/hyperdrive/ezeth/ReadEzEthHyperdrive"; -export { ReadWriteEzEthHyperdrive } from "src/hyperdrive/ezeth/ReadWriteEzEthHyperdrive"; - -// lseth -export { ReadLsEthHyperdrive } from "src/hyperdrive/lseth/ReadLsEthHyperdrive"; -export { ReadWriteLsEthHyperdrive } from "src/hyperdrive/lseth/ReadWriteLsEthHyperdrive"; - -// reth -export { ReadREthHyperdrive } from "src/hyperdrive/reth/ReadREthHyperdrive"; -export { ReadWriteREthHyperdrive } from "src/hyperdrive/reth/ReadWriteREthHyperdrive"; - -// steth -export { - ReadStEthHyperdrive, - type ReadStEthHyperdriveOptions, -} from "src/hyperdrive/steth/ReadStEthHyperdrive"; -export { - ReadWriteStEthHyperdrive, - type ReadWriteStEthHyperdriveOptions, -} from "src/hyperdrive/steth/ReadWriteStEthHyperdrive"; - -export { calculateAprFromPrice } from "src/hyperdrive/utils/calculateAprFromPrice"; - -// pool -export type { PoolConfig, PoolInfo } from "src/pool/types"; - -// shorts -export type { ClosedShort, OpenShort, Short } from "src/shorts/types"; - -// longs -export { calculateMatureLongYieldAfterFees } from "src/longs/calculateMatureLongYieldAfterFees"; -export type { - ClosedLong, - Long, - OpenLongPositionReceived, -} from "src/longs/types"; - -// lp -export type { ClosedLpShares } from "src/lp/ClosedLpShares"; - -// withdrawal shares -export type { RedeemedWithdrawalShares } from "src/withdrawalShares/RedeemedWithdrawalShares"; - -// Registry // - -export { registryAbi, type RegistryAbi } from "src/registry/abi"; -export { - ReadRegistry, - type ReadRegistryOptions, -} from "src/registry/ReadRegistry"; -export { - ReadWriteRegistry, - type ReadWriteRegistryOptions, -} from "src/registry/ReadWriteRegistry"; - -// Factory // - -export { factoryAbi, type FactoryAbi } from "src/factory/abi"; -export { ReadFactory, type ReadFactoryOptions } from "src/factory/ReadFactory"; -export { - ReadWriteFactory, - type ReadWriteFactoryOptions, -} from "src/factory/ReadWriteFactory"; - -// Token // - -export type { ReadToken } from "src/token/ReadToken"; -export type { ReadWriteToken } from "src/token/ReadWriteToken"; - -// eth -export { ReadEth, type ReadEthOptions } from "src/token/eth/ReadEth"; -export { - ReadWriteEth, - type ReadWriteEthOptions, -} from "src/token/eth/ReadWriteEth"; - -// erc-20 -export { erc20Abi, type Erc20Abi } from "src/token/erc20/abi"; -export { ReadErc20, type ReadErc20Options } from "src/token/erc20/ReadErc20"; -export { - ReadWriteErc20, - type ReadWriteErc20Options, -} from "src/token/erc20/ReadWriteErc20"; - -// erc-4626 -export { - erc4626Abi, - mockErc4626Abi, - type Erc4626Abi, - type MockErc4626Abi, -} from "src/token/erc4626/abi"; -export { ReadErc4626 } from "src/token/erc4626/ReadErc4626"; -export { ReadMockErc4626 } from "src/token/erc4626/ReadMockErc4626"; -export { ReadWriteErc4626 } from "src/token/erc4626/ReadWriteErc4626"; -export { ReadWriteMockErc4626 } from "src/token/erc4626/ReadWriteMockErc4626"; - -// lseth -export { lsEthAbi, type LsEthAbi } from "src/token/lseth/abi"; -export { ReadLsEth } from "src/token/lseth/ReadLsEth"; -export { ReadWriteLsEth } from "src/token/lseth/ReadWriteLsEth"; - -// reth -export { rEthAbi, type REthAbi } from "src/token/reth/abi"; -export { ReadREth } from "src/token/reth/ReadREth"; -export { ReadWriteREth } from "src/token/reth/ReadWriteREth"; - -// steth -export { stEthAbi, type StEthAbi } from "src/token/steth/abi"; -export { ReadStEth } from "src/token/steth/ReadStEth"; -export { ReadWriteStEth } from "src/token/steth/ReadWriteStEth"; - -// Errors // - -export { BlockNotFoundError } from "src/errors/BlockNotFoundError"; -export { HyperdriveSdkError } from "src/errors/HyperdriveSdkError"; -export { MethodNotImplementedError } from "src/errors/MethodNotImplementedError"; - -// Drift // - -export type { - ContractClientOptions, - ReadContractClientOptions, - ReadWriteContractClientOptions, -} from "src/drift/ContractClient"; -export { ReadClient, type ReadClientOptions } from "src/drift/ReadClient"; -export { - ReadWriteClient, - type ReadWriteClientOptions, -} from "src/drift/ReadWriteClient"; - -// Base // - -export { adjustAmountByPercentage } from "src/base/adjustAmountByPercentage"; -export { getHprFromApr } from "src/base/getHprFromApr"; -export { getHprFromApy } from "src/base/getHprFromApy"; -export type { Constructor } from "src/base/types"; +export * from "./contract"; +export * from "./errors"; +export * from "./factory"; +export * from "./hyperdrive"; +export * from "./model"; +export * from "./registry"; +export * from "./token"; +export * from "./utils"; diff --git a/packages/hyperdrive-js-core/src/exports/model.ts b/packages/hyperdrive-js-core/src/exports/model.ts new file mode 100644 index 000000000..24ba9e724 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/model.ts @@ -0,0 +1,10 @@ +export { + ReadModel, + type ReadContractModelOptions, + type ReadModelOptions, +} from "src/model/ReadModel"; +export { + ReadWriteModel, + type ReadWriteContractModelOptions, + type ReadWriteModelOptions, +} from "src/model/ReadWriteModel"; diff --git a/packages/hyperdrive-js-core/src/exports/registry/index.ts b/packages/hyperdrive-js-core/src/exports/registry/index.ts new file mode 100644 index 000000000..29cd2058f --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/registry/index.ts @@ -0,0 +1,2 @@ +export * from "./model"; +export * from "./rest"; diff --git a/packages/hyperdrive-js-core/src/exports/registry/model.ts b/packages/hyperdrive-js-core/src/exports/registry/model.ts new file mode 100644 index 000000000..194822a85 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/registry/model.ts @@ -0,0 +1,8 @@ +export { + ReadRegistry, + type ReadRegistryOptions, +} from "src/registry/ReadRegistry"; +export { + ReadWriteRegistry, + type ReadWriteRegistryOptions, +} from "src/registry/ReadWriteRegistry"; diff --git a/packages/hyperdrive-js-core/src/exports/registry/rest.ts b/packages/hyperdrive-js-core/src/exports/registry/rest.ts new file mode 100644 index 000000000..29e3390b5 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/registry/rest.ts @@ -0,0 +1 @@ +export { registryAbi, type RegistryAbi } from "src/registry/abi"; diff --git a/packages/hyperdrive-js-core/src/exports/token/index.ts b/packages/hyperdrive-js-core/src/exports/token/index.ts new file mode 100644 index 000000000..29cd2058f --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/token/index.ts @@ -0,0 +1,2 @@ +export * from "./model"; +export * from "./rest"; diff --git a/packages/hyperdrive-js-core/src/exports/token/model.ts b/packages/hyperdrive-js-core/src/exports/token/model.ts new file mode 100644 index 000000000..fd8033027 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/token/model.ts @@ -0,0 +1,34 @@ +export type { ReadToken } from "src/token/ReadToken"; +export type { ReadWriteToken } from "src/token/ReadWriteToken"; + +// eth +export { ReadEth, type ReadEthOptions } from "src/token/eth/ReadEth"; +export { + ReadWriteEth, + type ReadWriteEthOptions, +} from "src/token/eth/ReadWriteEth"; + +// erc-20 +export { ReadErc20, type ReadErc20Options } from "src/token/erc20/ReadErc20"; +export { + ReadWriteErc20, + type ReadWriteErc20Options, +} from "src/token/erc20/ReadWriteErc20"; + +// erc-4626 +export { ReadErc4626 } from "src/token/erc4626/ReadErc4626"; +export { ReadMockErc4626 } from "src/token/erc4626/ReadMockErc4626"; +export { ReadWriteErc4626 } from "src/token/erc4626/ReadWriteErc4626"; +export { ReadWriteMockErc4626 } from "src/token/erc4626/ReadWriteMockErc4626"; + +// lseth +export { ReadLsEth } from "src/token/lseth/ReadLsEth"; +export { ReadWriteLsEth } from "src/token/lseth/ReadWriteLsEth"; + +// reth +export { ReadREth } from "src/token/reth/ReadREth"; +export { ReadWriteREth } from "src/token/reth/ReadWriteREth"; + +// steth +export { ReadStEth } from "src/token/steth/ReadStEth"; +export { ReadWriteStEth } from "src/token/steth/ReadWriteStEth"; diff --git a/packages/hyperdrive-js-core/src/exports/token/rest.ts b/packages/hyperdrive-js-core/src/exports/token/rest.ts new file mode 100644 index 000000000..317a005ad --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/token/rest.ts @@ -0,0 +1,19 @@ +// erc-20 +export { erc20Abi, type Erc20Abi } from "src/token/erc20/abi"; + +// erc-4626 +export { + erc4626Abi, + mockErc4626Abi, + type Erc4626Abi, + type MockErc4626Abi, +} from "src/token/erc4626/abi"; + +// lseth +export { lsEthAbi, type LsEthAbi } from "src/token/lseth/abi"; + +// reth +export { rEthAbi, type REthAbi } from "src/token/reth/abi"; + +// steth +export { stEthAbi, type StEthAbi } from "src/token/steth/abi"; diff --git a/packages/hyperdrive-js-core/src/exports/utils.ts b/packages/hyperdrive-js-core/src/exports/utils.ts new file mode 100644 index 000000000..0acd4a93c --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/utils.ts @@ -0,0 +1,13 @@ +export { adjustAmountByPercentage } from "src/base/adjustAmountByPercentage"; +export { getHprFromApr } from "src/base/getHprFromApr"; +export { getHprFromApy } from "src/base/getHprFromApy"; +export { calculateAprFromPrice } from "src/hyperdrive/utils/calculateAprFromPrice"; +export { calculateMatureLongYieldAfterFees } from "src/longs/calculateMatureLongYieldAfterFees"; + +// types +export type { + Constructor, + MergeKeys, + Override, + Prettify, +} from "src/base/types"; diff --git a/packages/hyperdrive-js-core/src/exports/v1.0.14/hyperdrive/index.ts b/packages/hyperdrive-js-core/src/exports/v1.0.14/hyperdrive/index.ts new file mode 100644 index 000000000..b6837c3e2 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/v1.0.14/hyperdrive/index.ts @@ -0,0 +1 @@ +export * from "./model"; diff --git a/packages/hyperdrive-js-core/src/exports/v1.0.14.ts b/packages/hyperdrive-js-core/src/exports/v1.0.14/hyperdrive/model.ts similarity index 92% rename from packages/hyperdrive-js-core/src/exports/v1.0.14.ts rename to packages/hyperdrive-js-core/src/exports/v1.0.14/hyperdrive/model.ts index ccd7f5935..d041c708d 100644 --- a/packages/hyperdrive-js-core/src/exports/v1.0.14.ts +++ b/packages/hyperdrive-js-core/src/exports/v1.0.14/hyperdrive/model.ts @@ -16,6 +16,9 @@ export { ReadWriteEzEthHyperdrive_v1_0_14 } from "src/hyperdrive/ezeth/v1.0.14/R export { ReadLsEthHyperdrive_v1_0_14 } from "src/hyperdrive/lseth/v1.0.14/ReadLsEthHyperdrive_v1_0_14"; export { ReadWriteLsEthHyperdrive_v1_0_14 } from "src/hyperdrive/lseth/v1.0.14/ReadWriteLsEthHyperdrive_v1_0_14"; +// morpho +export { ReadMetaMorphoHyperdrive_v1_0_14 } from "src/hyperdrive/metamorpho/v1.0.14/ReadMetaMorphoHyperdrive_v1_0_14"; + // reth export { ReadREthHyperdrive_v1_0_14 } from "src/hyperdrive/reth/v1.0.14/ReadREthHyperdrive_v1_0_14"; export { ReadWriteREthHyperdrive_v1_0_14 } from "src/hyperdrive/reth/v1.0.14/ReadWriteREthHyperdrive_v1_0_14"; diff --git a/packages/hyperdrive-js-core/src/exports/v1.0.14/index.ts b/packages/hyperdrive-js-core/src/exports/v1.0.14/index.ts new file mode 100644 index 000000000..85fbc6375 --- /dev/null +++ b/packages/hyperdrive-js-core/src/exports/v1.0.14/index.ts @@ -0,0 +1 @@ +export * from "./hyperdrive"; diff --git a/packages/hyperdrive-js-core/src/factory/ReadFactory.ts b/packages/hyperdrive-js-core/src/factory/ReadFactory.ts index dc3812d28..515729686 100644 --- a/packages/hyperdrive-js-core/src/factory/ReadFactory.ts +++ b/packages/hyperdrive-js-core/src/factory/ReadFactory.ts @@ -1,30 +1,29 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Address } from "abitype"; -import { ReadContractClientOptions } from "src/drift/ContractClient"; -import { ReadClient } from "src/drift/ReadClient"; import { FactoryAbi, factoryAbi } from "src/factory/abi"; import { ReadHyperdrive } from "src/hyperdrive/base/ReadHyperdrive"; +import { ReadContractModelOptions, ReadModel } from "src/model/ReadModel"; -export interface ReadFactoryOptions extends ReadContractClientOptions {} +export interface ReadFactoryOptions extends ReadContractModelOptions {} -export class ReadFactory extends ReadClient { +export class ReadFactory extends ReadModel { address: Address; - contract: Contract; + contract: CachedReadContract; constructor({ debugName = "Hyperdrive Factory", address, cache, - cacheNamespace, - ...rest + namespace, + ...modelOptions }: ReadFactoryOptions) { - super({ debugName, ...rest }); + super({ debugName, ...modelOptions }); this.address = address; - this.contract = this.drift.contract({ + this.contract = this.contractFactory({ abi: factoryAbi, address, cache, - cacheNamespace, + namespace, }); } @@ -99,9 +98,8 @@ export class ReadFactory extends ReadClient { (address) => new ReadHyperdrive({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), ); } diff --git a/packages/hyperdrive-js-core/src/factory/ReadWriteFactory.ts b/packages/hyperdrive-js-core/src/factory/ReadWriteFactory.ts index 04036fbcc..be6f7193c 100644 --- a/packages/hyperdrive-js-core/src/factory/ReadWriteFactory.ts +++ b/packages/hyperdrive-js-core/src/factory/ReadWriteFactory.ts @@ -1,21 +1,20 @@ import { + CachedReadWriteContract, ContractReadOptions, - Drift, - ReadWriteAdapter, - ReadWriteContract, - ReplaceProps, -} from "@delvtech/drift"; -import { ReadWriteContractClientOptions } from "src/drift/ContractClient"; +} from "@delvtech/evm-client"; +import { Override } from "src/base/types"; +import { ReadWriteContractFactory } from "src/evm-client/contractFactory"; import { ReadFactory, ReadFactoryOptions } from "src/factory/ReadFactory"; import { FactoryAbi } from "src/factory/abi"; import { ReadWriteHyperdrive } from "src/hyperdrive/base/ReadWriteHyperdrive"; +import { ReadWriteContractModelOptions } from "src/model/ReadWriteModel"; export interface ReadWriteFactoryOptions - extends ReplaceProps {} + extends Override {} export class ReadWriteFactory extends ReadFactory { - declare contract: ReadWriteContract; - declare drift: Drift; + declare contract: CachedReadWriteContract; + declare contractFactory: ReadWriteContractFactory; constructor(options: ReadWriteFactoryOptions) { super(options); @@ -26,17 +25,16 @@ export class ReadWriteFactory extends ReadFactory { * deployed by the deployer factory. */ async getInstances( - options?: ContractReadOptions, + options?: ContractReadOptions ): Promise { const hyperdriveAddresses = await this.getInstanceAddresses(options); return hyperdriveAddresses.map( (address) => new ReadWriteHyperdrive({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, - }), + contractFactory: this.contractFactory, + network: this.network, + }) ); } } diff --git a/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.test.ts b/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.test.ts index 881928679..70077a91d 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.test.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.test.ts @@ -1,7 +1,6 @@ -import { ZERO_ADDRESS } from "@delvtech/drift"; -import { fixed, parseFixed } from "@delvtech/fixed-point-wasm"; import { ALICE, BOB } from "src/base/testing/accounts"; import { CheckpointEvent } from "src/checkpoint/types"; +import { fixed, parseFixed } from "src/fixed-point"; import { setupReadHyperdrive } from "src/hyperdrive/base/testing/setupReadHyperdrive"; import { decodeAssetFromTransferSingleEventData } from "src/pool/decodeAssetFromTransferSingleEventData"; import { @@ -14,7 +13,10 @@ import { assert, expect, test } from "vitest"; test("getVersion should return the parsed version of the contract", async () => { const { contract, readHyperdrive } = setupReadHyperdrive(); - contract.onRead("version").resolves("v1.0.14"); + contract.stubRead({ + functionName: "version", + value: "v1.0.14", + }); const value = await readHyperdrive.getVersion(); expect(value).toEqual({ @@ -32,7 +34,10 @@ test("getPoolConfig should return the PoolConfig from the contract as-is", async const { contract, readHyperdrive } = setupReadHyperdrive(); // stub out the contract call the sdk is going to make - contract.onRead("getPoolConfig").resolves(simplePoolConfig7Days); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig7Days, + }); // The sdk should return the correct data const value = await readHyperdrive.getPoolConfig(); @@ -45,7 +50,10 @@ test("getPoolConfig should return the PoolConfig from the contract as-is", async test("getPoolInfo should return the PoolInfo from the contract as-is", async () => { const { contract, readHyperdrive } = setupReadHyperdrive(); - contract.onRead("getPoolInfo").resolves(simplePoolInfo); + contract.stubRead({ + functionName: "getPoolInfo", + value: simplePoolInfo, + }); const value = await readHyperdrive.getPoolInfo(); expect(value).toBe(simplePoolInfo); @@ -58,8 +66,14 @@ test("getFixedRate should get the fixed rate as-is", async () => { // These are necessary to stub, but the values won't be used since we stub // calculateAPRFromReserves directly - contract.onRead("getPoolConfig").resolves(simplePoolConfig7Days); - contract.onRead("getPoolInfo").resolves(simplePoolInfo); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig7Days, + }); + contract.stubRead({ + functionName: "getPoolInfo", + value: simplePoolInfo, + }); const value = await readHyperdrive.getFixedApr(); expect(value).toBe(50000000000000000n); @@ -68,7 +82,7 @@ test("getFixedRate should get the fixed rate as-is", async () => { test("getTradingVolume should get the trading volume in terms of bonds", async () => { const { contract, readHyperdrive } = setupReadHyperdrive(); - contract.onGetEvents("OpenLong").resolves([ + contract.stubEvents("OpenLong", {}, [ { eventName: "OpenLong", args: { @@ -97,7 +111,7 @@ test("getTradingVolume should get the trading volume in terms of bonds", async ( }, ]); - contract.onGetEvents("CloseLong").resolves([ + contract.stubEvents("CloseLong", {}, [ { eventName: "CloseLong", args: { @@ -116,7 +130,7 @@ test("getTradingVolume should get the trading volume in terms of bonds", async ( }, ]); - contract.onGetEvents("OpenShort").resolves([ + contract.stubEvents("OpenShort", {}, [ { eventName: "OpenShort", args: { @@ -147,7 +161,7 @@ test("getTradingVolume should get the trading volume in terms of bonds", async ( }, ]); - contract.onGetEvents("CloseShort").resolves([]); + contract.stubEvents("CloseShort", {}, []); const value = await readHyperdrive.getTradingVolume(); @@ -159,27 +173,35 @@ test("getTradingVolume should get the trading volume in terms of bonds", async ( }); test("getShortAccruedYield should return the amount of yield a non-mature position has earned", async () => { - const { contract, drift, readHyperdrive } = setupReadHyperdrive(); + const { contract, network, readHyperdrive } = setupReadHyperdrive(); - drift.onGetBlock().resolves({ blockNumber: 1n, timestamp: 100n }); + network.stubGetBlock({ + value: { blockNumber: 1n, timestamp: 100n }, + }); - contract.onRead("getPoolConfig").resolves({ - ...simplePoolConfig7Days, - positionDuration: 86400n, // one day in seconds - checkpointDuration: 86400n, // one day in seconds + contract.stubRead({ + functionName: "getPoolConfig", + value: { + ...simplePoolConfig7Days, + positionDuration: 86400n, // one day in seconds + checkpointDuration: 86400n, // one day in seconds + }, }); // The pool info gives us the current price - contract.onRead("getPoolInfo").resolves({ - ...simplePoolInfo, - vaultSharePrice: parseFixed("1.01").bigint, + contract.stubRead({ + functionName: "getPoolInfo", + value: { ...simplePoolInfo, vaultSharePrice: parseFixed("1.01").bigint }, }); // The checkpoint gives us the price when the bond was opened - contract.onRead("getCheckpoint").resolves({ - vaultSharePrice: parseFixed("1.008").bigint, - weightedSpotPrice: 0n, - lastWeightedSpotPriceUpdateTime: 0n, + contract.stubRead({ + functionName: "getCheckpoint", + value: { + vaultSharePrice: parseFixed("1.008").bigint, + weightedSpotPrice: 0n, + lastWeightedSpotPriceUpdateTime: 0n, + }, }); const accruedYield = await readHyperdrive.getShortAccruedYield({ @@ -194,28 +216,40 @@ test("getShortAccruedYield should return the amount of yield a non-mature positi }); test("getShortAccruedYield should return the amount of yield a mature position has earned", async () => { - const { drift, contract, readHyperdrive } = setupReadHyperdrive(); - - drift.onGetBlock().resolves({ blockNumber: 1n, timestamp: 1699503565n }); + const { network, contract, readHyperdrive } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves({ - ...simplePoolConfig7Days, - positionDuration: 86400n, // one day in seconds - checkpointDuration: 86400n, // one day in seconds + network.stubGetBlock({ + value: { blockNumber: 1n, timestamp: 1699503565n }, + }); + contract.stubRead({ + functionName: "getPoolConfig", + value: { + ...simplePoolConfig7Days, + positionDuration: 86400n, // one day in seconds + checkpointDuration: 86400n, // one day in seconds + }, }); // This checkpoint gives us the price when the short was opened - contract.onRead("getCheckpoint", { _checkpointTime: 1n }).resolves({ - vaultSharePrice: parseFixed("1.008").bigint, - weightedSpotPrice: 0n, - lastWeightedSpotPriceUpdateTime: 0n, + contract.stubRead({ + functionName: "getCheckpoint", + args: { _checkpointTime: 1n }, + value: { + vaultSharePrice: parseFixed("1.008").bigint, + weightedSpotPrice: 0n, + lastWeightedSpotPriceUpdateTime: 0n, + }, }); // This checkpoint gives us the price when the shorts matured - contract.onRead("getCheckpoint", { _checkpointTime: 86401n }).resolves({ - vaultSharePrice: parseFixed("1.01").bigint, - weightedSpotPrice: 0n, - lastWeightedSpotPriceUpdateTime: 0n, + contract.stubRead({ + functionName: "getCheckpoint", + args: { _checkpointTime: 86401n }, + value: { + vaultSharePrice: parseFixed("1.01").bigint, + weightedSpotPrice: 0n, + lastWeightedSpotPriceUpdateTime: 0n, + }, }); const accruedYield = await readHyperdrive.getShortAccruedYield({ @@ -253,7 +287,7 @@ test("getCheckpointEvents should return an array of CheckpointEvents", async () }, }, ] as CheckpointEvent[]; - contract.onGetEvents("CreateCheckpoint").resolves(checkPointEvents); + contract.stubEvents("CreateCheckpoint", undefined, checkPointEvents); const events = await readHyperdrive.getCheckpointEvents(); @@ -272,7 +306,7 @@ test("getOpenLongs should account for longs opened with base", async () => { const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { eventName: "OpenLong", args: { @@ -304,7 +338,7 @@ test("getOpenLongs should account for longs opened with base", async () => { }, }, ]); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([]); + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, []); const value = await readHyperdrive.getOpenLongs({ account: BOB }); @@ -330,7 +364,7 @@ test("getOpenLongs should account for longs opened with shares", async () => { const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { eventName: "OpenLong", args: { @@ -364,7 +398,7 @@ test("getOpenLongs should account for longs opened with shares", async () => { ]); // Bob has not closed the position at all, these are just stubbed out - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([]); + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, []); const value = await readHyperdrive.getOpenLongs({ account: BOB }); expect(value).toEqual([ @@ -376,7 +410,6 @@ test("getOpenLongs should account for longs opened with shares", async () => { }, ]); }); - test("getOpenLongs should account for longs partially closed to base", async () => { // Description: // Bob opens up a long position over 2 txs in the same checkpoint, for a total @@ -389,7 +422,7 @@ test("getOpenLongs should account for longs partially closed to base", async () const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { eventName: "OpenLong", args: { @@ -422,7 +455,7 @@ test("getOpenLongs should account for longs partially closed to base", async () }, }, ]); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { eventName: "CloseLong", args: { @@ -468,7 +501,7 @@ test("getOpenLongs should account for longs fully closed to base", async () => { const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { eventName: "OpenLong", args: { @@ -501,7 +534,7 @@ test("getOpenLongs should account for longs fully closed to base", async () => { }, }, ]); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { eventName: "CloseLong", args: { @@ -522,7 +555,7 @@ test("getOpenLongs should account for longs fully closed to base", async () => { }, ]); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { eventName: "OpenLong", args: { @@ -556,7 +589,7 @@ test("getOpenLongs should account for longs fully closed to base", async () => { }, ]); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { eventName: "CloseLong", args: { @@ -589,7 +622,7 @@ test("getOpenLongs should handle when user fully closes then re-opens a position const { contract, readHyperdrive } = setupReadHyperdrive(); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { args: { extraData: "0x", @@ -628,7 +661,7 @@ test("getOpenLongs should handle when user fully closes then re-opens a position } as const, ]); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { args: { extraData: "0x", @@ -675,7 +708,7 @@ test("getOpenLongs should account for longs partially closed to shares", async ( const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { eventName: "OpenLong", args: { @@ -693,7 +726,7 @@ test("getOpenLongs should account for longs partially closed to shares", async ( }, ]); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { eventName: "CloseLong", blockNumber: 5n, @@ -738,7 +771,7 @@ test("getOpenLongs should account for longs fully closed to shares", async () => const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("OpenLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("OpenLong", { filter: { trader: BOB } }, [ { eventName: "OpenLong", args: { @@ -757,7 +790,7 @@ test("getOpenLongs should account for longs fully closed to shares", async () => }, ]); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { eventName: "CloseLong", blockNumber: 5n, @@ -787,13 +820,13 @@ test("getOpenLongs should account for longs fully closed to shares", async () => test("getClosedLongs should account for closing out to base", async () => { // Description: // Bob closes a long position of 2 bonds and receives back 2.2 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { eventName: "CloseLong", blockNumber: 5n, @@ -814,7 +847,7 @@ test("getClosedLongs should account for closing out to base", async () => { }, }, ]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getClosedLongs({ account: BOB }); expect(value).toEqual([ { @@ -833,13 +866,13 @@ test("getClosedLongs should account for closing out to shares", async () => { // Bob closes a long position of 2 bonds and receives back 1.9 shares. Shares // are worth 1.1 base at the time he closes, therefore his closed position is // valued at 2.09 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); const eventData = "0x0100000000000000000000000000000000000000000000000000000065d65640000000000000000000000000000000000000000000000001bc82c3277b2dc665"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onGetEvents("CloseLong", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseLong", { filter: { trader: BOB } }, [ { eventName: "CloseLong", blockNumber: 5n, @@ -862,7 +895,7 @@ test("getClosedLongs should account for closing out to shares", async () => { ]); // getBlock gives us the timestamp of when he closed the position - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getClosedLongs({ account: BOB }); expect(value).toEqual([ @@ -882,10 +915,13 @@ test("getOpenShorts should account for shorts opened with base", async () => { // Bob opens up a short position for 100 bonds over 2 txs in the same // checkpoint, for a total cost of around 1.44 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); - contract.onGetEvents("OpenShort", { filter: { trader: BOB } }).resolves([ + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); + contract.stubEvents("OpenShort", { filter: { trader: BOB } }, [ { eventName: "OpenShort", blockNumber: 1n, @@ -918,11 +954,13 @@ test("getOpenShorts should account for shorts opened with base", async () => { }, ]); - contract.onGetEvents("CloseShort", { filter: { trader: BOB } }).resolves([]); + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, []); - drift.onGetBlock().resolves({ - timestamp: 1713801432n, - blockNumber: 1n, + network.stubGetBlock({ + value: { + timestamp: 1713801432n, + blockNumber: 1n, + }, }); const value = await readHyperdrive.getOpenShorts({ account: BOB }); @@ -935,7 +973,7 @@ test("getOpenShorts should account for shorts opened with base", async () => { bondAmount: parseFixed("100").bigint, baseProceeds: parseFixed("98.576966043666144584").bigint, fixedRatePaid: parseFixed("0.175635145784387390").bigint, - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", maturity: 1716336000n, openedTimestamp: 1713801432n, }, @@ -947,10 +985,13 @@ test("getOpenShorts should account for shorts opened with shares", async () => { // Bob opens up a short position for 100 bonds over 2 txs in the same // checkpoint, for a total cost of around 1.44 shares. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); - contract.onGetEvents("OpenShort", { filter: { trader: BOB } }).resolves([ + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); + contract.stubEvents("OpenShort", { filter: { trader: BOB } }, [ { eventName: "OpenShort", blockNumber: 1n, @@ -983,11 +1024,13 @@ test("getOpenShorts should account for shorts opened with shares", async () => { }, ]); - contract.onGetEvents("CloseShort", { filter: { trader: BOB } }).resolves([]); + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, []); - drift.onGetBlock().resolves({ - timestamp: 1713801432n, - blockNumber: 1n, + network.stubGetBlock({ + value: { + timestamp: 1713801432n, + blockNumber: 1n, + }, }); const value = await readHyperdrive.getOpenShorts({ account: BOB }); @@ -1000,7 +1043,7 @@ test("getOpenShorts should account for shorts opened with shares", async () => { bondAmount: parseFixed("100").bigint, baseProceeds: parseFixed("98.576966043666144584").bigint, fixedRatePaid: parseFixed("0.175635145784387390").bigint, - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", maturity: 1716336000n, openedTimestamp: 1713801432n, }, @@ -1012,9 +1055,12 @@ test("getOpenShorts should account for shorts partially closed to base", async ( // Bob shorts 50 bonds for a total cost of 0.73 base. He then partially // closes this position, redeeming 25 bonds for 0.36 base. As a result, he has 25 // bonds left with a total cost of 0.37 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); const events = [ { @@ -1050,14 +1096,10 @@ test("getOpenShorts should account for shorts partially closed to base", async ( }, ] as const; - contract - .onGetEvents("OpenShort", { filter: { trader: BOB } }) - .resolves([events[0]]); - contract - .onGetEvents("CloseShort", { filter: { trader: BOB } }) - .resolves([events[1]]); + contract.stubEvents("OpenShort", { filter: { trader: BOB } }, [events[0]]); + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, [events[1]]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getOpenShorts({ account: BOB }); expect(value).toEqual([ @@ -1067,7 +1109,7 @@ test("getOpenShorts should account for shorts partially closed to base", async ( baseAmountPaid: parseFixed("0.367919766722905778").bigint, baseProceeds: parseFixed("24.637035274042034163").bigint, checkpointTime: 123454800n, - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", fixedRatePaid: parseFixed("0.179245221000329770").bigint, maturity: 1716336000n, openedTimestamp: 123456789n, @@ -1079,9 +1121,12 @@ test("getOpenShorts should account for shorts fully closed to base", async () => // Description: // Bob opens up a short position, then completely closes this position, As a // result, he no longer has any open short positions. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); const events = [ { @@ -1117,14 +1162,10 @@ test("getOpenShorts should account for shorts fully closed to base", async () => }, ] as const; - contract - .onGetEvents("OpenShort", { filter: { trader: BOB } }) - .resolves([events[0]]); - contract - .onGetEvents("CloseShort", { filter: { trader: BOB } }) - .resolves([events[1]]); + contract.stubEvents("OpenShort", { filter: { trader: BOB } }, [events[0]]); + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, [events[1]]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getOpenShorts({ account: BOB }); expect(value).toEqual([]); @@ -1135,9 +1176,12 @@ test("getOpenShorts should account for shorts partially closed to shares", async // Bob shorts 50 bonds for a total cost of 0.73 base. He then partially // closes this position, redeeming 25 bonds for 0.36 shares. As a result, he // has 25 bonds left with a total cost of 0.37 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); const events = [ { @@ -1173,14 +1217,10 @@ test("getOpenShorts should account for shorts partially closed to shares", async }, ] as const; - contract - .onGetEvents("OpenShort", { filter: { trader: BOB } }) - .resolves([events[0]]); - contract - .onGetEvents("CloseShort", { filter: { trader: BOB } }) - .resolves([events[1]]); + contract.stubEvents("OpenShort", { filter: { trader: BOB } }, [events[0]]); + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, [events[1]]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getOpenShorts({ account: BOB }); expect(value).toEqual([ @@ -1190,7 +1230,7 @@ test("getOpenShorts should account for shorts partially closed to shares", async baseAmountPaid: parseFixed("0.367919766723039831").bigint, baseProceeds: parseFixed("24.637035274042034163").bigint, checkpointTime: 123454800n, - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", fixedRatePaid: parseFixed("0.179245221000329770").bigint, maturity: 1716336000n, openedTimestamp: 123456789n, @@ -1203,9 +1243,12 @@ test("getOpenShorts should account for shorts fully closed to shares", async () // Bob opens up a short position, then completely closes this position, As a // result, he no longer has any open short positions. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); const events = [ { eventName: "OpenShort", @@ -1240,14 +1283,10 @@ test("getOpenShorts should account for shorts fully closed to shares", async () }, ] as const; - contract - .onGetEvents("OpenShort", { filter: { trader: BOB } }) - .resolves([events[0]]); - contract - .onGetEvents("CloseShort", { filter: { trader: BOB } }) - .resolves([events[1]]); + contract.stubEvents("OpenShort", { filter: { trader: BOB } }, [events[0]]); + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, [events[1]]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getOpenShorts({ account: BOB }); expect(value).toEqual([]); @@ -1259,19 +1298,26 @@ test("getOpenShorts should handle when user fully closes then re-opens a positio // in the same checkpoint, resulting in a single position with new accounting // (ie: the previous loss is not factored in). - const { contract, drift, readHyperdrive } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); + const { contract, network, readHyperdrive } = setupReadHyperdrive(); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); // pool info to get the price of shares at the time he closes the short - contract - .onRead("getPoolInfo", {}, { block: 5n }) - .resolves({ ...simplePoolInfo, vaultSharePrice: parseFixed("1.1").bigint }); + contract.stubRead({ + functionName: "getPoolInfo", + value: { ...simplePoolInfo, vaultSharePrice: parseFixed("1.1").bigint }, + options: { blockNumber: 5n }, + }); // Stub the timestamp so getOpenShorts can construct the checkpoint id - drift.onGetBlock().resolves({ - timestamp: 123456789n, - // this blockNumber is unused, but setting this to 3n, as there should be - // 3 blocks in this test flow - blockNumber: 3n, + network.stubGetBlock({ + value: { + timestamp: 123456789n, + // this blockNumber is unused, but setting this to 3n, as there should be + // 3 blocks in this test flow + blockNumber: 3n, + }, }); const events = [ @@ -1323,13 +1369,12 @@ test("getOpenShorts should handle when user fully closes then re-opens a positio }, ] as const; - contract - .onGetEvents("OpenShort", { filter: { trader: BOB } }) - .resolves([events[0], events[2]]); + contract.stubEvents("OpenShort", { filter: { trader: BOB } }, [ + events[0], + events[2], + ]); - contract - .onGetEvents("CloseShort", { filter: { trader: BOB } }) - .resolves([events[1]]); + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, [events[1]]); const value = await readHyperdrive.getOpenShorts({ account: BOB }); @@ -1349,18 +1394,32 @@ test("getOpenShorts should handle when user fully closes then re-opens a positio }); test("getShortBondsGivenDeposit & previewOpenShort should align within a given tolerance", async () => { - const { contract, drift, readHyperdrive } = setupReadHyperdrive(); - contract.onRead("getPoolConfig").resolves(simplePoolConfig30Days); - contract.onRead("getPoolInfo").resolves(simplePoolInfo); - contract.onRead("getCheckpointExposure").resolves(0n); - contract.onRead("getCheckpoint").resolves({ - vaultSharePrice: parseFixed(1.05).bigint, - weightedSpotPrice: 0n, - lastWeightedSpotPriceUpdateTime: 0n, + const { contract, network, readHyperdrive } = setupReadHyperdrive(); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig30Days, + }); + contract.stubRead({ + functionName: "getPoolInfo", + value: simplePoolInfo, }); - drift.onGetBlock().resolves({ - timestamp: 123456789n, - blockNumber: 1n, + contract.stubRead({ + functionName: "getCheckpointExposure", + value: 0n, + }); + contract.stubRead({ + functionName: "getCheckpoint", + value: { + vaultSharePrice: parseFixed(1.05).bigint, + weightedSpotPrice: 0n, + lastWeightedSpotPriceUpdateTime: 0n, + }, + }); + network.stubGetBlock({ + value: { + timestamp: 123456789n, + blockNumber: 1n, + }, }); const targetDeposit = parseFixed(1.123); @@ -1381,14 +1440,17 @@ test("getShortBondsGivenDeposit & previewOpenShort should align within a given t test("getClosedShorts should account for shorts closed to base", async () => { // Description: // Bob completely closes his position, redeeming 100 shorted bonds for 2 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); const eventData = "0x0200000000000000000000000000000000000000000000000000000065d76f800000000000000000000000000000000000000000000000056bc75e2d63100000"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onRead("getPoolConfig").resolves(simplePoolConfig7Days); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig7Days, + }); - contract.onGetEvents("CloseShort", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, [ { eventName: "CloseShort", args: { @@ -1406,7 +1468,7 @@ test("getClosedShorts should account for shorts closed to base", async () => { }, ]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getClosedShorts({ account: BOB }); @@ -1417,7 +1479,7 @@ test("getClosedShorts should account for shorts closed to base", async () => { bondAmount: parseFixed("100").bigint, checkpointTime: 123454800n, closedTimestamp: 123456789n, - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", maturity: 1708617600n, }, ]); @@ -1428,14 +1490,17 @@ test("getClosedShorts should account for shorts closed to shares", async () => { // Bob completely closes his position, redeeming 100 shorted bonds for 1.1 shares. // Shares are worth 1.1 base at the time he closes, therefore his closed position // is valued at 1.21 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); + const { contract, readHyperdrive, network } = setupReadHyperdrive(); const eventData = "0x0200000000000000000000000000000000000000000000000000000065d76f800000000000000000000000000000000000000000000000056bc75e2d63100000"; const { timestamp } = decodeAssetFromTransferSingleEventData(eventData); - contract.onRead("getPoolConfig").resolves(simplePoolConfig7Days); + contract.stubRead({ + functionName: "getPoolConfig", + value: simplePoolConfig7Days, + }); - contract.onGetEvents("CloseShort", { filter: { trader: BOB } }).resolves([ + contract.stubEvents("CloseShort", { filter: { trader: BOB } }, [ { eventName: "CloseShort", blockNumber: 5n, @@ -1454,7 +1519,7 @@ test("getClosedShorts should account for shorts closed to shares", async () => { }, ]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const value = await readHyperdrive.getClosedShorts({ account: BOB }); @@ -1465,7 +1530,7 @@ test("getClosedShorts should account for shorts closed to shares", async () => { bondAmount: parseFixed("100").bigint, checkpointTime: 123454800n, closedTimestamp: 123456789n, - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", maturity: 1708617600n, }, ]); @@ -1478,14 +1543,17 @@ test("getOpenLpPosition should return zero when a position is fully closed", asy // 1 base on this position) Bob is left with 0 LP shares and 0 base paid in his // current LP position. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); - contract.onRead("getPoolInfo").resolves(simplePoolInfo); - contract.onSimulateWrite("removeLiquidity").resolves({ + const { contract, readHyperdrive, network } = setupReadHyperdrive(); + contract.stubRead({ + functionName: "getPoolInfo", + value: simplePoolInfo, + }); + contract.stubSimulateWrite("removeLiquidity", { proceeds: parseFixed("100").bigint, withdrawalShares: 0n, }); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 175n }); - contract.onGetEvents("AddLiquidity", { filter: { provider: BOB } }).resolves([ + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 175n } }); + contract.stubEvents("AddLiquidity", { filter: { provider: BOB } }, [ { eventName: "AddLiquidity", blockNumber: 174n, @@ -1501,25 +1569,23 @@ test("getOpenLpPosition should return zero when a position is fully closed", asy }, ]); - contract - .onGetEvents("RemoveLiquidity", { filter: { provider: BOB } }) - .resolves([ - { - eventName: "RemoveLiquidity", - blockNumber: 175n, - args: { - extraData: "0x", - asBase: true, - amount: parseFixed("499").bigint, - lpAmount: parseFixed("498").bigint, - lpSharePrice: parseFixed("1.002867781011873985").bigint, - provider: "0x020a898437E9c9DCdF3c2ffdDB94E759C0DAdFB6", - vaultSharePrice: parseFixed("498.567723245858722697").bigint, - withdrawalShareAmount: 0n, - destination: BOB, - }, + contract.stubEvents("RemoveLiquidity", { filter: { provider: BOB } }, [ + { + eventName: "RemoveLiquidity", + blockNumber: 175n, + args: { + extraData: "0x", + asBase: true, + amount: parseFixed("499").bigint, + lpAmount: parseFixed("498").bigint, + lpSharePrice: parseFixed("1.002867781011873985").bigint, + provider: "0x020a898437E9c9DCdF3c2ffdDB94E759C0DAdFB6", + vaultSharePrice: parseFixed("498.567723245858722697").bigint, + withdrawalShareAmount: 0n, + destination: BOB, }, - ]); + }, + ]); const value = await readHyperdrive.getOpenLpPosition({ account: BOB, @@ -1541,14 +1607,17 @@ test("getOpenLpPosition should return the current lpShareBalance and baseAmountP // receiving 99 LP shares, depositing 100 base. Bob now has with 99 LP // shares and 100 base paid in his current LP position. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 175n }); - contract.onSimulateWrite("removeLiquidity").resolves({ + const { contract, readHyperdrive, network } = setupReadHyperdrive(); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 175n } }); + contract.stubSimulateWrite("removeLiquidity", { proceeds: parseFixed("100").bigint, withdrawalShares: 0n, }); - contract.onRead("getPoolInfo").resolves(simplePoolInfo); - contract.onGetEvents("AddLiquidity", { filter: { provider: BOB } }).resolves([ + contract.stubRead({ + functionName: "getPoolInfo", + value: simplePoolInfo, + }); + contract.stubEvents("AddLiquidity", { filter: { provider: BOB } }, [ { eventName: "AddLiquidity", blockNumber: 174n, @@ -1577,25 +1646,23 @@ test("getOpenLpPosition should return the current lpShareBalance and baseAmountP }, ]); - contract - .onGetEvents("RemoveLiquidity", { filter: { provider: BOB } }) - .resolves([ - { - eventName: "RemoveLiquidity", - blockNumber: 175n, - args: { - extraData: "0x", - asBase: true, - amount: parseFixed("499").bigint, - lpAmount: parseFixed("498").bigint, - lpSharePrice: parseFixed("1.002867781011873985").bigint, - provider: "0x020a898437E9c9DCdF3c2ffdDB94E759C0DAdFB6", - vaultSharePrice: parseFixed("1.0008670371827").bigint, - withdrawalShareAmount: 0n, - destination: BOB, - }, + contract.stubEvents("RemoveLiquidity", { filter: { provider: BOB } }, [ + { + eventName: "RemoveLiquidity", + blockNumber: 175n, + args: { + extraData: "0x", + asBase: true, + amount: parseFixed("499").bigint, + lpAmount: parseFixed("498").bigint, + lpSharePrice: parseFixed("1.002867781011873985").bigint, + provider: "0x020a898437E9c9DCdF3c2ffdDB94E759C0DAdFB6", + vaultSharePrice: parseFixed("1.0008670371827").bigint, + withdrawalShareAmount: 0n, + destination: BOB, }, - ]); + }, + ]); const value = await readHyperdrive.getOpenLpPosition({ account: BOB, @@ -1613,29 +1680,27 @@ test("getClosedLpShares should account for LP shares closed to base", async () = // Description: // Bob completely closes his LP position of 5 LP shares and receives back // base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); - - contract - .onGetEvents("RemoveLiquidity", { filter: { provider: BOB } }) - .resolves([ - { - eventName: "RemoveLiquidity", - blockNumber: 5n, - args: { - extraData: "0x", - asBase: true, - amount: parseFixed("10").bigint, - vaultSharePrice: parseFixed("9").bigint, - provider: BOB, - withdrawalShareAmount: 0n, - lpAmount: parseFixed("5").bigint, - lpSharePrice: parseFixed("2").bigint, - destination: BOB, - }, + const { contract, readHyperdrive, network } = setupReadHyperdrive(); + + contract.stubEvents("RemoveLiquidity", { filter: { provider: BOB } }, [ + { + eventName: "RemoveLiquidity", + blockNumber: 5n, + args: { + extraData: "0x", + asBase: true, + amount: parseFixed("10").bigint, + vaultSharePrice: parseFixed("9").bigint, + provider: BOB, + withdrawalShareAmount: 0n, + lpAmount: parseFixed("5").bigint, + lpSharePrice: parseFixed("2").bigint, + destination: BOB, }, - ]); + }, + ]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const closedLpShares = await readHyperdrive.getClosedLpShares({ account: BOB, @@ -1655,29 +1720,27 @@ test("getClosedLpShares should account for LP shares closed to vault shares", as // Description: // Bob completely closes his LP position of 5 LP shares and receives back // shares. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); - - contract - .onGetEvents("RemoveLiquidity", { filter: { provider: BOB } }) - .resolves([ - { - eventName: "RemoveLiquidity", - blockNumber: 5n, - args: { - extraData: "0x", - asBase: false, - amount: parseFixed("9").bigint, - vaultSharePrice: parseFixed("1.1").bigint, - provider: BOB, - withdrawalShareAmount: 0n, - lpAmount: parseFixed("5").bigint, - lpSharePrice: parseFixed("2").bigint, - destination: BOB, - }, + const { contract, readHyperdrive, network } = setupReadHyperdrive(); + + contract.stubEvents("RemoveLiquidity", { filter: { provider: BOB } }, [ + { + eventName: "RemoveLiquidity", + blockNumber: 5n, + args: { + extraData: "0x", + asBase: false, + amount: parseFixed("9").bigint, + vaultSharePrice: parseFixed("1.1").bigint, + provider: BOB, + withdrawalShareAmount: 0n, + lpAmount: parseFixed("5").bigint, + lpSharePrice: parseFixed("2").bigint, + destination: BOB, }, - ]); + }, + ]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const closedLpShares = await readHyperdrive.getClosedLpShares({ account: BOB, @@ -1696,27 +1759,25 @@ test("getClosedLpShares should account for LP shares closed to vault shares", as test("getRedeemedWithdrawalShares should account for withdrawal shares closed to base", async () => { // Description: // Bob completely redeems 5 withdrawal shares and receives 10 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); - - contract - .onGetEvents("RedeemWithdrawalShares", { filter: { provider: BOB } }) - .resolves([ - { - eventName: "RedeemWithdrawalShares", - blockNumber: 5n, - args: { - extraData: "0x", - asBase: true, - amount: parseFixed("10").bigint, - vaultSharePrice: parseFixed("9.8").bigint, - provider: BOB, - withdrawalShareAmount: parseFixed("5").bigint, - destination: BOB, - }, + const { contract, readHyperdrive, network } = setupReadHyperdrive(); + + contract.stubEvents("RedeemWithdrawalShares", { filter: { provider: BOB } }, [ + { + eventName: "RedeemWithdrawalShares", + blockNumber: 5n, + args: { + extraData: "0x", + asBase: true, + amount: parseFixed("10").bigint, + vaultSharePrice: parseFixed("9.8").bigint, + provider: BOB, + withdrawalShareAmount: parseFixed("5").bigint, + destination: BOB, }, - ]); + }, + ]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const redeemedWithdrawalShares = await readHyperdrive.getRedeemedWithdrawalShares({ @@ -1724,7 +1785,7 @@ test("getRedeemedWithdrawalShares should account for withdrawal shares closed to }); expect(redeemedWithdrawalShares).toEqual([ { - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", baseAmount: parseFixed("10").bigint, withdrawalShareAmount: parseFixed("5").bigint, redeemedTimestamp: 123456789n, @@ -1734,27 +1795,25 @@ test("getRedeemedWithdrawalShares should account for withdrawal shares closed to test("getRedeemedWithdrawalShares should account for withdrawal shares closed to vault shares", async () => { // Description: // Bob completely redeems 5 withdrawal shares and receives 8 shares that are worth 10 base. - const { contract, readHyperdrive, drift } = setupReadHyperdrive(); - - contract - .onGetEvents("RedeemWithdrawalShares", { filter: { provider: BOB } }) - .resolves([ - { - eventName: "RedeemWithdrawalShares", - blockNumber: 5n, - args: { - extraData: "0x", - asBase: false, - vaultSharePrice: parseFixed("1.25").bigint, - amount: parseFixed("8").bigint, - provider: BOB, - withdrawalShareAmount: parseFixed("5").bigint, - destination: BOB, - }, + const { contract, readHyperdrive, network } = setupReadHyperdrive(); + + contract.stubEvents("RedeemWithdrawalShares", { filter: { provider: BOB } }, [ + { + eventName: "RedeemWithdrawalShares", + blockNumber: 5n, + args: { + extraData: "0x", + asBase: false, + vaultSharePrice: parseFixed("1.25").bigint, + amount: parseFixed("8").bigint, + provider: BOB, + withdrawalShareAmount: parseFixed("5").bigint, + destination: BOB, }, - ]); + }, + ]); - drift.onGetBlock().resolves({ timestamp: 123456789n, blockNumber: 5n }); + network.stubGetBlock({ value: { timestamp: 123456789n, blockNumber: 5n } }); const redeemedWithdrawalShares = await readHyperdrive.getRedeemedWithdrawalShares({ @@ -1762,7 +1821,7 @@ test("getRedeemedWithdrawalShares should account for withdrawal shares closed to }); expect(redeemedWithdrawalShares).toEqual([ { - hyperdriveAddress: ZERO_ADDRESS, + hyperdriveAddress: "0x0000000000000000000000000000000000000000", baseAmount: parseFixed("10").bigint, withdrawalShareAmount: parseFixed("5").bigint, redeemedTimestamp: 123456789n, diff --git a/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.ts index 039ce7b8f..4c8b824c1 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/base/ReadHyperdrive.ts @@ -1,16 +1,16 @@ import { - Address, Block, BlockTag, - ContractEvent, + CachedReadContract, ContractGetEventsOptions, ContractReadOptions, ContractWriteOptions, - MergeKeys, - ReadContract, -} from "@delvtech/drift"; + Event, +} from "@delvtech/evm-client"; +import { Address } from "abitype"; import { assertNever } from "src/base/assertNever"; import { MAX_UINT256, SECONDS_PER_YEAR } from "src/base/constants"; +import { MergeKeys } from "src/base/types"; import { getCheckpointTime } from "src/checkpoint/getCheckpointTime"; import { Checkpoint, @@ -18,10 +18,9 @@ import { GetCheckpointParams, GetCheckpointTimeParams, } from "src/checkpoint/types"; -import { ReadContractClientOptions } from "src/drift/ContractClient"; -import { ReadClient } from "src/drift/ReadClient"; -import { getBlockOrThrow } from "src/drift/getBlockOrThrow"; import { HyperdriveSdkError } from "src/errors/HyperdriveSdkError"; +import { getBlockFromReadOptions } from "src/evm-client/utils/getBlockFromReadOptions"; +import { getBlockOrThrow } from "src/evm-client/utils/getBlockOrThrow"; import { fixed } from "src/fixed-point"; import { HyperdriveAbi, hyperdriveAbi } from "src/hyperdrive/base/abi"; import { MAX_ITERATIONS, NULL_BYTES } from "src/hyperdrive/constants"; @@ -34,6 +33,7 @@ import { } from "src/longs/types"; import { ClosedLpShares } from "src/lp/ClosedLpShares"; import { LP_ASSET_ID } from "src/lp/assetId"; +import { ReadContractModelOptions, ReadModel } from "src/model/ReadModel"; import { decodeAssetFromTransferSingleEventData } from "src/pool/decodeAssetFromTransferSingleEventData"; import { MarketState, PoolConfig, PoolInfo } from "src/pool/types"; import { calculateShortAccruedYield } from "src/shorts/calculateShortAccruedYield"; @@ -43,11 +43,11 @@ import { ReadEth } from "src/token/eth/ReadEth"; import { RedeemedWithdrawalShares } from "src/withdrawalShares/RedeemedWithdrawalShares"; import { WITHDRAW_SHARES_ASSET_ID } from "src/withdrawalShares/assetId"; -export interface ReadHyperdriveOptions extends ReadContractClientOptions {} +export interface ReadHyperdriveOptions extends ReadContractModelOptions {} -export class ReadHyperdrive extends ReadClient { +export class ReadHyperdrive extends ReadModel { readonly address: Address; - readonly contract: ReadContract; + readonly contract: CachedReadContract; /** * @hidden @@ -56,17 +56,16 @@ export class ReadHyperdrive extends ReadClient { debugName = "Hyperdrive", address, cache, - cacheNamespace, - drift, - ...rest + namespace, + ...modelOptions }: ReadHyperdriveOptions) { - super({ debugName, drift, ...rest }); + super({ debugName, ...modelOptions }); this.address = address; - this.contract = this.drift.contract({ + this.contract = this.contractFactory({ abi: hyperdriveAbi, address, cache, - cacheNamespace, + namespace, }); } @@ -106,13 +105,14 @@ export class ReadHyperdrive extends ReadClient { const address = await this.contract.read("baseToken"); return address === ReadEth.address ? new ReadEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }) : new ReadErc20({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } @@ -127,9 +127,9 @@ export class ReadHyperdrive extends ReadClient { const address = await this.contract.read("vaultSharesToken"); return new ReadErc20({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } @@ -188,7 +188,7 @@ export class ReadHyperdrive extends ReadClient { } const blockNumber = events[0].blockNumber; - return getBlockOrThrow(this.drift, { blockNumber }); + return getBlockOrThrow(this.network, { blockNumber }); } /** @@ -210,7 +210,7 @@ export class ReadHyperdrive extends ReadClient { blockRange: bigint; options?: ContractReadOptions; }): Promise { - const currentBlock = await getBlockOrThrow(this.drift, options); + const currentBlock = await getBlockOrThrow(this.network, options); // Clamp the start block to the pool's initialization block if the // blockRange is too big. let startBlockNumber = currentBlock.blockNumber! - blockRange; @@ -222,13 +222,13 @@ export class ReadHyperdrive extends ReadClient { // NOTE: Cloudchain will throw an error if the block number is too far back // in history. - const startBlock = await getBlockOrThrow(this.drift, { + const startBlock = await getBlockOrThrow(this.network, { blockNumber: startBlockNumber, }); // Get the info from fromBlock to get the starting vault share price const { vaultSharePrice: startVaultSharePrice } = await this.getPoolInfo({ - block: startBlockNumber, + blockNumber: startBlockNumber, }); // Get the current vaultSharePrice from the latest pool info @@ -273,7 +273,7 @@ export class ReadHyperdrive extends ReadClient { if (timestamp === undefined) { // Default to the block from read options const getBlockOptions = blockNumber ? { blockNumber } : options; - const block = await getBlockOrThrow(this.drift, getBlockOptions); + const block = await getBlockOrThrow(this.network, getBlockOptions); timestamp = block.timestamp; } @@ -625,12 +625,9 @@ export class ReadHyperdrive extends ReadClient { ContractGetEventsOptions & ContractGetEventsOptions, ): Promise<{ - addLiquidity: ContractEvent[]; - removeLiquidity: ContractEvent[]; - redeemWithdrawalShares: ContractEvent< - HyperdriveAbi, - "RedeemWithdrawalShares" - >[]; + addLiquidity: Event[]; + removeLiquidity: Event[]; + redeemWithdrawalShares: Event[]; }> { const addLiquidityEvents = await this.contract.getEvents( "AddLiquidity", @@ -677,14 +674,14 @@ export class ReadHyperdrive extends ReadClient { } // Attempt to fetch the blocks first to fail early if the block is not found - const currentBlock = await getBlockOrThrow(this.drift, options); - const startBlock = await getBlockOrThrow(this.drift, { + const currentBlock = await getBlockOrThrow(this.network, options); + const startBlock = await getBlockOrThrow(this.network, { blockNumber: fromBlock, }); // Get the info from fromBlock to get the starting lp share price const { lpSharePrice: startLpSharePrice } = await this.getPoolInfo({ - block: fromBlock, + blockNumber: fromBlock, }); // Get the current lpSharePrice from the latest pool info @@ -715,8 +712,8 @@ export class ReadHyperdrive extends ReadClient { openLongEvents, closeLongEvents, }: { - openLongEvents: ContractEvent[]; - closeLongEvents: ContractEvent[]; + openLongEvents: Event[]; + closeLongEvents: Event[]; }): Long[] { // Put open and long events in block order. We spread openLongEvents first // since you have to open a long before you can close one. @@ -781,13 +778,15 @@ export class ReadHyperdrive extends ReadClient { account: `0x${string}`; options?: ContractReadOptions; }): Promise { + const toBlock = getBlockFromReadOptions(options); + const transfersReceived = await this.contract.getEvents("TransferSingle", { filter: { to: account }, - toBlock: options?.block, + toBlock, }); const transfersSent = await this.contract.getEvents("TransferSingle", { filter: { from: account }, - toBlock: options?.block, + toBlock, }); const longsReceived = transfersReceived.filter((event) => { @@ -920,13 +919,15 @@ export class ReadHyperdrive extends ReadClient { account: `0x${string}`; options?: ContractReadOptions; }): Promise { + const toBlock = getBlockFromReadOptions(options); + const openLongEvents = await this.contract.getEvents("OpenLong", { filter: { trader: account }, - toBlock: options?.block, + toBlock, }); const closeLongEvents = await this.contract.getEvents("CloseLong", { filter: { trader: account }, - toBlock: options?.block, + toBlock, }); return this._calcOpenLongs({ @@ -948,20 +949,22 @@ export class ReadHyperdrive extends ReadClient { account: `0x${string}`; options?: ContractReadOptions; }): Promise { + const toBlock = getBlockFromReadOptions(options); + const { checkpointDuration, positionDuration } = await this.getPoolConfig(options); const openShortEvents = await this.contract.getEvents("OpenShort", { filter: { trader: account }, - toBlock: options?.block, + toBlock, }); const closeShortEvents = await this.contract.getEvents("CloseShort", { filter: { trader: account }, - toBlock: options?.block, + toBlock, }); return this._calcOpenShorts({ - hyperdriveAddress: this.address, + hyperdriveAddress: this.contract.address, checkpointDuration, positionDuration, openShortEvents, @@ -979,8 +982,8 @@ export class ReadHyperdrive extends ReadClient { hyperdriveAddress: Address; checkpointDuration: bigint; positionDuration: bigint; - openShortEvents: ContractEvent[]; - closeShortEvents: ContractEvent[]; + openShortEvents: Event[]; + closeShortEvents: Event[]; }): Promise { // Put open and short events in block order. We spread openShortEvents first // since you have to open a short before you can close one. @@ -992,7 +995,7 @@ export class ReadHyperdrive extends ReadClient { for (const event of orderedShortEvents) { const assetId = event.args.assetId.toString(); - const { timestamp } = await getBlockOrThrow(this.drift, { + const { timestamp } = await getBlockOrThrow(this.network, { blockNumber: event.blockNumber, }); @@ -1070,9 +1073,11 @@ export class ReadHyperdrive extends ReadClient { account: `0x${string}`; options?: ContractReadOptions; }): Promise { + const toBlock = getBlockFromReadOptions(options); + const closedLongs = await this.contract.getEvents("CloseLong", { filter: { trader: account }, - toBlock: options?.block, + toBlock, }); const closedLongsList: ClosedLong[] = await Promise.all( @@ -1090,7 +1095,7 @@ export class ReadHyperdrive extends ReadClient { baseAmountPaid: 0n, // TODO: Remove this field, this is copy/paste from @hyperdrive/queries maturity: event.args.maturityTime, closedTimestamp: ( - await getBlockOrThrow(this.drift, { + await getBlockOrThrow(this.network, { blockNumber: event.blockNumber, }) ).timestamp, @@ -1110,16 +1115,17 @@ export class ReadHyperdrive extends ReadClient { account: `0x${string}`; options?: ContractReadOptions; }): Promise { + const toBlock = getBlockFromReadOptions(options); const closedShorts = await this.contract.getEvents("CloseShort", { filter: { trader: account }, - toBlock: options?.block, + toBlock, }); const { checkpointDuration } = await this.getPoolConfig(options); const closedShortsList: ClosedShort[] = await Promise.all( closedShorts.map(async (event) => { const { assetId, maturityTime } = event.args; - const { timestamp } = await getBlockOrThrow(this.drift, { + const { timestamp } = await getBlockOrThrow(this.network, { blockNumber: event.blockNumber, }); @@ -1128,7 +1134,7 @@ export class ReadHyperdrive extends ReadClient { : fixed(event.args.amount).mul(event.args.vaultSharePrice).bigint; return { - hyperdriveAddress: this.address, + hyperdriveAddress: this.contract.address, assetId, bondAmount: event.args.bondAmount, baseAmountReceived: baseAmount, @@ -1271,15 +1277,16 @@ export class ReadHyperdrive extends ReadClient { baseValue: bigint; sharesValue: bigint; }> { + const toBlock = getBlockFromReadOptions(options); const addLiquidityEvents = await this.contract.getEvents("AddLiquidity", { filter: { provider: account }, - toBlock: options?.block, + toBlock, }); const removeLiquidityEvents = await this.contract.getEvents( "RemoveLiquidity", { filter: { provider: account }, - toBlock: options?.block, + toBlock, }, ); @@ -1345,11 +1352,8 @@ export class ReadHyperdrive extends ReadClient { addLiquidityEvents, removeLiquidityEvents, }: { - addLiquidityEvents: ContractEvent[]; - removeLiquidityEvents: ContractEvent< - typeof hyperdriveAbi, - "RemoveLiquidity" - >[]; + addLiquidityEvents: Event[]; + removeLiquidityEvents: Event[]; }) { const combinedEventsInOrder = [ ...addLiquidityEvents, @@ -1410,7 +1414,7 @@ export class ReadHyperdrive extends ReadClient { "RemoveLiquidity", { filter: { provider: account }, - toBlock: options?.block, + toBlock: getBlockFromReadOptions(options), }, ); return Promise.all( @@ -1433,7 +1437,7 @@ export class ReadHyperdrive extends ReadClient { withdrawalShareAmount, lpSharePrice, closedTimestamp: ( - await getBlockOrThrow(this.drift, { + await getBlockOrThrow(this.network, { blockNumber, }) ).timestamp, @@ -1473,7 +1477,7 @@ export class ReadHyperdrive extends ReadClient { "RedeemWithdrawalShares", { filter: { provider: account }, - toBlock: options?.block, + toBlock: getBlockFromReadOptions(options), }, ); @@ -1485,11 +1489,11 @@ export class ReadHyperdrive extends ReadClient { : fixed(amount).mul(vaultSharePrice).bigint; return { - hyperdriveAddress: this.address, + hyperdriveAddress: this.contract.address, withdrawalShareAmount, baseAmount, redeemedTimestamp: ( - await getBlockOrThrow(this.drift, { blockNumber }) + await getBlockOrThrow(this.network, { blockNumber }) ).timestamp, }; }), diff --git a/packages/hyperdrive-js-core/src/hyperdrive/base/ReadWriteHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/base/ReadWriteHyperdrive.ts index e9b3f7c34..33c8a9c50 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/base/ReadWriteHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/base/ReadWriteHyperdrive.ts @@ -1,28 +1,29 @@ import { + CachedReadWriteContract, ContractReadOptions, ContractWriteOptions, - Drift, - ReadWriteAdapter, - ReadWriteContract, -} from "@delvtech/drift"; -import { ReadWriteContractClientOptions } from "src/drift/ContractClient"; +} from "@delvtech/evm-client"; +import { ReadWriteContractFactory } from "src/evm-client/contractFactory"; +import { syncCacheWithTransaction } from "src/evm-client/syncCacheWithTransaction"; import { HyperdriveAbi } from "src/hyperdrive/base/abi"; import { ReadHyperdrive } from "src/hyperdrive/base/ReadHyperdrive"; import { NULL_BYTES } from "src/hyperdrive/constants"; +import { ReadWriteContractModelOptions } from "src/model/ReadWriteModel"; import { ReadWriteErc20 } from "src/token/erc20/ReadWriteErc20"; import { ReadWriteEth } from "src/token/eth/ReadWriteEth"; type ReadWriteParams = { args: Args; options?: ContractWriteOptions; + onTransactionCompleted?: (hash: `0x${string}`) => void; }; export interface ReadWriteHyperdriveOptions - extends ReadWriteContractClientOptions {} + extends ReadWriteContractModelOptions {} export class ReadWriteHyperdrive extends ReadHyperdrive { - declare drift: Drift; - declare contract: ReadWriteContract; + declare contract: CachedReadWriteContract; + declare contractFactory: ReadWriteContractFactory; constructor(options: ReadWriteHyperdriveOptions) { super(options); @@ -34,13 +35,14 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { const address = await this.contract.read("baseToken", {}, options); return address === ReadWriteEth.address ? new ReadWriteEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }) : new ReadWriteErc20({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } @@ -48,8 +50,9 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { const address = await this.contract.read("vaultSharesToken"); return new ReadWriteErc20({ address, - drift: this.drift, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } @@ -57,44 +60,38 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * Allows anyone to mint a new checkpoint. * @param time - The time (in seconds) of the checkpoint to create. */ + @syncCacheWithTransaction() async checkpoint({ args: { time }, options, }: ReadWriteParams<{ time: number }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "checkpoint", { _checkpointTime: BigInt(time), _maxIterations: 4n }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** * Allows an authorized address to pause this contract * @param paused - True to pause all deposits and false to unpause them */ + @syncCacheWithTransaction({ + cacheEntries: [{ functionName: "getMarketState" }], + }) async pause({ args: { paused }, options, }: ReadWriteParams<{ paused: boolean; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "pause", { _status: paused }, - { - ...options, - onMined: (receipt) => { - this.contract.invalidateReadsMatching("getMarketState"); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** @@ -108,6 +105,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * blocked. * @returns The initial number of LP shares created. */ + @syncCacheWithTransaction() async initialize({ args: { contribution, @@ -124,7 +122,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "initialize", { _apr: apr, @@ -135,14 +133,9 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { extraData: extraData, }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** @@ -155,6 +148,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * @return bondProceeds - The amount of bonds the user received * */ + @syncCacheWithTransaction() async openLong({ args: { destination, @@ -173,7 +167,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "openLong", { _amount: amount, @@ -181,14 +175,9 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { _minVaultSharePrice: minVaultSharePrice, _options: { destination, asBase, extraData }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** @@ -201,6 +190,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * @return maturityTime - The maturity time of the short. * @return traderDeposit - The amount the user deposited for this trade. */ + @syncCacheWithTransaction() async openShort({ args: { destination, @@ -219,7 +209,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "openShort", { _bondAmount: bondAmount, @@ -227,14 +217,9 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { _minVaultSharePrice: minVaultSharePrice, _options: { destination, asBase, extraData }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** @@ -247,6 +232,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * @param options - Contract Write Options * @return The amount of underlying asset the user receives. */ + @syncCacheWithTransaction() async closeLong({ args: { maturityTime, @@ -265,7 +251,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "closeLong", { _maturityTime: maturityTime, @@ -273,14 +259,9 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { _minOutput: minAmountOut, _options: { destination, asBase, extraData }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** @@ -293,6 +274,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * @param options - Contract Write Options * @return The amount of base tokens produced by closing this short */ + @syncCacheWithTransaction() async closeShort({ args: { maturityTime, @@ -311,7 +293,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "closeShort", { _maturityTime: maturityTime, @@ -319,14 +301,9 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { _minOutput: minAmountOut, _options: { destination, asBase, extraData }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** @@ -340,6 +317,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * @param options - Contract Write Options * @return lpShares The number of LP tokens created */ + @syncCacheWithTransaction() async addLiquidity({ args: { destination, @@ -360,7 +338,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "addLiquidity", { _contribution: contribution, @@ -369,14 +347,9 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { _maxApr: maxApr, _options: { destination, asBase, extraData }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } /** @@ -390,6 +363,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { receives a proportional amount of the pool's idle capital * @returns withdrawShares - The base that the LP receives buys out some of their LP shares, but it may not be sufficient to fully buy the LP out. In this case, the LP receives withdrawal shares equal in value to the present value they are owed. As idle capital becomes available, the pool will buy back these shares. */ + @syncCacheWithTransaction() async removeLiquidity({ args: { destination, @@ -406,21 +380,17 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "removeLiquidity", { _lpShares: lpSharesIn, _minOutputPerShare: minOutputPerShare, _options: { destination, asBase, extraData }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + + return hash; } /** @@ -433,6 +403,7 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { * @return baseProceeds The amount of base the LP received. * @return sharesRedeemed The amount of withdrawal shares that were redeemed. */ + @syncCacheWithTransaction() async redeemWithdrawalShares({ args: { withdrawalSharesIn, @@ -449,20 +420,15 @@ export class ReadWriteHyperdrive extends ReadHyperdrive { asBase?: boolean; extraData?: `0x${string}`; }>): Promise<`0x${string}`> { - return this.contract.write( + const hash = await this.contract.write( "redeemWithdrawalShares", { _withdrawalShares: withdrawalSharesIn, _minOutputPerShare: minOutputPerShare, _options: { destination, asBase, extraData }, }, - { - ...options, - onMined: (receipt) => { - this.contract.cache.clear(); - options?.onMined?.(receipt); - }, - }, + options, ); + return hash; } } diff --git a/packages/hyperdrive-js-core/src/hyperdrive/base/testing/setupReadHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/base/testing/setupReadHyperdrive.ts index 8b438f490..951c875c3 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/base/testing/setupReadHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/base/testing/setupReadHyperdrive.ts @@ -1,32 +1,41 @@ -import { ZERO_ADDRESS } from "@delvtech/drift"; -import { MockDrift } from "@delvtech/drift/testing"; -import { ReadHyperdrive_v1_0_14 } from "src/hyperdrive/base/v1.0.14/ReadHyperdrive_v1_0_14"; +import { + CachedReadContract, + createCachedReadContract, +} from "@delvtech/evm-client"; +import { NetworkStub, ReadContractStub } from "@delvtech/evm-client/stubs"; +import { Abi } from "abitype"; +import { ReadHyperdrive_v1_0_14 } from "src/exports/v1.0.14"; +import { HyperdriveAbi } from "src/hyperdrive/base/abi"; // No need to explicitly set return types as they are already set in the Stubs // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function setupReadHyperdrive() { - const drift = new MockDrift(); + const network = new NetworkStub(); + // TODO: We use the v1.0.14 version of ReadHyperdrive to avoid the need to - // stub every `convertToShares` and `convertToBase` call since drift only + // stub every `convertToShares` and `convertToBase` call since evm-client only // supports stubbing calls with static values. It should be refactored to // support stubbing a call with a function to dynamically calculate the return // value based on arguments and options. const readHyperdrive = new ReadHyperdrive_v1_0_14({ - address: ZERO_ADDRESS, - drift, + address: "0x123", + contractFactory: ({ abi }: { abi: TAbi }) => { + const contract = new ReadContractStub(abi); + return createCachedReadContract({ contract }); + }, + network: network, }); - // The ReadHyperdrive class doesn't infer that the contract is a MockContract, + // The ReadHyperdrive class doesn't infer that the contract is a Stub // so we need to cast it to the correct type. - const contract = drift.contract({ - abi: readHyperdrive.contract.abi, - address: readHyperdrive.contract.address, - }); + const contract = + readHyperdrive.contract as unknown as CachedReadContract & + ReadContractStub; - contract.onRead("decimals").resolves(18); + contract.stubRead({ functionName: "decimals", value: 18 }); return { - drift, contract, + network, readHyperdrive, }; } diff --git a/packages/hyperdrive-js-core/src/hyperdrive/base/v1.0.14/ReadHyperdrive_v1_0_14.ts b/packages/hyperdrive-js-core/src/hyperdrive/base/v1.0.14/ReadHyperdrive_v1_0_14.ts index 4c03e7e9c..2444d3681 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/base/v1.0.14/ReadHyperdrive_v1_0_14.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/base/v1.0.14/ReadHyperdrive_v1_0_14.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { fixed } from "src/fixed-point"; import { diff --git a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadErc4626Hyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadErc4626Hyperdrive.ts index 70d851039..379eaea11 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadErc4626Hyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadErc4626Hyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadHyperdrive, @@ -15,7 +15,7 @@ export class ReadErc4626Hyperdrive extends readErc4626HyperdriveMixin( */ export interface ReadErc4626HyperdriveMixin { /** - * Get a client for the tokenized vault for this Hyperdrive instance. + * Get a model of the tokenized vault for this Hyperdrive instance. */ getSharesToken(options?: ContractReadOptions): Promise; } @@ -38,9 +38,9 @@ export function readErc4626HyperdriveMixin< return new ReadErc4626({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadMockErc4626Hyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadMockErc4626Hyperdrive.ts index ba9c38c47..bc06ca533 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadMockErc4626Hyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadMockErc4626Hyperdrive.ts @@ -1,11 +1,11 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; -import { ReadHyperdriveOptions } from "src/hyperdrive/base/ReadHyperdrive"; +import { ReadHyperdriveOptions } from "src/exports"; import { ReadErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadErc4626Hyperdrive"; import { ReadMockErc4626 } from "src/token/erc4626/ReadMockErc4626"; export class ReadMockErc4626Hyperdrive extends readMockErc4626HyperdriveMixin( - ReadErc4626Hyperdrive, + ReadErc4626Hyperdrive ) {} /** @@ -19,7 +19,7 @@ export interface ReadMockErc4626HyperdriveMixin { * @internal */ export function readMockErc4626HyperdriveMixin< - T extends Constructor, + T extends Constructor >(Base: T): Constructor & T { return class extends Base { constructor(...[options]: any[]) { @@ -28,15 +28,15 @@ export function readMockErc4626HyperdriveMixin< } async getSharesToken( - options?: ContractReadOptions, + options?: ContractReadOptions ): Promise { const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadMockErc4626({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteErc4626Hyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteErc4626Hyperdrive.ts index 0db4b1511..4370a7180 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteErc4626Hyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteErc4626Hyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadWriteHyperdrive } from "src/hyperdrive/base/ReadWriteHyperdrive"; import { @@ -8,7 +8,7 @@ import { import { ReadWriteErc4626 } from "src/token/erc4626/ReadWriteErc4626"; export class ReadWriteErc4626Hyperdrive extends readWriteErc4626HyperdriveMixin( - ReadWriteHyperdrive, + ReadWriteHyperdrive ) {} export interface ReadWriteErc4626HyperdriveMixin @@ -20,19 +20,19 @@ export interface ReadWriteErc4626HyperdriveMixin * @internal */ export function readWriteErc4626HyperdriveMixin< - T extends Constructor, + T extends Constructor >(Base: T): Constructor & T { return class extends readErc4626HyperdriveMixin(Base) { async getSharesToken( - options?: ContractReadOptions, + options?: ContractReadOptions ): Promise { const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadWriteErc4626({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteMockErc4626Hyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteMockErc4626Hyperdrive.ts index 1bbd691d3..9c497d0bf 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteMockErc4626Hyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/erc4626/ReadWriteMockErc4626Hyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadWriteErc4626Hyperdrive } from "src/hyperdrive/erc4626/ReadWriteErc4626Hyperdrive"; import { ReadWriteMockErc4626 } from "src/token/erc4626/ReadWriteMockErc4626"; @@ -8,7 +8,7 @@ import { } from "./ReadMockErc4626Hyperdrive"; export class ReadWriteMockErc4626Hyperdrive extends readWriteMockErc4626HyperdriveMixin( - ReadWriteErc4626Hyperdrive, + ReadWriteErc4626Hyperdrive ) {} export interface ReadWriteMockErc4626HyperdriveMixin @@ -20,20 +20,20 @@ export interface ReadWriteMockErc4626HyperdriveMixin * @internal */ export function readWriteMockErc4626HyperdriveMixin< - T extends Constructor, + T extends Constructor >(Base: T): Constructor & T { // return class extends readErc4626HyperdriveMixin(Base) { return class extends readMockErc4626HyperdriveMixin(Base) { async getSharesToken( - options?: ContractReadOptions, + options?: ContractReadOptions ): Promise { const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadWriteMockErc4626({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadEzEthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadEzEthHyperdrive.ts index 05c7e2ec4..f279c55a6 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadEzEthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadEzEthHyperdrive.ts @@ -1,4 +1,4 @@ -import { Contract, ContractReadOptions, ReadContract } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadHyperdrive } from "src/hyperdrive/base/ReadHyperdrive"; import { @@ -16,15 +16,15 @@ export class ReadEzEthHyperdrive extends readEzEthHyperdriveMixin( * @internal */ export interface ReadEzEthHyperdriveMixin { - ezEthHyperdriveContract: Contract; + ezEthHyperdriveContract: CachedReadContract; /** - * Get a client for ETH, the base token for this Hyperdrive instance. + * Get a model of ETH, the base token for this Hyperdrive instance. */ getBaseToken(options?: ContractReadOptions): Promise; /** - * Get a client for the EzETH token for this Hyperdrive instance. + * Get a model of the EzETH token for this Hyperdrive instance. */ getSharesToken(options?: ContractReadOptions): Promise; } @@ -36,28 +36,29 @@ export function readEzEthHyperdriveMixin>( Base: T, ): Constructor & T { return class extends Base { - ezEthHyperdriveContract: ReadContract; + ezEthHyperdriveContract: CachedReadContract; constructor(...[options]: any[]) { const { debugName = "EzETH Hyperdrive", address, cache, - cacheNamespace, - ...rest + namespace, + ...modelOptions } = options as ConstructorParameters[0]; - super({ debugName, address, cache, cacheNamespace, ...rest }); - this.ezEthHyperdriveContract = this.drift.contract({ + super({ debugName, address, cache, namespace, ...modelOptions }); + this.ezEthHyperdriveContract = this.contractFactory({ abi: ezEthHyperdriveAbi, address, cache, - cacheNamespace, + namespace, }); } async getBaseToken(): Promise { return new ReadEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } @@ -65,9 +66,9 @@ export function readEzEthHyperdriveMixin>( const { vaultSharesToken } = await this.getPoolConfig(); return new ReadErc20({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadWriteEzEthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadWriteEzEthHyperdrive.ts index 9db9b52dc..556ce4d7b 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadWriteEzEthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/ezeth/ReadWriteEzEthHyperdrive.ts @@ -1,4 +1,7 @@ -import { ContractReadOptions, ReadWriteContract } from "@delvtech/drift"; +import { + CachedReadWriteContract, + ContractReadOptions, +} from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadWriteHyperdrive } from "src/hyperdrive/base/ReadWriteHyperdrive"; import { @@ -10,12 +13,12 @@ import { ReadWriteErc20 } from "src/token/erc20/ReadWriteErc20"; import { ReadWriteEth } from "src/token/eth/ReadWriteEth"; export class ReadWriteEzEthHyperdrive extends readWriteEzEthHyperdriveMixin( - ReadWriteHyperdrive, + ReadWriteHyperdrive ) {} export interface ReadWriteEzEthHyperdriveMixin extends ReadEzEthHyperdriveMixin { - ezEthHyperdriveContract: ReadWriteContract; + ezEthHyperdriveContract: CachedReadWriteContract; getBaseToken(options?: ContractReadOptions): Promise; getSharesToken(options?: ContractReadOptions): Promise; } @@ -24,26 +27,27 @@ export interface ReadWriteEzEthHyperdriveMixin * @internal */ export function readWriteEzEthHyperdriveMixin< - T extends Constructor, + T extends Constructor >(Base: T): Constructor & T { return class extends readEzEthHyperdriveMixin(Base) { - declare ezEthHyperdriveContract: ReadWriteContract; + declare ezEthHyperdriveContract: CachedReadWriteContract; async getBaseToken(): Promise { return new ReadWriteEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } async getSharesToken( - options?: ContractReadOptions, + options?: ContractReadOptions ): Promise { const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadWriteErc20({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/getHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/getHyperdrive.ts deleted file mode 100644 index fde57e04a..000000000 --- a/packages/hyperdrive-js-core/src/hyperdrive/getHyperdrive.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Drift, ReadWriteAdapter } from "@delvtech/drift"; -import semver from "semver"; -import { hyperdriveAbi } from "src/hyperdrive/base/abi"; -import { - ReadHyperdrive, - ReadHyperdriveOptions, -} from "src/hyperdrive/base/ReadHyperdrive"; -import { - ReadWriteHyperdrive, - ReadWriteHyperdriveOptions, -} from "src/hyperdrive/base/ReadWriteHyperdrive"; -import { ReadHyperdrive_v1_0_14 } from "src/hyperdrive/base/v1.0.14/ReadHyperdrive_v1_0_14"; -import { ReadWriteHyperdrive_v1_0_14 } from "src/hyperdrive/base/v1.0.14/ReadWriteHyperdrive_v1_0_14"; -import { ReadStEthHyperdrive } from "src/hyperdrive/steth/ReadStEthHyperdrive"; -import { ReadWriteStEthHyperdrive } from "src/hyperdrive/steth/ReadWriteStEthHyperdrive"; -import { ReadStEthHyperdrive_v1_0_14 } from "src/hyperdrive/steth/v1.0.14/ReadStEthHyperdrive_v1_0_14"; -import { ReadWriteStEthHyperdrive_v1_0_14 } from "src/hyperdrive/steth/v1.0.14/ReadWriteStEthHyperdrive_v1_0_14"; - -export interface HyperdriveOptions - extends ReadHyperdriveOptions { - drift: T; -} - -export type Hyperdrive = - T extends Drift ? ReadWriteHyperdrive : ReadHyperdrive; - -export async function getHyperdrive({ - address, - drift, - cache = drift.cache, - cacheNamespace, - earliestBlock, - debugName, -}: HyperdriveOptions): Promise> { - cacheNamespace ??= await drift.getChainId(); - - const options: HyperdriveOptions = { - address, - drift, - cache, - cacheNamespace, - earliestBlock, - debugName, - }; - const isReadWrite = isReadWriteOptions(options); - - const version = await drift.read({ - abi: hyperdriveAbi, - address, - fn: "version", - cacheNamespace, - }); - const isV1_0_14 = semver.lte(version, "1.0.14"); - - const kind = isV1_0_14 - ? undefined - : await drift.read({ - abi: hyperdriveAbi, - address, - fn: "kind", - cacheNamespace, - }); - - switch (kind) { - case "StETHHyperdrive": - if (isReadWrite && isV1_0_14) { - return new ReadWriteStEthHyperdrive_v1_0_14(options); - } - - if (isReadWrite) { - return new ReadWriteStEthHyperdrive(options); - } - - if (isV1_0_14) { - return new ReadStEthHyperdrive_v1_0_14(options) as any; - } - - return new ReadStEthHyperdrive(options) as any; - - default: - if (isReadWrite && isV1_0_14) { - return new ReadWriteHyperdrive_v1_0_14(options); - } - - if (isReadWrite) { - return new ReadWriteHyperdrive(options); - } - - if (isV1_0_14) { - return new ReadHyperdrive_v1_0_14(options) as any; - } - - return new ReadHyperdrive(options) as any; - } -} - -function isReadWriteOptions( - options: HyperdriveOptions, -): options is ReadWriteHyperdriveOptions { - return typeof options.drift.write === "function"; -} diff --git a/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadLsEthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadLsEthHyperdrive.ts index 3f90a02b4..0bf5eec48 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadLsEthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadLsEthHyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadHyperdrive, @@ -16,12 +16,12 @@ export class ReadLsEthHyperdrive extends readLsEthHyperdriveMixin( */ export interface ReadLsEthHyperdriveMixin { /** - * Get a client for ETH, the base token for this Hyperdrive instance. + * Get a model of ETH, the base token for this Hyperdrive instance. */ getBaseToken(options?: ContractReadOptions): Promise; /** - * Get a client for the LsETH token for this Hyperdrive instance. + * Get a model of the LsETH token for this Hyperdrive instance. */ getSharesToken(options?: ContractReadOptions): Promise; } @@ -41,7 +41,8 @@ export function readLsEthHyperdriveMixin>( async getBaseToken(): Promise { return new ReadEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } @@ -50,9 +51,9 @@ export function readLsEthHyperdriveMixin>( return new ReadLsEth({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadWriteLsEthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadWriteLsEthHyperdrive.ts index ddca694a7..9e0a15fbb 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadWriteLsEthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/lseth/ReadWriteLsEthHyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadWriteHyperdrive } from "src/hyperdrive/base/ReadWriteHyperdrive"; import { @@ -9,7 +9,7 @@ import { ReadWriteEth } from "src/token/eth/ReadWriteEth"; import { ReadWriteLsEth } from "src/token/lseth/ReadWriteLsEth"; export class ReadWriteLsEthHyperdrive extends readWriteLsEthHyperdriveMixin( - ReadWriteHyperdrive, + ReadWriteHyperdrive ) {} export interface ReadWriteLsEthHyperdriveMixin @@ -19,24 +19,25 @@ export interface ReadWriteLsEthHyperdriveMixin } export function readWriteLsEthHyperdriveMixin< - T extends Constructor, + T extends Constructor >(Base: T): Constructor & T { return class extends readLsEthHyperdriveMixin(Base) { async getSharesToken( - options?: ContractReadOptions, + options?: ContractReadOptions ): Promise { const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadWriteLsEth({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } async getBaseToken(): Promise { return new ReadWriteEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadMetaMorphoHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadMetaMorphoHyperdrive.ts new file mode 100644 index 000000000..764e9fed1 --- /dev/null +++ b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadMetaMorphoHyperdrive.ts @@ -0,0 +1,56 @@ +import { ReadContract } from "@delvtech/evm-client"; +import { Constructor } from "src/base/types"; +import { + ReadHyperdrive, + ReadHyperdriveOptions, +} from "src/hyperdrive/base/ReadHyperdrive"; +import { + MetaMorphoSnippetsABI, + metaMorphoSnippetsABI, +} from "src/hyperdrive/metamorpho/abi"; + +// See: https://www.notion.so/delv-tech/Testnet-Addresses-911a0f422f374059afa5c40d76373de6 +const SEPOLIA_METAMORPHO_SNIPPETS_ADDRESS = + "0xf5461A30b3723085F8E702fCc7461db85481c173"; + +export class ReadMetaMorphoHyperdrive extends readMetaMorphoHyperdriveMixin( + ReadHyperdrive, +) {} + +/** + * @internal + */ +export interface ReadMetaMorphoHyperdriveMixin { + metaMorphoContract: ReadContract; +} + +/** + * @internal + */ +export function readMetaMorphoHyperdriveMixin< + T extends Constructor, +>(Base: T): Constructor & T { + return class extends Base { + metaMorphoContract: ReadContract; + + constructor(...[options]: any[]) { + const { + debugName = "MetaMorpho Hyperdrive", + address, + cache, + namespace, + ...modelOptions + } = options as ReadHyperdriveOptions; + super({ debugName, address, cache, namespace, ...modelOptions }); + + this.metaMorphoContract = this.contractFactory({ + abi: metaMorphoSnippetsABI, + // TODO: Refactor to a switch/case on chainId once evm-client has chainId + // support on the Network interface + address: SEPOLIA_METAMORPHO_SNIPPETS_ADDRESS, + cache, + namespace, + }); + } + }; +} diff --git a/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadWriteMetaMorphoHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadWriteMetaMorphoHyperdrive.ts new file mode 100644 index 000000000..76ab82dbb --- /dev/null +++ b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/ReadWriteMetaMorphoHyperdrive.ts @@ -0,0 +1,26 @@ +import { ReadContract as ReadWriteContract } from "@delvtech/evm-client"; +import { Constructor } from "src/base/types"; +import { ReadWriteHyperdrive } from "src/hyperdrive/base/ReadWriteHyperdrive"; +import { MetaMorphoSnippetsABI } from "src/hyperdrive/metamorpho/abi"; + +export class ReadWriteMetaMorphoHyperdrive extends readWriteMetaMorphoHyperdriveMixin( + ReadWriteHyperdrive +) {} + +/** + * @internal + */ +export interface ReadWriteMetaMorphoHyperdriveMixin { + metaMorphoContract: ReadWriteContract; +} + +/** + * @internal + */ +export function readWriteMetaMorphoHyperdriveMixin< + T extends Constructor +>(Base: T): Constructor & T { + return class extends Base { + declare metaMorphoContract: ReadWriteContract; + }; +} diff --git a/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/abi.ts b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/abi.ts new file mode 100644 index 000000000..6b4f66e9f --- /dev/null +++ b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/abi.ts @@ -0,0 +1,61 @@ +export type MetaMorphoSnippetsABI = typeof metaMorphoSnippetsABI; +export const metaMorphoSnippetsABI = [ + { + inputs: [ + { + components: [ + { internalType: "address", name: "loanToken", type: "address" }, + { internalType: "address", name: "collateralToken", type: "address" }, + { internalType: "address", name: "oracle", type: "address" }, + { internalType: "address", name: "irm", type: "address" }, + { internalType: "uint256", name: "lltv", type: "uint256" }, + ], + internalType: "struct MarketParams", + name: "marketParams", + type: "tuple", + }, + { + components: [ + { + internalType: "uint128", + name: "totalSupplyAssets", + type: "uint128", + }, + { + internalType: "uint128", + name: "totalSupplyShares", + type: "uint128", + }, + { + internalType: "uint128", + name: "totalBorrowAssets", + type: "uint128", + }, + { + internalType: "uint128", + name: "totalBorrowShares", + type: "uint128", + }, + { internalType: "uint128", name: "lastUpdate", type: "uint128" }, + { internalType: "uint128", name: "fee", type: "uint128" }, + ], + internalType: "struct Market", + name: "market", + type: "tuple", + }, + ], + name: "supplyAPYMarket", + outputs: [{ internalType: "uint256", name: "supplyApy", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "vault", type: "address" }], + name: "supplyAPYVault", + outputs: [ + { internalType: "uint256", name: "avgSupplyApy", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/v1.0.14/ReadMetaMorphoHyperdrive_v1_0_14.ts b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/v1.0.14/ReadMetaMorphoHyperdrive_v1_0_14.ts new file mode 100644 index 000000000..333e8cfa1 --- /dev/null +++ b/packages/hyperdrive-js-core/src/hyperdrive/metamorpho/v1.0.14/ReadMetaMorphoHyperdrive_v1_0_14.ts @@ -0,0 +1,6 @@ +import { ReadHyperdrive_v1_0_14 } from "src/hyperdrive/base/v1.0.14/ReadHyperdrive_v1_0_14"; +import { readMetaMorphoHyperdriveMixin } from "src/hyperdrive/metamorpho/ReadMetaMorphoHyperdrive"; + +export class ReadMetaMorphoHyperdrive_v1_0_14 extends readMetaMorphoHyperdriveMixin( + ReadHyperdrive_v1_0_14 +) {} diff --git a/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadREthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadREthHyperdrive.ts index 708c1b57c..f463a34e0 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadREthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadREthHyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { fixed } from "@delvtech/fixed-point-wasm"; import { Constructor } from "src/base/types"; import { @@ -17,12 +17,12 @@ export class ReadREthHyperdrive extends readREthHyperdriveMixin( */ export interface ReadREthHyperdriveMixin { /** - * Get a client for ETH, the base token for this Hyperdrive instance. + * Get a model of ETH, the base token for this Hyperdrive instance. */ getBaseToken(options?: ContractReadOptions): Promise; /** - * Get a client for the rETH token for this Hyperdrive instance. + * Get a model of the rETH token for this Hyperdrive instance. */ getSharesToken(options?: ContractReadOptions): Promise; } @@ -42,7 +42,8 @@ export function readREthHyperdriveMixin>( async getBaseToken(): Promise { return new ReadEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } @@ -50,9 +51,9 @@ export function readREthHyperdriveMixin>( const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadREth({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } diff --git a/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadWriteREthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadWriteREthHyperdrive.ts index 0fa108bf3..aac239e18 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadWriteREthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/reth/ReadWriteREthHyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadWriteHyperdrive } from "src/hyperdrive/base/ReadWriteHyperdrive"; import { readREthHyperdriveMixin } from "src/hyperdrive/reth/ReadREthHyperdrive"; @@ -23,7 +23,8 @@ export function readWriteREthHyperdriveMixin< return class extends readREthHyperdriveMixin(Base) { async getBaseToken(): Promise { return new ReadWriteEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } @@ -33,9 +34,9 @@ export function readWriteREthHyperdriveMixin< const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadWriteREth({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadStEthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadStEthHyperdrive.ts index a77b69474..593828945 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadStEthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadStEthHyperdrive.ts @@ -1,4 +1,4 @@ -import { ContractReadOptions } from "@delvtech/drift"; +import { ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { fixed } from "src/fixed-point"; import { @@ -8,7 +8,22 @@ import { import { ReadEth } from "src/token/eth/ReadEth"; import { ReadStEth } from "src/token/steth/ReadStEth"; -export interface ReadStEthHyperdriveOptions extends ReadHyperdriveOptions {} +export interface ReadStEthHyperdriveOptions extends ReadHyperdriveOptions { + /** + * The `StETHHyperdrive` contract stores and operates on Lido balances in + * shares. However, since users are most familiar with stETH public balances, + * this model will accept and return balances in stETH by default and convert + * them to shares when interacting with the contract to ease UI integration. + * + * To use shares instead of stETH, set this to `true`. + * + * @default false + * + * @see + * https://docs.lido.fi/guides/lido-tokens-integration-guide#bookkeeping-shares + */ + useSharesAccounting?: boolean; +} export class ReadStEthHyperdrive extends readStEthHyperdriveMixin( ReadHyperdrive, @@ -23,12 +38,12 @@ export class ReadStEthHyperdrive extends readStEthHyperdriveMixin( */ export interface ReadStEthHyperdriveMixin { /** - * Get a client for ETH, the base token for this Hyperdrive instance. + * Get a model of ETH, the base token for this Hyperdrive instance. */ getBaseToken(options?: ContractReadOptions): Promise; /** - * Get a client for the Lido stETH token for this Hyperdrive instance. + * Get a model of the Lido stETH token for this Hyperdrive instance. */ getSharesToken(options?: ContractReadOptions): Promise; } @@ -48,7 +63,8 @@ export function readStEthHyperdriveMixin>( async getBaseToken(): Promise { return new ReadEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } @@ -56,9 +72,9 @@ export function readStEthHyperdriveMixin>( const { vaultSharesToken } = await this.getPoolConfig(); return new ReadStEth({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } diff --git a/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadWriteStEthHyperdrive.ts b/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadWriteStEthHyperdrive.ts index 17a0e466d..0d39e3ce6 100644 --- a/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadWriteStEthHyperdrive.ts +++ b/packages/hyperdrive-js-core/src/hyperdrive/steth/ReadWriteStEthHyperdrive.ts @@ -1,5 +1,9 @@ -import { ContractReadOptions, ReplaceProps } from "@delvtech/drift"; -import { Constructor } from "src/base/types"; +import { + CachedReadWriteContract, + ContractReadOptions, +} from "@delvtech/evm-client"; +import { Constructor, Override } from "src/base/types"; +import { HyperdriveAbi } from "src/hyperdrive/base/abi"; import { ReadWriteHyperdrive, ReadWriteHyperdriveOptions, @@ -13,40 +17,41 @@ import { ReadWriteEth } from "src/token/eth/ReadWriteEth"; import { ReadWriteStEth } from "src/token/steth/ReadWriteStEth"; export class ReadWriteStEthHyperdrive extends readWriteStEthHyperdriveMixin( - ReadWriteHyperdrive, + ReadWriteHyperdrive ) {} export interface ReadWriteStEthHyperdriveMixin extends ReadStEthHyperdriveMixin { + stEthHyperdriveContract: CachedReadWriteContract; getBaseToken(options?: ContractReadOptions): Promise; getSharesToken(options?: ContractReadOptions): Promise; } export interface ReadWriteStEthHyperdriveOptions - extends ReplaceProps< - ReadWriteHyperdriveOptions, - ReadStEthHyperdriveOptions - > {} + extends Override {} export function readWriteStEthHyperdriveMixin< - T extends Constructor, + T extends Constructor >(Base: T): Constructor & T { return class extends readStEthHyperdriveMixin(Base) { + declare stEthHyperdriveContract: CachedReadWriteContract; + async getBaseToken(): Promise { return new ReadWriteEth({ - drift: this.drift, + contractFactory: this.contractFactory, + network: this.network, }); } async getSharesToken( - options?: ContractReadOptions, + options?: ContractReadOptions ): Promise { const { vaultSharesToken } = await this.getPoolConfig(options); return new ReadWriteStEth({ address: vaultSharesToken, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + namespace: this.contract.namespace, + network: this.network, }); } }; diff --git a/packages/hyperdrive-js-core/src/drift/ReadClient.ts b/packages/hyperdrive-js-core/src/model/ReadModel.ts similarity index 51% rename from packages/hyperdrive-js-core/src/drift/ReadClient.ts rename to packages/hyperdrive-js-core/src/model/ReadModel.ts index 515130daa..81084113d 100644 --- a/packages/hyperdrive-js-core/src/drift/ReadClient.ts +++ b/packages/hyperdrive-js-core/src/model/ReadModel.ts @@ -1,14 +1,20 @@ -import { Drift } from "@delvtech/drift"; +import { Network } from "@delvtech/evm-client"; +import { Prettify } from "src/base/types"; +import { + ContractFactoryOptions, + ReadContractFactory, +} from "src/evm-client/contractFactory"; /** - * The base options required for all read clients. + * The base options required for all read models. */ -export interface ReadClientOptions { - drift: Drift; +export interface ReadModelOptions { + contractFactory: ReadContractFactory; + network: Network; /** * An arbitrary name for the instance. This is for convenience only (e.g., for - * use as a display name or in logging) and has no affect on the client's + * use as a display name or in logging) and has no affect on the model's * behavior. */ debugName?: string; @@ -20,22 +26,28 @@ export interface ReadClientOptions { } /** - * A base class for read-only clients. + * A base class for read-only models. */ -export class ReadClient { - drift: Drift; +export class ReadModel { debugName: string; + network: Network; + contractFactory: ReadContractFactory; - constructor({ debugName, drift, earliestBlock }: ReadClientOptions) { + constructor({ + debugName, + network, + contractFactory, + earliestBlock, + }: ReadModelOptions) { this.debugName = debugName ?? this.constructor.name; - this.drift = drift; + this.network = network; + this.contractFactory = contractFactory; // Override the contract factory to ensure that events are fetched from the // earliest block if necessary. if (earliestBlock) { - const originalContractFactory = this.drift.contract; - this.drift.contract = (options) => { - const contract = originalContractFactory(options); + this.contractFactory = (options) => { + const contract = contractFactory(options); // Override the getEvents method const originalGetEvents = contract.getEvents; @@ -51,8 +63,17 @@ export class ReadClient { return originalGetEvents(eventName, _options); }; - return contract as any; + return contract; }; } } } + +/** + * The options required to create a read model that represents a specific + * contract. + */ +export type ReadContractModelOptions = Prettify< + // The abi is omitted because it's assumed the model will import its own ABI + ReadModelOptions & Omit +>; diff --git a/packages/hyperdrive-js-core/src/model/ReadWriteModel.ts b/packages/hyperdrive-js-core/src/model/ReadWriteModel.ts new file mode 100644 index 000000000..8647d4221 --- /dev/null +++ b/packages/hyperdrive-js-core/src/model/ReadWriteModel.ts @@ -0,0 +1,33 @@ +import { Prettify } from "src/base/types"; +import { + ContractFactoryOptions, + ReadWriteContractFactory, +} from "src/evm-client/contractFactory"; +import { ReadModel, ReadModelOptions } from "src/model/ReadModel"; + +/** + * The base options required for all read-write models. + */ +export interface ReadWriteModelOptions extends ReadModelOptions { + contractFactory: ReadWriteContractFactory; +} + +/** + * A base class for read-write models. + */ +export class ReadWriteModel extends ReadModel { + declare contractFactory: ReadWriteContractFactory; + + constructor(options: ReadWriteModelOptions) { + super(options); + } +} + +/** + * The options required to create a read-write model that represents a specific + * contract. + */ +export type ReadWriteContractModelOptions = Prettify< + // The abi is omitted because it's assumed the model will import its own ABI + ReadWriteModelOptions & Omit +>; diff --git a/packages/hyperdrive-js-core/src/pool/types.ts b/packages/hyperdrive-js-core/src/pool/types.ts index 36c6d73f1..b3cf3623d 100644 --- a/packages/hyperdrive-js-core/src/pool/types.ts +++ b/packages/hyperdrive-js-core/src/pool/types.ts @@ -1,4 +1,4 @@ -import { FunctionReturn } from "@delvtech/drift"; +import { FunctionReturn } from "@delvtech/evm-client"; import { HyperdriveAbi } from "src/hyperdrive/base/abi"; export type PoolConfig = FunctionReturn; diff --git a/packages/hyperdrive-js-core/src/registry/ReadRegistry.ts b/packages/hyperdrive-js-core/src/registry/ReadRegistry.ts index 4bfe1514f..b5ff6db2c 100644 --- a/packages/hyperdrive-js-core/src/registry/ReadRegistry.ts +++ b/packages/hyperdrive-js-core/src/registry/ReadRegistry.ts @@ -1,35 +1,34 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Address } from "abitype"; -import { ReadContractClientOptions } from "src/drift/ContractClient"; -import { ReadClient } from "src/drift/ReadClient"; import { ReadFactory } from "src/factory/ReadFactory"; import { ReadHyperdrive } from "src/hyperdrive/base/ReadHyperdrive"; +import { ReadContractModelOptions, ReadModel } from "src/model/ReadModel"; import { RegistryAbi, registryAbi } from "src/registry/abi"; import { FactoryInfoWithMetadata, ReadInstanceInfoWithMetadata, } from "src/registry/types"; -export interface ReadRegistryOptions extends ReadContractClientOptions {} +export interface ReadRegistryOptions extends ReadContractModelOptions {} -export class ReadRegistry extends ReadClient { +export class ReadRegistry extends ReadModel { address: Address; - contract: Contract; + contract: CachedReadContract; constructor({ debugName = "Hyperdrive Registry", address, cache, - cacheNamespace, - ...rest + namespace, + ...modelOptions }: ReadRegistryOptions) { - super({ debugName, ...rest }); + super({ debugName, ...modelOptions }); this.address = address; - this.contract = this.drift.contract({ + this.contract = this.contractFactory({ abi: registryAbi, address, cache, - cacheNamespace, + namespace, }); } @@ -42,9 +41,8 @@ export class ReadRegistry extends ReadClient { (address) => new ReadFactory({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), ); } @@ -121,9 +119,8 @@ export class ReadRegistry extends ReadClient { (address) => new ReadHyperdrive({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), ); } @@ -170,9 +167,8 @@ export class ReadRegistry extends ReadClient { data: `0x${data.toString(16)}`, factory: new ReadFactory({ address: factory, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), }; } @@ -196,9 +192,8 @@ export class ReadRegistry extends ReadClient { data: `0x${data.toString(16)}`, factory: new ReadFactory({ address: factory, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), })); } diff --git a/packages/hyperdrive-js-core/src/registry/ReadWriteRegistry.ts b/packages/hyperdrive-js-core/src/registry/ReadWriteRegistry.ts index dc67671cf..a8cfad672 100644 --- a/packages/hyperdrive-js-core/src/registry/ReadWriteRegistry.ts +++ b/packages/hyperdrive-js-core/src/registry/ReadWriteRegistry.ts @@ -1,24 +1,23 @@ import { + CachedReadWriteContract, ContractReadOptions, - Drift, - ReadWriteAdapter, - ReadWriteContract, - ReplaceProps, -} from "@delvtech/drift"; +} from "@delvtech/evm-client"; import { Address } from "abitype"; -import { ReadWriteContractClientOptions } from "src/drift/ContractClient"; +import { Override } from "src/base/types"; +import { ReadWriteContractFactory } from "src/evm-client/contractFactory"; import { ReadWriteFactory } from "src/factory/ReadWriteFactory"; import { ReadWriteHyperdrive } from "src/hyperdrive/base/ReadWriteHyperdrive"; +import { ReadWriteContractModelOptions } from "src/model/ReadWriteModel"; import { ReadRegistry, ReadRegistryOptions } from "src/registry/ReadRegistry"; import { RegistryAbi } from "src/registry/abi"; import { ReadWriteInstanceInfoWithMetadata } from "src/registry/types"; export interface ReadWriteRegistryOptions - extends ReplaceProps {} + extends Override {} export class ReadWriteRegistry extends ReadRegistry { - declare drift: Drift; - declare contract: ReadWriteContract; + declare contract: CachedReadWriteContract; + declare contractFactory: ReadWriteContractFactory; constructor(options: ReadWriteRegistryOptions) { super(options); @@ -35,9 +34,8 @@ export class ReadWriteRegistry extends ReadRegistry { (address) => new ReadWriteFactory({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), ); } @@ -67,9 +65,8 @@ export class ReadWriteRegistry extends ReadRegistry { (address) => new ReadWriteHyperdrive({ address, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), ); } @@ -90,9 +87,8 @@ export class ReadWriteRegistry extends ReadRegistry { data: `0x${data.toString(16)}`, factory: new ReadWriteFactory({ address: factory, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), }; } @@ -116,9 +112,8 @@ export class ReadWriteRegistry extends ReadRegistry { data: `0x${data.toString(16)}`, factory: new ReadWriteFactory({ address: factory, - drift: this.drift, - cache: this.contract.cache, - cacheNamespace: this.contract.cacheNamespace, + contractFactory: this.contractFactory, + network: this.network, }), })); } diff --git a/packages/hyperdrive-js-core/src/registry/types.ts b/packages/hyperdrive-js-core/src/registry/types.ts index 987bab0c9..61eaf513e 100644 --- a/packages/hyperdrive-js-core/src/registry/types.ts +++ b/packages/hyperdrive-js-core/src/registry/types.ts @@ -1,4 +1,5 @@ -import { FunctionReturn, ReplaceProps } from "@delvtech/drift"; +import { FunctionReturn } from "@delvtech/evm-client"; +import { Override } from "src/base/types"; import { ReadFactory } from "src/factory/ReadFactory"; import { ReadWriteFactory } from "src/factory/ReadWriteFactory"; import { RegistryAbi } from "src/registry/abi"; @@ -7,7 +8,7 @@ import { RegistryAbi } from "src/registry/abi"; * The info collected for each Hyperdrive factory along with the metadata * associated with each instance. */ -export type FactoryInfoWithMetadata = ReplaceProps< +export type FactoryInfoWithMetadata = Override< FunctionReturn, { /** @@ -22,7 +23,7 @@ export type FactoryInfoWithMetadata = ReplaceProps< * The info related to each Hyperdrive instance along with the metadata * associated with each instance. */ -export type ReadInstanceInfoWithMetadata = ReplaceProps< +export type ReadInstanceInfoWithMetadata = Override< FunctionReturn, { /** @@ -38,7 +39,7 @@ export type ReadInstanceInfoWithMetadata = ReplaceProps< >; /** {@inheritDoc ReadInstanceInfoWithMetadata} */ -export type ReadWriteInstanceInfoWithMetadata = ReplaceProps< +export type ReadWriteInstanceInfoWithMetadata = Override< ReadInstanceInfoWithMetadata, { /** {@inheritDoc ReadInstanceInfoWithMetadata.factory} */ diff --git a/packages/hyperdrive-js-core/src/token/ReadToken.ts b/packages/hyperdrive-js-core/src/token/ReadToken.ts index a582e2f25..2b313b6e6 100644 --- a/packages/hyperdrive-js-core/src/token/ReadToken.ts +++ b/packages/hyperdrive-js-core/src/token/ReadToken.ts @@ -1,7 +1,7 @@ -import { ContractReadOptions } from "@delvtech/drift"; -import { ReadClient } from "src/drift/ReadClient"; +import { ContractReadOptions } from "@delvtech/evm-client"; +import { ReadModel } from "src/model/ReadModel"; -export interface ReadToken extends ReadClient { +export interface ReadToken extends ReadModel { address: `0x${string}`; /** diff --git a/packages/hyperdrive-js-core/src/token/ReadWriteToken.ts b/packages/hyperdrive-js-core/src/token/ReadWriteToken.ts index 8515c6bbd..ebd3a1f2c 100644 --- a/packages/hyperdrive-js-core/src/token/ReadWriteToken.ts +++ b/packages/hyperdrive-js-core/src/token/ReadWriteToken.ts @@ -1,9 +1,11 @@ -import { ContractWriteOptions, ReplaceProps } from "@delvtech/drift"; -import { ReadWriteClient } from "src/drift/ReadWriteClient"; +import { ContractWriteOptions } from "@delvtech/evm-client"; +import { ReadWriteContractFactory } from "src/evm-client/contractFactory"; +import { ReadWriteModel } from "src/model/ReadWriteModel"; import { ReadToken } from "src/token/ReadToken"; -export interface ReadWriteToken - extends ReplaceProps { +export interface ReadWriteToken extends ReadToken, ReadWriteModel { + contractFactory: ReadWriteContractFactory; + /** * Give a spending allowance to a given spender. * @param spender - The address of the spender. diff --git a/packages/hyperdrive-js-core/src/token/erc20/ReadErc20.ts b/packages/hyperdrive-js-core/src/token/erc20/ReadErc20.ts index 9fac7e2b0..7d2e94769 100644 --- a/packages/hyperdrive-js-core/src/token/erc20/ReadErc20.ts +++ b/packages/hyperdrive-js-core/src/token/erc20/ReadErc20.ts @@ -1,36 +1,34 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; -import { Address } from "abitype"; -import { ReadContractClientOptions } from "src/drift/ContractClient"; -import { ReadClient } from "src/drift/ReadClient"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; +import { ReadContractModelOptions, ReadModel } from "src/model/ReadModel"; import { erc20Abi, Erc20Abi } from "src/token/erc20/abi"; import { ReadToken } from "src/token/ReadToken"; -export interface ReadErc20Options extends ReadContractClientOptions {} +export interface ReadErc20Options extends ReadContractModelOptions {} -export class ReadErc20 extends ReadClient implements ReadToken { - contract: Contract; +export class ReadErc20 extends ReadModel implements ReadToken { + contract: CachedReadContract; constructor({ debugName = "ERC-20 Token", address, cache, - cacheNamespace, - ...rest + namespace, + ...modelOptions }: ReadErc20Options) { - super({ debugName, ...rest }); - this.contract = this.drift.contract({ + super({ debugName, ...modelOptions }); + this.contract = this.contractFactory({ abi: erc20Abi, address, cache, - cacheNamespace, + namespace, }); } - get address(): Address { + get address(): `0x${string}` { return this.contract.address; } - get namespace(): PropertyKey | undefined { - return this.contract.cacheNamespace; + get namespace(): string | undefined { + return this.contract.namespace; } getName(): Promise { diff --git a/packages/hyperdrive-js-core/src/token/erc20/ReadWriteErc20.ts b/packages/hyperdrive-js-core/src/token/erc20/ReadWriteErc20.ts index f1075bd3d..90fee23dc 100644 --- a/packages/hyperdrive-js-core/src/token/erc20/ReadWriteErc20.ts +++ b/packages/hyperdrive-js-core/src/token/erc20/ReadWriteErc20.ts @@ -1,24 +1,27 @@ import { + CachedReadWriteContract, ContractWriteOptions, - Drift, - ReadWriteAdapter, - ReadWriteContract, -} from "@delvtech/drift"; -import { ReadWriteContractClientOptions } from "src/drift/ContractClient"; +} from "@delvtech/evm-client"; +import { ReadWriteContractFactory } from "src/evm-client/contractFactory"; +import { syncCacheWithTransaction } from "src/evm-client/syncCacheWithTransaction"; +import { ReadWriteContractModelOptions } from "src/model/ReadWriteModel"; import { ReadWriteToken } from "src/token/ReadWriteToken"; import { ReadErc20 } from "src/token/erc20/ReadErc20"; import { Erc20Abi } from "src/token/erc20/abi"; -export interface ReadWriteErc20Options extends ReadWriteContractClientOptions {} +export interface ReadWriteErc20Options extends ReadWriteContractModelOptions {} export class ReadWriteErc20 extends ReadErc20 implements ReadWriteToken { - declare drift: Drift; - declare contract: ReadWriteContract; + declare contract: CachedReadWriteContract; + declare contractFactory: ReadWriteContractFactory; constructor(options: ReadWriteErc20Options) { super(options); } + @syncCacheWithTransaction({ + cacheEntries: [{ functionName: "allowance" }], + }) async approve({ spender, amount, @@ -32,13 +35,7 @@ export class ReadWriteErc20 extends ReadErc20 implements ReadWriteToken { const hash = await this.contract.write( "approve", { spender, amount }, - { - ...options, - onMined: (receipt) => { - this.contract.invalidateReadsMatching("allowance"); - options?.onMined?.(receipt); - }, - }, + options, ); return hash; } diff --git a/packages/hyperdrive-js-core/src/token/erc4626/ReadErc4626.ts b/packages/hyperdrive-js-core/src/token/erc4626/ReadErc4626.ts index d263fe299..935e5296f 100644 --- a/packages/hyperdrive-js-core/src/token/erc4626/ReadErc4626.ts +++ b/packages/hyperdrive-js-core/src/token/erc4626/ReadErc4626.ts @@ -1,4 +1,4 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadErc20, ReadErc20Options } from "src/token/erc20/ReadErc20"; import { Erc4626Abi, erc4626Abi } from "src/token/erc4626/abi"; @@ -9,7 +9,7 @@ export class ReadErc4626 extends readErc4626Mixin(ReadErc20) {} * @internal */ export interface ReadErc4626Mixin { - erc4626Contract: Contract; + erc4626Contract: CachedReadContract; /** * Get the total supply of assets in the vault. @@ -46,22 +46,22 @@ export function readErc4626Mixin>( Base: T, ): Constructor & T { return class extends Base implements ReadErc4626Mixin { - erc4626Contract: Contract; + erc4626Contract: CachedReadContract; constructor(...[options]: any[]) { const { debugName = "ERC-4626 Tokenized Vault", address, cache, - cacheNamespace, - ...rest + namespace, + ...modelOptions } = options as ReadErc20Options; - super({ debugName, address, cache, cacheNamespace, ...rest }); - this.erc4626Contract = this.drift.contract({ + super({ debugName, address, cache, namespace, ...modelOptions }); + this.erc4626Contract = this.contractFactory({ abi: erc4626Abi, address, cache, - cacheNamespace, + namespace, }); } diff --git a/packages/hyperdrive-js-core/src/token/erc4626/ReadMockErc4626.ts b/packages/hyperdrive-js-core/src/token/erc4626/ReadMockErc4626.ts index 657c2b13a..17809c137 100644 --- a/packages/hyperdrive-js-core/src/token/erc4626/ReadMockErc4626.ts +++ b/packages/hyperdrive-js-core/src/token/erc4626/ReadMockErc4626.ts @@ -1,4 +1,4 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { mockErc4626Abi, MockErc4626Abi } from "src/token/erc4626/abi"; import { ReadErc4626 } from "src/token/erc4626/ReadErc4626"; @@ -9,7 +9,7 @@ export class ReadMockErc4626 extends readMockErc4626Mixin(ReadErc4626) {} * @internal */ export interface ReadMockErc4626Mixin { - mockErc4626Contract: Contract; + mockErc4626Contract: CachedReadContract; /** * Get the rate of the vault. @@ -24,22 +24,22 @@ export function readMockErc4626Mixin>( BaseReadErc4626: T, ): Constructor & T { return class extends BaseReadErc4626 implements ReadMockErc4626Mixin { - mockErc4626Contract: Contract; + mockErc4626Contract: CachedReadContract; constructor(...[options]: any[]) { const { debugName = "Mock ERC-4626 Tokenized Vault", address, cache, - cacheNamespace, - ...rest + namespace, + ...modelOptions } = options as ConstructorParameters[0]; - super({ debugName, address, cache, cacheNamespace, ...rest }); - this.mockErc4626Contract = this.drift.contract({ + super({ debugName, address, cache, namespace, ...modelOptions }); + this.mockErc4626Contract = this.contractFactory({ abi: mockErc4626Abi, address, cache, - cacheNamespace, + namespace, }); } diff --git a/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteErc4626.ts b/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteErc4626.ts index 8521db317..5762a88b9 100644 --- a/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteErc4626.ts +++ b/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteErc4626.ts @@ -1,8 +1,8 @@ -import { ReadWriteContract } from "@delvtech/drift"; +import { CachedReadWriteContract } from "@delvtech/evm-client"; import { ReadWriteErc20 } from "src/token/erc20/ReadWriteErc20"; import { readErc4626Mixin } from "src/token/erc4626/ReadErc4626"; import { Erc4626Abi } from "src/token/erc4626/abi"; export class ReadWriteErc4626 extends readErc4626Mixin(ReadWriteErc20) { - declare erc4626Contract: ReadWriteContract; + declare erc4626Contract: CachedReadWriteContract; } diff --git a/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteMockErc4626.ts b/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteMockErc4626.ts index 4c04a4ae0..86dca9f4e 100644 --- a/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteMockErc4626.ts +++ b/packages/hyperdrive-js-core/src/token/erc4626/ReadWriteMockErc4626.ts @@ -1,4 +1,7 @@ -import { ContractWriteOptions, ReadWriteContract } from "@delvtech/drift"; +import { + CachedReadWriteContract, + ContractWriteOptions, +} from "@delvtech/evm-client"; import { MockErc4626Abi } from "src/token/erc4626/abi"; import { readMockErc4626Mixin } from "src/token/erc4626/ReadMockErc4626"; import { ReadWriteErc4626 } from "src/token/erc4626/ReadWriteErc4626"; @@ -6,7 +9,7 @@ import { ReadWriteErc4626 } from "src/token/erc4626/ReadWriteErc4626"; export class ReadWriteMockErc4626 extends readMockErc4626Mixin( ReadWriteErc4626, ) { - declare mockErc4626Contract: ReadWriteContract; + declare mockErc4626Contract: CachedReadWriteContract; /** * Mint shares. diff --git a/packages/hyperdrive-js-core/src/token/eth/ReadEth.ts b/packages/hyperdrive-js-core/src/token/eth/ReadEth.ts index 48a4f552e..4fbc627d7 100644 --- a/packages/hyperdrive-js-core/src/token/eth/ReadEth.ts +++ b/packages/hyperdrive-js-core/src/token/eth/ReadEth.ts @@ -1,10 +1,10 @@ -import { ContractReadOptions } from "@delvtech/drift"; -import { ReadClient, ReadClientOptions } from "src/drift/ReadClient"; +import { ContractReadOptions } from "@delvtech/evm-client"; +import { ReadModel, ReadModelOptions } from "src/model/ReadModel"; import { ReadToken } from "src/token/ReadToken"; -export interface ReadEthOptions extends ReadClientOptions {} +export interface ReadEthOptions extends ReadModelOptions {} -export class ReadEth extends ReadClient implements ReadToken { +export class ReadEth extends ReadModel implements ReadToken { static address = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" as const; address = ReadEth.address; @@ -42,9 +42,6 @@ export class ReadEth extends ReadClient implements ReadToken { account: `0x${string}`; options?: ContractReadOptions; }): Promise { - return this.drift.getBalance({ - address: account, - ...options, - }); + return this.network.getBalance(account, options); } } diff --git a/packages/hyperdrive-js-core/src/token/eth/ReadWriteEth.ts b/packages/hyperdrive-js-core/src/token/eth/ReadWriteEth.ts index e7f85bf9a..f7f26a6f7 100644 --- a/packages/hyperdrive-js-core/src/token/eth/ReadWriteEth.ts +++ b/packages/hyperdrive-js-core/src/token/eth/ReadWriteEth.ts @@ -1,13 +1,13 @@ -import { Drift, ReadWriteAdapter } from "@delvtech/drift"; -import { ReadWriteClientOptions } from "src/drift/ReadWriteClient"; import { MethodNotImplementedError } from "src/errors/MethodNotImplementedError"; +import { ReadWriteContractFactory } from "src/evm-client/contractFactory"; +import { ReadWriteModelOptions } from "src/model/ReadWriteModel"; import { ReadWriteToken } from "src/token/ReadWriteToken"; import { ReadEth } from "src/token/eth/ReadEth"; -export interface ReadWriteEthOptions extends ReadWriteClientOptions {} +export interface ReadWriteEthOptions extends ReadWriteModelOptions {} export class ReadWriteEth extends ReadEth implements ReadWriteToken { - declare drift: Drift; + declare contractFactory: ReadWriteContractFactory; constructor(options: ReadWriteEthOptions) { super(options); diff --git a/packages/hyperdrive-js-core/src/token/lseth/ReadLsEth.ts b/packages/hyperdrive-js-core/src/token/lseth/ReadLsEth.ts index 5fd3792e3..0f9d06c05 100644 --- a/packages/hyperdrive-js-core/src/token/lseth/ReadLsEth.ts +++ b/packages/hyperdrive-js-core/src/token/lseth/ReadLsEth.ts @@ -1,4 +1,4 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadErc20, ReadErc20Options } from "src/token/erc20/ReadErc20"; import { LsEthAbi, lsEthAbi } from "src/token/lseth/abi"; @@ -9,7 +9,7 @@ export class ReadLsEth extends readLsEthMixin(ReadErc20) {} * @internal */ export interface ReadLsEthMixin { - lsEthContract: Contract; + lsEthContract: CachedReadContract; /** * Get the total supply of underlying eth in the lsEth contract. @@ -57,17 +57,17 @@ export function readLsEthMixin>( Base: T, ): Constructor & T { return class extends Base implements ReadLsEthMixin { - lsEthContract: Contract; + lsEthContract: CachedReadContract; constructor(...[options]: any[]) { - const { drift, address, cache, cacheNamespace } = + const { contractFactory, address, cache, namespace } = options as ReadErc20Options; - super({ address, drift, cache, cacheNamespace }); - this.lsEthContract = drift.contract({ + super({ address, contractFactory, cache, namespace }); + this.lsEthContract = contractFactory({ abi: lsEthAbi, address, cache, - cacheNamespace, + namespace, }); } diff --git a/packages/hyperdrive-js-core/src/token/lseth/ReadWriteLsEth.ts b/packages/hyperdrive-js-core/src/token/lseth/ReadWriteLsEth.ts index f1e8237b7..622c91bac 100644 --- a/packages/hyperdrive-js-core/src/token/lseth/ReadWriteLsEth.ts +++ b/packages/hyperdrive-js-core/src/token/lseth/ReadWriteLsEth.ts @@ -1,8 +1,8 @@ -import { ReadWriteContract } from "@delvtech/drift"; +import { CachedReadWriteContract } from "@delvtech/evm-client"; import { ReadWriteErc20 } from "src/token/erc20/ReadWriteErc20"; import { readLsEthMixin } from "src/token/lseth/ReadLsEth"; import { LsEthAbi } from "src/token/lseth/abi"; export class ReadWriteLsEth extends readLsEthMixin(ReadWriteErc20) { - declare lsEthContract: ReadWriteContract; + declare lsEthContract: CachedReadWriteContract; } diff --git a/packages/hyperdrive-js-core/src/token/reth/ReadREth.ts b/packages/hyperdrive-js-core/src/token/reth/ReadREth.ts index 2bcdb7691..5814887bd 100644 --- a/packages/hyperdrive-js-core/src/token/reth/ReadREth.ts +++ b/packages/hyperdrive-js-core/src/token/reth/ReadREth.ts @@ -1,4 +1,4 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadErc20, ReadErc20Options } from "src/token/erc20/ReadErc20"; import { REthAbi, rEthAbi } from "src/token/reth/abi"; @@ -9,7 +9,7 @@ export class ReadREth extends readREthMixin(ReadErc20) {} * @internal */ export interface ReadREthMixin { - rEthContract: Contract; + rEthContract: CachedReadContract; /** * Get the total supply of underlying eth in the rETH contract. @@ -57,17 +57,17 @@ export function readREthMixin>( Base: T, ): Constructor & T { return class extends Base implements ReadREthMixin { - rEthContract: Contract; + rEthContract: CachedReadContract; constructor(...[options]: any[]) { - const { drift, address, cache, cacheNamespace } = + const { contractFactory, address, cache, namespace } = options as ReadErc20Options; - super({ address, drift, cache, cacheNamespace }); - this.rEthContract = drift.contract({ + super({ address, contractFactory, cache, namespace }); + this.rEthContract = contractFactory({ abi: rEthAbi, address, cache, - cacheNamespace, + namespace, }); } diff --git a/packages/hyperdrive-js-core/src/token/reth/ReadWriteREth.ts b/packages/hyperdrive-js-core/src/token/reth/ReadWriteREth.ts index 3b5ef80c7..58dcb09b6 100644 --- a/packages/hyperdrive-js-core/src/token/reth/ReadWriteREth.ts +++ b/packages/hyperdrive-js-core/src/token/reth/ReadWriteREth.ts @@ -1,8 +1,8 @@ -import { ReadWriteContract } from "@delvtech/drift"; +import { CachedReadWriteContract } from "@delvtech/evm-client"; import { ReadWriteErc20 } from "src/token/erc20/ReadWriteErc20"; import { readREthMixin } from "src/token/reth/ReadREth"; import { REthAbi } from "src/token/reth/abi"; export class ReadWriteREth extends readREthMixin(ReadWriteErc20) { - declare rEthContract: ReadWriteContract; + declare rEthContract: CachedReadWriteContract; } diff --git a/packages/hyperdrive-js-core/src/token/steth/ReadStEth.ts b/packages/hyperdrive-js-core/src/token/steth/ReadStEth.ts index dadbc9f19..b3bd469ff 100644 --- a/packages/hyperdrive-js-core/src/token/steth/ReadStEth.ts +++ b/packages/hyperdrive-js-core/src/token/steth/ReadStEth.ts @@ -1,4 +1,4 @@ -import { Contract, ContractReadOptions } from "@delvtech/drift"; +import { CachedReadContract, ContractReadOptions } from "@delvtech/evm-client"; import { Constructor } from "src/base/types"; import { ReadErc20, ReadErc20Options } from "src/token/erc20/ReadErc20"; import { StEthAbi, stEthAbi } from "src/token/steth/abi"; @@ -9,7 +9,7 @@ export class ReadStEth extends readStEthMixin(ReadErc20) {} * @internal */ export interface ReadStEthMixin { - stEthContract: Contract; + stEthContract: CachedReadContract; /** * Get the number of stETH shares held by an account. @@ -54,22 +54,22 @@ export function readStEthMixin>( Base: T, ): Constructor & T { return class extends Base implements ReadStEthMixin { - stEthContract: Contract; + stEthContract: CachedReadContract; constructor(...[options]: any[]) { const { debugName = "stETH Token", address, cache, - cacheNamespace, - ...rest + namespace, + ...modelOptions } = options as ReadErc20Options; - super({ debugName, address, cache, cacheNamespace, ...rest }); - this.stEthContract = this.drift.contract({ + super({ debugName, address, cache, namespace, ...modelOptions }); + this.stEthContract = this.contractFactory({ abi: stEthAbi, address, cache, - cacheNamespace, + namespace, }); } diff --git a/packages/hyperdrive-js-core/src/token/steth/ReadWriteStEth.ts b/packages/hyperdrive-js-core/src/token/steth/ReadWriteStEth.ts index 66ec0b8ff..24b25aec6 100644 --- a/packages/hyperdrive-js-core/src/token/steth/ReadWriteStEth.ts +++ b/packages/hyperdrive-js-core/src/token/steth/ReadWriteStEth.ts @@ -1,8 +1,8 @@ -import { ReadWriteContract } from "@delvtech/drift"; +import { CachedReadWriteContract } from "@delvtech/evm-client"; import { ReadWriteErc20 } from "src/token/erc20/ReadWriteErc20"; import { StEthAbi } from "src/token/steth/abi"; import { readStEthMixin } from "src/token/steth/ReadStEth"; export class ReadWriteStEth extends readStEthMixin(ReadWriteErc20) { - declare stEthContract: ReadWriteContract; + declare stEthContract: CachedReadWriteContract; } diff --git a/packages/hyperdrive-js-core/tsup.config.ts b/packages/hyperdrive-js-core/tsup.config.ts index 07ca24f96..41747e1e2 100644 --- a/packages/hyperdrive-js-core/tsup.config.ts +++ b/packages/hyperdrive-js-core/tsup.config.ts @@ -1,9 +1,44 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["src/exports/index.ts", "src/exports/v1.0.14.ts"], - format: ["esm", "cjs"], - sourcemap: true, + // Splitting the entry points in foundational packages like this makes it + // easier for wrapper packages to selectively re-export `*` from some entry + // points and while augmenting or modifying others. + entry: [ + "src/exports/index.ts", + + "src/exports/contract.ts", + "src/exports/errors.ts", + "src/exports/model.ts", + "src/exports/utils.ts", + + // factory + "src/exports/factory/index.ts", + "src/exports/factory/model.ts", + "src/exports/factory/rest.ts", + + // hyperdrive + "src/exports/hyperdrive/index.ts", + "src/exports/hyperdrive/model.ts", + "src/exports/hyperdrive/rest.ts", + + // registry + "src/exports/registry/index.ts", + "src/exports/registry/model.ts", + "src/exports/registry/rest.ts", + + // token + "src/exports/token/index.ts", + "src/exports/token/model.ts", + "src/exports/token/rest.ts", + + // v1.0.14 + "src/exports/v1.0.14/index.ts", + "src/exports/v1.0.14/hyperdrive/index.ts", + "src/exports/v1.0.14/hyperdrive/model.ts", + "src/exports/v1.0.14/hyperdrive/rest.ts", + ], + format: ["esm"], dts: true, clean: true, minify: true, diff --git a/yarn.lock b/yarn.lock index 2af3ee972..7dc49bfaa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1493,6 +1493,16 @@ lru-cache "^10.0.1" safe-stable-stringify "^2.5.0" +"@delvtech/evm-client@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@delvtech/evm-client/-/evm-client-0.5.1.tgz#b69bd04ecb9f1690c1ce94acb7362e4d30b9e1e5" + integrity sha512-Ixx7coKko1l9i2CkrrkhzRVnxzf+b3ROEppWvN7Q0+Gx3DLq1lq8oorXjZb5dZhs5K07LtJM7sUJLztxx8BIEA== + dependencies: + "@types/lodash.ismatch" "^4.4.9" + fast-safe-stringify "^2.1.1" + lodash.ismatch "^4.4.0" + lru-cache "^10.0.1" + "@discoveryjs/json-ext@0.5.7": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" @@ -4717,6 +4727,13 @@ dependencies: "@types/lodash" "*" +"@types/lodash.ismatch@^4.4.9": + version "4.4.9" + resolved "https://registry.yarnpkg.com/@types/lodash.ismatch/-/lodash.ismatch-4.4.9.tgz#97b4317f7dc3975bb51660a0f9a055ac7b67b134" + integrity sha512-qWihnStOPKH8urljLGm6ZOEdN/5Bt4vxKR81tL3L4ArUNLvcf9RW3QSnPs21eix5BiqioSWq4aAXD4Iep+d0fw== + dependencies: + "@types/lodash" "*" + "@types/lodash.mapvalues@^4.6.9": version "4.6.9" resolved "https://registry.yarnpkg.com/@types/lodash.mapvalues/-/lodash.mapvalues-4.6.9.tgz#1edb4b1d299db332166b474221b06058b34030a7" @@ -9258,7 +9275,7 @@ fast-redact@^3.0.0: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== -fast-safe-stringify@^2.0.6: +fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==