Skip to content

Commit

Permalink
Moved Contract/Call Witnesses to network.xyo.evm name space
Browse files Browse the repository at this point in the history
  • Loading branch information
arietrouw committed Dec 12, 2023
1 parent a766b8a commit 0260954
Show file tree
Hide file tree
Showing 22 changed files with 192 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { AxiosJson } from '@xylabs/axios'
import { exists } from '@xylabs/exists'
import { isHexZero } from '@xylabs/hex'
import { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'
import { getErc1822Status } from '@xyo-network/erc1822-witness'
import { getErc1967Status } from '@xyo-network/erc1967-witness'
import { getErc1822SlotStatus } from '@xyo-network/erc1822-witness'
import { getErc1967SlotStatus } from '@xyo-network/erc1967-witness'
import { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'
import { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'
import { Provider } from 'ethers'
Expand Down Expand Up @@ -38,10 +38,10 @@ export const getNftCollectionNfts = async (
const block = await provider.getBlockNumber()

//Check if ERC-1967 Upgradeable
const erc1967Status = await getErc1967Status(provider, contractAddress, block)
const erc1967Status = await getErc1967SlotStatus(provider, contractAddress, block)

//Check if ERC-1822 Upgradeable
const erc1822Status = await getErc1822Status(provider, contractAddress, block)
const erc1822Status = await getErc1822SlotStatus(provider, contractAddress, block)

const implementation =
!erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isHexZero } from '@xylabs/hex'
import { NftInfoFields, TokenType } from '@xyo-network/crypto-nft-payload-plugin'
import { getErc1822Status } from '@xyo-network/erc1822-witness'
import { getErc1967Status } from '@xyo-network/erc1967-witness'
import { getErc1822SlotStatus } from '@xyo-network/erc1822-witness'
import { getErc1967SlotStatus } from '@xyo-network/erc1967-witness'
import { ERC721__factory, ERC1155__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'
import { Provider } from 'ethers'
import { LRUCache } from 'lru-cache'
Expand Down Expand Up @@ -118,10 +118,10 @@ export const getNftsOwnedByAddress = async (
// Check if Upgradeable
const [erc1967Status, erc1822Status] = await Promise.all([
// Check if ERC-1967 Upgradeable
await getErc1967Status(provider, contract, block),
await getErc1967SlotStatus(provider, contract, block),

// Check if ERC-1822 Upgradeable
await getErc1822Status(provider, contract, block),
await getErc1822SlotStatus(provider, contract, block),
])

const implementation =
Expand Down
52 changes: 23 additions & 29 deletions packages/payloadset/packages/evm/packages/call/src/Diviner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import { AbstractDiviner } from '@xyo-network/abstract-diviner'
import { DivinerConfig, DivinerParams } from '@xyo-network/diviner-model'
import { isPayloadOfSchemaType, Payload } from '@xyo-network/payload-model'

import { asBlockchainContractCallSuccess, BlockchainContractCallResult, BlockchainContractCallResultSchema } from './Payload'
import { asEvmCallSuccess, EvmCallResult, EvmCallResultSchema } from './Payload'

export type FindCallResult<TResult = string, TPayload = Payload> = [TResult, TPayload] | [undefined, TPayload] | [undefined, undefined]

export const BlockchainContractCallDivinerConfigSchema = 'network.xyo.blockchain.contract.call.diviner.config'
export type BlockchainContractCallDivinerConfigSchema = typeof BlockchainContractCallDivinerConfigSchema
export const EvmCallDivinerConfigSchema = 'network.xyo.evm.call.diviner.config'
export type EvmCallDivinerConfigSchema = typeof EvmCallDivinerConfigSchema

export type BlockchainContractCallDivinerConfig = DivinerConfig<{
schema: BlockchainContractCallDivinerConfigSchema
export type EvmCallDivinerConfig = DivinerConfig<{
schema: EvmCallDivinerConfigSchema
}>
export type BlockchainContractCallDivinerParams = DivinerParams<BlockchainContractCallDivinerConfig>
export type EvmCallDivinerParams = DivinerParams<EvmCallDivinerConfig>

export const BlockchainContractCallResultsSchema = 'network.xyo.blockchain.contract.call.results'
export type BlockchainContractCallResultsSchema = typeof BlockchainContractCallResultsSchema
export const EvmCallResultsSchema = 'network.xyo.evm.call.results'
export type EvmCallResultsSchema = typeof EvmCallResultsSchema

export type BlockchainContractCallResults = Payload<
export type EvmCallResults = Payload<
{
address: string
chainId: string
Expand All @@ -31,21 +31,15 @@ export type BlockchainContractCallResults = Payload<
}
>
},
BlockchainContractCallResultsSchema
EvmCallResultsSchema
>

export class BlockchainContractCallDiviner<
TParams extends BlockchainContractCallDivinerParams = BlockchainContractCallDivinerParams,
> extends AbstractDiviner<TParams> {
static override configSchemas = [BlockchainContractCallDivinerConfigSchema]
export class EvmCallDiviner<TParams extends EvmCallDivinerParams = EvmCallDivinerParams> extends AbstractDiviner<TParams> {
static override configSchemas = [EvmCallDivinerConfigSchema]

protected static findCallResult<TResult = string>(
address: string,
functionName: string,
payloads: BlockchainContractCallResult[],
): TResult | undefined {
protected static findCallResult<TResult = string>(address: string, functionName: string, payloads: EvmCallResult[]): TResult | undefined {
const foundPayload = payloads.find((payload) => payload.functionName === functionName && payload.address === address)
return asBlockchainContractCallSuccess(foundPayload)?.result as TResult | undefined
return asEvmCallSuccess(foundPayload)?.result as TResult | undefined
}

protected static matchingExistingField<R = string, T extends Payload = Payload>(objs: T[], field: keyof T): R | undefined {
Expand All @@ -56,16 +50,16 @@ export class BlockchainContractCallDiviner<
return didNotMatch ? undefined : expectedValue
}

protected contractInfoRequiredFields(callResults: BlockchainContractCallResult[]): BlockchainContractCallResults {
protected contractInfoRequiredFields(callResults: EvmCallResult[]): EvmCallResults {
return {
address: assertEx(BlockchainContractCallDiviner.matchingExistingField(callResults, 'address'), 'Mismatched address'),
chainId: assertEx(BlockchainContractCallDiviner.matchingExistingField(callResults, 'chainId'), 'Mismatched chainId'),
schema: BlockchainContractCallResultsSchema,
address: assertEx(EvmCallDiviner.matchingExistingField(callResults, 'address'), 'Mismatched address'),
chainId: assertEx(EvmCallDiviner.matchingExistingField(callResults, 'chainId'), 'Mismatched chainId'),
schema: EvmCallResultsSchema,
}
}

protected override async divineHandler(inPayloads: BlockchainContractCallResult[] = []): Promise<BlockchainContractCallResults[]> {
const callResults = inPayloads.filter(isPayloadOfSchemaType<BlockchainContractCallResult>(BlockchainContractCallResultSchema))
protected override async divineHandler(inPayloads: EvmCallResult[] = []): Promise<EvmCallResults[]> {
const callResults = inPayloads.filter(isPayloadOfSchemaType<EvmCallResult>(EvmCallResultSchema))
const addresses = Object.keys(
callResults.reduce<Record<string, boolean>>((prev, result) => {
if (result.address) {
Expand All @@ -77,7 +71,7 @@ export class BlockchainContractCallDiviner<
const result = await Promise.all(
addresses.map(async (address) => {
const foundCallResults = callResults.filter((callResult) => callResult.address === address)
const results: BlockchainContractCallResults = {
const results: EvmCallResults = {
...{ results: await this.reduceResults(foundCallResults) },
...this.contractInfoRequiredFields(foundCallResults),
}
Expand All @@ -88,7 +82,7 @@ export class BlockchainContractCallDiviner<
return result
}

protected reduceResults(callResults: BlockchainContractCallResult[]): Promisable<BlockchainContractCallResults['results']> {
protected reduceResults(callResults: EvmCallResult[]): Promisable<EvmCallResults['results']> {
return callResults.reduce<
Record<
string,
Expand All @@ -98,7 +92,7 @@ export class BlockchainContractCallDiviner<
}
>
>((prev, callResult) => {
const typedCallResult = asBlockchainContractCallSuccess(callResult)
const typedCallResult = asEvmCallSuccess(callResult)
if (typedCallResult) {
prev[callResult.functionName] = { args: typedCallResult.args, result: typedCallResult?.result }
}
Expand Down
36 changes: 17 additions & 19 deletions packages/payloadset/packages/evm/packages/call/src/Payload.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { Payload } from '@xyo-network/payload-model'

export const BlockchainContractCallSchema = 'network.xyo.blockchain.contract.call'
export type BlockchainContractCallSchema = typeof BlockchainContractCallSchema
export const EvmCallSchema = 'network.xyo.blockchain.contract.call'
export type EvmCallSchema = typeof EvmCallSchema

export type BlockchainContractCall = Payload<
export type EvmCall = Payload<
{
address?: string
args?: unknown[]
block?: number
functionName?: string
},
BlockchainContractCallSchema
EvmCallSchema
>

export const BlockchainContractCallResultSchema = 'network.xyo.blockchain.contract.call.result'
export type BlockchainContractCallResultSchema = typeof BlockchainContractCallResultSchema
export const EvmCallResultSchema = 'network.xyo.blockchain.contract.call.result'
export type EvmCallResultSchema = typeof EvmCallResultSchema

export type BlockchainContractCallResultBase = Payload<
export type EvmCallResultBase = Payload<
{
address: string
args: unknown[]
Expand All @@ -25,29 +25,27 @@ export type BlockchainContractCallResultBase = Payload<
functionName: string
implementation?: string
},
BlockchainContractCallResultSchema
EvmCallResultSchema
>

export type BlockchainContractCallSuccess = BlockchainContractCallResultBase & {
export type EvmCallSuccess = EvmCallResultBase & {
result: unknown
}

export type BlockchainContractCallFailure = BlockchainContractCallResultBase & {
export type EvmCallFailure = EvmCallResultBase & {
error: string
}

export type BlockchainContractCallResult = BlockchainContractCallSuccess | BlockchainContractCallFailure
export type EvmCallResult = EvmCallSuccess | EvmCallFailure

export const isBlockchainContractCallSuccess = (payload?: BlockchainContractCallResult): payload is BlockchainContractCallSuccess => {
return (payload as BlockchainContractCallSuccess | undefined)?.result !== undefined
export const isEvmCallSuccess = (payload?: EvmCallResult): payload is EvmCallSuccess => {
return (payload as EvmCallSuccess | undefined)?.result !== undefined
}

export const isBlockchainContractCallFailure = (payload?: BlockchainContractCallResult): payload is BlockchainContractCallFailure => {
return (payload as BlockchainContractCallFailure | undefined)?.error !== undefined
export const isEvmCallFailure = (payload?: EvmCallResult): payload is EvmCallFailure => {
return (payload as EvmCallFailure | undefined)?.error !== undefined
}

export const asBlockchainContractCallSuccess = (payload?: BlockchainContractCallResult) =>
isBlockchainContractCallSuccess(payload) ? payload : undefined
export const asEvmCallSuccess = (payload?: EvmCallResult) => (isEvmCallSuccess(payload) ? payload : undefined)

export const asBlockchainContractCallFailure = (payload?: BlockchainContractCallResult) =>
isBlockchainContractCallFailure(payload) ? payload : undefined
export const asEvmCallFailure = (payload?: EvmCallResult) => (isEvmCallFailure(payload) ? payload : undefined)
44 changes: 20 additions & 24 deletions packages/payloadset/packages/evm/packages/call/src/Witness.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,29 @@
import { assertEx } from '@xylabs/assert'
import { getErc1822Status } from '@xyo-network/erc1822-witness'
import { getErc1967Status } from '@xyo-network/erc1967-witness'
import { getErc1822SlotStatus } from '@xyo-network/erc1822-witness'
import { getErc1967SlotStatus } from '@xyo-network/erc1967-witness'
import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
import { AbstractBlockchainWitness, BlockchainWitnessConfig, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'
import { Contract, JsonFragment } from 'ethers'

import {
BlockchainContractCall,
BlockchainContractCallResult,
BlockchainContractCallResultSchema,
BlockchainContractCallSchema,
BlockchainContractCallSuccess,
} from './Payload'
import { EvmCall, EvmCallResult, EvmCallResultSchema, EvmCallSchema, EvmCallSuccess } from './Payload'

export type Abi = string | ReadonlyArray<JsonFragment | string>

export const BlockchainContractCallWitnessConfigSchema = 'network.xyo.blockchain.contract.call.witness.config'
export type BlockchainContractCallWitnessConfigSchema = typeof BlockchainContractCallWitnessConfigSchema
export const EvmCallWitnessConfigSchema = 'network.xyo.evm.call.witness.config'
export type EvmCallWitnessConfigSchema = typeof EvmCallWitnessConfigSchema

export type BlockchainContractCallWitnessConfig = BlockchainWitnessConfig<
export type EvmCallWitnessConfig = BlockchainWitnessConfig<
{
abi?: Abi
address?: string
args?: unknown[]
block?: number
functionName?: string
},
BlockchainContractCallWitnessConfigSchema
EvmCallWitnessConfigSchema
>

export type BlockchainContractCallWitnessParams = BlockchainWitnessParams<BlockchainContractCallWitnessConfig>
export type EvmCallWitnessParams = BlockchainWitnessParams<EvmCallWitnessConfig>

const prefixHex = (value?: string) => {
if (value !== undefined) {
Expand All @@ -43,22 +37,24 @@ const isHexZero = (value?: string) => {
return prefixedValue === undefined ? true : BigInt(prefixedValue) === 0n
}

export class BlockchainContractCallWitness<
TParams extends BlockchainContractCallWitnessParams = BlockchainContractCallWitnessParams,
> extends AbstractBlockchainWitness<TParams, BlockchainContractCall, BlockchainContractCallResult> {
static override configSchemas = [BlockchainContractCallWitnessConfigSchema]
export class EvmCallWitness<TParams extends EvmCallWitnessParams = EvmCallWitnessParams> extends AbstractBlockchainWitness<
TParams,
EvmCall,
EvmCallResult
> {
static override configSchemas = [EvmCallWitnessConfigSchema]

get abi() {
return assertEx(this.config.abi, 'Missing abi')
}

protected override async observeHandler(inPayloads: BlockchainContractCall[] = []): Promise<BlockchainContractCallResult[]> {
protected override async observeHandler(inPayloads: EvmCall[] = []): Promise<EvmCallResult[]> {
await this.started('throw')
//calling it here to make sure we rests the cache
await this.getProviders()
try {
const observations = await Promise.all(
inPayloads.filter(isPayloadOfSchemaType(BlockchainContractCallSchema)).map(async ({ functionName, args, address, block: payloadBlock }) => {
inPayloads.filter(isPayloadOfSchemaType(EvmCallSchema)).map(async ({ functionName, args, address, block: payloadBlock }) => {
const validatedAddress = assertEx(address ?? this.config.address, 'Missing address')
const validatedFunctionName = assertEx(functionName ?? this.config.functionName, 'Missing address')
const mergedArgs = [...(args ?? this.config.args ?? [])]
Expand All @@ -68,10 +64,10 @@ export class BlockchainContractCallWitness<
const block = this.config.block ?? payloadBlock ?? (await provider.getBlockNumber())

//Check if ERC-1967 Upgradeable
const erc1967Status = await getErc1967Status(provider, validatedAddress, block)
const erc1967Status = await getErc1967SlotStatus(provider, validatedAddress, block)

//Check if ERC-1822 Upgradeable
const erc1822Status = await getErc1822Status(provider, validatedAddress, block)
const erc1822Status = await getErc1822SlotStatus(provider, validatedAddress, block)

const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation

Expand All @@ -84,14 +80,14 @@ export class BlockchainContractCallWitness<
//const error = ex as Error & { code: string }
//this.logger.error(`Error [${this.config.name}]: ${error.code} : ${error.message}`)
}
const observation: BlockchainContractCallSuccess = {
const observation: EvmCallSuccess = {
address: validatedAddress,
args: mergedArgs,
block,
chainId: Number((await provider.getNetwork()).chainId),
functionName: validatedFunctionName,
result: transformedResult,
schema: BlockchainContractCallResultSchema,
schema: EvmCallResultSchema,
}
if (implementation !== validatedAddress) {
observation.implementation = implementation
Expand Down
Loading

0 comments on commit 0260954

Please sign in to comment.