-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
77 changed files
with
1,598 additions
and
904 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,98 @@ | ||
/** | ||
* Combines members of an intersection into a readable type. | ||
* @see https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg | ||
*/ | ||
export type Prettify<T> = { | ||
[K in keyof T]: T[K]; | ||
} & unknown; | ||
|
||
/** | ||
* A generic constructor type. | ||
*/ | ||
export type Constructor< | ||
TInstanceType = any, | ||
TArgs extends any[] = any[], | ||
> = new (...args: TArgs) => TInstanceType; | ||
|
||
/** | ||
* Overrides properties of `T` with properties of `U`. | ||
*/ | ||
export type Override<T, U> = Prettify<Omit<T, keyof U> & U>; | ||
|
||
/** | ||
* Convert members of a union to an intersection. | ||
* | ||
* @example | ||
* ```ts | ||
* type Union = { a: number } | { b: string }; | ||
* type Intersection = UnionToIntersection<Union>; | ||
* // { 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> = ( | ||
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<GetBlockOptions>; | ||
* // { | ||
* // includeTransactions?: boolean | undefined; | ||
* // blockHash?: string | undefined; | ||
* // blockNumber?: bigint | undefined; | ||
* // blockTag?: string | undefined; | ||
* // } | ||
* ``` | ||
*/ | ||
export type MergeKeys<T> = | ||
UnionToIntersection<T> 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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 4 additions & 9 deletions
13
packages/hyperdrive-js-core/src/errors/HyperdriveSdkError.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<ErrorConstructor>) { | ||
super(message, options); | ||
this.name = "HyperdriveSdkError"; | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
packages/hyperdrive-js-core/src/evm-client/contractFactory.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { | ||
CachedReadContract, | ||
CachedReadWriteContract, | ||
SimpleCache, | ||
} from "@delvtech/evm-client"; | ||
import { Abi } from "abitype"; | ||
|
||
export interface ContractFactoryOptions<TAbi extends Abi = Abi> { | ||
abi: TAbi; | ||
address: `0x${string}`; | ||
cache?: SimpleCache; | ||
namespace?: string; | ||
} | ||
|
||
/** | ||
* A factory function that creates a `CachedReadContract` instance. | ||
*/ | ||
export type ReadContractFactory = <TAbi extends Abi = Abi>( | ||
options: ContractFactoryOptions<TAbi>, | ||
) => CachedReadContract<TAbi>; | ||
|
||
/** | ||
* A factory function that creates a `CachedReadWriteContract` instance. | ||
*/ | ||
export type ReadWriteContractFactory = <TAbi extends Abi = Abi>( | ||
options: ContractFactoryOptions<TAbi>, | ||
) => CachedReadWriteContract<TAbi>; |
85 changes: 85 additions & 0 deletions
85
packages/hyperdrive-js-core/src/evm-client/syncCacheWithTransaction.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<TAbi extends Abi>(options?: { | ||
cacheEntries?: { | ||
functionName?: FunctionName<TAbi>; | ||
args?: FunctionArgs<TAbi, FunctionName<TAbi>>; | ||
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; | ||
}; | ||
}; | ||
} |
13 changes: 13 additions & 0 deletions
13
packages/hyperdrive-js-core/src/evm-client/utils/getBlockFromReadOptions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
19 changes: 19 additions & 0 deletions
19
packages/hyperdrive-js-core/src/evm-client/utils/getBlockOrThrow.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { Block, Network, NetworkGetBlockOptions } from "@delvtech/evm-client"; | ||
import { BlockNotFoundError } from "src/errors/BlockNotFoundError"; | ||
|
||
/** | ||
* 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 | ||
* blocks that may not exist. | ||
* @throws `BlockNotFoundError` | ||
*/ | ||
export async function getBlockOrThrow( | ||
network: Network, | ||
options?: NetworkGetBlockOptions, | ||
): Promise<Block> { | ||
const fetched = await network.getBlock(options); | ||
if (!fetched) { | ||
throw new BlockNotFoundError(options); | ||
} | ||
return fetched; | ||
} |
12 changes: 12 additions & 0 deletions
12
packages/hyperdrive-js-core/src/evm-client/utils/isReadWriteContract.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<any> | CachedReadWriteContract<any>, | ||
): contract is CachedReadWriteContract { | ||
return "write" in contract; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export type { | ||
ContractFactoryOptions, | ||
ReadContractFactory, | ||
ReadWriteContractFactory, | ||
} from "src/evm-client/contractFactory"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { BlockNotFoundError } from "src/errors/BlockNotFoundError"; | ||
export { HyperdriveSdkError } from "src/errors/HyperdriveSdkError"; | ||
export { MethodNotImplementedError } from "src/errors/MethodNotImplementedError"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from "./model"; | ||
export * from "./rest"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export { ReadFactory, type ReadFactoryOptions } from "src/factory/ReadFactory"; | ||
export { | ||
ReadWriteFactory, | ||
type ReadWriteFactoryOptions, | ||
} from "src/factory/ReadWriteFactory"; |
Oops, something went wrong.