@xyo-network/crypto-nft-collection-witness-plugin 2.78.0 → 2.78.2

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.
Files changed (62) hide show
  1. package/dist/browser/index.cjs +117 -41
  2. package/dist/browser/index.cjs.map +1 -1
  3. package/dist/browser/index.js +115 -39
  4. package/dist/browser/index.js.map +1 -1
  5. package/dist/browser/lib/getNftCollectionCount.d.cts +1 -1
  6. package/dist/browser/lib/getNftCollectionCount.d.cts.map +1 -1
  7. package/dist/browser/lib/getNftCollectionCount.d.mts +1 -1
  8. package/dist/browser/lib/getNftCollectionCount.d.mts.map +1 -1
  9. package/dist/browser/lib/getNftCollectionCount.d.ts +1 -1
  10. package/dist/browser/lib/getNftCollectionCount.d.ts.map +1 -1
  11. package/dist/browser/lib/getNftCollectionMetadata.d.cts +3 -1
  12. package/dist/browser/lib/getNftCollectionMetadata.d.cts.map +1 -1
  13. package/dist/browser/lib/getNftCollectionMetadata.d.mts +3 -1
  14. package/dist/browser/lib/getNftCollectionMetadata.d.mts.map +1 -1
  15. package/dist/browser/lib/getNftCollectionMetadata.d.ts +3 -1
  16. package/dist/browser/lib/getNftCollectionMetadata.d.ts.map +1 -1
  17. package/dist/browser/lib/getNftCollectionNfts.d.cts +8 -1
  18. package/dist/browser/lib/getNftCollectionNfts.d.cts.map +1 -1
  19. package/dist/browser/lib/getNftCollectionNfts.d.mts +8 -1
  20. package/dist/browser/lib/getNftCollectionNfts.d.mts.map +1 -1
  21. package/dist/browser/lib/getNftCollectionNfts.d.ts +8 -1
  22. package/dist/browser/lib/getNftCollectionNfts.d.ts.map +1 -1
  23. package/dist/browser/lib/getProvider.d.cts +3 -0
  24. package/dist/browser/lib/getProvider.d.cts.map +1 -0
  25. package/dist/browser/lib/getProvider.d.mts +3 -0
  26. package/dist/browser/lib/getProvider.d.mts.map +1 -0
  27. package/dist/browser/lib/getProvider.d.ts +3 -0
  28. package/dist/browser/lib/getProvider.d.ts.map +1 -0
  29. package/dist/node/index.js +119 -41
  30. package/dist/node/index.js.map +1 -1
  31. package/dist/node/index.mjs +115 -39
  32. package/dist/node/index.mjs.map +1 -1
  33. package/dist/node/lib/getNftCollectionCount.d.cts +1 -1
  34. package/dist/node/lib/getNftCollectionCount.d.cts.map +1 -1
  35. package/dist/node/lib/getNftCollectionCount.d.mts +1 -1
  36. package/dist/node/lib/getNftCollectionCount.d.mts.map +1 -1
  37. package/dist/node/lib/getNftCollectionCount.d.ts +1 -1
  38. package/dist/node/lib/getNftCollectionCount.d.ts.map +1 -1
  39. package/dist/node/lib/getNftCollectionMetadata.d.cts +3 -1
  40. package/dist/node/lib/getNftCollectionMetadata.d.cts.map +1 -1
  41. package/dist/node/lib/getNftCollectionMetadata.d.mts +3 -1
  42. package/dist/node/lib/getNftCollectionMetadata.d.mts.map +1 -1
  43. package/dist/node/lib/getNftCollectionMetadata.d.ts +3 -1
  44. package/dist/node/lib/getNftCollectionMetadata.d.ts.map +1 -1
  45. package/dist/node/lib/getNftCollectionNfts.d.cts +8 -1
  46. package/dist/node/lib/getNftCollectionNfts.d.cts.map +1 -1
  47. package/dist/node/lib/getNftCollectionNfts.d.mts +8 -1
  48. package/dist/node/lib/getNftCollectionNfts.d.mts.map +1 -1
  49. package/dist/node/lib/getNftCollectionNfts.d.ts +8 -1
  50. package/dist/node/lib/getNftCollectionNfts.d.ts.map +1 -1
  51. package/dist/node/lib/getProvider.d.cts +3 -0
  52. package/dist/node/lib/getProvider.d.cts.map +1 -0
  53. package/dist/node/lib/getProvider.d.mts +3 -0
  54. package/dist/node/lib/getProvider.d.mts.map +1 -0
  55. package/dist/node/lib/getProvider.d.ts +3 -0
  56. package/dist/node/lib/getProvider.d.ts.map +1 -0
  57. package/package.json +12 -12
  58. package/src/Witness.ts +3 -3
  59. package/src/lib/getNftCollectionCount.ts +5 -18
  60. package/src/lib/getNftCollectionMetadata.ts +38 -18
  61. package/src/lib/getNftCollectionNfts.ts +62 -31
  62. package/src/lib/getProvider.ts +17 -0
@@ -1,12 +1,19 @@
1
- import { Auth, SDK } from '@infura/sdk'
1
+ import { Interface } from '@ethersproject/abi'
2
2
  import { NftCollectionMetadata } from '@xyo-network/crypto-nft-collection-payload-plugin'
3
- import { toTokenType } from '@xyo-network/crypto-nft-payload-plugin'
3
+ import { ERC721Enumerable__factory, ERC1155__factory } from '@xyo-network/open-zeppelin-typechain'
4
+ import { constants } from 'ethers'
4
5
 
6
+ import { getProviderFromEnv } from './getProvider'
5
7
  import { nonEvaluableContractAddresses } from './nonEvaluableContractAddresses'
6
8
 
7
- type ContractAddressOptions = {
8
- contractAddress: string
9
- cursor?: string
9
+ export function getInterfaceID(contractInterface: Interface) {
10
+ let interfaceID = constants.Zero
11
+ const functions: string[] = Object.keys(contractInterface.functions)
12
+ for (let i = 0; i < functions.length; i++) {
13
+ interfaceID = interfaceID.xor(contractInterface.getSighash(functions[i]))
14
+ }
15
+
16
+ return interfaceID.toHexString()
10
17
  }
11
18
 
12
19
  export const getNftCollectionMetadata = async (
@@ -18,21 +25,34 @@ export const getNftCollectionMetadata = async (
18
25
  * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on
19
26
  */
20
27
  chainId: number,
21
- // /**
22
- // * The ethers provider to use to search for NFTs
23
- // */
24
- // provider: ExternalProvider | JsonRpcFetchFunc,
25
- /**
26
- * The private key of the wallet to use to search for NFTs
27
- */
28
- privateKey: string,
29
28
  ): Promise<Omit<NftCollectionMetadata, 'total'>> => {
30
29
  if (nonEvaluableContractAddresses.includes(contractAddress.toUpperCase())) {
31
30
  throw new Error(`Unable to evaluate collection with contractAddress: ${contractAddress}`)
32
31
  }
33
- const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))
34
- const opts: ContractAddressOptions = { contractAddress }
35
- const { name, symbol, tokenType } = await sdk.api.getContractMetadata(opts)
36
- const type = toTokenType(tokenType)
37
- return { address: contractAddress, chainId, name, symbol, type }
32
+ const provider = getProviderFromEnv(chainId)
33
+ const contract721 = ERC721Enumerable__factory.connect(contractAddress, provider)
34
+ const contract1155 = ERC1155__factory.connect(contractAddress, provider)
35
+ let name: string = ''
36
+ try {
37
+ name = await contract721.name()
38
+ } catch (ex) {
39
+ const error = ex as Error
40
+ console.log(`name: ${error.message}`)
41
+ }
42
+ let symbol: string = ''
43
+ try {
44
+ symbol = await contract721.symbol()
45
+ } catch (ex) {
46
+ const error = ex as Error
47
+ console.log(`symbol: ${error.message}`)
48
+ }
49
+ let is1155: boolean = false
50
+ try {
51
+ is1155 = await contract1155.supportsInterface(getInterfaceID(ERC1155__factory.getInterface(ERC1155__factory.abi)))
52
+ } catch (ex) {
53
+ const error = ex as Error
54
+ console.log(`is1155: ${error.message}`)
55
+ is1155 = false
56
+ }
57
+ return { address: contractAddress, chainId, name, symbol, type: is1155 ? 'ERC1155' : 'ERC721' }
38
58
  }
@@ -1,11 +1,34 @@
1
- import { Auth, SDK } from '@infura/sdk'
2
- import { NftInfo, NftInfoFields, NftSchema, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'
1
+ import { AxiosJson } from '@xyo-network/axios'
2
+ import { NftInfo, NftMetadata, NftSchema, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'
3
+ import { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'
3
4
 
5
+ import { getNftCollectionMetadata } from './getNftCollectionMetadata'
6
+ import { getProviderFromEnv } from './getProvider'
4
7
  import { nonEvaluableContractAddresses } from './nonEvaluableContractAddresses'
5
8
 
6
- type ContractAddressOptions = {
7
- contractAddress: string
8
- cursor?: string
9
+ const ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'
10
+
11
+ /**
12
+ * Returns the equivalent IPFS gateway URL for the supplied URL.
13
+ * @param urlToCheck The URL to check
14
+ * @returns If the supplied URL is an IPFS URL, it converts the URL to the
15
+ * equivalent IPFS gateway URL. Otherwise, returns the original URL.
16
+ */
17
+ export const checkIpfsUrl = (urlToCheck: string, ipfsGateway: string) => {
18
+ const url = new URL(urlToCheck)
19
+ let protocol = url.protocol
20
+ let host = url.host
21
+ let path = url.pathname
22
+ const query = url.search
23
+ if (protocol === 'ipfs:') {
24
+ protocol = 'https:'
25
+ host = ipfsGateway
26
+ path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`
27
+ const root = `${protocol}//${host}/${path}`
28
+ return query?.length > 0 ? `${root}?${query}` : root
29
+ } else {
30
+ return urlToCheck
31
+ }
9
32
  }
10
33
 
11
34
  export const getNftCollectionNfts = async (
@@ -17,14 +40,6 @@ export const getNftCollectionNfts = async (
17
40
  * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on
18
41
  */
19
42
  chainId: number,
20
- // /**
21
- // * The ethers provider to use to search for NFTs
22
- // */
23
- // provider: ExternalProvider | JsonRpcFetchFunc,
24
- /**
25
- * The private key of the wallet to use to search for NFTs
26
- */
27
- privateKey: string,
28
43
  /**
29
44
  * The maximum number of NFTs to return. Configurable to prevent
30
45
  * large wallets from exhausting Infura API credits. Ideally a
@@ -35,22 +50,38 @@ export const getNftCollectionNfts = async (
35
50
  if (nonEvaluableContractAddresses.includes(contractAddress.toUpperCase())) {
36
51
  throw new Error(`Unable to evaluate collection with contractAddress: ${contractAddress}`)
37
52
  }
38
- const sdk = new SDK(new Auth({ chainId, privateKey, projectId: process.env.INFURA_PROJECT_ID, secretId: process.env.INFURA_PROJECT_SECRET }))
39
- const nfts: NftInfoFields[] = []
40
- let cursor: string | undefined = undefined
41
- do {
42
- const opts: ContractAddressOptions = { contractAddress, cursor }
43
- const { cursor: nextCursor, pageSize, total, assets } = await sdk.api.getNFTsForCollection(opts)
44
- const batch: NftInfoFields[] = assets.slice(0, Math.min(pageSize, total - nfts.length)).map((asset) => {
45
- const { contract: address, type: tokenType, ...rest } = asset
46
- const type = toTokenType(tokenType)
47
- return { address, chainId, type, ...rest }
48
- })
49
- nfts.push(...batch)
50
- cursor = nextCursor
51
- if (nfts.length >= total || !cursor) break
52
- } while (nfts.length < maxNfts)
53
- return nfts.map((nft) => {
54
- return { ...nft, schema: NftSchema }
55
- })
53
+ const axios = new AxiosJson({ timeout: 2000 })
54
+ const provider = getProviderFromEnv(chainId)
55
+ const enumerable = ERC721Enumerable__factory.connect(contractAddress, provider)
56
+ const storage = ERC721URIStorage__factory.connect(contractAddress, provider)
57
+ const supply1155 = ERC1155Supply__factory.connect(contractAddress, provider)
58
+ const result: NftInfo[] = []
59
+ const { type: nftType } = await getNftCollectionMetadata(contractAddress, chainId)
60
+
61
+ for (let i = 0; i < maxNfts; i++) {
62
+ const tokenId = (await enumerable.tokenByIndex(i)).toHexString()
63
+ const supply = nftType === toTokenType('ERC11155') ? (await supply1155.totalSupply(tokenId)).toHexString() : '0x01'
64
+ const metadataUri = await storage.tokenURI(tokenId)
65
+ const checkedMetaDataUri = checkIpfsUrl(metadataUri, ipfsGateway)
66
+ let metadata: NftMetadata | undefined = undefined
67
+ try {
68
+ metadata = (await axios.get(checkedMetaDataUri)).data
69
+ } catch (ex) {
70
+ const error = ex as Error
71
+ console.error(error.message)
72
+ }
73
+
74
+ const info: NftInfo = {
75
+ address: contractAddress,
76
+ chainId,
77
+ metadata,
78
+ metadataUri,
79
+ schema: NftSchema,
80
+ supply,
81
+ tokenId,
82
+ type: nftType,
83
+ }
84
+ result.push(info)
85
+ }
86
+ return result
56
87
  }
@@ -0,0 +1,17 @@
1
+ import { InfuraProvider, WebSocketProvider } from '@ethersproject/providers'
2
+
3
+ export const getProviderFromEnv = (chainId: string | number = 'homestead') => {
4
+ const infuraWssUri = process.env.INFURA_WSS_URI
5
+ const infuraProvider = new InfuraProvider('homestead', {
6
+ projectId: process.env.INFURA_PROJECT_ID,
7
+ projectSecret: process.env.INFURA_PROJECT_SECRET,
8
+ })
9
+
10
+ const infuraWebsocketProvider = infuraWssUri ? new WebSocketProvider(infuraWssUri, chainId) : undefined
11
+
12
+ const quickNodeUri = process.env.QUICKNODE_WSS_URI
13
+ const quickNodeProvider = quickNodeUri ? new WebSocketProvider(quickNodeUri, chainId) : undefined
14
+
15
+ const provider = infuraWebsocketProvider ?? infuraProvider ?? infuraWebsocketProvider ?? quickNodeProvider ?? infuraProvider
16
+ return provider
17
+ }