@xyo-network/evm-call-witness 4.1.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,187 @@
1
+ /* eslint-disable max-statements */
2
+
3
+ import '@xylabs/vitest-extended'
4
+
5
+ import { hexFrom } from '@xylabs/hex'
6
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
7
+ import type { PackageManifestPayload } from '@xyo-network/manifest'
8
+ import { ManifestWrapper } from '@xyo-network/manifest'
9
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
10
+ import { ModuleFactory } from '@xyo-network/module-model'
11
+ import {
12
+ ERC721__factory, ERC721Enumerable__factory, ERC1155__factory,
13
+ } from '@xyo-network/open-zeppelin-typechain'
14
+ import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
15
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
16
+ import { HDWallet } from '@xyo-network/wallet'
17
+ import { getProvidersFromEnv } from '@xyo-network/witness-evm-abstract'
18
+ import { asWitnessInstance } from '@xyo-network/witness-model'
19
+ import { Semaphore } from 'async-mutex'
20
+ import {
21
+ afterAll,
22
+ describe, expect,
23
+ it,
24
+ } from 'vitest'
25
+
26
+ import type { EvmCallResults } from '../../../../Diviner.ts'
27
+ import { EvmCallDiviner, EvmCallResultsSchema } from '../../../../Diviner.ts'
28
+ import type { EvmCallWitnessParams } from '../../../../model.ts'
29
+ import type { EvmCall, EvmCallResult } from '../../../../Payload.ts'
30
+ import { EvmCallResultSchema, EvmCallSchema } from '../../../../Payload.ts'
31
+ import { EvmCallWitness } from '../../../../Witness.ts'
32
+ import erc721SentinelManifest from '../Erc721Sentinel.json' with { type: 'json' }
33
+
34
+ const profileData: Record<string, number[]> = {}
35
+
36
+ const profile = (name: string) => {
37
+ const timeData = profileData[name] ?? []
38
+ timeData.push(Date.now())
39
+ profileData[name] = timeData
40
+ }
41
+
42
+ const profileReport = () => {
43
+ let lowest = Date.now()
44
+ let highest = 0
45
+ // eslint-disable-next-line unicorn/no-array-reduce
46
+ const results = Object.entries(profileData).reduce<Record<string, number>>((prev, [name, readings]) => {
47
+ const start = readings.at(0)
48
+ if (start) {
49
+ if (start < lowest) {
50
+ lowest = start
51
+ }
52
+ const end = readings.at(-1) ?? Date.now()
53
+ if (end > highest) {
54
+ highest = end
55
+ }
56
+ prev[name] = end - start
57
+ }
58
+ return prev
59
+ }, {})
60
+ if (highest) {
61
+ results['-all-'] = highest - lowest
62
+ }
63
+ return results
64
+ }
65
+
66
+ let tokenCount = 0
67
+
68
+ describe.skip('Erc721Sentinel', () => {
69
+ // const address = '0x562fC2927c77cB975680088566ADa1dC6cB8b5Ea' //Random ERC721
70
+ const address = '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' // Bored Apes
71
+
72
+ describe('report', () => {
73
+ it('specifying address', async () => {
74
+ profile('setup')
75
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
76
+ const wallet = await HDWallet.fromPhrase(mnemonic)
77
+ const locator = new ModuleFactoryLocator()
78
+ locator.register(EvmCallDiviner.factory())
79
+
80
+ locator.register(
81
+ new ModuleFactory(EvmCallWitness, {
82
+ config: { abi: ERC721__factory.abi },
83
+ providers: getProvidersFromEnv,
84
+ } as EvmCallWitnessParams),
85
+ { 'network.xyo.evm.interface': 'Erc721' },
86
+ )
87
+
88
+ locator.register(
89
+ new ModuleFactory(EvmCallWitness, {
90
+ config: { abi: ERC721Enumerable__factory.abi },
91
+ providers: getProvidersFromEnv,
92
+ } as EvmCallWitnessParams),
93
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
94
+ )
95
+
96
+ locator.register(
97
+ new ModuleFactory(EvmCallWitness, {
98
+ config: { abi: ERC1155__factory.abi },
99
+ providers: getProvidersFromEnv,
100
+ } as EvmCallWitnessParams),
101
+ { 'network.xyo.evm.interface': 'Erc1155' },
102
+ )
103
+ profile('setup')
104
+ profile('manifest')
105
+ const manifest = new ManifestWrapper(erc721SentinelManifest as PackageManifestPayload, wallet, locator)
106
+ profile('manifest-load')
107
+ const node = await manifest.loadNodeFromIndex(0)
108
+ profile('manifest-load')
109
+ profile('manifest-resolve')
110
+ const mods = await node.resolve('*')
111
+ profile('manifest-resolve')
112
+ profile('manifest')
113
+ expect(mods.length).toBeGreaterThan(5)
114
+
115
+ const collectionSentinel = asSentinelInstance(await node.resolve('NftInfoSentinel'))
116
+ expect(collectionSentinel).toBeDefined()
117
+
118
+ const tokenSentinel = asSentinelInstance(await node.resolve('NftTokenInfoSentinel'))
119
+ expect(tokenSentinel).toBeDefined()
120
+
121
+ const nameWitness = asWitnessInstance(await node.resolve('Erc721NameWitness'))
122
+ expect(nameWitness).toBeDefined()
123
+
124
+ const symbolWitness = asWitnessInstance(await node.resolve('Erc721SymbolWitness'))
125
+ expect(symbolWitness).toBeDefined()
126
+
127
+ const diviner = asDivinerInstance(await node.resolve('Erc721ContractInfoDiviner'))
128
+ expect(diviner).toBeDefined()
129
+
130
+ const collectionCallPayload: EvmCall = { address, schema: EvmCallSchema }
131
+ profile('collectionReport')
132
+ const report = await collectionSentinel?.report([collectionCallPayload])
133
+ profile('collectionReport')
134
+ profile('tokenCallSetup')
135
+ const info = report?.find(isPayloadOfSchemaType<EvmCallResults>(EvmCallResultsSchema))
136
+
137
+ const totalSupply = info?.results?.totalSupply ? BigInt(hexFrom(info.results.totalSupply.result as string, { prefix: true })) : 0n
138
+ expect(totalSupply).toBeGreaterThan(0n)
139
+
140
+ const chunkSize = 100n
141
+ const maxChunks = totalSupply / chunkSize
142
+ const chunks: EvmCall[][] = []
143
+
144
+ let offset = 0n
145
+ while (offset < totalSupply && chunks.length < maxChunks) {
146
+ offset = BigInt(chunks.length) * chunkSize
147
+
148
+ const chunkList: EvmCall[] = []
149
+
150
+ for (let i = offset; i < offset + chunkSize && i < totalSupply; i++) {
151
+ const call: EvmCall = {
152
+ address,
153
+ args: [`0x${BigInt(i).toString(16)}`],
154
+ functionName: 'tokenByIndex',
155
+ schema: EvmCallSchema,
156
+ }
157
+ chunkList.push(call)
158
+ }
159
+ chunks.push(chunkList)
160
+ }
161
+ profile('tokenCallSetup')
162
+ const maxConcurrent = 8
163
+ if (tokenSentinel) {
164
+ profile('tokenReport')
165
+ const semaphore = new Semaphore(maxConcurrent)
166
+ const tokenReportArrays = await Promise.all(
167
+ chunks.map(async (chunk) => {
168
+ return await semaphore.runExclusive(async () => {
169
+ const result = await tokenSentinel.report(chunk)
170
+ return result
171
+ })
172
+ }),
173
+ )
174
+ profile('tokenReport')
175
+ const tokenReport = tokenReportArrays.flat()
176
+ tokenCount = tokenReport.length
177
+ const tokenInfoPayloads = tokenReport.filter(isPayloadOfSchemaType<EvmCallResult>(EvmCallResultSchema))
178
+ expect(BigInt(tokenInfoPayloads.length)).toBe(totalSupply)
179
+ }
180
+ })
181
+ afterAll(() => {
182
+ const profileData = profileReport()
183
+ if (profileData['tokenReport']) console.log(`Timer: ${profileData['tokenReport'] / tokenCount}ms`)
184
+ console.log(`Profile: ${JSON.stringify(profileData, null, 2)}`)
185
+ })
186
+ })
187
+ })
@@ -0,0 +1,101 @@
1
+ import '@xylabs/vitest-extended'
2
+
3
+ import { delay } from '@xylabs/delay'
4
+ import { MemoryBoundWitnessDiviner } from '@xyo-network/diviner-boundwitness-memory'
5
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
6
+ import { GenericPayloadDiviner } from '@xyo-network/diviner-payload-generic'
7
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
8
+ import {
9
+ TemporalIndexingDiviner,
10
+ TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner,
11
+ TemporalIndexingDivinerIndexCandidateToIndexDiviner,
12
+ TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner,
13
+ TemporalIndexingDivinerStateToIndexCandidateDiviner,
14
+ } from '@xyo-network/diviner-temporal-indexing'
15
+ import type { PackageManifestPayload } from '@xyo-network/manifest'
16
+ import { ManifestWrapper } from '@xyo-network/manifest'
17
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
18
+ import { ModuleFactory } from '@xyo-network/module-model'
19
+ import type { MemoryNode } from '@xyo-network/node-memory'
20
+ import { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'
21
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
22
+ import { HDWallet } from '@xyo-network/wallet'
23
+ import type { WalletInstance } from '@xyo-network/wallet-model'
24
+ import { getProvidersFromEnv } from '@xyo-network/witness-evm-abstract'
25
+ import { TimestampWitness } from '@xyo-network/witness-timestamp'
26
+ import {
27
+ beforeAll, describe, expect,
28
+ it,
29
+ } from 'vitest'
30
+
31
+ import { EvmCallDiviner } from '../../../Diviner.ts'
32
+ import type { EvmCallWitnessParams } from '../../../model.ts'
33
+ import {
34
+ EvmCallSchema, isEvmCallResult, isEvmCallSuccess,
35
+ } from '../../../Payload.ts'
36
+ import { EvmCallWitness } from '../../../Witness.ts'
37
+ import erc721TotalSupplyIndexManifest from './Erc721.TotalSupply.Index.json' with { type: 'json' }
38
+
39
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Erc721.TotalSupply.Index', () => {
40
+ let wallet: WalletInstance
41
+ let node: MemoryNode
42
+
43
+ beforeAll(async () => {
44
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
45
+ wallet = await HDWallet.fromPhrase(mnemonic)
46
+ const locator = new ModuleFactoryLocator()
47
+ locator.register(MemoryBoundWitnessDiviner.factory())
48
+ locator.register(GenericPayloadDiviner.factory())
49
+ locator.register(TimestampWitness.factory())
50
+ locator.register(EvmCallDiviner.factory())
51
+ locator.register(TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner.factory())
52
+ locator.register(TemporalIndexingDivinerIndexCandidateToIndexDiviner.factory())
53
+ locator.register(TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner.factory())
54
+ locator.register(TemporalIndexingDivinerStateToIndexCandidateDiviner.factory())
55
+ locator.register(TemporalIndexingDiviner.factory())
56
+
57
+ locator.register(
58
+ new ModuleFactory(EvmCallWitness, {
59
+ config: { abi: ERC721Enumerable__factory.abi },
60
+ providers: getProvidersFromEnv,
61
+ } as EvmCallWitnessParams),
62
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
63
+ )
64
+ const manifest = new ManifestWrapper(erc721TotalSupplyIndexManifest as PackageManifestPayload, wallet, locator)
65
+ node = await manifest.loadNodeFromIndex(0)
66
+ })
67
+ type TestData = readonly [string]
68
+ const cases: readonly TestData[] = [
69
+ ['0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'], // BAYC
70
+ ] as const
71
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Sentinel', () => {
72
+ describe('Sentinel', () => {
73
+ it.each(cases)('returns totalSupply', async (address) => {
74
+ const sentinel = asSentinelInstance(await node.resolve('Sentinel'))
75
+ const input = {
76
+ address, chainId: 1, schema: EvmCallSchema,
77
+ }
78
+ const observations = await sentinel?.report([input])
79
+ expect(observations?.length).toBe(3)
80
+ const totalSupply = observations?.filter(isEvmCallResult).find(isEvmCallSuccess)
81
+ expect(totalSupply).toBeDefined()
82
+ expect(totalSupply?.result).toBeString()
83
+ const totalSupplyValue = totalSupply?.result as string
84
+ expect(Number.parseInt(totalSupplyValue)).toBeNumber()
85
+ })
86
+ })
87
+ describe.skip('Index', () => {
88
+ it.each(cases)('returns indexed result', async (address) => {
89
+ await delay(100)
90
+ const diviner = asDivinerInstance(await node.resolve('IndexDiviner'))
91
+ expect(diviner).toBeDefined()
92
+ const query = {
93
+ address, chainId: 1, schema: PayloadDivinerQuerySchema,
94
+ }
95
+ const result = await diviner?.divine([query])
96
+ expect(result).toBeDefined()
97
+ expect(result).toBeArrayOfSize(1)
98
+ })
99
+ })
100
+ })
101
+ })
@@ -0,0 +1,118 @@
1
+ import '@xylabs/vitest-extended'
2
+
3
+ import { delay } from '@xylabs/delay'
4
+ import { MemoryBoundWitnessDiviner } from '@xyo-network/diviner-boundwitness-memory'
5
+ import { JsonPatchDiviner } from '@xyo-network/diviner-jsonpatch'
6
+ import { JsonPathAggregateDiviner } from '@xyo-network/diviner-jsonpath-aggregate-memory'
7
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
8
+ import { GenericPayloadDiviner } from '@xyo-network/diviner-payload-generic'
9
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
10
+ import { RangeDiviner } from '@xyo-network/diviner-range'
11
+ import {
12
+ TemporalIndexingDiviner,
13
+ TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner,
14
+ TemporalIndexingDivinerIndexCandidateToIndexDiviner,
15
+ TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner,
16
+ TemporalIndexingDivinerStateToIndexCandidateDiviner,
17
+ } from '@xyo-network/diviner-temporal-indexing'
18
+ import { isNftId } from '@xyo-network/evm-nft-id-payload-plugin'
19
+ import type { PackageManifestPayload } from '@xyo-network/manifest'
20
+ import { ManifestWrapper } from '@xyo-network/manifest'
21
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
22
+ import { ModuleFactory } from '@xyo-network/module-model'
23
+ import type { MemoryNode } from '@xyo-network/node-memory'
24
+ import { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'
25
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
26
+ import { HDWallet } from '@xyo-network/wallet'
27
+ import type { WalletInstance } from '@xyo-network/wallet-model'
28
+ import { getProvidersFromEnv } from '@xyo-network/witness-evm-abstract'
29
+ import { TimestampWitness } from '@xyo-network/witness-timestamp'
30
+ import {
31
+ beforeAll, describe, expect,
32
+ it,
33
+ } from 'vitest'
34
+
35
+ import { EvmCallDiviner } from '../../../Diviner.ts'
36
+ import type { EvmCallWitnessParams } from '../../../model.ts'
37
+ import { EvmCallSchema } from '../../../Payload.ts'
38
+ import { EvmCallWitness } from '../../../Witness.ts'
39
+ import nodeManifest from './Erc721.NftId.Index.json' with { type: 'json' }
40
+
41
+ describe.skipIf(!process.env.INFURA_PROJECT_ID).skip('Erc721.NftId.Index', () => {
42
+ let wallet: WalletInstance
43
+ let node: MemoryNode
44
+
45
+ beforeAll(async () => {
46
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
47
+ wallet = await HDWallet.fromPhrase(mnemonic)
48
+ const locator = new ModuleFactoryLocator()
49
+ locator.register(MemoryBoundWitnessDiviner.factory())
50
+ locator.register(GenericPayloadDiviner.factory())
51
+ locator.register(TimestampWitness.factory())
52
+ locator.register(EvmCallDiviner.factory())
53
+ locator.register(TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner.factory())
54
+ locator.register(TemporalIndexingDivinerIndexCandidateToIndexDiviner.factory())
55
+ locator.register(TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner.factory())
56
+ locator.register(TemporalIndexingDivinerStateToIndexCandidateDiviner.factory())
57
+ locator.register(TemporalIndexingDiviner.factory())
58
+ locator.register(JsonPatchDiviner.factory())
59
+ locator.register(JsonPathAggregateDiviner.factory())
60
+ locator.register(RangeDiviner.factory())
61
+
62
+ locator.register(
63
+ new ModuleFactory(EvmCallWitness, {
64
+ config: { abi: ERC721Enumerable__factory.abi },
65
+ providers: getProvidersFromEnv,
66
+ } as EvmCallWitnessParams),
67
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
68
+ )
69
+ const manifest = new ManifestWrapper(nodeManifest as PackageManifestPayload, wallet, locator)
70
+ node = await manifest.loadNodeFromIndex(0)
71
+ })
72
+ type TestData = readonly [string]
73
+ const cases: readonly TestData[] = [
74
+ ['0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'], // BAYC
75
+ ] as const
76
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Sentinel', () => {
77
+ const tokensToCheck = 16
78
+ const tokenIds = Array.from({ length: tokensToCheck }).map((_, tokenIndex) => tokenIndex)
79
+ const tokenIndexes = tokenIds.map(tokenId => tokenId)
80
+ const chainId = 1
81
+ const functionName = 'tokenByIndex'
82
+ describe('Sentinel', () => {
83
+ it.each(cases)('returns NftIndexes', async (address) => {
84
+ const sentinel = asSentinelInstance(await node.resolve('Sentinel'))
85
+ for (const tokenIndex of tokenIndexes) {
86
+ const inputs = [{
87
+ address, args: [`0x${BigInt(tokenIndex).toString(16)}`], chainId, functionName, schema: EvmCallSchema,
88
+ }]
89
+ const observations = await sentinel?.report(inputs)
90
+ const nftIds = observations?.filter(isNftId)
91
+ expect(nftIds?.length).toBe(1)
92
+ for (const nftId of nftIds ?? []) {
93
+ expect(nftId.address).toBe(address)
94
+ expect(nftId.chainId).toBe(chainId)
95
+ expect(nftId.tokenId).toBeString()
96
+ expect(tokenIds).toContain(Number(BigInt(nftId.tokenId)))
97
+ }
98
+ }
99
+ })
100
+ })
101
+ describe('Index', () => {
102
+ it.each(cases)('returns indexed NftIndex results', async (address) => {
103
+ await delay(100)
104
+ const diviner = asDivinerInstance(await node.resolve('IndexDiviner'))
105
+ expect(diviner).toBeDefined()
106
+ for (const tokenIndex of tokenIndexes) {
107
+ const tokenId = `0x${BigInt(tokenIndex).toString(16)}`
108
+ const query = {
109
+ address, chainId, length: 1, schema: PayloadDivinerQuerySchema, tokenId,
110
+ }
111
+ const result = await diviner?.divine([query])
112
+ expect(result).toBeDefined()
113
+ expect(result).toBeArrayOfSize(1)
114
+ }
115
+ })
116
+ })
117
+ })
118
+ })
@@ -0,0 +1,124 @@
1
+ import '@xylabs/vitest-extended'
2
+
3
+ import { MemoryBoundWitnessDiviner } from '@xyo-network/diviner-boundwitness-memory'
4
+ import { JsonPatchDiviner } from '@xyo-network/diviner-jsonpatch'
5
+ import { JsonPathAggregateDiviner } from '@xyo-network/diviner-jsonpath-aggregate-memory'
6
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
7
+ import { GenericPayloadDiviner } from '@xyo-network/diviner-payload-generic'
8
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
9
+ import { RangeDiviner } from '@xyo-network/diviner-range'
10
+ import {
11
+ TemporalIndexingDiviner,
12
+ TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner,
13
+ TemporalIndexingDivinerIndexCandidateToIndexDiviner,
14
+ TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner,
15
+ TemporalIndexingDivinerStateToIndexCandidateDiviner,
16
+ } from '@xyo-network/diviner-temporal-indexing'
17
+ import { isNftIndex } from '@xyo-network/evm-nft-id-payload-plugin'
18
+ import type { PackageManifestPayload } from '@xyo-network/manifest'
19
+ import { ManifestWrapper } from '@xyo-network/manifest'
20
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
21
+ import { ModuleFactory } from '@xyo-network/module-model'
22
+ import type { MemoryNode } from '@xyo-network/node-memory'
23
+ import { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'
24
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
25
+ import { HDWallet } from '@xyo-network/wallet'
26
+ import type { WalletInstance } from '@xyo-network/wallet-model'
27
+ import { getProvidersFromEnv } from '@xyo-network/witness-evm-abstract'
28
+ import { TimestampWitness } from '@xyo-network/witness-timestamp'
29
+ import {
30
+ beforeAll, describe, expect,
31
+ it,
32
+ } from 'vitest'
33
+
34
+ import { EvmCallDiviner } from '../../../Diviner.ts'
35
+ import type { EvmCallWitnessParams } from '../../../model.ts'
36
+ import type { EvmCallResult } from '../../../Payload.ts'
37
+ import { EvmCallWitness } from '../../../Witness.ts'
38
+ import nodeManifest from './Erc721.NftIndex.Index.json' with { type: 'json' }
39
+
40
+ describe.runIf(process.env.INFURA_PROJECT_ID).skip('Erc721.NftIndex.Index', () => {
41
+ let wallet: WalletInstance
42
+ let node: MemoryNode
43
+
44
+ beforeAll(async () => {
45
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
46
+ wallet = await HDWallet.fromPhrase(mnemonic)
47
+ const locator = new ModuleFactoryLocator()
48
+ locator.register(MemoryBoundWitnessDiviner.factory())
49
+ locator.register(GenericPayloadDiviner.factory())
50
+ locator.register(TimestampWitness.factory())
51
+ locator.register(EvmCallDiviner.factory())
52
+ locator.register(TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner.factory())
53
+ locator.register(TemporalIndexingDivinerIndexCandidateToIndexDiviner.factory())
54
+ locator.register(TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner.factory())
55
+ locator.register(TemporalIndexingDivinerStateToIndexCandidateDiviner.factory())
56
+ locator.register(TemporalIndexingDiviner.factory())
57
+ locator.register(JsonPatchDiviner.factory())
58
+ locator.register(JsonPathAggregateDiviner.factory())
59
+ locator.register(RangeDiviner.factory())
60
+
61
+ locator.register(
62
+ new ModuleFactory(EvmCallWitness, {
63
+ config: { abi: ERC721Enumerable__factory.abi },
64
+ providers: getProvidersFromEnv,
65
+ } as EvmCallWitnessParams),
66
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
67
+ )
68
+ const manifest = new ManifestWrapper(nodeManifest as PackageManifestPayload, wallet, locator)
69
+ node = await manifest.loadNodeFromIndex(0)
70
+ })
71
+ type TestData = readonly [string]
72
+ const cases: readonly TestData[] = [
73
+ ['0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'], // BAYC
74
+ ] as const
75
+ describe('Sentinel', () => {
76
+ const totalSupply = 100
77
+ describe('Sentinel', () => {
78
+ it.each(cases)('returns NftIndexes', async (address) => {
79
+ const sentinel = asSentinelInstance(await node.resolve('Sentinel'))
80
+ const chainId = 1
81
+ const input: EvmCallResult = {
82
+ address,
83
+ args: [],
84
+ chainId,
85
+ functionName: 'totalSupply',
86
+ result: `${totalSupply}`,
87
+ schema: 'network.xyo.evm.call.result',
88
+ }
89
+
90
+ const observations = (await sentinel?.report([input])) ?? []
91
+ const nftIndexes = observations?.filter(isNftIndex)
92
+ expect(nftIndexes?.length).toBe(totalSupply)
93
+ for (const nftIndex of nftIndexes ?? []) {
94
+ expect(nftIndex.address).toBe(address)
95
+ expect(nftIndex.chainId).toBe(chainId)
96
+ expect(nftIndex.index).toBeNumber()
97
+ }
98
+ })
99
+ })
100
+ describe('Index', () => {
101
+ beforeAll(async () => {
102
+ const delay = (ms: number) => {
103
+ return new Promise(resolve => setTimeout(resolve, ms))
104
+ }
105
+ // Delay enough time for the diviners to index the results
106
+ await delay(4000)
107
+ })
108
+ it.each(cases)('returns indexed NftIndex results', async (address) => {
109
+ const diviner = asDivinerInstance(await node.resolve('IndexDiviner'))
110
+ expect(diviner).toBeDefined()
111
+ // Check we've indexed the results by sampling the first and last index
112
+ const sampleIndexes = [0, totalSupply - 1]
113
+ for (const index of sampleIndexes) {
114
+ const query = {
115
+ address, chainId: 1, index, schema: PayloadDivinerQuerySchema,
116
+ }
117
+ const result = await diviner?.divine([query])
118
+ expect(result).toBeDefined()
119
+ expect(result).toBeArrayOfSize(1)
120
+ }
121
+ })
122
+ })
123
+ })
124
+ })
package/typedoc.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "$schema": "https://typedoc.org/schema.json",
3
- "entryPoints": ["./src/index.ts"],
4
- "tsconfig": "./tsconfig.typedoc.json"
5
- }
package/xy.config.ts DELETED
@@ -1,10 +0,0 @@
1
- import type { XyTsupConfig } from '@xylabs/ts-scripts-yarn3'
2
- const config: XyTsupConfig = {
3
- compile: {
4
- browser: {},
5
- node: {},
6
- neutral: { src: true },
7
- },
8
- }
9
-
10
- export default config