@xyo-network/crypto-nft-collection-diviner-score-plugin 2.71.4 → 2.71.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/lib/rating/criteria/index.js +1 -1
- package/dist/cjs/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.js +3 -0
- package/dist/cjs/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.js.map +1 -1
- package/dist/cjs/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.js +53 -6
- package/dist/cjs/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.js.map +1 -1
- package/dist/cjs/lib/rating/criteria/scoring/total.js +19 -5
- package/dist/cjs/lib/rating/criteria/scoring/total.js.map +1 -1
- package/dist/docs.json +12 -12
- package/dist/esm/lib/rating/criteria/index.js +1 -1
- package/dist/esm/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.js +3 -0
- package/dist/esm/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.js.map +1 -1
- package/dist/esm/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.js +53 -6
- package/dist/esm/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.js.map +1 -1
- package/dist/esm/lib/rating/criteria/scoring/total.js +19 -5
- package/dist/esm/lib/rating/criteria/scoring/total.js.map +1 -1
- package/dist/types/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.d.ts.map +1 -1
- package/dist/types/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.d.ts +20 -0
- package/dist/types/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.d.ts.map +1 -1
- package/dist/types/lib/rating/criteria/scoring/total.d.ts +12 -0
- package/dist/types/lib/rating/criteria/scoring/total.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/lib/rating/criteria/index.ts +1 -1
- package/src/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.ts +2 -0
- package/src/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.ts +57 -6
- package/src/lib/rating/criteria/scoring/total.ts +19 -6
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.scoringCriteria = void 0;
|
|
4
4
|
const scoring_1 = require("./scoring");
|
|
5
|
-
exports.scoringCriteria = Object.assign(Object.assign({}, scoring_1.scoreMetadata), { Total: { score: scoring_1.scoreTotal, weight:
|
|
5
|
+
exports.scoringCriteria = Object.assign(Object.assign({}, scoring_1.scoreMetadata), { Total: { score: scoring_1.scoreTotal, weight: 2 } });
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -5,6 +5,9 @@ const crypto_nft_score_model_1 = require("@xyo-network/crypto-nft-score-model");
|
|
|
5
5
|
const maxScore = 10;
|
|
6
6
|
const scoreIndividualAttributes = (info) => {
|
|
7
7
|
const { attributes } = info.metrics.metadata;
|
|
8
|
+
const entries = Object.entries(attributes);
|
|
9
|
+
if (entries.length === 0)
|
|
10
|
+
return [0, maxScore];
|
|
8
11
|
const scores = Object.entries(attributes)
|
|
9
12
|
.map(([_trait, { values }]) => {
|
|
10
13
|
return Object.entries(values).map(([_traitValue, metrics]) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoreIndividualAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.ts"],"names":[],"mappings":";;;AACA,gFAAsE;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEZ,MAAM,yBAAyB,GAAG,CAAC,IAAmC,EAAS,EAAE;IACtF,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAQ,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE;YAClE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;YAClF,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC;SACD,IAAI,EAAE,CAAA;IACT,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9E,OAAO,IAAA,kCAAS,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"scoreIndividualAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.ts"],"names":[],"mappings":";;;AACA,gFAAsE;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEZ,MAAM,yBAAyB,GAAG,CAAC,IAAmC,EAAS,EAAE;IACtF,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAQ,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE;YAClE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;YAClF,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC;SACD,IAAI,EAAE,CAAA;IACT,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9E,OAAO,IAAA,kCAAS,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA;AAdY,QAAA,yBAAyB,6BAcrC"}
|
|
@@ -3,14 +3,61 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.scoreTotalAttributes = void 0;
|
|
4
4
|
const crypto_nft_score_model_1 = require("@xyo-network/crypto-nft-score-model");
|
|
5
5
|
const maxScore = 10;
|
|
6
|
+
/**
|
|
7
|
+
* Mean: What value is the distribution centered around
|
|
8
|
+
*/
|
|
9
|
+
const defaultMu = 0.15;
|
|
10
|
+
/**
|
|
11
|
+
* Standard Deviation: How spread out is the distribution
|
|
12
|
+
*/
|
|
13
|
+
const defaultSigma = 0.1;
|
|
14
|
+
/**
|
|
15
|
+
* Calculates the Gaussian probability density
|
|
16
|
+
* @param x
|
|
17
|
+
* @param mu Mean
|
|
18
|
+
* @param sigma Standard Deviation
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
const gaussianProbabilityDensity = (x, mu = defaultMu, sigma = defaultSigma) => {
|
|
22
|
+
const sqrtTwoPi = Math.sqrt(2 * Math.PI);
|
|
23
|
+
const denominator = sigma * sqrtTwoPi;
|
|
24
|
+
const power = -0.5 * Math.pow((x - mu) / sigma, 2);
|
|
25
|
+
return (1 / denominator) * Math.exp(power);
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* For a Gaussian distribution, the peak of the distribution is the mean
|
|
29
|
+
*/
|
|
30
|
+
const maxProbabilityDensity = gaussianProbabilityDensity(defaultMu);
|
|
31
|
+
/**
|
|
32
|
+
* We're working on some assumptions here:
|
|
33
|
+
*
|
|
34
|
+
* - If you have a 100% chance of getting a trait, everyone get's a trophy
|
|
35
|
+
* - If you have a 50% chance of getting a trait, it's not rare
|
|
36
|
+
* - If you have a 0% chance of getting a trait, it's not fun
|
|
37
|
+
*
|
|
38
|
+
* So we're looking for something Pareto-ish (somewhere between
|
|
39
|
+
* 80/20 or 90/10) as that's a good & sustainable model for the
|
|
40
|
+
* distribution of many traits in real life.
|
|
41
|
+
* However, we also don't want to maximally reward collections
|
|
42
|
+
* that have a lot of single attributes distributed uniformly
|
|
43
|
+
* (basically a 0% trait probably) as that's perfectly entropic
|
|
44
|
+
* but not very interesting (some overlap is desirable).
|
|
45
|
+
* So we're using a Gaussian distribution to model the
|
|
46
|
+
* probability density of the joint probability of all traits
|
|
47
|
+
* centered around 15%.
|
|
48
|
+
* @param info
|
|
49
|
+
* @returns
|
|
50
|
+
*/
|
|
6
51
|
const scoreTotalAttributes = (info) => {
|
|
7
52
|
const { attributes } = info.metrics.metadata;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
53
|
+
// This has somewhat of a filtering function by causing anything with 100% probability to
|
|
54
|
+
// add no value to the end score
|
|
55
|
+
const jointProbability = Object.entries(attributes).reduce((acc, [_trait, { metrics }]) => {
|
|
56
|
+
return acc * metrics.binomial.p;
|
|
57
|
+
}, 1);
|
|
58
|
+
const probabilityDensity = gaussianProbabilityDensity(jointProbability);
|
|
59
|
+
const score = [probabilityDensity, maxProbabilityDensity];
|
|
60
|
+
return (0, crypto_nft_score_model_1.normalize)(score, maxScore);
|
|
14
61
|
};
|
|
15
62
|
exports.scoreTotalAttributes = scoreTotalAttributes;
|
|
16
63
|
//# sourceMappingURL=scoreTotalAttributes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoreTotalAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.ts"],"names":[],"mappings":";;;AACA,gFAAsE;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"scoreTotalAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.ts"],"names":[],"mappings":";;;AACA,gFAAsE;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB;;GAEG;AACH,MAAM,SAAS,GAAG,IAAI,CAAA;AAEtB;;GAEG;AACH,MAAM,YAAY,GAAG,GAAG,CAAA;AAExB;;;;;;GAMG;AACH,MAAM,0BAA0B,GAAG,CAAC,CAAS,EAAE,KAAa,SAAS,EAAE,QAAgB,YAAY,EAAU,EAAE;IAC7G,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;IACxC,MAAM,WAAW,GAAG,KAAK,GAAG,SAAS,CAAA;IACrC,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAA;IAClD,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AAC5C,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,qBAAqB,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAA;AAEnE;;;;;;;;;;;;;;;;;;;GAmBG;AACI,MAAM,oBAAoB,GAAG,CAAC,IAAmC,EAAS,EAAE;IACjF,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;IAC5C,yFAAyF;IACzF,gCAAgC;IAChC,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE;QACxF,OAAO,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjC,CAAC,EAAE,CAAC,CAAC,CAAA;IACL,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,gBAAgB,CAAC,CAAA;IACvE,MAAM,KAAK,GAAU,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAA;IAChE,OAAO,IAAA,kCAAS,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA;AAVY,QAAA,oBAAoB,wBAUhC"}
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.scoreTotal = void 0;
|
|
4
4
|
const crypto_nft_score_model_1 = require("@xyo-network/crypto-nft-score-model");
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* This "magic" value was obtained using Solver in Excel
|
|
7
|
+
* to find the median, with mu/sigma fixed, which maximizes
|
|
8
|
+
* the distribution (the mode for lognormal) at 10,000
|
|
9
|
+
*/
|
|
10
|
+
const median = 81030839.8217352;
|
|
6
11
|
const defaultMu = Math.log(median);
|
|
7
|
-
const defaultSigma =
|
|
8
|
-
// const mean = Math.exp(defaultMu + Math.pow(defaultSigma, 2) / 2)
|
|
12
|
+
const defaultSigma = 3;
|
|
9
13
|
const mode = Math.exp(defaultMu - Math.pow(defaultSigma, 2));
|
|
10
|
-
// console.log(`mean: ${mean} median: ${median} mode: ${mode}`)
|
|
11
14
|
/**
|
|
12
15
|
* Calculates the log-normal probability density
|
|
13
16
|
* @param x the value at which you want to calculate the probability density
|
|
@@ -25,8 +28,19 @@ const logNormalProbabilityDensity = (x, mu = defaultMu, sigma = defaultSigma) =>
|
|
|
25
28
|
* For a lognormal distribution, the peak of the distribution is the mode
|
|
26
29
|
*/
|
|
27
30
|
const maxProbabilityDensity = logNormalProbabilityDensity(mode);
|
|
28
|
-
// console.log(`mode: ${mode} maxDensity: ${maxProbabilityDensity}`)
|
|
29
31
|
const maxScore = 10;
|
|
32
|
+
/**
|
|
33
|
+
* We're working on some assumptions here:
|
|
34
|
+
* - If there's < 1000 NFTs in your collection it starts becoming too niche
|
|
35
|
+
* - If there's > 20,000 NFTs in your collection it starts becoming too broad
|
|
36
|
+
* So there's a sweet spot somewhere between 2000 and 10,000
|
|
37
|
+
* where a collection has enough NFTs to be interesting, but
|
|
38
|
+
* not so many that it's teetering on a diluted money grab.
|
|
39
|
+
* To model that we're using a log-normal distribution optimized
|
|
40
|
+
* to maximally reward collections in the aforementioned range
|
|
41
|
+
* @param nft
|
|
42
|
+
* @returns
|
|
43
|
+
*/
|
|
30
44
|
const scoreTotal = (nft) => {
|
|
31
45
|
const density = logNormalProbabilityDensity(nft.total);
|
|
32
46
|
const score = [density, maxProbabilityDensity];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"total.js","sourceRoot":"","sources":["../../../../../../src/lib/rating/criteria/scoring/total.ts"],"names":[],"mappings":";;;AACA,gFAAsE;AAEtE,MAAM,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"total.js","sourceRoot":"","sources":["../../../../../../src/lib/rating/criteria/scoring/total.ts"],"names":[],"mappings":";;;AACA,gFAAsE;AAEtE;;;;GAIG;AACH,MAAM,MAAM,GAAG,gBAAgB,CAAA;AAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAClC,MAAM,YAAY,GAAG,CAAC,CAAA;AACtB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAA;AAC5D;;;;;;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;AAE/D,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB;;;;;;;;;;;GAWG;AACI,MAAM,UAAU,GAAG,CAAC,GAAuB,EAAS,EAAE;IAC3D,MAAM,OAAO,GAAG,2BAA2B,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACtD,MAAM,KAAK,GAAU,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAA;IACrD,OAAO,IAAA,kCAAS,EAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA;AAJY,QAAA,UAAU,cAItB"}
|
package/dist/docs.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/index.ts",
|
|
17
17
|
"line": 9,
|
|
18
18
|
"character": 0,
|
|
19
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
19
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/index.ts#L9"
|
|
20
20
|
}
|
|
21
21
|
],
|
|
22
22
|
"target": 1
|
|
@@ -3966,7 +3966,7 @@
|
|
|
3966
3966
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts",
|
|
3967
3967
|
"line": 29,
|
|
3968
3968
|
"character": 18,
|
|
3969
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
3969
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts#L29"
|
|
3970
3970
|
}
|
|
3971
3971
|
],
|
|
3972
3972
|
"type": {
|
|
@@ -7567,7 +7567,7 @@
|
|
|
7567
7567
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts",
|
|
7568
7568
|
"line": 31,
|
|
7569
7569
|
"character": 21,
|
|
7570
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
7570
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts#L31"
|
|
7571
7571
|
}
|
|
7572
7572
|
],
|
|
7573
7573
|
"signatures": [
|
|
@@ -7582,7 +7582,7 @@
|
|
|
7582
7582
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts",
|
|
7583
7583
|
"line": 31,
|
|
7584
7584
|
"character": 37,
|
|
7585
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
7585
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts#L31"
|
|
7586
7586
|
}
|
|
7587
7587
|
],
|
|
7588
7588
|
"parameters": [
|
|
@@ -16213,7 +16213,7 @@
|
|
|
16213
16213
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts",
|
|
16214
16214
|
"line": 26,
|
|
16215
16215
|
"character": 13,
|
|
16216
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
16216
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts#L26"
|
|
16217
16217
|
}
|
|
16218
16218
|
],
|
|
16219
16219
|
"typeParameters": [
|
|
@@ -16268,7 +16268,7 @@
|
|
|
16268
16268
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts",
|
|
16269
16269
|
"line": 8,
|
|
16270
16270
|
"character": 12,
|
|
16271
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
16271
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts#L8"
|
|
16272
16272
|
}
|
|
16273
16273
|
],
|
|
16274
16274
|
"type": {
|
|
@@ -16302,7 +16302,7 @@
|
|
|
16302
16302
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts",
|
|
16303
16303
|
"line": 18,
|
|
16304
16304
|
"character": 12,
|
|
16305
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
16305
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Diviner.ts#L18"
|
|
16306
16306
|
}
|
|
16307
16307
|
],
|
|
16308
16308
|
"type": {
|
|
@@ -16348,7 +16348,7 @@
|
|
|
16348
16348
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts",
|
|
16349
16349
|
"line": 6,
|
|
16350
16350
|
"character": 12,
|
|
16351
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
16351
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts#L6"
|
|
16352
16352
|
}
|
|
16353
16353
|
],
|
|
16354
16354
|
"type": {
|
|
@@ -16393,7 +16393,7 @@
|
|
|
16393
16393
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Plugin.ts",
|
|
16394
16394
|
"line": 7,
|
|
16395
16395
|
"character": 13,
|
|
16396
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
16396
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Plugin.ts#L7"
|
|
16397
16397
|
}
|
|
16398
16398
|
],
|
|
16399
16399
|
"signatures": [
|
|
@@ -16408,7 +16408,7 @@
|
|
|
16408
16408
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Plugin.ts",
|
|
16409
16409
|
"line": 7,
|
|
16410
16410
|
"character": 47,
|
|
16411
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
16411
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/Plugin.ts#L7"
|
|
16412
16412
|
}
|
|
16413
16413
|
],
|
|
16414
16414
|
"type": {
|
|
@@ -17983,7 +17983,7 @@
|
|
|
17983
17983
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts",
|
|
17984
17984
|
"line": 12,
|
|
17985
17985
|
"character": 13,
|
|
17986
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
17986
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts#L12"
|
|
17987
17987
|
}
|
|
17988
17988
|
],
|
|
17989
17989
|
"signatures": [
|
|
@@ -17998,7 +17998,7 @@
|
|
|
17998
17998
|
"fileName": "plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts",
|
|
17999
17999
|
"line": 12,
|
|
18000
18000
|
"character": 36,
|
|
18001
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/
|
|
18001
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/blob/746cc37b4/packages/plugins/packages/payloadset/packages/crypto/packages/nft/packages/collection/diviner/src/lib/rating/analyzeNftCollection.ts#L12"
|
|
18002
18002
|
}
|
|
18003
18003
|
],
|
|
18004
18004
|
"parameters": [
|
|
@@ -2,6 +2,9 @@ import { normalize } from '@xyo-network/crypto-nft-score-model';
|
|
|
2
2
|
const maxScore = 10;
|
|
3
3
|
export const scoreIndividualAttributes = (info) => {
|
|
4
4
|
const { attributes } = info.metrics.metadata;
|
|
5
|
+
const entries = Object.entries(attributes);
|
|
6
|
+
if (entries.length === 0)
|
|
7
|
+
return [0, maxScore];
|
|
5
8
|
const scores = Object.entries(attributes)
|
|
6
9
|
.map(([_trait, { values }]) => {
|
|
7
10
|
return Object.entries(values).map(([_traitValue, metrics]) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoreIndividualAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAS,MAAM,qCAAqC,CAAA;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,IAAmC,EAAS,EAAE;IACtF,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAQ,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE;YAClE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;YAClF,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC;SACD,IAAI,EAAE,CAAA;IACT,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9E,OAAO,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA"}
|
|
1
|
+
{"version":3,"file":"scoreIndividualAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAS,MAAM,qCAAqC,CAAA;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,IAAmC,EAAS,EAAE;IACtF,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;QAC5B,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAQ,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE;YAClE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;YAClF,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC;SACD,IAAI,EAAE,CAAA;IACT,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9E,OAAO,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA"}
|
|
@@ -1,12 +1,59 @@
|
|
|
1
1
|
import { normalize } from '@xyo-network/crypto-nft-score-model';
|
|
2
2
|
const maxScore = 10;
|
|
3
|
+
/**
|
|
4
|
+
* Mean: What value is the distribution centered around
|
|
5
|
+
*/
|
|
6
|
+
const defaultMu = 0.15;
|
|
7
|
+
/**
|
|
8
|
+
* Standard Deviation: How spread out is the distribution
|
|
9
|
+
*/
|
|
10
|
+
const defaultSigma = 0.1;
|
|
11
|
+
/**
|
|
12
|
+
* Calculates the Gaussian probability density
|
|
13
|
+
* @param x
|
|
14
|
+
* @param mu Mean
|
|
15
|
+
* @param sigma Standard Deviation
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
const gaussianProbabilityDensity = (x, mu = defaultMu, sigma = defaultSigma) => {
|
|
19
|
+
const sqrtTwoPi = Math.sqrt(2 * Math.PI);
|
|
20
|
+
const denominator = sigma * sqrtTwoPi;
|
|
21
|
+
const power = -0.5 * Math.pow((x - mu) / sigma, 2);
|
|
22
|
+
return (1 / denominator) * Math.exp(power);
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* For a Gaussian distribution, the peak of the distribution is the mean
|
|
26
|
+
*/
|
|
27
|
+
const maxProbabilityDensity = gaussianProbabilityDensity(defaultMu);
|
|
28
|
+
/**
|
|
29
|
+
* We're working on some assumptions here:
|
|
30
|
+
*
|
|
31
|
+
* - If you have a 100% chance of getting a trait, everyone get's a trophy
|
|
32
|
+
* - If you have a 50% chance of getting a trait, it's not rare
|
|
33
|
+
* - If you have a 0% chance of getting a trait, it's not fun
|
|
34
|
+
*
|
|
35
|
+
* So we're looking for something Pareto-ish (somewhere between
|
|
36
|
+
* 80/20 or 90/10) as that's a good & sustainable model for the
|
|
37
|
+
* distribution of many traits in real life.
|
|
38
|
+
* However, we also don't want to maximally reward collections
|
|
39
|
+
* that have a lot of single attributes distributed uniformly
|
|
40
|
+
* (basically a 0% trait probably) as that's perfectly entropic
|
|
41
|
+
* but not very interesting (some overlap is desirable).
|
|
42
|
+
* So we're using a Gaussian distribution to model the
|
|
43
|
+
* probability density of the joint probability of all traits
|
|
44
|
+
* centered around 15%.
|
|
45
|
+
* @param info
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
3
48
|
export const scoreTotalAttributes = (info) => {
|
|
4
49
|
const { attributes } = info.metrics.metadata;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
50
|
+
// This has somewhat of a filtering function by causing anything with 100% probability to
|
|
51
|
+
// add no value to the end score
|
|
52
|
+
const jointProbability = Object.entries(attributes).reduce((acc, [_trait, { metrics }]) => {
|
|
53
|
+
return acc * metrics.binomial.p;
|
|
54
|
+
}, 1);
|
|
55
|
+
const probabilityDensity = gaussianProbabilityDensity(jointProbability);
|
|
56
|
+
const score = [probabilityDensity, maxProbabilityDensity];
|
|
57
|
+
return normalize(score, maxScore);
|
|
11
58
|
};
|
|
12
59
|
//# sourceMappingURL=scoreTotalAttributes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoreTotalAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAS,MAAM,qCAAqC,CAAA;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB,MAAM,
|
|
1
|
+
{"version":3,"file":"scoreTotalAttributes.js","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAS,MAAM,qCAAqC,CAAA;AAEtE,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB;;GAEG;AACH,MAAM,SAAS,GAAG,IAAI,CAAA;AAEtB;;GAEG;AACH,MAAM,YAAY,GAAG,GAAG,CAAA;AAExB;;;;;;GAMG;AACH,MAAM,0BAA0B,GAAG,CAAC,CAAS,EAAE,KAAa,SAAS,EAAE,QAAgB,YAAY,EAAU,EAAE;IAC7G,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;IACxC,MAAM,WAAW,GAAG,KAAK,GAAG,SAAS,CAAA;IACrC,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAA;IAClD,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AAC5C,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,qBAAqB,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAA;AAEnE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAmC,EAAS,EAAE;IACjF,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAA;IAC5C,yFAAyF;IACzF,gCAAgC;IAChC,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE;QACxF,OAAO,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjC,CAAC,EAAE,CAAC,CAAC,CAAA;IACL,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,gBAAgB,CAAC,CAAA;IACvE,MAAM,KAAK,GAAU,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAA;IAChE,OAAO,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { normalize } from '@xyo-network/crypto-nft-score-model';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* This "magic" value was obtained using Solver in Excel
|
|
4
|
+
* to find the median, with mu/sigma fixed, which maximizes
|
|
5
|
+
* the distribution (the mode for lognormal) at 10,000
|
|
6
|
+
*/
|
|
7
|
+
const median = 81030839.8217352;
|
|
3
8
|
const defaultMu = Math.log(median);
|
|
4
|
-
const defaultSigma =
|
|
5
|
-
// const mean = Math.exp(defaultMu + Math.pow(defaultSigma, 2) / 2)
|
|
9
|
+
const defaultSigma = 3;
|
|
6
10
|
const mode = Math.exp(defaultMu - Math.pow(defaultSigma, 2));
|
|
7
|
-
// console.log(`mean: ${mean} median: ${median} mode: ${mode}`)
|
|
8
11
|
/**
|
|
9
12
|
* Calculates the log-normal probability density
|
|
10
13
|
* @param x the value at which you want to calculate the probability density
|
|
@@ -22,8 +25,19 @@ const logNormalProbabilityDensity = (x, mu = defaultMu, sigma = defaultSigma) =>
|
|
|
22
25
|
* For a lognormal distribution, the peak of the distribution is the mode
|
|
23
26
|
*/
|
|
24
27
|
const maxProbabilityDensity = logNormalProbabilityDensity(mode);
|
|
25
|
-
// console.log(`mode: ${mode} maxDensity: ${maxProbabilityDensity}`)
|
|
26
28
|
const maxScore = 10;
|
|
29
|
+
/**
|
|
30
|
+
* We're working on some assumptions here:
|
|
31
|
+
* - If there's < 1000 NFTs in your collection it starts becoming too niche
|
|
32
|
+
* - If there's > 20,000 NFTs in your collection it starts becoming too broad
|
|
33
|
+
* So there's a sweet spot somewhere between 2000 and 10,000
|
|
34
|
+
* where a collection has enough NFTs to be interesting, but
|
|
35
|
+
* not so many that it's teetering on a diluted money grab.
|
|
36
|
+
* To model that we're using a log-normal distribution optimized
|
|
37
|
+
* to maximally reward collections in the aforementioned range
|
|
38
|
+
* @param nft
|
|
39
|
+
* @returns
|
|
40
|
+
*/
|
|
27
41
|
export const scoreTotal = (nft) => {
|
|
28
42
|
const density = logNormalProbabilityDensity(nft.total);
|
|
29
43
|
const score = [density, maxProbabilityDensity];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"total.js","sourceRoot":"","sources":["../../../../../../src/lib/rating/criteria/scoring/total.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAS,MAAM,qCAAqC,CAAA;AAEtE,MAAM,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"total.js","sourceRoot":"","sources":["../../../../../../src/lib/rating/criteria/scoring/total.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAS,MAAM,qCAAqC,CAAA;AAEtE;;;;GAIG;AACH,MAAM,MAAM,GAAG,gBAAgB,CAAA;AAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAClC,MAAM,YAAY,GAAG,CAAC,CAAA;AACtB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAA;AAC5D;;;;;;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;AAE/D,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAuB,EAAS,EAAE;IAC3D,MAAM,OAAO,GAAG,2BAA2B,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACtD,MAAM,KAAK,GAAU,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAA;IACrD,OAAO,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AACnC,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoreIndividualAttributes.d.ts","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAA;AACjG,OAAO,EAAa,KAAK,EAAE,MAAM,qCAAqC,CAAA;AAItE,eAAO,MAAM,yBAAyB,SAAU,6BAA6B,KAAG,
|
|
1
|
+
{"version":3,"file":"scoreIndividualAttributes.d.ts","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreIndividualAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAA;AACjG,OAAO,EAAa,KAAK,EAAE,MAAM,qCAAqC,CAAA;AAItE,eAAO,MAAM,yBAAyB,SAAU,6BAA6B,KAAG,KAc/E,CAAA"}
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import { NftCollectionAttributeMetrics } from '@xyo-network/crypto-nft-collection-payload-plugin';
|
|
2
2
|
import { Score } from '@xyo-network/crypto-nft-score-model';
|
|
3
|
+
/**
|
|
4
|
+
* We're working on some assumptions here:
|
|
5
|
+
*
|
|
6
|
+
* - If you have a 100% chance of getting a trait, everyone get's a trophy
|
|
7
|
+
* - If you have a 50% chance of getting a trait, it's not rare
|
|
8
|
+
* - If you have a 0% chance of getting a trait, it's not fun
|
|
9
|
+
*
|
|
10
|
+
* So we're looking for something Pareto-ish (somewhere between
|
|
11
|
+
* 80/20 or 90/10) as that's a good & sustainable model for the
|
|
12
|
+
* distribution of many traits in real life.
|
|
13
|
+
* However, we also don't want to maximally reward collections
|
|
14
|
+
* that have a lot of single attributes distributed uniformly
|
|
15
|
+
* (basically a 0% trait probably) as that's perfectly entropic
|
|
16
|
+
* but not very interesting (some overlap is desirable).
|
|
17
|
+
* So we're using a Gaussian distribution to model the
|
|
18
|
+
* probability density of the joint probability of all traits
|
|
19
|
+
* centered around 15%.
|
|
20
|
+
* @param info
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
3
23
|
export declare const scoreTotalAttributes: (info: NftCollectionAttributeMetrics) => Score;
|
|
4
24
|
//# sourceMappingURL=scoreTotalAttributes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoreTotalAttributes.d.ts","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAA;AACjG,OAAO,EAAa,KAAK,EAAE,MAAM,qCAAqC,CAAA;
|
|
1
|
+
{"version":3,"file":"scoreTotalAttributes.d.ts","sourceRoot":"","sources":["../../../../../../../src/lib/rating/criteria/scoring/metadata/scoreTotalAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,mDAAmD,CAAA;AACjG,OAAO,EAAa,KAAK,EAAE,MAAM,qCAAqC,CAAA;AAiCtE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,SAAU,6BAA6B,KAAG,KAU1E,CAAA"}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { NftCollectionCount } from '@xyo-network/crypto-nft-collection-payload-plugin';
|
|
2
2
|
import { Score } from '@xyo-network/crypto-nft-score-model';
|
|
3
|
+
/**
|
|
4
|
+
* We're working on some assumptions here:
|
|
5
|
+
* - If there's < 1000 NFTs in your collection it starts becoming too niche
|
|
6
|
+
* - If there's > 20,000 NFTs in your collection it starts becoming too broad
|
|
7
|
+
* So there's a sweet spot somewhere between 2000 and 10,000
|
|
8
|
+
* where a collection has enough NFTs to be interesting, but
|
|
9
|
+
* not so many that it's teetering on a diluted money grab.
|
|
10
|
+
* To model that we're using a log-normal distribution optimized
|
|
11
|
+
* to maximally reward collections in the aforementioned range
|
|
12
|
+
* @param nft
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
3
15
|
export declare const scoreTotal: (nft: NftCollectionCount) => Score;
|
|
4
16
|
//# sourceMappingURL=total.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"total.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/rating/criteria/scoring/total.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAA;AACtF,OAAO,EAAa,KAAK,EAAE,MAAM,qCAAqC,CAAA;
|
|
1
|
+
{"version":3,"file":"total.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/rating/criteria/scoring/total.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAA;AACtF,OAAO,EAAa,KAAK,EAAE,MAAM,qCAAqC,CAAA;AA+BtE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,QAAS,kBAAkB,KAAG,KAIpD,CAAA"}
|
package/package.json
CHANGED
|
@@ -10,15 +10,15 @@
|
|
|
10
10
|
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@xyo-network/abstract-diviner": "~2.71.
|
|
14
|
-
"@xyo-network/core": "~2.71.
|
|
15
|
-
"@xyo-network/crypto-nft-collection-payload-plugin": "~2.71.
|
|
16
|
-
"@xyo-network/crypto-nft-payload-plugin": "~2.71.
|
|
17
|
-
"@xyo-network/crypto-nft-score-model": "~2.71.
|
|
18
|
-
"@xyo-network/diviner-model": "~2.71.
|
|
19
|
-
"@xyo-network/module": "~2.71.
|
|
20
|
-
"@xyo-network/payload-model": "~2.71.
|
|
21
|
-
"@xyo-network/payloadset-plugin": "~2.71.
|
|
13
|
+
"@xyo-network/abstract-diviner": "~2.71.5",
|
|
14
|
+
"@xyo-network/core": "~2.71.5",
|
|
15
|
+
"@xyo-network/crypto-nft-collection-payload-plugin": "~2.71.5",
|
|
16
|
+
"@xyo-network/crypto-nft-payload-plugin": "~2.71.5",
|
|
17
|
+
"@xyo-network/crypto-nft-score-model": "~2.71.5",
|
|
18
|
+
"@xyo-network/diviner-model": "~2.71.5",
|
|
19
|
+
"@xyo-network/module": "~2.71.5",
|
|
20
|
+
"@xyo-network/payload-model": "~2.71.5",
|
|
21
|
+
"@xyo-network/payloadset-plugin": "~2.71.5"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@xylabs/jest-helpers": "^2.9.3",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
},
|
|
62
62
|
"sideEffects": false,
|
|
63
63
|
"types": "dist/types/index.d.ts",
|
|
64
|
-
"version": "2.71.
|
|
64
|
+
"version": "2.71.5"
|
|
65
65
|
}
|
|
@@ -5,6 +5,8 @@ const maxScore = 10
|
|
|
5
5
|
|
|
6
6
|
export const scoreIndividualAttributes = (info: NftCollectionAttributeMetrics): Score => {
|
|
7
7
|
const { attributes } = info.metrics.metadata
|
|
8
|
+
const entries = Object.entries(attributes)
|
|
9
|
+
if (entries.length === 0) return [0, maxScore]
|
|
8
10
|
const scores = Object.entries(attributes)
|
|
9
11
|
.map(([_trait, { values }]) => {
|
|
10
12
|
return Object.entries(values).map<Score>(([_traitValue, metrics]) => {
|
|
@@ -3,12 +3,63 @@ import { normalize, Score } from '@xyo-network/crypto-nft-score-model'
|
|
|
3
3
|
|
|
4
4
|
const maxScore = 10
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Mean: What value is the distribution centered around
|
|
8
|
+
*/
|
|
9
|
+
const defaultMu = 0.15
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Standard Deviation: How spread out is the distribution
|
|
13
|
+
*/
|
|
14
|
+
const defaultSigma = 0.1
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Calculates the Gaussian probability density
|
|
18
|
+
* @param x
|
|
19
|
+
* @param mu Mean
|
|
20
|
+
* @param sigma Standard Deviation
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
const gaussianProbabilityDensity = (x: number, mu: number = defaultMu, sigma: number = defaultSigma): number => {
|
|
24
|
+
const sqrtTwoPi = Math.sqrt(2 * Math.PI)
|
|
25
|
+
const denominator = sigma * sqrtTwoPi
|
|
26
|
+
const power = -0.5 * Math.pow((x - mu) / sigma, 2)
|
|
27
|
+
return (1 / denominator) * Math.exp(power)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* For a Gaussian distribution, the peak of the distribution is the mean
|
|
32
|
+
*/
|
|
33
|
+
const maxProbabilityDensity = gaussianProbabilityDensity(defaultMu)
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* We're working on some assumptions here:
|
|
37
|
+
*
|
|
38
|
+
* - If you have a 100% chance of getting a trait, everyone get's a trophy
|
|
39
|
+
* - If you have a 50% chance of getting a trait, it's not rare
|
|
40
|
+
* - If you have a 0% chance of getting a trait, it's not fun
|
|
41
|
+
*
|
|
42
|
+
* So we're looking for something Pareto-ish (somewhere between
|
|
43
|
+
* 80/20 or 90/10) as that's a good & sustainable model for the
|
|
44
|
+
* distribution of many traits in real life.
|
|
45
|
+
* However, we also don't want to maximally reward collections
|
|
46
|
+
* that have a lot of single attributes distributed uniformly
|
|
47
|
+
* (basically a 0% trait probably) as that's perfectly entropic
|
|
48
|
+
* but not very interesting (some overlap is desirable).
|
|
49
|
+
* So we're using a Gaussian distribution to model the
|
|
50
|
+
* probability density of the joint probability of all traits
|
|
51
|
+
* centered around 15%.
|
|
52
|
+
* @param info
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
6
55
|
export const scoreTotalAttributes = (info: NftCollectionAttributeMetrics): Score => {
|
|
7
56
|
const { attributes } = info.metrics.metadata
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
57
|
+
// This has somewhat of a filtering function by causing anything with 100% probability to
|
|
58
|
+
// add no value to the end score
|
|
59
|
+
const jointProbability = Object.entries(attributes).reduce((acc, [_trait, { metrics }]) => {
|
|
60
|
+
return acc * metrics.binomial.p
|
|
61
|
+
}, 1)
|
|
62
|
+
const probabilityDensity = gaussianProbabilityDensity(jointProbability)
|
|
63
|
+
const score: Score = [probabilityDensity, maxProbabilityDensity]
|
|
64
|
+
return normalize(score, maxScore)
|
|
14
65
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { NftCollectionCount } from '@xyo-network/crypto-nft-collection-payload-plugin'
|
|
2
2
|
import { normalize, Score } from '@xyo-network/crypto-nft-score-model'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* This "magic" value was obtained using Solver in Excel
|
|
6
|
+
* to find the median, with mu/sigma fixed, which maximizes
|
|
7
|
+
* the distribution (the mode for lognormal) at 10,000
|
|
8
|
+
*/
|
|
9
|
+
const median = 81030839.8217352
|
|
5
10
|
const defaultMu = Math.log(median)
|
|
6
|
-
const defaultSigma =
|
|
7
|
-
// const mean = Math.exp(defaultMu + Math.pow(defaultSigma, 2) / 2)
|
|
11
|
+
const defaultSigma = 3
|
|
8
12
|
const mode = Math.exp(defaultMu - Math.pow(defaultSigma, 2))
|
|
9
|
-
// console.log(`mean: ${mean} median: ${median} mode: ${mode}`)
|
|
10
|
-
|
|
11
13
|
/**
|
|
12
14
|
* Calculates the log-normal probability density
|
|
13
15
|
* @param x the value at which you want to calculate the probability density
|
|
@@ -25,10 +27,21 @@ const logNormalProbabilityDensity = (x: number, mu: number = defaultMu, sigma: n
|
|
|
25
27
|
* For a lognormal distribution, the peak of the distribution is the mode
|
|
26
28
|
*/
|
|
27
29
|
const maxProbabilityDensity = logNormalProbabilityDensity(mode)
|
|
28
|
-
// console.log(`mode: ${mode} maxDensity: ${maxProbabilityDensity}`)
|
|
29
30
|
|
|
30
31
|
const maxScore = 10
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* We're working on some assumptions here:
|
|
35
|
+
* - If there's < 1000 NFTs in your collection it starts becoming too niche
|
|
36
|
+
* - If there's > 20,000 NFTs in your collection it starts becoming too broad
|
|
37
|
+
* So there's a sweet spot somewhere between 2000 and 10,000
|
|
38
|
+
* where a collection has enough NFTs to be interesting, but
|
|
39
|
+
* not so many that it's teetering on a diluted money grab.
|
|
40
|
+
* To model that we're using a log-normal distribution optimized
|
|
41
|
+
* to maximally reward collections in the aforementioned range
|
|
42
|
+
* @param nft
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
32
45
|
export const scoreTotal = (nft: NftCollectionCount): Score => {
|
|
33
46
|
const density = logNormalProbabilityDensity(nft.total)
|
|
34
47
|
const score: Score = [density, maxProbabilityDensity]
|