-
Notifications
You must be signed in to change notification settings - Fork 476
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
event listening for react & lots of fixes
- Loading branch information
Showing
25 changed files
with
381 additions
and
190 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
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,54 @@ | ||
import type { Abi, AbiEvent } from "abitype"; | ||
import type { BlockTag } from "viem"; | ||
import { eth_getLogs, getRpcClient } from "../../rpc/index.js"; | ||
import { resolveAbi } from "./resolve-abi.js"; | ||
import type { ContractEvent } from "../event.js"; | ||
import { | ||
resolveContractAbi, | ||
type ThirdwebContract, | ||
} from "../../contract/index.js"; | ||
|
||
type GetContractEventsOptions< | ||
abi extends Abi, | ||
abiEvent extends AbiEvent, | ||
contractEvent extends ContractEvent<abiEvent>, | ||
fBlock extends bigint | BlockTag, | ||
tBlock extends bigint | BlockTag, | ||
> = { | ||
contract: ThirdwebContract<abi>; | ||
events?: contractEvent[]; | ||
fromBlock?: fBlock; | ||
toBlock?: tBlock; | ||
}; | ||
|
||
export async function getContractEvents< | ||
const abi extends Abi, | ||
const abiEvent extends AbiEvent, | ||
const contractEvent extends ContractEvent<abiEvent>, | ||
const fBlock extends bigint | BlockTag, | ||
const tBlock extends bigint | BlockTag, | ||
>( | ||
options: GetContractEventsOptions< | ||
abi, | ||
abiEvent, | ||
contractEvent, | ||
fBlock, | ||
tBlock | ||
>, | ||
) { | ||
const rpcRequest = getRpcClient(options.contract); | ||
const parsedEvents = await (options.events | ||
? Promise.all(options.events.map((e) => resolveAbi(e))) | ||
: // if we don't have events passed then resolve the abi for the contract -> all events! | ||
(resolveContractAbi(options.contract).then((abi) => | ||
abi.filter((item) => item.type === "event"), | ||
) as Promise<AbiEvent[]>)); | ||
|
||
// @ts-expect-error - fromBlock and toBlock ARE allowed to be undefined | ||
return await eth_getLogs(rpcRequest, { | ||
fromBlock: options.fromBlock, | ||
toBlock: options.toBlock, | ||
address: options.contract.address, | ||
events: parsedEvents, | ||
}); | ||
} |
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,71 @@ | ||
import { parseAbiItem, type Abi, type AbiEvent } from "abitype"; | ||
import { | ||
isAbiEvent, | ||
type ContractEvent, | ||
type ContractEventInput, | ||
} from "../event.js"; | ||
import type { ParseEvent } from "../../abi/types.js"; | ||
|
||
const ABI_FN_RESOLUTION_CACHE = new WeakMap< | ||
ContractEvent<AbiEvent>, | ||
Promise<AbiEvent> | ||
>(); | ||
|
||
export function resolveAbi<abiEvent extends AbiEvent | string, abi extends Abi>( | ||
contractEvent: ContractEventInput<abi, abiEvent>, | ||
): Promise<ParseEvent<abi, abiEvent>> { | ||
if (ABI_FN_RESOLUTION_CACHE.has(contractEvent as ContractEvent<AbiEvent>)) { | ||
return ABI_FN_RESOLUTION_CACHE.get( | ||
contractEvent as ContractEvent<AbiEvent>, | ||
) as Promise<ParseEvent<abi, abiEvent>>; | ||
} | ||
const prom = (async () => { | ||
if (isAbiEvent(contractEvent.event)) { | ||
return contractEvent.event as ParseEvent<abi, abiEvent>; | ||
} | ||
// if the method starts with the string `event ` we always will want to try to parse it | ||
if (contractEvent.event.startsWith("event ")) { | ||
const abiItem = parseAbiItem(contractEvent.event); | ||
if (abiItem.type === "event") { | ||
return abiItem as ParseEvent<abi, abiEvent>; | ||
} | ||
throw new Error(`"method" passed is not of type "function"`); | ||
} | ||
// check if we have a "abi" on the contract | ||
if (contractEvent.contract.abi && contractEvent.contract.abi?.length > 0) { | ||
// extract the abiEv from it | ||
const abiEv = contractEvent.contract.abi?.find( | ||
(item) => item.type === "event" && item.name === contractEvent.event, | ||
); | ||
// if we were able to find it -> return it | ||
if (isAbiEvent(abiEv)) { | ||
return abiEv as ParseEvent<abi, abiEvent>; | ||
} | ||
} | ||
|
||
// if we get here we need to async resolve the ABI and try to find the method on there | ||
const { resolveContractAbi } = await import( | ||
"../../contract/actions/resolve-abi.js" | ||
); | ||
|
||
const abi = await resolveContractAbi(contractEvent.contract); | ||
// we try to find the abiEv in the abi | ||
const abiEv = abi.find((item) => { | ||
// if the item is not an event we can ignore it | ||
if (item.type !== "event") { | ||
return false; | ||
} | ||
// if the item is a function we can compare the name | ||
return item.name === contractEvent.event; | ||
}) as ParseEvent<abi, abiEvent> | undefined; | ||
|
||
if (!abiEv) { | ||
throw new Error( | ||
`could not find event with name ${contractEvent.event} in abi`, | ||
); | ||
} | ||
return abiEv; | ||
})(); | ||
ABI_FN_RESOLUTION_CACHE.set(contractEvent as ContractEvent<AbiEvent>, prom); | ||
return prom; | ||
} |
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,68 @@ | ||
import type { Abi, AbiEvent } from "abitype"; | ||
import type { GetLogsReturnType } from "viem"; | ||
import { | ||
eth_getLogs, | ||
getRpcClient, | ||
watchBlockNumber, | ||
} from "../../rpc/index.js"; | ||
import { resolveAbi } from "./resolve-abi.js"; | ||
import type { ContractEvent } from "../event.js"; | ||
import { | ||
resolveContractAbi, | ||
type ThirdwebContract, | ||
} from "../../contract/index.js"; | ||
|
||
export type WatchContractEventsOptions< | ||
abi extends Abi, | ||
abiEvent extends AbiEvent, | ||
contractEvent extends ContractEvent<abiEvent>, | ||
> = { | ||
onLogs: ( | ||
logs: GetLogsReturnType<undefined, abiEvent[], undefined, bigint, bigint>, | ||
) => void | undefined; | ||
contract: ThirdwebContract<abi>; | ||
events?: contractEvent[] | undefined; | ||
}; | ||
|
||
export function watchContractEvents< | ||
const abi extends Abi, | ||
const abiEvent extends AbiEvent, | ||
const contractEvent extends ContractEvent<abiEvent>, | ||
>(options: WatchContractEventsOptions<abi, abiEvent, contractEvent>) { | ||
const rpcRequest = getRpcClient(options.contract); | ||
const resolveAbiPromise = options.events | ||
? Promise.all(options.events.map((e) => resolveAbi(e))) | ||
: // if we don't have events passed then resolve the abi for the contract -> all events! | ||
(resolveContractAbi(options.contract).then((abi) => | ||
abi.filter((item) => item.type === "event"), | ||
) as Promise<abiEvent[]>); | ||
|
||
// returning this returns the underlying "unwatch" function | ||
return watchBlockNumber({ | ||
...options.contract, | ||
onNewBlockNumber: async (blockNumber) => { | ||
const parsedEvents = await resolveAbiPromise; | ||
|
||
const logs = (await eth_getLogs(rpcRequest, { | ||
// onNewBlockNumber fires exactly once per block | ||
// => we want to get the logs for the block that just happened | ||
// fromBlock is inclusive | ||
fromBlock: blockNumber, | ||
// toBlock is exclusive | ||
toBlock: blockNumber, | ||
address: options.contract.address, | ||
events: parsedEvents, | ||
})) as GetLogsReturnType< | ||
undefined, | ||
abiEvent[], | ||
undefined, | ||
bigint, | ||
bigint | ||
>; | ||
// if there were any logs associated with our event(s) | ||
if (logs.length) { | ||
options.onLogs(logs); | ||
} | ||
}, | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
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
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
6 changes: 3 additions & 3 deletions
6
...b/src/react/contract-hooks/useEstimate.ts → ...b/src/react/hooks/contract/useEstimate.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
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
6 changes: 3 additions & 3 deletions
6
...rdweb/src/react/contract-hooks/useSend.ts → ...rdweb/src/react/hooks/contract/useSend.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
4 changes: 2 additions & 2 deletions
4
...react/contract-hooks/useWaitForReceipt.ts → ...react/hooks/contract/useWaitForReceipt.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
Oops, something went wrong.