@xyo-network/crypto-nft-collection-diviner-score-plugin 2.70.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +165 -0
- package/README.md +13 -0
- package/dist/cjs/Diviner.js +35 -0
- package/dist/cjs/Diviner.js.map +1 -0
- package/dist/cjs/Plugin.js +16 -0
- package/dist/cjs/Plugin.js.map +1 -0
- package/dist/cjs/index.js +11 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lib/index.js +5 -0
- package/dist/cjs/lib/index.js.map +1 -0
- package/dist/cjs/lib/rating/analyzeNftCollection.js +19 -0
- package/dist/cjs/lib/rating/analyzeNftCollection.js.map +1 -0
- package/dist/cjs/lib/rating/criteria/index.js +38 -0
- package/dist/cjs/lib/rating/criteria/index.js.map +1 -0
- package/dist/cjs/lib/rating/index.js +5 -0
- package/dist/cjs/lib/rating/index.js.map +1 -0
- package/dist/docs.json +20712 -0
- package/dist/esm/Diviner.js +25 -0
- package/dist/esm/Diviner.js.map +1 -0
- package/dist/esm/Plugin.js +11 -0
- package/dist/esm/Plugin.js.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/index.js +2 -0
- package/dist/esm/lib/index.js.map +1 -0
- package/dist/esm/lib/rating/analyzeNftCollection.js +14 -0
- package/dist/esm/lib/rating/analyzeNftCollection.js.map +1 -0
- package/dist/esm/lib/rating/criteria/index.js +34 -0
- package/dist/esm/lib/rating/criteria/index.js.map +1 -0
- package/dist/esm/lib/rating/index.js +2 -0
- package/dist/esm/lib/rating/index.js.map +1 -0
- package/dist/types/Diviner.d.ts +16 -0
- package/dist/types/Diviner.d.ts.map +1 -0
- package/dist/types/Plugin.d.ts +47 -0
- package/dist/types/Plugin.d.ts.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/lib/index.d.ts +2 -0
- package/dist/types/lib/index.d.ts.map +1 -0
- package/dist/types/lib/rating/analyzeNftCollection.d.ts +9 -0
- package/dist/types/lib/rating/analyzeNftCollection.d.ts.map +1 -0
- package/dist/types/lib/rating/criteria/index.d.ts +9 -0
- package/dist/types/lib/rating/criteria/index.d.ts.map +1 -0
- package/dist/types/lib/rating/index.d.ts +2 -0
- package/dist/types/lib/rating/index.d.ts.map +1 -0
- package/package.json +65 -0
- package/src/Diviner.ts +44 -0
- package/src/Plugin.ts +16 -0
- package/src/index.ts +9 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/rating/analyzeNftCollection.ts +28 -0
- package/src/lib/rating/criteria/index.ts +39 -0
- package/src/lib/rating/index.ts +1 -0
- package/typedoc.json +5 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AbstractDiviner } from '@xyo-network/abstract-diviner';
|
|
2
|
+
import { PayloadHasher } from '@xyo-network/core';
|
|
3
|
+
import { isNftCollectionInfoPayload, NftCollectionScoreDivinerConfigSchema, NftCollectionScoreSchema, } from '@xyo-network/crypto-nft-collection-payload-plugin';
|
|
4
|
+
import { analyzeNftCollection } from './lib';
|
|
5
|
+
const toNftCollectionScorePayload = (rating) => {
|
|
6
|
+
return { ...rating, schema: NftCollectionScoreSchema };
|
|
7
|
+
};
|
|
8
|
+
export const isNftCollectionScorePayload = (payload) => payload.schema === NftCollectionScoreSchema;
|
|
9
|
+
export class NftCollectionScoreDiviner extends AbstractDiviner {
|
|
10
|
+
static configSchemas = [NftCollectionScoreDivinerConfigSchema];
|
|
11
|
+
divineHandler = async (payloads) => {
|
|
12
|
+
const nfts = payloads?.filter(isNftCollectionInfoPayload) ?? [];
|
|
13
|
+
const results = await Promise.all(nfts.map(async (p) => {
|
|
14
|
+
const [score, sourceHash] = await Promise.all([
|
|
15
|
+
// Get score
|
|
16
|
+
toNftCollectionScorePayload(await analyzeNftCollection(p)),
|
|
17
|
+
// Hash sources
|
|
18
|
+
PayloadHasher.hashAsync(p),
|
|
19
|
+
]);
|
|
20
|
+
return { ...score, schema: NftCollectionScoreSchema, sources: [sourceHash] };
|
|
21
|
+
}));
|
|
22
|
+
return results;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=Diviner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Diviner.js","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EACL,0BAA0B,EAE1B,qCAAqC,EAErC,wBAAwB,GACzB,MAAM,mDAAmD,CAAA;AAK1D,OAAO,EAAE,oBAAoB,EAAyB,MAAM,OAAO,CAAA;AAInE,MAAM,2BAA2B,GAAG,CAAC,MAA6B,EAA6B,EAAE;IAC/F,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,wBAAwB,EAA0C,CAAA;AAChG,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,OAAgB,EAAwC,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,wBAAwB,CAAA;AAElJ,MAAM,OAAO,yBAEX,SAAQ,eAAwB;IAChC,MAAM,CAAU,aAAa,GAAG,CAAC,qCAAqC,CAAC,CAAA;IAEpD,aAAa,GAAG,KAAK,EAAE,QAAoB,EAAsB,EAAE;QACpF,MAAM,IAAI,GAAG,QAAQ,EAAE,MAAM,CAAC,0BAA0B,CAAC,IAAI,EAAE,CAAA;QAC/D,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,IAAI,CAAC,GAAG,CAAqC,KAAK,EAAE,CAAC,EAAE,EAAE;YACvD,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAC5C,YAAY;gBACZ,2BAA2B,CAAC,MAAM,oBAAoB,CAAC,CAAC,CAAC,CAAC;gBAC1D,eAAe;gBACf,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;aAC3B,CAAC,CAAA;YACF,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,OAAO,EAAE,CAAC,UAAU,CAAC,EAA+B,CAAA;QAC3G,CAAC,CAAC,CACH,CAAA;QACD,OAAO,OAAO,CAAA;IAChB,CAAC,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin';
|
|
2
|
+
import { PayloadSetSchema } from '@xyo-network/payload-model';
|
|
3
|
+
import { createPayloadSetDivinerPlugin } from '@xyo-network/payloadset-plugin';
|
|
4
|
+
import { NftCollectionScoreDiviner } from './Diviner';
|
|
5
|
+
export const NftCollectionScoreDivinerPlugin = () => createPayloadSetDivinerPlugin({ required: { [NftSchema]: 1 }, schema: PayloadSetSchema }, {
|
|
6
|
+
diviner: async (params) => {
|
|
7
|
+
const result = await NftCollectionScoreDiviner.create(params);
|
|
8
|
+
return result;
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=Plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Plugin.js","sourceRoot":"","sources":["../../src/Plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAC7D,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAA;AAE9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAA;AAErD,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,6BAA6B,CAC3B,EAAE,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAC1D;IACE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACxB,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAC7D,OAAO,MAAM,CAAA;IACf,CAAC;CACF,CACF,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { NftCollectionScoreDivinerPlugin } from './Plugin';
|
|
2
|
+
export * from './Diviner';
|
|
3
|
+
export * from './lib';
|
|
4
|
+
export { NftCollectionScoreDivinerPlugin };
|
|
5
|
+
// eslint-disable-next-line import/no-default-export
|
|
6
|
+
export default NftCollectionScoreDivinerPlugin;
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAA;AAE1D,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AAErB,OAAO,EAAE,+BAA+B,EAAE,CAAA;AAE1C,oDAAoD;AACpD,eAAe,+BAA+B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { scoringCriteria } from './criteria';
|
|
2
|
+
export const analyzeNftCollection = async (
|
|
3
|
+
/**
|
|
4
|
+
* The NFT to evaluate
|
|
5
|
+
*/
|
|
6
|
+
nft) => {
|
|
7
|
+
const result = Object.fromEntries(await Promise.all(Object.entries(scoringCriteria).map(async ([key, { score, weight }]) => {
|
|
8
|
+
const rawScore = await score(nft);
|
|
9
|
+
const weighted = rawScore.map((v) => v * weight);
|
|
10
|
+
return [key, weighted];
|
|
11
|
+
})));
|
|
12
|
+
return result;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=analyzeNftCollection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeNftCollection.js","sourceRoot":"","sources":["../../../../src/lib/rating/analyzeNftCollection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAQ5C,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK;AACvC;;GAEG;AACH,GAAsB,EACU,EAAE;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAC/B,MAAM,OAAO,CAAC,GAAG,CACf,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;QACrE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAU,CAAA;QACzD,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAU,CAAA;IACjC,CAAC,CAAC,CACH,CACuB,CAAA;IAC1B,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const median = 100000;
|
|
2
|
+
const defaultMu = Math.log(median);
|
|
3
|
+
const defaultSigma = 2;
|
|
4
|
+
// const mean = Math.exp(defaultMu + Math.pow(defaultSigma, 2) / 2)
|
|
5
|
+
const mode = Math.exp(defaultMu - Math.pow(defaultSigma, 2));
|
|
6
|
+
// console.log(`mean: ${mean} median: ${median} mode: ${mode}`)
|
|
7
|
+
/**
|
|
8
|
+
* Calculates the log-normal probability density
|
|
9
|
+
* @param x the value at which you want to calculate the probability density
|
|
10
|
+
* @param mu mean of the associated normal distribution
|
|
11
|
+
* @param sigma standard deviation of the associated normal distribution
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
const logNormalProbabilityDensity = (x, mu = defaultMu, sigma = defaultSigma) => {
|
|
15
|
+
if (x <= 0)
|
|
16
|
+
return 0;
|
|
17
|
+
const logX = Math.log(x);
|
|
18
|
+
return (1 / (x * sigma * Math.sqrt(2 * Math.PI))) * Math.exp(-0.5 * Math.pow((logX - mu) / sigma, 2));
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* For a lognormal distribution, the peak of the distribution is the mode
|
|
22
|
+
*/
|
|
23
|
+
const maxProbabilityDensity = logNormalProbabilityDensity(mode);
|
|
24
|
+
// console.log(`mode: ${mode} maxDensity: ${maxProbabilityDensity}`)
|
|
25
|
+
const scoreTotal = async (nft) => {
|
|
26
|
+
const density = logNormalProbabilityDensity(nft.total);
|
|
27
|
+
const normalized = density / maxProbabilityDensity;
|
|
28
|
+
const score = Math.min(Math.floor(normalized * 100), 100);
|
|
29
|
+
return await Promise.resolve([score, 100]);
|
|
30
|
+
};
|
|
31
|
+
export const scoringCriteria = {
|
|
32
|
+
total: { score: scoreTotal, weight: 1 },
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/lib/rating/criteria/index.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,GAAG,MAAM,CAAA;AACrB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAClC,MAAM,YAAY,GAAG,CAAC,CAAA;AACtB,mEAAmE;AACnE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAA;AAC5D,+DAA+D;AAE/D;;;;;;GAMG;AACH,MAAM,2BAA2B,GAAG,CAAC,CAAS,EAAE,KAAa,SAAS,EAAE,QAAgB,YAAY,EAAU,EAAE;IAC9G,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACpB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACxB,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;AACvG,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,IAAI,CAAC,CAAA;AAC/D,oEAAoE;AAEpE,MAAM,UAAU,GAAG,KAAK,EAAE,GAAsB,EAAkB,EAAE;IAClE,MAAM,OAAO,GAAG,2BAA2B,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACtD,MAAM,UAAU,GAAG,OAAO,GAAG,qBAAqB,CAAA;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;IACzD,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;AAC5C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE;CACxC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/rating/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AbstractDiviner } from '@xyo-network/abstract-diviner';
|
|
2
|
+
import { NftCollectionScoreDivinerConfig } from '@xyo-network/crypto-nft-collection-payload-plugin';
|
|
3
|
+
import { DivinerParams } from '@xyo-network/diviner-model';
|
|
4
|
+
import { AnyConfigSchema } from '@xyo-network/module';
|
|
5
|
+
import { Payload } from '@xyo-network/payload-model';
|
|
6
|
+
export type NftCollectionScoreDivinerParams = DivinerParams<AnyConfigSchema<NftCollectionScoreDivinerConfig>>;
|
|
7
|
+
export declare const isNftCollectionScorePayload: (payload: Payload) => payload is import("@xyo-network/payload-model").SchemaFields & import("@xyo-network/payload-model").PayloadFields & {
|
|
8
|
+
schema: "network.xyo.crypto.nft.collection.score";
|
|
9
|
+
} & Partial<Omit<import("@xyo-network/crypto-nft-collection-payload-plugin").NftCollectionAnalysis, "schema">> & {
|
|
10
|
+
schema: "network.xyo.crypto.nft.collection.score";
|
|
11
|
+
};
|
|
12
|
+
export declare class NftCollectionScoreDiviner<TParams extends NftCollectionScoreDivinerParams = NftCollectionScoreDivinerParams> extends AbstractDiviner<TParams> {
|
|
13
|
+
static configSchemas: "network.xyo.crypto.nft.collection.score.diviner.config"[];
|
|
14
|
+
protected divineHandler: (payloads?: Payload[]) => Promise<Payload[]>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=Diviner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,OAAO,EAEL,+BAA+B,EAIhC,MAAM,mDAAmD,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAIpD,MAAM,MAAM,+BAA+B,GAAG,aAAa,CAAC,eAAe,CAAC,+BAA+B,CAAC,CAAC,CAAA;AAM7G,eAAO,MAAM,2BAA2B,YAAa,OAAO;;;;CAAsF,CAAA;AAElJ,qBAAa,yBAAyB,CACpC,OAAO,SAAS,+BAA+B,GAAG,+BAA+B,CACjF,SAAQ,eAAe,CAAC,OAAO,CAAC;IAChC,OAAgB,aAAa,6DAA0C;IAEvE,UAAmB,aAAa,cAAqB,OAAO,EAAE,KAAG,QAAQ,OAAO,EAAE,CAAC,CAclF;CACF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { NftCollectionScoreDiviner } from './Diviner';
|
|
2
|
+
export declare const NftCollectionScoreDivinerPlugin: () => import("@xyo-network/payloadset-plugin").PayloadSetDivinerPlugin<NftCollectionScoreDiviner<import("@xyo-network/core").BaseParamsFields & {
|
|
3
|
+
account?: import("@xyo-network/account-model").AccountInstance | "random" | undefined;
|
|
4
|
+
accountDerivationPath?: string | undefined;
|
|
5
|
+
config: import("@xyo-network/payload-model").SchemaFields & import("@xyo-network/payload-model").PayloadFields & {
|
|
6
|
+
readonly archivist?: import("@xyo-network/module-model").ArchivistModuleConfig | undefined;
|
|
7
|
+
readonly name?: string | undefined;
|
|
8
|
+
readonly paging?: Record<string, {
|
|
9
|
+
size?: number | undefined;
|
|
10
|
+
}> | undefined;
|
|
11
|
+
readonly schema: string;
|
|
12
|
+
readonly security?: {
|
|
13
|
+
readonly allowAnonymous?: boolean | undefined;
|
|
14
|
+
readonly allowed?: Record<string, (string | import("@xyo-network/module-model").CosigningAddressSet)[]> | undefined;
|
|
15
|
+
readonly disallowed?: Record<string, string[]> | undefined;
|
|
16
|
+
} | undefined;
|
|
17
|
+
readonly sign?: boolean | undefined;
|
|
18
|
+
readonly storeQueries?: boolean | undefined;
|
|
19
|
+
} & Omit<Omit<import("@xyo-network/payload-model").SchemaFields & import("@xyo-network/payload-model").PayloadFields & {
|
|
20
|
+
readonly archivist?: import("@xyo-network/module-model").ArchivistModuleConfig | undefined;
|
|
21
|
+
readonly name?: string | undefined;
|
|
22
|
+
readonly paging?: Record<string, {
|
|
23
|
+
size?: number | undefined;
|
|
24
|
+
}> | undefined;
|
|
25
|
+
readonly schema: "network.xyo.crypto.nft.collection.score.diviner.config";
|
|
26
|
+
readonly security?: {
|
|
27
|
+
readonly allowAnonymous?: boolean | undefined;
|
|
28
|
+
readonly allowed?: Record<string, (string | import("@xyo-network/module-model").CosigningAddressSet)[]> | undefined;
|
|
29
|
+
readonly disallowed?: Record<string, string[]> | undefined;
|
|
30
|
+
} | undefined;
|
|
31
|
+
readonly sign?: boolean | undefined;
|
|
32
|
+
readonly storeQueries?: boolean | undefined;
|
|
33
|
+
} & Omit<{
|
|
34
|
+
schema: "network.xyo.crypto.nft.collection.score.diviner.config";
|
|
35
|
+
} & Omit<{
|
|
36
|
+
schema: "network.xyo.crypto.nft.collection.score.diviner.config";
|
|
37
|
+
}, "schema">, "schema"> & {
|
|
38
|
+
schema: "network.xyo.crypto.nft.collection.score.diviner.config";
|
|
39
|
+
}, "schema"> & {
|
|
40
|
+
schema: string;
|
|
41
|
+
}, "schema"> & {
|
|
42
|
+
schema: string;
|
|
43
|
+
};
|
|
44
|
+
ephemeralQueryAccountEnabled?: boolean | undefined;
|
|
45
|
+
wallet?: import("@xyo-network/wallet-model").WalletInstance | undefined;
|
|
46
|
+
}>>;
|
|
47
|
+
//# sourceMappingURL=Plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Plugin.d.ts","sourceRoot":"","sources":["../../src/Plugin.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAA;AAErD,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GASzC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAA;AAE1D,cAAc,WAAW,CAAA;AACzB,cAAc,OAAO,CAAA;AAErB,OAAO,EAAE,+BAA+B,EAAE,CAAA;AAG1C,eAAe,+BAA+B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NftCollectionInfo } from '@xyo-network/crypto-nft-collection-payload-plugin';
|
|
2
|
+
import { Score } from '@xyo-network/crypto-nft-score-model';
|
|
3
|
+
import { scoringCriteria } from './criteria';
|
|
4
|
+
export type ScoringCriteriaKey = keyof typeof scoringCriteria & PropertyKey;
|
|
5
|
+
export type NftCollectionAnalysis = {
|
|
6
|
+
[key in ScoringCriteriaKey]: Score;
|
|
7
|
+
};
|
|
8
|
+
export declare const analyzeNftCollection: (nft: NftCollectionInfo) => Promise<NftCollectionAnalysis>;
|
|
9
|
+
//# sourceMappingURL=analyzeNftCollection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeNftCollection.d.ts","sourceRoot":"","sources":["../../../../src/lib/rating/analyzeNftCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAA;AACrF,OAAO,EAAE,KAAK,EAAE,MAAM,qCAAqC,CAAA;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,eAAe,GAAG,WAAW,CAAA;AAE3E,MAAM,MAAM,qBAAqB,GAAG;KACjC,GAAG,IAAI,kBAAkB,GAAG,KAAK;CACnC,CAAA;AAED,eAAO,MAAM,oBAAoB,QAI1B,iBAAiB,KACrB,QAAQ,qBAAqB,CAW/B,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NftCollectionInfo } from '@xyo-network/crypto-nft-collection-payload-plugin';
|
|
2
|
+
import { Score } from '@xyo-network/crypto-nft-score-model';
|
|
3
|
+
export declare const scoringCriteria: {
|
|
4
|
+
total: {
|
|
5
|
+
score: (nft: NftCollectionInfo) => Promise<Score>;
|
|
6
|
+
weight: number;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/rating/criteria/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAA;AACrF,OAAO,EAAE,KAAK,EAAE,MAAM,qCAAqC,CAAA;AAmC3D,eAAO,MAAM,eAAe;;qBAPG,iBAAiB,KAAG,QAAQ,KAAK,CAAC;;;CAShE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/rating/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xyo-network/crypto-nft-collection-diviner-score-plugin",
|
|
3
|
+
"author": {
|
|
4
|
+
"email": "support@xyo.network",
|
|
5
|
+
"name": "XYO Development Team",
|
|
6
|
+
"url": "https://xyo.network"
|
|
7
|
+
},
|
|
8
|
+
"bugs": {
|
|
9
|
+
"email": "support@xyo.network",
|
|
10
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@xyo-network/abstract-diviner": "~2.70.9",
|
|
14
|
+
"@xyo-network/core": "~2.70.9",
|
|
15
|
+
"@xyo-network/crypto-nft-collection-payload-plugin": "~2.70.9",
|
|
16
|
+
"@xyo-network/crypto-nft-payload-plugin": "~2.70.9",
|
|
17
|
+
"@xyo-network/crypto-nft-score-model": "~2.70.9",
|
|
18
|
+
"@xyo-network/diviner-model": "~2.70.9",
|
|
19
|
+
"@xyo-network/module": "~2.70.9",
|
|
20
|
+
"@xyo-network/payload-model": "~2.70.9",
|
|
21
|
+
"@xyo-network/payloadset-plugin": "~2.70.9"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@xylabs/jest-helpers": "^2.9.3",
|
|
25
|
+
"@xylabs/ts-scripts-yarn3": "^2.19.0",
|
|
26
|
+
"@xylabs/tsconfig": "^2.19.0",
|
|
27
|
+
"ethers": "^5.7.2",
|
|
28
|
+
"jest": "^29.6.2",
|
|
29
|
+
"typescript": "^5.1.6"
|
|
30
|
+
},
|
|
31
|
+
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
32
|
+
"browser": "dist/esm/index.js",
|
|
33
|
+
"docs": "dist/docs.json",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"node": {
|
|
37
|
+
"import": "./dist/esm/index.js",
|
|
38
|
+
"require": "./dist/cjs/index.js"
|
|
39
|
+
},
|
|
40
|
+
"browser": {
|
|
41
|
+
"import": "./dist/esm/index.js",
|
|
42
|
+
"require": "./dist/cjs/index.js"
|
|
43
|
+
},
|
|
44
|
+
"default": "./dist/esm/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./dist/docs.json": {
|
|
47
|
+
"default": "./dist/docs.json"
|
|
48
|
+
},
|
|
49
|
+
"./package.json": "./package.json"
|
|
50
|
+
},
|
|
51
|
+
"main": "dist/cjs/index.js",
|
|
52
|
+
"module": "dist/esm/index.js",
|
|
53
|
+
"homepage": "https://xyo.network",
|
|
54
|
+
"license": "LGPL-3.0",
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
|
|
61
|
+
},
|
|
62
|
+
"sideEffects": false,
|
|
63
|
+
"types": "dist/types/index.d.ts",
|
|
64
|
+
"version": "2.70.9"
|
|
65
|
+
}
|
package/src/Diviner.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AbstractDiviner } from '@xyo-network/abstract-diviner'
|
|
2
|
+
import { PayloadHasher } from '@xyo-network/core'
|
|
3
|
+
import {
|
|
4
|
+
isNftCollectionInfoPayload,
|
|
5
|
+
NftCollectionScoreDivinerConfig,
|
|
6
|
+
NftCollectionScoreDivinerConfigSchema,
|
|
7
|
+
NftCollectionScorePayload,
|
|
8
|
+
NftCollectionScoreSchema,
|
|
9
|
+
} from '@xyo-network/crypto-nft-collection-payload-plugin'
|
|
10
|
+
import { DivinerParams } from '@xyo-network/diviner-model'
|
|
11
|
+
import { AnyConfigSchema } from '@xyo-network/module'
|
|
12
|
+
import { Payload } from '@xyo-network/payload-model'
|
|
13
|
+
|
|
14
|
+
import { analyzeNftCollection, NftCollectionAnalysis } from './lib'
|
|
15
|
+
|
|
16
|
+
export type NftCollectionScoreDivinerParams = DivinerParams<AnyConfigSchema<NftCollectionScoreDivinerConfig>>
|
|
17
|
+
|
|
18
|
+
const toNftCollectionScorePayload = (rating: NftCollectionAnalysis): NftCollectionScorePayload => {
|
|
19
|
+
return { ...rating, schema: NftCollectionScoreSchema } as unknown as NftCollectionScorePayload
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const isNftCollectionScorePayload = (payload: Payload): payload is NftCollectionScorePayload => payload.schema === NftCollectionScoreSchema
|
|
23
|
+
|
|
24
|
+
export class NftCollectionScoreDiviner<
|
|
25
|
+
TParams extends NftCollectionScoreDivinerParams = NftCollectionScoreDivinerParams,
|
|
26
|
+
> extends AbstractDiviner<TParams> {
|
|
27
|
+
static override configSchemas = [NftCollectionScoreDivinerConfigSchema]
|
|
28
|
+
|
|
29
|
+
protected override divineHandler = async (payloads?: Payload[]): Promise<Payload[]> => {
|
|
30
|
+
const nfts = payloads?.filter(isNftCollectionInfoPayload) ?? []
|
|
31
|
+
const results = await Promise.all(
|
|
32
|
+
nfts.map<Promise<NftCollectionScorePayload>>(async (p) => {
|
|
33
|
+
const [score, sourceHash] = await Promise.all([
|
|
34
|
+
// Get score
|
|
35
|
+
toNftCollectionScorePayload(await analyzeNftCollection(p)),
|
|
36
|
+
// Hash sources
|
|
37
|
+
PayloadHasher.hashAsync(p),
|
|
38
|
+
])
|
|
39
|
+
return { ...score, schema: NftCollectionScoreSchema, sources: [sourceHash] } as NftCollectionScorePayload
|
|
40
|
+
}),
|
|
41
|
+
)
|
|
42
|
+
return results
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/Plugin.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NftSchema } from '@xyo-network/crypto-nft-payload-plugin'
|
|
2
|
+
import { PayloadSetSchema } from '@xyo-network/payload-model'
|
|
3
|
+
import { createPayloadSetDivinerPlugin } from '@xyo-network/payloadset-plugin'
|
|
4
|
+
|
|
5
|
+
import { NftCollectionScoreDiviner } from './Diviner'
|
|
6
|
+
|
|
7
|
+
export const NftCollectionScoreDivinerPlugin = () =>
|
|
8
|
+
createPayloadSetDivinerPlugin<NftCollectionScoreDiviner>(
|
|
9
|
+
{ required: { [NftSchema]: 1 }, schema: PayloadSetSchema },
|
|
10
|
+
{
|
|
11
|
+
diviner: async (params) => {
|
|
12
|
+
const result = await NftCollectionScoreDiviner.create(params)
|
|
13
|
+
return result
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
)
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NftCollectionScoreDivinerPlugin } from './Plugin'
|
|
2
|
+
|
|
3
|
+
export * from './Diviner'
|
|
4
|
+
export * from './lib'
|
|
5
|
+
|
|
6
|
+
export { NftCollectionScoreDivinerPlugin }
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line import/no-default-export
|
|
9
|
+
export default NftCollectionScoreDivinerPlugin
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './rating'
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { NftCollectionInfo } from '@xyo-network/crypto-nft-collection-payload-plugin'
|
|
2
|
+
import { Score } from '@xyo-network/crypto-nft-score-model'
|
|
3
|
+
|
|
4
|
+
import { scoringCriteria } from './criteria'
|
|
5
|
+
|
|
6
|
+
export type ScoringCriteriaKey = keyof typeof scoringCriteria & PropertyKey
|
|
7
|
+
|
|
8
|
+
export type NftCollectionAnalysis = {
|
|
9
|
+
[key in ScoringCriteriaKey]: Score
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const analyzeNftCollection = async (
|
|
13
|
+
/**
|
|
14
|
+
* The NFT to evaluate
|
|
15
|
+
*/
|
|
16
|
+
nft: NftCollectionInfo,
|
|
17
|
+
): Promise<NftCollectionAnalysis> => {
|
|
18
|
+
const result = Object.fromEntries(
|
|
19
|
+
await Promise.all(
|
|
20
|
+
Object.entries(scoringCriteria).map(async ([key, { score, weight }]) => {
|
|
21
|
+
const rawScore = await score(nft)
|
|
22
|
+
const weighted = rawScore.map((v) => v * weight) as Score
|
|
23
|
+
return [key, weighted] as const
|
|
24
|
+
}),
|
|
25
|
+
),
|
|
26
|
+
) as NftCollectionAnalysis
|
|
27
|
+
return result
|
|
28
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NftCollectionInfo } from '@xyo-network/crypto-nft-collection-payload-plugin'
|
|
2
|
+
import { Score } from '@xyo-network/crypto-nft-score-model'
|
|
3
|
+
|
|
4
|
+
const median = 100000
|
|
5
|
+
const defaultMu = Math.log(median)
|
|
6
|
+
const defaultSigma = 2
|
|
7
|
+
// const mean = Math.exp(defaultMu + Math.pow(defaultSigma, 2) / 2)
|
|
8
|
+
const mode = Math.exp(defaultMu - Math.pow(defaultSigma, 2))
|
|
9
|
+
// console.log(`mean: ${mean} median: ${median} mode: ${mode}`)
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Calculates the log-normal probability density
|
|
13
|
+
* @param x the value at which you want to calculate the probability density
|
|
14
|
+
* @param mu mean of the associated normal distribution
|
|
15
|
+
* @param sigma standard deviation of the associated normal distribution
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
const logNormalProbabilityDensity = (x: number, mu: number = defaultMu, sigma: number = defaultSigma): number => {
|
|
19
|
+
if (x <= 0) return 0
|
|
20
|
+
const logX = Math.log(x)
|
|
21
|
+
return (1 / (x * sigma * Math.sqrt(2 * Math.PI))) * Math.exp(-0.5 * Math.pow((logX - mu) / sigma, 2))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* For a lognormal distribution, the peak of the distribution is the mode
|
|
26
|
+
*/
|
|
27
|
+
const maxProbabilityDensity = logNormalProbabilityDensity(mode)
|
|
28
|
+
// console.log(`mode: ${mode} maxDensity: ${maxProbabilityDensity}`)
|
|
29
|
+
|
|
30
|
+
const scoreTotal = async (nft: NftCollectionInfo): Promise<Score> => {
|
|
31
|
+
const density = logNormalProbabilityDensity(nft.total)
|
|
32
|
+
const normalized = density / maxProbabilityDensity
|
|
33
|
+
const score = Math.min(Math.floor(normalized * 100), 100)
|
|
34
|
+
return await Promise.resolve([score, 100])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const scoringCriteria = {
|
|
38
|
+
total: { score: scoreTotal, weight: 1 },
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './analyzeNftCollection'
|