@xyo-network/crypto-nft-diviner-score-plugin 2.95.4 → 2.96.0-rc.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/Diviner.ts","../../src/lib/rating/criteria/scoring/contract.ts","../../src/lib/rating/criteria/scoring/metadata/animationUrl.ts","../../src/lib/rating/criteria/scoring/metadata/lib/urlHelpers.ts","../../src/lib/rating/criteria/scoring/metadata/attributes/evaluateAttributes.ts","../../src/lib/rating/criteria/scoring/metadata/backgroundColor.ts","../../src/lib/rating/criteria/scoring/metadata/description.ts","../../src/lib/rating/criteria/scoring/metadata/externalUrl.ts","../../src/lib/rating/criteria/scoring/metadata/image.ts","../../src/lib/rating/criteria/scoring/metadata/imageData.ts","../../src/lib/rating/criteria/scoring/metadata/name.ts","../../src/lib/rating/criteria/scoring/metadata/youtubeUrl.ts","../../src/lib/rating/criteria/scoring/supply.ts","../../src/lib/rating/criteria/scoring/tokenId.ts","../../src/lib/rating/criteria/scoring/type.ts","../../src/lib/rating/criteria/scoringCriteria.ts","../../src/lib/rating/analyzeNft.ts","../../src/Plugin.ts"],"sourcesContent":["import {\n isNftInfo,\n NftInfo,\n NftScore,\n NftScoreDivinerConfig,\n NftScoreDivinerConfigSchema,\n NftScoreSchema,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { DivinerParams } from '@xyo-network/diviner-model'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema } from '@xyo-network/payload-model'\n\nimport { analyzeNft, NftAnalysis } from './lib'\n\nexport type NftScoreDivinerParams = DivinerParams<AnyConfigSchema<NftScoreDivinerConfig>>\n\nconst toNftScorePayload = (nftInfo: NftInfo, scores: NftAnalysis): NftScore => {\n const { address, chainId, type } = nftInfo\n return { address, chainId, schema: NftScoreSchema, scores, type }\n}\n\nexport const isNftScore = (payload: Payload): payload is NftScore => payload.schema === NftScoreSchema\n\nexport class NftScoreDiviner<TParams extends NftScoreDivinerParams = NftScoreDivinerParams> extends AbstractDiviner<TParams> {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, NftScoreDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = NftScoreDivinerConfigSchema\n\n protected override divineHandler = async (payloads?: Payload[]): Promise<Payload[]> => {\n const nftInfos = payloads?.filter(isNftInfo) ?? []\n const results = await Promise.all(\n nftInfos.map<Promise<NftScore>>(async (nftInfo) => {\n const [score, sourceHash] = await Promise.all([\n // Analyze the NFT\n toNftScorePayload(nftInfo, await analyzeNft(nftInfo)),\n // Hash the source payload\n PayloadBuilder.dataHash(nftInfo),\n ])\n return { ...score, sources: [sourceHash] }\n }),\n )\n return results\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\nimport { isAddress } from 'ethers'\n\nexport const scoreContractAddress: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.address) return FAIL\n if (typeof nft.address !== 'string') return FAIL\n if (!isAddress(nft.address)) return FAIL\n return PASS\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nexport const scoreNftAnimationUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreAnimationUrl(nft.metadata?.animation_url)\n}\n\nexport const scoreAnimationUrl = (animation_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (animation_url === undefined || animation_url === null) return PASS\n incrementPossible(score)\n if (typeof animation_url !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isValidUrl(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isSecure(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isWeb3(animation_url)) return score\n return incrementTotal(score)\n}\n","import { URL } from '@xylabs/url'\n\nexport const web3Protocols = ['ipfs:', 'ar:']\n\nexport const toUrl = (url?: string | null): URL | undefined => {\n if (!url) return undefined\n try {\n return new URL(url)\n } catch {\n return undefined\n }\n}\n\nexport const isValidUrl = (url?: string | null): boolean => toUrl(url) !== undefined\n// eslint-disable-next-line unicorn/prefer-includes\nexport const isWeb3 = (url?: string | null): boolean => web3Protocols.some((protocol) => protocol === toUrl(url)?.protocol)\nexport const isWeb2 = (url?: string | null): boolean => !isWeb3(url)\nexport const isSecure = (url?: string | null): boolean => isWeb3(url) || toUrl(url)?.protocol === 'https:'\n","import { NftAttribute, NftInfoFields, OpenSeaNftAttribute, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isDate = (value: unknown): value is Date => {\n if (isNumber(value)) {\n try {\n new Date(value)\n return true\n } catch {\n return false\n }\n }\n return false\n}\n\nconst isNumber = (value: unknown): value is number => typeof value === 'number'\n\nconst isPercentage = (value: unknown): boolean => isNumber(value) && value >= 0 && value <= 100\n\nconst isNonEmptyString = (value: unknown): value is string => typeof value === 'string' && value.length > 0\n\nconst isNonEmptyStringOrNumber = (value: unknown): value is string | number => value === 'number' || isNonEmptyString(value)\n\nexport const evaluateNftAttributes = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore =>\n nft?.metadata?.attributes ? evaluateAttributes(nft?.metadata?.attributes) : [0, 1]\n\nexport const evaluateAttributes = (attributes: NftAttribute[] | OpenSeaNftAttribute[] | unknown): ScaledScore => {\n if (!attributes || !Array.isArray(attributes) || attributes.length === 0) return [0, 1]\n const score: ScaledScore = [0, 0]\n for (const attribute of attributes) {\n const [attributeTotal, attributePossible] = evaluateAttribute(attribute)\n incrementTotalAndPossible(score, attributeTotal, attributePossible)\n }\n return [1, 1]\n}\n\nexport const evaluateAttribute = (attribute: OpenSeaNftAttribute): ScaledScore => {\n const score: ScaledScore = [0, 1]\n const max_value = attribute?.max_value\n const trait_type = attribute?.trait_type\n const value = attribute?.value\n\n // Validate trait_type & value\n if (!attribute || typeof attribute !== 'object' || !isNonEmptyString(trait_type) || !isNonEmptyStringOrNumber(value)) return score\n incrementTotal(score)\n\n // Validate display_type\n incrementPossible(score)\n if (validDisplayType(attribute)) incrementTotal(score)\n\n // Validate max_value\n if (max_value !== undefined) {\n incrementPossible(score)\n if (isNumber(max_value) && isNumber(value) && value <= max_value) incrementTotal(score)\n }\n\n return score\n}\n\nconst validDisplayType = (attribute: OpenSeaNftAttribute): boolean => {\n switch (attribute?.display_type) {\n case 'number':\n case 'boost_number': {\n if (isNumber(attribute?.value)) return true\n break\n }\n case 'boost_percentage': {\n if (isPercentage(attribute?.value)) return true\n break\n }\n case 'date': {\n if (isDate(attribute?.value)) return true\n break\n }\n case 'string':\n case undefined: {\n if (isNonEmptyString(attribute?.value)) return true\n break\n }\n default: {\n break\n }\n }\n return false\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isHexColor = /^[\\da-f]{6}$/i\n\nexport const scoreNftBackgroundColor = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreBackgroundColor(nft.metadata?.background_color)\n}\n\nexport const scoreBackgroundColor = (background_color: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (background_color === undefined || background_color === null) return PASS\n incrementPossible(score)\n if (typeof background_color !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isHexColor.test(background_color.toUpperCase())) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftDescription = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreDescription(nft.metadata?.description)\n}\n\nexport const scoreDescription = (description: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!description || typeof description !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftExternalUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreExternalUrl(nft?.metadata?.external_url)\n}\nexport const scoreExternalUrl = (external_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 2]\n if (external_url === undefined || external_url === null || typeof external_url !== 'string' || !isValidUrl(external_url)) return score\n incrementTotal(score)\n if (!isSecure(external_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nconst MaxPossibleImageScore = 3\n\nexport const scoreNftImage = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image) {\n return scoreImage(nft.metadata?.image)\n } else {\n // but there is image data, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image_data ? PASS : [0, MaxPossibleImageScore]\n }\n}\n\nexport const scoreImage = (image: unknown): ScaledScore => {\n const score: ScaledScore = [0, MaxPossibleImageScore]\n if (!image || typeof image !== 'string' || !isValidUrl(image)) return score\n incrementTotal(score)\n if (!isSecure(image)) return score\n incrementTotal(score)\n if (!isWeb3(image)) return score\n incrementTotal(score)\n return score\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\nimport { parse } from 'svg-parser'\n\nconst MaxPossibleImageDataScore = 1\n\n// NOTE: There is probably a deeper check we can do\n// here, but this is a good start\nconst isValidImageData = (image_data: string): boolean => {\n // If it doesn't start with an svg tag, it's not an svg\n if (!image_data.startsWith('<svg')) return false\n try {\n // If it can't be parsed, it's not an svg\n parse(image_data)\n return true\n } catch {\n return false\n }\n}\n\nexport const scoreNftImageData = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image_data) {\n return scoreImageData(nft.metadata?.image_data)\n } else {\n // but there is an image, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image ? PASS : [0, MaxPossibleImageDataScore]\n }\n}\n\nexport const scoreImageData = (image_data: unknown): ScaledScore => {\n return !image_data || typeof image_data !== 'string' || !isValidImageData(image_data) ?\n [0, MaxPossibleImageDataScore]\n : [MaxPossibleImageDataScore, MaxPossibleImageDataScore]\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftName = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreName(nft.metadata?.name)\n}\nexport const scoreName = (name: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!name || typeof name !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftYoutubeUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreYoutubeUrl(nft?.metadata?.youtube_url)\n}\nexport const scoreYoutubeUrl = (youtube_url: unknown): ScaledScore => {\n if (youtube_url === undefined || youtube_url === null) return PASS\n const score: ScaledScore = [0, 2]\n if (typeof youtube_url !== 'string' || !isValidUrl(youtube_url)) return score\n incrementTotal(score)\n if (!isSecure(youtube_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreSupply: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.supply) return FAIL\n if (typeof nft.supply !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\n/**\n * Callers SHALL NOT assume that ID numbers have any specific pattern to them, and\n * MUST treat the ID as a \"black box\"\n * @param nft\n * @returns\n */\nexport const scoreTokenId: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.tokenId) return FAIL\n if (typeof nft.tokenId !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreType: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.type) return FAIL\n if (typeof nft.type !== 'string') return FAIL\n const type = nft.type.toUpperCase()\n if (type !== 'ERC721' && type !== 'ERC1155') return FAIL\n return PASS\n}\n","import {\n evaluateNftAttributes,\n scoreContractAddress,\n scoreNftAnimationUrl,\n scoreNftBackgroundColor,\n scoreNftDescription,\n scoreNftExternalUrl,\n scoreNftImage,\n scoreNftImageData,\n scoreNftName,\n scoreNftYoutubeUrl,\n scoreSupply,\n scoreTokenId,\n scoreType,\n} from './scoring'\n\nconst attributesScoringCriteria = {\n Attributes: { score: evaluateNftAttributes, weight: 1 },\n}\n\nconst metadataScoringCriteria = {\n 'Animation URL': { score: scoreNftAnimationUrl, weight: 1 },\n 'Background Color': { score: scoreNftBackgroundColor, weight: 1 },\n Description: { score: scoreNftDescription, weight: 1 },\n 'External Url': { score: scoreNftExternalUrl, weight: 1 },\n Image: { score: scoreNftImage, weight: 1 },\n 'Image Data': { score: scoreNftImageData, weight: 1 },\n Name: { score: scoreNftName, weight: 1 },\n 'YouTube URL': { score: scoreNftYoutubeUrl, weight: 1 },\n ...attributesScoringCriteria,\n}\n\nexport const scoringCriteria = {\n 'Contract Address': { score: scoreContractAddress, weight: 1 },\n Supply: { score: scoreSupply, weight: 1 },\n 'Token Id': { score: scoreTokenId, weight: 1 },\n Type: { score: scoreType, weight: 1 },\n ...metadataScoringCriteria,\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { Score } from '@xyo-network/crypto-nft-score-model'\n\nimport { scoringCriteria } from './criteria'\n\nexport type ScoringCriteriaKey = keyof typeof scoringCriteria & PropertyKey\n\nexport type NftAnalysis = {\n [key in ScoringCriteriaKey]: Score\n}\n\nexport const analyzeNft = async (\n /**\n * The NFT to evaluate\n */\n nft: NftInfoFields,\n): Promise<NftAnalysis> => {\n const result = Object.fromEntries(\n await Promise.all(\n Object.entries(scoringCriteria).map(async ([key, { score, weight }]) => {\n const rawScore = await score(nft)\n const weighted = rawScore.map((v) => v * weight) as Score\n return [key, weighted] as const\n }),\n ),\n ) as NftAnalysis\n return result\n}\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetDivinerPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { NftScoreDiviner } from './Diviner'\n\nexport const NftScoreDivinerPlugin = () =>\n createPayloadSetDivinerPlugin<NftScoreDiviner>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n diviner: async (params) => {\n const result = await NftScoreDiviner.create(params)\n return result\n },\n },\n )\n"],"mappings":"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","names":["PASS","PASS","incrementPossible","incrementTotal","incrementTotalAndPossible","incrementPossible","incrementTotal","incrementTotalAndPossible","PASS","incrementTotal","incrementTotal","incrementTotal","incrementTotal","PASS","PASS","incrementTotal","PASS","incrementTotal","incrementTotal","PASS","PASS","incrementTotal","FAIL","PASS","FAIL","PASS","FAIL","PASS"]}
1
+ {"version":3,"sources":["../../src/Diviner.ts","../../src/lib/rating/criteria/scoring/contract.ts","../../src/lib/rating/criteria/scoring/metadata/animationUrl.ts","../../src/lib/rating/criteria/scoring/metadata/lib/urlHelpers.ts","../../src/lib/rating/criteria/scoring/metadata/attributes/evaluateAttributes.ts","../../src/lib/rating/criteria/scoring/metadata/backgroundColor.ts","../../src/lib/rating/criteria/scoring/metadata/description.ts","../../src/lib/rating/criteria/scoring/metadata/externalUrl.ts","../../src/lib/rating/criteria/scoring/metadata/image.ts","../../src/lib/rating/criteria/scoring/metadata/imageData.ts","../../src/lib/rating/criteria/scoring/metadata/name.ts","../../src/lib/rating/criteria/scoring/metadata/youtubeUrl.ts","../../src/lib/rating/criteria/scoring/supply.ts","../../src/lib/rating/criteria/scoring/tokenId.ts","../../src/lib/rating/criteria/scoring/type.ts","../../src/lib/rating/criteria/scoringCriteria.ts","../../src/lib/rating/analyzeNft.ts","../../src/Plugin.ts"],"sourcesContent":["import {\n isNftInfo,\n NftInfo,\n NftScore,\n NftScoreDivinerConfig,\n NftScoreDivinerConfigSchema,\n NftScoreSchema,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { DivinerParams } from '@xyo-network/diviner-model'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema } from '@xyo-network/payload-model'\n\nimport { analyzeNft, NftAnalysis } from './lib'\n\nexport type NftScoreDivinerParams = DivinerParams<AnyConfigSchema<NftScoreDivinerConfig>>\n\nconst toNftScorePayload = (nftInfo: NftInfo, scores: NftAnalysis): NftScore => {\n const { address, chainId, type } = nftInfo\n return { address, chainId, schema: NftScoreSchema, scores, type }\n}\n\nexport const isNftScore = (payload: Payload): payload is NftScore => payload.schema === NftScoreSchema\n\nexport class NftScoreDiviner<TParams extends NftScoreDivinerParams = NftScoreDivinerParams> extends AbstractDiviner<TParams> {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, NftScoreDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = NftScoreDivinerConfigSchema\n\n protected override divineHandler = async (payloads?: Payload[]): Promise<Payload[]> => {\n const nftInfos = payloads?.filter(isNftInfo) ?? []\n const results = await Promise.all(\n nftInfos.map<Promise<NftScore>>(async (nftInfo) => {\n const [score, sourceHash] = await Promise.all([\n // Analyze the NFT\n toNftScorePayload(nftInfo, await analyzeNft(nftInfo)),\n // Hash the source payload\n PayloadBuilder.dataHash(nftInfo),\n ])\n return { ...score, sources: [sourceHash] }\n }),\n )\n return results\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\nimport { isAddress } from 'ethers'\n\nexport const scoreContractAddress: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.address) return FAIL\n if (typeof nft.address !== 'string') return FAIL\n if (!isAddress(nft.address)) return FAIL\n return PASS\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nexport const scoreNftAnimationUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreAnimationUrl(nft.metadata?.animation_url)\n}\n\nexport const scoreAnimationUrl = (animation_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (animation_url === undefined || animation_url === null) return PASS\n incrementPossible(score)\n if (typeof animation_url !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isValidUrl(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isSecure(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isWeb3(animation_url)) return score\n return incrementTotal(score)\n}\n","import { URL } from '@xylabs/url'\n\nexport const web3Protocols = ['ipfs:', 'ar:']\n\nexport const toUrl = (url?: string | null): URL | undefined => {\n if (!url) return undefined\n try {\n return new URL(url)\n } catch {\n return undefined\n }\n}\n\nexport const isValidUrl = (url?: string | null): boolean => toUrl(url) !== undefined\n// eslint-disable-next-line unicorn/prefer-includes\nexport const isWeb3 = (url?: string | null): boolean => web3Protocols.some((protocol) => protocol === toUrl(url)?.protocol)\nexport const isWeb2 = (url?: string | null): boolean => !isWeb3(url)\nexport const isSecure = (url?: string | null): boolean => isWeb3(url) || toUrl(url)?.protocol === 'https:'\n","import { NftAttribute, NftInfoFields, OpenSeaNftAttribute, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isDate = (value: unknown): value is Date => {\n if (isNumber(value)) {\n try {\n new Date(value)\n return true\n } catch {\n return false\n }\n }\n return false\n}\n\nconst isNumber = (value: unknown): value is number => typeof value === 'number'\n\nconst isPercentage = (value: unknown): boolean => isNumber(value) && value >= 0 && value <= 100\n\nconst isNonEmptyString = (value: unknown): value is string => typeof value === 'string' && value.length > 0\n\nconst isNonEmptyStringOrNumber = (value: unknown): value is string | number => value === 'number' || isNonEmptyString(value)\n\nexport const evaluateNftAttributes = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore =>\n nft?.metadata?.attributes ? evaluateAttributes(nft?.metadata?.attributes) : [0, 1]\n\nexport const evaluateAttributes = (attributes: NftAttribute[] | OpenSeaNftAttribute[] | unknown): ScaledScore => {\n if (!attributes || !Array.isArray(attributes) || attributes.length === 0) return [0, 1]\n const score: ScaledScore = [0, 0]\n for (const attribute of attributes) {\n const [attributeTotal, attributePossible] = evaluateAttribute(attribute)\n incrementTotalAndPossible(score, attributeTotal, attributePossible)\n }\n return [1, 1]\n}\n\nexport const evaluateAttribute = (attribute: OpenSeaNftAttribute): ScaledScore => {\n const score: ScaledScore = [0, 1]\n const max_value = attribute?.max_value\n const trait_type = attribute?.trait_type\n const value = attribute?.value\n\n // Validate trait_type & value\n if (!attribute || typeof attribute !== 'object' || !isNonEmptyString(trait_type) || !isNonEmptyStringOrNumber(value)) return score\n incrementTotal(score)\n\n // Validate display_type\n incrementPossible(score)\n if (validDisplayType(attribute)) incrementTotal(score)\n\n // Validate max_value\n if (max_value !== undefined) {\n incrementPossible(score)\n if (isNumber(max_value) && isNumber(value) && value <= max_value) incrementTotal(score)\n }\n\n return score\n}\n\nconst validDisplayType = (attribute: OpenSeaNftAttribute): boolean => {\n switch (attribute?.display_type) {\n case 'number':\n case 'boost_number': {\n if (isNumber(attribute?.value)) return true\n break\n }\n case 'boost_percentage': {\n if (isPercentage(attribute?.value)) return true\n break\n }\n case 'date': {\n if (isDate(attribute?.value)) return true\n break\n }\n case 'string':\n case undefined: {\n if (isNonEmptyString(attribute?.value)) return true\n break\n }\n default: {\n break\n }\n }\n return false\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isHexColor = /^[\\da-f]{6}$/i\n\nexport const scoreNftBackgroundColor = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreBackgroundColor(nft.metadata?.background_color)\n}\n\nexport const scoreBackgroundColor = (background_color: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (background_color === undefined || background_color === null) return PASS\n incrementPossible(score)\n if (typeof background_color !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isHexColor.test(background_color.toUpperCase())) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftDescription = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreDescription(nft.metadata?.description)\n}\n\nexport const scoreDescription = (description: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!description || typeof description !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftExternalUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreExternalUrl(nft?.metadata?.external_url)\n}\nexport const scoreExternalUrl = (external_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 2]\n if (external_url === undefined || external_url === null || typeof external_url !== 'string' || !isValidUrl(external_url)) return score\n incrementTotal(score)\n if (!isSecure(external_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nconst MaxPossibleImageScore = 3\n\nexport const scoreNftImage = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image) {\n return scoreImage(nft.metadata?.image)\n } else {\n // but there is image data, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image_data ? PASS : [0, MaxPossibleImageScore]\n }\n}\n\nexport const scoreImage = (image: unknown): ScaledScore => {\n const score: ScaledScore = [0, MaxPossibleImageScore]\n if (!image || typeof image !== 'string' || !isValidUrl(image)) return score\n incrementTotal(score)\n if (!isSecure(image)) return score\n incrementTotal(score)\n if (!isWeb3(image)) return score\n incrementTotal(score)\n return score\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\nimport { parse } from 'svg-parser'\n\nconst MaxPossibleImageDataScore = 1\n\n// NOTE: There is probably a deeper check we can do\n// here, but this is a good start\nconst isValidImageData = (image_data: string): boolean => {\n // If it doesn't start with an svg tag, it's not an svg\n if (!image_data.startsWith('<svg')) return false\n try {\n // If it can't be parsed, it's not an svg\n parse(image_data)\n return true\n } catch {\n return false\n }\n}\n\nexport const scoreNftImageData = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image_data) {\n return scoreImageData(nft.metadata?.image_data)\n } else {\n // but there is an image, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image ? PASS : [0, MaxPossibleImageDataScore]\n }\n}\n\nexport const scoreImageData = (image_data: unknown): ScaledScore => {\n return !image_data || typeof image_data !== 'string' || !isValidImageData(image_data) ?\n [0, MaxPossibleImageDataScore]\n : [MaxPossibleImageDataScore, MaxPossibleImageDataScore]\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftName = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreName(nft.metadata?.name)\n}\nexport const scoreName = (name: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!name || typeof name !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftYoutubeUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreYoutubeUrl(nft?.metadata?.youtube_url)\n}\nexport const scoreYoutubeUrl = (youtube_url: unknown): ScaledScore => {\n if (youtube_url === undefined || youtube_url === null) return PASS\n const score: ScaledScore = [0, 2]\n if (typeof youtube_url !== 'string' || !isValidUrl(youtube_url)) return score\n incrementTotal(score)\n if (!isSecure(youtube_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreSupply: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.supply) return FAIL\n if (typeof nft.supply !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\n/**\n * Callers SHALL NOT assume that ID numbers have any specific pattern to them, and\n * MUST treat the ID as a \"black box\"\n * @param nft\n * @returns\n */\nexport const scoreTokenId: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.tokenId) return FAIL\n if (typeof nft.tokenId !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreType: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.type) return FAIL\n if (typeof nft.type !== 'string') return FAIL\n const type = nft.type.toUpperCase()\n if (type !== 'ERC721' && type !== 'ERC1155') return FAIL\n return PASS\n}\n","import {\n evaluateNftAttributes,\n scoreContractAddress,\n scoreNftAnimationUrl,\n scoreNftBackgroundColor,\n scoreNftDescription,\n scoreNftExternalUrl,\n scoreNftImage,\n scoreNftImageData,\n scoreNftName,\n scoreNftYoutubeUrl,\n scoreSupply,\n scoreTokenId,\n scoreType,\n} from './scoring'\n\nconst attributesScoringCriteria = {\n Attributes: { score: evaluateNftAttributes, weight: 1 },\n}\n\nconst metadataScoringCriteria = {\n 'Animation URL': { score: scoreNftAnimationUrl, weight: 1 },\n 'Background Color': { score: scoreNftBackgroundColor, weight: 1 },\n Description: { score: scoreNftDescription, weight: 1 },\n 'External Url': { score: scoreNftExternalUrl, weight: 1 },\n Image: { score: scoreNftImage, weight: 1 },\n 'Image Data': { score: scoreNftImageData, weight: 1 },\n Name: { score: scoreNftName, weight: 1 },\n 'YouTube URL': { score: scoreNftYoutubeUrl, weight: 1 },\n ...attributesScoringCriteria,\n}\n\nexport const scoringCriteria = {\n 'Contract Address': { score: scoreContractAddress, weight: 1 },\n Supply: { score: scoreSupply, weight: 1 },\n 'Token Id': { score: scoreTokenId, weight: 1 },\n Type: { score: scoreType, weight: 1 },\n ...metadataScoringCriteria,\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { Score } from '@xyo-network/crypto-nft-score-model'\n\nimport { scoringCriteria } from './criteria'\n\nexport type ScoringCriteriaKey = keyof typeof scoringCriteria & PropertyKey\n\nexport type NftAnalysis = {\n [key in ScoringCriteriaKey]: Score\n}\n\nexport const analyzeNft = async (\n /**\n * The NFT to evaluate\n */\n nft: NftInfoFields,\n): Promise<NftAnalysis> => {\n const result = Object.fromEntries(\n await Promise.all(\n Object.entries(scoringCriteria).map(async ([key, { score, weight }]) => {\n const rawScore = await score(nft)\n const weighted = rawScore.map((v) => v * weight) as Score\n return [key, weighted] as const\n }),\n ),\n ) as NftAnalysis\n return result\n}\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetDivinerPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { NftScoreDiviner } from './Diviner'\n\nexport const NftScoreDivinerPlugin = () =>\n createPayloadSetDivinerPlugin<NftScoreDiviner>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n diviner: async (params) => {\n const result = await NftScoreDiviner.create(params)\n return result\n },\n },\n )\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EAIA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAGhC,SAAS,sBAAsB;;;ACV/B,SAAS,MAAM,YAAqC;AACpD,SAAS,iBAAiB;AAEnB,IAAM,uBAA+D,CAAC,QAAuB;AAClG,MAAI,CAAC,IAAI,QAAS,QAAO;AACzB,MAAI,OAAO,IAAI,YAAY,SAAU,QAAO;AAC5C,MAAI,CAAC,UAAU,IAAI,OAAO,EAAG,QAAO;AACpC,SAAO;AACT;;;ACRA,SAAS,mBAAmB,gBAAgB,2BAA2B,QAAAA,aAAyB;;;ACDhG,SAAS,WAAW;AAEb,IAAM,gBAAgB,CAAC,SAAS,KAAK;AAErC,IAAM,QAAQ,CAAC,QAAyC;AAC7D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,WAAO,IAAI,IAAI,GAAG;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,aAAa,CAAC,QAAiC,MAAM,GAAG,MAAM;AAEpE,IAAM,SAAS,CAAC,QAAiC,cAAc,KAAK,CAAC,aAAa,aAAa,MAAM,GAAG,GAAG,QAAQ;AAEnH,IAAM,WAAW,CAAC,QAAiC,OAAO,GAAG,KAAK,MAAM,GAAG,GAAG,aAAa;;;ADZ3F,IAAM,uBAAuB,CAAC,QAA2D;AAC9F,SAAO,kBAAkB,IAAI,UAAU,aAAa;AACtD;AAEO,IAAM,oBAAoB,CAAC,kBAAwC;AACxE,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,MAAI,kBAAkB,UAAa,kBAAkB,KAAM,QAAOC;AAClE,oBAAkB,KAAK;AACvB,MAAI,OAAO,kBAAkB,SAAU,QAAO;AAC9C,4BAA0B,KAAK;AAC/B,MAAI,CAAC,WAAW,aAAa,EAAG,QAAO;AACvC,4BAA0B,KAAK;AAC/B,MAAI,CAAC,SAAS,aAAa,EAAG,QAAO;AACrC,4BAA0B,KAAK;AAC/B,MAAI,CAAC,OAAO,aAAa,EAAG,QAAO;AACnC,SAAO,eAAe,KAAK;AAC7B;;;AEpBA,SAAS,qBAAAC,oBAAmB,kBAAAC,iBAAgB,6BAAAC,kCAA8C;AAE1F,IAAM,SAAS,CAAC,UAAkC;AAChD,MAAI,SAAS,KAAK,GAAG;AACnB,QAAI;AACF,UAAI,KAAK,KAAK;AACd,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,WAAW,CAAC,UAAoC,OAAO,UAAU;AAEvE,IAAM,eAAe,CAAC,UAA4B,SAAS,KAAK,KAAK,SAAS,KAAK,SAAS;AAE5F,IAAM,mBAAmB,CAAC,UAAoC,OAAO,UAAU,YAAY,MAAM,SAAS;AAE1G,IAAM,2BAA2B,CAAC,UAA6C,UAAU,YAAY,iBAAiB,KAAK;AAEpH,IAAM,wBAAwB,CAAC,QACpC,KAAK,UAAU,aAAa,mBAAmB,KAAK,UAAU,UAAU,IAAI,CAAC,GAAG,CAAC;AAE5E,IAAM,qBAAqB,CAAC,eAA8E;AAC/G,MAAI,CAAC,cAAc,CAAC,MAAM,QAAQ,UAAU,KAAK,WAAW,WAAW,EAAG,QAAO,CAAC,GAAG,CAAC;AACtF,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,aAAW,aAAa,YAAY;AAClC,UAAM,CAAC,gBAAgB,iBAAiB,IAAI,kBAAkB,SAAS;AACvE,IAAAA,2BAA0B,OAAO,gBAAgB,iBAAiB;AAAA,EACpE;AACA,SAAO,CAAC,GAAG,CAAC;AACd;AAEO,IAAM,oBAAoB,CAAC,cAAgD;AAChF,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,QAAM,YAAY,WAAW;AAC7B,QAAM,aAAa,WAAW;AAC9B,QAAM,QAAQ,WAAW;AAGzB,MAAI,CAAC,aAAa,OAAO,cAAc,YAAY,CAAC,iBAAiB,UAAU,KAAK,CAAC,yBAAyB,KAAK,EAAG,QAAO;AAC7H,EAAAD,gBAAe,KAAK;AAGpB,EAAAD,mBAAkB,KAAK;AACvB,MAAI,iBAAiB,SAAS,EAAG,CAAAC,gBAAe,KAAK;AAGrD,MAAI,cAAc,QAAW;AAC3B,IAAAD,mBAAkB,KAAK;AACvB,QAAI,SAAS,SAAS,KAAK,SAAS,KAAK,KAAK,SAAS,UAAW,CAAAC,gBAAe,KAAK;AAAA,EACxF;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CAAC,cAA4C;AACpE,UAAQ,WAAW,cAAc;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK,gBAAgB;AACnB,UAAI,SAAS,WAAW,KAAK,EAAG,QAAO;AACvC;AAAA,IACF;AAAA,IACA,KAAK,oBAAoB;AACvB,UAAI,aAAa,WAAW,KAAK,EAAG,QAAO;AAC3C;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,UAAI,OAAO,WAAW,KAAK,EAAG,QAAO;AACrC;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK,QAAW;AACd,UAAI,iBAAiB,WAAW,KAAK,EAAG,QAAO;AAC/C;AAAA,IACF;AAAA,IACA,SAAS;AACP;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACnFA,SAAS,qBAAAE,oBAAmB,kBAAAC,iBAAgB,6BAAAC,4BAA2B,QAAAC,aAAyB;AAEhG,IAAM,aAAa;AAEZ,IAAM,0BAA0B,CAAC,QAA2D;AACjG,SAAO,qBAAqB,IAAI,UAAU,gBAAgB;AAC5D;AAEO,IAAM,uBAAuB,CAAC,qBAA2C;AAC9E,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,MAAI,qBAAqB,UAAa,qBAAqB,KAAM,QAAOA;AACxE,EAAAH,mBAAkB,KAAK;AACvB,MAAI,OAAO,qBAAqB,SAAU,QAAO;AACjD,EAAAE,2BAA0B,KAAK;AAC/B,MAAI,CAAC,WAAW,KAAK,iBAAiB,YAAY,CAAC,EAAG,QAAO;AAC7D,SAAOD,gBAAe,KAAK;AAC7B;;;AChBA,SAAS,kBAAAG,uBAAmC;AAErC,IAAM,sBAAsB,CAAC,QAA2D;AAC7F,SAAO,iBAAiB,IAAI,UAAU,WAAW;AACnD;AAEO,IAAM,mBAAmB,CAAC,gBAAsC;AACrE,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,MAAI,CAAC,eAAe,OAAO,gBAAgB,SAAU,QAAO;AAC5D,SAAOA,gBAAe,KAAK;AAC7B;;;ACVA,SAAS,kBAAAC,uBAAmC;AAIrC,IAAM,sBAAsB,CAAC,QAA2D;AAC7F,SAAO,iBAAiB,KAAK,UAAU,YAAY;AACrD;AACO,IAAM,mBAAmB,CAAC,iBAAuC;AACtE,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,MAAI,iBAAiB,UAAa,iBAAiB,QAAQ,OAAO,iBAAiB,YAAY,CAAC,WAAW,YAAY,EAAG,QAAO;AACjI,EAAAC,gBAAe,KAAK;AACpB,MAAI,CAAC,SAAS,YAAY,EAAG,QAAO;AACpC,SAAOA,gBAAe,KAAK;AAC7B;;;ACbA,SAAS,kBAAAC,iBAAgB,QAAAC,aAAyB;AAIlD,IAAM,wBAAwB;AAEvB,IAAM,gBAAgB,CAAC,QAA2D;AAEvF,MAAI,KAAK,UAAU,OAAO;AACxB,WAAO,WAAW,IAAI,UAAU,KAAK;AAAA,EACvC,OAAO;AAEL,WAAO,IAAI,UAAU,aAAaC,QAAO,CAAC,GAAG,qBAAqB;AAAA,EACpE;AACF;AAEO,IAAM,aAAa,CAAC,UAAgC;AACzD,QAAM,QAAqB,CAAC,GAAG,qBAAqB;AACpD,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,WAAW,KAAK,EAAG,QAAO;AACtE,EAAAC,gBAAe,KAAK;AACpB,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,EAAAA,gBAAe,KAAK;AACpB,MAAI,CAAC,OAAO,KAAK,EAAG,QAAO;AAC3B,EAAAA,gBAAe,KAAK;AACpB,SAAO;AACT;;;ACzBA,SAAS,QAAAC,aAAyB;AAClC,SAAS,aAAa;AAEtB,IAAM,4BAA4B;AAIlC,IAAM,mBAAmB,CAAC,eAAgC;AAExD,MAAI,CAAC,WAAW,WAAW,MAAM,EAAG,QAAO;AAC3C,MAAI;AAEF,UAAM,UAAU;AAChB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,oBAAoB,CAAC,QAA2D;AAE3F,MAAI,KAAK,UAAU,YAAY;AAC7B,WAAO,eAAe,IAAI,UAAU,UAAU;AAAA,EAChD,OAAO;AAEL,WAAO,IAAI,UAAU,QAAQA,QAAO,CAAC,GAAG,yBAAyB;AAAA,EACnE;AACF;AAEO,IAAM,iBAAiB,CAAC,eAAqC;AAClE,SAAO,CAAC,cAAc,OAAO,eAAe,YAAY,CAAC,iBAAiB,UAAU,IAChF,CAAC,GAAG,yBAAyB,IAC7B,CAAC,2BAA2B,yBAAyB;AAC3D;;;ACjCA,SAAS,kBAAAC,uBAAmC;AAErC,IAAM,eAAe,CAAC,QAA2D;AACtF,SAAO,UAAU,IAAI,UAAU,IAAI;AACrC;AACO,IAAM,YAAY,CAAC,SAA+B;AACvD,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,SAAOA,gBAAe,KAAK;AAC7B;;;ACTA,SAAS,kBAAAC,iBAAgB,QAAAC,aAAyB;AAI3C,IAAM,qBAAqB,CAAC,QAA2D;AAC5F,SAAO,gBAAgB,KAAK,UAAU,WAAW;AACnD;AACO,IAAM,kBAAkB,CAAC,gBAAsC;AACpE,MAAI,gBAAgB,UAAa,gBAAgB,KAAM,QAAOC;AAC9D,QAAM,QAAqB,CAAC,GAAG,CAAC;AAChC,MAAI,OAAO,gBAAgB,YAAY,CAAC,WAAW,WAAW,EAAG,QAAO;AACxE,EAAAC,gBAAe,KAAK;AACpB,MAAI,CAAC,SAAS,WAAW,EAAG,QAAO;AACnC,SAAOA,gBAAe,KAAK;AAC7B;;;ACdA,SAAS,QAAAC,OAAM,QAAAC,aAAqC;AAE7C,IAAM,cAAsD,CAAC,QAAuB;AACzF,MAAI,CAAC,IAAI,OAAQ,QAAOD;AACxB,MAAI,OAAO,IAAI,WAAW,SAAU,QAAOA;AAC3C,MAAI;AACF,WAAO,OAAO,IAAI,OAAO,KAAK,MAAM,OAAO,IAAI,OAAO,IAAI,MAAM,OAAOC,QAAOD;AAAA,EAChF,QAAQ;AACN,WAAOA;AAAA,EACT;AACF;;;ACVA,SAAS,QAAAE,OAAM,QAAAC,aAAqC;AAQ7C,IAAM,eAAuD,CAAC,QAAuB;AAC1F,MAAI,CAAC,IAAI,QAAS,QAAOD;AACzB,MAAI,OAAO,IAAI,YAAY,SAAU,QAAOA;AAC5C,MAAI;AACF,WAAO,OAAO,IAAI,OAAO,KAAK,MAAM,OAAO,IAAI,OAAO,IAAI,MAAM,OAAOC,QAAOD;AAAA,EAChF,QAAQ;AACN,WAAOA;AAAA,EACT;AACF;;;AChBA,SAAS,QAAAE,OAAM,QAAAC,aAAqC;AAE7C,IAAM,YAAoD,CAAC,QAAuB;AACvF,MAAI,CAAC,IAAI,KAAM,QAAOD;AACtB,MAAI,OAAO,IAAI,SAAS,SAAU,QAAOA;AACzC,QAAM,OAAO,IAAI,KAAK,YAAY;AAClC,MAAI,SAAS,YAAY,SAAS,UAAW,QAAOA;AACpD,SAAOC;AACT;;;ACOA,IAAM,4BAA4B;AAAA,EAChC,YAAY,EAAE,OAAO,uBAAuB,QAAQ,EAAE;AACxD;AAEA,IAAM,0BAA0B;AAAA,EAC9B,iBAAiB,EAAE,OAAO,sBAAsB,QAAQ,EAAE;AAAA,EAC1D,oBAAoB,EAAE,OAAO,yBAAyB,QAAQ,EAAE;AAAA,EAChE,aAAa,EAAE,OAAO,qBAAqB,QAAQ,EAAE;AAAA,EACrD,gBAAgB,EAAE,OAAO,qBAAqB,QAAQ,EAAE;AAAA,EACxD,OAAO,EAAE,OAAO,eAAe,QAAQ,EAAE;AAAA,EACzC,cAAc,EAAE,OAAO,mBAAmB,QAAQ,EAAE;AAAA,EACpD,MAAM,EAAE,OAAO,cAAc,QAAQ,EAAE;AAAA,EACvC,eAAe,EAAE,OAAO,oBAAoB,QAAQ,EAAE;AAAA,EACtD,GAAG;AACL;AAEO,IAAM,kBAAkB;AAAA,EAC7B,oBAAoB,EAAE,OAAO,sBAAsB,QAAQ,EAAE;AAAA,EAC7D,QAAQ,EAAE,OAAO,aAAa,QAAQ,EAAE;AAAA,EACxC,YAAY,EAAE,OAAO,cAAc,QAAQ,EAAE;AAAA,EAC7C,MAAM,EAAE,OAAO,WAAW,QAAQ,EAAE;AAAA,EACpC,GAAG;AACL;;;AC3BO,IAAM,aAAa,OAIxB,QACyB;AACzB,QAAM,SAAS,OAAO;AAAA,IACpB,MAAM,QAAQ;AAAA,MACZ,OAAO,QAAQ,eAAe,EAAE,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,OAAO,CAAC,MAAM;AACtE,cAAM,WAAW,MAAM,MAAM,GAAG;AAChC,cAAM,WAAW,SAAS,IAAI,CAAC,MAAM,IAAI,MAAM;AAC/C,eAAO,CAAC,KAAK,QAAQ;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;;;AhBTA,IAAM,oBAAoB,CAAC,SAAkB,WAAkC;AAC7E,QAAM,EAAE,SAAS,SAAS,KAAK,IAAI;AACnC,SAAO,EAAE,SAAS,SAAS,QAAQ,gBAAgB,QAAQ,KAAK;AAClE;AAEO,IAAM,aAAa,CAAC,YAA0C,QAAQ,WAAW;AAEjF,IAAM,kBAAN,cAA6F,gBAAyB;AAAA,EAC3H,OAAyB,gBAA0B,CAAC,GAAG,MAAM,eAAe,2BAA2B;AAAA,EACvG,OAAyB,sBAA8B;AAAA,EAEpC,gBAAgB,OAAO,aAA6C;AACrF,UAAM,WAAW,UAAU,OAAO,SAAS,KAAK,CAAC;AACjD,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,SAAS,IAAuB,OAAO,YAAY;AACjD,cAAM,CAAC,OAAO,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA;AAAA,UAE5C,kBAAkB,SAAS,MAAM,WAAW,OAAO,CAAC;AAAA;AAAA,UAEpD,eAAe,SAAS,OAAO;AAAA,QACjC,CAAC;AACD,eAAO,EAAE,GAAG,OAAO,SAAS,CAAC,UAAU,EAAE;AAAA,MAC3C,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AACF;;;AiB5CA,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AACjC,SAAS,qCAAqC;AAIvC,IAAM,wBAAwB,MACnC;AAAA,EACE,EAAE,UAAU,EAAE,CAAC,SAAS,GAAG,EAAE,GAAG,QAAQ,iBAAiB;AAAA,EACzD;AAAA,IACE,SAAS,OAAO,WAAW;AACzB,YAAM,SAAS,MAAM,gBAAgB,OAAO,MAAM;AAClD,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":["PASS","PASS","incrementPossible","incrementTotal","incrementTotalAndPossible","incrementPossible","incrementTotal","incrementTotalAndPossible","PASS","incrementTotal","incrementTotal","incrementTotal","incrementTotal","PASS","PASS","incrementTotal","PASS","incrementTotal","incrementTotal","PASS","PASS","incrementTotal","FAIL","PASS","FAIL","PASS","FAIL","PASS"]}
@@ -38,12 +38,9 @@ var import_payload_builder = require("@xyo-network/payload-builder");
38
38
  var import_crypto_nft_score_model = require("@xyo-network/crypto-nft-score-model");
39
39
  var import_ethers = require("ethers");
40
40
  var scoreContractAddress = (nft) => {
41
- if (!nft.address)
42
- return import_crypto_nft_score_model.FAIL;
43
- if (typeof nft.address !== "string")
44
- return import_crypto_nft_score_model.FAIL;
45
- if (!(0, import_ethers.isAddress)(nft.address))
46
- return import_crypto_nft_score_model.FAIL;
41
+ if (!nft.address) return import_crypto_nft_score_model.FAIL;
42
+ if (typeof nft.address !== "string") return import_crypto_nft_score_model.FAIL;
43
+ if (!(0, import_ethers.isAddress)(nft.address)) return import_crypto_nft_score_model.FAIL;
47
44
  return import_crypto_nft_score_model.PASS;
48
45
  };
49
46
 
@@ -54,8 +51,7 @@ var import_crypto_nft_score_model2 = require("@xyo-network/crypto-nft-score-mode
54
51
  var import_url = require("@xylabs/url");
55
52
  var web3Protocols = ["ipfs:", "ar:"];
56
53
  var toUrl = (url) => {
57
- if (!url)
58
- return void 0;
54
+ if (!url) return void 0;
59
55
  try {
60
56
  return new import_url.URL(url);
61
57
  } catch {
@@ -72,20 +68,15 @@ var scoreNftAnimationUrl = (nft) => {
72
68
  };
73
69
  var scoreAnimationUrl = (animation_url) => {
74
70
  const score = [0, 0];
75
- if (animation_url === void 0 || animation_url === null)
76
- return import_crypto_nft_score_model2.PASS;
71
+ if (animation_url === void 0 || animation_url === null) return import_crypto_nft_score_model2.PASS;
77
72
  (0, import_crypto_nft_score_model2.incrementPossible)(score);
78
- if (typeof animation_url !== "string")
79
- return score;
73
+ if (typeof animation_url !== "string") return score;
80
74
  (0, import_crypto_nft_score_model2.incrementTotalAndPossible)(score);
81
- if (!isValidUrl(animation_url))
82
- return score;
75
+ if (!isValidUrl(animation_url)) return score;
83
76
  (0, import_crypto_nft_score_model2.incrementTotalAndPossible)(score);
84
- if (!isSecure(animation_url))
85
- return score;
77
+ if (!isSecure(animation_url)) return score;
86
78
  (0, import_crypto_nft_score_model2.incrementTotalAndPossible)(score);
87
- if (!isWeb3(animation_url))
88
- return score;
79
+ if (!isWeb3(animation_url)) return score;
89
80
  return (0, import_crypto_nft_score_model2.incrementTotal)(score);
90
81
  };
91
82
 
@@ -108,8 +99,7 @@ var isNonEmptyString = (value) => typeof value === "string" && value.length > 0;
108
99
  var isNonEmptyStringOrNumber = (value) => value === "number" || isNonEmptyString(value);
109
100
  var evaluateNftAttributes = (nft) => nft?.metadata?.attributes ? evaluateAttributes(nft?.metadata?.attributes) : [0, 1];
110
101
  var evaluateAttributes = (attributes) => {
111
- if (!attributes || !Array.isArray(attributes) || attributes.length === 0)
112
- return [0, 1];
102
+ if (!attributes || !Array.isArray(attributes) || attributes.length === 0) return [0, 1];
113
103
  const score = [0, 0];
114
104
  for (const attribute of attributes) {
115
105
  const [attributeTotal, attributePossible] = evaluateAttribute(attribute);
@@ -122,16 +112,13 @@ var evaluateAttribute = (attribute) => {
122
112
  const max_value = attribute?.max_value;
123
113
  const trait_type = attribute?.trait_type;
124
114
  const value = attribute?.value;
125
- if (!attribute || typeof attribute !== "object" || !isNonEmptyString(trait_type) || !isNonEmptyStringOrNumber(value))
126
- return score;
115
+ if (!attribute || typeof attribute !== "object" || !isNonEmptyString(trait_type) || !isNonEmptyStringOrNumber(value)) return score;
127
116
  (0, import_crypto_nft_score_model3.incrementTotal)(score);
128
117
  (0, import_crypto_nft_score_model3.incrementPossible)(score);
129
- if (validDisplayType(attribute))
130
- (0, import_crypto_nft_score_model3.incrementTotal)(score);
118
+ if (validDisplayType(attribute)) (0, import_crypto_nft_score_model3.incrementTotal)(score);
131
119
  if (max_value !== void 0) {
132
120
  (0, import_crypto_nft_score_model3.incrementPossible)(score);
133
- if (isNumber(max_value) && isNumber(value) && value <= max_value)
134
- (0, import_crypto_nft_score_model3.incrementTotal)(score);
121
+ if (isNumber(max_value) && isNumber(value) && value <= max_value) (0, import_crypto_nft_score_model3.incrementTotal)(score);
135
122
  }
136
123
  return score;
137
124
  };
@@ -139,24 +126,20 @@ var validDisplayType = (attribute) => {
139
126
  switch (attribute?.display_type) {
140
127
  case "number":
141
128
  case "boost_number": {
142
- if (isNumber(attribute?.value))
143
- return true;
129
+ if (isNumber(attribute?.value)) return true;
144
130
  break;
145
131
  }
146
132
  case "boost_percentage": {
147
- if (isPercentage(attribute?.value))
148
- return true;
133
+ if (isPercentage(attribute?.value)) return true;
149
134
  break;
150
135
  }
151
136
  case "date": {
152
- if (isDate(attribute?.value))
153
- return true;
137
+ if (isDate(attribute?.value)) return true;
154
138
  break;
155
139
  }
156
140
  case "string":
157
141
  case void 0: {
158
- if (isNonEmptyString(attribute?.value))
159
- return true;
142
+ if (isNonEmptyString(attribute?.value)) return true;
160
143
  break;
161
144
  }
162
145
  default: {
@@ -174,14 +157,11 @@ var scoreNftBackgroundColor = (nft) => {
174
157
  };
175
158
  var scoreBackgroundColor = (background_color) => {
176
159
  const score = [0, 0];
177
- if (background_color === void 0 || background_color === null)
178
- return import_crypto_nft_score_model4.PASS;
160
+ if (background_color === void 0 || background_color === null) return import_crypto_nft_score_model4.PASS;
179
161
  (0, import_crypto_nft_score_model4.incrementPossible)(score);
180
- if (typeof background_color !== "string")
181
- return score;
162
+ if (typeof background_color !== "string") return score;
182
163
  (0, import_crypto_nft_score_model4.incrementTotalAndPossible)(score);
183
- if (!isHexColor.test(background_color.toUpperCase()))
184
- return score;
164
+ if (!isHexColor.test(background_color.toUpperCase())) return score;
185
165
  return (0, import_crypto_nft_score_model4.incrementTotal)(score);
186
166
  };
187
167
 
@@ -192,8 +172,7 @@ var scoreNftDescription = (nft) => {
192
172
  };
193
173
  var scoreDescription = (description) => {
194
174
  const score = [0, 1];
195
- if (!description || typeof description !== "string")
196
- return score;
175
+ if (!description || typeof description !== "string") return score;
197
176
  return (0, import_crypto_nft_score_model5.incrementTotal)(score);
198
177
  };
199
178
 
@@ -204,11 +183,9 @@ var scoreNftExternalUrl = (nft) => {
204
183
  };
205
184
  var scoreExternalUrl = (external_url) => {
206
185
  const score = [0, 2];
207
- if (external_url === void 0 || external_url === null || typeof external_url !== "string" || !isValidUrl(external_url))
208
- return score;
186
+ if (external_url === void 0 || external_url === null || typeof external_url !== "string" || !isValidUrl(external_url)) return score;
209
187
  (0, import_crypto_nft_score_model6.incrementTotal)(score);
210
- if (!isSecure(external_url))
211
- return score;
188
+ if (!isSecure(external_url)) return score;
212
189
  return (0, import_crypto_nft_score_model6.incrementTotal)(score);
213
190
  };
214
191
 
@@ -224,14 +201,11 @@ var scoreNftImage = (nft) => {
224
201
  };
225
202
  var scoreImage = (image) => {
226
203
  const score = [0, MaxPossibleImageScore];
227
- if (!image || typeof image !== "string" || !isValidUrl(image))
228
- return score;
204
+ if (!image || typeof image !== "string" || !isValidUrl(image)) return score;
229
205
  (0, import_crypto_nft_score_model7.incrementTotal)(score);
230
- if (!isSecure(image))
231
- return score;
206
+ if (!isSecure(image)) return score;
232
207
  (0, import_crypto_nft_score_model7.incrementTotal)(score);
233
- if (!isWeb3(image))
234
- return score;
208
+ if (!isWeb3(image)) return score;
235
209
  (0, import_crypto_nft_score_model7.incrementTotal)(score);
236
210
  return score;
237
211
  };
@@ -241,8 +215,7 @@ var import_crypto_nft_score_model8 = require("@xyo-network/crypto-nft-score-mode
241
215
  var import_svg_parser = require("svg-parser");
242
216
  var MaxPossibleImageDataScore = 1;
243
217
  var isValidImageData = (image_data) => {
244
- if (!image_data.startsWith("<svg"))
245
- return false;
218
+ if (!image_data.startsWith("<svg")) return false;
246
219
  try {
247
220
  (0, import_svg_parser.parse)(image_data);
248
221
  return true;
@@ -268,8 +241,7 @@ var scoreNftName = (nft) => {
268
241
  };
269
242
  var scoreName = (name) => {
270
243
  const score = [0, 1];
271
- if (!name || typeof name !== "string")
272
- return score;
244
+ if (!name || typeof name !== "string") return score;
273
245
  return (0, import_crypto_nft_score_model9.incrementTotal)(score);
274
246
  };
275
247
 
@@ -279,24 +251,19 @@ var scoreNftYoutubeUrl = (nft) => {
279
251
  return scoreYoutubeUrl(nft?.metadata?.youtube_url);
280
252
  };
281
253
  var scoreYoutubeUrl = (youtube_url) => {
282
- if (youtube_url === void 0 || youtube_url === null)
283
- return import_crypto_nft_score_model10.PASS;
254
+ if (youtube_url === void 0 || youtube_url === null) return import_crypto_nft_score_model10.PASS;
284
255
  const score = [0, 2];
285
- if (typeof youtube_url !== "string" || !isValidUrl(youtube_url))
286
- return score;
256
+ if (typeof youtube_url !== "string" || !isValidUrl(youtube_url)) return score;
287
257
  (0, import_crypto_nft_score_model10.incrementTotal)(score);
288
- if (!isSecure(youtube_url))
289
- return score;
258
+ if (!isSecure(youtube_url)) return score;
290
259
  return (0, import_crypto_nft_score_model10.incrementTotal)(score);
291
260
  };
292
261
 
293
262
  // src/lib/rating/criteria/scoring/supply.ts
294
263
  var import_crypto_nft_score_model11 = require("@xyo-network/crypto-nft-score-model");
295
264
  var scoreSupply = (nft) => {
296
- if (!nft.supply)
297
- return import_crypto_nft_score_model11.FAIL;
298
- if (typeof nft.supply !== "string")
299
- return import_crypto_nft_score_model11.FAIL;
265
+ if (!nft.supply) return import_crypto_nft_score_model11.FAIL;
266
+ if (typeof nft.supply !== "string") return import_crypto_nft_score_model11.FAIL;
300
267
  try {
301
268
  return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? import_crypto_nft_score_model11.PASS : import_crypto_nft_score_model11.FAIL;
302
269
  } catch {
@@ -307,10 +274,8 @@ var scoreSupply = (nft) => {
307
274
  // src/lib/rating/criteria/scoring/tokenId.ts
308
275
  var import_crypto_nft_score_model12 = require("@xyo-network/crypto-nft-score-model");
309
276
  var scoreTokenId = (nft) => {
310
- if (!nft.tokenId)
311
- return import_crypto_nft_score_model12.FAIL;
312
- if (typeof nft.tokenId !== "string")
313
- return import_crypto_nft_score_model12.FAIL;
277
+ if (!nft.tokenId) return import_crypto_nft_score_model12.FAIL;
278
+ if (typeof nft.tokenId !== "string") return import_crypto_nft_score_model12.FAIL;
314
279
  try {
315
280
  return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? import_crypto_nft_score_model12.PASS : import_crypto_nft_score_model12.FAIL;
316
281
  } catch {
@@ -321,13 +286,10 @@ var scoreTokenId = (nft) => {
321
286
  // src/lib/rating/criteria/scoring/type.ts
322
287
  var import_crypto_nft_score_model13 = require("@xyo-network/crypto-nft-score-model");
323
288
  var scoreType = (nft) => {
324
- if (!nft.type)
325
- return import_crypto_nft_score_model13.FAIL;
326
- if (typeof nft.type !== "string")
327
- return import_crypto_nft_score_model13.FAIL;
289
+ if (!nft.type) return import_crypto_nft_score_model13.FAIL;
290
+ if (typeof nft.type !== "string") return import_crypto_nft_score_model13.FAIL;
328
291
  const type = nft.type.toUpperCase();
329
- if (type !== "ERC721" && type !== "ERC1155")
330
- return import_crypto_nft_score_model13.FAIL;
292
+ if (type !== "ERC721" && type !== "ERC1155") return import_crypto_nft_score_model13.FAIL;
331
293
  return import_crypto_nft_score_model13.PASS;
332
294
  };
333
295
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts","../../src/lib/rating/criteria/scoring/contract.ts","../../src/lib/rating/criteria/scoring/metadata/animationUrl.ts","../../src/lib/rating/criteria/scoring/metadata/lib/urlHelpers.ts","../../src/lib/rating/criteria/scoring/metadata/attributes/evaluateAttributes.ts","../../src/lib/rating/criteria/scoring/metadata/backgroundColor.ts","../../src/lib/rating/criteria/scoring/metadata/description.ts","../../src/lib/rating/criteria/scoring/metadata/externalUrl.ts","../../src/lib/rating/criteria/scoring/metadata/image.ts","../../src/lib/rating/criteria/scoring/metadata/imageData.ts","../../src/lib/rating/criteria/scoring/metadata/name.ts","../../src/lib/rating/criteria/scoring/metadata/youtubeUrl.ts","../../src/lib/rating/criteria/scoring/supply.ts","../../src/lib/rating/criteria/scoring/tokenId.ts","../../src/lib/rating/criteria/scoring/type.ts","../../src/lib/rating/criteria/scoringCriteria.ts","../../src/lib/rating/analyzeNft.ts","../../src/Plugin.ts"],"sourcesContent":["export * from './Diviner'\nexport * from './lib'\nexport { NftScoreDivinerPlugin as default, NftScoreDivinerPlugin } from './Plugin'\n","import {\n isNftInfo,\n NftInfo,\n NftScore,\n NftScoreDivinerConfig,\n NftScoreDivinerConfigSchema,\n NftScoreSchema,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { DivinerParams } from '@xyo-network/diviner-model'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema } from '@xyo-network/payload-model'\n\nimport { analyzeNft, NftAnalysis } from './lib'\n\nexport type NftScoreDivinerParams = DivinerParams<AnyConfigSchema<NftScoreDivinerConfig>>\n\nconst toNftScorePayload = (nftInfo: NftInfo, scores: NftAnalysis): NftScore => {\n const { address, chainId, type } = nftInfo\n return { address, chainId, schema: NftScoreSchema, scores, type }\n}\n\nexport const isNftScore = (payload: Payload): payload is NftScore => payload.schema === NftScoreSchema\n\nexport class NftScoreDiviner<TParams extends NftScoreDivinerParams = NftScoreDivinerParams> extends AbstractDiviner<TParams> {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, NftScoreDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = NftScoreDivinerConfigSchema\n\n protected override divineHandler = async (payloads?: Payload[]): Promise<Payload[]> => {\n const nftInfos = payloads?.filter(isNftInfo) ?? []\n const results = await Promise.all(\n nftInfos.map<Promise<NftScore>>(async (nftInfo) => {\n const [score, sourceHash] = await Promise.all([\n // Analyze the NFT\n toNftScorePayload(nftInfo, await analyzeNft(nftInfo)),\n // Hash the source payload\n PayloadBuilder.dataHash(nftInfo),\n ])\n return { ...score, sources: [sourceHash] }\n }),\n )\n return results\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\nimport { isAddress } from 'ethers'\n\nexport const scoreContractAddress: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.address) return FAIL\n if (typeof nft.address !== 'string') return FAIL\n if (!isAddress(nft.address)) return FAIL\n return PASS\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nexport const scoreNftAnimationUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreAnimationUrl(nft.metadata?.animation_url)\n}\n\nexport const scoreAnimationUrl = (animation_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (animation_url === undefined || animation_url === null) return PASS\n incrementPossible(score)\n if (typeof animation_url !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isValidUrl(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isSecure(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isWeb3(animation_url)) return score\n return incrementTotal(score)\n}\n","import { URL } from '@xylabs/url'\n\nexport const web3Protocols = ['ipfs:', 'ar:']\n\nexport const toUrl = (url?: string | null): URL | undefined => {\n if (!url) return undefined\n try {\n return new URL(url)\n } catch {\n return undefined\n }\n}\n\nexport const isValidUrl = (url?: string | null): boolean => toUrl(url) !== undefined\n// eslint-disable-next-line unicorn/prefer-includes\nexport const isWeb3 = (url?: string | null): boolean => web3Protocols.some((protocol) => protocol === toUrl(url)?.protocol)\nexport const isWeb2 = (url?: string | null): boolean => !isWeb3(url)\nexport const isSecure = (url?: string | null): boolean => isWeb3(url) || toUrl(url)?.protocol === 'https:'\n","import { NftAttribute, NftInfoFields, OpenSeaNftAttribute, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isDate = (value: unknown): value is Date => {\n if (isNumber(value)) {\n try {\n new Date(value)\n return true\n } catch {\n return false\n }\n }\n return false\n}\n\nconst isNumber = (value: unknown): value is number => typeof value === 'number'\n\nconst isPercentage = (value: unknown): boolean => isNumber(value) && value >= 0 && value <= 100\n\nconst isNonEmptyString = (value: unknown): value is string => typeof value === 'string' && value.length > 0\n\nconst isNonEmptyStringOrNumber = (value: unknown): value is string | number => value === 'number' || isNonEmptyString(value)\n\nexport const evaluateNftAttributes = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore =>\n nft?.metadata?.attributes ? evaluateAttributes(nft?.metadata?.attributes) : [0, 1]\n\nexport const evaluateAttributes = (attributes: NftAttribute[] | OpenSeaNftAttribute[] | unknown): ScaledScore => {\n if (!attributes || !Array.isArray(attributes) || attributes.length === 0) return [0, 1]\n const score: ScaledScore = [0, 0]\n for (const attribute of attributes) {\n const [attributeTotal, attributePossible] = evaluateAttribute(attribute)\n incrementTotalAndPossible(score, attributeTotal, attributePossible)\n }\n return [1, 1]\n}\n\nexport const evaluateAttribute = (attribute: OpenSeaNftAttribute): ScaledScore => {\n const score: ScaledScore = [0, 1]\n const max_value = attribute?.max_value\n const trait_type = attribute?.trait_type\n const value = attribute?.value\n\n // Validate trait_type & value\n if (!attribute || typeof attribute !== 'object' || !isNonEmptyString(trait_type) || !isNonEmptyStringOrNumber(value)) return score\n incrementTotal(score)\n\n // Validate display_type\n incrementPossible(score)\n if (validDisplayType(attribute)) incrementTotal(score)\n\n // Validate max_value\n if (max_value !== undefined) {\n incrementPossible(score)\n if (isNumber(max_value) && isNumber(value) && value <= max_value) incrementTotal(score)\n }\n\n return score\n}\n\nconst validDisplayType = (attribute: OpenSeaNftAttribute): boolean => {\n switch (attribute?.display_type) {\n case 'number':\n case 'boost_number': {\n if (isNumber(attribute?.value)) return true\n break\n }\n case 'boost_percentage': {\n if (isPercentage(attribute?.value)) return true\n break\n }\n case 'date': {\n if (isDate(attribute?.value)) return true\n break\n }\n case 'string':\n case undefined: {\n if (isNonEmptyString(attribute?.value)) return true\n break\n }\n default: {\n break\n }\n }\n return false\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isHexColor = /^[\\da-f]{6}$/i\n\nexport const scoreNftBackgroundColor = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreBackgroundColor(nft.metadata?.background_color)\n}\n\nexport const scoreBackgroundColor = (background_color: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (background_color === undefined || background_color === null) return PASS\n incrementPossible(score)\n if (typeof background_color !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isHexColor.test(background_color.toUpperCase())) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftDescription = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreDescription(nft.metadata?.description)\n}\n\nexport const scoreDescription = (description: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!description || typeof description !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftExternalUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreExternalUrl(nft?.metadata?.external_url)\n}\nexport const scoreExternalUrl = (external_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 2]\n if (external_url === undefined || external_url === null || typeof external_url !== 'string' || !isValidUrl(external_url)) return score\n incrementTotal(score)\n if (!isSecure(external_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nconst MaxPossibleImageScore = 3\n\nexport const scoreNftImage = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image) {\n return scoreImage(nft.metadata?.image)\n } else {\n // but there is image data, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image_data ? PASS : [0, MaxPossibleImageScore]\n }\n}\n\nexport const scoreImage = (image: unknown): ScaledScore => {\n const score: ScaledScore = [0, MaxPossibleImageScore]\n if (!image || typeof image !== 'string' || !isValidUrl(image)) return score\n incrementTotal(score)\n if (!isSecure(image)) return score\n incrementTotal(score)\n if (!isWeb3(image)) return score\n incrementTotal(score)\n return score\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\nimport { parse } from 'svg-parser'\n\nconst MaxPossibleImageDataScore = 1\n\n// NOTE: There is probably a deeper check we can do\n// here, but this is a good start\nconst isValidImageData = (image_data: string): boolean => {\n // If it doesn't start with an svg tag, it's not an svg\n if (!image_data.startsWith('<svg')) return false\n try {\n // If it can't be parsed, it's not an svg\n parse(image_data)\n return true\n } catch {\n return false\n }\n}\n\nexport const scoreNftImageData = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image_data) {\n return scoreImageData(nft.metadata?.image_data)\n } else {\n // but there is an image, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image ? PASS : [0, MaxPossibleImageDataScore]\n }\n}\n\nexport const scoreImageData = (image_data: unknown): ScaledScore => {\n return !image_data || typeof image_data !== 'string' || !isValidImageData(image_data) ?\n [0, MaxPossibleImageDataScore]\n : [MaxPossibleImageDataScore, MaxPossibleImageDataScore]\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftName = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreName(nft.metadata?.name)\n}\nexport const scoreName = (name: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!name || typeof name !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftYoutubeUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreYoutubeUrl(nft?.metadata?.youtube_url)\n}\nexport const scoreYoutubeUrl = (youtube_url: unknown): ScaledScore => {\n if (youtube_url === undefined || youtube_url === null) return PASS\n const score: ScaledScore = [0, 2]\n if (typeof youtube_url !== 'string' || !isValidUrl(youtube_url)) return score\n incrementTotal(score)\n if (!isSecure(youtube_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreSupply: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.supply) return FAIL\n if (typeof nft.supply !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\n/**\n * Callers SHALL NOT assume that ID numbers have any specific pattern to them, and\n * MUST treat the ID as a \"black box\"\n * @param nft\n * @returns\n */\nexport const scoreTokenId: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.tokenId) return FAIL\n if (typeof nft.tokenId !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreType: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.type) return FAIL\n if (typeof nft.type !== 'string') return FAIL\n const type = nft.type.toUpperCase()\n if (type !== 'ERC721' && type !== 'ERC1155') return FAIL\n return PASS\n}\n","import {\n evaluateNftAttributes,\n scoreContractAddress,\n scoreNftAnimationUrl,\n scoreNftBackgroundColor,\n scoreNftDescription,\n scoreNftExternalUrl,\n scoreNftImage,\n scoreNftImageData,\n scoreNftName,\n scoreNftYoutubeUrl,\n scoreSupply,\n scoreTokenId,\n scoreType,\n} from './scoring'\n\nconst attributesScoringCriteria = {\n Attributes: { score: evaluateNftAttributes, weight: 1 },\n}\n\nconst metadataScoringCriteria = {\n 'Animation URL': { score: scoreNftAnimationUrl, weight: 1 },\n 'Background Color': { score: scoreNftBackgroundColor, weight: 1 },\n Description: { score: scoreNftDescription, weight: 1 },\n 'External Url': { score: scoreNftExternalUrl, weight: 1 },\n Image: { score: scoreNftImage, weight: 1 },\n 'Image Data': { score: scoreNftImageData, weight: 1 },\n Name: { score: scoreNftName, weight: 1 },\n 'YouTube URL': { score: scoreNftYoutubeUrl, weight: 1 },\n ...attributesScoringCriteria,\n}\n\nexport const scoringCriteria = {\n 'Contract Address': { score: scoreContractAddress, weight: 1 },\n Supply: { score: scoreSupply, weight: 1 },\n 'Token Id': { score: scoreTokenId, weight: 1 },\n Type: { score: scoreType, weight: 1 },\n ...metadataScoringCriteria,\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { Score } from '@xyo-network/crypto-nft-score-model'\n\nimport { scoringCriteria } from './criteria'\n\nexport type ScoringCriteriaKey = keyof typeof scoringCriteria & PropertyKey\n\nexport type NftAnalysis = {\n [key in ScoringCriteriaKey]: Score\n}\n\nexport const analyzeNft = async (\n /**\n * The NFT to evaluate\n */\n nft: NftInfoFields,\n): Promise<NftAnalysis> => {\n const result = Object.fromEntries(\n await Promise.all(\n Object.entries(scoringCriteria).map(async ([key, { score, weight }]) => {\n const rawScore = await score(nft)\n const weighted = rawScore.map((v) => v * weight) as Score\n return [key, weighted] as const\n }),\n ),\n ) as NftAnalysis\n return result\n}\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetDivinerPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { NftScoreDiviner } from './Diviner'\n\nexport const NftScoreDivinerPlugin = () =>\n createPayloadSetDivinerPlugin<NftScoreDiviner>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n diviner: async (params) => {\n const result = await NftScoreDiviner.create(params)\n return result\n },\n },\n )\n"],"mappings":"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","names":["import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_payload_plugin"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts","../../src/lib/rating/criteria/scoring/contract.ts","../../src/lib/rating/criteria/scoring/metadata/animationUrl.ts","../../src/lib/rating/criteria/scoring/metadata/lib/urlHelpers.ts","../../src/lib/rating/criteria/scoring/metadata/attributes/evaluateAttributes.ts","../../src/lib/rating/criteria/scoring/metadata/backgroundColor.ts","../../src/lib/rating/criteria/scoring/metadata/description.ts","../../src/lib/rating/criteria/scoring/metadata/externalUrl.ts","../../src/lib/rating/criteria/scoring/metadata/image.ts","../../src/lib/rating/criteria/scoring/metadata/imageData.ts","../../src/lib/rating/criteria/scoring/metadata/name.ts","../../src/lib/rating/criteria/scoring/metadata/youtubeUrl.ts","../../src/lib/rating/criteria/scoring/supply.ts","../../src/lib/rating/criteria/scoring/tokenId.ts","../../src/lib/rating/criteria/scoring/type.ts","../../src/lib/rating/criteria/scoringCriteria.ts","../../src/lib/rating/analyzeNft.ts","../../src/Plugin.ts"],"sourcesContent":["export * from './Diviner'\nexport * from './lib'\nexport { NftScoreDivinerPlugin as default, NftScoreDivinerPlugin } from './Plugin'\n","import {\n isNftInfo,\n NftInfo,\n NftScore,\n NftScoreDivinerConfig,\n NftScoreDivinerConfigSchema,\n NftScoreSchema,\n} from '@xyo-network/crypto-nft-payload-plugin'\nimport { AbstractDiviner } from '@xyo-network/diviner-abstract'\nimport { DivinerParams } from '@xyo-network/diviner-model'\nimport { AnyConfigSchema } from '@xyo-network/module-model'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, Schema } from '@xyo-network/payload-model'\n\nimport { analyzeNft, NftAnalysis } from './lib'\n\nexport type NftScoreDivinerParams = DivinerParams<AnyConfigSchema<NftScoreDivinerConfig>>\n\nconst toNftScorePayload = (nftInfo: NftInfo, scores: NftAnalysis): NftScore => {\n const { address, chainId, type } = nftInfo\n return { address, chainId, schema: NftScoreSchema, scores, type }\n}\n\nexport const isNftScore = (payload: Payload): payload is NftScore => payload.schema === NftScoreSchema\n\nexport class NftScoreDiviner<TParams extends NftScoreDivinerParams = NftScoreDivinerParams> extends AbstractDiviner<TParams> {\n static override readonly configSchemas: Schema[] = [...super.configSchemas, NftScoreDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = NftScoreDivinerConfigSchema\n\n protected override divineHandler = async (payloads?: Payload[]): Promise<Payload[]> => {\n const nftInfos = payloads?.filter(isNftInfo) ?? []\n const results = await Promise.all(\n nftInfos.map<Promise<NftScore>>(async (nftInfo) => {\n const [score, sourceHash] = await Promise.all([\n // Analyze the NFT\n toNftScorePayload(nftInfo, await analyzeNft(nftInfo)),\n // Hash the source payload\n PayloadBuilder.dataHash(nftInfo),\n ])\n return { ...score, sources: [sourceHash] }\n }),\n )\n return results\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\nimport { isAddress } from 'ethers'\n\nexport const scoreContractAddress: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.address) return FAIL\n if (typeof nft.address !== 'string') return FAIL\n if (!isAddress(nft.address)) return FAIL\n return PASS\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nexport const scoreNftAnimationUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreAnimationUrl(nft.metadata?.animation_url)\n}\n\nexport const scoreAnimationUrl = (animation_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (animation_url === undefined || animation_url === null) return PASS\n incrementPossible(score)\n if (typeof animation_url !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isValidUrl(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isSecure(animation_url)) return score\n incrementTotalAndPossible(score)\n if (!isWeb3(animation_url)) return score\n return incrementTotal(score)\n}\n","import { URL } from '@xylabs/url'\n\nexport const web3Protocols = ['ipfs:', 'ar:']\n\nexport const toUrl = (url?: string | null): URL | undefined => {\n if (!url) return undefined\n try {\n return new URL(url)\n } catch {\n return undefined\n }\n}\n\nexport const isValidUrl = (url?: string | null): boolean => toUrl(url) !== undefined\n// eslint-disable-next-line unicorn/prefer-includes\nexport const isWeb3 = (url?: string | null): boolean => web3Protocols.some((protocol) => protocol === toUrl(url)?.protocol)\nexport const isWeb2 = (url?: string | null): boolean => !isWeb3(url)\nexport const isSecure = (url?: string | null): boolean => isWeb3(url) || toUrl(url)?.protocol === 'https:'\n","import { NftAttribute, NftInfoFields, OpenSeaNftAttribute, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isDate = (value: unknown): value is Date => {\n if (isNumber(value)) {\n try {\n new Date(value)\n return true\n } catch {\n return false\n }\n }\n return false\n}\n\nconst isNumber = (value: unknown): value is number => typeof value === 'number'\n\nconst isPercentage = (value: unknown): boolean => isNumber(value) && value >= 0 && value <= 100\n\nconst isNonEmptyString = (value: unknown): value is string => typeof value === 'string' && value.length > 0\n\nconst isNonEmptyStringOrNumber = (value: unknown): value is string | number => value === 'number' || isNonEmptyString(value)\n\nexport const evaluateNftAttributes = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore =>\n nft?.metadata?.attributes ? evaluateAttributes(nft?.metadata?.attributes) : [0, 1]\n\nexport const evaluateAttributes = (attributes: NftAttribute[] | OpenSeaNftAttribute[] | unknown): ScaledScore => {\n if (!attributes || !Array.isArray(attributes) || attributes.length === 0) return [0, 1]\n const score: ScaledScore = [0, 0]\n for (const attribute of attributes) {\n const [attributeTotal, attributePossible] = evaluateAttribute(attribute)\n incrementTotalAndPossible(score, attributeTotal, attributePossible)\n }\n return [1, 1]\n}\n\nexport const evaluateAttribute = (attribute: OpenSeaNftAttribute): ScaledScore => {\n const score: ScaledScore = [0, 1]\n const max_value = attribute?.max_value\n const trait_type = attribute?.trait_type\n const value = attribute?.value\n\n // Validate trait_type & value\n if (!attribute || typeof attribute !== 'object' || !isNonEmptyString(trait_type) || !isNonEmptyStringOrNumber(value)) return score\n incrementTotal(score)\n\n // Validate display_type\n incrementPossible(score)\n if (validDisplayType(attribute)) incrementTotal(score)\n\n // Validate max_value\n if (max_value !== undefined) {\n incrementPossible(score)\n if (isNumber(max_value) && isNumber(value) && value <= max_value) incrementTotal(score)\n }\n\n return score\n}\n\nconst validDisplayType = (attribute: OpenSeaNftAttribute): boolean => {\n switch (attribute?.display_type) {\n case 'number':\n case 'boost_number': {\n if (isNumber(attribute?.value)) return true\n break\n }\n case 'boost_percentage': {\n if (isPercentage(attribute?.value)) return true\n break\n }\n case 'date': {\n if (isDate(attribute?.value)) return true\n break\n }\n case 'string':\n case undefined: {\n if (isNonEmptyString(attribute?.value)) return true\n break\n }\n default: {\n break\n }\n }\n return false\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementPossible, incrementTotal, incrementTotalAndPossible, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nconst isHexColor = /^[\\da-f]{6}$/i\n\nexport const scoreNftBackgroundColor = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreBackgroundColor(nft.metadata?.background_color)\n}\n\nexport const scoreBackgroundColor = (background_color: unknown): ScaledScore => {\n const score: ScaledScore = [0, 0]\n if (background_color === undefined || background_color === null) return PASS\n incrementPossible(score)\n if (typeof background_color !== 'string') return score\n incrementTotalAndPossible(score)\n if (!isHexColor.test(background_color.toUpperCase())) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftDescription = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreDescription(nft.metadata?.description)\n}\n\nexport const scoreDescription = (description: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!description || typeof description !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftExternalUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreExternalUrl(nft?.metadata?.external_url)\n}\nexport const scoreExternalUrl = (external_url: unknown): ScaledScore => {\n const score: ScaledScore = [0, 2]\n if (external_url === undefined || external_url === null || typeof external_url !== 'string' || !isValidUrl(external_url)) return score\n incrementTotal(score)\n if (!isSecure(external_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl, isWeb3 } from './lib'\n\nconst MaxPossibleImageScore = 3\n\nexport const scoreNftImage = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image) {\n return scoreImage(nft.metadata?.image)\n } else {\n // but there is image data, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image_data ? PASS : [0, MaxPossibleImageScore]\n }\n}\n\nexport const scoreImage = (image: unknown): ScaledScore => {\n const score: ScaledScore = [0, MaxPossibleImageScore]\n if (!image || typeof image !== 'string' || !isValidUrl(image)) return score\n incrementTotal(score)\n if (!isSecure(image)) return score\n incrementTotal(score)\n if (!isWeb3(image)) return score\n incrementTotal(score)\n return score\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\nimport { parse } from 'svg-parser'\n\nconst MaxPossibleImageDataScore = 1\n\n// NOTE: There is probably a deeper check we can do\n// here, but this is a good start\nconst isValidImageData = (image_data: string): boolean => {\n // If it doesn't start with an svg tag, it's not an svg\n if (!image_data.startsWith('<svg')) return false\n try {\n // If it can't be parsed, it's not an svg\n parse(image_data)\n return true\n } catch {\n return false\n }\n}\n\nexport const scoreNftImageData = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n // If there's no image data\n if (nft?.metadata?.image_data) {\n return scoreImageData(nft.metadata?.image_data)\n } else {\n // but there is an image, skip this scoring criteria, otherwise fail it completely\n return nft.metadata?.image ? PASS : [0, MaxPossibleImageDataScore]\n }\n}\n\nexport const scoreImageData = (image_data: unknown): ScaledScore => {\n return !image_data || typeof image_data !== 'string' || !isValidImageData(image_data) ?\n [0, MaxPossibleImageDataScore]\n : [MaxPossibleImageDataScore, MaxPossibleImageDataScore]\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreNftName = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreName(nft.metadata?.name)\n}\nexport const scoreName = (name: unknown): ScaledScore => {\n const score: ScaledScore = [0, 1]\n if (!name || typeof name !== 'string') return score\n return incrementTotal(score)\n}\n","import { NftInfoFields, OpenSeaNftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { incrementTotal, PASS, ScaledScore } from '@xyo-network/crypto-nft-score-model'\n\nimport { isSecure, isValidUrl } from './lib'\n\nexport const scoreNftYoutubeUrl = (nft: NftInfoFields | OpenSeaNftInfoFields): ScaledScore => {\n return scoreYoutubeUrl(nft?.metadata?.youtube_url)\n}\nexport const scoreYoutubeUrl = (youtube_url: unknown): ScaledScore => {\n if (youtube_url === undefined || youtube_url === null) return PASS\n const score: ScaledScore = [0, 2]\n if (typeof youtube_url !== 'string' || !isValidUrl(youtube_url)) return score\n incrementTotal(score)\n if (!isSecure(youtube_url)) return score\n return incrementTotal(score)\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreSupply: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.supply) return FAIL\n if (typeof nft.supply !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\n/**\n * Callers SHALL NOT assume that ID numbers have any specific pattern to them, and\n * MUST treat the ID as a \"black box\"\n * @param nft\n * @returns\n */\nexport const scoreTokenId: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.tokenId) return FAIL\n if (typeof nft.tokenId !== 'string') return FAIL\n try {\n return BigInt(nft.tokenId) >= 0n && BigInt(nft.tokenId) < 2n ** 256n ? PASS : FAIL\n } catch {\n return FAIL\n }\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { FAIL, PASS, PassFailScoringFunction } from '@xyo-network/crypto-nft-score-model'\n\nexport const scoreType: PassFailScoringFunction<NftInfoFields> = (nft: NftInfoFields) => {\n if (!nft.type) return FAIL\n if (typeof nft.type !== 'string') return FAIL\n const type = nft.type.toUpperCase()\n if (type !== 'ERC721' && type !== 'ERC1155') return FAIL\n return PASS\n}\n","import {\n evaluateNftAttributes,\n scoreContractAddress,\n scoreNftAnimationUrl,\n scoreNftBackgroundColor,\n scoreNftDescription,\n scoreNftExternalUrl,\n scoreNftImage,\n scoreNftImageData,\n scoreNftName,\n scoreNftYoutubeUrl,\n scoreSupply,\n scoreTokenId,\n scoreType,\n} from './scoring'\n\nconst attributesScoringCriteria = {\n Attributes: { score: evaluateNftAttributes, weight: 1 },\n}\n\nconst metadataScoringCriteria = {\n 'Animation URL': { score: scoreNftAnimationUrl, weight: 1 },\n 'Background Color': { score: scoreNftBackgroundColor, weight: 1 },\n Description: { score: scoreNftDescription, weight: 1 },\n 'External Url': { score: scoreNftExternalUrl, weight: 1 },\n Image: { score: scoreNftImage, weight: 1 },\n 'Image Data': { score: scoreNftImageData, weight: 1 },\n Name: { score: scoreNftName, weight: 1 },\n 'YouTube URL': { score: scoreNftYoutubeUrl, weight: 1 },\n ...attributesScoringCriteria,\n}\n\nexport const scoringCriteria = {\n 'Contract Address': { score: scoreContractAddress, weight: 1 },\n Supply: { score: scoreSupply, weight: 1 },\n 'Token Id': { score: scoreTokenId, weight: 1 },\n Type: { score: scoreType, weight: 1 },\n ...metadataScoringCriteria,\n}\n","import { NftInfoFields } from '@xyo-network/crypto-nft-payload-plugin'\nimport { Score } from '@xyo-network/crypto-nft-score-model'\n\nimport { scoringCriteria } from './criteria'\n\nexport type ScoringCriteriaKey = keyof typeof scoringCriteria & PropertyKey\n\nexport type NftAnalysis = {\n [key in ScoringCriteriaKey]: Score\n}\n\nexport const analyzeNft = async (\n /**\n * The NFT to evaluate\n */\n nft: NftInfoFields,\n): Promise<NftAnalysis> => {\n const result = Object.fromEntries(\n await Promise.all(\n Object.entries(scoringCriteria).map(async ([key, { score, weight }]) => {\n const rawScore = await score(nft)\n const weighted = rawScore.map((v) => v * weight) as Score\n return [key, weighted] as const\n }),\n ),\n ) as NftAnalysis\n return result\n}\n","import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetDivinerPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { NftScoreDiviner } from './Diviner'\n\nexport const NftScoreDivinerPlugin = () =>\n createPayloadSetDivinerPlugin<NftScoreDiviner>(\n { required: { [NftSchema]: 1 }, schema: PayloadSetSchema },\n {\n diviner: async (params) => {\n const result = await NftScoreDiviner.create(params)\n return result\n },\n },\n )\n"],"mappings":"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","names":["import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_score_model","import_crypto_nft_payload_plugin"]}