@xyo-network/crypto-nft-collection-witness-plugin 2.82.0-rc.1 → 2.82.1
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/dist/browser/index.cjs +2 -8
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.js +2 -8
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/lib/getNftCollectionNfts.d.cts.map +1 -1
- package/dist/browser/lib/getNftCollectionNfts.d.mts.map +1 -1
- package/dist/browser/lib/getNftCollectionNfts.d.ts.map +1 -1
- package/dist/node/index.js +2 -8
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +2 -8
- package/dist/node/index.mjs.map +1 -1
- package/dist/node/lib/getNftCollectionNfts.d.cts.map +1 -1
- package/dist/node/lib/getNftCollectionNfts.d.mts.map +1 -1
- package/dist/node/lib/getNftCollectionNfts.d.ts.map +1 -1
- package/package.json +20 -21
- package/src/lib/getNftCollectionNfts.ts +5 -10
package/dist/browser/index.cjs
CHANGED
|
@@ -124,8 +124,8 @@ var contractHasFunctions = async (provider, address, contractInterface, function
|
|
|
124
124
|
|
|
125
125
|
// src/lib/getNftCollectionNfts.ts
|
|
126
126
|
var import_axios = require("@xylabs/axios");
|
|
127
|
-
var import_bignumber = require("@xylabs/bignumber");
|
|
128
127
|
var import_exists = require("@xylabs/exists");
|
|
128
|
+
var import_hex = require("@xylabs/hex");
|
|
129
129
|
var import_blockchain_erc1822_witness = require("@xyo-network/blockchain-erc1822-witness");
|
|
130
130
|
var import_blockchain_erc1967_witness = require("@xyo-network/blockchain-erc1967-witness");
|
|
131
131
|
var import_crypto_nft_payload_plugin = require("@xyo-network/crypto-nft-payload-plugin");
|
|
@@ -167,12 +167,6 @@ var tryCall = async (func, name) => {
|
|
|
167
167
|
|
|
168
168
|
// src/lib/getNftCollectionNfts.ts
|
|
169
169
|
var ipfsGateway = "5d7b6582.beta.decentralnetworkservices.com";
|
|
170
|
-
var hexBytesOnlyOnly = (value) => {
|
|
171
|
-
return value.startsWith("0x") ? value.substring(2) : value;
|
|
172
|
-
};
|
|
173
|
-
var isHexZero = (value) => {
|
|
174
|
-
return value === void 0 ? true : new import_bignumber.BigNumber(hexBytesOnlyOnly(value), "hex").eqn(0);
|
|
175
|
-
};
|
|
176
170
|
function range(size, startAt = 0) {
|
|
177
171
|
return [...Array(size).keys()].map((i) => i + startAt);
|
|
178
172
|
}
|
|
@@ -181,7 +175,7 @@ var getNftCollectionNfts = async (contractAddress, provider, types, maxNfts = 10
|
|
|
181
175
|
const block = await provider.getBlockNumber();
|
|
182
176
|
const erc1967Status = await (0, import_blockchain_erc1967_witness.getErc1967Status)(provider, contractAddress, block);
|
|
183
177
|
const erc1822Status = await (0, import_blockchain_erc1822_witness.getErc1822Status)(provider, contractAddress, block);
|
|
184
|
-
const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
178
|
+
const implementation = !erc1967Status.slots.implementation || (0, import_hex.isHexZero)(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
185
179
|
const axios = new import_axios.AxiosJson({ timeout: 2e3 });
|
|
186
180
|
const enumerable = import_open_zeppelin_typechain2.ERC721Enumerable__factory.connect(implementation, provider);
|
|
187
181
|
const storage = import_open_zeppelin_typechain2.ERC721URIStorage__factory.connect(implementation, provider);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts"],"sourcesContent":["import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { BigNumber as XyBigNumber } from '@xylabs/bignumber'\nimport { exists } from '@xylabs/exists'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nconst hexBytesOnlyOnly = (value: string) => {\n return value.startsWith('0x') ? value.substring(2) : value\n}\n\nconst isHexZero = (value?: string) => {\n return value === undefined ? true : new XyBigNumber(hexBytesOnlyOnly(value), 'hex').eqn(0)\n}\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n"],"mappings":"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","names":["import_crypto_nft_payload_plugin","import_assert","import_open_zeppelin_typechain","import_witness_blockchain_abstract","attributes","p","import_open_zeppelin_typechain","XyBigNumber"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts"],"sourcesContent":["import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { exists } from '@xylabs/exists'\nimport { isHexZero } from '@xylabs/hex'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation =\n !erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation)\n ? erc1822Status.implementation\n : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,oCAA0B;AAC1B,2BAAiC;AACjC,+BAAuE;;;ACFvE,IAAAC,iBAAyB;AACzB,yBAA2B;AAC3B,kBAA8B;AAC9B,kDAOO;AACP,IAAAC,kCAA0C;AAC1C,IAAAC,sCAAmE;;;ACV5D,IAAM,qCAAqC,CAAI,UAAgC;AACpF,QAAM,eAAgC,CAAC;AAEvC,QAAM,QAAQ,CAAC,SAAS;AACtB,eAAW,YAAY,MAAM;AAC3B,UAAI,OAAO,UAAU,eAAe,KAAK,MAAM,QAAQ,GAAG;AACxD,cAAM,QAAQ,KAAK,QAAmB;AACtC,YAAI,UAAU,UAAa,UAAU,MAAM;AACzC,gBAAM,cAAc,MAAM,SAAS;AACnC,cAAI,CAAC,aAAa,QAAQ,GAAG;AAC3B,yBAAa,QAAQ,IAAI,EAAE,CAAC,WAAW,GAAG,EAAE;AAAA,UAC9C,WAAW,CAAC,aAAa,QAAQ,EAAG,WAAW,GAAG;AAChD;AAAC,YAAC,aAAa,QAAQ,EAA6B,WAAW,IAAI;AAAA,UACrE,OAAO;AACL;AAAC,YAAC,aAAa,QAAQ,EAA6B,WAAW,KAAK;AAAA,UACtE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;AChBO,IAAM,yCAAyC,CAAC,GAAW,MAA8C;AAE9G,QAAM,OAAO,IAAI;AAGjB,QAAM,WAAW,IAAI,KAAK,IAAI;AAG9B,QAAM,SAAS,KAAK,KAAK,QAAQ;AAEjC,SAAO,EAAE,MAAM,GAAG,QAAQ,SAAS;AACrC;;;ACZO,IAAM,0BAA0B,CAAC,SAAgD;AACtF,QAAM,SAAS,KACZ,IAAI,CAAC,QAAQ,KAAK,UAAU,UAA+C,EAC3E,OAAO,CAAC,MAAkC,MAAM,MAAS,EACzD,IAAI,CAACC,gBAAe;AACnB,WAAO,OAAO,YAAYA,YAAW,IAAI,CAAC,cAAc,CAAC,UAAU,YAAY,UAAU,KAAK,CAAC,CAAC;AAAA,EAClG,CAAC;AACH,QAAM,eAAe,mCAAmC,MAAM;AAC9D,QAAM,IAAI,KAAK;AACf,QAAM,aAAa,OAAO;AAAA,IACxB,OAAO,QAAQ,YAAY,EACxB,OAAO,CAAC,MAAmC,EAAE,CAAC,MAAM,MAAS,EAC7D,IAAI,CAAC,CAAC,OAAO,OAAO,MAAM;AACzB,YAAM,aAAa,OAAO,OAAO,OAAO,EAAE,OAAO,CAAC,MAAM,SAAS,OAAO,MAAM,CAAC;AAC/E,YAAM,EAAE,EAAE,IAAI,uCAAuC,KAAK,QAAQ,aAAa,CAAC;AAChF,YAAM,SAAS,OAAO;AAAA,QACpB,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,eAAe,MAAM;AACxD,gBAAM,EAAE,GAAAC,GAAE,IAAI,uCAAuC,GAAG,kBAAkB,CAAC;AAC3E,gBAAM,UAA2B,EAAE,UAAU,EAAE,GAAAA,GAAE,GAAG,OAAO,gBAAgB;AAC3E,iBAAO,CAAC,OAAO,OAAO;AAAA,QACxB,CAAC;AAAA,MACH;AACA,aAAO,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,GAAG,OAAO,WAAW,GAAG,OAAO,CAAC;AAAA,IAC5E,CAAC;AAAA,EACL;AACA,SAAO,EAAE,UAAU,EAAE,WAAW,EAAE;AACpC;;;ACjCA,oBAAyB;AAGlB,IAAM,uBAAuB,OAAO,UAAoB,SAAiB,mBAA8B,kBAA4B;AACxI,MAAI;AACF,UAAM,WAAW,MAAM,SAAS,QAAQ,SAAS,QAAQ;AACzD,aAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,YAAM,eAAW,wBAAS,kBAAkB,YAAY,cAAc,CAAC,CAAC,GAAG,UAAU,iCAAiC;AACtH,UAAI,CAAC,SAAS,SAAS,SAAS,UAAU,CAAC,CAAC,GAAG;AAC7C,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,SAAS,IAAI;AACX,UAAM,QAAQ;AACd,YAAQ,IAAI,KAAK;AACjB,WAAO;AAAA,EACT;AACF;;;ACnBA,mBAA0B;AAC1B,oBAAuB;AACvB,iBAA0B;AAC1B,wCAAiC;AACjC,wCAAiC;AACjC,uCAAwE;AACxE,IAAAC,kCAA6F;AAC7F,yCAA6B;;;ACN7B,qCAA4D;AAKrD,IAAM,YAAY,OAAO,UAAoB,YAAoB;AACtE,SAAO,MAAM,qBAAqB,UAAU,SAAS,0DAA2B,gBAAgB,GAAG,CAAC,KAAK,CAAC;AAC5G;AAEO,IAAM,WAAW,OAAO,UAAoB,YAAoB;AACrE,SAAO,MAAM,qBAAqB,UAAU,SAAS,+CAAgB,gBAAgB,GAAG,CAAC,QAAQ,UAAU,UAAU,CAAC;AACxH;AAEO,IAAM,aAAa,OAAO,UAAoB,YAAoB;AACvE,QAAM,CAAC,QAAQ,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,SAAS,UAAU,OAAO,GAAG,UAAU,UAAU,OAAO,CAAC,CAAC;AACvG,QAAM,SAAsB,CAAC;AAC7B,MAAI,QAAQ;AACV,WAAO,KAAK,QAAQ;AAAA,EACtB;AACA,MAAI,SAAS;AACX,WAAO,KAAK,SAAS;AAAA,EACvB;AACA,SAAO;AACT;;;ACxBO,IAAM,UAAU,OAAU,MAAwB,SAA0C;AACjG,MAAI;AACF,WAAO,MAAM,KAAK;AAAA,EACpB,SAAS,IAAI;AACX,QAAI,MAAM;AACR,YAAM,QAAQ;AACd,cAAQ,IAAI,mBAAmB,IAAI,MAAM,MAAM,OAAO,EAAE;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AACF;;;AFGA,IAAM,cAAc;AAEpB,SAAS,MAAM,MAAc,UAAkB,GAA0B;AACvE,SAAO,CAAC,GAAG,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,IAAI,OAAO;AACvD;AAEO,IAAM,uBAAuB,OAIlC,iBAIA,UACA,OAMA,UAAU,QACa;AACvB,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,eAAe;AAG5C,UAAM,gBAAgB,UAAM,oDAAiB,UAAU,iBAAiB,KAAK;AAG7E,UAAM,gBAAgB,UAAM,oDAAiB,UAAU,iBAAiB,KAAK;AAE7E,UAAM,iBACJ,CAAC,cAAc,MAAM,sBAAkB,sBAAU,cAAc,MAAM,cAAc,IAC/E,cAAc,iBACd,cAAc;AAEpB,UAAM,QAAQ,IAAI,uBAAU,EAAE,SAAS,IAAK,CAAC;AAC7C,UAAM,aAAa,0DAA0B,QAAQ,gBAAgB,QAAQ;AAC7E,UAAM,UAAU,0DAA0B,QAAQ,gBAAgB,QAAQ;AAC1E,UAAM,aAAa,uDAAuB,QAAQ,gBAAgB,QAAQ;AAC1E,UAAM,aAAa,SAAU,MAAM,WAAW,UAAU,cAAc;AAEtE,UAAM,eAAe,MAAM,OAAO;AAElC,UAAM,UACJ,MAAM,QAAQ;AAAA,MACZ,aAAa,IAAI,OAAO,QAAQ,MAAM;AACpC,cAAM,UAAW,MAAM,QAAQ,YAAY,MAAM,WAAW,aAAa,GAAG,EAAE,UAAU,MAAM,CAAC,CAAC,KAAM,OAAO,CAAC;AAC9G,YAAI,YAAY,QAAW;AACzB,gBAAM,SAAS,WAAW,aAAS,8CAAY,SAAS,CAAC,IACpD,MAAM,QAAQ,YAAY,MAAM,WAAW,sBAAsB,EAAE,OAAO,CAAC,KAAM,SAClF;AACJ,gBAAM,cAAc,MAAM,QAAQ,YAAY,MAAM,QAAQ,SAAS,SAAS,EAAE,UAAU,MAAM,CAAC,CAAC;AAClG,gBAAM,qBAAqB,kBAAc,iDAAa,aAAa,WAAW,IAAI;AAClF,cAAI,WAAoC;AACxC,cAAI,uBAAuB,QAAW;AACpC,gBAAI;AACF,0BAAY,MAAM,MAAM,IAAI,kBAAkB,GAAG;AAAA,YACnD,SAAS,IAAI;AACX,oBAAM,QAAQ;AACd,sBAAQ,MAAM,wBAAwB,MAAM,OAAO,EAAE;AAAA,YACvD;AAAA,UACF;AAEA,gBAAM,OAAgB;AAAA,YACpB,SAAS;AAAA,YACT,SAAS,QAAQ,MAAM,SAAS,WAAW,GAAG,OAAO;AAAA,YACrD;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,YACR,QAAQ,KAAK,OAAO,SAAS,EAAE,CAAC;AAAA,YAChC,SAAS,KAAK,QAAQ,SAAS,EAAE,CAAC;AAAA,YAClC,MAAM,WAAW,GAAG,CAAC;AAAA,YACrB,OAAO;AAAA,UACT;AACA,cAAI,mBAAmB,iBAAiB;AACtC,iBAAK,iBAAiB;AAAA,UACxB;AACA,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH,GACA,OAAO,oBAAM;AACf,WAAO;AAAA,EACT,SAAS,IAAI;AACX,UAAM,QAAQ;AACd,YAAQ,MAAM,iCAAiC,MAAM,IAAI,KAAK,MAAM,OAAO,EAAE;AAC7E,YAAQ,IAAI,MAAM,KAAK;AACvB,WAAO,CAAC;AAAA,EACV;AACF;;;ALtFA,IAAM,iBAAiB;AAOvB,IAAM,OAAO,QAAQ,QAAQ;AAI7B,SAAS,cAAiB,SAAkC,QAAkB;AAC5E,MAAI,UAAU,QAAQ,WAAW,YAAY;AAC3C,UAAM,QAAQ;AAAA,EAChB;AACA,SAAO,QAAQ,WAAW,cAAc,QAAQ,QAAQ;AAC1D;AAEO,IAAM,6BAAN,cAEG,8DAAiF;AAAA,EACzF,OAAgB,gBAAgB,CAAC,4EAAgC;AAAA,EAEjE,MAAyB,eAAe,UAAsE;AAC5G,UAAM,KAAK,QAAQ,OAAO;AAC1B,UAAM,KAAK,aAAa;AACxB,UAAM,UAAU,UAAU,OAAO,uEAA2B,KAAK,CAAC;AAClE,UAAM,eAAe,MAAM,QAAQ;AAAA,MACjC,QAAQ,IAAgC,OAAO,UAAU;AACvD,cAAM,cAAU,yBAAS,OAAO,WAAW,KAAK,OAAO,SAAS,4BAA4B;AAC5F,cAAM,WAAW,MAAM,KAAK,YAAY,MAAM,IAAI;AAClD,cAAM,cAAU;AAAA,UACd,8BAAW,UAAM,yBAAS,OAAO,WAAW,KAAK,OAAO,SAAS,4BAA4B,CAAC;AAAA,UAC9F;AAAA,QACF,EAAE,SAAS;AAEX,cAAM,mBAAmB,0DAA0B,QAAQ,SAAS,QAAQ;AAE5E,cAAM,UAAU,OAAO,WAAW;AAClC,cAAM,CAAC,MAAM,QAAQ,OAAO,cAAc,gBAAgB,IAAI,MAAM,QAAQ,WAAW;AAAA,UACrF,MAAM,iBAAiB,KAAK;AAAA,UAC5B,MAAM,iBAAiB,OAAO;AAAA,UAC9B,MAAM,iBAAiB,YAAY;AAAA,UACnC,MAAM,WAAW,UAAU,OAAO;AAAA,UAClC,MAAM,KAAK,eAAe;AAAA,QAC5B,CAAC;AACD,cAAM,QAAQ,cAAc,cAAc,IAAI;AAC9C,cAAM,OAAO,MAAM,qBAAqB,SAAS,UAAU,OAAO,OAAO;AACzE,cAAM,UAAU,wBAAwB,IAAI;AAC5C,cAAM,YAAY,cAAc,gBAAgB;AAChD,cAAM,CAAC,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA;AAAA,UAElC,QAAQ,IAAI,KAAK,IAAI,CAAC,QAAQ,0BAAc,UAAU,GAAG,CAAC,CAAC;AAAA;AAAA,UAE3D,YAAY,UAAU,OAAO,IAAI,IAAI;AAAA,QACvC,CAAC;AACD,cAAM,UAA6B;AAAA,UACjC;AAAA,UACA;AAAA,UACA;AAAA,UACA,MAAM,cAAc,MAAM,IAAI;AAAA,UAC9B,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,cAAc,QAAQ,IAAI;AAAA,UAClC,OAAO,OAAO,cAAc,OAAO,IAAI,CAAC;AAAA,UACxC,MAAM,MAAM,GAAG,CAAC;AAAA,UAChB;AAAA,QACF;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;;;ADrFO,IAAM,mCAAmC,UAC9C;AAAA,EACE,EAAE,UAAU,EAAE,CAAC,2CAAS,GAAG,EAAE,GAAG,QAAQ,sCAAiB;AAAA,EACzD;AAAA,IACE,SAAS,OAAO,WAAW;AACzB,YAAM,SAAS,MAAM,2BAA2B,OAAO,MAAM;AAC7D,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ADPF,IAAO,cAAQ;","names":["import_crypto_nft_payload_plugin","import_assert","import_open_zeppelin_typechain","import_witness_blockchain_abstract","attributes","p","import_open_zeppelin_typechain"]}
|
package/dist/browser/index.js
CHANGED
|
@@ -94,8 +94,8 @@ var contractHasFunctions = async (provider, address, contractInterface, function
|
|
|
94
94
|
|
|
95
95
|
// src/lib/getNftCollectionNfts.ts
|
|
96
96
|
import { AxiosJson } from "@xylabs/axios";
|
|
97
|
-
import { BigNumber as XyBigNumber } from "@xylabs/bignumber";
|
|
98
97
|
import { exists } from "@xylabs/exists";
|
|
98
|
+
import { isHexZero } from "@xylabs/hex";
|
|
99
99
|
import { getErc1822Status } from "@xyo-network/blockchain-erc1822-witness";
|
|
100
100
|
import { getErc1967Status } from "@xyo-network/blockchain-erc1967-witness";
|
|
101
101
|
import { NftSchema, toTokenType } from "@xyo-network/crypto-nft-payload-plugin";
|
|
@@ -137,12 +137,6 @@ var tryCall = async (func, name) => {
|
|
|
137
137
|
|
|
138
138
|
// src/lib/getNftCollectionNfts.ts
|
|
139
139
|
var ipfsGateway = "5d7b6582.beta.decentralnetworkservices.com";
|
|
140
|
-
var hexBytesOnlyOnly = (value) => {
|
|
141
|
-
return value.startsWith("0x") ? value.substring(2) : value;
|
|
142
|
-
};
|
|
143
|
-
var isHexZero = (value) => {
|
|
144
|
-
return value === void 0 ? true : new XyBigNumber(hexBytesOnlyOnly(value), "hex").eqn(0);
|
|
145
|
-
};
|
|
146
140
|
function range(size, startAt = 0) {
|
|
147
141
|
return [...Array(size).keys()].map((i) => i + startAt);
|
|
148
142
|
}
|
|
@@ -151,7 +145,7 @@ var getNftCollectionNfts = async (contractAddress, provider, types, maxNfts = 10
|
|
|
151
145
|
const block = await provider.getBlockNumber();
|
|
152
146
|
const erc1967Status = await getErc1967Status(provider, contractAddress, block);
|
|
153
147
|
const erc1822Status = await getErc1822Status(provider, contractAddress, block);
|
|
154
|
-
const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
148
|
+
const implementation = !erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
155
149
|
const axios = new AxiosJson({ timeout: 2e3 });
|
|
156
150
|
const enumerable = ERC721Enumerable__factory.connect(implementation, provider);
|
|
157
151
|
const storage = ERC721URIStorage__factory.connect(implementation, provider);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { BigNumber as XyBigNumber } from '@xylabs/bignumber'\nimport { exists } from '@xylabs/exists'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nconst hexBytesOnlyOnly = (value: string) => {\n return value.startsWith('0x') ? value.substring(2) : value\n}\n\nconst isHexZero = (value?: string) => {\n return value === undefined ? true : new XyBigNumber(hexBytesOnlyOnly(value), 'hex').eqn(0)\n}\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n","import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ERC721Enumerable__factory","attributes","p","assertEx","ERC721Enumerable__factory","NftSchema"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { exists } from '@xylabs/exists'\nimport { isHexZero } from '@xylabs/hex'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation =\n !erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation)\n ? erc1822Status.implementation\n : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n","import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ERC721Enumerable__factory","attributes","p","assertEx","ERC721Enumerable__factory","NftSchema"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAWjC,eAAO,MAAM,oBAAoB,oBAId,MAAM,YAIb,QAAQ,UACV,SAAS,EAAE,uBAOlB,QAAQ,OAAO,EAAE,CAqEnB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAWjC,eAAO,MAAM,oBAAoB,oBAId,MAAM,YAIb,QAAQ,UACV,SAAS,EAAE,uBAOlB,QAAQ,OAAO,EAAE,CAqEnB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAWjC,eAAO,MAAM,oBAAoB,oBAId,MAAM,YAIb,QAAQ,UACV,SAAS,EAAE,uBAOlB,QAAQ,OAAO,EAAE,CAqEnB,CAAA"}
|
package/dist/node/index.js
CHANGED
|
@@ -128,8 +128,8 @@ var contractHasFunctions = async (provider, address, contractInterface, function
|
|
|
128
128
|
|
|
129
129
|
// src/lib/getNftCollectionNfts.ts
|
|
130
130
|
var import_axios = require("@xylabs/axios");
|
|
131
|
-
var import_bignumber = require("@xylabs/bignumber");
|
|
132
131
|
var import_exists = require("@xylabs/exists");
|
|
132
|
+
var import_hex = require("@xylabs/hex");
|
|
133
133
|
var import_blockchain_erc1822_witness = require("@xyo-network/blockchain-erc1822-witness");
|
|
134
134
|
var import_blockchain_erc1967_witness = require("@xyo-network/blockchain-erc1967-witness");
|
|
135
135
|
var import_crypto_nft_payload_plugin = require("@xyo-network/crypto-nft-payload-plugin");
|
|
@@ -171,12 +171,6 @@ var tryCall = async (func, name) => {
|
|
|
171
171
|
|
|
172
172
|
// src/lib/getNftCollectionNfts.ts
|
|
173
173
|
var ipfsGateway = "5d7b6582.beta.decentralnetworkservices.com";
|
|
174
|
-
var hexBytesOnlyOnly = (value) => {
|
|
175
|
-
return value.startsWith("0x") ? value.substring(2) : value;
|
|
176
|
-
};
|
|
177
|
-
var isHexZero = (value) => {
|
|
178
|
-
return value === void 0 ? true : new import_bignumber.BigNumber(hexBytesOnlyOnly(value), "hex").eqn(0);
|
|
179
|
-
};
|
|
180
174
|
function range(size, startAt = 0) {
|
|
181
175
|
return [...Array(size).keys()].map((i) => i + startAt);
|
|
182
176
|
}
|
|
@@ -185,7 +179,7 @@ var getNftCollectionNfts = async (contractAddress, provider, types, maxNfts = 10
|
|
|
185
179
|
const block = await provider.getBlockNumber();
|
|
186
180
|
const erc1967Status = await (0, import_blockchain_erc1967_witness.getErc1967Status)(provider, contractAddress, block);
|
|
187
181
|
const erc1822Status = await (0, import_blockchain_erc1822_witness.getErc1822Status)(provider, contractAddress, block);
|
|
188
|
-
const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
182
|
+
const implementation = !erc1967Status.slots.implementation || (0, import_hex.isHexZero)(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
189
183
|
const axios = new import_axios.AxiosJson({ timeout: 2e3 });
|
|
190
184
|
const enumerable = import_open_zeppelin_typechain2.ERC721Enumerable__factory.connect(implementation, provider);
|
|
191
185
|
const storage = import_open_zeppelin_typechain2.ERC721URIStorage__factory.connect(implementation, provider);
|
package/dist/node/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts"],"sourcesContent":["import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { BigNumber as XyBigNumber } from '@xylabs/bignumber'\nimport { exists } from '@xylabs/exists'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nconst hexBytesOnlyOnly = (value: string) => {\n return value.startsWith('0x') ? value.substring(2) : value\n}\n\nconst isHexZero = (value?: string) => {\n return value === undefined ? true : new XyBigNumber(hexBytesOnlyOnly(value), 'hex').eqn(0)\n}\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n"],"mappings":"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","names":["import_crypto_nft_payload_plugin","import_assert","import_open_zeppelin_typechain","import_witness_blockchain_abstract","attributes","p","import_open_zeppelin_typechain","XyBigNumber"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts"],"sourcesContent":["import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { exists } from '@xylabs/exists'\nimport { isHexZero } from '@xylabs/hex'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation =\n !erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation)\n ? erc1822Status.implementation\n : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n"],"mappings":"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","names":["import_crypto_nft_payload_plugin","import_assert","import_open_zeppelin_typechain","import_witness_blockchain_abstract","attributes","p","import_open_zeppelin_typechain"]}
|
package/dist/node/index.mjs
CHANGED
|
@@ -98,8 +98,8 @@ var contractHasFunctions = async (provider, address, contractInterface, function
|
|
|
98
98
|
|
|
99
99
|
// src/lib/getNftCollectionNfts.ts
|
|
100
100
|
import { AxiosJson } from "@xylabs/axios";
|
|
101
|
-
import { BigNumber as XyBigNumber } from "@xylabs/bignumber";
|
|
102
101
|
import { exists } from "@xylabs/exists";
|
|
102
|
+
import { isHexZero } from "@xylabs/hex";
|
|
103
103
|
import { getErc1822Status } from "@xyo-network/blockchain-erc1822-witness";
|
|
104
104
|
import { getErc1967Status } from "@xyo-network/blockchain-erc1967-witness";
|
|
105
105
|
import { NftSchema, toTokenType } from "@xyo-network/crypto-nft-payload-plugin";
|
|
@@ -141,12 +141,6 @@ var tryCall = async (func, name) => {
|
|
|
141
141
|
|
|
142
142
|
// src/lib/getNftCollectionNfts.ts
|
|
143
143
|
var ipfsGateway = "5d7b6582.beta.decentralnetworkservices.com";
|
|
144
|
-
var hexBytesOnlyOnly = (value) => {
|
|
145
|
-
return value.startsWith("0x") ? value.substring(2) : value;
|
|
146
|
-
};
|
|
147
|
-
var isHexZero = (value) => {
|
|
148
|
-
return value === void 0 ? true : new XyBigNumber(hexBytesOnlyOnly(value), "hex").eqn(0);
|
|
149
|
-
};
|
|
150
144
|
function range(size, startAt = 0) {
|
|
151
145
|
return [...Array(size).keys()].map((i) => i + startAt);
|
|
152
146
|
}
|
|
@@ -155,7 +149,7 @@ var getNftCollectionNfts = async (contractAddress, provider, types, maxNfts = 10
|
|
|
155
149
|
const block = await provider.getBlockNumber();
|
|
156
150
|
const erc1967Status = await getErc1967Status(provider, contractAddress, block);
|
|
157
151
|
const erc1822Status = await getErc1822Status(provider, contractAddress, block);
|
|
158
|
-
const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
152
|
+
const implementation = !erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation;
|
|
159
153
|
const axios = new AxiosJson({ timeout: 2e3 });
|
|
160
154
|
const enumerable = ERC721Enumerable__factory.connect(implementation, provider);
|
|
161
155
|
const storage = ERC721URIStorage__factory.connect(implementation, provider);
|
package/dist/node/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { BigNumber as XyBigNumber } from '@xylabs/bignumber'\nimport { exists } from '@xylabs/exists'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nconst hexBytesOnlyOnly = (value: string) => {\n return value.startsWith('0x') ? value.substring(2) : value\n}\n\nconst isHexZero = (value?: string) => {\n return value === undefined ? true : new XyBigNumber(hexBytesOnlyOnly(value), 'hex').eqn(0)\n}\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation = isHexZero(erc1967Status.slots.implementation) ? erc1822Status.implementation : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n","import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ERC721Enumerable__factory","attributes","p","assertEx","ERC721Enumerable__factory","NftSchema"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Plugin.ts","../../src/Witness.ts","../../src/lib/collectionMetrics/lib/calculateAllPropertiesDistribution.ts","../../src/lib/collectionMetrics/lib/probabilityDistributions/binomial/calculateBinomialParamsFromProbability.ts","../../src/lib/collectionMetrics/getNftCollectionMetrics.ts","../../src/lib/contractHasFunctions.ts","../../src/lib/getNftCollectionNfts.ts","../../src/lib/tokenTypes.ts","../../src/lib/tryCall.ts","../../src/index.ts"],"sourcesContent":["import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetWitnessPlugin, PayloadSetWitnessPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { CryptoNftCollectionWitness } from './Witness'\n\nexport const CryptoNftCollectionWitnessPlugin = (): PayloadSetWitnessPlugin<CryptoNftCollectionWitness> =>\n createPayloadSetWitnessPlugin<CryptoNftCollectionWitness>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n witness: async (params) => {\n const result = await CryptoNftCollectionWitness.create(params)\n return result\n },\n },\n )\n","import { assertEx } from '@xylabs/assert'\nimport { EthAddress } from '@xylabs/eth-address'\nimport { PayloadHasher } from '@xyo-network/core'\nimport {\n isNftCollectionWitnessQuery,\n NftCollectionInfo,\n NftCollectionSchema,\n NftCollectionWitnessConfig,\n NftCollectionWitnessConfigSchema,\n NftCollectionWitnessQuery,\n} from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { ERC721Enumerable__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { AbstractBlockchainWitness, BlockchainWitnessParams } from '@xyo-network/witness-blockchain-abstract'\n\nimport { getNftCollectionMetrics, getNftCollectionNfts, tokenTypes } from './lib'\n\nexport type CryptoNftCollectionWitnessParams = BlockchainWitnessParams<NftCollectionWitnessConfig>\n\nconst defaultMaxNfts = 100\n\n/**\n * A \"no operation\" Promise to be used\n * when no action is desired but a Promise\n * is required to be returned\n */\nconst NoOp = Promise.resolve()\n\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert: true): T\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: false): T | undefined\nfunction resolvedValue<T>(settled: PromiseSettledResult<T>, assert?: boolean) {\n if (assert && settled.status === 'rejected') {\n throw settled.reason\n }\n return settled.status === 'fulfilled' ? settled.value : undefined\n}\n\nexport class CryptoNftCollectionWitness<\n TParams extends CryptoNftCollectionWitnessParams = CryptoNftCollectionWitnessParams,\n> extends AbstractBlockchainWitness<TParams, NftCollectionWitnessQuery, NftCollectionInfo> {\n static override configSchemas = [NftCollectionWitnessConfigSchema]\n\n protected override async observeHandler(payloads?: NftCollectionWitnessQuery[]): Promise<NftCollectionInfo[]> {\n await this.started('throw')\n await this.getProviders() //make sure cache clears\n const queries = payloads?.filter(isNftCollectionWitnessQuery) ?? []\n const observations = await Promise.all(\n queries.map<Promise<NftCollectionInfo>>(async (query) => {\n const chainId = assertEx(query?.chainId || this.config.chainId, 'params.chainId is required')\n const provider = await this.getProvider(true, true)\n const address = assertEx(\n EthAddress.parse(assertEx(query?.address || this.config.address, 'params.address is required')),\n 'Failed to parse params.address',\n ).toString()\n\n const erc721Enumerable = ERC721Enumerable__factory.connect(address, provider)\n\n const maxNfts = query?.maxNfts || defaultMaxNfts\n const [name, symbol, total, typesSettled, archivistSettled] = await Promise.allSettled([\n await erc721Enumerable.name(),\n await erc721Enumerable.symbol(),\n await erc721Enumerable.totalSupply(),\n await tokenTypes(provider, address),\n await this.writeArchivist(),\n ])\n const types = resolvedValue(typesSettled, true)\n const nfts = await getNftCollectionNfts(address, provider, types, maxNfts)\n const metrics = getNftCollectionMetrics(nfts)\n const archivist = resolvedValue(archivistSettled)\n const [sources] = await Promise.all([\n // Hash all the payloads\n Promise.all(nfts.map((nft) => PayloadHasher.hashAsync(nft))),\n // Insert them into the archivist if we have one\n archivist ? archivist.insert(nfts) : NoOp,\n ])\n const payload: NftCollectionInfo = {\n address,\n chainId,\n metrics,\n name: resolvedValue(name, true),\n schema: NftCollectionSchema,\n sources,\n symbol: resolvedValue(symbol, true),\n total: Number(resolvedValue(total, true)),\n type: types.at(0),\n types,\n }\n return payload\n }),\n )\n return observations.flat()\n }\n}\n","import { Distribution } from './distribution'\n\nexport const calculateAllPropertiesDistribution = <T>(array: T[]): Distribution<T> => {\n const distribution: Distribution<T> = {}\n\n array.forEach((item) => {\n for (const property in item) {\n if (Object.prototype.hasOwnProperty.call(item, property)) {\n const value = item[property as keyof T]\n if (value !== undefined && value !== null) {\n const valueString = value.toString()\n if (!distribution[property]) {\n distribution[property] = { [valueString]: 1 }\n } else if (!distribution[property]![valueString]) {\n ;(distribution[property] as Record<string, number>)[valueString] = 1\n } else {\n ;(distribution[property] as Record<string, number>)[valueString] += 1\n }\n }\n }\n }\n })\n\n return distribution\n}\n","import { BinomialDistributionParameters } from '@xyo-network/crypto-nft-collection-payload-plugin'\n\n/**\n * Calculates the parameters of a binomial distribution given the number of trials and success probability\n * @param n Number of trials\n * @param p Success probability\n * @returns The binomial distribution parameters\n */\nexport const calculateBinomialParamsFromProbability = (n: number, p: number): BinomialDistributionParameters => {\n // Mean (µ)\n const mean = n * p\n\n // Variance (σ^2)\n const variance = n * p * (1 - p)\n\n // Standard Deviation (σ)\n const stdDev = Math.sqrt(variance)\n\n return { mean, p, stdDev, variance }\n}\n","import { NftCollectionMetrics, NftTraitMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin'\nimport { NftInfoFields, OpenSeaNftAttribute } from '@xyo-network/crypto-nft-payload-plugin'\n\nimport { calculateAllPropertiesDistribution, calculateBinomialParamsFromProbability } from './lib'\n\ntype TraitDistributionEntry = [string, { [key: string]: number }]\n\nexport const getNftCollectionMetrics = (nfts: NftInfoFields[]): NftCollectionMetrics => {\n const traits = nfts\n .map((nft) => nft?.metadata?.attributes as OpenSeaNftAttribute[] | undefined)\n .filter((v): v is OpenSeaNftAttribute[] => v !== undefined)\n .map((attributes) => {\n return Object.fromEntries(attributes.map((attribute) => [attribute.trait_type, attribute.value]))\n })\n const distribution = calculateAllPropertiesDistribution(traits)\n const n = nfts.length\n const attributes = Object.fromEntries(\n Object.entries(distribution)\n .filter((v): v is TraitDistributionEntry => v[1] !== undefined)\n .map(([trait, entries]) => {\n const traitCount = Object.values(entries).reduce((prev, curr) => prev + curr, 0)\n const { p } = calculateBinomialParamsFromProbability(nfts.length, traitCount / n)\n const values = Object.fromEntries(\n Object.entries(entries).map(([value, traitValueCount]) => {\n const { p } = calculateBinomialParamsFromProbability(n, traitValueCount / n)\n const metrics: NftTraitMetrics = { binomial: { p }, count: traitValueCount }\n return [value, metrics]\n }),\n )\n return [trait, { metrics: { binomial: { p }, count: traitCount }, values }]\n }),\n )\n return { metadata: { attributes } }\n}\n","import { assertEx } from '@xylabs/assert'\nimport { Interface, Provider } from 'ethers'\n\nexport const contractHasFunctions = async (provider: Provider, address: string, contractInterface: Interface, functionNames: string[]) => {\n try {\n const bytecode = await provider.getCode(address, 'latest')\n for (let i = 0; i < functionNames.length; i++) {\n const selector = assertEx(contractInterface.getFunction(functionNames[i])?.selector, 'Function not found on interface')\n if (!bytecode.includes(selector.substring(2))) {\n return false\n }\n return true\n }\n return false\n } catch (ex) {\n const error = ex as Error\n console.log(error)\n return false\n }\n}\n","import { AxiosJson } from '@xylabs/axios'\nimport { exists } from '@xylabs/exists'\nimport { isHexZero } from '@xylabs/hex'\nimport { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'\nimport { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'\nimport { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721Enumerable__factory, ERC721URIStorage__factory, ERC1155Supply__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { checkIpfsUrl } from '@xyo-network/witness-blockchain-abstract'\nimport { Provider } from 'ethers'\n\nimport { tokenTypes } from './tokenTypes'\nimport { tryCall } from './tryCall'\n\nconst ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'\n\nfunction range(size: number, startAt: number = 0): ReadonlyArray<number> {\n return [...Array(size).keys()].map((i) => i + startAt)\n}\n\nexport const getNftCollectionNfts = async (\n /**\n * The address of the NFT contract to search for\n */\n contractAddress: string,\n /**\n * The chain ID (1 = Ethereum Mainnet, 4 = Rinkeby, etc.) of the chain to search for NFTs on\n */\n provider: Provider,\n types?: TokenType[],\n /**\n * The maximum number of NFTs to return. Configurable to prevent\n * large wallets from exhausting Infura API credits. Ideally a\n * multiple of 100 as that appears to be the default page size.\n */\n maxNfts = 100,\n): Promise<NftInfo[]> => {\n try {\n const block = await provider.getBlockNumber()\n\n //Check if ERC-1967 Upgradeable\n const erc1967Status = await getErc1967Status(provider, contractAddress, block)\n\n //Check if ERC-1822 Upgradeable\n const erc1822Status = await getErc1822Status(provider, contractAddress, block)\n\n const implementation =\n !erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation)\n ? erc1822Status.implementation\n : erc1967Status.implementation\n\n const axios = new AxiosJson({ timeout: 2000 })\n const enumerable = ERC721Enumerable__factory.connect(implementation, provider)\n const storage = ERC721URIStorage__factory.connect(implementation, provider)\n const supply1155 = ERC1155Supply__factory.connect(implementation, provider)\n const finalTypes = types ?? (await tokenTypes(provider, implementation))\n\n const maxNftsArray = range(maxNfts)\n\n const result: NftInfo[] = (\n await Promise.all(\n maxNftsArray.map(async (_value, i) => {\n const tokenId = (await tryCall(async () => await enumerable.tokenByIndex(i, { blockTag: block }))) ?? BigInt(i)\n if (tokenId !== undefined) {\n const supply = finalTypes.includes(toTokenType('ERC1155'))\n ? (await tryCall(async () => await supply1155['totalSupply(uint256)'](tokenId))) ?? '0x01'\n : '0x01'\n const metadataUri = await tryCall(async () => await storage.tokenURI(tokenId, { blockTag: block }))\n const checkedMetaDataUri = metadataUri ? checkIpfsUrl(metadataUri, ipfsGateway) : undefined\n let metadata: NftMetadata | undefined = undefined\n if (checkedMetaDataUri !== undefined) {\n try {\n metadata = (await axios.get(checkedMetaDataUri)).data\n } catch (ex) {\n const error = ex as Error\n console.error(`Get Metadata failed: ${error.message}`)\n }\n }\n\n const info: NftInfo = {\n address: contractAddress,\n chainId: Number((await provider.getNetwork()).chainId),\n metadata,\n metadataUri,\n schema: NftSchema,\n supply: `0x${supply.toString(16)}`,\n tokenId: `0x${tokenId.toString(16)}`,\n type: finalTypes.at(0),\n types: finalTypes,\n }\n if (implementation !== contractAddress) {\n info.implementation = implementation\n }\n return info\n }\n }),\n )\n ).filter(exists)\n return result\n } catch (ex) {\n const error = ex as Error\n console.error(`getNftCollectionNfts failed: [${error.name}] ${error.message}`)\n console.log(error.stack)\n return []\n }\n}\n","import { TokenType } from '@xyo-network/crypto-nft-payload-plugin'\nimport { ERC721__factory, ERC1155URIStorage__factory } from '@xyo-network/open-zeppelin-typechain'\nimport { Provider } from 'ethers'\n\nimport { contractHasFunctions } from './contractHasFunctions'\n\nexport const isErc1155 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC1155URIStorage__factory.createInterface(), ['uri'])\n}\n\nexport const isErc721 = async (provider: Provider, address: string) => {\n return await contractHasFunctions(provider, address, ERC721__factory.createInterface(), ['name', 'symbol', 'tokenURI'])\n}\n\nexport const tokenTypes = async (provider: Provider, address: string) => {\n const [erc721, erc1155] = await Promise.all([isErc721(provider, address), isErc1155(provider, address)])\n const result: TokenType[] = []\n if (erc721) {\n result.push('ERC721')\n }\n if (erc1155) {\n result.push('ERC1155')\n }\n return result\n}\n","export const tryCall = async <T>(func: () => Promise<T>, name?: string): Promise<T | undefined> => {\n try {\n return await func()\n } catch (ex) {\n if (name) {\n const error = ex as Error\n console.log(`tryCall failed [${name}]: ${error.message}`)\n }\n return undefined\n }\n}\n","import { CryptoNftCollectionWitnessPlugin } from './Plugin'\n\nexport * from './lib'\nexport * from './Witness'\n\nexport { CryptoNftCollectionWitnessPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default CryptoNftCollectionWitnessPlugin\n"],"mappings":"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","names":["NftSchema","assertEx","ERC721Enumerable__factory","attributes","p","assertEx","ERC721Enumerable__factory","NftSchema"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAWjC,eAAO,MAAM,oBAAoB,oBAId,MAAM,YAIb,QAAQ,UACV,SAAS,EAAE,uBAOlB,QAAQ,OAAO,EAAE,CAqEnB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAWjC,eAAO,MAAM,oBAAoB,oBAId,MAAM,YAIb,QAAQ,UACV,SAAS,EAAE,uBAOlB,QAAQ,OAAO,EAAE,CAqEnB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"getNftCollectionNfts.d.ts","sourceRoot":"","sources":["../../../src/lib/getNftCollectionNfts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAA0B,SAAS,EAAe,MAAM,wCAAwC,CAAA;AAGhH,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAWjC,eAAO,MAAM,oBAAoB,oBAId,MAAM,YAIb,QAAQ,UACV,SAAS,EAAE,uBAOlB,QAAQ,OAAO,EAAE,CAqEnB,CAAA"}
|
package/package.json
CHANGED
|
@@ -10,28 +10,28 @@
|
|
|
10
10
|
"url": "https://github.com/XYOracleNetwork/plugins/issues"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@xylabs/assert": "^2.13.
|
|
14
|
-
"@xylabs/axios": "^2.13.
|
|
15
|
-
"@xylabs/
|
|
16
|
-
"@xylabs/
|
|
17
|
-
"@xylabs/
|
|
18
|
-
"@xyo-network/blockchain-erc1822-witness": "~2.82.
|
|
19
|
-
"@xyo-network/blockchain-erc1967-witness": "~2.82.
|
|
20
|
-
"@xyo-network/core": "^2.82.0
|
|
21
|
-
"@xyo-network/crypto-nft-collection-payload-plugin": "~2.82.
|
|
22
|
-
"@xyo-network/crypto-nft-payload-plugin": "~2.82.
|
|
13
|
+
"@xylabs/assert": "^2.13.20",
|
|
14
|
+
"@xylabs/axios": "^2.13.20",
|
|
15
|
+
"@xylabs/eth-address": "^2.13.20",
|
|
16
|
+
"@xylabs/exists": "^2.13.20",
|
|
17
|
+
"@xylabs/hex": "^2.13.20",
|
|
18
|
+
"@xyo-network/blockchain-erc1822-witness": "~2.82.1",
|
|
19
|
+
"@xyo-network/blockchain-erc1967-witness": "~2.82.1",
|
|
20
|
+
"@xyo-network/core": "^2.82.0",
|
|
21
|
+
"@xyo-network/crypto-nft-collection-payload-plugin": "~2.82.1",
|
|
22
|
+
"@xyo-network/crypto-nft-payload-plugin": "~2.82.1",
|
|
23
23
|
"@xyo-network/open-zeppelin-typechain": "^3.0.5",
|
|
24
|
-
"@xyo-network/payload-model": "^2.82.0
|
|
25
|
-
"@xyo-network/payloadset-plugin": "^2.82.0
|
|
26
|
-
"@xyo-network/witness-blockchain-abstract": "^2.82.0
|
|
27
|
-
"ethers": "^6.
|
|
24
|
+
"@xyo-network/payload-model": "^2.82.0",
|
|
25
|
+
"@xyo-network/payloadset-plugin": "^2.82.0",
|
|
26
|
+
"@xyo-network/witness-blockchain-abstract": "^2.82.0",
|
|
27
|
+
"ethers": "^6.9.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@xylabs/jest-helpers": "^2.13.
|
|
31
|
-
"@xylabs/ts-scripts-yarn3": "^3.2.
|
|
32
|
-
"@xylabs/tsconfig": "^3.2.
|
|
33
|
-
"@xyo-network/account": "^2.82.0
|
|
34
|
-
"@xyo-network/account-model": "^2.82.0
|
|
30
|
+
"@xylabs/jest-helpers": "^2.13.20",
|
|
31
|
+
"@xylabs/ts-scripts-yarn3": "^3.2.10",
|
|
32
|
+
"@xylabs/tsconfig": "^3.2.10",
|
|
33
|
+
"@xyo-network/account": "^2.82.0",
|
|
34
|
+
"@xyo-network/account-model": "^2.82.0",
|
|
35
35
|
"jest": "^29.7.0",
|
|
36
36
|
"typescript": "^5.3.2"
|
|
37
37
|
},
|
|
@@ -75,6 +75,5 @@
|
|
|
75
75
|
"url": "https://github.com/XYOracleNetwork/plugins.git"
|
|
76
76
|
},
|
|
77
77
|
"sideEffects": false,
|
|
78
|
-
"version": "2.82.
|
|
79
|
-
"stableVersion": "2.81.7"
|
|
78
|
+
"version": "2.82.1"
|
|
80
79
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AxiosJson } from '@xylabs/axios'
|
|
2
|
-
import { BigNumber as XyBigNumber } from '@xylabs/bignumber'
|
|
3
2
|
import { exists } from '@xylabs/exists'
|
|
3
|
+
import { isHexZero } from '@xylabs/hex'
|
|
4
4
|
import { getErc1822Status } from '@xyo-network/blockchain-erc1822-witness'
|
|
5
5
|
import { getErc1967Status } from '@xyo-network/blockchain-erc1967-witness'
|
|
6
6
|
import { NftInfo, NftMetadata, NftSchema, TokenType, toTokenType } from '@xyo-network/crypto-nft-payload-plugin'
|
|
@@ -13,14 +13,6 @@ import { tryCall } from './tryCall'
|
|
|
13
13
|
|
|
14
14
|
const ipfsGateway = '5d7b6582.beta.decentralnetworkservices.com'
|
|
15
15
|
|
|
16
|
-
const hexBytesOnlyOnly = (value: string) => {
|
|
17
|
-
return value.startsWith('0x') ? value.substring(2) : value
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const isHexZero = (value?: string) => {
|
|
21
|
-
return value === undefined ? true : new XyBigNumber(hexBytesOnlyOnly(value), 'hex').eqn(0)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
16
|
function range(size: number, startAt: number = 0): ReadonlyArray<number> {
|
|
25
17
|
return [...Array(size).keys()].map((i) => i + startAt)
|
|
26
18
|
}
|
|
@@ -51,7 +43,10 @@ export const getNftCollectionNfts = async (
|
|
|
51
43
|
//Check if ERC-1822 Upgradeable
|
|
52
44
|
const erc1822Status = await getErc1822Status(provider, contractAddress, block)
|
|
53
45
|
|
|
54
|
-
const implementation =
|
|
46
|
+
const implementation =
|
|
47
|
+
!erc1967Status.slots.implementation || isHexZero(erc1967Status.slots.implementation)
|
|
48
|
+
? erc1822Status.implementation
|
|
49
|
+
: erc1967Status.implementation
|
|
55
50
|
|
|
56
51
|
const axios = new AxiosJson({ timeout: 2000 })
|
|
57
52
|
const enumerable = ERC721Enumerable__factory.connect(implementation, provider)
|