@xyo-network/crypto-contract-function-read-plugin 4.2.0 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/crypto-contract-function-read-plugin",
3
- "version": "4.2.0",
3
+ "version": "5.0.0",
4
4
  "description": "Typescript/Javascript Plugins for XYO Platform",
5
5
  "homepage": "https://xyo.network",
6
6
  "bugs": {
@@ -28,45 +28,49 @@
28
28
  },
29
29
  "module": "dist/neutral/index.mjs",
30
30
  "types": "dist/neutral/index.d.ts",
31
+ "files": [
32
+ "dist",
33
+ "src"
34
+ ],
31
35
  "dependencies": {
32
- "@xylabs/assert": "^4.15.1",
33
- "@xylabs/promise": "^4.15.1",
34
- "@xyo-network/abstract-witness": "^4.3.0",
35
- "@xyo-network/crypto-contract-function-read-payload-plugin": "^4.2.0",
36
- "@xyo-network/crypto-nft-payload-plugin": "^4.2.0",
37
- "@xyo-network/diviner-abstract": "^4.3.0",
38
- "@xyo-network/module-model": "^4.3.0",
39
- "@xyo-network/payload-model": "^4.3.0",
40
- "@xyo-network/payloadset-plugin": "^4.3.0",
41
- "@xyo-network/witness-model": "^4.3.0",
36
+ "@xylabs/assert": "^5.0.0",
37
+ "@xylabs/promise": "^5.0.0",
38
+ "@xyo-network/abstract-witness": "^5.0.0",
39
+ "@xyo-network/crypto-contract-function-read-payload-plugin": "^5.0.0",
40
+ "@xyo-network/crypto-nft-payload-plugin": "^5.0.0",
41
+ "@xyo-network/diviner-abstract": "^5.0.0",
42
+ "@xyo-network/module-model": "^5.0.0",
43
+ "@xyo-network/payload-model": "^5.0.0",
44
+ "@xyo-network/payloadset-plugin": "^5.0.0",
45
+ "@xyo-network/witness-model": "^5.0.0",
42
46
  "ethers": "^6.15.0"
43
47
  },
44
48
  "devDependencies": {
45
- "@xylabs/delay": "^4.15.1",
46
- "@xylabs/hex": "^4.15.1",
47
- "@xylabs/object": "^4.15.1",
48
- "@xylabs/ts-scripts-yarn3": "^7.0.1",
49
- "@xylabs/tsconfig": "^7.0.1",
50
- "@xylabs/vitest-extended": "^4.15.1",
51
- "@xyo-network/archivist-memory": "^4.3.0",
52
- "@xyo-network/diviner-boundwitness-memory": "^4.3.0",
53
- "@xyo-network/diviner-jsonpatch": "^4.3.0",
54
- "@xyo-network/diviner-jsonpath-aggregate-memory": "^4.3.0",
55
- "@xyo-network/diviner-model": "^4.3.0",
56
- "@xyo-network/diviner-payload-generic": "^4.3.0",
57
- "@xyo-network/diviner-payload-model": "^4.3.0",
58
- "@xyo-network/diviner-range": "^4.3.0",
59
- "@xyo-network/diviner-temporal-indexing": "^4.3.0",
60
- "@xyo-network/evm-nft-id-payload-plugin": "^4.2.0",
61
- "@xyo-network/manifest": "^4.3.0",
62
- "@xyo-network/module-factory-locator": "^4.3.0",
63
- "@xyo-network/node-memory": "^4.3.0",
49
+ "@xylabs/delay": "^5.0.0",
50
+ "@xylabs/hex": "^5.0.0",
51
+ "@xylabs/object": "^5.0.0",
52
+ "@xylabs/ts-scripts-yarn3": "^7.0.2",
53
+ "@xylabs/tsconfig": "^7.0.2",
54
+ "@xylabs/vitest-extended": "^5.0.0",
55
+ "@xyo-network/archivist-memory": "^5.0.0",
56
+ "@xyo-network/diviner-boundwitness-memory": "^5.0.0",
57
+ "@xyo-network/diviner-jsonpatch": "^5.0.0",
58
+ "@xyo-network/diviner-jsonpath-aggregate-memory": "^5.0.0",
59
+ "@xyo-network/diviner-model": "^5.0.0",
60
+ "@xyo-network/diviner-payload-generic": "^5.0.0",
61
+ "@xyo-network/diviner-payload-model": "^5.0.0",
62
+ "@xyo-network/diviner-range": "^5.0.0",
63
+ "@xyo-network/diviner-temporal-indexing": "^5.0.0",
64
+ "@xyo-network/evm-nft-id-payload-plugin": "^5.0.0",
65
+ "@xyo-network/manifest": "^5.0.0",
66
+ "@xyo-network/module-factory-locator": "^5.0.0",
67
+ "@xyo-network/node-memory": "^5.0.0",
64
68
  "@xyo-network/open-zeppelin-typechain": "^3.5.4",
65
- "@xyo-network/sentinel-model": "^4.3.0",
66
- "@xyo-network/wallet": "^4.3.0",
67
- "@xyo-network/wallet-model": "^4.3.0",
68
- "@xyo-network/witness-blockchain-abstract": "^4.3.0",
69
- "@xyo-network/witness-timestamp": "^4.3.0",
69
+ "@xyo-network/sentinel-model": "^5.0.0",
70
+ "@xyo-network/wallet": "^5.0.0",
71
+ "@xyo-network/wallet-model": "^5.0.0",
72
+ "@xyo-network/witness-blockchain-abstract": "^5.0.0",
73
+ "@xyo-network/witness-timestamp": "^5.0.0",
70
74
  "async-mutex": "^0.5.0",
71
75
  "typescript": "^5.8.3",
72
76
  "vitest": "^3.2.4"
@@ -0,0 +1,167 @@
1
+ import '@xylabs/vitest-extended'
2
+
3
+ import { MemoryArchivist } from '@xyo-network/archivist-memory'
4
+ import type { CryptoContractFunctionCall } from '@xyo-network/crypto-contract-function-read-payload-plugin'
5
+ import {
6
+ CryptoContractFunctionCallSchema,
7
+ isErc721ContractInfo,
8
+ isErc1155ContractInfo,
9
+ } from '@xyo-network/crypto-contract-function-read-payload-plugin'
10
+ import { MemoryBoundWitnessDiviner } from '@xyo-network/diviner-boundwitness-memory'
11
+ import { JsonPatchDiviner } from '@xyo-network/diviner-jsonpatch'
12
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
13
+ import { GenericPayloadDiviner } from '@xyo-network/diviner-payload-generic'
14
+ import type { PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model'
15
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
16
+ import {
17
+ TemporalIndexingDiviner,
18
+ TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner,
19
+ TemporalIndexingDivinerIndexCandidateToIndexDiviner,
20
+ TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner,
21
+ TemporalIndexingDivinerStateToIndexCandidateDiviner,
22
+ } from '@xyo-network/diviner-temporal-indexing'
23
+ import type { ModuleManifest, PackageManifestPayload } from '@xyo-network/manifest'
24
+ import { ManifestWrapper } from '@xyo-network/manifest'
25
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
26
+ import { ModuleFactory } from '@xyo-network/module-model'
27
+ import type { MemoryNode } from '@xyo-network/node-memory'
28
+ import {
29
+ ERC721__factory, ERC721Enumerable__factory, ERC1155__factory,
30
+ } from '@xyo-network/open-zeppelin-typechain'
31
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
32
+ import { HDWallet } from '@xyo-network/wallet'
33
+ import type { WalletInstance } from '@xyo-network/wallet-model'
34
+ import { getProviderFromEnv } from '@xyo-network/witness-blockchain-abstract'
35
+ import { TimestampWitness } from '@xyo-network/witness-timestamp'
36
+ import type { Provider } from 'ethers'
37
+ import {
38
+ beforeAll,
39
+ describe, expect, it,
40
+ } from 'vitest'
41
+
42
+ import { CryptoContractDiviner } from '../../../Diviner/index.ts'
43
+ import type { CryptoContractFunctionReadWitnessParams } from '../../../Witness.ts'
44
+ import { CryptoContractFunctionReadWitness } from '../../../Witness.ts'
45
+ import erc721IndexNodeManifest from './Contract.Sentinel.Erc721.Index.json' with { type: 'json' }
46
+ import erc1155IndexNodeManifest from './Contract.Sentinel.Erc1155.Index.json' with { type: 'json' }
47
+ import sentinelNodeManifest from './Contract.Sentinel.Node.json' with { type: 'json' }
48
+
49
+ const maxProviders = 32
50
+
51
+ describe.skip('Contract Node', () => {
52
+ type TokenType = 'ERC721' | 'ERC1155'
53
+ const cases: [TokenType, string][] = [
54
+ ['ERC721', '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'],
55
+ ['ERC1155', '0xEdB61f74B0d09B2558F1eeb79B247c1F363Ae452'],
56
+ ['ERC1155', '0x2A6d6a082C410a195157EC4caf67CB9fD718f087'],
57
+ ['ERC1155', '0x33FD426905F149f8376e227d0C9D3340AaD17aF1'],
58
+ ['ERC1155', '0x7DaEC605E9e2a1717326eeDFd660601e2753A057'],
59
+ ['ERC1155', '0xCaf94eB06D4dE233c45B353723C387D3E440f3d6'],
60
+ ['ERC1155', '0xbF42C1972877F39e102807E5E80ed2ff5D16aa5f'],
61
+ ]
62
+ const getProviders = () => {
63
+ const providers: Provider[] = []
64
+ for (let i = 0; i < maxProviders; i++) {
65
+ providers.push(getProviderFromEnv())
66
+ }
67
+ return providers
68
+ }
69
+ let wallet: WalletInstance
70
+ let node: MemoryNode
71
+ beforeAll(async () => {
72
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
73
+ wallet = await HDWallet.fromPhrase(mnemonic)
74
+ const locator = new ModuleFactoryLocator()
75
+ locator.register(MemoryArchivist.factory())
76
+ locator.register(MemoryBoundWitnessDiviner.factory())
77
+ locator.register(GenericPayloadDiviner.factory())
78
+ locator.register(TimestampWitness.factory())
79
+
80
+ locator.register(CryptoContractDiviner.factory())
81
+
82
+ locator.register(TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner.factory(), CryptoContractDiviner.labels)
83
+
84
+ locator.register(TemporalIndexingDivinerIndexCandidateToIndexDiviner.factory(), CryptoContractDiviner.labels)
85
+
86
+ locator.register(TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner.factory(), CryptoContractDiviner.labels)
87
+
88
+ locator.register(TemporalIndexingDivinerStateToIndexCandidateDiviner.factory(), CryptoContractDiviner.labels)
89
+
90
+ locator.register(TemporalIndexingDiviner.factory(), CryptoContractDiviner.labels)
91
+ locator.register(
92
+
93
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
94
+ config: { abi: ERC721__factory.abi },
95
+ providers: getProviders(),
96
+ } as CryptoContractFunctionReadWitnessParams),
97
+ { 'network.xyo.evm.interface': 'Erc721' },
98
+ )
99
+ locator.register(
100
+
101
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
102
+ config: { abi: ERC721Enumerable__factory.abi },
103
+ providers: getProviders(),
104
+ } as CryptoContractFunctionReadWitnessParams),
105
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
106
+ )
107
+ locator.register(
108
+
109
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
110
+ config: { abi: ERC1155__factory.abi },
111
+ providers: getProviders(),
112
+ } as CryptoContractFunctionReadWitnessParams),
113
+ { 'network.xyo.evm.interface': 'Erc1155' },
114
+ )
115
+ locator.register(JsonPatchDiviner.factory())
116
+ locator.register(TemporalIndexingDiviner.factory())
117
+ const publicChildren: ModuleManifest[] = [
118
+ ...(erc721IndexNodeManifest as PackageManifestPayload).nodes,
119
+ ...(erc1155IndexNodeManifest as PackageManifestPayload).nodes,
120
+ ]
121
+ const manifest = new ManifestWrapper(sentinelNodeManifest as PackageManifestPayload, wallet, locator, publicChildren)
122
+ node = await manifest.loadNodeFromIndex(0)
123
+ })
124
+ describe('Sentinel', () => {
125
+ it.each(cases)('With %s (%s)', async (_, address) => {
126
+ const collectionSentinel = asSentinelInstance(await node.resolve('NftInfoSentinel'))
127
+ expect(collectionSentinel).toBeDefined()
128
+ const collectionCallPayload: CryptoContractFunctionCall = { address, schema: CryptoContractFunctionCallSchema }
129
+ const report = await collectionSentinel?.report([collectionCallPayload])
130
+ let foundAny = false
131
+ const erc721 = report?.find(isErc721ContractInfo)
132
+ if (erc721) {
133
+ foundAny = true
134
+ expect(erc721?.results?.name).toBe('BoredApeYachtClub')
135
+ expect(erc721?.results?.symbol).toBe('BAYC')
136
+ }
137
+ const erc1155 = report?.find(isErc1155ContractInfo)
138
+ if (erc1155) {
139
+ foundAny = true
140
+ expect(erc1155?.results?.uri).toBeDefined()
141
+ }
142
+ expect(foundAny).toBe(true)
143
+ })
144
+ })
145
+ describe('ERC721 Index', () => {
146
+ const erc721Cases = cases.filter(([type]) => type === 'ERC721')
147
+ it.each(erc721Cases)('With %s (%s)', async (_, address) => {
148
+ const diviner = asDivinerInstance(await node.resolve('Erc721IndexDiviner'))
149
+ expect(diviner).toBeDefined()
150
+ const query = { address, schema: PayloadDivinerQuerySchema } as PayloadDivinerQueryPayload
151
+ const result = await diviner?.divine([query])
152
+ expect(result).toBeDefined()
153
+ expect(result).toBeArrayOfSize(1)
154
+ })
155
+ })
156
+ describe('ERC1155 Index', () => {
157
+ const erc1155 = cases.filter(([type]) => type === 'ERC1155')
158
+ it.each(erc1155)('With %s (%s)', async (_, address) => {
159
+ const diviner = asDivinerInstance(await node.resolve('Erc1155IndexDiviner'))
160
+ expect(diviner).toBeDefined()
161
+ const query = { address, schema: PayloadDivinerQuerySchema } as PayloadDivinerQueryPayload
162
+ const result = await diviner?.divine([query])
163
+ expect(result).toBeDefined()
164
+ expect(result).toBeArrayOfSize(1)
165
+ })
166
+ })
167
+ })
@@ -0,0 +1,162 @@
1
+ /* eslint-disable max-statements */
2
+
3
+ import '@xylabs/vitest-extended'
4
+
5
+ import type {
6
+ ContractInfo,
7
+ CryptoContractFunctionCall,
8
+ } from '@xyo-network/crypto-contract-function-read-payload-plugin'
9
+ import {
10
+ ContractInfoSchema,
11
+ CryptoContractFunctionCallSchema,
12
+ } from '@xyo-network/crypto-contract-function-read-payload-plugin'
13
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
14
+ import type { PackageManifestPayload } from '@xyo-network/manifest'
15
+ import { ManifestWrapper } from '@xyo-network/manifest'
16
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
17
+ import { ModuleFactory } from '@xyo-network/module-model'
18
+ import {
19
+ ERC721__factory, ERC721Enumerable__factory, ERC1155__factory,
20
+ } from '@xyo-network/open-zeppelin-typechain'
21
+ import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
22
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
23
+ import { HDWallet } from '@xyo-network/wallet'
24
+ import { getProviderFromEnv } from '@xyo-network/witness-blockchain-abstract'
25
+ import { asWitnessInstance } from '@xyo-network/witness-model'
26
+ import type { Provider } from 'ethers'
27
+ import {
28
+ afterAll,
29
+ describe, expect, it,
30
+ } from 'vitest'
31
+
32
+ import { CryptoContractDiviner } from '../../../Diviner/index.ts'
33
+ import type { CryptoContractFunctionReadWitnessParams } from '../../../Witness.ts'
34
+ import { CryptoContractFunctionReadWitness } from '../../../Witness.ts'
35
+ import erc721SentinelManifest from '../Erc721Sentinel.json' with { type: 'json' }
36
+
37
+ const profileData: Record<string, number[]> = {}
38
+
39
+ const profile = (name: string) => {
40
+ const timeData = profileData[name] ?? []
41
+ timeData.push(Date.now())
42
+ profileData[name] = timeData
43
+ }
44
+
45
+ const profileReport = () => {
46
+ let lowest = Date.now()
47
+ let highest = 0
48
+ // eslint-disable-next-line unicorn/no-array-reduce
49
+ const results = Object.entries(profileData).reduce<Record<string, number>>((prev, [name, readings]) => {
50
+ const start = readings.at(0)
51
+ if (start) {
52
+ if (start < lowest) {
53
+ lowest = start
54
+ }
55
+ const end = readings.at(-1) ?? Date.now()
56
+ if (end > highest) {
57
+ highest = end
58
+ }
59
+ prev[name] = end - start
60
+ }
61
+ return prev
62
+ }, {})
63
+ if (highest) {
64
+ results['-all-'] = highest - lowest
65
+ }
66
+ return results
67
+ }
68
+
69
+ const tokenCount = 0
70
+ const maxProviders = 32
71
+
72
+ describe('Erc721Sentinel', () => {
73
+ // const address = '0x562fC2927c77cB975680088566ADa1dC6cB8b5Ea' //Random ERC721
74
+ const address = '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' // Bored Apes
75
+
76
+ const getProviders = () => {
77
+ const providers: Provider[] = []
78
+ for (let i = 0; i < maxProviders; i++) {
79
+ providers.push(getProviderFromEnv())
80
+ }
81
+ return providers
82
+ }
83
+
84
+ describe('report', () => {
85
+ it('specifying address', async () => {
86
+ profile('setup')
87
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
88
+ const wallet = await HDWallet.fromPhrase(mnemonic)
89
+ const locator = new ModuleFactoryLocator()
90
+
91
+ locator.register(CryptoContractDiviner.factory())
92
+
93
+ locator.register(
94
+
95
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
96
+ config: { abi: ERC721__factory.abi },
97
+ providers: getProviders(),
98
+ } as CryptoContractFunctionReadWitnessParams),
99
+ { 'network.xyo.evm.interface': 'Erc721' },
100
+ )
101
+
102
+ locator.register(
103
+
104
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
105
+ config: { abi: ERC721Enumerable__factory.abi },
106
+ providers: getProviders(),
107
+ } as CryptoContractFunctionReadWitnessParams),
108
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
109
+ )
110
+
111
+ locator.register(
112
+
113
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
114
+ config: { abi: ERC1155__factory.abi },
115
+ providers: getProviders(),
116
+ } as CryptoContractFunctionReadWitnessParams),
117
+ { 'network.xyo.evm.interface': 'Erc1155' },
118
+ )
119
+ profile('setup')
120
+ profile('manifest')
121
+ const manifest = new ManifestWrapper(erc721SentinelManifest as PackageManifestPayload, wallet, locator)
122
+ profile('manifest-load')
123
+ const node = await manifest.loadNodeFromIndex(0)
124
+ profile('manifest-load')
125
+ profile('manifest-resolve')
126
+ const mods = await node.resolve('*')
127
+ profile('manifest-resolve')
128
+ profile('manifest')
129
+ expect(mods.length).toBeGreaterThan(5)
130
+
131
+ const collectionSentinel = asSentinelInstance(await node.resolve('NftInfoSentinel'))
132
+ expect(collectionSentinel).toBeDefined()
133
+
134
+ const tokenSentinel = asSentinelInstance(await node.resolve('NftTokenInfoSentinel'))
135
+ expect(tokenSentinel).toBeDefined()
136
+
137
+ const nameWitness = asWitnessInstance(await node.resolve('Erc721NameWitness'))
138
+ expect(nameWitness).toBeDefined()
139
+
140
+ const symbolWitness = asWitnessInstance(await node.resolve('Erc721SymbolWitness'))
141
+ expect(symbolWitness).toBeDefined()
142
+
143
+ const diviner = asDivinerInstance(await node.resolve('Erc721ContractInfoDiviner'))
144
+ expect(diviner).toBeDefined()
145
+
146
+ const collectionCallPayload: CryptoContractFunctionCall = { address, schema: CryptoContractFunctionCallSchema }
147
+ profile('collectionReport')
148
+ const report = await collectionSentinel?.report([collectionCallPayload])
149
+ profile('collectionReport')
150
+ profile('tokenCallSetup')
151
+ const info = report?.find(isPayloadOfSchemaType<ContractInfo>(ContractInfoSchema))
152
+
153
+ expect(info?.results?.name).toBe('BoredApeYachtClub')
154
+ expect(info?.results?.symbol).toBe('BAYC')
155
+ })
156
+ afterAll(() => {
157
+ const profileData = profileReport()
158
+ if (profileData['tokenReport']) console.log(`Timer: ${profileData['tokenReport'] / tokenCount}ms`)
159
+ console.log(`Profile: ${JSON.stringify(profileData, null, 2)}`)
160
+ })
161
+ })
162
+ })
@@ -0,0 +1,203 @@
1
+ /* eslint-disable max-statements */
2
+
3
+ import '@xylabs/vitest-extended'
4
+
5
+ import { hexFromHexString } from '@xylabs/hex'
6
+ import type {
7
+ ContractInfo,
8
+ CryptoContractFunctionCall,
9
+ CryptoContractFunctionCallResult,
10
+ } from '@xyo-network/crypto-contract-function-read-payload-plugin'
11
+ import {
12
+ ContractInfoSchema,
13
+ CryptoContractFunctionCallResultSchema,
14
+ CryptoContractFunctionCallSchema,
15
+ } from '@xyo-network/crypto-contract-function-read-payload-plugin'
16
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
17
+ import type { PackageManifestPayload } from '@xyo-network/manifest'
18
+ import { ManifestWrapper } from '@xyo-network/manifest'
19
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
20
+ import { ModuleFactory } from '@xyo-network/module-model'
21
+ import {
22
+ ERC721__factory, ERC721Enumerable__factory, ERC1155__factory,
23
+ } from '@xyo-network/open-zeppelin-typechain'
24
+ import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
25
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
26
+ import { HDWallet } from '@xyo-network/wallet'
27
+ import { getProviderFromEnv } from '@xyo-network/witness-blockchain-abstract'
28
+ import { asWitnessInstance } from '@xyo-network/witness-model'
29
+ import { Semaphore } from 'async-mutex'
30
+ import type { Provider } from 'ethers'
31
+ import {
32
+ afterAll,
33
+ describe, expect, it,
34
+ } from 'vitest'
35
+
36
+ import { CryptoContractDiviner } from '../../../Diviner/index.ts'
37
+ import type { CryptoContractFunctionReadWitnessParams } from '../../../Witness.ts'
38
+ import { CryptoContractFunctionReadWitness } from '../../../Witness.ts'
39
+ import erc721SentinelManifest from '../Erc721Sentinel.json' with { type: 'json' }
40
+
41
+ const profileData: Record<string, number[]> = {}
42
+
43
+ const profile = (name: string) => {
44
+ const timeData = profileData[name] ?? []
45
+ timeData.push(Date.now())
46
+ profileData[name] = timeData
47
+ }
48
+
49
+ const profileReport = () => {
50
+ let lowest = Date.now()
51
+ let highest = 0
52
+ // eslint-disable-next-line unicorn/no-array-reduce
53
+ const results = Object.entries(profileData).reduce<Record<string, number>>((prev, [name, readings]) => {
54
+ const start = readings.at(0)
55
+ if (start) {
56
+ if (start < lowest) {
57
+ lowest = start
58
+ }
59
+ const end = readings.at(-1) ?? Date.now()
60
+ if (end > highest) {
61
+ highest = end
62
+ }
63
+ prev[name] = end - start
64
+ }
65
+ return prev
66
+ }, {})
67
+ if (highest) {
68
+ results['-all-'] = highest - lowest
69
+ }
70
+ return results
71
+ }
72
+
73
+ let tokenCount = 0
74
+ const maxProviders = 32
75
+
76
+ describe('Erc721Sentinel', () => {
77
+ // const address = '0x562fC2927c77cB975680088566ADa1dC6cB8b5Ea' //Random ERC721
78
+ const address = '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D' // Bored Apes
79
+
80
+ const getProviders = () => {
81
+ const providers: Provider[] = []
82
+ for (let i = 0; i < maxProviders; i++) {
83
+ providers.push(getProviderFromEnv())
84
+ }
85
+ return providers
86
+ }
87
+
88
+ describe('report', () => {
89
+ it('specifying address', async () => {
90
+ profile('setup')
91
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
92
+ const wallet = await HDWallet.fromPhrase(mnemonic)
93
+ const locator = new ModuleFactoryLocator()
94
+ locator.register(CryptoContractDiviner.factory())
95
+
96
+ locator.register(
97
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
98
+ config: { abi: ERC721__factory.abi },
99
+ providers: getProviders(),
100
+ } as CryptoContractFunctionReadWitnessParams),
101
+ { 'network.xyo.evm.interface': 'Erc721' },
102
+ )
103
+
104
+ locator.register(
105
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
106
+ config: { abi: ERC721Enumerable__factory.abi },
107
+ providers: getProviders(),
108
+ } as CryptoContractFunctionReadWitnessParams),
109
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
110
+ )
111
+
112
+ locator.register(
113
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
114
+ config: { abi: ERC1155__factory.abi },
115
+ providers: getProviders(),
116
+ } as CryptoContractFunctionReadWitnessParams),
117
+ { 'network.xyo.evm.interface': 'Erc1155' },
118
+ )
119
+ profile('setup')
120
+ profile('manifest')
121
+ const manifest = new ManifestWrapper(erc721SentinelManifest as PackageManifestPayload, wallet, locator)
122
+ profile('manifest-load')
123
+ const node = await manifest.loadNodeFromIndex(0)
124
+ profile('manifest-load')
125
+ profile('manifest-resolve')
126
+ const mods = await node.resolve('*')
127
+ profile('manifest-resolve')
128
+ profile('manifest')
129
+ expect(mods.length).toBeGreaterThan(5)
130
+
131
+ const collectionSentinel = asSentinelInstance(await node.resolve('NftInfoSentinel'))
132
+ expect(collectionSentinel).toBeDefined()
133
+
134
+ const tokenSentinel = asSentinelInstance(await node.resolve('NftTokenInfoSentinel'))
135
+ expect(tokenSentinel).toBeDefined()
136
+
137
+ const nameWitness = asWitnessInstance(await node.resolve('Erc721NameWitness'))
138
+ expect(nameWitness).toBeDefined()
139
+
140
+ const symbolWitness = asWitnessInstance(await node.resolve('Erc721SymbolWitness'))
141
+ expect(symbolWitness).toBeDefined()
142
+
143
+ const diviner = asDivinerInstance(await node.resolve('Erc721ContractInfoDiviner'))
144
+ expect(diviner).toBeDefined()
145
+
146
+ const collectionCallPayload: CryptoContractFunctionCall = { address, schema: CryptoContractFunctionCallSchema }
147
+ profile('collectionReport')
148
+ const report = await collectionSentinel?.report([collectionCallPayload])
149
+ profile('collectionReport')
150
+ profile('tokenCallSetup')
151
+ const info = report?.find(isPayloadOfSchemaType<ContractInfo>(ContractInfoSchema))
152
+
153
+ const totalSupply = info?.results?.totalSupply ? BigInt(hexFromHexString(info.results.totalSupply as string, { prefix: true })) : 0n
154
+ expect(totalSupply).toBeGreaterThan(0n)
155
+
156
+ const chunkSize = 100n
157
+ const maxChunks = totalSupply / chunkSize
158
+ const chunks: CryptoContractFunctionCall[][] = []
159
+
160
+ let offset = 0n
161
+ while (offset < totalSupply && chunks.length < maxChunks) {
162
+ offset = BigInt(chunks.length) * chunkSize
163
+
164
+ const chunkList: CryptoContractFunctionCall[] = []
165
+
166
+ for (let i = offset; i < offset + chunkSize && i < totalSupply; i++) {
167
+ const call: CryptoContractFunctionCall = {
168
+ address,
169
+ args: [`0x${BigInt(i).toString(16)}`],
170
+ functionName: 'tokenByIndex',
171
+ schema: CryptoContractFunctionCallSchema,
172
+ }
173
+ chunkList.push(call)
174
+ }
175
+ chunks.push(chunkList)
176
+ }
177
+ profile('tokenCallSetup')
178
+ const maxConcurrent = 8
179
+ if (tokenSentinel) {
180
+ profile('tokenReport')
181
+ const semaphore = new Semaphore(maxConcurrent)
182
+ const tokenReportArrays = await Promise.all(
183
+ chunks.map(async (chunk) => {
184
+ return await semaphore.runExclusive(async () => {
185
+ const result = await tokenSentinel.report(chunk)
186
+ return result
187
+ })
188
+ }),
189
+ )
190
+ profile('tokenReport')
191
+ const tokenReport = tokenReportArrays.flat()
192
+ tokenCount = tokenReport.length
193
+ const tokenInfoPayloads = tokenReport.filter(isPayloadOfSchemaType<CryptoContractFunctionCallResult>(CryptoContractFunctionCallResultSchema))
194
+ expect(BigInt(tokenInfoPayloads.length)).toBe(totalSupply)
195
+ }
196
+ }, 30_000)
197
+ afterAll(() => {
198
+ const profileData = profileReport()
199
+ if (profileData['tokenReport']) console.log(`Timer: ${profileData['tokenReport'] / tokenCount}ms`)
200
+ console.log(`Profile: ${JSON.stringify(profileData, null, 2)}`)
201
+ })
202
+ })
203
+ })
@@ -0,0 +1,120 @@
1
+ import '@xylabs/vitest-extended'
2
+
3
+ import {
4
+ CryptoContractFunctionCallSchema,
5
+ isCryptoContractFunctionCallResult,
6
+ isCryptoContractFunctionCallSuccess,
7
+ } from '@xyo-network/crypto-contract-function-read-payload-plugin'
8
+ import { MemoryBoundWitnessDiviner } from '@xyo-network/diviner-boundwitness-memory'
9
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
10
+ import { GenericPayloadDiviner } from '@xyo-network/diviner-payload-generic'
11
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
12
+ import {
13
+ TemporalIndexingDiviner,
14
+ TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner,
15
+ TemporalIndexingDivinerIndexCandidateToIndexDiviner,
16
+ TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner,
17
+ TemporalIndexingDivinerStateToIndexCandidateDiviner,
18
+ } from '@xyo-network/diviner-temporal-indexing'
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 { getProviderFromEnv } from '@xyo-network/witness-blockchain-abstract'
29
+ import { TimestampWitness } from '@xyo-network/witness-timestamp'
30
+ import type { Provider } from 'ethers'
31
+ import {
32
+ beforeAll, describe, expect,
33
+ it,
34
+ } from 'vitest'
35
+
36
+ import { CryptoContractDiviner } from '../../Diviner/index.ts'
37
+ import type { CryptoContractFunctionReadWitnessParams } from '../../Witness.ts'
38
+ import { CryptoContractFunctionReadWitness } from '../../Witness.ts'
39
+ import erc721TotalSupplyIndexManifest from './Erc721.TotalSupply.Index.json' with { type: 'json' }
40
+
41
+ const maxProviders = 32
42
+
43
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Erc721.TotalSupply.Index', () => {
44
+ let wallet: WalletInstance
45
+ let node: MemoryNode
46
+
47
+ const getProviders = () => {
48
+ const providers: Provider[] = []
49
+ for (let i = 0; i < maxProviders; i++) {
50
+ providers.push(getProviderFromEnv())
51
+ }
52
+ return providers
53
+ }
54
+ beforeAll(async () => {
55
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
56
+ wallet = await HDWallet.fromPhrase(mnemonic)
57
+ const locator = new ModuleFactoryLocator()
58
+ locator.register(MemoryBoundWitnessDiviner.factory())
59
+ locator.register(GenericPayloadDiviner.factory())
60
+ locator.register(TimestampWitness.factory())
61
+
62
+ locator.register(CryptoContractDiviner.factory())
63
+ locator.register(TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner.factory())
64
+ locator.register(TemporalIndexingDivinerIndexCandidateToIndexDiviner.factory())
65
+ locator.register(TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner.factory())
66
+ locator.register(TemporalIndexingDivinerStateToIndexCandidateDiviner.factory())
67
+ locator.register(TemporalIndexingDiviner.factory())
68
+
69
+ locator.register(
70
+
71
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
72
+ config: { abi: ERC721Enumerable__factory.abi },
73
+ providers: getProviders(),
74
+ } as CryptoContractFunctionReadWitnessParams),
75
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
76
+ )
77
+ const manifest = new ManifestWrapper(erc721TotalSupplyIndexManifest as PackageManifestPayload, wallet, locator)
78
+ node = await manifest.loadNodeFromIndex(0)
79
+ })
80
+ type TestData = readonly [string]
81
+ const cases: readonly TestData[] = [
82
+ ['0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'], // BAYC
83
+ ] as const
84
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Sentinel', () => {
85
+ describe('Sentinel', () => {
86
+ it.each(cases)('returns totalSupply', async (address) => {
87
+ const sentinel = asSentinelInstance(await node.resolve('Sentinel'))
88
+ const input = {
89
+ address, chainId: 1, schema: CryptoContractFunctionCallSchema,
90
+ }
91
+ const observations = await sentinel?.report([input])
92
+ expect(observations?.length).toBe(3)
93
+ const totalSupply = observations?.filter(isCryptoContractFunctionCallResult).find(isCryptoContractFunctionCallSuccess)
94
+ expect(totalSupply).toBeDefined()
95
+ expect(totalSupply?.result).toBeString()
96
+ const totalSupplyValue = totalSupply?.result as string
97
+ expect(Number.parseInt(totalSupplyValue)).toBeNumber()
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 result', async (address) => {
109
+ const diviner = asDivinerInstance(await node.resolve('IndexDiviner'))
110
+ expect(diviner).toBeDefined()
111
+ const query = {
112
+ address, chainId: 1, schema: PayloadDivinerQuerySchema,
113
+ }
114
+ const result = await diviner?.divine([query])
115
+ expect(result).toBeDefined()
116
+ expect(result).toBeArrayOfSize(1)
117
+ })
118
+ })
119
+ })
120
+ })
@@ -0,0 +1,133 @@
1
+ import '@xylabs/vitest-extended'
2
+
3
+ import { delay } from '@xylabs/delay'
4
+ import { CryptoContractFunctionCallSchema } from '@xyo-network/crypto-contract-function-read-payload-plugin'
5
+ import { MemoryBoundWitnessDiviner } from '@xyo-network/diviner-boundwitness-memory'
6
+ import { JsonPatchDiviner } from '@xyo-network/diviner-jsonpatch'
7
+ import { JsonPathAggregateDiviner } from '@xyo-network/diviner-jsonpath-aggregate-memory'
8
+ import { asDivinerInstance } from '@xyo-network/diviner-model'
9
+ import { GenericPayloadDiviner } from '@xyo-network/diviner-payload-generic'
10
+ import { PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'
11
+ import { RangeDiviner } from '@xyo-network/diviner-range'
12
+ import {
13
+ TemporalIndexingDiviner,
14
+ TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner,
15
+ TemporalIndexingDivinerIndexCandidateToIndexDiviner,
16
+ TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner,
17
+ TemporalIndexingDivinerStateToIndexCandidateDiviner,
18
+ } from '@xyo-network/diviner-temporal-indexing'
19
+ import { isNftId } from '@xyo-network/evm-nft-id-payload-plugin'
20
+ import type { PackageManifestPayload } from '@xyo-network/manifest'
21
+ import { ManifestWrapper } from '@xyo-network/manifest'
22
+ import { ModuleFactoryLocator } from '@xyo-network/module-factory-locator'
23
+ import { ModuleFactory } from '@xyo-network/module-model'
24
+ import type { MemoryNode } from '@xyo-network/node-memory'
25
+ import { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'
26
+ import { asSentinelInstance } from '@xyo-network/sentinel-model'
27
+ import { HDWallet } from '@xyo-network/wallet'
28
+ import type { WalletInstance } from '@xyo-network/wallet-model'
29
+ import { getProviderFromEnv } from '@xyo-network/witness-blockchain-abstract'
30
+ import { TimestampWitness } from '@xyo-network/witness-timestamp'
31
+ import type { Provider } from 'ethers'
32
+ import {
33
+ beforeAll, describe, expect,
34
+ it,
35
+ } from 'vitest'
36
+
37
+ import { CryptoContractDiviner } from '../../Diviner/index.ts'
38
+ import type { CryptoContractFunctionReadWitnessParams } from '../../Witness.ts'
39
+ import { CryptoContractFunctionReadWitness } from '../../Witness.ts'
40
+ import nodeManifest from './Erc721.NftId.Index.json' with { type: 'json' }
41
+
42
+ const maxProviders = 32
43
+
44
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Erc721.NftId.Index', () => {
45
+ let wallet: WalletInstance
46
+ let node: MemoryNode
47
+
48
+ const getProviders = () => {
49
+ const providers: Provider[] = []
50
+ for (let i = 0; i < maxProviders; i++) {
51
+ providers.push(getProviderFromEnv())
52
+ }
53
+ return providers
54
+ }
55
+ beforeAll(async () => {
56
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
57
+ wallet = await HDWallet.fromPhrase(mnemonic)
58
+ const locator = new ModuleFactoryLocator()
59
+ locator.register(MemoryBoundWitnessDiviner.factory())
60
+ locator.register(GenericPayloadDiviner.factory())
61
+ locator.register(TimestampWitness.factory())
62
+
63
+ locator.register(CryptoContractDiviner.factory())
64
+ locator.register(TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner.factory())
65
+ locator.register(TemporalIndexingDivinerIndexCandidateToIndexDiviner.factory())
66
+ locator.register(TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner.factory())
67
+ locator.register(TemporalIndexingDivinerStateToIndexCandidateDiviner.factory())
68
+ locator.register(TemporalIndexingDiviner.factory())
69
+ locator.register(JsonPatchDiviner.factory())
70
+ locator.register(JsonPathAggregateDiviner.factory())
71
+ locator.register(RangeDiviner.factory())
72
+
73
+ locator.register(
74
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
75
+ config: { abi: ERC721Enumerable__factory.abi },
76
+ providers: getProviders(),
77
+ } as CryptoContractFunctionReadWitnessParams),
78
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
79
+ )
80
+ const manifest = new ManifestWrapper(nodeManifest as PackageManifestPayload, wallet, locator)
81
+ node = await manifest.loadNodeFromIndex(0)
82
+ })
83
+ type TestData = readonly [string]
84
+ const cases: readonly TestData[] = [
85
+ ['0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'], // BAYC
86
+ ] as const
87
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Sentinel', () => {
88
+ const tokensToCheck = 16
89
+ const tokenIndexes = Array.from({ length: tokensToCheck }).map((_, tokenIndex) => {
90
+ // Add one to prevent 0 index
91
+ return tokenIndex + 1
92
+ })
93
+ describe('Sentinel', () => {
94
+ it.each(cases)('returns NftIndexes', async (address) => {
95
+ const sentinel = asSentinelInstance(await node.resolve('Sentinel'))
96
+ const chainId = 1
97
+ const inputs = tokenIndexes.map((_, tokenIndex) => {
98
+ return {
99
+ address,
100
+ args: [`0x${BigInt(tokenIndex).toString(16)}`],
101
+ chainId,
102
+ functionName: 'tokenByIndex',
103
+ schema: CryptoContractFunctionCallSchema,
104
+ }
105
+ })
106
+ const observations = await sentinel?.report(inputs)
107
+ const nftId = observations?.filter(isNftId)
108
+ expect(nftId?.length).toBe(tokensToCheck)
109
+ for (const nftIndex of nftId ?? []) {
110
+ expect(nftIndex.address).toBe(address)
111
+ expect(nftIndex.chainId).toBe(chainId)
112
+ }
113
+ })
114
+ })
115
+ describe.skip('Index', () => {
116
+ it.each(cases)('returns indexed NftIndex results', async (address) => {
117
+ await delay(100)
118
+ const diviner = asDivinerInstance(await node.resolve('IndexDiviner'))
119
+ expect(diviner).toBeDefined()
120
+ // Check we've indexed the results by sampling the first and last index
121
+ const sampleIndexes = [0, tokensToCheck - 1]
122
+ for (const index of sampleIndexes) {
123
+ const query = {
124
+ address, chainId: 1, index, schema: PayloadDivinerQuerySchema,
125
+ }
126
+ const result = await diviner?.divine([query])
127
+ expect(result).toBeDefined()
128
+ expect(result).toBeArrayOfSize(1)
129
+ }
130
+ })
131
+ })
132
+ })
133
+ })
@@ -0,0 +1,127 @@
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 { isNftIndex } 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 { getProviderFromEnv } from '@xyo-network/witness-blockchain-abstract'
29
+ import { TimestampWitness } from '@xyo-network/witness-timestamp'
30
+ import type { Provider } from 'ethers'
31
+ import {
32
+ beforeAll, describe, expect,
33
+ it,
34
+ } from 'vitest'
35
+
36
+ import { CryptoContractDiviner } from '../../Diviner/index.ts'
37
+ import type { CryptoContractFunctionReadWitnessParams } from '../../Witness.ts'
38
+ import { CryptoContractFunctionReadWitness } from '../../Witness.ts'
39
+ import nodeManifest from './Erc721.NftIndex.Index.json' with { type: 'json' }
40
+
41
+ const maxProviders = 32
42
+
43
+ describe.skipIf(!process.env.INFURA_PROJECT_ID).skip('Erc721.NftIndex.Index', () => {
44
+ let wallet: WalletInstance
45
+ let node: MemoryNode
46
+
47
+ const getProviders = () => {
48
+ const providers: Provider[] = []
49
+ for (let i = 0; i < maxProviders; i++) {
50
+ providers.push(getProviderFromEnv())
51
+ }
52
+ return providers
53
+ }
54
+ beforeAll(async () => {
55
+ const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief'
56
+ wallet = await HDWallet.fromPhrase(mnemonic)
57
+ const locator = new ModuleFactoryLocator()
58
+ locator.register(MemoryBoundWitnessDiviner.factory())
59
+ locator.register(GenericPayloadDiviner.factory())
60
+ locator.register(TimestampWitness.factory())
61
+ locator.register(CryptoContractDiviner.factory())
62
+ locator.register(TemporalIndexingDivinerDivinerQueryToIndexQueryDiviner.factory())
63
+ locator.register(TemporalIndexingDivinerIndexCandidateToIndexDiviner.factory())
64
+ locator.register(TemporalIndexingDivinerIndexQueryResponseToDivinerQueryResponseDiviner.factory())
65
+ locator.register(TemporalIndexingDivinerStateToIndexCandidateDiviner.factory())
66
+ locator.register(TemporalIndexingDiviner.factory())
67
+ locator.register(JsonPatchDiviner.factory())
68
+ locator.register(JsonPathAggregateDiviner.factory())
69
+ locator.register(RangeDiviner.factory())
70
+
71
+ locator.register(
72
+ new ModuleFactory(CryptoContractFunctionReadWitness, {
73
+ config: { abi: ERC721Enumerable__factory.abi },
74
+ providers: getProviders(),
75
+ } as CryptoContractFunctionReadWitnessParams),
76
+ { 'network.xyo.evm.interface': 'Erc721Enumerable' },
77
+ )
78
+ const manifest = new ManifestWrapper(nodeManifest as PackageManifestPayload, wallet, locator)
79
+ node = await manifest.loadNodeFromIndex(0)
80
+ })
81
+ type TestData = readonly [string]
82
+ const cases: readonly TestData[] = [
83
+ ['0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D'], // BAYC
84
+ ] as const
85
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('Sentinel', () => {
86
+ const totalSupply = 2710
87
+ describe('Sentinel', () => {
88
+ it.each(cases)('returns NftIndexes', async (address) => {
89
+ const sentinel = asSentinelInstance(await node.resolve('Sentinel'))
90
+ const chainId = 1
91
+ const input = {
92
+ address,
93
+ args: [],
94
+ chainId,
95
+ functionName: 'totalSupply',
96
+ result: `${totalSupply}`,
97
+ schema: 'network.xyo.crypto.contract.function.call.result',
98
+ }
99
+ const observations = await sentinel?.report([input])
100
+ const nftIndexes = observations?.filter(isNftIndex)
101
+ expect(nftIndexes?.length).toBe(totalSupply)
102
+ for (const nftIndex of nftIndexes ?? []) {
103
+ expect(nftIndex.address).toBe(address)
104
+ expect(nftIndex.chainId).toBe(chainId)
105
+ expect(nftIndex.index).toBeNumber()
106
+ }
107
+ })
108
+ })
109
+ describe.skip('Index', () => {
110
+ it.each(cases)('returns indexed NftIndex results', async (address) => {
111
+ await delay(100)
112
+ const diviner = asDivinerInstance(await node.resolve('IndexDiviner'))
113
+ expect(diviner).toBeDefined()
114
+ // Check we've indexed the results by sampling the first and last index
115
+ const sampleIndexes = [0, totalSupply - 1]
116
+ for (const index of sampleIndexes) {
117
+ const query = {
118
+ address, chainId: 1, index, schema: PayloadDivinerQuerySchema,
119
+ }
120
+ const result = await diviner?.divine([query])
121
+ expect(result).toBeDefined()
122
+ expect(result).toBeArrayOfSize(1)
123
+ }
124
+ })
125
+ })
126
+ })
127
+ })
@@ -0,0 +1,46 @@
1
+ import '@xylabs/vitest-extended'
2
+
3
+ import type { CryptoContractFunctionCall, CryptoContractFunctionCallResult } from '@xyo-network/crypto-contract-function-read-payload-plugin'
4
+ import {
5
+ CryptoContractFunctionCallResultSchema,
6
+ CryptoContractFunctionCallSchema,
7
+ CryptoContractFunctionReadWitnessConfigSchema,
8
+ } from '@xyo-network/crypto-contract-function-read-payload-plugin'
9
+ import { ERC20__factory } from '@xyo-network/open-zeppelin-typechain'
10
+ import type { Payload } from '@xyo-network/payload-model'
11
+ import { isPayloadOfSchemaType } from '@xyo-network/payload-model'
12
+ import { getProviderFromEnv } from '@xyo-network/witness-blockchain-abstract'
13
+ import {
14
+ describe, expect,
15
+ it,
16
+ } from 'vitest'
17
+
18
+ import { CryptoContractFunctionReadWitness } from '../Witness.ts'
19
+
20
+ const validateObservation = (observation: Payload[]) => {
21
+ const results = observation.filter(isPayloadOfSchemaType<CryptoContractFunctionCallResult>(CryptoContractFunctionCallResultSchema))
22
+ expect(results.length).toBeGreaterThan(0)
23
+ expect(observation.length).toEqual(results.length)
24
+ }
25
+
26
+ describe.skipIf(!process.env.INFURA_PROJECT_ID)('CryptoWalletNftWitness', () => {
27
+ const address = '0x55296f69f40ea6d20e478533c15a6b08b654e758' // XYO ERC20
28
+ const functionName = 'balanceOf'
29
+ const args = ['0xaDe7DFBC532A01dB67BFEA3b728D4eA22869f381'] // Random Holder
30
+ const provider = getProviderFromEnv()
31
+ describe('observe', () => {
32
+ describe('with no address or chainId in query', () => {
33
+ it('uses values from config', async () => {
34
+ const witness = await CryptoContractFunctionReadWitness.create({
35
+ config: { abi: ERC20__factory.abi, schema: CryptoContractFunctionReadWitnessConfigSchema },
36
+ providers: [provider],
37
+ })
38
+ const call: CryptoContractFunctionCall = {
39
+ address, args, functionName, schema: CryptoContractFunctionCallSchema,
40
+ }
41
+ const observation = await witness.observe([call])
42
+ validateObservation(observation)
43
+ })
44
+ })
45
+ })
46
+ })
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
- }