trust algo v4

This commit is contained in:
keyan 2023-07-05 20:30:50 -05:00
parent 56dc0568e0
commit 8350b1df3b
3 changed files with 300 additions and 214 deletions

167
package-lock.json generated
View File

@ -35,6 +35,7 @@
"jquery": "^3.6.1", "jquery": "^3.6.1",
"lexical": "^0.7.5", "lexical": "^0.7.5",
"ln-service": "^54.2.6", "ln-service": "^54.2.6",
"mathjs": "^11.8.2",
"mdast-util-find-and-replace": "^1.1.1", "mdast-util-find-and-replace": "^1.1.1",
"mdast-util-from-markdown": "^1.2.0", "mdast-util-from-markdown": "^1.2.0",
"mdast-util-to-string": "^3.1.0", "mdast-util-to-string": "^3.1.0",
@ -5625,6 +5626,18 @@
"resolved": "https://registry.npmjs.org/compact-encoding-struct/-/compact-encoding-struct-1.3.0.tgz", "resolved": "https://registry.npmjs.org/compact-encoding-struct/-/compact-encoding-struct-1.3.0.tgz",
"integrity": "sha512-8wgarWCGjtTQlpLu7ebVeeW0hEterei/D8MoIASBiZIUKV2RtzEaViAK+EMemOOOaHQFbp6yRH/k4Q2I94Qpxg==" "integrity": "sha512-8wgarWCGjtTQlpLu7ebVeeW0hEterei/D8MoIASBiZIUKV2RtzEaViAK+EMemOOOaHQFbp6yRH/k4Q2I94Qpxg=="
}, },
"node_modules/complex.js": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz",
"integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==",
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
"url": "https://www.patreon.com/infusion"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -6055,6 +6068,11 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/decimal.js": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
},
"node_modules/decimal.js-light": { "node_modules/decimal.js-light": {
"version": "2.5.1", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
@ -6573,6 +6591,11 @@
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
}, },
"node_modules/escape-latex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
},
"node_modules/escape-string-regexp": { "node_modules/escape-string-regexp": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -7887,6 +7910,18 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
"url": "https://www.patreon.com/infusion"
}
},
"node_modules/fresh": { "node_modules/fresh": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@ -9466,6 +9501,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/javascript-natural-sort": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
},
"node_modules/jmespath": { "node_modules/jmespath": {
"version": "0.16.0", "version": "0.16.0",
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
@ -10122,6 +10162,44 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/mathjs": {
"version": "11.8.2",
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.8.2.tgz",
"integrity": "sha512-ZePu0oDbM0vuFExikIMY/9syjo/jbgNbX6ti+iMdaALDuxciMCsXIslGDBEn7QCpCWYBiVCYmc0lsmk5bwHBdQ==",
"dependencies": {
"@babel/runtime": "^7.22.5",
"complex.js": "^2.1.1",
"decimal.js": "^10.4.3",
"escape-latex": "^1.2.0",
"fraction.js": "^4.2.0",
"javascript-natural-sort": "^0.7.1",
"seedrandom": "^3.0.5",
"tiny-emitter": "^2.1.0",
"typed-function": "^4.1.0"
},
"bin": {
"mathjs": "bin/cli.js"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/mathjs/node_modules/@babel/runtime": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/mathjs/node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"node_modules/md5.js": { "node_modules/md5.js": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@ -14319,6 +14397,11 @@
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.5.0.tgz", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.5.0.tgz",
"integrity": "sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w==" "integrity": "sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w=="
}, },
"node_modules/seedrandom": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
},
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@ -15684,6 +15767,11 @@
"resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-2.0.1.tgz", "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-2.0.1.tgz",
"integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw==" "integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw=="
}, },
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"node_modules/tiny-secp256k1": { "node_modules/tiny-secp256k1": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz",
@ -15929,6 +16017,14 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/typed-function": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.0.tgz",
"integrity": "sha512-DGwUl6cioBW5gw2L+6SMupGwH/kZOqivy17E4nsh1JI9fKF87orMmlQx3KISQPmg3sfnOUGlwVkroosvgddrlg==",
"engines": {
"node": ">= 14"
}
},
"node_modules/typeforce": { "node_modules/typeforce": {
"version": "1.18.0", "version": "1.18.0",
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",
@ -21735,6 +21831,11 @@
"resolved": "https://registry.npmjs.org/compact-encoding-struct/-/compact-encoding-struct-1.3.0.tgz", "resolved": "https://registry.npmjs.org/compact-encoding-struct/-/compact-encoding-struct-1.3.0.tgz",
"integrity": "sha512-8wgarWCGjtTQlpLu7ebVeeW0hEterei/D8MoIASBiZIUKV2RtzEaViAK+EMemOOOaHQFbp6yRH/k4Q2I94Qpxg==" "integrity": "sha512-8wgarWCGjtTQlpLu7ebVeeW0hEterei/D8MoIASBiZIUKV2RtzEaViAK+EMemOOOaHQFbp6yRH/k4Q2I94Qpxg=="
}, },
"complex.js": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz",
"integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg=="
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -22076,6 +22177,11 @@
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
}, },
"decimal.js": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
},
"decimal.js-light": { "decimal.js-light": {
"version": "2.5.1", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
@ -22475,6 +22581,11 @@
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
}, },
"escape-latex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
},
"escape-string-regexp": { "escape-string-regexp": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -23432,6 +23543,11 @@
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
}, },
"fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA=="
},
"fresh": { "fresh": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@ -24583,6 +24699,11 @@
} }
} }
}, },
"javascript-natural-sort": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
},
"jmespath": { "jmespath": {
"version": "0.16.0", "version": "0.16.0",
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
@ -25116,6 +25237,37 @@
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz",
"integrity": "sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA==" "integrity": "sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA=="
}, },
"mathjs": {
"version": "11.8.2",
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.8.2.tgz",
"integrity": "sha512-ZePu0oDbM0vuFExikIMY/9syjo/jbgNbX6ti+iMdaALDuxciMCsXIslGDBEn7QCpCWYBiVCYmc0lsmk5bwHBdQ==",
"requires": {
"@babel/runtime": "^7.22.5",
"complex.js": "^2.1.1",
"decimal.js": "^10.4.3",
"escape-latex": "^1.2.0",
"fraction.js": "^4.2.0",
"javascript-natural-sort": "^0.7.1",
"seedrandom": "^3.0.5",
"tiny-emitter": "^2.1.0",
"typed-function": "^4.1.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"requires": {
"regenerator-runtime": "^0.13.11"
}
},
"regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
}
}
},
"md5.js": { "md5.js": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@ -28138,6 +28290,11 @@
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.5.0.tgz", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.5.0.tgz",
"integrity": "sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w==" "integrity": "sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w=="
}, },
"seedrandom": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
},
"semver": { "semver": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@ -29186,6 +29343,11 @@
"resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-2.0.1.tgz", "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-2.0.1.tgz",
"integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw==" "integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw=="
}, },
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"tiny-secp256k1": { "tiny-secp256k1": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz",
@ -29378,6 +29540,11 @@
"mime-types": "~2.1.24" "mime-types": "~2.1.24"
} }
}, },
"typed-function": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.0.tgz",
"integrity": "sha512-DGwUl6cioBW5gw2L+6SMupGwH/kZOqivy17E4nsh1JI9fKF87orMmlQx3KISQPmg3sfnOUGlwVkroosvgddrlg=="
},
"typeforce": { "typeforce": {
"version": "1.18.0", "version": "1.18.0",
"resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz",

View File

@ -36,6 +36,7 @@
"jquery": "^3.6.1", "jquery": "^3.6.1",
"lexical": "^0.7.5", "lexical": "^0.7.5",
"ln-service": "^54.2.6", "ln-service": "^54.2.6",
"mathjs": "^11.8.2",
"mdast-util-find-and-replace": "^1.1.1", "mdast-util-find-and-replace": "^1.1.1",
"mdast-util-from-markdown": "^1.2.0", "mdast-util-from-markdown": "^1.2.0",
"mdast-util-to-string": "^3.1.0", "mdast-util-to-string": "^3.1.0",

View File

@ -1,239 +1,157 @@
const math = require('mathjs')
function trust ({ boss, models }) { function trust ({ boss, models }) {
return async function () { return async function () {
console.log('doing trust') try {
console.time('trust')
console.timeLog('trust', 'getting graph')
const graph = await getGraph(models) const graph = await getGraph(models)
const user = await models.user.findUnique({ where: { name: process.env.WOT_SOURCE || 'k00b' } }) console.timeLog('trust', 'computing trust')
const trust = await trustGivenGraph(graph, user.id) const trust = await trustGivenGraph(graph)
console.timeLog('trust', 'storing trust')
await storeTrust(models, trust) await storeTrust(models, trust)
console.log('done doing trust') console.timeEnd('trust')
} catch (e) {
console.error(e)
throw e
}
} }
} }
// only explore a path up to this depth from start const MAX_DEPTH = 10
const MAX_DEPTH = 6 const MAX_TRUST = 1
const MAX_TRUST = 0.9 const MIN_SUCCESS = 1
const MIN_SUCCESS = 5 // increasing disgree_mult increases distrust when there's disagreement
// increasing disgree_mult increases distrust when there's disagreement, at 1x we double count disagreement, // ... this cancels DISAGREE_MULT number of "successes" for every disagreement
// at 2x we triple count, etc ... this count is reflected/added in the number of total "trials" between users const DISAGREE_MULT = 10
const DISAGREE_MULT = 1
// https://en.wikipedia.org/wiki/Normal_distribution#Quantile_function // https://en.wikipedia.org/wiki/Normal_distribution#Quantile_function
const Z_CONFIDENCE = 2.326347874041 // 98% confidence const Z_CONFIDENCE = 6.109410204869 // 99.9999999% confidence
const SEEDS = [616, 6030, 946, 4502]
function pathsOverlap (arr1 = [], arr2 = []) { const SEED_WEIGHT = 0.25
const dp = new Array(arr1.length + 1).fill(0).map(() => new Array(arr2.length + 1).fill(0)) const AGAINST_MSAT_MIN = 1000
for (let i = arr1.length - 1; i >= 0; i--) { const MSAT_MIN = 1000
for (let j = arr2.length - 1; j >= 0; j--) {
if (arr1[i] === arr2[j]) {
dp[i][j] = dp[i + 1][j + 1] + 1
if (dp[i][j] > 1) {
return true
}
} else {
dp[i][j] = 0
}
}
}
return false
}
/*
This approximates an upper bound of trust given a list of indepent trust
values ... we basically are compressing a trust vector into a single value
without having to compute the trust using the inclusion-exclusion principle
*/
function boundedTrust (probs) {
const max = Math.max(...probs)
const sum = probs.reduce((a, c) => a + c)
const trust = sum - max * (sum - max)
return Math.min(trust, MAX_TRUST)
}
/*
Given the paths to each node and the accumulated trust along that path
this function returns an object where the keys are the node ids and
their value is the trust of that node
*/
function trustGivenPaths (paths) {
const trust = {}
for (const [node, npaths] of Object.entries(paths)) {
trust[node] = boundedTrust(Object.values(npaths))
}
return trust
}
/* /*
Given a graph and start this function returns an object where Given a graph and start this function returns an object where
the keys are the node id and their value is the trust of that node the keys are the node id and their value is the trust of that node
*/ */
function trustGivenGraph (graph, start) { function trustGivenGraph (graph) {
const queue = [] // queue of to be visited nodes // empty matrix of proper size nstackers x nstackers
queue.push(start) // visit start first const mat = math.zeros(graph.length, graph.length, 'sparse')
const depth = {} // store the node depth ... XXX space inefficient // create a map of user id to position in matrix
depth[start] = 0 // start node is depth 0 const posByUserId = {}
for (const [idx, val] of graph.entries()) {
const paths = {} // { node : { path to node as stringified json array : trust } } posByUserId[val.id] = idx
paths[start] = { '[]': 1 } // the paths to start is an empty path with trust of 1
// while we have nodes to visit
while (queue.length > 0) {
const node = queue.shift()
if (depth[node] === MAX_DEPTH) break
if (!graph[node]) {
// node doesn't have outbound edges
continue
} }
// for all of this nodes outbound edges // iterate over graph, inserting edges into matrix
for (let i = 0; i < graph[node].length; i++) { for (const [idx, val] of graph.entries()) {
const { node: sibling, trust } = graph[node][i] for (const { node, trust } of val.hops) {
let explore = false try {
mat.set([idx, posByUserId[node]], Number(trust))
// for all existing paths to this node } catch (e) {
for (const [key, value] of Object.entries(paths[node])) { console.log('error:', idx, node, posByUserId[node], trust)
const parentPath = JSON.parse(key) throw e
if (parentPath.includes(sibling)) {
// sibling already exists on a path to us, ie this would be a cycle
continue
}
// add this path to sibling
const path = JSON.stringify([...parentPath, node])
paths[sibling] = paths[sibling] || {}
// if this sibling has not been visited along this path
if (!paths[sibling][path]) {
// here we exclude paths that aren't disjoint - they mininally contribute
// to trust so we just exclude them, yielding a very small underestimation
// of trust while reducing the number of paths we have to explore
let disjoint = true
// for all the paths to sibling
for (const [key2] of Object.entries(paths[sibling])) {
// if this existing path to sibling contains overlap with the
// path we're exploring, ignore it
const otherPath = JSON.parse(key2)
const parsedPath = JSON.parse(path)
if (pathsOverlap(otherPath, parsedPath)) {
disjoint = false
break
}
}
// if this path is disjoint with all existing paths to sibling
if (disjoint) {
// accumulate the trust along the path and store it
paths[sibling][path] = value * trust
explore = true
} }
} }
} }
// if we shouldn't explore this sibling, don't queue it // perform random walk over trust matrix
if (!explore) continue // the resulting matrix columns represent the trust a user (col) has for each other user (rows)
depth[sibling] = depth[node] + 1 // XXX this scales N^3 and mathjs is slow
queue.push(sibling) let matT = math.transpose(mat)
} const original = matT.clone()
for (let i = 0; i < MAX_DEPTH; i++) {
console.timeLog('trust', `matrix multiply ${i}`)
matT = math.multiply(original, matT)
matT = math.add(math.multiply(1 - SEED_WEIGHT, matT), math.multiply(SEED_WEIGHT, original))
} }
return trustGivenPaths(paths) console.timeLog('trust', 'normalizing result')
// we normalize the result taking the z-score, then min-max to [0,1]
// we remove seeds and 0 trust people from the result because they are known outliers
// but we need to keep them in the result to keep positions correct
function resultForId (id) {
let result = math.squeeze(math.subset(math.transpose(matT), math.index(posByUserId[id], math.range(0, graph.length))))
const outliers = SEEDS.concat([id])
outliers.forEach(id => result.set([posByUserId[id]], 0))
const withoutZero = math.filter(result, val => val > 0)
// NOTE: this might be improved by using median and mad (modified z score)
// given the distribution is skewed
const mean = math.mean(withoutZero)
const std = math.std(withoutZero)
result = result.map(val => val >= 0 ? (val - mean) / std : 0)
const min = math.min(result)
const max = math.max(result)
result = math.map(result, val => (val - min) / (max - min))
outliers.forEach(id => result.set([posByUserId[id]], MAX_TRUST))
return result
}
// turn the result vector into an object
const result = {}
resultForId(616).forEach((val, idx) => {
result[graph[idx].id] = val
})
return result
} }
/* /*
OLD TRUST GRAPH graph is returned as json in adjacency list where edges are the trust value 0-1
graph is returned as json in adjacency list where edges are the trust value 0-.9 graph = [
graph = { { id: node1, hops: [{node : node2, trust: trust12}, {node: node3, trust: trust13}] },
node1 : [{node : node2, trust: trust12}, {node: node3, trust: trust13}], ...
node2 : [{node : node1, trust: trust21}], ]
node3 : [{node : node2, trust: trust32}],
}
*/ */
// async function getGraph (models) {
// const [{ graph }] = await models.$queryRaw`
// select json_object_agg(id, hops) as graph
// from (
// select id, json_agg(json_build_object('node', oid, 'trust', trust)) as hops
// from (
// select "ItemAct"."userId" as id, "Item"."userId" as oid, least(${MAX_TRUST},
// sum(POWER(.99, EXTRACT(DAY FROM (NOW_UTC() - "ItemAct".created_at))))/21.0) as trust
// from "ItemAct"
// join "Item" on "itemId" = "Item".id and "ItemAct"."userId" <> "Item"."userId"
// where "ItemAct".act = 'VOTE' group by "ItemAct"."userId", "Item"."userId"
// ) a
// group by id
// ) b`
// return graph
// }
// old upvote confidence graph
// async function getGraph (models) {
// const [{ graph }] = await models.$queryRaw`
// select json_object_agg(id, hops) as graph
// from (
// select id, json_agg(json_build_object('node', oid, 'trust', trust)) as hops
// from (
// select s.id, s.oid, confidence(s.shared, count(*), ${Z_CONFIDENCE}) as trust
// from (
// select a."userId" as id, b."userId" as oid, count(*) as shared
// from "ItemAct" b
// join users bu on bu.id = b."userId"
// join "ItemAct" a on b."itemId" = a."itemId"
// join users au on au.id = a."userId"
// join "Item" on "Item".id = b."itemId"
// where b.act = 'VOTE'
// and a.act = 'VOTE'
// and "Item"."parentId" is null
// and "Item"."userId" <> b."userId"
// and "Item"."userId" <> a."userId"
// and b."userId" <> a."userId"
// and "Item".created_at >= au.created_at and "Item".created_at >= bu.created_at
// group by b."userId", a."userId") s
// join users u on s.id = u.id
// join users ou on s.oid = ou.id
// join "ItemAct" on "ItemAct"."userId" = s.oid
// join "Item" on "Item".id = "ItemAct"."itemId"
// where "ItemAct".act = 'VOTE' and "Item"."parentId" is null
// and "Item"."userId" <> s.oid and "Item"."userId" <> s.id
// and "Item".created_at >= u.created_at and "Item".created_at >= ou.created_at
// group by s.id, s.oid, s.shared
// ) a
// group by id
// ) b`
// return graph
// }
async function getGraph (models) { async function getGraph (models) {
const [{ graph }] = await models.$queryRaw` return await models.$queryRaw`
SELECT json_object_agg(id, hops) AS graph SELECT id, array_agg(json_build_object(
FROM ( 'node', oid,
SELECT id, json_agg(json_build_object('node', oid, 'trust', trust)) AS hops 'trust', CASE WHEN total_trust > 0 THEN trust / total_trust::float ELSE 0 END)) AS hops
FROM ( FROM (
WITH user_votes AS ( WITH user_votes AS (
SELECT "ItemAct"."userId" AS user_id, users.name AS name, "ItemAct"."itemId" AS item_id, min("ItemAct".created_at) AS act_at, SELECT "ItemAct"."userId" AS user_id, users.name AS name, "ItemAct"."itemId" AS item_id, min("ItemAct".created_at) AS act_at,
users.created_at AS user_at, "ItemAct".act = 'DONT_LIKE_THIS' AS against, count(*) OVER (partition by "ItemAct"."userId") AS user_vote_count users.created_at AS user_at, "ItemAct".act = 'DONT_LIKE_THIS' AS against,
count(*) OVER (partition by "ItemAct"."userId") AS user_vote_count
FROM "ItemAct" FROM "ItemAct"
JOIN "Item" ON "Item".id = "ItemAct"."itemId" AND "ItemAct".act IN ('FEE', 'TIP', 'DONT_LIKE_THIS') AND "Item"."parentId" IS NULL JOIN "Item" ON "Item".id = "ItemAct"."itemId" AND "ItemAct".act IN ('FEE', 'TIP', 'DONT_LIKE_THIS')
AND "Item"."parentId" IS NULL AND NOT "Item".bio AND "Item"."userId" <> "ItemAct"."userId"
JOIN users ON "ItemAct"."userId" = users.id JOIN users ON "ItemAct"."userId" = users.id
GROUP BY user_id, name, item_id, user_at, against GROUP BY user_id, name, item_id, user_at, against
HAVING CASE WHEN
"ItemAct".act = 'DONT_LIKE_THIS' THEN sum("ItemAct".msats) > ${AGAINST_MSAT_MIN}
ELSE sum("ItemAct".msats) > ${MSAT_MIN} END
), ),
user_pair AS ( user_pair AS (
SELECT a.user_id AS a_id, a.name AS a_name, b.user_id AS b_id, b.name AS b_name, SELECT a.user_id AS a_id, b.user_id AS b_id,
count(*) FILTER(WHERE a.act_at > b.act_at AND a.against = b.against) AS before, count(*) FILTER(WHERE a.act_at > b.act_at AND a.against = b.against) AS before,
count(*) FILTER(WHERE b.act_at > a.act_at AND a.against = b.against) AS after, count(*) FILTER(WHERE b.act_at > a.act_at AND a.against = b.against) AS after,
count(*) FILTER(WHERE a.against <> b.against) * ${DISAGREE_MULT} AS disagree, count(*) FILTER(WHERE a.against <> b.against) * ${DISAGREE_MULT} AS disagree,
CASE WHEN b.user_at > a.user_at THEN b.user_vote_count ELSE a.user_vote_count END AS total b.user_vote_count AS b_total, a.user_vote_count AS a_total
FROM user_votes a FROM user_votes a
JOIN user_votes b ON a.item_id = b.item_id JOIN user_votes b ON a.item_id = b.item_id
GROUP BY a.user_id, a.name, a.user_at, a.user_vote_count, b.user_id, b.name, b.user_at, b.user_vote_count WHERE a.user_id <> b.user_id
) GROUP BY a.user_id, a.user_vote_count, b.user_id, b.user_vote_count
SELECT a_id AS id, a_name, b_id AS oid, b_name, confidence(before, total + disagree - after, ${Z_CONFIDENCE}) AS trust, before, after, disagree, total ),
trust_pairs AS (
SELECT a_id AS id, b_id AS oid,
CASE WHEN before - disagree >= ${MIN_SUCCESS} AND b_total - after > 0 THEN
confidence(before - disagree, b_total - after, ${Z_CONFIDENCE})
ELSE 0 END AS trust
FROM user_pair FROM user_pair
WHERE before >= ${MIN_SUCCESS} WHERE b_id <> ANY (${SEEDS})
UNION ALL
SELECT a_id AS id, seed_id AS oid, ${MAX_TRUST}::float/ARRAY_LENGTH(${SEEDS}::int[], 1) as trust
FROM user_pair, unnest(${SEEDS}::int[]) seed_id
GROUP BY a_id, a_total, seed_id
)
SELECT id, oid, trust, sum(trust) OVER (PARTITION BY id) AS total_trust
FROM trust_pairs
) a ) a
GROUP BY a.id GROUP BY a.id
) b` ORDER BY id ASC`
return graph
} }
async function storeTrust (models, nodeTrust) { async function storeTrust (models, nodeTrust) {