From 3373dac0408ba21471c03d604512dbe4cb5c3738 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 18 Jan 2024 13:15:22 +0200 Subject: [PATCH 01/63] Add base docs, improve generate.sh, generate models --- docs/package-lock.json | 7006 ++++++++++++++++- .../components/responses/internalError.yaml | 5 + .../components/responses/invalidAuth.yaml | 5 + .../responses/invalidParameter.yaml | 5 + docs/spec/components/responses/notFound.yaml | 5 + docs/spec/components/schemas/Balance.yaml | 25 + docs/spec/components/schemas/BalanceKey.yaml | 12 + docs/spec/components/schemas/Errors.yaml | 35 + docs/spec/components/schemas/Event.yaml | 34 + docs/spec/components/schemas/EventKey.yaml | 12 + .../integrations@points-svc@balance.yaml | 24 + .../paths/integrations@points-svc@events.yaml | 38 + .../integrations@points-svc@events@{id}.yaml | 31 + .../integrations@points-svc@leaderboard.yaml | 44 + generate.sh | 10 +- resources/db.go | 52 + resources/flag.go | 37 + resources/included.go | 105 + resources/links.go | 13 + resources/model_balance.go | 43 + resources/model_balance_attributes.go | 14 + resources/model_details.go | 65 + resources/model_event.go | 43 + resources/model_event_attributes.go | 20 + resources/model_key.go | 33 + resources/model_relation.go | 10 + resources/model_relation_collection.go | 21 + resources/model_resource_type.go | 13 + 28 files changed, 7731 insertions(+), 29 deletions(-) create mode 100644 docs/spec/components/responses/internalError.yaml create mode 100644 docs/spec/components/responses/invalidAuth.yaml create mode 100644 docs/spec/components/responses/invalidParameter.yaml create mode 100644 docs/spec/components/responses/notFound.yaml create mode 100644 docs/spec/components/schemas/Balance.yaml create mode 100644 docs/spec/components/schemas/BalanceKey.yaml create mode 100644 docs/spec/components/schemas/Errors.yaml create mode 100644 docs/spec/components/schemas/Event.yaml create mode 100644 docs/spec/components/schemas/EventKey.yaml create mode 100644 docs/spec/paths/integrations@points-svc@balance.yaml create mode 100644 docs/spec/paths/integrations@points-svc@events.yaml create mode 100644 docs/spec/paths/integrations@points-svc@events@{id}.yaml create mode 100644 docs/spec/paths/integrations@points-svc@leaderboard.yaml create mode 100644 resources/db.go create mode 100644 resources/flag.go create mode 100644 resources/included.go create mode 100644 resources/links.go create mode 100644 resources/model_balance.go create mode 100644 resources/model_balance_attributes.go create mode 100644 resources/model_details.go create mode 100644 resources/model_event.go create mode 100644 resources/model_event_attributes.go create mode 100644 resources/model_key.go create mode 100644 resources/model_relation.go create mode 100644 resources/model_relation_collection.go create mode 100644 resources/model_resource_type.go diff --git a/docs/package-lock.json b/docs/package-lock.json index 93feaaa..a719d07 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -1,8 +1,6962 @@ { "name": "rarime-points-svc", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "points-svc", + "version": "1.0.0", + "dependencies": { + "@tokend/redoc-cli": "^0.9.9", + "swagger-repo": "^2.0.0-rc.11" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dependencies": { + "@babel/highlight": "^7.0.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.0.tgz", + "integrity": "sha512-zBZfgvBB/ywjx0Rgc2+BwoH/3H+lDtlgD4hBOpEv5LxRnYsm/753iRuLepqnYlynpjC3AdQxtxsoeHJoEEwOAw==", + "dependencies": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", + "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "dependencies": { + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz", + "integrity": "sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==", + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + }, + "node_modules/@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dependencies": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.13.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.4.tgz", + "integrity": "sha512-uvoOulWHhI+0+1f9L4BoozY7U5cIkZ9PgJqvb041d6vypgUmtVPG4vmGm4pSggjl8BELzvHyUeJSUyEMY6b+qA==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.2.tgz", + "integrity": "sha512-7Bl2rALb7HpvXFL7TETNzKSAeBVCPHELzc0C//9FCxN8nsiueWSJBqaF+2oIJScyILStASR/Cx5WMkXGYTiJFA==", + "dependencies": { + "regenerator-runtime": "^0.13.2" + } + }, + "node_modules/@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/template/node_modules/@babel/highlight": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", + "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz", + "integrity": "sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.0", + "@babel/types": "^7.13.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/highlight": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", + "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.0.tgz", + "integrity": "sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/types/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "node_modules/@exodus/schemasafe": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-rc.3.tgz", + "integrity": "sha512-GoXw0U2Qaa33m3eUcxuHnHpNvHjNlLo0gtV091XBpaRINaB4X6FGCG5XKxSFNFiPpugUDqNruHzaqpTdDm4AOg==" + }, + "node_modules/@tokend/redoc": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@tokend/redoc/-/redoc-2.3.3.tgz", + "integrity": "sha512-wL2bVXkzoC3jkBTQ9lBBq/MZhoVxLgsgTVdEPSR56U63gP+gdPKPXe91bDfl5hFB73++bvPrFyr7BgpIqpx+oQ==", + "dependencies": { + "classnames": "^2.2.6", + "decko": "^1.2.0", + "dompurify": "^2.0.8", + "eventemitter3": "^4.0.0", + "json-pointer": "^0.6.0", + "json-schema-ref-parser": "^6.1.0", + "lunr": "2.3.8", + "mark.js": "^8.11.1", + "marked": "^0.7.0", + "memoize-one": "~5.1.1", + "mobx-react": "6.1.5", + "openapi-sampler": "1.0.0-beta.15", + "perfect-scrollbar": "^1.4.0", + "polished": "^3.4.4", + "prismjs": "^1.19.0", + "prop-types": "^15.7.2", + "react-dropdown": "^1.7.0", + "react-tabs": "^3.1.0", + "slugify": "^1.4.0", + "stickyfill": "^1.1.1", + "swagger2openapi": "^5.3.4", + "tslib": "^1.11.1", + "url-template": "^2.0.8" + }, + "engines": { + "node": ">=6.9", + "npm": ">=3.0.0" + }, + "peerDependencies": { + "core-js": "^3.1.4", + "mobx": "^4.2.0 || ^5.0.0", + "react": "^16.8.4", + "react-dom": "^16.8.4", + "styled-components": "^4.1.1" + } + }, + "node_modules/@tokend/redoc-cli": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/@tokend/redoc-cli/-/redoc-cli-0.9.9.tgz", + "integrity": "sha512-Qgo8oz1zSbrz+LG8QAouPcs4z526375YRvmQCwEMjYKxYQVOpLwmXlyDQRBCymStwLGh85ABjz+fTObqsypjfQ==", + "dependencies": { + "@tokend/redoc": "2.3.3", + "chokidar": "^3.0.2", + "handlebars": "^4.1.2", + "isarray": "^2.0.5", + "mkdirp": "^0.5.1", + "mobx": "^4.2.0", + "node-libs-browser": "^2.2.1", + "react": "^16.8.6", + "react-dom": "^16.8.6", + "redoc": "2.0.0-rc.24", + "styled-components": "^4.3.2", + "tslib": "^1.10.0", + "yargs": "^13.3.0" + }, + "bin": { + "redoc-cli": "index.js" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/@tokend/redoc-cli/node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/@tokend/redoc-cli/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@tokend/redoc-cli/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/@tokend/redoc-cli/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/@tokend/redoc/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dependencies": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dependencies": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dependencies": { + "lodash": "^4.17.11" + } + }, + "node_modules/async-each": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", + "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/babel-plugin-styled-components": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz", + "integrity": "sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-module-imports": "^7.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/better-ajv-errors": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/better-ajv-errors/-/better-ajv-errors-0.5.7.tgz", + "integrity": "sha512-O7tpXektKWVwYCH5g6Vs3lKD+sJs7JHh5guapmGJd+RTwxhFZEf4FwvbHBURUnoXsTeFaMvGuhTTmEGiHpNi6w==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/runtime": "^7.0.0", + "chalk": "^2.4.1", + "core-js": "^2.5.7", + "json-to-ast": "^2.0.3", + "jsonpointer": "^4.0.1", + "leven": "^2.1.0" + }, + "peerDependencies": { + "ajv": "4.11.8 - 6" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", + "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dependencies": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "node_modules/buffer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, + "node_modules/camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/chokidar/node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/chokidar/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/chokidar/node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/chokidar/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/cjson": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.2.1.tgz", + "integrity": "sha1-c82KrWXZ4VBfmvF0TTt5wVJ2gqU=", + "engines": { + "node": ">= 0.3.0" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, + "node_modules/clipboard": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", + "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", + "optional": true, + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dependencies": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-error-fragment": { + "version": "0.0.230", + "resolved": "https://registry.npmjs.org/code-error-fragment/-/code-error-fragment-0.0.230.tgz", + "integrity": "sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/colors": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "node_modules/component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js." + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz", + "integrity": "sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^3.3.0" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decko": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decko/-/decko-1.2.0.tgz", + "integrity": "sha1-/UPHNelnuAEzBohKVvvmZZlraBc=" + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/deref": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/deref/-/deref-0.7.6.tgz", + "integrity": "sha512-8en95BZvFIHY+G4bnW1292qFfubV7NSogpoBNJFCbbSPEvRGKkOfMRgVhl3AtXSdxpRQ6WMuZhMVIlpFVBB3AA==", + "dependencies": { + "deep-extend": "^0.6.0" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/dompurify": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.6.tgz", + "integrity": "sha512-7b7ZArhhH0SP6W2R9cqK6RjaU82FZ2UPM7RO8qN1b1wyvC/NY1FNWcX1Pu00fFOAnzEORtwXe4bPaClg6pUybQ==" + }, + "node_modules/drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ebnf-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", + "integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/elliptic/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/email-addresses": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.0.3.tgz", + "integrity": "sha512-kUlSC06PVvvjlMRpNIl3kR1NRXLEe86VQ7N0bQeaCZb2g+InShCeHQp/JvyYNTugMnRN2NvJhHlc3q12MWbbpg==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.21.tgz", + "integrity": "sha1-U9ZSz6EDA4gnlFilJmxf/HCcY8M=", + "dependencies": { + "esprima": "~1.0.2", + "estraverse": "~0.0.4" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.4.0" + }, + "optionalDependencies": { + "source-map": ">= 0.1.2" + } + }, + "node_modules/escodegen/node_modules/esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-0.0.4.tgz", + "integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dependencies": { + "fill-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dependencies": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/expand-range/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "dependencies": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/faker": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", + "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" + }, + "node_modules/fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "node_modules/fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "node_modules/filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/filename-reserved-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", + "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/filenamify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", + "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", + "dependencies": { + "filename-reserved-regex": "^1.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/filenamify-url": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz", + "integrity": "sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A=", + "dependencies": { + "filenamify": "^1.0.0", + "humanize-url": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/format-util": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.3.tgz", + "integrity": "sha1-Ay3KShFiYqEsQ/TD7IVmQWxbLZU=" + }, + "node_modules/formidable": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau" + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "bundleDependencies": [ + "node-pre-gyp" + ], + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/fsevents/node_modules/abbrev": { + "version": "1.1.1", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/ansi-regex": { + "version": "2.1.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/aproba": { + "version": "1.2.0", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/are-we-there-yet": { + "version": "1.1.5", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/fsevents/node_modules/balanced-match": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/brace-expansion": { + "version": "1.1.11", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fsevents/node_modules/chownr": { + "version": "1.1.1", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/code-point-at": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/concat-map": { + "version": "0.0.1", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/console-control-strings": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/core-util-is": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/debug": { + "version": "2.6.9", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/fsevents/node_modules/deep-extend": { + "version": "0.6.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fsevents/node_modules/delegates": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/detect-libc": { + "version": "1.0.3", + "inBundle": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/fsevents/node_modules/fs-minipass": { + "version": "1.2.5", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^2.2.1" + } + }, + "node_modules/fsevents/node_modules/fs.realpath": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/gauge": { + "version": "2.7.4", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/fsevents/node_modules/glob": { + "version": "7.1.3", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/has-unicode": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/iconv-lite": { + "version": "0.4.24", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/ignore-walk": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/fsevents/node_modules/inflight": { + "version": "1.0.6", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/fsevents/node_modules/inherits": { + "version": "2.0.3", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/ini": { + "version": "1.3.5", + "inBundle": true, + "license": "ISC", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/isarray": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/minimatch": { + "version": "3.0.4", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fsevents/node_modules/minimist": { + "version": "0.0.8", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/minipass": { + "version": "2.3.5", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/fsevents/node_modules/minizlib": { + "version": "1.2.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^2.2.1" + } + }, + "node_modules/fsevents/node_modules/mkdirp": { + "version": "0.5.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/fsevents/node_modules/ms": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/needle": { + "version": "2.2.4", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/fsevents/node_modules/node-pre-gyp": { + "version": "0.10.3", + "inBundle": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/fsevents/node_modules/nopt": { + "version": "4.0.1", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/fsevents/node_modules/npm-bundled": { + "version": "1.0.5", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/npm-packlist": { + "version": "1.2.0", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "node_modules/fsevents/node_modules/npmlog": { + "version": "4.1.2", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/fsevents/node_modules/number-is-nan": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/object-assign": { + "version": "4.1.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/once": { + "version": "1.4.0", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/fsevents/node_modules/os-homedir": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/os-tmpdir": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/osenv": { + "version": "0.1.5", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/fsevents/node_modules/path-is-absolute": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/process-nextick-args": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/rc": { + "version": "1.2.8", + "inBundle": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/fsevents/node_modules/rc/node_modules/minimist": { + "version": "1.2.0", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/readable-stream": { + "version": "2.3.6", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/fsevents/node_modules/rimraf": { + "version": "2.6.3", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/fsevents/node_modules/safe-buffer": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/safer-buffer": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/sax": { + "version": "1.2.4", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/semver": { + "version": "5.6.0", + "inBundle": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/fsevents/node_modules/set-blocking": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/signal-exit": { + "version": "3.0.2", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/string_decoder": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fsevents/node_modules/string-width": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/strip-ansi": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/strip-json-comments": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents/node_modules/tar": { + "version": "4.4.8", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/fsevents/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/fsevents/node_modules/wide-align": { + "version": "1.1.3", + "inBundle": true, + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/fsevents/node_modules/wrappy": { + "version": "1.0.2", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/fsevents/node_modules/yallist": { + "version": "3.0.3", + "inBundle": true, + "license": "ISC", + "optional": true + }, + "node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-2.0.1.tgz", + "integrity": "sha512-uFlk3bukljeiWKQ2XvPfjcSi/ou7IfoDf2p+Fj672saLAr8bnOdFVqI/JSgrSgInKpCg5BksxEwGUl++dbg8Dg==", + "dependencies": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify-url": "^1.0.0", + "fs-extra": "^7.0.0", + "globby": "^6.1.0", + "graceful-fs": "^4.1.11", + "rimraf": "^2.6.2" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dependencies": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-base/node_modules/glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dependencies": { + "is-glob": "^2.0.0" + } + }, + "node_modules/glob-base/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-base/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "optional": true, + "dependencies": { + "delegate": "^3.1.2" + } + }, + "node_modules/graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "node_modules/graphlib": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.7.tgz", + "integrity": "sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==", + "dependencies": { + "lodash": "^4.17.5" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http2-client": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.2.tgz", + "integrity": "sha512-CY9yoIetaoblM5CTrzHc7mJvH1Fo9/XmO6kxRkTCnWbSPq5brQYbtJ7hJrI5nKMYpyqPJYdPN9mkQbRBVvsoSQ==" + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "node_modules/humanize-url": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz", + "integrity": "sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8=", + "dependencies": { + "normalize-url": "^1.0.0", + "strip-url-auth": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "deprecated": "Please upgrade to v0.1.7", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "deprecated": "Please upgrade to v0.1.5", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dependencies": { + "is-primitive": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jison": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz", + "integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=", + "dependencies": { + "cjson": "~0.2.1", + "ebnf-parser": "~0.1.9", + "escodegen": "0.0.21", + "esprima": "1.0.x", + "jison-lex": "0.2.x", + "JSONSelect": "0.4.0", + "lex-parser": "~0.1.3", + "nomnom": "1.5.2" + }, + "bin": { + "jison": "lib/cli.js" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/jison-lex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.2.1.tgz", + "integrity": "sha1-rEuBXozOUTLrErXfz+jXB7iETf4=", + "dependencies": { + "lex-parser": "0.1.x", + "nomnom": "1.5.2" + }, + "bin": { + "jison-lex": "cli.js" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/jison/node_modules/esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/js-base64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", + "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-pointer": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.0.tgz", + "integrity": "sha1-jlAFUKaqxUZKRzN32leqbMIoKNc=", + "dependencies": { + "foreach": "^2.0.4" + } + }, + "node_modules/json-refs": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.12.tgz", + "integrity": "sha512-6RbO1Y3e0Hty/tEpXtQG6jUx7g1G8e39GIOuPugobPC8BX1gZ0OGZQpBn1FLWGkuWF35GRGADvhwdEIFpwIjyA==", + "dependencies": { + "commander": "~2.11.0", + "graphlib": "^2.1.1", + "js-yaml": "^3.10.0", + "lodash": "^4.17.4", + "native-promise-only": "^0.8.1", + "path-loader": "^1.0.5", + "slash": "^1.0.0", + "uri-js": "^3.0.2" + }, + "bin": { + "json-refs": "bin/json-refs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/json-refs/node_modules/commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "node_modules/json-schema-faker": { + "version": "0.5.0-rc15", + "resolved": "https://registry.npmjs.org/json-schema-faker/-/json-schema-faker-0.5.0-rc15.tgz", + "integrity": "sha512-q9my8/67q/JHTvZCuT75LQGfj8Ar4uRUK0rSvOWMu6VbYyrfR9b4GQOmgjHm8ez052+GVNfK+nSiM/WUsU/4Zw==", + "dependencies": { + "deref": "^0.7.1", + "json-schema-ref-parser": "^5.0.0", + "jsonpath": "^1.0.0", + "randexp": "^0.4.5", + "tslib": "^1.7.1" + } + }, + "node_modules/json-schema-faker/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/json-schema-faker/node_modules/json-schema-ref-parser": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-5.1.3.tgz", + "integrity": "sha512-CpDFlBwz/6la78hZxyB9FECVKGYjIIl3Ms3KLqFj99W7IIb7D00/RDgc++IGB4BBALl0QRhh5m4q5WNSopvLtQ==", + "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", + "dependencies": { + "call-me-maybe": "^1.0.1", + "debug": "^3.1.0", + "js-yaml": "^3.12.0", + "ono": "^4.0.6" + } + }, + "node_modules/json-schema-faker/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/json-schema-ref-parser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-6.1.0.tgz", + "integrity": "sha512-pXe9H1m6IgIpXmE5JSb8epilNTGsmTb2iPohAXpOdhqGFbQjNeHHsZxU+C8w6T81GZxSPFLeUoqDJmzxx5IGuw==", + "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", + "dependencies": { + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.12.1", + "ono": "^4.0.11" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "node_modules/json-to-ast": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json-to-ast/-/json-to-ast-2.1.0.tgz", + "integrity": "sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==", + "dependencies": { + "code-error-fragment": "0.0.230", + "grapheme-splitter": "^1.0.4" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.0.1.tgz", + "integrity": "sha512-HY5kSg82LHIs0r0h9gYBwpNc1w1qGY0qJ7al01W1bJltsN2lp+mjjA/a79gXWuvD6Xf8oPkD2d5uKMZQXTGzqA==", + "hasInstallScript": true, + "dependencies": { + "esprima": "1.2.2", + "jison": "0.4.13", + "static-eval": "2.0.2", + "underscore": "1.7.0" + } + }, + "node_modules/jsonpath/node_modules/esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs=", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/JSONSelect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", + "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=", + "engines": { + "node": ">=0.4.7" + } + }, + "node_modules/kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dependencies": { + "invert-kv": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lex-parser": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", + "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" + }, + "node_modules/livereload": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.7.0.tgz", + "integrity": "sha512-PHnIGczQEvmCctDvRTWylA+1wSwE0/eFm+LkNhlmlAFus/aCRlVE97UOLOf6TUGLmZyfg7z7twG37ZiOgNJAyQ==", + "dependencies": { + "chokidar": "^1.7.0", + "opts": ">= 1.2.0", + "ws": "^1.1.5" + }, + "bin": { + "livereload": "bin/livereload.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/livereload/node_modules/anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dependencies": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "node_modules/livereload/node_modules/arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dependencies": { + "arr-flatten": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dependencies": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", + "dependencies": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + }, + "optionalDependencies": { + "fsevents": "^1.0.0" + } + }, + "node_modules/livereload/node_modules/expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dependencies": { + "is-posix-bracket": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dependencies": { + "is-glob": "^2.0.0" + } + }, + "node_modules/livereload/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dependencies": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/livereload/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lunr": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", + "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==" + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha1-GA8fnr74sOY45BZq1S24eb6y/8U=" + }, + "node_modules/marked": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mem": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", + "dependencies": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/memoize-one": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz", + "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" + }, + "node_modules/merge-anything": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-2.4.4.tgz", + "integrity": "sha512-l5XlriUDJKQT12bH+rVhAHjwIuXWdAIecGwsYjv2LJo+dA1AeRTmeQS+3QBpO6lEthBMDi2IUMpLC1yyRvGlwQ==", + "dependencies": { + "is-what": "^3.3.1" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "bin": { + "mime": "cli.js" + } + }, + "node_modules/mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "dependencies": { + "mime-db": "~1.38.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "deprecated": "Critical bug fixed in v2.0.1, please upgrade to the latest version.", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "node_modules/mobx": { + "version": "4.15.7", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-4.15.7.tgz", + "integrity": "sha512-X4uQvuf2zYKHVO5kRT5Utmr+J9fDnRgxWWnSqJ4oiccPTQU38YG+/O3nPmOhUy4jeHexl7XJJpWDBgEnEfp+8w==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mobx" + } + }, + "node_modules/mobx-react": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-6.1.5.tgz", + "integrity": "sha512-EfWoXmGE2CfozH4Xirb65+il1ynHFCmxBSUabMSf+511YfjVs6QRcCrHkiVw+Il8iWp1gIyfa9qKkUgbDA9/2w==", + "dependencies": { + "mobx-react-lite": "^1.4.2" + }, + "peerDependencies": { + "mobx": "^4.0.0 || ^5.0.0", + "react": "^16.8.0 || 16.9.0-alpha.0" + } + }, + "node_modules/mobx-react-lite": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-1.5.2.tgz", + "integrity": "sha512-PyZmARqqWtpuQaAoHF5pKX7h6TKNLwq6vtovm4zZvG6sEbMRHHSqioGXSeQbpRmG8Kw8uln3q/W1yMO5IfL5Sg==", + "peerDependencies": { + "mobx": "^4.0.0 || ^5.0.0", + "react": "^16.8.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "optional": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=" + }, + "node_modules/negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node_modules/node-fetch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", + "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha1-271K8SE04uY1wkXvk//Pb2BnOl0=", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, + "node_modules/nomnom": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", + "integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=", + "deprecated": "Package no longer supported. Contact support@npmjs.com for more info.", + "dependencies": { + "colors": "0.5.x", + "underscore": "1.1.x" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nomnom/node_modules/underscore": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz", + "integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=", + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dependencies": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oas-kit-common": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.7.tgz", + "integrity": "sha512-8+P8gBjN9bGfa5HPgyefO78o394PUwHoQjuD4hM0Bpl56BkcxoyW4MpWMPM6ATm+yIIz4qT1igmuVukUtjP/pQ==", + "dependencies": { + "safe-json-stringify": "^1.2.0" + } + }, + "node_modules/oas-linter": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-1.0.8.tgz", + "integrity": "sha512-d60OArJNBalU5q9utXgsWUdxNS2EWenLp/fSrCQXFHoZhFOLQDTCh2CeqddifM0q1Q0Z9noTiFnwuyqSi2Pa6A==", + "dependencies": { + "js-yaml": "^3.12.0", + "should": "^13.2.1" + } + }, + "node_modules/oas-resolver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-1.1.1.tgz", + "integrity": "sha512-r7jWfhtW/eQ42/eqnUXMUS46jB+XoNlIOSkjN6ZQH+3tqPQHMwAqRUQTqdh+0Qw7IAipftb6zFVwyfE6kVCmGQ==", + "dependencies": { + "js-yaml": "^3.12.0", + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.6", + "reftools": "^1.0.4", + "yargs": "^12.0.2" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.2.tgz", + "integrity": "sha512-Q9xqeUtc17ccP/dpUfARci4kwFFszyJAgR/wbDhrRR/73GqsY5uSmKaIK+RmBqO8J4jVYrrDPjQKvt1IcpQdGw==" + }, + "node_modules/oas-validator": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-1.1.13.tgz", + "integrity": "sha512-sEWaUq5/b5+iOUEtnu/Ioi3bN1SwIvexSpeFdg3H0v4ASPmK1l/70vpYXfupVElFzjx4unc2odFp9oJR+L5f7w==", + "dependencies": { + "ajv": "^5.5.2", + "better-ajv-errors": "^0.5.2", + "js-yaml": "^3.12.0", + "oas-kit-common": "^1.0.4", + "oas-linter": "^1.0.8", + "oas-resolver": "^1.0.12", + "oas-schema-walker": "^1.1.0", + "reftools": "^1.0.3", + "should": "^13.2.1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dependencies": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ono": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.11.tgz", + "integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==", + "dependencies": { + "format-util": "^1.0.3" + } + }, + "node_modules/openapi-sampler": { + "version": "1.0.0-beta.15", + "resolved": "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.0.0-beta.15.tgz", + "integrity": "sha512-wUD/vD3iBHKik/sME3uwUu4X3HFA53rDrPcVvLzgEELjHLbnTpSYfm4Jo9qZT1dPfBRowAnrF/VRQfOjL5QRAw==", + "dependencies": { + "json-pointer": "^0.6.0" + } + }, + "node_modules/optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "node_modules/options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/opts": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/opts/-/opts-1.2.6.tgz", + "integrity": "sha1-0YXAQlz9652h0YKQi2W1wCOP67M=" + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "node_modules/os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dependencies": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dependencies": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-glob/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-glob/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-loader": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.9.tgz", + "integrity": "sha512-pD37gArtr+/72Tst9oJoDB9k7gB9A09Efj7yyBi5HDUqaxqULXBWW8Rnw2TfNF+3sN7QZv0ZNdW1Qx2pFGW5Jg==", + "dependencies": { + "native-promise-only": "^0.8.1", + "superagent": "^3.8.3" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/perfect-scrollbar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.0.tgz", + "integrity": "sha512-NrNHJn5mUGupSiheBTy6x+6SXCFbLlm8fVZh9moIzw/LgqElN5q4ncR4pbCBCYuCJ8Kcl9mYM0NgDxvW+b4LxA==" + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/polished": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-3.7.1.tgz", + "integrity": "sha512-/QgHrNGYwIA4mwxJ/7FSvalUJsm7KNfnXiScVSEG2Xa5qxDeBn4nmdjN2pW00mkM2Tts64ktc47U8F7Ed1BRAA==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/polished/node_modules/@babel/runtime": { + "version": "7.13.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.7.tgz", + "integrity": "sha512-h+ilqoX998mRVM5FtB5ijRuHUDVt5l3yfoOi2uh18Z/O3hvyaHQ39NpxVkCIG5yFs+mLq/ewFp8Bss6zmWv6ZA==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + } + }, + "node_modules/polished/node_modules/regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prismjs": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", + "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", + "optionalDependencies": { + "clipboard": "^2.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "node_modules/prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dependencies": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/randexp": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.9.tgz", + "integrity": "sha512-maAX1cnBkzIZ89O4tSQUOF098xjGMC8N+9vuY/WfHwg87THw6odD2Br35donlj5e6KnB1SB0QBHhTQhhDHuTPQ==", + "dependencies": { + "drange": "^1.0.0", + "ret": "^0.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/randexp/node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dependencies": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/randomatic/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dependencies": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + }, + "peerDependencies": { + "react": "^16.14.0" + } + }, + "node_modules/react-dropdown": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/react-dropdown/-/react-dropdown-1.9.2.tgz", + "integrity": "sha512-g4eufErTi5P5T5bGK+VmLl//qvAHy79jm6KKx8G2Tl3mG90bpigb+Aw85P+C2JUdAnIIQdv8kP/oHN314GvAfw==", + "dependencies": { + "classnames": "^2.2.3" + }, + "peerDependencies": { + "react": "^0.14.7 || ^15.0.0-0 || ^16.0.0 || ^17.0.0", + "react-dom": "^0.14.7 || ^15.0.0-0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-tabs": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-3.2.0.tgz", + "integrity": "sha512-q7oNapNRoYTQq8gDhApXwdBheuuN5qQ4YvUaQUAkb6OSSttJulBAvxJ0FS6W5uojvMxbbIZKu1f2I+GXISoLjw==", + "dependencies": { + "clsx": "^1.1.0", + "prop-types": "^15.5.0" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.0-0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/redoc": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.24.tgz", + "integrity": "sha512-h82NZFDzTUgAEtd0st3D29EsrxO8bw+26xdX1Y0vtwlp6uiQUA44uZLpdBnOlcSWMipbZ75ra6uuBU2NHFNPGg==", + "dependencies": { + "classnames": "^2.2.6", + "decko": "^1.2.0", + "dompurify": "^2.0.8", + "eventemitter3": "^4.0.0", + "json-pointer": "^0.6.0", + "json-schema-ref-parser": "^6.1.0", + "lunr": "2.3.8", + "mark.js": "^8.11.1", + "marked": "^0.7.0", + "memoize-one": "~5.1.1", + "mobx-react": "6.1.5", + "openapi-sampler": "1.0.0-beta.15", + "perfect-scrollbar": "^1.4.0", + "polished": "^3.4.4", + "prismjs": "^1.19.0", + "prop-types": "^15.7.2", + "react-dropdown": "^1.7.0", + "react-tabs": "^3.1.0", + "slugify": "^1.4.0", + "stickyfill": "^1.1.1", + "swagger2openapi": "^5.3.4", + "tslib": "^1.11.1", + "url-template": "^2.0.8" + }, + "engines": { + "node": ">=6.9", + "npm": ">=3.0.0" + }, + "peerDependencies": { + "core-js": "^3.1.4", + "mobx": "^4.2.0 || ^5.0.0", + "react": "^16.8.4", + "react-dom": "^16.8.4", + "styled-components": "^4.1.1" + } + }, + "node_modules/redoc/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/reftools": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.0.7.tgz", + "integrity": "sha512-J4rugWI8+trddvJxXzK0VeEW9YBfofY5SOJzmvRRiVYRzbR8RbFjtlP2eZbJlqz5GwkvO9iCJZLvkem7dGA5zg==" + }, + "node_modules/regenerator-runtime": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + }, + "node_modules/regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dependencies": { + "is-equal-shallow": "^0.1.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-dir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/require-dir/-/require-dir-1.2.0.tgz", + "integrity": "sha512-LY85DTSu+heYgDqq/mK+7zFHWkttVNRXC9NKcKGyuGLdlsfbjEPrIEYdCVrx6hqnJb+xSu3Lzaoo8VnmOhhjNA==", + "engines": { + "node": "*" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==" + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", + "optional": true + }, + "node_modules/semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "deprecated": "Critical bug fixed in v3.0.1, please upgrade to the latest version.", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", + "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=" + }, + "node_modules/signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/slugify": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.7.tgz", + "integrity": "sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "deprecated": "Please upgrade to v1.0.1", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "optional": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dependencies": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "dependencies": { + "escodegen": "^1.8.1" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dependencies": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/static-eval/node_modules/estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stickyfill": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stickyfill/-/stickyfill-1.1.1.tgz", + "integrity": "sha1-OUE/7p0CXHSn5ZzuyyN4TMDxfwI=" + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-url-auth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-url-auth/-/strip-url-auth-1.0.1.tgz", + "integrity": "sha1-IrD6OkE4WzO+PzMVUbu4N/oM164=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/styled-components": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz", + "integrity": "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==", + "hasInstallScript": true, + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@emotion/is-prop-valid": "^0.8.1", + "@emotion/unitless": "^0.7.0", + "babel-plugin-styled-components": ">= 1", + "css-to-react-native": "^2.2.2", + "memoize-one": "^5.0.0", + "merge-anything": "^2.2.4", + "prop-types": "^15.5.4", + "react-is": "^16.6.0", + "stylis": "^3.5.0", + "stylis-rule-sheet": "^0.0.10", + "supports-color": "^5.5.0" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, + "node_modules/stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + }, + "node_modules/stylis-rule-sheet": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", + "peerDependencies": { + "stylis": "^3.5.0" + } + }, + "node_modules/superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swagger-editor-dist": { + "version": "3.6.25", + "resolved": "https://registry.npmjs.org/swagger-editor-dist/-/swagger-editor-dist-3.6.25.tgz", + "integrity": "sha512-RGJkzjI5K4uYT0Lt9R82Oqm5x3NBFWaq3H+u+QSHqRO7JB0DazlibjTNx/BfKWgYVzzVFMaIlCIf8DIbgp4f0g==" + }, + "node_modules/swagger-methods": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/swagger-methods/-/swagger-methods-1.0.8.tgz", + "integrity": "sha512-G6baCwuHA+C5jf4FNOrosE4XlmGsdjbOjdBK4yuiDDj/ro9uR4Srj3OR84oQMT8F3qKp00tYNv0YN730oTHPZA==", + "deprecated": "This package is no longer being maintained." + }, + "node_modules/swagger-repo": { + "version": "2.0.0-rc.11", + "resolved": "https://registry.npmjs.org/swagger-repo/-/swagger-repo-2.0.0-rc.11.tgz", + "integrity": "sha512-/MVudBX2shmHeYIAltASxc32pUKM0N/wBmty979RhtRmvozJqgZXtDm0bqJ3PHtddQn6sDwwq1prvhO4Nl+iGw==", + "dependencies": { + "body-parser": "^1.15.2", + "chalk": "^2.4.1", + "commander": "^2.9.0", + "cors": "^2.7.1", + "express": "^4.13.4", + "fs-extra": "^7.0.1", + "gh-pages": "^2.0.1", + "glob": "^7.0.0", + "js-yaml": "^3.5.3", + "json-pointer": "^0.6.0", + "jsonpath": "^1.0.0", + "livereload": "^0.7.0", + "lodash": "^4.5.0", + "mkdirp": "^0.5.1", + "node-fetch": "^2.3.0", + "oas-validator": "^1.1.13", + "require-dir": "^1.0.0", + "swagger-editor-dist": "^3.6.16", + "swagger-ui-dist": "^3.20.1", + "sway": "^2.0.5" + }, + "bin": { + "swagger-repo": "bin/swagger-repo.js" + }, + "engines": { + "node": ">=10.14.0" + } + }, + "node_modules/swagger-schema-official": { + "version": "2.0.0-bab6bed", + "resolved": "https://registry.npmjs.org/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz", + "integrity": "sha1-cAcEaNbSl3ylI3suUZyn0Gouo/0=" + }, + "node_modules/swagger-ui-dist": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.22.0.tgz", + "integrity": "sha512-ZFcQoi4XT2t/NGKByVwmb4iERLtGmQQEFqHNC1PmdauWVZ2y80akkzctghgAftTlc8xpUp+I62nm4Km2q82ajQ==" + }, + "node_modules/swagger2openapi": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-5.4.0.tgz", + "integrity": "sha512-f5QqfXawiVijhjMtYqWZ55ESHPZFqrPC8L9idhIiuSX8O2qsa1i4MVGtCM3TQF+Smzr/6WfT/7zBuzG3aTgPAA==", + "dependencies": { + "better-ajv-errors": "^0.6.1", + "call-me-maybe": "^1.0.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.7", + "oas-resolver": "^2.3.0", + "oas-schema-walker": "^1.1.3", + "oas-validator": "^3.4.0", + "reftools": "^1.1.0", + "yaml": "^1.8.3", + "yargs": "^12.0.5" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + } + }, + "node_modules/swagger2openapi/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/swagger2openapi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/better-ajv-errors": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/better-ajv-errors/-/better-ajv-errors-0.6.7.tgz", + "integrity": "sha512-PYgt/sCzR4aGpyNy5+ViSQ77ognMnWq7745zM+/flYO4/Yisdtp9wDQW2IKCyVYPUxQt3E/b5GBSwfhd1LPdlg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/runtime": "^7.0.0", + "chalk": "^2.4.1", + "core-js": "^3.2.1", + "json-to-ast": "^2.0.3", + "jsonpointer": "^4.0.1", + "leven": "^3.1.0" + }, + "peerDependencies": { + "ajv": "4.11.8 - 6" + } + }, + "node_modules/swagger2openapi/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/swagger2openapi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/swagger2openapi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/swagger2openapi/node_modules/core-js": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.0.tgz", + "integrity": "sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/swagger2openapi/node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/swagger2openapi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/swagger2openapi/node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/swagger2openapi/node_modules/oas-linter": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.1.tgz", + "integrity": "sha512-e5G6bbq3Nrfxm+SDPR5AiZ6n2smVUmhLA1OgI2/Bl8e2ywfWsKw/yuqrwiXXiNHb1wdM/GyPMX6QjCGJODlaaA==", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/oas-resolver": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.4.tgz", + "integrity": "sha512-1vIj5Wkjmi+kZj5sFamt95LkuXoalmoKUohtaUQoCQZjLfPFaY8uZ7nw6IZaWuE6eLON2b6xrXhxD4hiTdYl0g==", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.8", + "yaml": "^1.10.0", + "yargs": "^16.1.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/oas-resolver/node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/swagger2openapi/node_modules/oas-resolver/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger2openapi/node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/oas-validator": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-3.4.0.tgz", + "integrity": "sha512-l/SxykuACi2U51osSsBXTxdsFc8Fw41xI7AsZkzgVgWJAzoEFaaNptt35WgY9C3757RUclsm6ye5GvSyYoozLQ==", + "dependencies": { + "ajv": "^5.5.2", + "better-ajv-errors": "^0.6.7", + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.7", + "oas-linter": "^3.1.0", + "oas-resolver": "^2.3.0", + "oas-schema-walker": "^1.1.3", + "reftools": "^1.1.0", + "should": "^13.2.1", + "yaml": "^1.8.3" + } + }, + "node_modules/swagger2openapi/node_modules/reftools": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.8.tgz", + "integrity": "sha512-Yvz9NH8uFHzD/AXX82Li1GdAP6FzDBxEZw+njerNBBQv/XHihqsWAjNfXtaq4QD2l4TEZVnp4UbktdYSegAM3g==", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/swagger2openapi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/swagger2openapi/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger2openapi/node_modules/yargs-parser": { + "version": "20.2.6", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.6.tgz", + "integrity": "sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/sway": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/sway/-/sway-2.0.5.tgz", + "integrity": "sha512-F7Y+IiVXAtBgUxlbEKuL5WUVaoriWEvYKXwE5XF+44ZKVY2ZGw4gOLqQFZvGqwQAODoqDVU8ENKKgO+u+S0DzQ==", + "dependencies": { + "debug": "^3.1.0", + "faker": "^4.1.0", + "js-base64": "^2.4.5", + "js-yaml": "^3.12.0", + "json-refs": "^3.0.7", + "json-schema-faker": "0.5.0-rc15", + "lodash": "^4.17.10", + "native-promise-only": "^0.8.1", + "path-to-regexp": "^1.7.0", + "swagger-methods": "^1.0.0", + "swagger-schema-official": "2.0.0-bab6bed", + "z-schema": "^3.22.0" + } + }, + "node_modules/sway/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/sway/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/sway/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/sway/node_modules/path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uglify-js": { + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz", + "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, + "node_modules/underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" + }, + "node_modules/union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "deprecated": "Critical bug fixed in v3.0.1, please upgrade to the latest version.", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/uri-js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz", + "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "dependencies": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "node_modules/yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dependencies": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "node_modules/yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/z-schema": { + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.25.1.tgz", + "integrity": "sha512-7tDlwhrBG+oYFdXNOjILSurpfQyuVgkRe3hB2q8TEssamDHB7BbLWYkYO98nTn0FibfdFroFKDjndbgufAgS/Q==", + "dependencies": { + "core-js": "^2.5.7", + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^10.0.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "optionalDependencies": { + "commander": "^2.7.1" + } + } + }, "dependencies": { "@babel/code-frame": { "version": "7.0.0", @@ -371,11 +7325,6 @@ } } }, - "JSONSelect": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", - "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" - }, "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", @@ -2288,22 +9237,22 @@ "bundled": true, "optional": true }, - "string-width": { - "version": "1.0.2", + "string_decoder": { + "version": "1.1.1", "bundled": true, "optional": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "safe-buffer": "~5.1.0" } }, - "string_decoder": { - "version": "1.1.1", + "string-width": { + "version": "1.0.2", "bundled": true, "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "strip-ansi": { @@ -2837,12 +9786,12 @@ "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz", "integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=", "requires": { - "JSONSelect": "0.4.0", "cjson": "~0.2.1", "ebnf-parser": "~0.1.9", "escodegen": "0.0.21", "esprima": "1.0.x", "jison-lex": "0.2.x", + "JSONSelect": "0.4.0", "lex-parser": "~0.1.3", "nomnom": "1.5.2" }, @@ -3010,6 +9959,11 @@ "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" }, + "JSONSelect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", + "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" + }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -3428,7 +10382,8 @@ "mobx-react-lite": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-1.5.2.tgz", - "integrity": "sha512-PyZmARqqWtpuQaAoHF5pKX7h6TKNLwq6vtovm4zZvG6sEbMRHHSqioGXSeQbpRmG8Kw8uln3q/W1yMO5IfL5Sg==" + "integrity": "sha512-PyZmARqqWtpuQaAoHF5pKX7h6TKNLwq6vtovm4zZvG6sEbMRHHSqioGXSeQbpRmG8Kw8uln3q/W1yMO5IfL5Sg==", + "requires": {} }, "ms": { "version": "2.0.0", @@ -4775,6 +11730,14 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -4784,14 +11747,6 @@ "strip-ansi": "^4.0.0" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -4846,7 +11801,8 @@ "stylis-rule-sheet": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", - "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", + "requires": {} }, "superagent": { "version": "3.8.3", diff --git a/docs/spec/components/responses/internalError.yaml b/docs/spec/components/responses/internalError.yaml new file mode 100644 index 0000000..163d136 --- /dev/null +++ b/docs/spec/components/responses/internalError.yaml @@ -0,0 +1,5 @@ +description: Internal server error +content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Errors' \ No newline at end of file diff --git a/docs/spec/components/responses/invalidAuth.yaml b/docs/spec/components/responses/invalidAuth.yaml new file mode 100644 index 0000000..07a81f5 --- /dev/null +++ b/docs/spec/components/responses/invalidAuth.yaml @@ -0,0 +1,5 @@ +description: You must provide a valid authorization params. +content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Errors' \ No newline at end of file diff --git a/docs/spec/components/responses/invalidParameter.yaml b/docs/spec/components/responses/invalidParameter.yaml new file mode 100644 index 0000000..c6871c0 --- /dev/null +++ b/docs/spec/components/responses/invalidParameter.yaml @@ -0,0 +1,5 @@ +description: One of the parameters is invalid. Refer to the response body for details. +content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Errors' \ No newline at end of file diff --git a/docs/spec/components/responses/notFound.yaml b/docs/spec/components/responses/notFound.yaml new file mode 100644 index 0000000..9b842e8 --- /dev/null +++ b/docs/spec/components/responses/notFound.yaml @@ -0,0 +1,5 @@ +description: Requested resource does not exist. +content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Errors' diff --git a/docs/spec/components/schemas/Balance.yaml b/docs/spec/components/schemas/Balance.yaml new file mode 100644 index 0000000..85c4a4b --- /dev/null +++ b/docs/spec/components/schemas/Balance.yaml @@ -0,0 +1,25 @@ +allOf: + - $ref: '#/components/schemas/BalanceKey' + - type: object + required: + - attributes + properties: + attributes: + type: object + required: + - amount + - events_count + - updated_at + properties: + amount: + type: integer + description: Amount of points + example: 580 + events_count: + type: integer + description: Amount of events that have been claimed + example: 19 + updated_at: + type: integer + description: Unix milliseconds timestamp of the last points accruing + example: 1705573056000 \ No newline at end of file diff --git a/docs/spec/components/schemas/BalanceKey.yaml b/docs/spec/components/schemas/BalanceKey.yaml new file mode 100644 index 0000000..3ccb78f --- /dev/null +++ b/docs/spec/components/schemas/BalanceKey.yaml @@ -0,0 +1,12 @@ +type: object +required: + - id + - type +properties: + id: + type: string + example: "157801" + type: + type: string + enum: + - balance diff --git a/docs/spec/components/schemas/Errors.yaml b/docs/spec/components/schemas/Errors.yaml new file mode 100644 index 0000000..cc3c9b2 --- /dev/null +++ b/docs/spec/components/schemas/Errors.yaml @@ -0,0 +1,35 @@ +description: 'Standard JSON:API error' +type: object +required: + - errors +properties: + errors: + type: array + description: Non empty array of errors occurred during request processing + items: + type: object + required: + - title + - status + properties: + title: + type: string + description: 'Title is a short, human-readable summary of the problem' + example: Bad Request + detail: + type: string + description: >- + Detail is a human-readable explanation specific to this occurrence + of the problem + example: "Request body was expected" + status: + type: integer + description: Status is the HTTP status code applicable to this problem + example: 400 + enum: + - 400 + - 401 + - 403 + - 404 + - 409 + - 500 diff --git a/docs/spec/components/schemas/Event.yaml b/docs/spec/components/schemas/Event.yaml new file mode 100644 index 0000000..1144c70 --- /dev/null +++ b/docs/spec/components/schemas/Event.yaml @@ -0,0 +1,34 @@ +allOf: + - $ref: '#/components/schemas/EventKey' + - type: object + required: + - attributes + properties: + attributes: + type: object + required: + - type + - reward + - metadata + - is_claimed + - created_at + properties: + type: + type: string + description: Event type. Allowed event types are configured on back-end. + example: "org_id" + reward: + type: integer + description: Event reward in points. Configured along with `type`. + example: 200 + is_claimed: + type: boolean + description: If event has been already claimed + created_at: + type: integer + description: Unix milliseconds timestamp of event creation + example: 1705573056000 + metadata: + type: string + description: Event metadata in JSON format. Configured along with `type`. + format: json.RawMessage \ No newline at end of file diff --git a/docs/spec/components/schemas/EventKey.yaml b/docs/spec/components/schemas/EventKey.yaml new file mode 100644 index 0000000..25dc058 --- /dev/null +++ b/docs/spec/components/schemas/EventKey.yaml @@ -0,0 +1,12 @@ +type: object +required: + - id + - type +properties: + id: + type: string + example: "157801" + type: + type: string + enum: + - event diff --git a/docs/spec/paths/integrations@points-svc@balance.yaml b/docs/spec/paths/integrations@points-svc@balance.yaml new file mode 100644 index 0000000..e1d5f83 --- /dev/null +++ b/docs/spec/paths/integrations@points-svc@balance.yaml @@ -0,0 +1,24 @@ +get: + tags: + - Points balance + summary: Get points balance for user + description: Balance of authorized user who makes the request + operationId: getPointsBalance + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Balance' + 400: + $ref: '#/components/responses/invalidParameter' + 401: + $ref: '#/components/responses/invalidAuth' + 500: + $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml new file mode 100644 index 0000000..1299424 --- /dev/null +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -0,0 +1,38 @@ +get: + tags: + - Events + summary: Get events for user + description: | + Returns list of _available_ and _claimed_ events for the single user. + Events are sorted by `created_at` field. + operationId: getEvents + parameters: + - in: query + name: 'filter[is_claimed]' + description: If event has been already claimed. By default all events are returned. + required: false + schema: + type: boolean + - $ref: '#/components/parameters/pageLimitParam' + - $ref: '#/components/parameters/pageCursorParam' + - $ref: '#/components/parameters/sortingParam' + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Event' + 400: + $ref: '#/components/responses/invalidParameter' + 401: + $ref: '#/components/responses/invalidAuth' + 500: + $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@points-svc@events@{id}.yaml b/docs/spec/paths/integrations@points-svc@events@{id}.yaml new file mode 100644 index 0000000..cb4316e --- /dev/null +++ b/docs/spec/paths/integrations@points-svc@events@{id}.yaml @@ -0,0 +1,31 @@ +put: + tags: + - Events + summary: Claim points for event + description: Update event status to _claimed_ and accrue points. + operationId: claimEvent + parameters: + - in: path + name: 'id' + required: true + schema: + type: string + example: "157801" + responses: + 200: + description: OK + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Event' + 400: + $ref: '#/components/responses/invalidParameter' + 401: + $ref: '#/components/responses/invalidAuth' + 500: + $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@points-svc@leaderboard.yaml b/docs/spec/paths/integrations@points-svc@leaderboard.yaml new file mode 100644 index 0000000..9e67e65 --- /dev/null +++ b/docs/spec/paths/integrations@points-svc@leaderboard.yaml @@ -0,0 +1,44 @@ +get: + tags: + - Points balance + summary: Get leaderboard + description: Returns leaders sorted by points or number of claimed events in descending order. + operationId: getLeaderboard + parameters: + - in: query + name: 'page[limit]' + description: Number of leaders to return + required: false + schema: + type: integer + minimum: 3 + maximum: 50 + default: 10 + - in: query + name: 'page[order_by]' + description: | + First field to sort by. If you specify `events`, then the leaderboard + will be sorted by number of claimed events and then by points. + required: false + schema: + type: string + enum: [points, events] + default: points + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Balance' + 400: + $ref: '#/components/responses/invalidParameter' + 500: + $ref: '#/components/responses/internalError' diff --git a/generate.sh b/generate.sh index 0559aba..10c2b93 100755 --- a/generate.sh +++ b/generate.sh @@ -1,10 +1,11 @@ #!/usr/bin/env bash -GENERATOR_IMAGE=tokend/openapi-generator:v0.1.0 +GENERATOR_IMAGE=registry.gitlab.com/tokend/openapi-go-generator:c59241b52b0e37bbbeb02a214ab5bfd07627aabc +[[ ! -x "$(command -v go 2>/dev/null)" ]] && echo "go is not installed" && exit 1 -GENERATED="${GOPATH}/src/github.com/rarimo/rarime-points-svc/resources" -OPENAPI_DIR="${GOPATH}/src/github.com/rarimo/rarime-points-svc/docs/web_deploy" +GENERATED="$PWD/resources" +OPENAPI_DIR="$PWD/docs/web_deploy" PACKAGE_NAME=resources function printHelp { @@ -50,7 +51,8 @@ function parseArgs { function generate { (cd docs && npm run build) - docker run -v "${OPENAPI_DIR}":/openapi -v "${GENERATED}":/generated "${GENERATOR_IMAGE}" generate -pkg "${PACKAGE_NAME}" --raw-formats-as-types + docker run --rm -v "${OPENAPI_DIR}":/openapi -v "${GENERATED}":/generated "${GENERATOR_IMAGE}" \ + generate -pkg "${PACKAGE_NAME}" --raw-formats-as-types --meta-for-lists goimports -w ${GENERATED} } diff --git a/resources/db.go b/resources/db.go new file mode 100644 index 0000000..5381330 --- /dev/null +++ b/resources/db.go @@ -0,0 +1,52 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import ( + "database/sql/driver" + + "encoding/json" + + "gitlab.com/distributed_lab/logan/v3/errors" +) + +// driverValue - converts interface into db supported type +func driverValue(data interface{}) (driver.Value, error) { + data, err := json.Marshal(data) + if err != nil { + return nil, errors.New("failed to marshal details") + } + + return data, nil +} + +// driveScan - converts jsonb into type struct +func driveScan(src, dest interface{}) error { + data, err := convertJSONB(src) + if err != nil { + return err + } + + err = json.Unmarshal(data, dest) + if err != nil { + return errors.Wrap(err, "failed to unmarshal jsonb") + } + + return nil +} + +func convertJSONB(src interface{}) ([]byte, error) { + var data []byte + switch rawData := src.(type) { + case []byte: + data = rawData + case string: + data = []byte(rawData) + default: + return nil, errors.New("Unexpected type for jsonb") + } + + return data, nil +} diff --git a/resources/flag.go b/resources/flag.go new file mode 100644 index 0000000..3b6a81a --- /dev/null +++ b/resources/flag.go @@ -0,0 +1,37 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type Flagger interface { + IsFlag() bool +} + +type Flag struct { + Name string `json:"name"` + Value int32 `json:"value"` +} + +type Flags struct { + Mask int32 `json:"mask"` + Values []Flag `json:"flags"` +} + +func FlagsFromMask(mask int32, allFlags map[int32]string) Flags { + values := []Flag{} + + for value, name := range allFlags { + if (value & mask) == value { + values = append(values, Flag{ + Value: value, + Name: name, + }) + } + } + + return Flags{ + Mask: mask, + Values: values, + } +} diff --git a/resources/included.go b/resources/included.go new file mode 100644 index 0000000..68d70a2 --- /dev/null +++ b/resources/included.go @@ -0,0 +1,105 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import ( + "encoding/json" + + "gitlab.com/distributed_lab/logan/v3/errors" +) + +type Resource interface { + //GetKey - returns key of the Resource + GetKey() Key +} + +// Included - an array of Resource objects that are related to the primary data and/or +// each other (“included resources”). +type Included struct { + includes map[Key]json.RawMessage +} + +// Add - adds new include into collection. If one already present - skips it +func (c *Included) Add(includes ...Resource) { + for i := range includes { + c.add(includes[i]) + } +} + +func (c *Included) add(include Resource) { + if c.includes == nil { + c.includes = make(map[Key]json.RawMessage) + } + + _, ok := c.includes[include.GetKey()] + if ok { + return + } + + data, err := json.Marshal(include) + if err != nil { + panic(errors.Wrap(err, "failed to add into includes")) + } + + c.includes[include.GetKey()] = json.RawMessage(data) +} + +// MarshalJSON - marshals include collection as array of json objects +func (c Included) MarshalJSON() ([]byte, error) { + uniqueEntries := make([]json.RawMessage, 0, len(c.includes)) + for _, value := range c.includes { + uniqueEntries = append(uniqueEntries, value) + } + + return json.Marshal(uniqueEntries) +} + +// UmarshalJSON - unmarshal array of json objects into include collection +func (c *Included) UnmarshalJSON(data []byte) error { + var keys []Key + err := json.Unmarshal(data, &keys) + if err != nil { + return errors.Wrap(err, "failed to unmarshal keys for include") + } + + var entries []json.RawMessage + err = json.Unmarshal(data, &entries) + if err != nil { + return errors.Wrap(err, "failed to unmarshal entries for include") + } + + c.includes = make(map[Key]json.RawMessage) + // we assume that json.Unmarshal guaranties the same order for arrays + // in case of broken order for arrays - we would panic on get of specific entry + for i := range keys { + c.includes[keys[i]] = entries[i] + } + + return nil +} + +// tryFindEntry - tries to find entry in include collection and unmarshal it +// if entry does not exists - returns false +// if entry exists but fails to unmarshal or key mismatches - panics +func (c *Included) tryFindEntry(key Key, entry Resource) bool { + rawEntry, exist := c.includes[key] + if !exist { + return false + } + + err := json.Unmarshal(rawEntry, entry) + if err != nil { + panic(errors.Wrap(err, "failed to unmarshal entry from include collection")) + } + + if entry.GetKey() != key { + panic(errors.From(errors.New("keys mismatched"), map[string]interface{}{ + "expected_key": key, + "actual_key": entry.GetKey(), + })) + } + + return true +} diff --git a/resources/links.go b/resources/links.go new file mode 100644 index 0000000..c23282d --- /dev/null +++ b/resources/links.go @@ -0,0 +1,13 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type Links struct { + First string `json:"first,omitempty"` + Last string `json:"last,omitempty"` + Next string `json:"next,omitempty"` + Prev string `json:"prev,omitempty"` + Self string `json:"self,omitempty"` +} diff --git a/resources/model_balance.go b/resources/model_balance.go new file mode 100644 index 0000000..00524a6 --- /dev/null +++ b/resources/model_balance.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type Balance struct { + Key + Attributes BalanceAttributes `json:"attributes"` +} +type BalanceResponse struct { + Data Balance `json:"data"` + Included Included `json:"included"` +} + +type BalanceListResponse struct { + Data []Balance `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *BalanceListResponse) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *BalanceListResponse) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustBalance - returns Balance from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustBalance(key Key) *Balance { + var balance Balance + if c.tryFindEntry(key, &balance) { + return &balance + } + return nil +} diff --git a/resources/model_balance_attributes.go b/resources/model_balance_attributes.go new file mode 100644 index 0000000..c76de6e --- /dev/null +++ b/resources/model_balance_attributes.go @@ -0,0 +1,14 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type BalanceAttributes struct { + // Amount of points + Amount int32 `json:"amount"` + // Amount of events that have been claimed + EventsCount int32 `json:"events_count"` + // Unix milliseconds timestamp of the last points accruing + UpdatedAt int32 `json:"updated_at"` +} diff --git a/resources/model_details.go b/resources/model_details.go new file mode 100644 index 0000000..36e0d24 --- /dev/null +++ b/resources/model_details.go @@ -0,0 +1,65 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import ( + "database/sql/driver" + "encoding/json" + + "gitlab.com/distributed_lab/logan/v3/errors" +) + +type Details json.RawMessage + +// UnmarshalJSON - casts data to Details +func (d *Details) UnmarshalJSON(data []byte) error { + if d == nil { + return errors.New("regources.Details: UnmarshalJSON on nil pointer") + } + *d = append((*d)[0:0], data...) + return nil +} + +// MarshalJSON - casts Details to []byte +func (d Details) MarshalJSON() ([]byte, error) { + if d == nil { + return []byte("null"), nil + } + return d, nil +} + +func (d Details) String() string { + return string(d) +} + +// Value - implements db driver method for auto marshal +func (r Details) Value() (driver.Value, error) { + result, err := json.Marshal(r) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal Details data") + } + + return result, nil +} + +// Scan - implements db driver method for auto unmarshal +func (r *Details) Scan(src interface{}) error { + var data []byte + switch rawData := src.(type) { + case []byte: + data = rawData + case string: + data = []byte(rawData) + default: + return errors.New("Unexpected type for jsonb") + } + + err := json.Unmarshal(data, r) + if err != nil { + return errors.Wrap(err, "failed to unmarshal Details data") + } + + return nil +} diff --git a/resources/model_event.go b/resources/model_event.go new file mode 100644 index 0000000..4fb0991 --- /dev/null +++ b/resources/model_event.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type Event struct { + Key + Attributes EventAttributes `json:"attributes"` +} +type EventResponse struct { + Data Event `json:"data"` + Included Included `json:"included"` +} + +type EventListResponse struct { + Data []Event `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *EventListResponse) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *EventListResponse) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustEvent - returns Event from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustEvent(key Key) *Event { + var event Event + if c.tryFindEntry(key, &event) { + return &event + } + return nil +} diff --git a/resources/model_event_attributes.go b/resources/model_event_attributes.go new file mode 100644 index 0000000..70aff15 --- /dev/null +++ b/resources/model_event_attributes.go @@ -0,0 +1,20 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type EventAttributes struct { + // Unix milliseconds timestamp of event creation + CreatedAt int32 `json:"created_at"` + // If event has been already claimed + IsClaimed bool `json:"is_claimed"` + // Event metadata in JSON format. Configured along with `type`. + Metadata json.RawMessage `json:"metadata"` + // Event reward in points. Configured along with `type`. + Reward int32 `json:"reward"` + // Event type. Allowed event types are configured on back-end. + Type string `json:"type"` +} diff --git a/resources/model_key.go b/resources/model_key.go new file mode 100644 index 0000000..59379dd --- /dev/null +++ b/resources/model_key.go @@ -0,0 +1,33 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "strconv" + +type Key struct { + ID string `json:"id"` + Type ResourceType `json:"type"` +} + +func NewKeyInt64(id int64, resourceType ResourceType) Key { + return Key{ + ID: strconv.FormatInt(id, 10), + Type: resourceType, + } +} + +func (r *Key) GetKey() Key { + return *r +} + +func (r Key) GetKeyP() *Key { + return &r +} + +func (r Key) AsRelation() *Relation { + return &Relation{ + Data: r.GetKeyP(), + } +} diff --git a/resources/model_relation.go b/resources/model_relation.go new file mode 100644 index 0000000..c6e3f47 --- /dev/null +++ b/resources/model_relation.go @@ -0,0 +1,10 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type Relation struct { + Data *Key `json:"data,omitempty"` + Links *Links `json:"links,omitempty"` +} diff --git a/resources/model_relation_collection.go b/resources/model_relation_collection.go new file mode 100644 index 0000000..13b6ebd --- /dev/null +++ b/resources/model_relation_collection.go @@ -0,0 +1,21 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type RelationCollection struct { + Data []Key `json:"data"` + Links *Links `json:"links,omitempty"` +} + +func (r RelationCollection) MarshalJSON() ([]byte, error) { + if r.Data == nil { + r.Data = []Key{} + } + + type temp RelationCollection + return json.Marshal(temp(r)) +} diff --git a/resources/model_resource_type.go b/resources/model_resource_type.go new file mode 100644 index 0000000..f5c17da --- /dev/null +++ b/resources/model_resource_type.go @@ -0,0 +1,13 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type ResourceType string + +// List of ResourceType +const ( + BALANCE ResourceType = "balance" + EVENT ResourceType = "event" +) From 10119ae54251b957f8bc15bc4feedc90a0b2999b Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 18 Jan 2024 14:06:02 +0200 Subject: [PATCH 02/63] Add SQL migration --- internal/assets/migrations/001_initial.sql | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 4c4e740..2cbe13c 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -1,3 +1,43 @@ -- +migrate Up +DROP FUNCTION IF EXISTS trigger_set_updated_at cascade; + +CREATE FUNCTION trigger_set_updated_at() RETURNS TRIGGER + LANGUAGE plpgsql +AS $$ BEGIN NEW.updated_at = NOW() at time zone 'utc'; RETURN NEW; END; $$; + +CREATE TABLE IF NOT EXISTS balances +( + id serial primary key, + did text not null unique, + amount integer not null default 0, + updated_at timestamp without time zone not null default NOW() +); + +CREATE INDEX IF NOT EXISTS balances_did_index on balances using btree (did); + +CREATE TRIGGER set_updated_at + before update + on balances + for each row +EXECUTE FUNCTION trigger_set_updated_at(); + +CREATE TABLE IF NOT EXISTS events +( + id serial primary key, + did text not null, + type text not null, + is_claimed boolean not null, + created_at timestamp without time zone not null default NOW() +); + +CREATE INDEX IF NOT EXISTS events_did_index on events using btree (did); -- +migrate Down +DROP INDEX IF EXISTS events_did_index; +DROP TABLE IF EXISTS events; + +DROP TRIGGER IF EXISTS set_updated_at on balances; +DROP INDEX IF EXISTS balances_did_index; +DROP TABLE IF EXISTS balances; + +DROP FUNCTION IF EXISTS trigger_set_updated_at cascade; From aef4ad664beccdb4723f06c4a0b7d10ce198ac12 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Fri, 19 Jan 2024 13:14:47 +0200 Subject: [PATCH 03/63] Changes of service API --- .../parameters/pageCursorParam.yaml | 7 +++ .../parameters/pageNumberParam.yaml | 6 --- docs/spec/components/schemas/Balance.yaml | 17 ++++--- docs/spec/components/schemas/Event.yaml | 49 +++++++++++-------- .../paths/integrations@points-svc@events.yaml | 21 +++++--- .../integrations@points-svc@events@{id}.yaml | 15 ++---- 6 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 docs/spec/components/parameters/pageCursorParam.yaml delete mode 100644 docs/spec/components/parameters/pageNumberParam.yaml diff --git a/docs/spec/components/parameters/pageCursorParam.yaml b/docs/spec/components/parameters/pageCursorParam.yaml new file mode 100644 index 0000000..d40c572 --- /dev/null +++ b/docs/spec/components/parameters/pageCursorParam.yaml @@ -0,0 +1,7 @@ +in: query +name: 'page[cursor]' +required: false +schema: + type: integer + example: 157781 +description: Cursor position diff --git a/docs/spec/components/parameters/pageNumberParam.yaml b/docs/spec/components/parameters/pageNumberParam.yaml deleted file mode 100644 index 4659012..0000000 --- a/docs/spec/components/parameters/pageNumberParam.yaml +++ /dev/null @@ -1,6 +0,0 @@ -in: query -name: 'page[number]' -required: false -schema: - type: integer -description: The number of a page to return. diff --git a/docs/spec/components/schemas/Balance.yaml b/docs/spec/components/schemas/Balance.yaml index 85c4a4b..0afe4ce 100644 --- a/docs/spec/components/schemas/Balance.yaml +++ b/docs/spec/components/schemas/Balance.yaml @@ -7,19 +7,20 @@ allOf: attributes: type: object required: + - user_did - amount - - events_count - updated_at properties: + user_did: + type: string + description: DID of the points owner + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" amount: type: integer description: Amount of points example: 580 - events_count: - type: integer - description: Amount of events that have been claimed - example: 19 updated_at: - type: integer - description: Unix milliseconds timestamp of the last points accruing - example: 1705573056000 \ No newline at end of file + type: string + format: time.Time + description: UTC time (RFC3339) of the last points accruing + example: "2021-08-12T13:00:00Z" diff --git a/docs/spec/components/schemas/Event.yaml b/docs/spec/components/schemas/Event.yaml index 1144c70..bc966a2 100644 --- a/docs/spec/components/schemas/Event.yaml +++ b/docs/spec/components/schemas/Event.yaml @@ -7,28 +7,37 @@ allOf: attributes: type: object required: - - type - - reward - - metadata - - is_claimed + - status - created_at + - meta properties: - type: + status: type: string - description: Event type. Allowed event types are configured on back-end. - example: "org_id" - reward: - type: integer - description: Event reward in points. Configured along with `type`. - example: 200 - is_claimed: - type: boolean - description: If event has been already claimed + description: See `filter[status]` parameter for explanation + enum: [open, fulfilled, claimed] created_at: - type: integer - description: Unix milliseconds timestamp of event creation - example: 1705573056000 - metadata: type: string - description: Event metadata in JSON format. Configured along with `type`. - format: json.RawMessage \ No newline at end of file + format: time.Time + description: UTC time (RFC3339) of event creation + example: "2021-08-12T13:00:00Z" + meta: + type: object + required: + - static + properties: + static: + type: string + format: json.RawMessage + description: Primary event metadata. This is a template to be filled by `dynamic` when it's present. + example: | + { + "title": "Verify proof {:id}", + "description": "Your proof should be verified by somebody", + "type": "unlimited", + "reward": 5 + } + dynamic: + type: string + format: json.RawMessage + description: Some events require dynamic data, which can be filled into `static` template. + example: { "id": "123" } diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml index 1299424..9d1f91c 100644 --- a/docs/spec/paths/integrations@points-svc@events.yaml +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -1,18 +1,23 @@ get: tags: - Events - summary: Get events for user - description: | - Returns list of _available_ and _claimed_ events for the single user. - Events are sorted by `created_at` field. + summary: Get events + description: Returns events for a single user. operationId: getEvents parameters: - in: query - name: 'filter[is_claimed]' - description: If event has been already claimed. By default all events are returned. + name: 'filter[status]' + description: | + Filter by event status, which is: + - `open` - you need to do something on the platform + - `fulfilled` - you have done something and are eligible to claim the reward + - `claimed` - you have claimed the reward required: false schema: - type: boolean + type: array + items: + type: string + enum: [open, fulfilled, claimed] - $ref: '#/components/parameters/pageLimitParam' - $ref: '#/components/parameters/pageCursorParam' - $ref: '#/components/parameters/sortingParam' @@ -33,6 +38,6 @@ get: 400: $ref: '#/components/responses/invalidParameter' 401: - $ref: '#/components/responses/invalidAuth' + $ref: '#/components/responses/invalidAuth' 500: $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@points-svc@events@{id}.yaml b/docs/spec/paths/integrations@points-svc@events@{id}.yaml index cb4316e..26c67d0 100644 --- a/docs/spec/paths/integrations@points-svc@events@{id}.yaml +++ b/docs/spec/paths/integrations@points-svc@events@{id}.yaml @@ -1,4 +1,4 @@ -put: +patch: tags: - Events summary: Claim points for event @@ -12,17 +12,8 @@ put: type: string example: "157801" responses: - 200: - description: OK - content: - application/vnd.api+json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Event' + 204: + description: No content 400: $ref: '#/components/responses/invalidParameter' 401: From 54c3553625fd80ba957a8b174d3f24c96a2838f2 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Fri, 19 Jan 2024 13:51:10 +0200 Subject: [PATCH 04/63] Change DB schema and formatting --- internal/assets/migrations/001_initial.sql | 28 ++++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 2cbe13c..9dd6988 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -7,37 +7,33 @@ AS $$ BEGIN NEW.updated_at = NOW() at time zone 'utc'; RETURN NEW; END; $$; CREATE TABLE IF NOT EXISTS balances ( - id serial primary key, - did text not null unique, - amount integer not null default 0, + id serial PRIMARY KEY, + did text not null unique, + amount integer not null default 0, updated_at timestamp without time zone not null default NOW() ); -CREATE INDEX IF NOT EXISTS balances_did_index on balances using btree (did); - CREATE TRIGGER set_updated_at before update on balances for each row EXECUTE FUNCTION trigger_set_updated_at(); +CREATE TYPE event_status AS ENUM ('open', 'fulfilled', 'claimed'); + CREATE TABLE IF NOT EXISTS events ( - id serial primary key, - did text not null, - type text not null, - is_claimed boolean not null, - created_at timestamp without time zone not null default NOW() + id serial PRIMARY KEY, + type_id smallint not null, + balance_id integer null REFERENCES balances (id), + status event_status not null, + created_at timestamp without time zone not null default NOW(), + meta text ); -CREATE INDEX IF NOT EXISTS events_did_index on events using btree (did); - -- +migrate Down -DROP INDEX IF EXISTS events_did_index; DROP TABLE IF EXISTS events; - +DROP TYPE IF EXISTS event_status; DROP TRIGGER IF EXISTS set_updated_at on balances; -DROP INDEX IF EXISTS balances_did_index; DROP TABLE IF EXISTS balances; - DROP FUNCTION IF EXISTS trigger_set_updated_at cascade; From 2b3fa90fb57a6326bb8441ae5276b4cc54aaf2b0 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Fri, 19 Jan 2024 15:23:06 +0200 Subject: [PATCH 05/63] Fix Event meta in docs, regenerate models --- docs/spec/components/schemas/Event.yaml | 21 +------------------- docs/spec/components/schemas/EventMeta.yaml | 22 +++++++++++++++++++++ resources/model_balance_attributes.go | 10 ++++++---- resources/model_event_attributes.go | 17 ++++++---------- resources/model_event_meta.go | 14 +++++++++++++ 5 files changed, 49 insertions(+), 35 deletions(-) create mode 100644 docs/spec/components/schemas/EventMeta.yaml create mode 100644 resources/model_event_meta.go diff --git a/docs/spec/components/schemas/Event.yaml b/docs/spec/components/schemas/Event.yaml index bc966a2..20f4f73 100644 --- a/docs/spec/components/schemas/Event.yaml +++ b/docs/spec/components/schemas/Event.yaml @@ -21,23 +21,4 @@ allOf: description: UTC time (RFC3339) of event creation example: "2021-08-12T13:00:00Z" meta: - type: object - required: - - static - properties: - static: - type: string - format: json.RawMessage - description: Primary event metadata. This is a template to be filled by `dynamic` when it's present. - example: | - { - "title": "Verify proof {:id}", - "description": "Your proof should be verified by somebody", - "type": "unlimited", - "reward": 5 - } - dynamic: - type: string - format: json.RawMessage - description: Some events require dynamic data, which can be filled into `static` template. - example: { "id": "123" } + $ref: '#/components/schemas/EventMeta' diff --git a/docs/spec/components/schemas/EventMeta.yaml b/docs/spec/components/schemas/EventMeta.yaml new file mode 100644 index 0000000..ec181e4 --- /dev/null +++ b/docs/spec/components/schemas/EventMeta.yaml @@ -0,0 +1,22 @@ +type: object +required: + - static +properties: + static: + type: string + format: json.RawMessage + description: | + Primary event metadata in plain JSON. This is a template + to be filled by `dynamic` when it's present. + example: + { + "title": "Verify proof {:id}", + "description": "Your proof should be verified by somebody", + "type": "unlimited", + "reward": 5 + } + dynamic: + type: string + format: json.RawMessage + description: Some events require dynamic data, which can be filled into `static` template. + example: { "id": "123" } diff --git a/resources/model_balance_attributes.go b/resources/model_balance_attributes.go index c76de6e..b535c13 100644 --- a/resources/model_balance_attributes.go +++ b/resources/model_balance_attributes.go @@ -4,11 +4,13 @@ package resources +import "time" + type BalanceAttributes struct { // Amount of points Amount int32 `json:"amount"` - // Amount of events that have been claimed - EventsCount int32 `json:"events_count"` - // Unix milliseconds timestamp of the last points accruing - UpdatedAt int32 `json:"updated_at"` + // UTC time (RFC3339) of the last points accruing + UpdatedAt time.Time `json:"updated_at"` + // DID of the points owner + UserDid string `json:"user_did"` } diff --git a/resources/model_event_attributes.go b/resources/model_event_attributes.go index 70aff15..cf3cd40 100644 --- a/resources/model_event_attributes.go +++ b/resources/model_event_attributes.go @@ -4,17 +4,12 @@ package resources -import "encoding/json" +import "time" type EventAttributes struct { - // Unix milliseconds timestamp of event creation - CreatedAt int32 `json:"created_at"` - // If event has been already claimed - IsClaimed bool `json:"is_claimed"` - // Event metadata in JSON format. Configured along with `type`. - Metadata json.RawMessage `json:"metadata"` - // Event reward in points. Configured along with `type`. - Reward int32 `json:"reward"` - // Event type. Allowed event types are configured on back-end. - Type string `json:"type"` + // UTC time (RFC3339) of event creation + CreatedAt time.Time `json:"created_at"` + Meta EventMeta `json:"meta"` + // See `filter[status]` parameter for explanation + Status string `json:"status"` } diff --git a/resources/model_event_meta.go b/resources/model_event_meta.go new file mode 100644 index 0000000..541c1ce --- /dev/null +++ b/resources/model_event_meta.go @@ -0,0 +1,14 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type EventMeta struct { + // Some events require dynamic data, which can be filled into `static` template. + Dynamic *json.RawMessage `json:"dynamic,omitempty"` + // Primary event metadata in plain JSON. This is a template to be filled by `dynamic` when it's present. + Static json.RawMessage `json:"static"` +} From 938d5f286765b30265c39f1143cf03f61a42538f Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Fri, 19 Jan 2024 15:32:26 +0200 Subject: [PATCH 06/63] Add basic models to work with DB --- internal/data/main.go | 43 ++++++++++++++++++ internal/data/pg/balances.go | 80 ++++++++++++++++++++++++++++++++++ internal/data/pg/events.go | 84 ++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 internal/data/main.go create mode 100644 internal/data/pg/balances.go create mode 100644 internal/data/pg/events.go diff --git a/internal/data/main.go b/internal/data/main.go new file mode 100644 index 0000000..2026b9f --- /dev/null +++ b/internal/data/main.go @@ -0,0 +1,43 @@ +package data + +import ( + "database/sql" + "time" +) + +type EventsQ interface { + New() EventsQ + Insert(Event) error + UpdateStatus(string) error + Select() ([]Event, error) + + FilterByID(string) EventsQ + FilterByBalanceID(...string) EventsQ + FilterByStatus(...string) EventsQ +} + +type BalancesQ interface { + New() BalancesQ + Insert(Balance) error + UpdateAmount(int) error + Get() (*Balance, error) + + FilterByID(string) BalancesQ + FilterByUserDID(string) BalancesQ +} + +type Event struct { + ID string `db:"id"` + TypeID string `db:"type_id"` + BalanceID string `db:"balance_id"` + Status string `db:"status"` + CreatedAt time.Time `db:"created_at"` + Meta sql.NullString `db:"meta"` +} + +type Balance struct { + ID string `db:"id"` + DID string `db:"did"` + Amount int `db:"amount"` + UpdatedAt time.Time `db:"updated_at"` +} diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go new file mode 100644 index 0000000..0a69dd6 --- /dev/null +++ b/internal/data/pg/balances.go @@ -0,0 +1,80 @@ +package pg + +import ( + "database/sql" + "errors" + "fmt" + + "github.com/Masterminds/squirrel" + "github.com/rarimo/points-svc/internal/data" + "gitlab.com/distributed_lab/kit/pgdb" +) + +const balancesTable = "balances" + +type balances struct { + db *pgdb.DB + selector squirrel.SelectBuilder + updater squirrel.UpdateBuilder +} + +func NewBalances(db *pgdb.DB) data.BalancesQ { + return &balances{ + db: db, + selector: squirrel.Select("*").From(balancesTable), + updater: squirrel.Update(balancesTable), + } +} + +func (q *balances) New() data.BalancesQ { + return NewBalances(q.db.Clone()) +} + +func (q *balances) Insert(balance data.Balance) error { + stmt := squirrel.Insert(balancesTable).SetMap(map[string]interface{}{ + "id": balance.ID, + "did": balance.DID, + "amount": balance.Amount, + }) + + if err := q.db.Exec(stmt); err != nil { + return fmt.Errorf("insert balance %+v: %w", balance, err) + } + + return nil +} + +func (q *balances) UpdateAmount(amount int) error { + stmt := q.updater.Set("amount", amount) + + if err := q.db.Exec(stmt); err != nil { + return fmt.Errorf("update balance amount to %d: %w", amount, err) + } + + return nil +} + +func (q *balances) Get() (*data.Balance, error) { + var res data.Balance + + if err := q.db.Get(&res, q.selector); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } + return nil, fmt.Errorf("get balance: %w", err) + } + + return &res, nil +} + +func (q *balances) FilterByID(id string) data.BalancesQ { + q.selector = q.selector.Where(squirrel.Eq{"id": id}) + q.updater = q.updater.Where(squirrel.Eq{"id": id}) + return q +} + +func (q *balances) FilterByUserDID(did string) data.BalancesQ { + q.selector = q.selector.Where(squirrel.Eq{"did": did}) + q.updater = q.updater.Where(squirrel.Eq{"did": did}) + return q +} diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go new file mode 100644 index 0000000..072b106 --- /dev/null +++ b/internal/data/pg/events.go @@ -0,0 +1,84 @@ +package pg + +import ( + "fmt" + + "github.com/Masterminds/squirrel" + "github.com/rarimo/points-svc/internal/data" + "gitlab.com/distributed_lab/kit/pgdb" +) + +const eventsTable = "events" + +type events struct { + db *pgdb.DB + selector squirrel.SelectBuilder + updater squirrel.UpdateBuilder +} + +func NewEvents(db *pgdb.DB) data.EventsQ { + return &events{ + db: db, + selector: squirrel.Select("*").From(eventsTable), + updater: squirrel.Update(eventsTable), + } +} + +func (q *events) New() data.EventsQ { + return NewEvents(q.db.Clone()) +} + +func (q *events) Insert(event data.Event) error { + stmt := squirrel.Insert(eventsTable).SetMap(map[string]interface{}{ + "id": event.ID, + "type_id": event.TypeID, + "balance_id": event.BalanceID, + "status": event.Status, + "created_at": event.CreatedAt, + "meta": event.Meta, + }) + + if err := q.db.Exec(stmt); err != nil { + return fmt.Errorf("insert event %+v: %w", event, err) + } + + return nil +} + +func (q *events) UpdateStatus(status string) error { + stmt := q.updater.Set("status", status) + + if err := q.db.Exec(stmt); err != nil { + return fmt.Errorf("update event status to %s: %w", status, err) + } + + return nil +} + +func (q *events) Select() ([]data.Event, error) { + var res []data.Event + + if err := q.db.Select(&res, q.selector); err != nil { + return nil, fmt.Errorf("select events: %w", err) + } + + return res, nil +} + +func (q *events) FilterByID(id string) data.EventsQ { + q.selector = q.selector.Where(squirrel.Eq{"id": id}) + q.updater = q.updater.Where(squirrel.Eq{"id": id}) + return q +} + +func (q *events) FilterByBalanceID(ids ...string) data.EventsQ { + q.selector = q.selector.Where(squirrel.Eq{"balance_id": ids}) + q.updater = q.updater.Where(squirrel.Eq{"balance_id": ids}) + return q +} + +func (q *events) FilterByStatus(statuses ...string) data.EventsQ { + q.selector = q.selector.Where(squirrel.Eq{"status": statuses}) + q.updater = q.updater.Where(squirrel.Eq{"status": statuses}) + return q +} From 7e0b78ceb5b82d0d4817445cfb2a930c81be2f50 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 22 Jan 2024 11:59:38 +0200 Subject: [PATCH 07/63] Add 2 simple handlers, fix amount in balance model --- .gitignore | 1 + docs/spec/components/schemas/Balance.yaml | 1 + internal/data/main.go | 15 +++++-- internal/data/pg/events.go | 14 ++++++- internal/service/handlers/claim_event.go | 50 +++++++++++++++++++++++ internal/service/handlers/ctx.go | 23 +++++++++++ internal/service/handlers/get_balance.go | 49 ++++++++++++++++++++++ internal/service/handlers/leaderboard.go | 8 ++++ internal/service/handlers/list_events.go | 14 +++++++ internal/service/main.go | 2 + internal/service/router.go | 12 ++++-- resources/model_balance_attributes.go | 2 +- 12 files changed, 182 insertions(+), 9 deletions(-) create mode 100644 internal/service/handlers/claim_event.go create mode 100644 internal/service/handlers/get_balance.go create mode 100644 internal/service/handlers/leaderboard.go create mode 100644 internal/service/handlers/list_events.go diff --git a/.gitignore b/.gitignore index abba456..07831c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .vscode/ .idea/ config.*.yaml +docker-compose.yaml docs/node_modules docs/web_deploy vendor/ diff --git a/docs/spec/components/schemas/Balance.yaml b/docs/spec/components/schemas/Balance.yaml index 0afe4ce..c61c5be 100644 --- a/docs/spec/components/schemas/Balance.yaml +++ b/docs/spec/components/schemas/Balance.yaml @@ -17,6 +17,7 @@ allOf: example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" amount: type: integer + format: int description: Amount of points example: 580 updated_at: diff --git a/internal/data/main.go b/internal/data/main.go index 2026b9f..b556eb2 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -5,15 +5,24 @@ import ( "time" ) +type EventStatus string + +const ( + EventOpen EventStatus = "open" + EventFulfilled EventStatus = "fulfilled" + EventClaimed EventStatus = "claimed" +) + type EventsQ interface { New() EventsQ Insert(Event) error - UpdateStatus(string) error + UpdateStatus(EventStatus) error Select() ([]Event, error) + Get() (*Event, error) FilterByID(string) EventsQ FilterByBalanceID(...string) EventsQ - FilterByStatus(...string) EventsQ + FilterByStatus(...EventStatus) EventsQ } type BalancesQ interface { @@ -30,7 +39,7 @@ type Event struct { ID string `db:"id"` TypeID string `db:"type_id"` BalanceID string `db:"balance_id"` - Status string `db:"status"` + Status EventStatus `db:"status"` CreatedAt time.Time `db:"created_at"` Meta sql.NullString `db:"meta"` } diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 072b106..ccbcbd4 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -45,7 +45,7 @@ func (q *events) Insert(event data.Event) error { return nil } -func (q *events) UpdateStatus(status string) error { +func (q *events) UpdateStatus(status data.EventStatus) error { stmt := q.updater.Set("status", status) if err := q.db.Exec(stmt); err != nil { @@ -65,6 +65,16 @@ func (q *events) Select() ([]data.Event, error) { return res, nil } +func (q *events) Get() (*data.Event, error) { + var res data.Event + + if err := q.db.Get(&res, q.selector); err != nil { + return nil, fmt.Errorf("get event: %w", err) + } + + return &res, nil +} + func (q *events) FilterByID(id string) data.EventsQ { q.selector = q.selector.Where(squirrel.Eq{"id": id}) q.updater = q.updater.Where(squirrel.Eq{"id": id}) @@ -77,7 +87,7 @@ func (q *events) FilterByBalanceID(ids ...string) data.EventsQ { return q } -func (q *events) FilterByStatus(statuses ...string) data.EventsQ { +func (q *events) FilterByStatus(statuses ...data.EventStatus) data.EventsQ { q.selector = q.selector.Where(squirrel.Eq{"status": statuses}) q.updater = q.updater.Where(squirrel.Eq{"status": statuses}) return q diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go new file mode 100644 index 0000000..66c47e0 --- /dev/null +++ b/internal/service/handlers/claim_event.go @@ -0,0 +1,50 @@ +package handlers + +import ( + "net/http" + + "github.com/go-chi/chi" + "github.com/rarimo/points-svc/internal/data" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" +) + +func ClaimEvent(w http.ResponseWriter, r *http.Request) { + did := r.Header.Get("X-User-DID") + + eventID := chi.URLParam(r, "id") + if eventID == "" { + ape.RenderErr(w, problems.BadRequest(nil)...) + return + } + + balance := getBalanceByDID(did, w, r) + if balance == nil { + return + } + + event, err := EventsQ(r). + FilterByID(eventID). + FilterByBalanceID(balance.ID). + FilterByStatus(data.EventFulfilled). + Get() + + if err != nil { + Log(r).WithError(err).Error("Failed to get event by balance ID") + ape.RenderErr(w, problems.InternalError()) + return + } + if event == nil { + Log(r).Debugf("Event not found for id=%s balance_id=%s status=%s", eventID, balance.ID, data.EventFulfilled) + ape.RenderErr(w, problems.NotFound()) + return + } + + if err = EventsQ(r).FilterByID(eventID).UpdateStatus(data.EventClaimed); err != nil { + Log(r).WithError(err).Error("Failed to claim event") + ape.RenderErr(w, problems.InternalError()) + return + } + + w.WriteHeader(http.StatusNoContent) +} diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index b4ed886..3a736f0 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -4,6 +4,7 @@ import ( "context" "net/http" + "github.com/rarimo/points-svc/internal/data" "gitlab.com/distributed_lab/logan/v3" ) @@ -11,6 +12,8 @@ type ctxKey int const ( logCtxKey ctxKey = iota + eventsQCtxKey + balancesQCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -22,3 +25,23 @@ func CtxLog(entry *logan.Entry) func(context.Context) context.Context { func Log(r *http.Request) *logan.Entry { return r.Context().Value(logCtxKey).(*logan.Entry) } + +func CtxEventsQ(q data.EventsQ) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, eventsQCtxKey, q) + } +} + +func EventsQ(r *http.Request) data.EventsQ { + return r.Context().Value(eventsQCtxKey).(data.EventsQ).New() +} + +func CtxBalancesQ(q data.BalancesQ) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, balancesQCtxKey, q) + } +} + +func BalancesQ(r *http.Request) data.BalancesQ { + return r.Context().Value(balancesQCtxKey).(data.BalancesQ).New() +} diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go new file mode 100644 index 0000000..01ca150 --- /dev/null +++ b/internal/service/handlers/get_balance.go @@ -0,0 +1,49 @@ +package handlers + +import ( + "net/http" + + "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/points-svc/resources" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" +) + +func GetBalance(w http.ResponseWriter, r *http.Request) { + did := r.Header.Get("X-User-DID") // TODO: get DID from auth + balance := getBalanceByDID(did, w, r) + if balance == nil { + return + } + + ape.Render(w, resources.BalanceResponse{ + Data: resources.Balance{ + Key: resources.Key{ + ID: balance.ID, + Type: resources.BALANCE, + }, + Attributes: resources.BalanceAttributes{ + Amount: balance.Amount, + UpdatedAt: balance.UpdatedAt, + UserDid: balance.DID, + }, + }, + }) +} + +func getBalanceByDID(did string, w http.ResponseWriter, r *http.Request) *data.Balance { + balance, err := BalancesQ(r).FilterByUserDID(did).Get() + if err != nil { + Log(r).WithError(err).Error("Failed to get balance by DID") + ape.RenderErr(w, problems.InternalError()) + return nil + } + + if balance == nil { + Log(r).Debugf("Balance not found for DID %s", did) + ape.RenderErr(w, problems.NotFound()) + return nil + } + + return balance +} diff --git a/internal/service/handlers/leaderboard.go b/internal/service/handlers/leaderboard.go new file mode 100644 index 0000000..a780780 --- /dev/null +++ b/internal/service/handlers/leaderboard.go @@ -0,0 +1,8 @@ +package handlers + +import ( + "net/http" +) + +func Leaderboard(w http.ResponseWriter, r *http.Request) { +} diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go new file mode 100644 index 0000000..33f0144 --- /dev/null +++ b/internal/service/handlers/list_events.go @@ -0,0 +1,14 @@ +package handlers + +import "net/http" + +func ListEvents(w http.ResponseWriter, r *http.Request) { + did := r.Header.Get("X-User-DID") + + balance := getBalanceByDID(did, w, r) + if balance == nil { + return + } + + //events, err := EventsQ(r).Select() +} diff --git a/internal/service/main.go b/internal/service/main.go index a735706..aed0a15 100644 --- a/internal/service/main.go +++ b/internal/service/main.go @@ -14,6 +14,7 @@ type service struct { log *logan.Entry copus types.Copus listener net.Listener + cfg config.Config } func (s *service) run() error { @@ -32,6 +33,7 @@ func newService(cfg config.Config) *service { log: cfg.Log(), copus: cfg.Copus(), listener: cfg.Listener(), + cfg: cfg, } } diff --git a/internal/service/router.go b/internal/service/router.go index a81530f..34d6145 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -2,7 +2,8 @@ package service import ( "github.com/go-chi/chi" - "github.com/rarimo/rarime-points-svc/internal/service/handlers" + "github.com/rarimo/points-svc/internal/data/pg" + "github.com/rarimo/points-svc/internal/service/handlers" "gitlab.com/distributed_lab/ape" ) @@ -14,10 +15,15 @@ func (s *service) router() chi.Router { ape.LoganMiddleware(s.log), ape.CtxMiddleware( handlers.CtxLog(s.log), + handlers.CtxEventsQ(pg.NewEvents(s.cfg.DB())), + handlers.CtxBalancesQ(pg.NewBalances(s.cfg.DB())), ), ) - r.Route("/integrations/rarime-points-svc", func(r chi.Router) { - // configure endpoints here + r.Route("/integrations/points-svc", func(r chi.Router) { + r.Get("/balance", handlers.GetBalance) + r.Get("/leaderboard", handlers.Leaderboard) + r.Get("/events", handlers.ListEvents) + r.Put("/events/{id}", handlers.ClaimEvent) }) return r diff --git a/resources/model_balance_attributes.go b/resources/model_balance_attributes.go index b535c13..185da96 100644 --- a/resources/model_balance_attributes.go +++ b/resources/model_balance_attributes.go @@ -8,7 +8,7 @@ import "time" type BalanceAttributes struct { // Amount of points - Amount int32 `json:"amount"` + Amount int `json:"amount"` // UTC time (RFC3339) of the last points accruing UpdatedAt time.Time `json:"updated_at"` // DID of the points owner From 088c775a014e1e627c281ae6244d2f3351a38dd8 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 22 Jan 2024 12:49:16 +0200 Subject: [PATCH 08/63] Implement events list handler --- go.mod | 3 +- go.sum | 11 ++++ internal/data/main.go | 8 +++ internal/data/pg/events.go | 5 ++ internal/service/handlers/list_events.go | 69 ++++++++++++++++++++++-- internal/service/page/links.go | 29 ++++++++++ internal/service/page/page_params.go | 29 ++++++++++ internal/service/requests/list_events.go | 28 ++++++++++ 8 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 internal/service/page/links.go create mode 100644 internal/service/page/page_params.go create mode 100644 internal/service/requests/list_events.go diff --git a/go.mod b/go.mod index c26c23c..9150d8a 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,17 @@ module github.com/rarimo/rarime-points-svc go 1.21.3 require ( + github.com/Masterminds/squirrel v1.4.0 github.com/alecthomas/kingpin v2.2.6+incompatible github.com/go-chi/chi v4.1.2+incompatible github.com/rubenv/sql-migrate v1.6.1 gitlab.com/distributed_lab/ape v1.7.1 gitlab.com/distributed_lab/kit v1.11.2 gitlab.com/distributed_lab/logan v3.8.1+incompatible + gitlab.com/distributed_lab/urlval/v4 v4.0.3 ) require ( - github.com/Masterminds/squirrel v1.4.0 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect diff --git a/go.sum b/go.sum index 376e4b1..da93d1b 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -104,6 +105,7 @@ github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -158,6 +160,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rubenv/sql-migrate v1.6.1 h1:bo6/sjsan9HaXAsNxYP/jCEDUGibHp8JmOBw7NTGRos= @@ -187,6 +190,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -206,6 +210,7 @@ github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmv github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +gitlab.com/distributed_lab/ape v1.6.1/go.mod h1:Qy9Y2arL0hmZIpVpctGEFhdrVsjWtyVJ5G+bZWcFT4s= gitlab.com/distributed_lab/ape v1.7.1 h1:LpTmZgG7Lvx6ulopQbH2aWI3s8ey9FsKVjbic3ZQIy4= gitlab.com/distributed_lab/ape v1.7.1/go.mod h1:Qy9Y2arL0hmZIpVpctGEFhdrVsjWtyVJ5G+bZWcFT4s= gitlab.com/distributed_lab/figure v2.1.0+incompatible h1:8kNtvWO91BSQ4OsqL2P3qNWSBnh/Q/TdWB8vHy8xvNI= @@ -213,12 +218,15 @@ gitlab.com/distributed_lab/figure v2.1.0+incompatible/go.mod h1:tk+aPBohT49MGPLy gitlab.com/distributed_lab/kit v1.11.2 h1:3GYAVe/ih5fvFuM/44zIorv9mUyD3JBQe/5v+GL7x+k= gitlab.com/distributed_lab/kit v1.11.2/go.mod h1:MZj5Vb71YBWJ2wLAb9fDvlCYKewmNDNVWjAiERwgbdA= gitlab.com/distributed_lab/logan v3.7.2+incompatible/go.mod h1:25oL/FPFXmyYzWeA6vahMvnFJV8P7mOx0jZhRP7nhlc= +gitlab.com/distributed_lab/logan v3.8.0+incompatible/go.mod h1:25oL/FPFXmyYzWeA6vahMvnFJV8P7mOx0jZhRP7nhlc= gitlab.com/distributed_lab/logan v3.8.1+incompatible h1:bYiP3P0AA0cpAL/fyOYWGq1aiKw16vZFoJz+nwbqdvU= gitlab.com/distributed_lab/logan v3.8.1+incompatible/go.mod h1:25oL/FPFXmyYzWeA6vahMvnFJV8P7mOx0jZhRP7nhlc= gitlab.com/distributed_lab/lorem v0.2.0 h1:Rc7Ef3eGSpei8EtWcV6fzPW3O/QEF2zgZR4+hV8WJAw= gitlab.com/distributed_lab/lorem v0.2.0/go.mod h1:wkzrGoB1L/yUBu56SfoJ/vNiPqiHZcg75AnBkWNcjhQ= gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c h1:cpIjV8C//7sLVvMcBaFGopI8sMcCw8Za7T0HIf52esU= gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c/go.mod h1:4TnADX84dQjQMRHKIMPCVL0L97rD/Jxv0xDbrN6aKzk= +gitlab.com/distributed_lab/urlval/v4 v4.0.3 h1:ZgdSBcvaoHBYmgze/u0bYfvq5Xx47pGTdfFmMYxn27s= +gitlab.com/distributed_lab/urlval/v4 v4.0.3/go.mod h1:IdRM8gOyzpXNoAkIKWVwN+dChh6+1TioS/SVhTGvRFA= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -244,6 +252,7 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -258,8 +267,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= diff --git a/internal/data/main.go b/internal/data/main.go index b556eb2..a00bd8d 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -3,6 +3,8 @@ package data import ( "database/sql" "time" + + "gitlab.com/distributed_lab/kit/pgdb" ) type EventStatus string @@ -13,10 +15,16 @@ const ( EventClaimed EventStatus = "claimed" ) +func (s EventStatus) String() string { + return string(s) +} + type EventsQ interface { New() EventsQ Insert(Event) error UpdateStatus(EventStatus) error + + Page(*pgdb.CursorPageParams) EventsQ Select() ([]Event, error) Get() (*Event, error) diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index ccbcbd4..c617f43 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -55,6 +55,11 @@ func (q *events) UpdateStatus(status data.EventStatus) error { return nil } +func (q *events) Page(page *pgdb.CursorPageParams) data.EventsQ { + q.selector = page.ApplyTo(q.selector, "id") + return q +} + func (q *events) Select() ([]data.Event, error) { var res []data.Event diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index 33f0144..c78d78a 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -1,14 +1,75 @@ package handlers -import "net/http" +import ( + "encoding/json" + "net/http" + + "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/points-svc/internal/service/requests" + "github.com/rarimo/points-svc/resources" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" +) func ListEvents(w http.ResponseWriter, r *http.Request) { - did := r.Header.Get("X-User-DID") + req, err := requests.NewListEvents(r) + if err != nil { + ape.RenderErr(w, problems.BadRequest(err)...) + return + } - balance := getBalanceByDID(did, w, r) + balance := getBalanceByDID(req.DID, w, r) if balance == nil { return } - //events, err := EventsQ(r).Select() + q := EventsQ(r).FilterByBalanceID(balance.ID) + if req.FilterStatus != nil { + q.FilterByStatus(*req.FilterStatus) + } + + events, err := q.Page(&req.CursorPageParams).Select() + if err != nil { + Log(r).WithError(err).Error("Failed to get event list") + ape.RenderErr(w, problems.InternalError()) + return + } + + var last string + if len(events) > 0 { + last = events[len(events)-1].ID + } + + resp := newEventsResponse(events) + resp.Links = req.CursorParams.GetCursorLinks(r, last) + ape.Render(w, resp) +} + +func newEventsResponse(events []data.Event) *resources.EventListResponse { + list := make([]resources.Event, len(events)) + + for i, event := range events { + var dynamic *json.RawMessage + if event.Meta.Valid { + d := json.RawMessage(event.Meta.String) + dynamic = &d + } + + list[i] = resources.Event{ + Key: resources.Key{ + ID: event.ID, + Type: resources.EVENT, + }, + Attributes: resources.EventAttributes{ + CreatedAt: event.CreatedAt, + Meta: resources.EventMeta{ + Static: json.RawMessage{}, // TODO: add from config + Dynamic: dynamic, + }, + Status: event.Status.String(), + }, + } + } + + return &resources.EventListResponse{Data: list} } diff --git a/internal/service/page/links.go b/internal/service/page/links.go new file mode 100644 index 0000000..57e124c --- /dev/null +++ b/internal/service/page/links.go @@ -0,0 +1,29 @@ +package page + +import ( + "net/http" + "strconv" + + "github.com/rarimo/points-svc/resources" +) + +func (p *CursorParams) GetCursorLinks(r *http.Request, last string) *resources.Links { + result := resources.Links{ + Self: p.getCursorLink(r, p.Cursor, p.Order), + } + if last != "" { + lastI, _ := strconv.ParseUint(last, 10, 64) + result.Next = p.getCursorLink(r, lastI, p.Order) + } + return &result +} + +func (p *CursorParams) getCursorLink(r *http.Request, cursor uint64, order string) string { + u := r.URL + query := u.Query() + query.Set(pageParamCursor, strconv.FormatUint(cursor, 10)) + query.Set(pageParamLimit, strconv.FormatUint(p.Limit, 10)) + query.Set(pageParamOrder, order) + u.RawQuery = query.Encode() + return u.String() +} diff --git a/internal/service/page/page_params.go b/internal/service/page/page_params.go new file mode 100644 index 0000000..588cbb4 --- /dev/null +++ b/internal/service/page/page_params.go @@ -0,0 +1,29 @@ +package page + +import ( + "math" + + val "github.com/go-ozzo/ozzo-validation/v4" + "gitlab.com/distributed_lab/kit/pgdb" +) + +const ( + pageParamLimit = "page[limit]" + pageParamCursor = "page[cursor]" + pageParamOrder = "page[order]" + + maxLimit uint64 = 100 +) + +// CursorParams is a wrapper around pgdb.CursorPageParams with useful validation and rendering methods +type CursorParams struct { + pgdb.CursorPageParams +} + +func (p *CursorParams) Validate() error { + return val.Errors{ + pageParamLimit: val.Validate(p.Limit, val.Max(maxLimit)), + pageParamOrder: val.Validate(p.Order, val.In(pgdb.OrderTypeAsc, pgdb.OrderTypeDesc)), + pageParamCursor: val.Validate(p.Cursor, val.Max(uint64(math.MaxInt32))), + }.Filter() +} diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go new file mode 100644 index 0000000..2efe1eb --- /dev/null +++ b/internal/service/requests/list_events.go @@ -0,0 +1,28 @@ +package requests + +import ( + "fmt" + "net/http" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/points-svc/internal/service/page" + "gitlab.com/distributed_lab/urlval/v4" +) + +type ListEvents struct { + page.CursorParams + DID string + FilterStatus *data.EventStatus `filter:"status"` +} + +func NewListEvents(r *http.Request) (req ListEvents, err error) { + if err = urlval.Decode(r.URL.Query(), &req); err != nil { + return req, validation.Errors{ + "query": fmt.Errorf("failed to decode query: %w", err), + } + } + + req.DID = r.Header.Get("X-User-DID") + return +} From 590334423681de3aec13e4cec03a8d6dcad0946b Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 22 Jan 2024 13:04:31 +0200 Subject: [PATCH 09/63] Drop sorting leaderboard by number of events until this is necessary --- .../paths/integrations@points-svc@leaderboard.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/docs/spec/paths/integrations@points-svc@leaderboard.yaml b/docs/spec/paths/integrations@points-svc@leaderboard.yaml index 9e67e65..55c36e3 100644 --- a/docs/spec/paths/integrations@points-svc@leaderboard.yaml +++ b/docs/spec/paths/integrations@points-svc@leaderboard.yaml @@ -14,16 +14,6 @@ get: minimum: 3 maximum: 50 default: 10 - - in: query - name: 'page[order_by]' - description: | - First field to sort by. If you specify `events`, then the leaderboard - will be sorted by number of claimed events and then by points. - required: false - schema: - type: string - enum: [points, events] - default: points responses: 200: description: Success From 79f7859e8662162b8f9f06214e6fc07a72e1f16e Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 22 Jan 2024 14:17:28 +0200 Subject: [PATCH 10/63] Add leaderboard endpoint handler --- internal/data/main.go | 2 ++ internal/data/pg/balances.go | 15 +++++++++ internal/service/handlers/leaderboard.go | 40 ++++++++++++++++++++++++ internal/service/requests/leaderboard.go | 31 ++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 internal/service/requests/leaderboard.go diff --git a/internal/data/main.go b/internal/data/main.go index a00bd8d..7de3197 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -37,6 +37,8 @@ type BalancesQ interface { New() BalancesQ Insert(Balance) error UpdateAmount(int) error + + SelectLeaders(count int) ([]Balance, error) Get() (*Balance, error) FilterByID(string) BalancesQ diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index 0a69dd6..1d8a179 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -54,6 +54,21 @@ func (q *balances) UpdateAmount(amount int) error { return nil } +func (q *balances) SelectLeaders(count int) ([]data.Balance, error) { + var res []data.Balance + + stmt := squirrel.Select("*"). + From(balancesTable). + OrderBy("amount DESC, updated_at ASC"). + Limit(uint64(count)) + + if err := q.db.Select(&res, stmt); err != nil { + return nil, fmt.Errorf("select leaders: %w", err) + } + + return res, nil +} + func (q *balances) Get() (*data.Balance, error) { var res data.Balance diff --git a/internal/service/handlers/leaderboard.go b/internal/service/handlers/leaderboard.go index a780780..90fd892 100644 --- a/internal/service/handlers/leaderboard.go +++ b/internal/service/handlers/leaderboard.go @@ -2,7 +2,47 @@ package handlers import ( "net/http" + + "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/points-svc/internal/service/requests" + "github.com/rarimo/points-svc/resources" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" ) func Leaderboard(w http.ResponseWriter, r *http.Request) { + req, err := requests.NewLeaderboard(r) + if err != nil { + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + + leaders, err := BalancesQ(r).SelectLeaders(req.Limit) + if err != nil { + Log(r).WithError(err).Error("Failed to get balance leaders") + ape.RenderErr(w, problems.InternalError()) + return + } + + ape.Render(w, newLeaderboardResponse(leaders)) +} + +func newLeaderboardResponse(balances []data.Balance) resources.BalanceListResponse { + list := make([]resources.Balance, len(balances)) + for i, balance := range balances { + + list[i] = resources.Balance{ + Key: resources.Key{ + ID: balance.ID, + Type: resources.BALANCE, + }, + Attributes: resources.BalanceAttributes{ + Amount: balance.Amount, + UpdatedAt: balance.UpdatedAt, + UserDid: balance.DID, + }, + } + } + + return resources.BalanceListResponse{Data: list} } diff --git a/internal/service/requests/leaderboard.go b/internal/service/requests/leaderboard.go new file mode 100644 index 0000000..9cf0595 --- /dev/null +++ b/internal/service/requests/leaderboard.go @@ -0,0 +1,31 @@ +package requests + +import ( + "fmt" + "net/http" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "gitlab.com/distributed_lab/urlval/v4" +) + +type Leaderboard struct { + Limit int `page:"limit"` +} + +func NewLeaderboard(r *http.Request) (req Leaderboard, err error) { + if err = urlval.Decode(r.URL.Query(), &req); err != nil { + return req, validation.Errors{ + "page[limit]": fmt.Errorf("failed to decode query: %v", err), + } + } + + if req.Limit == 0 { + req.Limit = 10 + } + + err = validation.Errors{ + "page[limit]": validation.Validate(req.Limit, validation.Min(3), validation.Max(50)), + }.Filter() + + return +} From 7132cbb11ad361b0b9373c359dfb1c1c9af92cae Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 22 Jan 2024 14:51:28 +0200 Subject: [PATCH 11/63] Get user rank among all balances --- docs/spec/components/schemas/Balance.yaml | 5 +++ .../integrations@points-svc@balance.yaml | 2 +- internal/data/main.go | 2 + internal/data/pg/balances.go | 5 +++ internal/service/handlers/claim_event.go | 2 +- internal/service/handlers/get_balance.go | 38 +++++++++++-------- internal/service/handlers/leaderboard.go | 13 +------ internal/service/handlers/list_events.go | 2 +- resources/model_balance_attributes.go | 2 + 9 files changed, 41 insertions(+), 30 deletions(-) diff --git a/docs/spec/components/schemas/Balance.yaml b/docs/spec/components/schemas/Balance.yaml index c61c5be..02728b8 100644 --- a/docs/spec/components/schemas/Balance.yaml +++ b/docs/spec/components/schemas/Balance.yaml @@ -25,3 +25,8 @@ allOf: format: time.Time description: UTC time (RFC3339) of the last points accruing example: "2021-08-12T13:00:00Z" + rank: + type: integer + format: int + description: Rank of the user in the full leaderboard. Returned only for the single user. + example: 294 diff --git a/docs/spec/paths/integrations@points-svc@balance.yaml b/docs/spec/paths/integrations@points-svc@balance.yaml index e1d5f83..8a32634 100644 --- a/docs/spec/paths/integrations@points-svc@balance.yaml +++ b/docs/spec/paths/integrations@points-svc@balance.yaml @@ -2,7 +2,7 @@ get: tags: - Points balance summary: Get points balance for user - description: Balance of authorized user who makes the request + description: Balance of authorized user who makes the request. Rank in leaderboard is included. operationId: getPointsBalance responses: 200: diff --git a/internal/data/main.go b/internal/data/main.go index 7de3197..ac96b28 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -40,6 +40,7 @@ type BalancesQ interface { SelectLeaders(count int) ([]Balance, error) Get() (*Balance, error) + WithRank() BalancesQ FilterByID(string) BalancesQ FilterByUserDID(string) BalancesQ @@ -59,4 +60,5 @@ type Balance struct { DID string `db:"did"` Amount int `db:"amount"` UpdatedAt time.Time `db:"updated_at"` + Rank *int `db:"rank"` } diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index 1d8a179..9fde24a 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -82,6 +82,11 @@ func (q *balances) Get() (*data.Balance, error) { return &res, nil } +func (q *balances) WithRank() data.BalancesQ { + q.selector = q.selector.Column("RANK() OVER (ORDER BY amount DESC, updated_at ASC) AS rank") + return q +} + func (q *balances) FilterByID(id string) data.BalancesQ { q.selector = q.selector.Where(squirrel.Eq{"id": id}) q.updater = q.updater.Where(squirrel.Eq{"id": id}) diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index 66c47e0..0acdf25 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -18,7 +18,7 @@ func ClaimEvent(w http.ResponseWriter, r *http.Request) { return } - balance := getBalanceByDID(did, w, r) + balance := getBalanceByDID(did, false, w, r) if balance == nil { return } diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go index 01ca150..08b4f5b 100644 --- a/internal/service/handlers/get_balance.go +++ b/internal/service/handlers/get_balance.go @@ -11,28 +11,36 @@ import ( func GetBalance(w http.ResponseWriter, r *http.Request) { did := r.Header.Get("X-User-DID") // TODO: get DID from auth - balance := getBalanceByDID(did, w, r) + balance := getBalanceByDID(did, true, w, r) if balance == nil { return } - ape.Render(w, resources.BalanceResponse{ - Data: resources.Balance{ - Key: resources.Key{ - ID: balance.ID, - Type: resources.BALANCE, - }, - Attributes: resources.BalanceAttributes{ - Amount: balance.Amount, - UpdatedAt: balance.UpdatedAt, - UserDid: balance.DID, - }, + ape.Render(w, newBalanceModel(*balance)) +} + +func newBalanceModel(balance data.Balance) resources.Balance { + return resources.Balance{ + Key: resources.Key{ + ID: balance.ID, + Type: resources.BALANCE, + }, + Attributes: resources.BalanceAttributes{ + Amount: balance.Amount, + UpdatedAt: balance.UpdatedAt, + UserDid: balance.DID, + Rank: balance.Rank, }, - }) + } } -func getBalanceByDID(did string, w http.ResponseWriter, r *http.Request) *data.Balance { - balance, err := BalancesQ(r).FilterByUserDID(did).Get() +func getBalanceByDID(did string, withRank bool, w http.ResponseWriter, r *http.Request) *data.Balance { + q := BalancesQ(r).FilterByUserDID(did) + if withRank { + q.WithRank() + } + + balance, err := q.Get() if err != nil { Log(r).WithError(err).Error("Failed to get balance by DID") ape.RenderErr(w, problems.InternalError()) diff --git a/internal/service/handlers/leaderboard.go b/internal/service/handlers/leaderboard.go index 90fd892..9dbc2cf 100644 --- a/internal/service/handlers/leaderboard.go +++ b/internal/service/handlers/leaderboard.go @@ -30,18 +30,7 @@ func Leaderboard(w http.ResponseWriter, r *http.Request) { func newLeaderboardResponse(balances []data.Balance) resources.BalanceListResponse { list := make([]resources.Balance, len(balances)) for i, balance := range balances { - - list[i] = resources.Balance{ - Key: resources.Key{ - ID: balance.ID, - Type: resources.BALANCE, - }, - Attributes: resources.BalanceAttributes{ - Amount: balance.Amount, - UpdatedAt: balance.UpdatedAt, - UserDid: balance.DID, - }, - } + list[i] = newBalanceModel(balance) } return resources.BalanceListResponse{Data: list} diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index c78d78a..cf16fb2 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -18,7 +18,7 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { return } - balance := getBalanceByDID(req.DID, w, r) + balance := getBalanceByDID(req.DID, false, w, r) if balance == nil { return } diff --git a/resources/model_balance_attributes.go b/resources/model_balance_attributes.go index 185da96..8e8c319 100644 --- a/resources/model_balance_attributes.go +++ b/resources/model_balance_attributes.go @@ -9,6 +9,8 @@ import "time" type BalanceAttributes struct { // Amount of points Amount int `json:"amount"` + // Rank of the user in the full leaderboard. Returned only for the single user. + Rank *int `json:"rank,omitempty"` // UTC time (RFC3339) of the last points accruing UpdatedAt time.Time `json:"updated_at"` // DID of the points owner From 9c52056734d2498e4c1347ff4d3274dbd80511d5 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 22 Jan 2024 15:52:10 +0200 Subject: [PATCH 12/63] Save received points amount when event is claimed --- docs/spec/components/schemas/Event.yaml | 7 +++++ internal/assets/migrations/001_initial.sql | 13 +++++---- internal/data/main.go | 15 +++++----- internal/data/pg/events.go | 34 +++++++++++----------- internal/service/handlers/claim_event.go | 7 ++++- internal/service/handlers/list_events.go | 8 ++++- resources/model_event_attributes.go | 2 ++ 7 files changed, 54 insertions(+), 32 deletions(-) diff --git a/docs/spec/components/schemas/Event.yaml b/docs/spec/components/schemas/Event.yaml index 20f4f73..5433c42 100644 --- a/docs/spec/components/schemas/Event.yaml +++ b/docs/spec/components/schemas/Event.yaml @@ -22,3 +22,10 @@ allOf: example: "2021-08-12T13:00:00Z" meta: $ref: '#/components/schemas/EventMeta' + points_amount: + type: integer + description: | + How many points were accrued. Required only for `claimed` events. + This is necessary, as the reward might change over time, while + the certain balance should be left intact. + example: 50 diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 9dd6988..79a8912 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -23,12 +23,13 @@ CREATE TYPE event_status AS ENUM ('open', 'fulfilled', 'claimed'); CREATE TABLE IF NOT EXISTS events ( - id serial PRIMARY KEY, - type_id smallint not null, - balance_id integer null REFERENCES balances (id), - status event_status not null, - created_at timestamp without time zone not null default NOW(), - meta text + id serial PRIMARY KEY, + type_id smallint not null, + balance_id integer null REFERENCES balances (id), + status event_status not null, + created_at timestamp without time zone not null default NOW(), + meta text, + points_amount integer ); -- +migrate Down diff --git a/internal/data/main.go b/internal/data/main.go index ac96b28..54409fc 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -22,7 +22,7 @@ func (s EventStatus) String() string { type EventsQ interface { New() EventsQ Insert(Event) error - UpdateStatus(EventStatus) error + Update(Event) error Page(*pgdb.CursorPageParams) EventsQ Select() ([]Event, error) @@ -47,12 +47,13 @@ type BalancesQ interface { } type Event struct { - ID string `db:"id"` - TypeID string `db:"type_id"` - BalanceID string `db:"balance_id"` - Status EventStatus `db:"status"` - CreatedAt time.Time `db:"created_at"` - Meta sql.NullString `db:"meta"` + ID string `db:"id"` + TypeID string `db:"type_id"` + BalanceID string `db:"balance_id"` + Status EventStatus `db:"status"` + CreatedAt time.Time `db:"created_at"` + Meta sql.NullString `db:"meta"` + PointsAmount sql.NullInt32 `db:"points_amount"` } type Balance struct { diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index c617f43..5ee6f8b 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -13,14 +13,12 @@ const eventsTable = "events" type events struct { db *pgdb.DB selector squirrel.SelectBuilder - updater squirrel.UpdateBuilder } func NewEvents(db *pgdb.DB) data.EventsQ { return &events{ db: db, selector: squirrel.Select("*").From(eventsTable), - updater: squirrel.Update(eventsTable), } } @@ -29,27 +27,32 @@ func (q *events) New() data.EventsQ { } func (q *events) Insert(event data.Event) error { - stmt := squirrel.Insert(eventsTable).SetMap(map[string]interface{}{ - "id": event.ID, - "type_id": event.TypeID, - "balance_id": event.BalanceID, - "status": event.Status, - "created_at": event.CreatedAt, - "meta": event.Meta, - }) + imap := map[string]any{ // ID must be created sequentially + "type_id": event.TypeID, + "balance_id": event.BalanceID, + "status": event.Status, + "created_at": event.CreatedAt, + "meta": event.Meta, + "points_amount": event.PointsAmount, + } - if err := q.db.Exec(stmt); err != nil { + if err := q.db.Exec(squirrel.Insert(eventsTable).SetMap(imap)); err != nil { return fmt.Errorf("insert event %+v: %w", event, err) } return nil } -func (q *events) UpdateStatus(status data.EventStatus) error { - stmt := q.updater.Set("status", status) +func (q *events) Update(event data.Event) error { + umap := map[string]any{ + "status": event.Status, + "meta": event.Meta, + "points_amount": event.PointsAmount, + } + stmt := squirrel.Update(eventsTable).SetMap(umap).Where(squirrel.Eq{"id": event.ID}) if err := q.db.Exec(stmt); err != nil { - return fmt.Errorf("update event status to %s: %w", status, err) + return fmt.Errorf("update event with map %+v: %w", umap, err) } return nil @@ -82,18 +85,15 @@ func (q *events) Get() (*data.Event, error) { func (q *events) FilterByID(id string) data.EventsQ { q.selector = q.selector.Where(squirrel.Eq{"id": id}) - q.updater = q.updater.Where(squirrel.Eq{"id": id}) return q } func (q *events) FilterByBalanceID(ids ...string) data.EventsQ { q.selector = q.selector.Where(squirrel.Eq{"balance_id": ids}) - q.updater = q.updater.Where(squirrel.Eq{"balance_id": ids}) return q } func (q *events) FilterByStatus(statuses ...data.EventStatus) data.EventsQ { q.selector = q.selector.Where(squirrel.Eq{"status": statuses}) - q.updater = q.updater.Where(squirrel.Eq{"status": statuses}) return q } diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index 0acdf25..e408d1c 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -40,7 +40,12 @@ func ClaimEvent(w http.ResponseWriter, r *http.Request) { return } - if err = EventsQ(r).FilterByID(eventID).UpdateStatus(data.EventClaimed); err != nil { + err = EventsQ(r).Update(data.Event{ + ID: event.ID, + Status: data.EventClaimed, + // TODO: add points amount from config, accrue points + }) + if err != nil { Log(r).WithError(err).Error("Failed to claim event") ape.RenderErr(w, problems.InternalError()) return diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index cf16fb2..face7ae 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -55,6 +55,11 @@ func newEventsResponse(events []data.Event) *resources.EventListResponse { dynamic = &d } + var points *int32 + if event.PointsAmount.Valid { + points = &event.PointsAmount.Int32 + } + list[i] = resources.Event{ Key: resources.Key{ ID: event.ID, @@ -66,7 +71,8 @@ func newEventsResponse(events []data.Event) *resources.EventListResponse { Static: json.RawMessage{}, // TODO: add from config Dynamic: dynamic, }, - Status: event.Status.String(), + Status: event.Status.String(), + PointsAmount: points, }, } } diff --git a/resources/model_event_attributes.go b/resources/model_event_attributes.go index cf3cd40..7d852d0 100644 --- a/resources/model_event_attributes.go +++ b/resources/model_event_attributes.go @@ -10,6 +10,8 @@ type EventAttributes struct { // UTC time (RFC3339) of event creation CreatedAt time.Time `json:"created_at"` Meta EventMeta `json:"meta"` + // How many points were accrued. Required only for `claimed` events. This is necessary, as the reward might change over time, while the certain balance should be left intact. + PointsAmount *int32 `json:"points_amount,omitempty"` // See `filter[status]` parameter for explanation Status string `json:"status"` } From 39655875be242f75086afe8e31aa16d4b86db27f Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 11:23:04 +0200 Subject: [PATCH 13/63] Add config for event types --- config.yaml | 17 ++- docs/spec/components/schemas/EventMeta.yaml | 13 +- .../components/schemas/EventStaticMeta.yaml | 29 +++++ go.mod | 23 +++- go.sum | 115 +++++++++++++++++- internal/config/main.go | 15 ++- internal/data/evtypes/config.go | 59 +++++++++ internal/data/evtypes/main.go | 25 ++++ internal/service/handlers/list_events.go | 2 +- resources/model_event_meta.go | 3 +- resources/model_event_static_meta.go | 19 +++ 11 files changed, 288 insertions(+), 32 deletions(-) create mode 100644 docs/spec/components/schemas/EventStaticMeta.yaml create mode 100644 internal/data/evtypes/config.go create mode 100644 internal/data/evtypes/main.go create mode 100644 resources/model_event_static_meta.go diff --git a/config.yaml b/config.yaml index ec3ea6f..d4c5f96 100644 --- a/config.yaml +++ b/config.yaml @@ -3,7 +3,7 @@ log: disable_sentry: true db: - url: db_url + url: postgres://points:points@localhost:5432/points?sslmode=disable listener: addr: :8000 @@ -14,3 +14,18 @@ cop: upstream: "http://..." service_name: rarime-points-svc service_port: 80 + +event_types: + types: + - id: 1 + name: get_poh + title: Get PoH credential + reward: 50 + description: Lorem ipsum dolor sit amet + expires_at: 2020-01-01T00:00:00Z + - id: 2 + name: daily_login + title: Daily login + reward: 5 + description: Lorem ipsum dolor sit amet + expires_at: 2020-01-01T00:00:00Z diff --git a/docs/spec/components/schemas/EventMeta.yaml b/docs/spec/components/schemas/EventMeta.yaml index ec181e4..0d92ecf 100644 --- a/docs/spec/components/schemas/EventMeta.yaml +++ b/docs/spec/components/schemas/EventMeta.yaml @@ -3,18 +3,7 @@ required: - static properties: static: - type: string - format: json.RawMessage - description: | - Primary event metadata in plain JSON. This is a template - to be filled by `dynamic` when it's present. - example: - { - "title": "Verify proof {:id}", - "description": "Your proof should be verified by somebody", - "type": "unlimited", - "reward": 5 - } + $ref: '#/components/schemas/EventStaticMeta' dynamic: type: string format: json.RawMessage diff --git a/docs/spec/components/schemas/EventStaticMeta.yaml b/docs/spec/components/schemas/EventStaticMeta.yaml new file mode 100644 index 0000000..c25cbf5 --- /dev/null +++ b/docs/spec/components/schemas/EventStaticMeta.yaml @@ -0,0 +1,29 @@ +type: object +description: | + Primary event metadata in plain JSON. This is a template + to be filled by `dynamic` when it's present. +required: + - name + - reward + - title + - description +properties: + name: + type: string + description: Unique event code name + example: get_poh + reward: + type: integer + description: Reward amount in points + example: 50 + expires_at: + type: string + format: time.Time + description: General event expiration date + example: 2020-01-01T00:00:00Z + title: + type: string + example: Get PoH credential + description: + type: string + example: Lorem ipsum dolor sit amet diff --git a/go.mod b/go.mod index 9150d8a..dde5b2a 100644 --- a/go.mod +++ b/go.mod @@ -6,44 +6,57 @@ require ( github.com/Masterminds/squirrel v1.4.0 github.com/alecthomas/kingpin v2.2.6+incompatible github.com/go-chi/chi v4.1.2+incompatible + github.com/go-ozzo/ozzo-validation/v4 v4.2.1 github.com/rubenv/sql-migrate v1.6.1 gitlab.com/distributed_lab/ape v1.7.1 + gitlab.com/distributed_lab/figure/v3 v3.1.3 gitlab.com/distributed_lab/kit v1.11.2 gitlab.com/distributed_lab/logan v3.8.1+incompatible gitlab.com/distributed_lab/urlval/v4 v4.0.3 ) require ( + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/go-ethereum v1.10.25 // indirect github.com/fsnotify/fsnotify v1.4.7 // indirect github.com/getsentry/raven-go v0.2.0 // indirect github.com/getsentry/sentry-go v0.7.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect - github.com/go-ozzo/ozzo-validation/v4 v4.2.1 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-stack/stack v1.8.0 // indirect github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/magiconair/properties v1.8.0 // indirect - github.com/mitchellh/mapstructure v1.1.2 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/sirupsen/logrus v1.6.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/afero v1.1.2 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.0.0 // indirect github.com/spf13/pflag v1.0.3 // indirect github.com/spf13/viper v1.3.2 // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect gitlab.com/distributed_lab/figure v2.1.0+incompatible // indirect gitlab.com/distributed_lab/lorem v0.2.0 // indirect gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/sys v0.15.0 // indirect - golang.org/x/text v0.3.3 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index da93d1b..e5faa3b 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,10 @@ github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4K github.com/Masterminds/squirrel v1.4.0 h1:he5i/EXixZxrBUWcxzDYMiju9WZ3ld/l7QBNuo/eN3w= github.com/Masterminds/squirrel v1.4.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= @@ -19,31 +23,54 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.10.25 h1:5dFrKJDnYf8L6/5o42abCE6a9yJm9cs4EJVRyYMr55s= +github.com/ethereum/go-ethereum v1.10.25/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/sentry-go v0.7.0 h1:MR2yfR4vFfv/2+iBuSnkdQwVg7N9cJzihZ6KJu7srwQ= @@ -58,16 +85,24 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ozzo/ozzo-validation/v4 v4.2.1 h1:XALUNshPYumA7UShB7iM3ZVlqIBn0jfwjqAMIoyE1N0= github.com/go-ozzo/ozzo-validation/v4 v4.2.1/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= @@ -75,18 +110,34 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 h1:aQ4kMXDAmP9IRIZHcSKB2orXHGwGiSxH4PX1BzKHR50= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -102,7 +153,6 @@ github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiD github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -125,9 +175,15 @@ github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= @@ -136,8 +192,11 @@ github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go. github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= @@ -146,6 +205,8 @@ github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -160,17 +221,29 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rubenv/sql-migrate v1.6.1 h1:bo6/sjsan9HaXAsNxYP/jCEDUGibHp8JmOBw7NTGRos= github.com/rubenv/sql-migrate v1.6.1/go.mod h1:tPzespupJS0jacLfhbwto/UjSX+8h2FdWB7ar+QlHa0= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= @@ -185,18 +258,31 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -206,6 +292,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -215,6 +303,8 @@ gitlab.com/distributed_lab/ape v1.7.1 h1:LpTmZgG7Lvx6ulopQbH2aWI3s8ey9FsKVjbic3Z gitlab.com/distributed_lab/ape v1.7.1/go.mod h1:Qy9Y2arL0hmZIpVpctGEFhdrVsjWtyVJ5G+bZWcFT4s= gitlab.com/distributed_lab/figure v2.1.0+incompatible h1:8kNtvWO91BSQ4OsqL2P3qNWSBnh/Q/TdWB8vHy8xvNI= gitlab.com/distributed_lab/figure v2.1.0+incompatible/go.mod h1:tk+aPBohT49MGPLy5+eVbE1HpD/CaC5drBHfVpRI8eE= +gitlab.com/distributed_lab/figure/v3 v3.1.3 h1:gCHplT1Ih8B1s4eYTeAhRZyto3gIWoUCUj3yYfNM4r8= +gitlab.com/distributed_lab/figure/v3 v3.1.3/go.mod h1:gYbCEdQBQCVEg+ap0zrpjY56BU95k9H8ELebL1ChONo= gitlab.com/distributed_lab/kit v1.11.2 h1:3GYAVe/ih5fvFuM/44zIorv9mUyD3JBQe/5v+GL7x+k= gitlab.com/distributed_lab/kit v1.11.2/go.mod h1:MZj5Vb71YBWJ2wLAb9fDvlCYKewmNDNVWjAiERwgbdA= gitlab.com/distributed_lab/logan v3.7.2+incompatible/go.mod h1:25oL/FPFXmyYzWeA6vahMvnFJV8P7mOx0jZhRP7nhlc= @@ -230,6 +320,8 @@ gitlab.com/distributed_lab/urlval/v4 v4.0.3/go.mod h1:IdRM8gOyzpXNoAkIKWVwN+dChh golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -239,9 +331,12 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -252,19 +347,25 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -275,6 +376,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/config/main.go b/internal/config/main.go index 96d1daa..71432df 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -1,6 +1,7 @@ package config import ( + "github.com/rarimo/points-svc/internal/data/evtypes" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/copus" "gitlab.com/distributed_lab/kit/copus/types" @@ -13,6 +14,7 @@ type Config interface { pgdb.Databaser types.Copuser comfig.Listenerer + evtypes.EventTypeser } type config struct { @@ -20,15 +22,18 @@ type config struct { pgdb.Databaser types.Copuser comfig.Listenerer + evtypes.EventTypeser + getter kv.Getter } func New(getter kv.Getter) Config { return &config{ - getter: getter, - Databaser: pgdb.NewDatabaser(getter), - Copuser: copus.NewCopuser(getter), - Listenerer: comfig.NewListenerer(getter), - Logger: comfig.NewLogger(getter, comfig.LoggerOpts{}), + getter: getter, + EventTypeser: evtypes.NewConfig(getter), + Databaser: pgdb.NewDatabaser(getter), + Copuser: copus.NewCopuser(getter), + Listenerer: comfig.NewListenerer(getter), + Logger: comfig.NewLogger(getter, comfig.LoggerOpts{}), } } diff --git a/internal/data/evtypes/config.go b/internal/data/evtypes/config.go new file mode 100644 index 0000000..9665591 --- /dev/null +++ b/internal/data/evtypes/config.go @@ -0,0 +1,59 @@ +package evtypes + +import ( + "fmt" + "time" + + "github.com/rarimo/points-svc/resources" + "gitlab.com/distributed_lab/figure/v3" + "gitlab.com/distributed_lab/kit/comfig" + "gitlab.com/distributed_lab/kit/kv" +) + +type EventTypeser interface { + EventTypes() Types +} + +type config struct { + once comfig.Once + getter kv.Getter +} + +func NewConfig(getter kv.Getter) EventTypeser { + return &config{getter: getter} +} + +func (c *config) EventTypes() Types { + return c.once.Do(func() interface{} { + var raw struct { + Types []struct { + ID int32 `fig:"id,required"` + Name string `fig:"name,required"` + Description string `fig:"description,required"` + Reward int32 `fig:"reward,required"` + Title string `fig:"title,required"` + ExpiresAt *time.Time `fig:"expires_at"` + } `fig:"types,required"` + } + + err := figure.Out(&raw). + From(kv.MustGetStringMap(c.getter, "event_types")). + Please() + if err != nil { + panic(fmt.Errorf("failed to figure out event_types: %s", err)) + } + + inner := make([]resources.EventStaticMeta, len(raw.Types)) + for _, t := range raw.Types { + inner[t.ID-1] = resources.EventStaticMeta{ + Name: t.Name, + Description: t.Description, + Reward: t.Reward, + Title: t.Title, + ExpiresAt: t.ExpiresAt, + } + } + + return Types{inner} + }).(Types) +} diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go new file mode 100644 index 0000000..4b4481d --- /dev/null +++ b/internal/data/evtypes/main.go @@ -0,0 +1,25 @@ +package evtypes + +import ( + "errors" + + "github.com/rarimo/points-svc/resources" +) + +var ErrInvalidID = errors.New("wrong event type id") + +type Types struct { + inner []resources.EventStaticMeta +} + +func (t *Types) Get(id int) (resources.EventStaticMeta, error) { + if t.inner == nil { + panic("event types are not correctly initialized") + } + + if id <= 0 || id > len(t.inner) { + return resources.EventStaticMeta{}, ErrInvalidID + } + + return t.inner[id-1], nil +} diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index face7ae..1817f22 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -68,7 +68,7 @@ func newEventsResponse(events []data.Event) *resources.EventListResponse { Attributes: resources.EventAttributes{ CreatedAt: event.CreatedAt, Meta: resources.EventMeta{ - Static: json.RawMessage{}, // TODO: add from config + //Static: json.RawMessage{}, // TODO: add from config Dynamic: dynamic, }, Status: event.Status.String(), diff --git a/resources/model_event_meta.go b/resources/model_event_meta.go index 541c1ce..a475a1f 100644 --- a/resources/model_event_meta.go +++ b/resources/model_event_meta.go @@ -9,6 +9,5 @@ import "encoding/json" type EventMeta struct { // Some events require dynamic data, which can be filled into `static` template. Dynamic *json.RawMessage `json:"dynamic,omitempty"` - // Primary event metadata in plain JSON. This is a template to be filled by `dynamic` when it's present. - Static json.RawMessage `json:"static"` + Static EventStaticMeta `json:"static"` } diff --git a/resources/model_event_static_meta.go b/resources/model_event_static_meta.go new file mode 100644 index 0000000..4ce9529 --- /dev/null +++ b/resources/model_event_static_meta.go @@ -0,0 +1,19 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "time" + +// Primary event metadata in plain JSON. This is a template to be filled by `dynamic` when it's present. +type EventStaticMeta struct { + Description string `json:"description"` + // General event expiration date + ExpiresAt *time.Time `json:"expires_at,omitempty"` + // Unique event code name + Name string `json:"name"` + // Reward amount in points + Reward int32 `json:"reward"` + Title string `json:"title"` +} From 604ceafd85c32643dd94a05570391d733a7df9c1 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 12:31:39 +0200 Subject: [PATCH 14/63] Simplify config by dropping ID, use in handlers, drop triggers from DB --- config.yaml | 7 ++----- internal/assets/migrations/001_initial.sql | 16 +--------------- internal/data/evtypes/config.go | 5 ++--- internal/data/evtypes/main.go | 15 ++++++--------- internal/data/main.go | 2 +- internal/data/pg/balances.go | 5 ++++- internal/data/pg/events.go | 4 +++- internal/service/handlers/claim_event.go | 20 +++++++++++++++++++- internal/service/handlers/ctx.go | 12 ++++++++++++ internal/service/handlers/list_events.go | 17 ++++++++++++++--- internal/service/router.go | 1 + 11 files changed, 65 insertions(+), 39 deletions(-) diff --git a/config.yaml b/config.yaml index d4c5f96..063e296 100644 --- a/config.yaml +++ b/config.yaml @@ -17,15 +17,12 @@ cop: event_types: types: - - id: 1 - name: get_poh + - name: get_poh title: Get PoH credential reward: 50 description: Lorem ipsum dolor sit amet expires_at: 2020-01-01T00:00:00Z - - id: 2 - name: daily_login + - name: daily_login title: Daily login reward: 5 description: Lorem ipsum dolor sit amet - expires_at: 2020-01-01T00:00:00Z diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 79a8912..d29d4f9 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -1,10 +1,4 @@ -- +migrate Up -DROP FUNCTION IF EXISTS trigger_set_updated_at cascade; - -CREATE FUNCTION trigger_set_updated_at() RETURNS TRIGGER - LANGUAGE plpgsql -AS $$ BEGIN NEW.updated_at = NOW() at time zone 'utc'; RETURN NEW; END; $$; - CREATE TABLE IF NOT EXISTS balances ( id serial PRIMARY KEY, @@ -13,19 +7,13 @@ CREATE TABLE IF NOT EXISTS balances updated_at timestamp without time zone not null default NOW() ); -CREATE TRIGGER set_updated_at - before update - on balances - for each row -EXECUTE FUNCTION trigger_set_updated_at(); - CREATE TYPE event_status AS ENUM ('open', 'fulfilled', 'claimed'); CREATE TABLE IF NOT EXISTS events ( id serial PRIMARY KEY, - type_id smallint not null, balance_id integer null REFERENCES balances (id), + type text not null, status event_status not null, created_at timestamp without time zone not null default NOW(), meta text, @@ -35,6 +23,4 @@ CREATE TABLE IF NOT EXISTS events -- +migrate Down DROP TABLE IF EXISTS events; DROP TYPE IF EXISTS event_status; -DROP TRIGGER IF EXISTS set_updated_at on balances; DROP TABLE IF EXISTS balances; -DROP FUNCTION IF EXISTS trigger_set_updated_at cascade; diff --git a/internal/data/evtypes/config.go b/internal/data/evtypes/config.go index 9665591..9f90b63 100644 --- a/internal/data/evtypes/config.go +++ b/internal/data/evtypes/config.go @@ -27,7 +27,6 @@ func (c *config) EventTypes() Types { return c.once.Do(func() interface{} { var raw struct { Types []struct { - ID int32 `fig:"id,required"` Name string `fig:"name,required"` Description string `fig:"description,required"` Reward int32 `fig:"reward,required"` @@ -43,9 +42,9 @@ func (c *config) EventTypes() Types { panic(fmt.Errorf("failed to figure out event_types: %s", err)) } - inner := make([]resources.EventStaticMeta, len(raw.Types)) + inner := make(map[string]resources.EventStaticMeta, len(raw.Types)) for _, t := range raw.Types { - inner[t.ID-1] = resources.EventStaticMeta{ + inner[t.Name] = resources.EventStaticMeta{ Name: t.Name, Description: t.Description, Reward: t.Reward, diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index 4b4481d..1507d37 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -1,25 +1,22 @@ package evtypes import ( - "errors" - "github.com/rarimo/points-svc/resources" ) -var ErrInvalidID = errors.New("wrong event type id") - type Types struct { - inner []resources.EventStaticMeta + inner map[string]resources.EventStaticMeta } -func (t *Types) Get(id int) (resources.EventStaticMeta, error) { +func (t Types) Get(name string) *resources.EventStaticMeta { if t.inner == nil { panic("event types are not correctly initialized") } - if id <= 0 || id > len(t.inner) { - return resources.EventStaticMeta{}, ErrInvalidID + v, ok := t.inner[name] + if !ok { + return nil } - return t.inner[id-1], nil + return &v } diff --git a/internal/data/main.go b/internal/data/main.go index 54409fc..33d9c74 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -48,8 +48,8 @@ type BalancesQ interface { type Event struct { ID string `db:"id"` - TypeID string `db:"type_id"` BalanceID string `db:"balance_id"` + Type string `db:"type"` Status EventStatus `db:"status"` CreatedAt time.Time `db:"created_at"` Meta sql.NullString `db:"meta"` diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index 9fde24a..b4698da 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -4,6 +4,7 @@ import ( "database/sql" "errors" "fmt" + "time" "github.com/Masterminds/squirrel" "github.com/rarimo/points-svc/internal/data" @@ -45,7 +46,9 @@ func (q *balances) Insert(balance data.Balance) error { } func (q *balances) UpdateAmount(amount int) error { - stmt := q.updater.Set("amount", amount) + stmt := q.updater. + Set("amount", amount). + Set("updated_at", time.Now().UTC()) if err := q.db.Exec(stmt); err != nil { return fmt.Errorf("update balance amount to %d: %w", amount, err) diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 5ee6f8b..7f08778 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -2,6 +2,7 @@ package pg import ( "fmt" + "time" "github.com/Masterminds/squirrel" "github.com/rarimo/points-svc/internal/data" @@ -28,8 +29,8 @@ func (q *events) New() data.EventsQ { func (q *events) Insert(event data.Event) error { imap := map[string]any{ // ID must be created sequentially - "type_id": event.TypeID, "balance_id": event.BalanceID, + "type": event.Type, "status": event.Status, "created_at": event.CreatedAt, "meta": event.Meta, @@ -48,6 +49,7 @@ func (q *events) Update(event data.Event) error { "status": event.Status, "meta": event.Meta, "points_amount": event.PointsAmount, + "updated_at": time.Now().UTC(), } stmt := squirrel.Update(eventsTable).SetMap(umap).Where(squirrel.Eq{"id": event.ID}) diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index e408d1c..7448f61 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -1,6 +1,7 @@ package handlers import ( + "database/sql" "net/http" "github.com/go-chi/chi" @@ -40,10 +41,20 @@ func ClaimEvent(w http.ResponseWriter, r *http.Request) { return } + evType := EventTypes(r).Get(event.Type) + if evType == nil { + Log(r).Error("Wrong event type is stored in DB: might be bad event config") + ape.RenderErr(w, problems.InternalError()) + return + } + err = EventsQ(r).Update(data.Event{ ID: event.ID, Status: data.EventClaimed, - // TODO: add points amount from config, accrue points + PointsAmount: sql.NullInt32{ + Int32: evType.Reward, + Valid: true, + }, }) if err != nil { Log(r).WithError(err).Error("Failed to claim event") @@ -51,5 +62,12 @@ func ClaimEvent(w http.ResponseWriter, r *http.Request) { return } + err = BalancesQ(r).FilterByID(balance.ID).UpdateAmount(int(evType.Reward)) + if err != nil { + Log(r).WithError(err).Error("Failed to accrue points to the balance") + ape.RenderErr(w, problems.InternalError()) + return + } + w.WriteHeader(http.StatusNoContent) } diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index 3a736f0..fd2cb9d 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -5,6 +5,7 @@ import ( "net/http" "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/points-svc/internal/data/evtypes" "gitlab.com/distributed_lab/logan/v3" ) @@ -14,6 +15,7 @@ const ( logCtxKey ctxKey = iota eventsQCtxKey balancesQCtxKey + eventTypesCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -45,3 +47,13 @@ func CtxBalancesQ(q data.BalancesQ) func(context.Context) context.Context { func BalancesQ(r *http.Request) data.BalancesQ { return r.Context().Value(balancesQCtxKey).(data.BalancesQ).New() } + +func CtxEventTypes(types evtypes.Types) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, eventTypesCtxKey, types) + } +} + +func EventTypes(r *http.Request) evtypes.Types { + return r.Context().Value(eventTypesCtxKey).(evtypes.Types) +} diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index 1817f22..e6d6722 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -35,17 +35,28 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { return } + orderedMeta := make([]resources.EventStaticMeta, len(events)) + for i, event := range events { + evType := EventTypes(r).Get(event.Type) + if evType == nil { + Log(r).Error("Wrong event type is stored in DB: might be bad event config") + ape.RenderErr(w, problems.InternalError()) + return + } + orderedMeta[i] = *evType + } + resp := newEventsResponse(events, orderedMeta) + var last string if len(events) > 0 { last = events[len(events)-1].ID } - resp := newEventsResponse(events) resp.Links = req.CursorParams.GetCursorLinks(r, last) ape.Render(w, resp) } -func newEventsResponse(events []data.Event) *resources.EventListResponse { +func newEventsResponse(events []data.Event, meta []resources.EventStaticMeta) *resources.EventListResponse { list := make([]resources.Event, len(events)) for i, event := range events { @@ -68,7 +79,7 @@ func newEventsResponse(events []data.Event) *resources.EventListResponse { Attributes: resources.EventAttributes{ CreatedAt: event.CreatedAt, Meta: resources.EventMeta{ - //Static: json.RawMessage{}, // TODO: add from config + Static: meta[i], Dynamic: dynamic, }, Status: event.Status.String(), diff --git a/internal/service/router.go b/internal/service/router.go index 34d6145..e928702 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -17,6 +17,7 @@ func (s *service) router() chi.Router { handlers.CtxLog(s.log), handlers.CtxEventsQ(pg.NewEvents(s.cfg.DB())), handlers.CtxBalancesQ(pg.NewBalances(s.cfg.DB())), + handlers.CtxEventTypes(s.cfg.EventTypes()), ), ) r.Route("/integrations/points-svc", func(r chi.Router) { From f3df5caa28a8e8d896fb00c44a9441c983d3105c Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 14:10:01 +0200 Subject: [PATCH 15/63] Balance creation endpoint with open events insertion --- .../integrations@points-svc@balance.yaml | 36 ++++++++++- internal/data/evtypes/main.go | 23 ++++++++ internal/data/main.go | 2 +- internal/data/pg/events.go | 21 +++---- internal/service/handlers/create_balance.go | 59 +++++++++++++++++++ internal/service/handlers/get_balance.go | 1 + internal/service/handlers/list_events.go | 30 ++++++---- internal/service/router.go | 3 +- 8 files changed, 152 insertions(+), 23 deletions(-) create mode 100644 internal/service/handlers/create_balance.go diff --git a/docs/spec/paths/integrations@points-svc@balance.yaml b/docs/spec/paths/integrations@points-svc@balance.yaml index 8a32634..f8d1e48 100644 --- a/docs/spec/paths/integrations@points-svc@balance.yaml +++ b/docs/spec/paths/integrations@points-svc@balance.yaml @@ -2,7 +2,9 @@ get: tags: - Points balance summary: Get points balance for user - description: Balance of authorized user who makes the request. Rank in leaderboard is included. + description: | + Balance of authorized user who makes the request. Rank in leaderboard is included. + You should create new balance for the new user by making POST request. operationId: getPointsBalance responses: 200: @@ -22,3 +24,35 @@ get: $ref: '#/components/responses/invalidAuth' 500: $ref: '#/components/responses/internalError' + +post: + tags: + - Points balance + summary: Create points balance + description: | + Create an empty balance for authorized user who makes the request. Rank is included. + This operation might be time-consuming, because `open` events should be added for + the new account synchronously (to display them right after the request). + operationId: createPointsBalance + responses: + 201: + description: Created + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Balance' + 401: + $ref: '#/components/responses/invalidAuth' + 409: + description: Balance already exists for provided DID + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Errors' + 500: + $ref: '#/components/responses/internalError' diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index 1507d37..f98cb10 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -1,6 +1,8 @@ package evtypes import ( + "time" + "github.com/rarimo/points-svc/resources" ) @@ -20,3 +22,24 @@ func (t Types) Get(name string) *resources.EventStaticMeta { return &v } + +// List returns non-expired event types +func (t Types) List() []resources.EventStaticMeta { + if t.inner == nil { + panic("event types are not correctly initialized") + } + + res := make([]resources.EventStaticMeta, 0, len(t.inner)) + for _, v := range t.inner { + if isExpiredEvent(v) { + continue + } + res = append(res, v) + } + + return res +} + +func isExpiredEvent(ev resources.EventStaticMeta) bool { + return ev.ExpiresAt != nil && ev.ExpiresAt.Before(time.Now().UTC()) +} diff --git a/internal/data/main.go b/internal/data/main.go index 33d9c74..df5d9b9 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -21,7 +21,7 @@ func (s EventStatus) String() string { type EventsQ interface { New() EventsQ - Insert(Event) error + Insert(...Event) error Update(Event) error Page(*pgdb.CursorPageParams) EventsQ diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 7f08778..86e205f 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -27,18 +27,19 @@ func (q *events) New() data.EventsQ { return NewEvents(q.db.Clone()) } -func (q *events) Insert(event data.Event) error { - imap := map[string]any{ // ID must be created sequentially - "balance_id": event.BalanceID, - "type": event.Type, - "status": event.Status, - "created_at": event.CreatedAt, - "meta": event.Meta, - "points_amount": event.PointsAmount, +func (q *events) Insert(events ...data.Event) error { + if len(events) == 0 { + return nil } - if err := q.db.Exec(squirrel.Insert(eventsTable).SetMap(imap)); err != nil { - return fmt.Errorf("insert event %+v: %w", event, err) + stmt := squirrel.Insert(eventsTable). + Columns("balance_id", "type", "status", "created_at", "meta", "points_amount") + for _, event := range events { + stmt = stmt.Values(event.BalanceID, event.Type, event.Status, event.CreatedAt, event.Meta, event.PointsAmount) + } + + if err := q.db.Exec(stmt); err != nil { + return fmt.Errorf("insert events [%+v]: %w", events, err) } return nil diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go new file mode 100644 index 0000000..7987910 --- /dev/null +++ b/internal/service/handlers/create_balance.go @@ -0,0 +1,59 @@ +package handlers + +import ( + "database/sql" + "net/http" + + "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/points-svc/resources" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" +) + +func CreateBalance(w http.ResponseWriter, r *http.Request) { + did := r.Header.Get("X-User-DID") + + balance := getBalanceByDID(did, false, w, r) + if balance != nil { + ape.RenderErr(w, problems.Conflict()) + return + } + + if err := BalancesQ(r).Insert(data.Balance{DID: did}); err != nil { + Log(r).WithError(err).Error("Failed to create balance") + ape.RenderErr(w, problems.InternalError()) + return + } + // We can't return inserted balance in a single query, because we can't calculate + // rank in transaction: RANK() is a window function allowed on a set of rows, + // while with RETURNING we operate a single one. + balance = getBalanceByDID(did, true, w, r) + if balance == nil { + return + } + + err := EventsQ(r).Insert(prepareOpenEvents(balance.ID, EventTypes(r).List())...) + if err != nil { + Log(r).WithError(err).Error("Failed to add open events") + ape.RenderErr(w, problems.InternalError()) + return + } + + ape.Render(w, newBalanceModel(*balance)) +} + +func prepareOpenEvents(balanceID string, evTypes []resources.EventStaticMeta) []data.Event { + events := make([]data.Event, len(evTypes)) + for i, evType := range evTypes { + events[i] = data.Event{ + BalanceID: balanceID, + Type: evType.Name, + Status: data.EventOpen, + PointsAmount: sql.NullInt32{ + Int32: evType.Reward, + Valid: true, + }, + } + } + return events +} diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go index 08b4f5b..2f403c7 100644 --- a/internal/service/handlers/get_balance.go +++ b/internal/service/handlers/get_balance.go @@ -11,6 +11,7 @@ import ( func GetBalance(w http.ResponseWriter, r *http.Request) { did := r.Header.Get("X-User-DID") // TODO: get DID from auth + balance := getBalanceByDID(did, true, w, r) if balance == nil { return diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index e6d6722..cab86da 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -35,27 +35,37 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { return } - orderedMeta := make([]resources.EventStaticMeta, len(events)) - for i, event := range events { - evType := EventTypes(r).Get(event.Type) - if evType == nil { - Log(r).Error("Wrong event type is stored in DB: might be bad event config") - ape.RenderErr(w, problems.InternalError()) - return - } - orderedMeta[i] = *evType + meta, ok := getOrderedEventsMeta(events, w, r) + if !ok { + return } - resp := newEventsResponse(events, orderedMeta) var last string if len(events) > 0 { last = events[len(events)-1].ID } + resp := newEventsResponse(events, meta) resp.Links = req.CursorParams.GetCursorLinks(r, last) ape.Render(w, resp) } +func getOrderedEventsMeta(events []data.Event, w http.ResponseWriter, r *http.Request) ([]resources.EventStaticMeta, bool) { + res := make([]resources.EventStaticMeta, len(events)) + + for i, event := range events { + evType := EventTypes(r).Get(event.Type) + if evType == nil { + Log(r).Error("Wrong event type is stored in DB: might be bad event config") + ape.RenderErr(w, problems.InternalError()) + return nil, false + } + res[i] = *evType + } + + return res, true +} + func newEventsResponse(events []data.Event, meta []resources.EventStaticMeta) *resources.EventListResponse { list := make([]resources.Event, len(events)) diff --git a/internal/service/router.go b/internal/service/router.go index e928702..fe3014f 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -22,9 +22,10 @@ func (s *service) router() chi.Router { ) r.Route("/integrations/points-svc", func(r chi.Router) { r.Get("/balance", handlers.GetBalance) + r.Post("/balance", handlers.CreateBalance) r.Get("/leaderboard", handlers.Leaderboard) r.Get("/events", handlers.ListEvents) - r.Put("/events/{id}", handlers.ClaimEvent) + r.Patch("/events/{id}", handlers.ClaimEvent) }) return r From 92441c9f2673799eae654cd2a845e7baf83cf5fc Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 14:46:25 +0200 Subject: [PATCH 16/63] Status filter for events must be multiple --- internal/service/handlers/list_events.go | 4 ++-- internal/service/requests/list_events.go | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index cab86da..3c5a4f5 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -24,8 +24,8 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { } q := EventsQ(r).FilterByBalanceID(balance.ID) - if req.FilterStatus != nil { - q.FilterByStatus(*req.FilterStatus) + if len(req.FilterStatus) > 0 { + q.FilterByStatus(req.FilterStatus...) } events, err := q.Page(&req.CursorPageParams).Select() diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go index 2efe1eb..dd7ad60 100644 --- a/internal/service/requests/list_events.go +++ b/internal/service/requests/list_events.go @@ -13,7 +13,7 @@ import ( type ListEvents struct { page.CursorParams DID string - FilterStatus *data.EventStatus `filter:"status"` + FilterStatus []data.EventStatus `filter:"status"` } func NewListEvents(r *http.Request) (req ListEvents, err error) { @@ -24,5 +24,8 @@ func NewListEvents(r *http.Request) (req ListEvents, err error) { } req.DID = r.Header.Get("X-User-DID") + err = validation.Errors{ + "filter[status]": validation.Validate(req.FilterStatus, validation.Each(validation.In(data.EventOpen, data.EventFulfilled, data.EventClaimed))), + }.Filter() return } From 0666a5d5b30aa19e9f36279920f0e35fbd4febcb Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 15:17:03 +0200 Subject: [PATCH 17/63] Add frequency for event types --- config.yaml | 2 ++ docs/spec/components/schemas/EventStaticMeta.yaml | 7 +++++++ internal/data/evtypes/config.go | 14 ++++++++++++++ internal/data/evtypes/main.go | 14 ++++++++++++++ resources/model_event_static_meta.go | 2 ++ 5 files changed, 39 insertions(+) diff --git a/config.yaml b/config.yaml index 063e296..f3d4fc9 100644 --- a/config.yaml +++ b/config.yaml @@ -21,8 +21,10 @@ event_types: title: Get PoH credential reward: 50 description: Lorem ipsum dolor sit amet + frequency: one-time expires_at: 2020-01-01T00:00:00Z - name: daily_login title: Daily login reward: 5 + frequency: daily description: Lorem ipsum dolor sit amet diff --git a/docs/spec/components/schemas/EventStaticMeta.yaml b/docs/spec/components/schemas/EventStaticMeta.yaml index c25cbf5..bd847b1 100644 --- a/docs/spec/components/schemas/EventStaticMeta.yaml +++ b/docs/spec/components/schemas/EventStaticMeta.yaml @@ -7,6 +7,7 @@ required: - reward - title - description + - frequency properties: name: type: string @@ -27,3 +28,9 @@ properties: description: type: string example: Lorem ipsum dolor sit amet + frequency: + type: string + description: | + Event frequency, which means how often you can fulfill + certain task and claim the reward. + enum: [one-time, daily, weekly, unlimited, custom] diff --git a/internal/data/evtypes/config.go b/internal/data/evtypes/config.go index 9f90b63..4a3abc3 100644 --- a/internal/data/evtypes/config.go +++ b/internal/data/evtypes/config.go @@ -31,6 +31,7 @@ func (c *config) EventTypes() Types { Description string `fig:"description,required"` Reward int32 `fig:"reward,required"` Title string `fig:"title,required"` + Frequency Frequency `fig:"frequency,required"` ExpiresAt *time.Time `fig:"expires_at"` } `fig:"types,required"` } @@ -44,11 +45,16 @@ func (c *config) EventTypes() Types { inner := make(map[string]resources.EventStaticMeta, len(raw.Types)) for _, t := range raw.Types { + if !checkFreqValue(t.Frequency) { + panic(fmt.Errorf("invalid frequency: %s", t.Frequency)) + } + inner[t.Name] = resources.EventStaticMeta{ Name: t.Name, Description: t.Description, Reward: t.Reward, Title: t.Title, + Frequency: t.Frequency.String(), ExpiresAt: t.ExpiresAt, } } @@ -56,3 +62,11 @@ func (c *config) EventTypes() Types { return Types{inner} }).(Types) } + +func checkFreqValue(f Frequency) bool { + switch f { + case OneTime, Daily, Weekly, Unlimited, Custom: + return true + } + return false +} diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index f98cb10..4847908 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -6,6 +6,20 @@ import ( "github.com/rarimo/points-svc/resources" ) +type Frequency string + +func (f Frequency) String() string { + return string(f) +} + +const ( + OneTime Frequency = "one-time" + Daily Frequency = "daily" + Weekly Frequency = "weekly" + Unlimited Frequency = "unlimited" + Custom Frequency = "custom" +) + type Types struct { inner map[string]resources.EventStaticMeta } diff --git a/resources/model_event_static_meta.go b/resources/model_event_static_meta.go index 4ce9529..e7c3be4 100644 --- a/resources/model_event_static_meta.go +++ b/resources/model_event_static_meta.go @@ -11,6 +11,8 @@ type EventStaticMeta struct { Description string `json:"description"` // General event expiration date ExpiresAt *time.Time `json:"expires_at,omitempty"` + // Event frequency, which means how often you can fulfill certain task and claim the reward. + Frequency string `json:"frequency"` // Unique event code name Name string `json:"name"` // Reward amount in points From a7d4eaa2600bbff4ae8c6c6b96a30fde391d4a10 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 16:04:15 +0200 Subject: [PATCH 18/63] Update docker build base for Go 1.21 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b5714eb..8726690 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20-alpine as buildbase +FROM golang:1.21-alpine as buildbase RUN apk add git build-base From 11cf985125865dd2e533ee5235bafee668f6a0fb Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 16:12:35 +0200 Subject: [PATCH 19/63] Update go.mod for Go 1.21 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index dde5b2a..cfe4cea 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/rarimo/rarime-points-svc -go 1.21.3 +go 1.21 require ( github.com/Masterminds/squirrel v1.4.0 From 69aa27bf5fac2bfd46670481044954e077720914 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 16:37:47 +0200 Subject: [PATCH 20/63] Upgrade Go version in werf.yaml also --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index cfe4cea..dde5b2a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/rarimo/rarime-points-svc -go 1.21 +go 1.21.3 require ( github.com/Masterminds/squirrel v1.4.0 From b41d81650f0c14e56851ef19f5228433e3a4452c Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 17:59:22 +0200 Subject: [PATCH 21/63] Add events counting --- .../paths/integrations@points-svc@events.yaml | 16 ++++++++++ internal/data/main.go | 1 + internal/data/pg/events.go | 23 +++++++++++++++ internal/service/handlers/list_events.go | 29 +++++++++++++++---- internal/service/requests/list_events.go | 1 + 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml index 9d1f91c..0216c50 100644 --- a/docs/spec/paths/integrations@points-svc@events.yaml +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -18,6 +18,13 @@ get: items: type: string enum: [open, fulfilled, claimed] + - in: query + name: count + description: Count total number of events for a single user, applying filters. + required: false + schema: + type: boolean + example: true - $ref: '#/components/parameters/pageLimitParam' - $ref: '#/components/parameters/pageCursorParam' - $ref: '#/components/parameters/sortingParam' @@ -35,6 +42,15 @@ get: type: array items: $ref: '#/components/schemas/Event' + meta: + type: object + required: + - events_count + properties: + events_count: + type: integer + description: Appears when `count=true` is specified + example: 18 400: $ref: '#/components/responses/invalidParameter' 401: diff --git a/internal/data/main.go b/internal/data/main.go index df5d9b9..fcf3035 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -27,6 +27,7 @@ type EventsQ interface { Page(*pgdb.CursorPageParams) EventsQ Select() ([]Event, error) Get() (*Event, error) + Count() (int, error) FilterByID(string) EventsQ FilterByBalanceID(...string) EventsQ diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 86e205f..58cee8e 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -14,12 +14,14 @@ const eventsTable = "events" type events struct { db *pgdb.DB selector squirrel.SelectBuilder + counter squirrel.SelectBuilder } func NewEvents(db *pgdb.DB) data.EventsQ { return &events{ db: db, selector: squirrel.Select("*").From(eventsTable), + counter: squirrel.Select("count(id) AS count").From(eventsTable), } } @@ -86,17 +88,38 @@ func (q *events) Get() (*data.Event, error) { return &res, nil } +func (q *events) Count() (int, error) { + var res struct { + Count int `db:"count"` + } + + if err := q.db.Get(&res, q.counter); err != nil { + return 0, fmt.Errorf("count events: %w", err) + } + + return res.Count, nil +} + func (q *events) FilterByID(id string) data.EventsQ { q.selector = q.selector.Where(squirrel.Eq{"id": id}) + q.counter = q.counter.Where(squirrel.Eq{"id": id}) return q } func (q *events) FilterByBalanceID(ids ...string) data.EventsQ { + if len(ids) == 0 { + return q + } q.selector = q.selector.Where(squirrel.Eq{"balance_id": ids}) + q.counter = q.counter.Where(squirrel.Eq{"balance_id": ids}) return q } func (q *events) FilterByStatus(statuses ...data.EventStatus) data.EventsQ { + if len(statuses) == 0 { + return q + } q.selector = q.selector.Where(squirrel.Eq{"status": statuses}) + q.counter = q.counter.Where(squirrel.Eq{"status": statuses}) return q } diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index 3c5a4f5..1686543 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -23,18 +23,30 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { return } - q := EventsQ(r).FilterByBalanceID(balance.ID) - if len(req.FilterStatus) > 0 { - q.FilterByStatus(req.FilterStatus...) - } - - events, err := q.Page(&req.CursorPageParams).Select() + events, err := EventsQ(r). + FilterByBalanceID(balance.ID). + FilterByStatus(req.FilterStatus...). + Page(&req.CursorPageParams). + Select() if err != nil { Log(r).WithError(err).Error("Failed to get event list") ape.RenderErr(w, problems.InternalError()) return } + var eventsCount int + if req.Count { + eventsCount, err = EventsQ(r). + FilterByBalanceID(balance.ID). + FilterByStatus(req.FilterStatus...). + Count() + if err != nil { + Log(r).WithError(err).Error("Failed to count events") + ape.RenderErr(w, problems.InternalError()) + return + } + } + meta, ok := getOrderedEventsMeta(events, w, r) if !ok { return @@ -47,6 +59,11 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { resp := newEventsResponse(events, meta) resp.Links = req.CursorParams.GetCursorLinks(r, last) + if req.Count { + _ = resp.PutMeta(struct { + EventsCount int `json:"events_count"` + }{eventsCount}) + } ape.Render(w, resp) } diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go index dd7ad60..d2258a2 100644 --- a/internal/service/requests/list_events.go +++ b/internal/service/requests/list_events.go @@ -14,6 +14,7 @@ type ListEvents struct { page.CursorParams DID string FilterStatus []data.EventStatus `filter:"status"` + Count bool `url:"count"` } func NewListEvents(r *http.Request) (req ListEvents, err error) { From 496dec95602f7c7a9b95de2b25ac291c500a07f4 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 18:16:08 +0200 Subject: [PATCH 22/63] Change actions.yaml to build pullable image --- .github/workflows/actions.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/actions.yaml b/.github/workflows/actions.yaml index 11c0936..f49c6c6 100644 --- a/.github/workflows/actions.yaml +++ b/.github/workflows/actions.yaml @@ -27,5 +27,5 @@ jobs: echo $GITHUB_SHA - name: Run Build run: | - . $(werf ci-env github --as-file) - werf export service --tag ghcr.io/$GITHUB_REPOSITORY:$GITHUB_SHA + . $(werf ci-env github --as-file) + werf export service --tag ghcr.io/$GITHUB_REPOSITORY:$GITHUB_SHA \ No newline at end of file From 9fe85709874bccbd9864fb28eeabd58739aa53f5 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 18:19:31 +0200 Subject: [PATCH 23/63] Change actions.yaml to build pullable image (2) --- .github/workflows/actions.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/actions.yaml b/.github/workflows/actions.yaml index f49c6c6..fe3deaf 100644 --- a/.github/workflows/actions.yaml +++ b/.github/workflows/actions.yaml @@ -1,5 +1,9 @@ on: workflow_dispatch: + push: + branches: + - 'master' + - 'main' jobs: converge: @@ -27,5 +31,5 @@ jobs: echo $GITHUB_SHA - name: Run Build run: | - . $(werf ci-env github --as-file) - werf export service --tag ghcr.io/$GITHUB_REPOSITORY:$GITHUB_SHA \ No newline at end of file + . $(werf ci-env github --as-file) + werf export service --tag ghcr.io/$GITHUB_REPOSITORY:$GITHUB_SHA From 18e3806eb6798747948b1a146b02c07e4203cdb7 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 18:35:52 +0200 Subject: [PATCH 24/63] Fix werf.yaml --- werf.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/werf.yaml b/werf.yaml index 5d63e7e..d5c6261 100644 --- a/werf.yaml +++ b/werf.yaml @@ -1,13 +1,13 @@ configVersion: 1 -project: "rarime-points-svc" +project: "points-svc" --- image: builder from: golang:1.21-alpine docker: - WORKDIR: /go/src/github.com/rarimo/rarime-points-svc + WORKDIR: /go/src/github.com/rarimo/points-svc git: - add: / - to: /go/src/github.com/rarimo/rarime-points-svc + to: /go/src/github.com/rarimo/points-svc stageDependencies: install: - go.mod @@ -20,26 +20,26 @@ shell: - export CGO_ENABLED=1 - export GO111MODULE=on - export GOOS=linux - - cd /go/src/github.com/rarimo/rarime-points-svc + - cd /go/src/github.com/rarimo/points-svc - go mod tidy - go mod vendor setup: - export CGO_ENABLED=1 - export GO111MODULE=on - export GOOS=linux - - cd /go/src/github.com/rarimo/rarime-points-svc - - go build -o /usr/local/bin/rarime-points-svc /go/src/github.com/rarimo/rarime-points-svc + - cd /go/src/github.com/rarimo/points-svc + - go build -o /usr/local/bin/points-svc /go/src/github.com/rarimo/points-svc --- image: service from: alpine:3.9 docker: - ENTRYPOINT: rarime-points-svc + ENTRYPOINT: points-svc shell: setup: - apk add --no-cache ca-certificates import: - image: builder - add: /usr/local/bin/rarime-points-svc - to: /usr/local/bin/rarime-points-svc + add: /usr/local/bin/points-svc + to: /usr/local/bin/points-svc after: setup \ No newline at end of file From 52dcef800808003477e01e6c7f76fd2e209dbf3a Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 18:47:12 +0200 Subject: [PATCH 25/63] Delete werf-giterminism.yaml, drop triggers in actions.yaml --- .github/workflows/actions.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/actions.yaml b/.github/workflows/actions.yaml index fe3deaf..11c0936 100644 --- a/.github/workflows/actions.yaml +++ b/.github/workflows/actions.yaml @@ -1,9 +1,5 @@ on: workflow_dispatch: - push: - branches: - - 'master' - - 'main' jobs: converge: From 12024b650eb61934483647b6efb75461f974f1ec Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 23 Jan 2024 19:21:32 +0200 Subject: [PATCH 26/63] Change module name --- docs/package-lock.json | 2 +- internal/config/main.go | 2 +- internal/data/evtypes/config.go | 2 +- internal/data/evtypes/main.go | 2 +- internal/data/pg/balances.go | 2 +- internal/data/pg/events.go | 2 +- internal/service/handlers/claim_event.go | 2 +- internal/service/handlers/create_balance.go | 4 ++-- internal/service/handlers/ctx.go | 4 ++-- internal/service/handlers/get_balance.go | 4 ++-- internal/service/handlers/leaderboard.go | 6 +++--- internal/service/handlers/list_events.go | 6 +++--- internal/service/page/links.go | 2 +- internal/service/requests/list_events.go | 4 ++-- internal/service/router.go | 6 +++--- werf.yaml | 18 +++++++++--------- 16 files changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index a719d07..b5e50e7 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -5,7 +5,7 @@ "requires": true, "packages": { "": { - "name": "points-svc", + "name": "rarime-points-svc", "version": "1.0.0", "dependencies": { "@tokend/redoc-cli": "^0.9.9", diff --git a/internal/config/main.go b/internal/config/main.go index 71432df..23c1474 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -1,7 +1,7 @@ package config import ( - "github.com/rarimo/points-svc/internal/data/evtypes" + "github.com/rarimo/rarime-points-svc/internal/data/evtypes" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/copus" "gitlab.com/distributed_lab/kit/copus/types" diff --git a/internal/data/evtypes/config.go b/internal/data/evtypes/config.go index 4a3abc3..a918106 100644 --- a/internal/data/evtypes/config.go +++ b/internal/data/evtypes/config.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/rarimo/points-svc/resources" + "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/figure/v3" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/kv" diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index 4847908..125cd12 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -3,7 +3,7 @@ package evtypes import ( "time" - "github.com/rarimo/points-svc/resources" + "github.com/rarimo/rarime-points-svc/resources" ) type Frequency string diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index b4698da..596341f 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -7,7 +7,7 @@ import ( "time" "github.com/Masterminds/squirrel" - "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/data" "gitlab.com/distributed_lab/kit/pgdb" ) diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 58cee8e..803925c 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -5,7 +5,7 @@ import ( "time" "github.com/Masterminds/squirrel" - "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/data" "gitlab.com/distributed_lab/kit/pgdb" ) diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index 7448f61..1af8e52 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/go-chi/chi" - "github.com/rarimo/points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/data" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index 7987910..957cc59 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -4,8 +4,8 @@ import ( "database/sql" "net/http" - "github.com/rarimo/points-svc/internal/data" - "github.com/rarimo/points-svc/resources" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index fd2cb9d..d18d0dd 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -4,8 +4,8 @@ import ( "context" "net/http" - "github.com/rarimo/points-svc/internal/data" - "github.com/rarimo/points-svc/internal/data/evtypes" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/data/evtypes" "gitlab.com/distributed_lab/logan/v3" ) diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go index 2f403c7..4cd78f2 100644 --- a/internal/service/handlers/get_balance.go +++ b/internal/service/handlers/get_balance.go @@ -3,8 +3,8 @@ package handlers import ( "net/http" - "github.com/rarimo/points-svc/internal/data" - "github.com/rarimo/points-svc/resources" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) diff --git a/internal/service/handlers/leaderboard.go b/internal/service/handlers/leaderboard.go index 9dbc2cf..397312a 100644 --- a/internal/service/handlers/leaderboard.go +++ b/internal/service/handlers/leaderboard.go @@ -3,9 +3,9 @@ package handlers import ( "net/http" - "github.com/rarimo/points-svc/internal/data" - "github.com/rarimo/points-svc/internal/service/requests" - "github.com/rarimo/points-svc/resources" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/service/requests" + "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index 1686543..edfd9f1 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -4,9 +4,9 @@ import ( "encoding/json" "net/http" - "github.com/rarimo/points-svc/internal/data" - "github.com/rarimo/points-svc/internal/service/requests" - "github.com/rarimo/points-svc/resources" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/service/requests" + "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) diff --git a/internal/service/page/links.go b/internal/service/page/links.go index 57e124c..2568607 100644 --- a/internal/service/page/links.go +++ b/internal/service/page/links.go @@ -4,7 +4,7 @@ import ( "net/http" "strconv" - "github.com/rarimo/points-svc/resources" + "github.com/rarimo/rarime-points-svc/resources" ) func (p *CursorParams) GetCursorLinks(r *http.Request, last string) *resources.Links { diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go index d2258a2..6f61d7e 100644 --- a/internal/service/requests/list_events.go +++ b/internal/service/requests/list_events.go @@ -5,8 +5,8 @@ import ( "net/http" validation "github.com/go-ozzo/ozzo-validation/v4" - "github.com/rarimo/points-svc/internal/data" - "github.com/rarimo/points-svc/internal/service/page" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/service/page" "gitlab.com/distributed_lab/urlval/v4" ) diff --git a/internal/service/router.go b/internal/service/router.go index fe3014f..4eaa23b 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -2,8 +2,8 @@ package service import ( "github.com/go-chi/chi" - "github.com/rarimo/points-svc/internal/data/pg" - "github.com/rarimo/points-svc/internal/service/handlers" + "github.com/rarimo/rarime-points-svc/internal/data/pg" + "github.com/rarimo/rarime-points-svc/internal/service/handlers" "gitlab.com/distributed_lab/ape" ) @@ -20,7 +20,7 @@ func (s *service) router() chi.Router { handlers.CtxEventTypes(s.cfg.EventTypes()), ), ) - r.Route("/integrations/points-svc", func(r chi.Router) { + r.Route("/integrations/rarime-points-svc", func(r chi.Router) { r.Get("/balance", handlers.GetBalance) r.Post("/balance", handlers.CreateBalance) r.Get("/leaderboard", handlers.Leaderboard) diff --git a/werf.yaml b/werf.yaml index d5c6261..5d63e7e 100644 --- a/werf.yaml +++ b/werf.yaml @@ -1,13 +1,13 @@ configVersion: 1 -project: "points-svc" +project: "rarime-points-svc" --- image: builder from: golang:1.21-alpine docker: - WORKDIR: /go/src/github.com/rarimo/points-svc + WORKDIR: /go/src/github.com/rarimo/rarime-points-svc git: - add: / - to: /go/src/github.com/rarimo/points-svc + to: /go/src/github.com/rarimo/rarime-points-svc stageDependencies: install: - go.mod @@ -20,26 +20,26 @@ shell: - export CGO_ENABLED=1 - export GO111MODULE=on - export GOOS=linux - - cd /go/src/github.com/rarimo/points-svc + - cd /go/src/github.com/rarimo/rarime-points-svc - go mod tidy - go mod vendor setup: - export CGO_ENABLED=1 - export GO111MODULE=on - export GOOS=linux - - cd /go/src/github.com/rarimo/points-svc - - go build -o /usr/local/bin/points-svc /go/src/github.com/rarimo/points-svc + - cd /go/src/github.com/rarimo/rarime-points-svc + - go build -o /usr/local/bin/rarime-points-svc /go/src/github.com/rarimo/rarime-points-svc --- image: service from: alpine:3.9 docker: - ENTRYPOINT: points-svc + ENTRYPOINT: rarime-points-svc shell: setup: - apk add --no-cache ca-certificates import: - image: builder - add: /usr/local/bin/points-svc - to: /usr/local/bin/points-svc + add: /usr/local/bin/rarime-points-svc + to: /usr/local/bin/rarime-points-svc after: setup \ No newline at end of file From 2841ee961f335d4b96aa8feab0c8b11cf6e55ee4 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 12:05:06 +0200 Subject: [PATCH 27/63] Add auth middleware with hacks --- .github/workflows/actions_branch.yaml | 1 - go.mod | 35 ++-- go.sum | 190 ++++++++++++++------ internal/config/main.go | 6 +- internal/service/handlers/claim_event.go | 3 +- internal/service/handlers/create_balance.go | 2 +- internal/service/handlers/ctx.go | 12 ++ internal/service/handlers/get_balance.go | 2 +- internal/service/handlers/list_events.go | 3 +- internal/service/handlers/middleware.go | 45 +++++ internal/service/requests/list_events.go | 2 - internal/service/router.go | 11 +- 12 files changed, 231 insertions(+), 81 deletions(-) create mode 100644 internal/service/handlers/middleware.go diff --git a/.github/workflows/actions_branch.yaml b/.github/workflows/actions_branch.yaml index 4da5f7e..f85552b 100644 --- a/.github/workflows/actions_branch.yaml +++ b/.github/workflows/actions_branch.yaml @@ -2,7 +2,6 @@ on: push: branches: - 'main' - - 'feature/base' jobs: converge: diff --git a/go.mod b/go.mod index dde5b2a..63220be 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/alecthomas/kingpin v2.2.6+incompatible github.com/go-chi/chi v4.1.2+incompatible github.com/go-ozzo/ozzo-validation/v4 v4.2.1 + github.com/rarimo/rarime-auth-svc v0.0.1-rc8 github.com/rubenv/sql-migrate v1.6.1 gitlab.com/distributed_lab/ape v1.7.1 gitlab.com/distributed_lab/figure/v3 v3.1.3 @@ -16,29 +17,38 @@ require ( ) require ( - github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect - github.com/deckarep/golang-set v1.8.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/ethereum/go-ethereum v1.10.25 // indirect - github.com/fsnotify/fsnotify v1.4.7 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/ethereum/go-ethereum v1.13.8 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/getsentry/raven-go v0.2.0 // indirect github.com/getsentry/sentry-go v0.7.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect - github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-stack/stack v1.8.0 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect + github.com/golang-jwt/jwt/v5 v5.2.0 // indirect github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/uint256 v1.2.4 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/magiconair/properties v1.8.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -47,16 +57,21 @@ require ( github.com/spf13/afero v1.1.2 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.0.0 // indirect - github.com/spf13/pflag v1.0.3 // indirect + github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.3.2 // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect + github.com/supranational/blst v0.3.11 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect gitlab.com/distributed_lab/figure v2.1.0+incompatible // indirect gitlab.com/distributed_lab/lorem v0.2.0 // indirect gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c // indirect golang.org/x/crypto v0.17.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + golang.org/x/tools v0.15.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index e5faa3b..88b41ac 100644 --- a/go.sum +++ b/go.sum @@ -3,15 +3,19 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= github.com/Masterminds/squirrel v1.4.0 h1:he5i/EXixZxrBUWcxzDYMiju9WZ3ld/l7QBNuo/eN3w= github.com/Masterminds/squirrel v1.4.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= -github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= @@ -23,15 +27,35 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= +github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= +github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -39,12 +63,16 @@ github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= -github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= @@ -53,12 +81,12 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/go-ethereum v1.10.25 h1:5dFrKJDnYf8L6/5o42abCE6a9yJm9cs4EJVRyYMr55s= -github.com/ethereum/go-ethereum v1.10.25/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= +github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= @@ -66,11 +94,14 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+ github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/sentry-go v0.7.0 h1:MR2yfR4vFfv/2+iBuSnkdQwVg7N9cJzihZ6KJu7srwQ= @@ -85,31 +116,39 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ozzo/ozzo-validation/v4 v4.2.1 h1:XALUNshPYumA7UShB7iM3ZVlqIBn0jfwjqAMIoyE1N0= github.com/go-ozzo/ozzo-validation/v4 v4.2.1/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= -github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= +github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 h1:aQ4kMXDAmP9IRIZHcSKB2orXHGwGiSxH4PX1BzKHR50= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -119,17 +158,17 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -152,6 +191,8 @@ github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6i github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -162,12 +203,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= @@ -182,12 +227,14 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= @@ -197,6 +244,9 @@ github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxd github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= @@ -221,10 +271,18 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= -github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= -github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rarimo/rarime-auth-svc v0.0.1-rc8 h1:MBx51/ynR8BaRz5HvcbatYe4hnB2ZDVwM7cmGEepg+Y= +github.com/rarimo/rarime-auth-svc v0.0.1-rc8/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -254,12 +312,13 @@ github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -267,22 +326,24 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= -github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -322,6 +383,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -332,11 +397,11 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -345,11 +410,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -357,16 +425,18 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -376,8 +446,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -387,3 +457,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/internal/config/main.go b/internal/config/main.go index 23c1474..95ce2b1 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -1,6 +1,7 @@ package config import ( + "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/copus" @@ -15,6 +16,7 @@ type Config interface { types.Copuser comfig.Listenerer evtypes.EventTypeser + auth.Auther } type config struct { @@ -23,6 +25,7 @@ type config struct { types.Copuser comfig.Listenerer evtypes.EventTypeser + auth.Auther getter kv.Getter } @@ -30,10 +33,11 @@ type config struct { func New(getter kv.Getter) Config { return &config{ getter: getter, - EventTypeser: evtypes.NewConfig(getter), Databaser: pgdb.NewDatabaser(getter), Copuser: copus.NewCopuser(getter), Listenerer: comfig.NewListenerer(getter), Logger: comfig.NewLogger(getter, comfig.LoggerOpts{}), + EventTypeser: evtypes.NewConfig(getter), + Auther: auth.NewAuther(getter), } } diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index 1af8e52..f4b8315 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -11,8 +11,7 @@ import ( ) func ClaimEvent(w http.ResponseWriter, r *http.Request) { - did := r.Header.Get("X-User-DID") - + did := UserDID(r) eventID := chi.URLParam(r, "id") if eventID == "" { ape.RenderErr(w, problems.BadRequest(nil)...) diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index 957cc59..7230d22 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -11,7 +11,7 @@ import ( ) func CreateBalance(w http.ResponseWriter, r *http.Request) { - did := r.Header.Get("X-User-DID") + did := UserDID(r) balance := getBalanceByDID(did, false, w, r) if balance != nil { diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index d18d0dd..756e9cd 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -16,6 +16,8 @@ const ( eventsQCtxKey balancesQCtxKey eventTypesCtxKey + userClaimCtxKey + userDidCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -57,3 +59,13 @@ func CtxEventTypes(types evtypes.Types) func(context.Context) context.Context { func EventTypes(r *http.Request) evtypes.Types { return r.Context().Value(eventTypesCtxKey).(evtypes.Types) } + +func CtxUserDID(did string) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, userDidCtxKey, did) + } +} + +func UserDID(r *http.Request) string { + return r.Context().Value(userDidCtxKey).(string) +} diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go index 4cd78f2..c5e1cdb 100644 --- a/internal/service/handlers/get_balance.go +++ b/internal/service/handlers/get_balance.go @@ -10,7 +10,7 @@ import ( ) func GetBalance(w http.ResponseWriter, r *http.Request) { - did := r.Header.Get("X-User-DID") // TODO: get DID from auth + did := UserDID(r) balance := getBalanceByDID(did, true, w, r) if balance == nil { diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index edfd9f1..207e48b 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -18,7 +18,8 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { return } - balance := getBalanceByDID(req.DID, false, w, r) + did := UserDID(r) + balance := getBalanceByDID(did, false, w, r) if balance == nil { return } diff --git a/internal/service/handlers/middleware.go b/internal/service/handlers/middleware.go new file mode 100644 index 0000000..3d074b1 --- /dev/null +++ b/internal/service/handlers/middleware.go @@ -0,0 +1,45 @@ +package handlers + +import ( + "net/http" + + "github.com/rarimo/rarime-auth-svc/pkg/auth" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" + "gitlab.com/distributed_lab/logan/v3" +) + +func AuthMiddleware(auth *auth.Client, log *logan.Entry) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // in current implementation any error is internal, despite the status + claims, _, err := auth.ValidateJWT(r.Header) + if err != nil { + log.WithError(err).Error("failed to execute auth validate request") + ape.Render(w, problems.InternalError()) + return + } + + if len(claims) == 0 { + log.Debug("No claims returned for user") + ape.RenderErr(w, problems.Unauthorized()) + return + } + if len(claims) > 1 { + log.Errorf("Expected 1 claim to get user DID from, got %d claims", len(claims)) + ape.RenderErr(w, problems.InternalError()) + return + } + + claim := claims[0] + if claim.User == "" { + log.Debug("No user DID found in claim") + ape.RenderErr(w, problems.Unauthorized()) + return + } + + ctx := CtxUserDID(claim.User)(r.Context()) + next.ServeHTTP(w, r.WithContext(ctx)) + }) + } +} diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go index 6f61d7e..02f0640 100644 --- a/internal/service/requests/list_events.go +++ b/internal/service/requests/list_events.go @@ -12,7 +12,6 @@ import ( type ListEvents struct { page.CursorParams - DID string FilterStatus []data.EventStatus `filter:"status"` Count bool `url:"count"` } @@ -24,7 +23,6 @@ func NewListEvents(r *http.Request) (req ListEvents, err error) { } } - req.DID = r.Header.Get("X-User-DID") err = validation.Errors{ "filter[status]": validation.Validate(req.FilterStatus, validation.Each(validation.In(data.EventOpen, data.EventFulfilled, data.EventClaimed))), }.Filter() diff --git a/internal/service/router.go b/internal/service/router.go index 4eaa23b..bbb4ab5 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -21,11 +21,14 @@ func (s *service) router() chi.Router { ), ) r.Route("/integrations/rarime-points-svc", func(r chi.Router) { - r.Get("/balance", handlers.GetBalance) - r.Post("/balance", handlers.CreateBalance) + r.Group(func(r chi.Router) { + r.Use(handlers.AuthMiddleware(s.cfg.Auth(), s.log)) + r.Get("/balance", handlers.GetBalance) + r.Post("/balance", handlers.CreateBalance) + r.Get("/events", handlers.ListEvents) + r.Patch("/events/{id}", handlers.ClaimEvent) + }) r.Get("/leaderboard", handlers.Leaderboard) - r.Get("/events", handlers.ListEvents) - r.Patch("/events/{id}", handlers.ClaimEvent) }) return r From 7a04dbcd94719ae69a431e4660928bef7cc55052 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 12:21:54 +0200 Subject: [PATCH 28/63] Add docs CI, fix example config and readme --- .github/workflows/deploy-gh-pages.yaml | 33 ++++++++++++++++++++++++++ README.md | 9 ------- config.yaml | 3 +++ 3 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/deploy-gh-pages.yaml diff --git a/.github/workflows/deploy-gh-pages.yaml b/.github/workflows/deploy-gh-pages.yaml new file mode 100644 index 0000000..d19e1e1 --- /dev/null +++ b/.github/workflows/deploy-gh-pages.yaml @@ -0,0 +1,33 @@ +# Builds the docs and deploys to GitHub pages +# +# https://github.com/actions/setup-node +# Using https://github.com/marketplace/actions/deploy-to-github-pages +name: Deploy to Github pages + +on: + push: + branches: + - main + - master + +jobs: + deploy_pages: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '18' + + - run: | + cd ./docs + npm install + npm run build + + - run: touch docs/.nojekyll + - name: Deploy docs 🚀 + uses: JamesIves/github-pages-deploy-action@releases/v3 + with: + BRANCH: gh-pages # The branch the action should deploy to. + FOLDER: docs/web_deploy # The folder the action should deploy. diff --git a/README.md b/README.md index 96aabf5..9c7819c 100644 --- a/README.md +++ b/README.md @@ -56,12 +56,3 @@ use `docker run ` with `-p 8080:80` to expose port 80 to 8080 ### Database For services, we do use ***PostgresSQL*** database. You can [install it locally](https://www.postgresql.org/download/) or use [docker image](https://hub.docker.com/_/postgres/). - - -### Third-party services - - -## Contact - -Responsible -The primary contact for this project is [//]: # (TODO: place link to your telegram and email) diff --git a/config.yaml b/config.yaml index f3d4fc9..fb00bc1 100644 --- a/config.yaml +++ b/config.yaml @@ -28,3 +28,6 @@ event_types: reward: 5 frequency: daily description: Lorem ipsum dolor sit amet + +auth: + addr: http://rarime-auth From 9e0d1c7258be878149d71d60e08edcb237e33b8d Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 14:29:51 +0200 Subject: [PATCH 29/63] =?UTF-8?q?Make=20everything=20JSON:API=20compliant?= =?UTF-8?q?=20=F0=9F=A4=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spec/components/parameters/filterDID.yaml | 7 +++ .../components/parameters/includeBalance.yaml | 9 ++++ .../{pageCursorParam.yaml => pageCursor.yaml} | 0 .../{pageLimitParam.yaml => pageLimit.yaml} | 0 .../{sortingParam.yaml => pageOrder.yaml} | 2 +- docs/spec/components/schemas/BalanceKey.yaml | 3 +- docs/spec/components/schemas/ClaimEvent.yaml | 17 ++++++++ .../components/schemas/ClaimEventKey.yaml | 11 +++++ .../components/schemas/CreateBalance.yaml | 16 +++++++ .../components/schemas/CreateBalanceKey.yaml | 7 +++ docs/spec/components/schemas/Event.yaml | 13 ++++++ .../integrations@points-svc@balance.yaml | 12 ++++++ .../paths/integrations@points-svc@events.yaml | 8 ++-- .../integrations@points-svc@events@{id}.yaml | 12 ++++-- resources/model_claim_event.go | 43 +++++++++++++++++++ resources/model_claim_event_attributes.go | 10 +++++ resources/model_create_balance.go | 43 +++++++++++++++++++ resources/model_create_balance_attributes.go | 10 +++++ resources/model_event.go | 3 +- resources/model_event_relationships.go | 9 ++++ resources/model_resource_type.go | 6 ++- 21 files changed, 229 insertions(+), 12 deletions(-) create mode 100644 docs/spec/components/parameters/filterDID.yaml create mode 100644 docs/spec/components/parameters/includeBalance.yaml rename docs/spec/components/parameters/{pageCursorParam.yaml => pageCursor.yaml} (100%) rename docs/spec/components/parameters/{pageLimitParam.yaml => pageLimit.yaml} (100%) rename docs/spec/components/parameters/{sortingParam.yaml => pageOrder.yaml} (69%) create mode 100644 docs/spec/components/schemas/ClaimEvent.yaml create mode 100644 docs/spec/components/schemas/ClaimEventKey.yaml create mode 100644 docs/spec/components/schemas/CreateBalance.yaml create mode 100644 docs/spec/components/schemas/CreateBalanceKey.yaml create mode 100644 resources/model_claim_event.go create mode 100644 resources/model_claim_event_attributes.go create mode 100644 resources/model_create_balance.go create mode 100644 resources/model_create_balance_attributes.go create mode 100644 resources/model_event_relationships.go diff --git a/docs/spec/components/parameters/filterDID.yaml b/docs/spec/components/parameters/filterDID.yaml new file mode 100644 index 0000000..48d0d2a --- /dev/null +++ b/docs/spec/components/parameters/filterDID.yaml @@ -0,0 +1,7 @@ +in: query +name: 'filter[did]' +required: true +description: Filter by single user DID. Auth is required for this filter. +schema: + type: string + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" diff --git a/docs/spec/components/parameters/includeBalance.yaml b/docs/spec/components/parameters/includeBalance.yaml new file mode 100644 index 0000000..bc3cd01 --- /dev/null +++ b/docs/spec/components/parameters/includeBalance.yaml @@ -0,0 +1,9 @@ +in: query +name: include +description: Include user balance after updating +required: false +schema: + type: array + items: + type: string + enum: [ balance ] diff --git a/docs/spec/components/parameters/pageCursorParam.yaml b/docs/spec/components/parameters/pageCursor.yaml similarity index 100% rename from docs/spec/components/parameters/pageCursorParam.yaml rename to docs/spec/components/parameters/pageCursor.yaml diff --git a/docs/spec/components/parameters/pageLimitParam.yaml b/docs/spec/components/parameters/pageLimit.yaml similarity index 100% rename from docs/spec/components/parameters/pageLimitParam.yaml rename to docs/spec/components/parameters/pageLimit.yaml diff --git a/docs/spec/components/parameters/sortingParam.yaml b/docs/spec/components/parameters/pageOrder.yaml similarity index 69% rename from docs/spec/components/parameters/sortingParam.yaml rename to docs/spec/components/parameters/pageOrder.yaml index 35c5633..b7fe176 100644 --- a/docs/spec/components/parameters/sortingParam.yaml +++ b/docs/spec/components/parameters/pageOrder.yaml @@ -8,5 +8,5 @@ schema: - desc default: desc description: >- - Order of records on the page. If sortingParam is not specified, order of + Order of records on the page. If pageOrder is not specified, order of records is by default sorted by ID. diff --git a/docs/spec/components/schemas/BalanceKey.yaml b/docs/spec/components/schemas/BalanceKey.yaml index 3ccb78f..74d3c42 100644 --- a/docs/spec/components/schemas/BalanceKey.yaml +++ b/docs/spec/components/schemas/BalanceKey.yaml @@ -8,5 +8,4 @@ properties: example: "157801" type: type: string - enum: - - balance + enum: [ balance ] diff --git a/docs/spec/components/schemas/ClaimEvent.yaml b/docs/spec/components/schemas/ClaimEvent.yaml new file mode 100644 index 0000000..25348b4 --- /dev/null +++ b/docs/spec/components/schemas/ClaimEvent.yaml @@ -0,0 +1,17 @@ +allOf: + - $ref: '#/components/schemas/ClaimEventKey' + - type: object + x-go-is-request: true + required: + - attributes + properties: + attributes: + type: object + required: + - user_did + - status + properties: + status: + type: string + description: New status. Just to be JSON:API compliant. + enum: [ claimed ] diff --git a/docs/spec/components/schemas/ClaimEventKey.yaml b/docs/spec/components/schemas/ClaimEventKey.yaml new file mode 100644 index 0000000..1d52c55 --- /dev/null +++ b/docs/spec/components/schemas/ClaimEventKey.yaml @@ -0,0 +1,11 @@ +type: object +required: + - id + - type +properties: + id: + type: string + example: "157801" + type: + type: string + enum: [ claim_event ] diff --git a/docs/spec/components/schemas/CreateBalance.yaml b/docs/spec/components/schemas/CreateBalance.yaml new file mode 100644 index 0000000..d8d51d4 --- /dev/null +++ b/docs/spec/components/schemas/CreateBalance.yaml @@ -0,0 +1,16 @@ +allOf: + - $ref: '#/components/schemas/CreateBalanceKey' + - type: object + x-go-is-request: true + required: + - attributes + properties: + attributes: + type: object + required: + - user_did + properties: + user_did: + type: string + description: DID of the balance owner + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" diff --git a/docs/spec/components/schemas/CreateBalanceKey.yaml b/docs/spec/components/schemas/CreateBalanceKey.yaml new file mode 100644 index 0000000..781ec34 --- /dev/null +++ b/docs/spec/components/schemas/CreateBalanceKey.yaml @@ -0,0 +1,7 @@ +type: object +required: + - type +properties: + type: + type: string + enum: [ create_balance ] diff --git a/docs/spec/components/schemas/Event.yaml b/docs/spec/components/schemas/Event.yaml index 5433c42..aeabba1 100644 --- a/docs/spec/components/schemas/Event.yaml +++ b/docs/spec/components/schemas/Event.yaml @@ -3,6 +3,7 @@ allOf: - type: object required: - attributes + - relationships properties: attributes: type: object @@ -29,3 +30,15 @@ allOf: This is necessary, as the reward might change over time, while the certain balance should be left intact. example: 50 + relationships: + type: object + required: + - balance + properties: + balance: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/BalanceKey' diff --git a/docs/spec/paths/integrations@points-svc@balance.yaml b/docs/spec/paths/integrations@points-svc@balance.yaml index f8d1e48..f18a5cb 100644 --- a/docs/spec/paths/integrations@points-svc@balance.yaml +++ b/docs/spec/paths/integrations@points-svc@balance.yaml @@ -6,6 +6,8 @@ get: Balance of authorized user who makes the request. Rank in leaderboard is included. You should create new balance for the new user by making POST request. operationId: getPointsBalance + parameters: + - $ref: '#/components/parameters/filterDID' responses: 200: description: Success @@ -34,6 +36,16 @@ post: This operation might be time-consuming, because `open` events should be added for the new account synchronously (to display them right after the request). operationId: createPointsBalance + requestBody: + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/CreateBalance' responses: 201: description: Created diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml index 0216c50..164ff26 100644 --- a/docs/spec/paths/integrations@points-svc@events.yaml +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -5,6 +5,7 @@ get: description: Returns events for a single user. operationId: getEvents parameters: + - $ref: '#/components/parameters/filterDID' - in: query name: 'filter[status]' description: | @@ -25,9 +26,10 @@ get: schema: type: boolean example: true - - $ref: '#/components/parameters/pageLimitParam' - - $ref: '#/components/parameters/pageCursorParam' - - $ref: '#/components/parameters/sortingParam' + - $ref: '#/components/parameters/includeBalance' + - $ref: '#/components/parameters/pageLimit' + - $ref: '#/components/parameters/pageCursor' + - $ref: '#/components/parameters/pageOrder' responses: 200: description: Success diff --git a/docs/spec/paths/integrations@points-svc@events@{id}.yaml b/docs/spec/paths/integrations@points-svc@events@{id}.yaml index 26c67d0..536e359 100644 --- a/docs/spec/paths/integrations@points-svc@events@{id}.yaml +++ b/docs/spec/paths/integrations@points-svc@events@{id}.yaml @@ -2,7 +2,9 @@ patch: tags: - Events summary: Claim points for event - description: Update event status to _claimed_ and accrue points. + description: | + Update event status to _claimed_ and accrue points. + User must be authorized, and event must be _fulfilled_ by him. operationId: claimEvent parameters: - in: path @@ -12,8 +14,12 @@ patch: type: string example: "157801" responses: - 204: - description: No content + 200: + description: Event claimed, points accrued + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ClaimEvent' 400: $ref: '#/components/responses/invalidParameter' 401: diff --git a/resources/model_claim_event.go b/resources/model_claim_event.go new file mode 100644 index 0000000..4b8fe7b --- /dev/null +++ b/resources/model_claim_event.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type ClaimEvent struct { + Key + Attributes ClaimEventAttributes `json:"attributes"` +} +type ClaimEventRequest struct { + Data ClaimEvent `json:"data"` + Included Included `json:"included"` +} + +type ClaimEventListRequest struct { + Data []ClaimEvent `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *ClaimEventListRequest) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *ClaimEventListRequest) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustClaimEvent - returns ClaimEvent from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustClaimEvent(key Key) *ClaimEvent { + var claimEvent ClaimEvent + if c.tryFindEntry(key, &claimEvent) { + return &claimEvent + } + return nil +} diff --git a/resources/model_claim_event_attributes.go b/resources/model_claim_event_attributes.go new file mode 100644 index 0000000..ec7e93f --- /dev/null +++ b/resources/model_claim_event_attributes.go @@ -0,0 +1,10 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type ClaimEventAttributes struct { + // New status. Just to be JSON:API compliant. + Status string `json:"status"` +} diff --git a/resources/model_create_balance.go b/resources/model_create_balance.go new file mode 100644 index 0000000..e3ae5ec --- /dev/null +++ b/resources/model_create_balance.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type CreateBalance struct { + Key + Attributes CreateBalanceAttributes `json:"attributes"` +} +type CreateBalanceRequest struct { + Data CreateBalance `json:"data"` + Included Included `json:"included"` +} + +type CreateBalanceListRequest struct { + Data []CreateBalance `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *CreateBalanceListRequest) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *CreateBalanceListRequest) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustCreateBalance - returns CreateBalance from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustCreateBalance(key Key) *CreateBalance { + var createBalance CreateBalance + if c.tryFindEntry(key, &createBalance) { + return &createBalance + } + return nil +} diff --git a/resources/model_create_balance_attributes.go b/resources/model_create_balance_attributes.go new file mode 100644 index 0000000..c9fb8a1 --- /dev/null +++ b/resources/model_create_balance_attributes.go @@ -0,0 +1,10 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type CreateBalanceAttributes struct { + // DID of the balance owner + UserDid string `json:"user_did"` +} diff --git a/resources/model_event.go b/resources/model_event.go index 4fb0991..534160b 100644 --- a/resources/model_event.go +++ b/resources/model_event.go @@ -8,7 +8,8 @@ import "encoding/json" type Event struct { Key - Attributes EventAttributes `json:"attributes"` + Attributes EventAttributes `json:"attributes"` + Relationships EventRelationships `json:"relationships"` } type EventResponse struct { Data Event `json:"data"` diff --git a/resources/model_event_relationships.go b/resources/model_event_relationships.go new file mode 100644 index 0000000..b4547ea --- /dev/null +++ b/resources/model_event_relationships.go @@ -0,0 +1,9 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type EventRelationships struct { + Balance Relation `json:"balance"` +} diff --git a/resources/model_resource_type.go b/resources/model_resource_type.go index f5c17da..a029c42 100644 --- a/resources/model_resource_type.go +++ b/resources/model_resource_type.go @@ -8,6 +8,8 @@ type ResourceType string // List of ResourceType const ( - BALANCE ResourceType = "balance" - EVENT ResourceType = "event" + BALANCE ResourceType = "balance" + CLAIM_EVENT ResourceType = "claim_event" + CREATE_BALANCE ResourceType = "create_balance" + EVENT ResourceType = "event" ) From 4c72cab3d824d8474a2b17762f1739e8d7102eaa Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 14:38:46 +0200 Subject: [PATCH 30/63] Add events filter by type name --- docs/spec/paths/integrations@points-svc@events.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml index 164ff26..daa5489 100644 --- a/docs/spec/paths/integrations@points-svc@events.yaml +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -19,6 +19,15 @@ get: items: type: string enum: [open, fulfilled, claimed] + - in: query + name: 'filter[meta.static.name]' + description: Filter by event type name. Possible values should be hard-coded in the client. + required: false + schema: + type: array + items: + type: string + example: "create_org" - in: query name: count description: Count total number of events for a single user, applying filters. From 8d3ddcafd57658b0a2dcbed027bc5f11813f405e Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 15:10:45 +0200 Subject: [PATCH 31/63] Fix missing request body and response in docs --- .../paths/integrations@points-svc@events.yaml | 4 ++++ .../integrations@points-svc@events@{id}.yaml | 23 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml index daa5489..4a540d9 100644 --- a/docs/spec/paths/integrations@points-svc@events.yaml +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -53,6 +53,10 @@ get: type: array items: $ref: '#/components/schemas/Event' + included: + type: array + items: + $ref: '#/components/schemas/Balance' meta: type: object required: diff --git a/docs/spec/paths/integrations@points-svc@events@{id}.yaml b/docs/spec/paths/integrations@points-svc@events@{id}.yaml index 536e359..a3e073b 100644 --- a/docs/spec/paths/integrations@points-svc@events@{id}.yaml +++ b/docs/spec/paths/integrations@points-svc@events@{id}.yaml @@ -13,13 +13,34 @@ patch: schema: type: string example: "157801" + requestBody: + required: true + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/ClaimEvent' responses: 200: description: Event claimed, points accrued content: application/vnd.api+json: schema: - $ref: '#/components/schemas/ClaimEvent' + type: object + required: + - data + - included + properties: + data: + $ref: '#/components/schemas/Event' + included: + type: array + items: + $ref: '#/components/schemas/Balance' 400: $ref: '#/components/responses/invalidParameter' 401: From ecf4e986cd2fe60fe7c069c4248e66cc34ac0a65 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 15:33:08 +0200 Subject: [PATCH 32/63] =?UTF-8?q?Do=20not=20include=20event=20in=20events?= =?UTF-8?q?=20list=20to=20reduce=20response=20size=20because=20of=20relati?= =?UTF-8?q?onships=20=F0=9F=A4=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/spec/components/parameters/includeBalance.yaml | 9 --------- docs/spec/components/schemas/Event.yaml | 1 - docs/spec/paths/integrations@points-svc@events.yaml | 5 ----- resources/model_event.go | 4 ++-- 4 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 docs/spec/components/parameters/includeBalance.yaml diff --git a/docs/spec/components/parameters/includeBalance.yaml b/docs/spec/components/parameters/includeBalance.yaml deleted file mode 100644 index bc3cd01..0000000 --- a/docs/spec/components/parameters/includeBalance.yaml +++ /dev/null @@ -1,9 +0,0 @@ -in: query -name: include -description: Include user balance after updating -required: false -schema: - type: array - items: - type: string - enum: [ balance ] diff --git a/docs/spec/components/schemas/Event.yaml b/docs/spec/components/schemas/Event.yaml index aeabba1..e43ddc1 100644 --- a/docs/spec/components/schemas/Event.yaml +++ b/docs/spec/components/schemas/Event.yaml @@ -3,7 +3,6 @@ allOf: - type: object required: - attributes - - relationships properties: attributes: type: object diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml index 4a540d9..b63b88b 100644 --- a/docs/spec/paths/integrations@points-svc@events.yaml +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -35,7 +35,6 @@ get: schema: type: boolean example: true - - $ref: '#/components/parameters/includeBalance' - $ref: '#/components/parameters/pageLimit' - $ref: '#/components/parameters/pageCursor' - $ref: '#/components/parameters/pageOrder' @@ -53,10 +52,6 @@ get: type: array items: $ref: '#/components/schemas/Event' - included: - type: array - items: - $ref: '#/components/schemas/Balance' meta: type: object required: diff --git a/resources/model_event.go b/resources/model_event.go index 534160b..dde1c7c 100644 --- a/resources/model_event.go +++ b/resources/model_event.go @@ -8,8 +8,8 @@ import "encoding/json" type Event struct { Key - Attributes EventAttributes `json:"attributes"` - Relationships EventRelationships `json:"relationships"` + Attributes EventAttributes `json:"attributes"` + Relationships *EventRelationships `json:"relationships,omitempty"` } type EventResponse struct { Data Event `json:"data"` From 3910d84c799f8a81d10754b7fb17a8853ed7a282 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 16:42:47 +0200 Subject: [PATCH 33/63] =?UTF-8?q?Edit=20API=20according=20to=20new=20JSON:?= =?UTF-8?q?API=20compliant=20docs=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../paths/integrations@points-svc@events.yaml | 2 +- go.mod | 64 ++++++---- go.sum | 83 ++++++++++++ internal/data/main.go | 1 + internal/data/pg/events.go | 9 ++ internal/service/handlers/claim_event.go | 118 ++++++++++++++---- internal/service/handlers/create_balance.go | 12 +- internal/service/handlers/ctx.go | 12 +- internal/service/handlers/get_balance.go | 15 ++- internal/service/handlers/list_events.go | 62 ++++----- internal/service/handlers/middleware.go | 20 +-- internal/service/requests/claim_event.go | 26 ++++ internal/service/requests/create_balance.go | 23 ++++ internal/service/requests/get_balance.go | 26 ++++ internal/service/requests/list_events.go | 3 + 15 files changed, 371 insertions(+), 105 deletions(-) create mode 100644 internal/service/requests/claim_event.go create mode 100644 internal/service/requests/create_balance.go create mode 100644 internal/service/requests/get_balance.go diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@points-svc@events.yaml index b63b88b..806de93 100644 --- a/docs/spec/paths/integrations@points-svc@events.yaml +++ b/docs/spec/paths/integrations@points-svc@events.yaml @@ -1,7 +1,7 @@ get: tags: - Events - summary: Get events + summary: List events description: Returns events for a single user. operationId: getEvents parameters: diff --git a/go.mod b/go.mod index 63220be..5e3e88f 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,8 @@ require ( github.com/Masterminds/squirrel v1.4.0 github.com/alecthomas/kingpin v2.2.6+incompatible github.com/go-chi/chi v4.1.2+incompatible - github.com/go-ozzo/ozzo-validation/v4 v4.2.1 - github.com/rarimo/rarime-auth-svc v0.0.1-rc8 + github.com/go-ozzo/ozzo-validation/v4 v4.3.0 + github.com/rarimo/rarime-auth-svc v0.0.1-rc9 github.com/rubenv/sql-migrate v1.6.1 gitlab.com/distributed_lab/ape v1.7.1 gitlab.com/distributed_lab/figure/v3 v3.1.3 @@ -22,56 +22,70 @@ require ( github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect - github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/ethereum/go-ethereum v1.13.8 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/ethereum/go-ethereum v1.13.11 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/raven-go v0.2.0 // indirect - github.com/getsentry/sentry-go v0.7.0 // indirect + github.com/getsentry/sentry-go v0.26.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect - github.com/go-ole/go-ole v1.2.5 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect - github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/jsonapi v1.0.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect + github.com/iden3/go-iden3-core v1.0.2 // indirect + github.com/iden3/go-iden3-crypto v0.0.15 // indirect + github.com/iden3/go-rapidsnark/types v0.0.3 // indirect + github.com/iden3/go-rapidsnark/verifier v0.0.5 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.7 // indirect - github.com/magiconair/properties v1.8.0 // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/pelletier/go-toml v1.2.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - github.com/spf13/afero v1.1.2 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/jwalterweatherman v1.0.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.3.2 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect gitlab.com/distributed_lab/figure v2.1.0+incompatible // indirect - gitlab.com/distributed_lab/lorem v0.2.0 // indirect + gitlab.com/distributed_lab/lorem v0.2.1 // indirect gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.15.0 // indirect + golang.org/x/tools v0.17.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 88b41ac..400ec57 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= @@ -33,10 +34,14 @@ github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsy github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= +github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= @@ -77,6 +82,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= @@ -87,6 +94,8 @@ github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/ethereum/go-ethereum v1.13.11 h1:b51Dsm+rEg7anFRUMGB8hODXHvNfcRKzz9vcj8wSdUs= +github.com/ethereum/go-ethereum v1.13.11/go.mod h1:gFtlVORuUcT+UUIcJ/veCNjkuOSujCi338uSHJrYAew= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= @@ -94,9 +103,12 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+ github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= @@ -106,6 +118,8 @@ github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JY github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/sentry-go v0.7.0 h1:MR2yfR4vFfv/2+iBuSnkdQwVg7N9cJzihZ6KJu7srwQ= github.com/getsentry/sentry-go v0.7.0/go.mod h1:pLFpD2Y5RHIKF9Bw3KH6/68DeN2K/XBJd8awjdPnUwg= +github.com/getsentry/sentry-go v0.26.0 h1:IX3++sF6/4B5JcevhdZfdKIHfyvMmAq/UnqcyT2H6mA= +github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= @@ -118,8 +132,11 @@ github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpj github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ozzo/ozzo-validation/v4 v4.2.1 h1:XALUNshPYumA7UShB7iM3ZVlqIBn0jfwjqAMIoyE1N0= github.com/go-ozzo/ozzo-validation/v4 v4.2.1/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= +github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= +github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -148,9 +165,13 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 h1:aQ4kMXDAmP9IRIZHcSKB2orXHGwGiSxH4PX1BzKHR50= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= +github.com/google/jsonapi v1.0.0 h1:qIGgO5Smu3yJmSs+QlvhQnrscdZfFhiV6S8ryJAglqU= +github.com/google/jsonapi v1.0.0/go.mod h1:YYHiRPJT8ARXGER8In9VuLv4qvLfDmA9ULQqptbLE4s= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -169,6 +190,14 @@ github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/iden3/go-iden3-core v1.0.2 h1:HwNDFeqcUv4ybZj5tH+58JKWKarn/qqBpNCqTLxGP0Y= +github.com/iden3/go-iden3-core v1.0.2/go.mod h1:X4PjlJG8OsEQEsSbzzYqqAk2olYGZ2nuGqiUPyEYjOo= +github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= +github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= +github.com/iden3/go-rapidsnark/types v0.0.3 h1:f0s1Qdut1qHe1O67+m+xUVRBPwSXnq5j0xSrBi0jqM4= +github.com/iden3/go-rapidsnark/types v0.0.3/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= +github.com/iden3/go-rapidsnark/verifier v0.0.5 h1:J7y0ovrEjDQoWtZmlrp4tgGng1A9faMeYsQH4igAEqA= +github.com/iden3/go-rapidsnark/verifier v0.0.5/go.mod h1:KgL3Yr9NehlFDI4EIWVLE3UDUi8ulyjbp7HcXSBfiGI= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -219,6 +248,8 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -242,6 +273,8 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= @@ -250,6 +283,8 @@ github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFV github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= @@ -262,6 +297,10 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -281,6 +320,8 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rarimo/rarime-auth-svc v0.0.1-rc8 h1:MBx51/ynR8BaRz5HvcbatYe4hnB2ZDVwM7cmGEepg+Y= github.com/rarimo/rarime-auth-svc v0.0.1-rc8/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= +github.com/rarimo/rarime-auth-svc v0.0.1-rc9 h1:JZfq1q3WaaLwa8ICk8RHEx4+ojl/JBE8N5zJ/uHZUwM= +github.com/rarimo/rarime-auth-svc v0.0.1-rc9/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -295,6 +336,10 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= @@ -302,32 +347,49 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -374,17 +436,27 @@ gitlab.com/distributed_lab/logan v3.8.1+incompatible h1:bYiP3P0AA0cpAL/fyOYWGq1a gitlab.com/distributed_lab/logan v3.8.1+incompatible/go.mod h1:25oL/FPFXmyYzWeA6vahMvnFJV8P7mOx0jZhRP7nhlc= gitlab.com/distributed_lab/lorem v0.2.0 h1:Rc7Ef3eGSpei8EtWcV6fzPW3O/QEF2zgZR4+hV8WJAw= gitlab.com/distributed_lab/lorem v0.2.0/go.mod h1:wkzrGoB1L/yUBu56SfoJ/vNiPqiHZcg75AnBkWNcjhQ= +gitlab.com/distributed_lab/lorem v0.2.1 h1:A1QoiEDRN3vlPrwsXJmPlENanQwu3FxpDl5vE4DT5qg= +gitlab.com/distributed_lab/lorem v0.2.1/go.mod h1:wkzrGoB1L/yUBu56SfoJ/vNiPqiHZcg75AnBkWNcjhQ= gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c h1:cpIjV8C//7sLVvMcBaFGopI8sMcCw8Za7T0HIf52esU= gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c/go.mod h1:4TnADX84dQjQMRHKIMPCVL0L97rD/Jxv0xDbrN6aKzk= gitlab.com/distributed_lab/urlval/v4 v4.0.3 h1:ZgdSBcvaoHBYmgze/u0bYfvq5Xx47pGTdfFmMYxn27s= gitlab.com/distributed_lab/urlval/v4 v4.0.3/go.mod h1:IdRM8gOyzpXNoAkIKWVwN+dChh6+1TioS/SVhTGvRFA= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -399,9 +471,12 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -416,10 +491,13 @@ golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -427,12 +505,15 @@ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= @@ -445,6 +526,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= diff --git a/internal/data/main.go b/internal/data/main.go index fcf3035..306209e 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -32,6 +32,7 @@ type EventsQ interface { FilterByID(string) EventsQ FilterByBalanceID(...string) EventsQ FilterByStatus(...EventStatus) EventsQ + FilterByType(...string) EventsQ } type BalancesQ interface { diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 803925c..528439f 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -123,3 +123,12 @@ func (q *events) FilterByStatus(statuses ...data.EventStatus) data.EventsQ { q.counter = q.counter.Where(squirrel.Eq{"status": statuses}) return q } + +func (q *events) FilterByType(types ...string) data.EventsQ { + if len(types) == 0 { + return q + } + q.selector = q.selector.Where(squirrel.Eq{"type": types}) + q.counter = q.counter.Where(squirrel.Eq{"type": types}) + return q +} diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index f4b8315..3b22691 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -2,71 +2,145 @@ package handlers import ( "database/sql" + "fmt" "net/http" - "github.com/go-chi/chi" + "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/service/requests" + "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) func ClaimEvent(w http.ResponseWriter, r *http.Request) { - did := UserDID(r) - eventID := chi.URLParam(r, "id") - if eventID == "" { - ape.RenderErr(w, problems.BadRequest(nil)...) + req, err := requests.NewClaimEvent(r) + if err != nil { + ape.RenderErr(w, problems.BadRequest(err)...) return } - balance := getBalanceByDID(did, false, w, r) + event := getEventToClaim(req.Data.ID, w, r) + if event == nil { + return + } + balance := getBalanceByID(event.BalanceID, true, w, r) if balance == nil { return } + evType := EventTypes(r).Get(event.Type) + if evType == nil { + Log(r).Error("Wrong event type is stored in DB: might be bad event config") + ape.RenderErr(w, problems.InternalError()) + return + } + + event = claimEventWithPoints(*event, balance.Amount, int(evType.Reward), w, r) + if event == nil { + return + } + // can't return balance on update, see create_balance.go + balance = getBalanceByID(event.BalanceID, true, w, r) + if balance == nil { + return + } + + ape.Render(w, newClaimEventResponse(*event, *evType, *balance)) +} + +func getEventToClaim(id string, w http.ResponseWriter, r *http.Request) *data.Event { event, err := EventsQ(r). - FilterByID(eventID). - FilterByBalanceID(balance.ID). + FilterByID(id). FilterByStatus(data.EventFulfilled). Get() if err != nil { Log(r).WithError(err).Error("Failed to get event by balance ID") ape.RenderErr(w, problems.InternalError()) - return + return nil } + if event == nil { - Log(r).Debugf("Event not found for id=%s balance_id=%s status=%s", eventID, balance.ID, data.EventFulfilled) + Log(r).Debugf("Event not found for id=%s status=%s", id, data.EventFulfilled) ape.RenderErr(w, problems.NotFound()) - return + return nil } - evType := EventTypes(r).Get(event.Type) - if evType == nil { - Log(r).Error("Wrong event type is stored in DB: might be bad event config") + return event +} + +func getBalanceByID(id string, doAuth bool, w http.ResponseWriter, r *http.Request) *data.Balance { + balance, err := BalancesQ(r).WithRank().FilterByID(id).Get() + + if err != nil || balance == nil { + if err == nil { + err = fmt.Errorf("DB constraint violation: found event with balance_id=%s not present", id) + } + + Log(r).WithError(err).Error("Failed to get balance by ID") ape.RenderErr(w, problems.InternalError()) - return + return nil } - err = EventsQ(r).Update(data.Event{ + if doAuth && !auth.Authenticates(UserClaims(r), auth.UserGrant(balance.DID)) { + ape.RenderErr(w, problems.Unauthorized()) + return nil + } + + return balance +} + +func claimEventWithPoints(event data.Event, currBalance, reward int, w http.ResponseWriter, r *http.Request) *data.Event { + claimed := data.Event{ ID: event.ID, Status: data.EventClaimed, PointsAmount: sql.NullInt32{ - Int32: evType.Reward, + Int32: int32(reward), Valid: true, }, - }) + } + + err := EventsQ(r).Update(claimed) if err != nil { Log(r).WithError(err).Error("Failed to claim event") ape.RenderErr(w, problems.InternalError()) - return + return nil } - err = BalancesQ(r).FilterByID(balance.ID).UpdateAmount(int(evType.Reward)) + err = BalancesQ(r).FilterByID(event.BalanceID).UpdateAmount(currBalance + reward) if err != nil { Log(r).WithError(err).Error("Failed to accrue points to the balance") ape.RenderErr(w, problems.InternalError()) - return + return nil } + // While we don't have updated_at and other special attributes in events, we can + // safely return the same struct without redundant queries. It is still faster + // than with RETURNING clause. + event.Status = claimed.Status + event.PointsAmount = claimed.PointsAmount + return &event +} + +func newClaimEventResponse( + event data.Event, + meta resources.EventStaticMeta, + balance data.Balance, +) resources.EventResponse { + + eventModel := newEventModel(event, meta) + eventModel.Relationships = &resources.EventRelationships{ + Balance: resources.Relation{ + Data: &resources.Key{ + ID: balance.ID, + Type: resources.BALANCE, + }, + }, + } + + resp := resources.EventResponse{Data: eventModel} + inc := newBalanceModel(balance) + resp.Included.Add(&inc) - w.WriteHeader(http.StatusNoContent) + return resp } diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index 7230d22..8ed5fc5 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -5,21 +5,27 @@ import ( "net/http" "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/service/requests" "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) func CreateBalance(w http.ResponseWriter, r *http.Request) { - did := UserDID(r) + req, err := requests.NewCreateBalance(r) + if err != nil { + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + did := req.Data.Attributes.UserDid balance := getBalanceByDID(did, false, w, r) if balance != nil { ape.RenderErr(w, problems.Conflict()) return } - if err := BalancesQ(r).Insert(data.Balance{DID: did}); err != nil { + if err = BalancesQ(r).Insert(data.Balance{DID: did}); err != nil { Log(r).WithError(err).Error("Failed to create balance") ape.RenderErr(w, problems.InternalError()) return @@ -32,7 +38,7 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - err := EventsQ(r).Insert(prepareOpenEvents(balance.ID, EventTypes(r).List())...) + err = EventsQ(r).Insert(prepareOpenEvents(balance.ID, EventTypes(r).List())...) if err != nil { Log(r).WithError(err).Error("Failed to add open events") ape.RenderErr(w, problems.InternalError()) diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index 756e9cd..16b5fb3 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -4,6 +4,7 @@ import ( "context" "net/http" + "github.com/rarimo/rarime-auth-svc/resources" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" "gitlab.com/distributed_lab/logan/v3" @@ -16,8 +17,7 @@ const ( eventsQCtxKey balancesQCtxKey eventTypesCtxKey - userClaimCtxKey - userDidCtxKey + userClaimsCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -60,12 +60,12 @@ func EventTypes(r *http.Request) evtypes.Types { return r.Context().Value(eventTypesCtxKey).(evtypes.Types) } -func CtxUserDID(did string) func(context.Context) context.Context { +func CtxUserClaims(claim []resources.Claim) func(context.Context) context.Context { return func(ctx context.Context) context.Context { - return context.WithValue(ctx, userDidCtxKey, did) + return context.WithValue(ctx, userClaimsCtxKey, claim) } } -func UserDID(r *http.Request) string { - return r.Context().Value(userDidCtxKey).(string) +func UserClaims(r *http.Request) []resources.Claim { + return r.Context().Value(userClaimsCtxKey).([]resources.Claim) } diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go index c5e1cdb..84744b6 100644 --- a/internal/service/handlers/get_balance.go +++ b/internal/service/handlers/get_balance.go @@ -3,16 +3,22 @@ package handlers import ( "net/http" + "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/service/requests" "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) func GetBalance(w http.ResponseWriter, r *http.Request) { - did := UserDID(r) + req, err := requests.NewGetBalance(r) + if err != nil { + ape.RenderErr(w, problems.BadRequest(err)...) + return + } - balance := getBalanceByDID(did, true, w, r) + balance := getBalanceByDID(req.FilterDID, true, w, r) if balance == nil { return } @@ -36,6 +42,11 @@ func newBalanceModel(balance data.Balance) resources.Balance { } func getBalanceByDID(did string, withRank bool, w http.ResponseWriter, r *http.Request) *data.Balance { + if !auth.Authenticates(UserClaims(r), auth.UserGrant(did)) { + ape.RenderErr(w, problems.Unauthorized()) + return nil + } + q := BalancesQ(r).FilterByUserDID(did) if withRank { q.WithRank() diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index 207e48b..b27bf45 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -18,8 +18,7 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { return } - did := UserDID(r) - balance := getBalanceByDID(did, false, w, r) + balance := getBalanceByDID(req.FilterDID, false, w, r) if balance == nil { return } @@ -27,6 +26,7 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { events, err := EventsQ(r). FilterByBalanceID(balance.ID). FilterByStatus(req.FilterStatus...). + FilterByType(req.FilterType...). Page(&req.CursorPageParams). Select() if err != nil { @@ -40,6 +40,7 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { eventsCount, err = EventsQ(r). FilterByBalanceID(balance.ID). FilterByStatus(req.FilterStatus...). + FilterByType(req.FilterType...). Count() if err != nil { Log(r).WithError(err).Error("Failed to count events") @@ -84,36 +85,39 @@ func getOrderedEventsMeta(events []data.Event, w http.ResponseWriter, r *http.Re return res, true } -func newEventsResponse(events []data.Event, meta []resources.EventStaticMeta) *resources.EventListResponse { - list := make([]resources.Event, len(events)) - - for i, event := range events { - var dynamic *json.RawMessage - if event.Meta.Valid { - d := json.RawMessage(event.Meta.String) - dynamic = &d - } +func newEventModel(event data.Event, meta resources.EventStaticMeta) resources.Event { + var dynamic *json.RawMessage + if event.Meta.Valid { + d := json.RawMessage(event.Meta.String) + dynamic = &d + } - var points *int32 - if event.PointsAmount.Valid { - points = &event.PointsAmount.Int32 - } + var points *int32 + if event.PointsAmount.Valid { + points = &event.PointsAmount.Int32 + } - list[i] = resources.Event{ - Key: resources.Key{ - ID: event.ID, - Type: resources.EVENT, + return resources.Event{ + Key: resources.Key{ + ID: event.ID, + Type: resources.EVENT, + }, + Attributes: resources.EventAttributes{ + CreatedAt: event.CreatedAt, + Meta: resources.EventMeta{ + Static: meta, + Dynamic: dynamic, }, - Attributes: resources.EventAttributes{ - CreatedAt: event.CreatedAt, - Meta: resources.EventMeta{ - Static: meta[i], - Dynamic: dynamic, - }, - Status: event.Status.String(), - PointsAmount: points, - }, - } + Status: event.Status.String(), + PointsAmount: points, + }, + } +} + +func newEventsResponse(events []data.Event, meta []resources.EventStaticMeta) *resources.EventListResponse { + list := make([]resources.Event, len(events)) + for i, event := range events { + list[i] = newEventModel(event, meta[i]) } return &resources.EventListResponse{Data: list} diff --git a/internal/service/handlers/middleware.go b/internal/service/handlers/middleware.go index 3d074b1..376f438 100644 --- a/internal/service/handlers/middleware.go +++ b/internal/service/handlers/middleware.go @@ -12,8 +12,7 @@ import ( func AuthMiddleware(auth *auth.Client, log *logan.Entry) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // in current implementation any error is internal, despite the status - claims, _, err := auth.ValidateJWT(r.Header) + claims, err := auth.ValidateJWT(r.Header) if err != nil { log.WithError(err).Error("failed to execute auth validate request") ape.Render(w, problems.InternalError()) @@ -21,24 +20,11 @@ func AuthMiddleware(auth *auth.Client, log *logan.Entry) func(http.Handler) http } if len(claims) == 0 { - log.Debug("No claims returned for user") - ape.RenderErr(w, problems.Unauthorized()) - return - } - if len(claims) > 1 { - log.Errorf("Expected 1 claim to get user DID from, got %d claims", len(claims)) - ape.RenderErr(w, problems.InternalError()) - return - } - - claim := claims[0] - if claim.User == "" { - log.Debug("No user DID found in claim") - ape.RenderErr(w, problems.Unauthorized()) + ape.Render(w, problems.Unauthorized()) return } - ctx := CtxUserDID(claim.User)(r.Context()) + ctx := CtxUserClaims(claims)(r.Context()) next.ServeHTTP(w, r.WithContext(ctx)) }) } diff --git a/internal/service/requests/claim_event.go b/internal/service/requests/claim_event.go new file mode 100644 index 0000000..f74e365 --- /dev/null +++ b/internal/service/requests/claim_event.go @@ -0,0 +1,26 @@ +package requests + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/go-chi/chi" + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/resources" +) + +func NewClaimEvent(r *http.Request) (req resources.ClaimEventRequest, err error) { + id := chi.URLParam(r, "id") + if err = json.NewDecoder(r.Body).Decode(&req); err != nil { + err = fmt.Errorf("decode request body: %w", err) + return + } + + return req, validation.Errors{ + "data/id": validation.Validate(req.Data.ID, validation.Required, validation.In(id)), + "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.CLAIM_EVENT)), + "data/attributes/status": validation.Validate(req.Data.Attributes.Status, validation.Required, validation.In(data.EventClaimed)), + }.Filter() +} diff --git a/internal/service/requests/create_balance.go b/internal/service/requests/create_balance.go new file mode 100644 index 0000000..298c7c2 --- /dev/null +++ b/internal/service/requests/create_balance.go @@ -0,0 +1,23 @@ +package requests + +import ( + "encoding/json" + "fmt" + "net/http" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-points-svc/resources" +) + +func NewCreateBalance(r *http.Request) (req resources.CreateBalanceRequest, err error) { + if err = json.NewDecoder(r.Body).Decode(&req); err != nil { + err = fmt.Errorf("decode request body: %w", err) + return + } + + return req, validation.Errors{ + "data/id": validation.Validate(req.Data.ID, validation.Empty), + "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.CREATE_BALANCE)), + "data/attributes/user_did": validation.Validate(req.Data.Attributes.UserDid, validation.Required), + }.Filter() +} diff --git a/internal/service/requests/get_balance.go b/internal/service/requests/get_balance.go new file mode 100644 index 0000000..d450a7b --- /dev/null +++ b/internal/service/requests/get_balance.go @@ -0,0 +1,26 @@ +package requests + +import ( + "fmt" + "net/http" + + validation "github.com/go-ozzo/ozzo-validation/v4" + "gitlab.com/distributed_lab/urlval/v4" +) + +type GetBalance struct { + FilterDID string `filter:"did"` +} + +func NewGetBalance(r *http.Request) (req GetBalance, err error) { + if err = urlval.Decode(r.URL.Query(), &req); err != nil { + return req, validation.Errors{ + "query": fmt.Errorf("failed to decode query: %w", err), + } + } + + err = validation.Errors{ + "filter[did]": validation.Validate(req.FilterDID, validation.Required), + }.Filter() + return +} diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go index 02f0640..5faa580 100644 --- a/internal/service/requests/list_events.go +++ b/internal/service/requests/list_events.go @@ -12,7 +12,9 @@ import ( type ListEvents struct { page.CursorParams + FilterDID string `filter:"did"` FilterStatus []data.EventStatus `filter:"status"` + FilterType []string `filter:"meta.static.name"` Count bool `url:"count"` } @@ -24,6 +26,7 @@ func NewListEvents(r *http.Request) (req ListEvents, err error) { } err = validation.Errors{ + "filter[did]": validation.Validate(req.FilterDID, validation.Required), "filter[status]": validation.Validate(req.FilterStatus, validation.Each(validation.In(data.EventOpen, data.EventFulfilled, data.EventClaimed))), }.Filter() return From 2218ba84b637cc22307d718a009428e2e1e200a6 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 16:52:36 +0200 Subject: [PATCH 34/63] =?UTF-8?q?Add=20indexes=E2=98=9D=EF=B8=8F=20to=20ev?= =?UTF-8?q?ents,=20make=20balance=5Fid=20not=20nullable=20=F0=9F=90=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/assets/migrations/001_initial.sql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index d29d4f9..53dc265 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -12,7 +12,7 @@ CREATE TYPE event_status AS ENUM ('open', 'fulfilled', 'claimed'); CREATE TABLE IF NOT EXISTS events ( id serial PRIMARY KEY, - balance_id integer null REFERENCES balances (id), + balance_id integer not null REFERENCES balances (id), type text not null, status event_status not null, created_at timestamp without time zone not null default NOW(), @@ -20,7 +20,12 @@ CREATE TABLE IF NOT EXISTS events points_amount integer ); +CREATE INDEX IF NOT EXISTS events_balance_id_index ON events using btree (balance_id); +CREATE INDEX IF NOT EXISTS events_type_index ON events using btree (type); + -- +migrate Down +DROP INDEX IF EXISTS events_type_index; +DROP INDEX IF EXISTS events_balance_id_index; DROP TABLE IF EXISTS events; DROP TYPE IF EXISTS event_status; DROP TABLE IF EXISTS balances; From f1951d849ce09a37b2f628ce322dd170ee284b3a Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 16:56:43 +0200 Subject: [PATCH 35/63] =?UTF-8?q?Fix=20deps=20broken=20for=20some=20reason?= =?UTF-8?q?=20=F0=9F=98=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 9 ------ go.sum | 87 +++++++++++----------------------------------------------- 2 files changed, 16 insertions(+), 80 deletions(-) diff --git a/go.mod b/go.mod index 5e3e88f..f6dd9f5 100644 --- a/go.mod +++ b/go.mod @@ -42,10 +42,6 @@ require ( github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect - github.com/iden3/go-iden3-core v1.0.2 // indirect - github.com/iden3/go-iden3-crypto v0.0.15 // indirect - github.com/iden3/go-rapidsnark/types v0.0.3 // indirect - github.com/iden3/go-rapidsnark/verifier v0.0.5 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -53,9 +49,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -65,7 +59,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect @@ -75,7 +68,6 @@ require ( gitlab.com/distributed_lab/figure v2.1.0+incompatible // indirect gitlab.com/distributed_lab/lorem v0.2.1 // indirect gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c // indirect - go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect @@ -85,7 +77,6 @@ require ( golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.17.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 400ec57..5caa962 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= @@ -32,13 +30,10 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -74,14 +69,13 @@ github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBS github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= @@ -92,8 +86,6 @@ github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZi github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= -github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= github.com/ethereum/go-ethereum v1.13.11 h1:b51Dsm+rEg7anFRUMGB8hODXHvNfcRKzz9vcj8wSdUs= github.com/ethereum/go-ethereum v1.13.11/go.mod h1:gFtlVORuUcT+UUIcJ/veCNjkuOSujCi338uSHJrYAew= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= @@ -101,12 +93,10 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= @@ -116,7 +106,6 @@ github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2Gihuqh github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/getsentry/sentry-go v0.7.0 h1:MR2yfR4vFfv/2+iBuSnkdQwVg7N9cJzihZ6KJu7srwQ= github.com/getsentry/sentry-go v0.7.0/go.mod h1:pLFpD2Y5RHIKF9Bw3KH6/68DeN2K/XBJd8awjdPnUwg= github.com/getsentry/sentry-go v0.26.0 h1:IX3++sF6/4B5JcevhdZfdKIHfyvMmAq/UnqcyT2H6mA= github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= @@ -125,15 +114,15 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-ozzo/ozzo-validation/v4 v4.2.1 h1:XALUNshPYumA7UShB7iM3ZVlqIBn0jfwjqAMIoyE1N0= github.com/go-ozzo/ozzo-validation/v4 v4.2.1/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= @@ -163,13 +152,10 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 h1:aQ4kMXDAmP9IRIZHcSKB2orXHGwGiSxH4PX1BzKHR50= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= github.com/google/jsonapi v1.0.0 h1:qIGgO5Smu3yJmSs+QlvhQnrscdZfFhiV6S8ryJAglqU= github.com/google/jsonapi v1.0.0/go.mod h1:YYHiRPJT8ARXGER8In9VuLv4qvLfDmA9ULQqptbLE4s= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -190,14 +176,6 @@ github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/iden3/go-iden3-core v1.0.2 h1:HwNDFeqcUv4ybZj5tH+58JKWKarn/qqBpNCqTLxGP0Y= -github.com/iden3/go-iden3-core v1.0.2/go.mod h1:X4PjlJG8OsEQEsSbzzYqqAk2olYGZ2nuGqiUPyEYjOo= -github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= -github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= -github.com/iden3/go-rapidsnark/types v0.0.3 h1:f0s1Qdut1qHe1O67+m+xUVRBPwSXnq5j0xSrBi0jqM4= -github.com/iden3/go-rapidsnark/types v0.0.3/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= -github.com/iden3/go-rapidsnark/verifier v0.0.5 h1:J7y0ovrEjDQoWtZmlrp4tgGng1A9faMeYsQH4igAEqA= -github.com/iden3/go-rapidsnark/verifier v0.0.5/go.mod h1:KgL3Yr9NehlFDI4EIWVLE3UDUi8ulyjbp7HcXSBfiGI= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -220,8 +198,8 @@ github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6i github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -246,7 +224,6 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -271,8 +248,6 @@ github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQ github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -283,8 +258,6 @@ github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFV github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= @@ -295,10 +268,7 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -306,8 +276,9 @@ github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTw github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= @@ -318,8 +289,6 @@ github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuI github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rarimo/rarime-auth-svc v0.0.1-rc8 h1:MBx51/ynR8BaRz5HvcbatYe4hnB2ZDVwM7cmGEepg+Y= -github.com/rarimo/rarime-auth-svc v0.0.1-rc8/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= github.com/rarimo/rarime-auth-svc v0.0.1-rc9 h1:JZfq1q3WaaLwa8ICk8RHEx4+ojl/JBE8N5zJ/uHZUwM= github.com/rarimo/rarime-auth-svc v0.0.1-rc9/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= @@ -345,32 +314,24 @@ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= @@ -434,7 +395,6 @@ gitlab.com/distributed_lab/logan v3.7.2+incompatible/go.mod h1:25oL/FPFXmyYzWeA6 gitlab.com/distributed_lab/logan v3.8.0+incompatible/go.mod h1:25oL/FPFXmyYzWeA6vahMvnFJV8P7mOx0jZhRP7nhlc= gitlab.com/distributed_lab/logan v3.8.1+incompatible h1:bYiP3P0AA0cpAL/fyOYWGq1aiKw16vZFoJz+nwbqdvU= gitlab.com/distributed_lab/logan v3.8.1+incompatible/go.mod h1:25oL/FPFXmyYzWeA6vahMvnFJV8P7mOx0jZhRP7nhlc= -gitlab.com/distributed_lab/lorem v0.2.0 h1:Rc7Ef3eGSpei8EtWcV6fzPW3O/QEF2zgZR4+hV8WJAw= gitlab.com/distributed_lab/lorem v0.2.0/go.mod h1:wkzrGoB1L/yUBu56SfoJ/vNiPqiHZcg75AnBkWNcjhQ= gitlab.com/distributed_lab/lorem v0.2.1 h1:A1QoiEDRN3vlPrwsXJmPlENanQwu3FxpDl5vE4DT5qg= gitlab.com/distributed_lab/lorem v0.2.1/go.mod h1:wkzrGoB1L/yUBu56SfoJ/vNiPqiHZcg75AnBkWNcjhQ= @@ -442,19 +402,13 @@ gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c h1:cpIjV8C gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c/go.mod h1:4TnADX84dQjQMRHKIMPCVL0L97rD/Jxv0xDbrN6aKzk= gitlab.com/distributed_lab/urlval/v4 v4.0.3 h1:ZgdSBcvaoHBYmgze/u0bYfvq5Xx47pGTdfFmMYxn27s= gitlab.com/distributed_lab/urlval/v4 v4.0.3/go.mod h1:IdRM8gOyzpXNoAkIKWVwN+dChh6+1TioS/SVhTGvRFA= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= @@ -469,12 +423,9 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -490,12 +441,9 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -503,21 +451,18 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From d850ecc8f42670c35f0abc2d7f066d57c741e3bd Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 17:01:17 +0200 Subject: [PATCH 36/63] Rename points-svc to rarime-points-svc in docs --- ...c@balance.yaml => integrations@rarime-points-svc@balance.yaml} | 0 ...svc@events.yaml => integrations@rarime-points-svc@events.yaml} | 0 ...@{id}.yaml => integrations@rarime-points-svc@events@{id}.yaml} | 0 ...board.yaml => integrations@rarime-points-svc@leaderboard.yaml} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename docs/spec/paths/{integrations@points-svc@balance.yaml => integrations@rarime-points-svc@balance.yaml} (100%) rename docs/spec/paths/{integrations@points-svc@events.yaml => integrations@rarime-points-svc@events.yaml} (100%) rename docs/spec/paths/{integrations@points-svc@events@{id}.yaml => integrations@rarime-points-svc@events@{id}.yaml} (100%) rename docs/spec/paths/{integrations@points-svc@leaderboard.yaml => integrations@rarime-points-svc@leaderboard.yaml} (100%) diff --git a/docs/spec/paths/integrations@points-svc@balance.yaml b/docs/spec/paths/integrations@rarime-points-svc@balance.yaml similarity index 100% rename from docs/spec/paths/integrations@points-svc@balance.yaml rename to docs/spec/paths/integrations@rarime-points-svc@balance.yaml diff --git a/docs/spec/paths/integrations@points-svc@events.yaml b/docs/spec/paths/integrations@rarime-points-svc@events.yaml similarity index 100% rename from docs/spec/paths/integrations@points-svc@events.yaml rename to docs/spec/paths/integrations@rarime-points-svc@events.yaml diff --git a/docs/spec/paths/integrations@points-svc@events@{id}.yaml b/docs/spec/paths/integrations@rarime-points-svc@events@{id}.yaml similarity index 100% rename from docs/spec/paths/integrations@points-svc@events@{id}.yaml rename to docs/spec/paths/integrations@rarime-points-svc@events@{id}.yaml diff --git a/docs/spec/paths/integrations@points-svc@leaderboard.yaml b/docs/spec/paths/integrations@rarime-points-svc@leaderboard.yaml similarity index 100% rename from docs/spec/paths/integrations@points-svc@leaderboard.yaml rename to docs/spec/paths/integrations@rarime-points-svc@leaderboard.yaml From 423c6ecd73b62b868c9166216497cf687e4422b7 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 17:24:56 +0200 Subject: [PATCH 37/63] Allow docs deployment to be triggered manually --- .github/workflows/deploy-gh-pages.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy-gh-pages.yaml b/.github/workflows/deploy-gh-pages.yaml index d19e1e1..63f357d 100644 --- a/.github/workflows/deploy-gh-pages.yaml +++ b/.github/workflows/deploy-gh-pages.yaml @@ -5,6 +5,7 @@ name: Deploy to Github pages on: + workflow_dispatch: push: branches: - main From e6f7d5dc010c2486487a76d4e4447c40aedb9ab1 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 29 Jan 2024 11:43:08 +0200 Subject: [PATCH 38/63] Rewrite DB schema: use UUID for unpredictable IDs, add fields and indexes --- internal/assets/migrations/001_initial.sql | 39 ++++++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 53dc265..dfe32e2 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -1,31 +1,56 @@ -- +migrate Up +CREATE OR REPLACE FUNCTION trigger_set_updated_at() RETURNS trigger + LANGUAGE plpgsql +AS $$ BEGIN NEW.updated_at = NOW() at time zone 'utc'; RETURN NEW; END; $$; + CREATE TABLE IF NOT EXISTS balances ( - id serial PRIMARY KEY, - did text not null unique, + did text PRIMARY KEY, amount integer not null default 0, + created_at timestamp without time zone not null default NOW(), updated_at timestamp without time zone not null default NOW() ); +CREATE INDEX IF NOT EXISTS balances_amount_index ON balances using btree (amount); + +CREATE TRIGGER set_updated_at + BEFORE UPDATE + ON balances + FOR EACH ROW +EXECUTE FUNCTION trigger_set_updated_at(); + CREATE TYPE event_status AS ENUM ('open', 'fulfilled', 'claimed'); CREATE TABLE IF NOT EXISTS events ( - id serial PRIMARY KEY, - balance_id integer not null REFERENCES balances (id), + id uuid PRIMARY KEY not null default gen_random_uuid(), + user_did text not null REFERENCES balances (did), type text not null, status event_status not null, created_at timestamp without time zone not null default NOW(), - meta text, + updated_at timestamp without time zone not null default NOW(), + meta jsonb, points_amount integer ); -CREATE INDEX IF NOT EXISTS events_balance_id_index ON events using btree (balance_id); +CREATE INDEX IF NOT EXISTS events_user_did_index ON events using btree (user_did); CREATE INDEX IF NOT EXISTS events_type_index ON events using btree (type); +CREATE TRIGGER set_updated_at + BEFORE UPDATE + ON events + FOR EACH ROW +EXECUTE FUNCTION trigger_set_updated_at(); + -- +migrate Down +DROP TRIGGER IF EXISTS set_updated_at ON events; DROP INDEX IF EXISTS events_type_index; -DROP INDEX IF EXISTS events_balance_id_index; +DROP INDEX IF EXISTS events_user_did_index; DROP TABLE IF EXISTS events; DROP TYPE IF EXISTS event_status; + +DROP TRIGGER IF EXISTS set_updated_at ON balances; +DROP INDEX IF EXISTS balances_amount_index; DROP TABLE IF EXISTS balances; + +DROP FUNCTION IF EXISTS trigger_set_updated_at(); From 354e734f41e0e56ad3039691a0dfbc6bb3b919fd Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 29 Jan 2024 14:44:17 +0200 Subject: [PATCH 39/63] Replace dates with Unix time to allow seamless pagination --- internal/assets/migrations/001_initial.sql | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index dfe32e2..439d801 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -1,14 +1,14 @@ -- +migrate Up CREATE OR REPLACE FUNCTION trigger_set_updated_at() RETURNS trigger LANGUAGE plpgsql -AS $$ BEGIN NEW.updated_at = NOW() at time zone 'utc'; RETURN NEW; END; $$; +AS $$ BEGIN NEW.updated_at = EXTRACT('EPOCH' FROM NOW()); RETURN NEW; END; $$; CREATE TABLE IF NOT EXISTS balances ( did text PRIMARY KEY, - amount integer not null default 0, - created_at timestamp without time zone not null default NOW(), - updated_at timestamp without time zone not null default NOW() + amount integer not null default 0, + created_at integer not null default EXTRACT('EPOCH' FROM NOW()), + updated_at integer not null default EXTRACT('EPOCH' FROM NOW()) ); CREATE INDEX IF NOT EXISTS balances_amount_index ON balances using btree (amount); @@ -23,18 +23,19 @@ CREATE TYPE event_status AS ENUM ('open', 'fulfilled', 'claimed'); CREATE TABLE IF NOT EXISTS events ( - id uuid PRIMARY KEY not null default gen_random_uuid(), - user_did text not null REFERENCES balances (did), - type text not null, - status event_status not null, - created_at timestamp without time zone not null default NOW(), - updated_at timestamp without time zone not null default NOW(), + id uuid PRIMARY KEY not null default gen_random_uuid(), + user_did text not null REFERENCES balances (did), + type text not null, + status event_status not null, + created_at integer not null default EXTRACT('EPOCH' FROM NOW()), + updated_at integer not null default EXTRACT('EPOCH' FROM NOW()), meta jsonb, points_amount integer ); CREATE INDEX IF NOT EXISTS events_user_did_index ON events using btree (user_did); CREATE INDEX IF NOT EXISTS events_type_index ON events using btree (type); +CREATE INDEX IF NOT EXISTS events_updated_at_index ON events using btree (updated_at); CREATE TRIGGER set_updated_at BEFORE UPDATE @@ -46,6 +47,7 @@ EXECUTE FUNCTION trigger_set_updated_at(); DROP TRIGGER IF EXISTS set_updated_at ON events; DROP INDEX IF EXISTS events_type_index; DROP INDEX IF EXISTS events_user_did_index; +DROP INDEX IF EXISTS events_updated_at_index; DROP TABLE IF EXISTS events; DROP TYPE IF EXISTS event_status; From f4111d074911df70c3099466f6e1e17f5888e320 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 29 Jan 2024 15:15:08 +0200 Subject: [PATCH 40/63] Rewrite models to REST and DB requirements --- .../components/parameters/pageCursor.yaml | 2 +- docs/spec/components/schemas/Balance.yaml | 17 +++--- docs/spec/components/schemas/BalanceKey.yaml | 3 +- .../components/schemas/ClaimEventKey.yaml | 2 +- docs/spec/components/schemas/Event.yaml | 12 ++-- docs/spec/components/schemas/EventKey.yaml | 2 +- ...rations@rarime-points-svc@leaderboard.yaml | 34 ----------- ...ations@rarime-points-svc@v1@balances.yaml} | 57 +++++++++---------- ...s@rarime-points-svc@v1@balances@{did}.yaml | 33 +++++++++++ ...grations@rarime-points-svc@v1@events.yaml} | 2 +- ...ons@rarime-points-svc@v1@events@{id}.yaml} | 2 +- 11 files changed, 84 insertions(+), 82 deletions(-) delete mode 100644 docs/spec/paths/integrations@rarime-points-svc@leaderboard.yaml rename docs/spec/paths/{integrations@rarime-points-svc@balance.yaml => integrations@rarime-points-svc@v1@balances.yaml} (79%) create mode 100644 docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml rename docs/spec/paths/{integrations@rarime-points-svc@events.yaml => integrations@rarime-points-svc@v1@events.yaml} (100%) rename docs/spec/paths/{integrations@rarime-points-svc@events@{id}.yaml => integrations@rarime-points-svc@v1@events@{id}.yaml} (95%) diff --git a/docs/spec/components/parameters/pageCursor.yaml b/docs/spec/components/parameters/pageCursor.yaml index d40c572..78a9688 100644 --- a/docs/spec/components/parameters/pageCursor.yaml +++ b/docs/spec/components/parameters/pageCursor.yaml @@ -3,5 +3,5 @@ name: 'page[cursor]' required: false schema: type: integer - example: 157781 + example: 1706531218 description: Cursor position diff --git a/docs/spec/components/schemas/Balance.yaml b/docs/spec/components/schemas/Balance.yaml index 02728b8..dd44edb 100644 --- a/docs/spec/components/schemas/Balance.yaml +++ b/docs/spec/components/schemas/Balance.yaml @@ -7,24 +7,23 @@ allOf: attributes: type: object required: - - user_did - amount + - created_at - updated_at properties: - user_did: - type: string - description: DID of the points owner - example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" amount: type: integer format: int description: Amount of points example: 580 + created_at: + type: integer + description: Unix timestamp of balance creation + example: 1706531218 updated_at: - type: string - format: time.Time - description: UTC time (RFC3339) of the last points accruing - example: "2021-08-12T13:00:00Z" + type: integer + description: Unix timestamp of the last points accruing + example: 1706531218 rank: type: integer format: int diff --git a/docs/spec/components/schemas/BalanceKey.yaml b/docs/spec/components/schemas/BalanceKey.yaml index 74d3c42..2cb5769 100644 --- a/docs/spec/components/schemas/BalanceKey.yaml +++ b/docs/spec/components/schemas/BalanceKey.yaml @@ -5,7 +5,8 @@ required: properties: id: type: string - example: "157801" + description: DID of the points owner + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" type: type: string enum: [ balance ] diff --git a/docs/spec/components/schemas/ClaimEventKey.yaml b/docs/spec/components/schemas/ClaimEventKey.yaml index 1d52c55..6826b01 100644 --- a/docs/spec/components/schemas/ClaimEventKey.yaml +++ b/docs/spec/components/schemas/ClaimEventKey.yaml @@ -5,7 +5,7 @@ required: properties: id: type: string - example: "157801" + example: "059c81dd-2a54-44a8-8142-c15ad8f88949" type: type: string enum: [ claim_event ] diff --git a/docs/spec/components/schemas/Event.yaml b/docs/spec/components/schemas/Event.yaml index e43ddc1..9dffbf1 100644 --- a/docs/spec/components/schemas/Event.yaml +++ b/docs/spec/components/schemas/Event.yaml @@ -9,6 +9,7 @@ allOf: required: - status - created_at + - updated_at - meta properties: status: @@ -16,10 +17,13 @@ allOf: description: See `filter[status]` parameter for explanation enum: [open, fulfilled, claimed] created_at: - type: string - format: time.Time - description: UTC time (RFC3339) of event creation - example: "2021-08-12T13:00:00Z" + type: integer + description: Unix timestamp of event creation + example: 1706531218 + updated_at: + type: integer + description: Unix timestamp of the event status change + example: 1706531218 meta: $ref: '#/components/schemas/EventMeta' points_amount: diff --git a/docs/spec/components/schemas/EventKey.yaml b/docs/spec/components/schemas/EventKey.yaml index 25dc058..001fce7 100644 --- a/docs/spec/components/schemas/EventKey.yaml +++ b/docs/spec/components/schemas/EventKey.yaml @@ -5,7 +5,7 @@ required: properties: id: type: string - example: "157801" + example: "059c81dd-2a54-44a8-8142-c15ad8f88949" type: type: string enum: diff --git a/docs/spec/paths/integrations@rarime-points-svc@leaderboard.yaml b/docs/spec/paths/integrations@rarime-points-svc@leaderboard.yaml deleted file mode 100644 index 55c36e3..0000000 --- a/docs/spec/paths/integrations@rarime-points-svc@leaderboard.yaml +++ /dev/null @@ -1,34 +0,0 @@ -get: - tags: - - Points balance - summary: Get leaderboard - description: Returns leaders sorted by points or number of claimed events in descending order. - operationId: getLeaderboard - parameters: - - in: query - name: 'page[limit]' - description: Number of leaders to return - required: false - schema: - type: integer - minimum: 3 - maximum: 50 - default: 10 - responses: - 200: - description: Success - content: - application/vnd.api+json: - schema: - type: object - required: - - data - properties: - data: - type: array - items: - $ref: '#/components/schemas/Balance' - 400: - $ref: '#/components/responses/invalidParameter' - 500: - $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@rarime-points-svc@balance.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml similarity index 79% rename from docs/spec/paths/integrations@rarime-points-svc@balance.yaml rename to docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml index f18a5cb..77ddd0f 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@balance.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml @@ -1,32 +1,3 @@ -get: - tags: - - Points balance - summary: Get points balance for user - description: | - Balance of authorized user who makes the request. Rank in leaderboard is included. - You should create new balance for the new user by making POST request. - operationId: getPointsBalance - parameters: - - $ref: '#/components/parameters/filterDID' - responses: - 200: - description: Success - content: - application/vnd.api+json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Balance' - 400: - $ref: '#/components/responses/invalidParameter' - 401: - $ref: '#/components/responses/invalidAuth' - 500: - $ref: '#/components/responses/internalError' - post: tags: - Points balance @@ -68,3 +39,31 @@ post: $ref: '#/components/schemas/Errors' 500: $ref: '#/components/responses/internalError' + +get: + tags: + - Points balance + summary: Get leaderboard + description: Returns leaders sorted by points in descending order. + operationId: getLeaderboard + parameters: + - $ref: '#/components/parameters/pageCursor' + - $ref: '#/components/parameters/pageLimit' + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Balance' + 400: + $ref: '#/components/responses/invalidParameter' + 500: + $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml new file mode 100644 index 0000000..20ed389 --- /dev/null +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml @@ -0,0 +1,33 @@ +get: + tags: + - Points balance + summary: Get points balance + description: | + Balance of authorized user who makes the request. Rank in leaderboard is included. + You should create new balance for the new user by making POST request. + operationId: getPointsBalance + parameters: + - in: path + name: 'did' + required: true + schema: + type: string + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Balance' + 400: + $ref: '#/components/responses/invalidParameter' + 401: + $ref: '#/components/responses/invalidAuth' + 500: + $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@rarime-points-svc@events.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@events.yaml similarity index 100% rename from docs/spec/paths/integrations@rarime-points-svc@events.yaml rename to docs/spec/paths/integrations@rarime-points-svc@v1@events.yaml index 806de93..0f756fe 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@events.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@events.yaml @@ -35,8 +35,8 @@ get: schema: type: boolean example: true - - $ref: '#/components/parameters/pageLimit' - $ref: '#/components/parameters/pageCursor' + - $ref: '#/components/parameters/pageLimit' - $ref: '#/components/parameters/pageOrder' responses: 200: diff --git a/docs/spec/paths/integrations@rarime-points-svc@events@{id}.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml similarity index 95% rename from docs/spec/paths/integrations@rarime-points-svc@events@{id}.yaml rename to docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml index a3e073b..6fdd600 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@events@{id}.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml @@ -12,7 +12,7 @@ patch: required: true schema: type: string - example: "157801" + example: "059c81dd-2a54-44a8-8142-c15ad8f88949" requestBody: required: true content: From 521c50c2e196aacf5bb7f980327b2b87a6f7ee5b Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 29 Jan 2024 17:18:58 +0200 Subject: [PATCH 41/63] Rewrite handlers to new models --- internal/data/main.go | 41 +++++++-------- internal/data/pg/balances.go | 43 ++++++---------- internal/data/pg/events.go | 41 ++++++++------- internal/service/handlers/claim_event.go | 57 ++++----------------- internal/service/handlers/create_balance.go | 12 ++--- internal/service/handlers/get_balance.go | 6 +-- internal/service/handlers/leaderboard.go | 4 +- internal/service/handlers/list_events.go | 19 +++---- resources/model_balance_attributes.go | 10 ++-- resources/model_event_attributes.go | 8 +-- 10 files changed, 95 insertions(+), 146 deletions(-) diff --git a/internal/data/main.go b/internal/data/main.go index 306209e..100dabd 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -2,7 +2,7 @@ package data import ( "database/sql" - "time" + "encoding/json" "gitlab.com/distributed_lab/kit/pgdb" ) @@ -22,7 +22,7 @@ func (s EventStatus) String() string { type EventsQ interface { New() EventsQ Insert(...Event) error - Update(Event) error + Update(status EventStatus, meta []json.RawMessage, points *int32) (*Event, error) Page(*pgdb.CursorPageParams) EventsQ Select() ([]Event, error) @@ -30,38 +30,39 @@ type EventsQ interface { Count() (int, error) FilterByID(string) EventsQ - FilterByBalanceID(...string) EventsQ + FilterByUserDID(string) EventsQ FilterByStatus(...EventStatus) EventsQ FilterByType(...string) EventsQ } type BalancesQ interface { New() BalancesQ - Insert(Balance) error - UpdateAmount(int) error + Insert(did string) error + AddAmount(points int32) error - SelectLeaders(count int) ([]Balance, error) + Page(*pgdb.CursorPageParams) BalancesQ + Select() ([]Balance, error) Get() (*Balance, error) WithRank() BalancesQ - FilterByID(string) BalancesQ - FilterByUserDID(string) BalancesQ + FilterByDID(string) BalancesQ } type Event struct { - ID string `db:"id"` - BalanceID string `db:"balance_id"` - Type string `db:"type"` - Status EventStatus `db:"status"` - CreatedAt time.Time `db:"created_at"` - Meta sql.NullString `db:"meta"` - PointsAmount sql.NullInt32 `db:"points_amount"` + ID string `db:"id"` + UserDID string `db:"user_did"` + Type string `db:"type"` + Status EventStatus `db:"status"` + CreatedAt int32 `db:"created_at"` + UpdatedAt int32 `db:"updated_at"` + Meta json.RawMessage `db:"meta"` + PointsAmount sql.NullInt32 `db:"points_amount"` } type Balance struct { - ID string `db:"id"` - DID string `db:"did"` - Amount int `db:"amount"` - UpdatedAt time.Time `db:"updated_at"` - Rank *int `db:"rank"` + DID string `db:"did"` + Amount int `db:"amount"` + CreatedAt int32 `db:"created_at"` + UpdatedAt int32 `db:"updated_at"` + Rank *int `db:"rank"` } diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index 596341f..d118aa7 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -4,7 +4,6 @@ import ( "database/sql" "errors" "fmt" - "time" "github.com/Masterminds/squirrel" "github.com/rarimo/rarime-points-svc/internal/data" @@ -31,42 +30,36 @@ func (q *balances) New() data.BalancesQ { return NewBalances(q.db.Clone()) } -func (q *balances) Insert(balance data.Balance) error { - stmt := squirrel.Insert(balancesTable).SetMap(map[string]interface{}{ - "id": balance.ID, - "did": balance.DID, - "amount": balance.Amount, - }) +func (q *balances) Insert(did string) error { + stmt := squirrel.Insert(balancesTable).Columns("did").Values(did) if err := q.db.Exec(stmt); err != nil { - return fmt.Errorf("insert balance %+v: %w", balance, err) + return fmt.Errorf("insert balance for did %s: %w", did, err) } return nil } -func (q *balances) UpdateAmount(amount int) error { - stmt := q.updater. - Set("amount", amount). - Set("updated_at", time.Now().UTC()) +func (q *balances) AddAmount(points int32) error { + stmt := q.updater.Set("amount", squirrel.Expr("amount + ?", points)) if err := q.db.Exec(stmt); err != nil { - return fmt.Errorf("update balance amount to %d: %w", amount, err) + return fmt.Errorf("add %d points: %w", points, err) } return nil } -func (q *balances) SelectLeaders(count int) ([]data.Balance, error) { - var res []data.Balance +func (q *balances) Page(page *pgdb.CursorPageParams) data.BalancesQ { + q.selector = page.ApplyTo(q.selector, "amount") + return q +} - stmt := squirrel.Select("*"). - From(balancesTable). - OrderBy("amount DESC, updated_at ASC"). - Limit(uint64(count)) +func (q *balances) Select() ([]data.Balance, error) { + var res []data.Balance - if err := q.db.Select(&res, stmt); err != nil { - return nil, fmt.Errorf("select leaders: %w", err) + if err := q.db.Select(&res, q.selector); err != nil { + return nil, fmt.Errorf("select balances: %w", err) } return res, nil @@ -90,13 +83,7 @@ func (q *balances) WithRank() data.BalancesQ { return q } -func (q *balances) FilterByID(id string) data.BalancesQ { - q.selector = q.selector.Where(squirrel.Eq{"id": id}) - q.updater = q.updater.Where(squirrel.Eq{"id": id}) - return q -} - -func (q *balances) FilterByUserDID(did string) data.BalancesQ { +func (q *balances) FilterByDID(did string) data.BalancesQ { q.selector = q.selector.Where(squirrel.Eq{"did": did}) q.updater = q.updater.Where(squirrel.Eq{"did": did}) return q diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 528439f..1782f69 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -1,8 +1,9 @@ package pg import ( + "database/sql" + "encoding/json" "fmt" - "time" "github.com/Masterminds/squirrel" "github.com/rarimo/rarime-points-svc/internal/data" @@ -35,9 +36,9 @@ func (q *events) Insert(events ...data.Event) error { } stmt := squirrel.Insert(eventsTable). - Columns("balance_id", "type", "status", "created_at", "meta", "points_amount") + Columns("user_did", "type", "status", "meta", "points_amount") for _, event := range events { - stmt = stmt.Values(event.BalanceID, event.Type, event.Status, event.CreatedAt, event.Meta, event.PointsAmount) + stmt = stmt.Values(event.UserDID, event.Type, event.Status, event.Meta, event.PointsAmount) } if err := q.db.Exec(stmt); err != nil { @@ -47,24 +48,29 @@ func (q *events) Insert(events ...data.Event) error { return nil } -func (q *events) Update(event data.Event) error { +func (q *events) Update(status data.EventStatus, meta []json.RawMessage, points *int32) (*data.Event, error) { umap := map[string]any{ - "status": event.Status, - "meta": event.Meta, - "points_amount": event.PointsAmount, - "updated_at": time.Now().UTC(), + "status": status, + } + if points != nil { + umap["points_amount"] = sql.NullInt32{Int32: *points, Valid: true} + } + if len(meta) != 0 { + umap["meta"] = meta } - stmt := squirrel.Update(eventsTable).SetMap(umap).Where(squirrel.Eq{"id": event.ID}) - if err := q.db.Exec(stmt); err != nil { - return fmt.Errorf("update event with map %+v: %w", umap, err) + var res data.Event + stmt := squirrel.Update(eventsTable).SetMap(umap) + + if err := q.db.Get(&res, stmt); err != nil { + return nil, fmt.Errorf("update event with map %+v: %w", umap, err) } - return nil + return &res, nil } func (q *events) Page(page *pgdb.CursorPageParams) data.EventsQ { - q.selector = page.ApplyTo(q.selector, "id") + q.selector = page.ApplyTo(q.selector, "updated_at") return q } @@ -106,12 +112,9 @@ func (q *events) FilterByID(id string) data.EventsQ { return q } -func (q *events) FilterByBalanceID(ids ...string) data.EventsQ { - if len(ids) == 0 { - return q - } - q.selector = q.selector.Where(squirrel.Eq{"balance_id": ids}) - q.counter = q.counter.Where(squirrel.Eq{"balance_id": ids}) +func (q *events) FilterByUserDID(did string) data.EventsQ { + q.selector = q.selector.Where(squirrel.Eq{"user_did": did}) + q.counter = q.counter.Where(squirrel.Eq{"user_did": did}) return q } diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index 3b22691..38dc62a 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -1,8 +1,6 @@ package handlers import ( - "database/sql" - "fmt" "net/http" "github.com/rarimo/rarime-auth-svc/pkg/auth" @@ -24,10 +22,6 @@ func ClaimEvent(w http.ResponseWriter, r *http.Request) { if event == nil { return } - balance := getBalanceByID(event.BalanceID, true, w, r) - if balance == nil { - return - } evType := EventTypes(r).Get(event.Type) if evType == nil { @@ -36,12 +30,12 @@ func ClaimEvent(w http.ResponseWriter, r *http.Request) { return } - event = claimEventWithPoints(*event, balance.Amount, int(evType.Reward), w, r) + event = claimEventWithPoints(*event, evType.Reward, w, r) if event == nil { return } - // can't return balance on update, see create_balance.go - balance = getBalanceByID(event.BalanceID, true, w, r) + // can't return balance with rank on update, see create_balance.go + balance := getBalanceByDID(event.UserDID, true, w, r) if balance == nil { return } @@ -67,59 +61,30 @@ func getEventToClaim(id string, w http.ResponseWriter, r *http.Request) *data.Ev return nil } - return event -} - -func getBalanceByID(id string, doAuth bool, w http.ResponseWriter, r *http.Request) *data.Balance { - balance, err := BalancesQ(r).WithRank().FilterByID(id).Get() - - if err != nil || balance == nil { - if err == nil { - err = fmt.Errorf("DB constraint violation: found event with balance_id=%s not present", id) - } - - Log(r).WithError(err).Error("Failed to get balance by ID") - ape.RenderErr(w, problems.InternalError()) - return nil - } - - if doAuth && !auth.Authenticates(UserClaims(r), auth.UserGrant(balance.DID)) { + if !auth.Authenticates(UserClaims(r), auth.UserGrant(event.UserDID)) { ape.RenderErr(w, problems.Unauthorized()) return nil } - return balance + return event } -func claimEventWithPoints(event data.Event, currBalance, reward int, w http.ResponseWriter, r *http.Request) *data.Event { - claimed := data.Event{ - ID: event.ID, - Status: data.EventClaimed, - PointsAmount: sql.NullInt32{ - Int32: int32(reward), - Valid: true, - }, - } - - err := EventsQ(r).Update(claimed) +func claimEventWithPoints(event data.Event, reward int32, w http.ResponseWriter, r *http.Request) *data.Event { + claimed, err := EventsQ(r).FilterByID(event.ID).Update(data.EventClaimed, nil, &reward) if err != nil { Log(r).WithError(err).Error("Failed to claim event") ape.RenderErr(w, problems.InternalError()) return nil } - err = BalancesQ(r).FilterByID(event.BalanceID).UpdateAmount(currBalance + reward) + err = BalancesQ(r).FilterByDID(event.UserDID).AddAmount(reward) if err != nil { Log(r).WithError(err).Error("Failed to accrue points to the balance") ape.RenderErr(w, problems.InternalError()) return nil } - // While we don't have updated_at and other special attributes in events, we can - // safely return the same struct without redundant queries. It is still faster - // than with RETURNING clause. - event.Status = claimed.Status - event.PointsAmount = claimed.PointsAmount - return &event + + return claimed } func newClaimEventResponse( @@ -132,7 +97,7 @@ func newClaimEventResponse( eventModel.Relationships = &resources.EventRelationships{ Balance: resources.Relation{ Data: &resources.Key{ - ID: balance.ID, + ID: balance.DID, Type: resources.BALANCE, }, }, diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index 8ed5fc5..fd2f031 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -25,7 +25,7 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - if err = BalancesQ(r).Insert(data.Balance{DID: did}); err != nil { + if err = BalancesQ(r).Insert(did); err != nil { Log(r).WithError(err).Error("Failed to create balance") ape.RenderErr(w, problems.InternalError()) return @@ -38,7 +38,7 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - err = EventsQ(r).Insert(prepareOpenEvents(balance.ID, EventTypes(r).List())...) + err = EventsQ(r).Insert(prepareOpenEvents(balance.DID, EventTypes(r).List())...) if err != nil { Log(r).WithError(err).Error("Failed to add open events") ape.RenderErr(w, problems.InternalError()) @@ -48,13 +48,13 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { ape.Render(w, newBalanceModel(*balance)) } -func prepareOpenEvents(balanceID string, evTypes []resources.EventStaticMeta) []data.Event { +func prepareOpenEvents(did string, evTypes []resources.EventStaticMeta) []data.Event { events := make([]data.Event, len(evTypes)) for i, evType := range evTypes { events[i] = data.Event{ - BalanceID: balanceID, - Type: evType.Name, - Status: data.EventOpen, + UserDID: did, + Type: evType.Name, + Status: data.EventOpen, PointsAmount: sql.NullInt32{ Int32: evType.Reward, Valid: true, diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go index 84744b6..ed011b0 100644 --- a/internal/service/handlers/get_balance.go +++ b/internal/service/handlers/get_balance.go @@ -29,13 +29,13 @@ func GetBalance(w http.ResponseWriter, r *http.Request) { func newBalanceModel(balance data.Balance) resources.Balance { return resources.Balance{ Key: resources.Key{ - ID: balance.ID, + ID: balance.DID, Type: resources.BALANCE, }, Attributes: resources.BalanceAttributes{ Amount: balance.Amount, + CreatedAt: balance.CreatedAt, UpdatedAt: balance.UpdatedAt, - UserDid: balance.DID, Rank: balance.Rank, }, } @@ -47,7 +47,7 @@ func getBalanceByDID(did string, withRank bool, w http.ResponseWriter, r *http.R return nil } - q := BalancesQ(r).FilterByUserDID(did) + q := BalancesQ(r).FilterByDID(did) if withRank { q.WithRank() } diff --git a/internal/service/handlers/leaderboard.go b/internal/service/handlers/leaderboard.go index 397312a..351add4 100644 --- a/internal/service/handlers/leaderboard.go +++ b/internal/service/handlers/leaderboard.go @@ -11,13 +11,13 @@ import ( ) func Leaderboard(w http.ResponseWriter, r *http.Request) { - req, err := requests.NewLeaderboard(r) + _, err := requests.NewLeaderboard(r) if err != nil { ape.RenderErr(w, problems.BadRequest(err)...) return } - leaders, err := BalancesQ(r).SelectLeaders(req.Limit) + leaders, err := BalancesQ(r).Select() // TODO: add pagination if err != nil { Log(r).WithError(err).Error("Failed to get balance leaders") ape.RenderErr(w, problems.InternalError()) diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index b27bf45..aee2b71 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -1,9 +1,9 @@ package handlers import ( - "encoding/json" "net/http" + "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/service/requests" "github.com/rarimo/rarime-points-svc/resources" @@ -18,13 +18,13 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { return } - balance := getBalanceByDID(req.FilterDID, false, w, r) - if balance == nil { + if !auth.Authenticates(UserClaims(r), auth.UserGrant(req.FilterDID)) { + ape.RenderErr(w, problems.Unauthorized()) return } events, err := EventsQ(r). - FilterByBalanceID(balance.ID). + FilterByUserDID(req.FilterDID). FilterByStatus(req.FilterStatus...). FilterByType(req.FilterType...). Page(&req.CursorPageParams). @@ -38,7 +38,7 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { var eventsCount int if req.Count { eventsCount, err = EventsQ(r). - FilterByBalanceID(balance.ID). + FilterByUserDID(req.FilterDID). FilterByStatus(req.FilterStatus...). FilterByType(req.FilterType...). Count() @@ -86,12 +86,6 @@ func getOrderedEventsMeta(events []data.Event, w http.ResponseWriter, r *http.Re } func newEventModel(event data.Event, meta resources.EventStaticMeta) resources.Event { - var dynamic *json.RawMessage - if event.Meta.Valid { - d := json.RawMessage(event.Meta.String) - dynamic = &d - } - var points *int32 if event.PointsAmount.Valid { points = &event.PointsAmount.Int32 @@ -104,9 +98,10 @@ func newEventModel(event data.Event, meta resources.EventStaticMeta) resources.E }, Attributes: resources.EventAttributes{ CreatedAt: event.CreatedAt, + UpdatedAt: event.UpdatedAt, Meta: resources.EventMeta{ Static: meta, - Dynamic: dynamic, + Dynamic: &event.Meta, }, Status: event.Status.String(), PointsAmount: points, diff --git a/resources/model_balance_attributes.go b/resources/model_balance_attributes.go index 8e8c319..af5f3ff 100644 --- a/resources/model_balance_attributes.go +++ b/resources/model_balance_attributes.go @@ -4,15 +4,13 @@ package resources -import "time" - type BalanceAttributes struct { // Amount of points Amount int `json:"amount"` + // Unix timestamp of balance creation + CreatedAt int32 `json:"created_at"` // Rank of the user in the full leaderboard. Returned only for the single user. Rank *int `json:"rank,omitempty"` - // UTC time (RFC3339) of the last points accruing - UpdatedAt time.Time `json:"updated_at"` - // DID of the points owner - UserDid string `json:"user_did"` + // Unix timestamp of the last points accruing + UpdatedAt int32 `json:"updated_at"` } diff --git a/resources/model_event_attributes.go b/resources/model_event_attributes.go index 7d852d0..26f3f6a 100644 --- a/resources/model_event_attributes.go +++ b/resources/model_event_attributes.go @@ -4,14 +4,14 @@ package resources -import "time" - type EventAttributes struct { - // UTC time (RFC3339) of event creation - CreatedAt time.Time `json:"created_at"` + // Unix timestamp of event creation + CreatedAt int32 `json:"created_at"` Meta EventMeta `json:"meta"` // How many points were accrued. Required only for `claimed` events. This is necessary, as the reward might change over time, while the certain balance should be left intact. PointsAmount *int32 `json:"points_amount,omitempty"` // See `filter[status]` parameter for explanation Status string `json:"status"` + // Unix timestamp of the event status change + UpdatedAt int32 `json:"updated_at"` } From 8d46727197564c75010ec7ec47f437ad3a7e7758 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 29 Jan 2024 17:38:32 +0200 Subject: [PATCH 42/63] Add cursor pagination for the leaderboard --- internal/service/handlers/leaderboard.go | 14 +++++++++++--- internal/service/page/page_params.go | 10 ++++++++-- internal/service/requests/leaderboard.go | 11 +++++++++-- internal/service/requests/list_events.go | 5 +++++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/internal/service/handlers/leaderboard.go b/internal/service/handlers/leaderboard.go index 351add4..a99ce21 100644 --- a/internal/service/handlers/leaderboard.go +++ b/internal/service/handlers/leaderboard.go @@ -2,6 +2,7 @@ package handlers import ( "net/http" + "strconv" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/service/requests" @@ -11,20 +12,27 @@ import ( ) func Leaderboard(w http.ResponseWriter, r *http.Request) { - _, err := requests.NewLeaderboard(r) + req, err := requests.NewLeaderboard(r) if err != nil { ape.RenderErr(w, problems.BadRequest(err)...) return } - leaders, err := BalancesQ(r).Select() // TODO: add pagination + leaders, err := BalancesQ(r).Page(&req.CursorPageParams).Select() if err != nil { Log(r).WithError(err).Error("Failed to get balance leaders") ape.RenderErr(w, problems.InternalError()) return } - ape.Render(w, newLeaderboardResponse(leaders)) + var last string + if len(leaders) > 0 { + last = strconv.Itoa(leaders[len(leaders)-1].Amount) + } + + resp := newLeaderboardResponse(leaders) + resp.Links = req.GetCursorLinks(r, last) + ape.Render(w, resp) } func newLeaderboardResponse(balances []data.Balance) resources.BalanceListResponse { diff --git a/internal/service/page/page_params.go b/internal/service/page/page_params.go index 588cbb4..b69b18d 100644 --- a/internal/service/page/page_params.go +++ b/internal/service/page/page_params.go @@ -18,12 +18,18 @@ const ( // CursorParams is a wrapper around pgdb.CursorPageParams with useful validation and rendering methods type CursorParams struct { pgdb.CursorPageParams + IsLeaderboard bool // deny ascending order for leaderboard } func (p *CursorParams) Validate() error { + var orderRule val.Rule = val.In(pgdb.OrderTypeAsc, pgdb.OrderTypeDesc) + if p.IsLeaderboard { + orderRule = val.Empty + } + return val.Errors{ - pageParamLimit: val.Validate(p.Limit, val.Max(maxLimit)), - pageParamOrder: val.Validate(p.Order, val.In(pgdb.OrderTypeAsc, pgdb.OrderTypeDesc)), pageParamCursor: val.Validate(p.Cursor, val.Max(uint64(math.MaxInt32))), + pageParamLimit: val.Validate(p.Limit, val.Max(maxLimit)), + pageParamOrder: val.Validate(p.Order, orderRule), }.Filter() } diff --git a/internal/service/requests/leaderboard.go b/internal/service/requests/leaderboard.go index 9cf0595..99ad411 100644 --- a/internal/service/requests/leaderboard.go +++ b/internal/service/requests/leaderboard.go @@ -5,11 +5,14 @@ import ( "net/http" validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-points-svc/internal/service/page" "gitlab.com/distributed_lab/urlval/v4" ) +const leaderboardDefaultLimit = 10 + type Leaderboard struct { - Limit int `page:"limit"` + page.CursorParams } func NewLeaderboard(r *http.Request) (req Leaderboard, err error) { @@ -19,8 +22,12 @@ func NewLeaderboard(r *http.Request) (req Leaderboard, err error) { } } + req.IsLeaderboard = true if req.Limit == 0 { - req.Limit = 10 + req.Limit = leaderboardDefaultLimit + } + if err = req.Validate(); err != nil { + return } err = validation.Errors{ diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go index 5faa580..2c03bee 100644 --- a/internal/service/requests/list_events.go +++ b/internal/service/requests/list_events.go @@ -25,9 +25,14 @@ func NewListEvents(r *http.Request) (req ListEvents, err error) { } } + if err = req.Validate(); err != nil { + return + } + err = validation.Errors{ "filter[did]": validation.Validate(req.FilterDID, validation.Required), "filter[status]": validation.Validate(req.FilterStatus, validation.Each(validation.In(data.EventOpen, data.EventFulfilled, data.EventClaimed))), }.Filter() + return } From dc7b3b59352e5f65f38331debed99f7f2ea179ad Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 30 Jan 2024 12:15:58 +0200 Subject: [PATCH 43/63] Replace with offset pagination in leaderboard --- .../components/parameters/pageNumber.yaml | 8 +++ internal/data/main.go | 2 +- internal/data/pg/balances.go | 2 +- internal/service/handlers/leaderboard.go | 12 +---- internal/service/handlers/list_events.go | 2 +- internal/service/page/cursor_params.go | 53 +++++++++++++++++++ internal/service/page/links.go | 29 ---------- internal/service/page/offset_params.go | 44 +++++++++++++++ internal/service/page/page_params.go | 35 ------------ internal/service/requests/leaderboard.go | 20 ++----- internal/service/requests/list_events.go | 5 -- 11 files changed, 113 insertions(+), 99 deletions(-) create mode 100644 docs/spec/components/parameters/pageNumber.yaml create mode 100644 internal/service/page/cursor_params.go delete mode 100644 internal/service/page/links.go create mode 100644 internal/service/page/offset_params.go delete mode 100644 internal/service/page/page_params.go diff --git a/docs/spec/components/parameters/pageNumber.yaml b/docs/spec/components/parameters/pageNumber.yaml new file mode 100644 index 0000000..676bf0c --- /dev/null +++ b/docs/spec/components/parameters/pageNumber.yaml @@ -0,0 +1,8 @@ +in: query +name: 'page[number]' +description: The number of the page to return. +required: false +schema: + type: integer + default: 0 + example: 3 diff --git a/internal/data/main.go b/internal/data/main.go index 100dabd..9e64ed8 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -40,7 +40,7 @@ type BalancesQ interface { Insert(did string) error AddAmount(points int32) error - Page(*pgdb.CursorPageParams) BalancesQ + Page(*pgdb.OffsetPageParams) BalancesQ Select() ([]Balance, error) Get() (*Balance, error) WithRank() BalancesQ diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index d118aa7..f5bc5a1 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -50,7 +50,7 @@ func (q *balances) AddAmount(points int32) error { return nil } -func (q *balances) Page(page *pgdb.CursorPageParams) data.BalancesQ { +func (q *balances) Page(page *pgdb.OffsetPageParams) data.BalancesQ { q.selector = page.ApplyTo(q.selector, "amount") return q } diff --git a/internal/service/handlers/leaderboard.go b/internal/service/handlers/leaderboard.go index a99ce21..2f1226f 100644 --- a/internal/service/handlers/leaderboard.go +++ b/internal/service/handlers/leaderboard.go @@ -2,7 +2,6 @@ package handlers import ( "net/http" - "strconv" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/service/requests" @@ -18,21 +17,14 @@ func Leaderboard(w http.ResponseWriter, r *http.Request) { return } - leaders, err := BalancesQ(r).Page(&req.CursorPageParams).Select() + leaders, err := BalancesQ(r).Page(&req.OffsetPageParams).Select() if err != nil { Log(r).WithError(err).Error("Failed to get balance leaders") ape.RenderErr(w, problems.InternalError()) return } - var last string - if len(leaders) > 0 { - last = strconv.Itoa(leaders[len(leaders)-1].Amount) - } - - resp := newLeaderboardResponse(leaders) - resp.Links = req.GetCursorLinks(r, last) - ape.Render(w, resp) + ape.Render(w, newLeaderboardResponse(leaders)) } func newLeaderboardResponse(balances []data.Balance) resources.BalanceListResponse { diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index aee2b71..3aad5e6 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -60,7 +60,7 @@ func ListEvents(w http.ResponseWriter, r *http.Request) { } resp := newEventsResponse(events, meta) - resp.Links = req.CursorParams.GetCursorLinks(r, last) + resp.Links = req.CursorParams.GetLinks(r, last) if req.Count { _ = resp.PutMeta(struct { EventsCount int `json:"events_count"` diff --git a/internal/service/page/cursor_params.go b/internal/service/page/cursor_params.go new file mode 100644 index 0000000..eeca0f4 --- /dev/null +++ b/internal/service/page/cursor_params.go @@ -0,0 +1,53 @@ +package page + +import ( + "math" + "net/http" + "strconv" + + val "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-points-svc/resources" + "gitlab.com/distributed_lab/kit/pgdb" +) + +const ( + pageParamLimit = "page[limit]" + pageParamCursor = "page[cursor]" + pageParamOrder = "page[order]" + + maxLimit uint64 = 100 +) + +// CursorParams is a wrapper around pgdb.CursorPageParams with useful validation and rendering methods +type CursorParams struct { + pgdb.CursorPageParams +} + +func (p *CursorParams) Validate() error { + return val.Errors{ + pageParamLimit: val.Validate(p.Limit, val.Max(maxLimit)), + pageParamOrder: val.Validate(p.Order, val.In(pgdb.OrderTypeAsc, pgdb.OrderTypeDesc)), + pageParamCursor: val.Validate(p.Cursor, val.Max(uint64(math.MaxInt32))), + }.Filter() +} + +func (p *CursorParams) GetLinks(r *http.Request, last string) *resources.Links { + result := resources.Links{ + Self: p.getLink(r, p.Cursor), + } + if last != "" { + lastI, _ := strconv.ParseUint(last, 10, 64) + result.Next = p.getLink(r, lastI) + } + return &result +} + +func (p *CursorParams) getLink(r *http.Request, cursor uint64) string { + u := r.URL + query := u.Query() + query.Set(pageParamCursor, strconv.FormatUint(cursor, 10)) + query.Set(pageParamLimit, strconv.FormatUint(p.Limit, 10)) + query.Set(pageParamOrder, p.Order) + u.RawQuery = query.Encode() + return u.String() +} diff --git a/internal/service/page/links.go b/internal/service/page/links.go deleted file mode 100644 index 2568607..0000000 --- a/internal/service/page/links.go +++ /dev/null @@ -1,29 +0,0 @@ -package page - -import ( - "net/http" - "strconv" - - "github.com/rarimo/rarime-points-svc/resources" -) - -func (p *CursorParams) GetCursorLinks(r *http.Request, last string) *resources.Links { - result := resources.Links{ - Self: p.getCursorLink(r, p.Cursor, p.Order), - } - if last != "" { - lastI, _ := strconv.ParseUint(last, 10, 64) - result.Next = p.getCursorLink(r, lastI, p.Order) - } - return &result -} - -func (p *CursorParams) getCursorLink(r *http.Request, cursor uint64, order string) string { - u := r.URL - query := u.Query() - query.Set(pageParamCursor, strconv.FormatUint(cursor, 10)) - query.Set(pageParamLimit, strconv.FormatUint(p.Limit, 10)) - query.Set(pageParamOrder, order) - u.RawQuery = query.Encode() - return u.String() -} diff --git a/internal/service/page/offset_params.go b/internal/service/page/offset_params.go new file mode 100644 index 0000000..5d25d00 --- /dev/null +++ b/internal/service/page/offset_params.go @@ -0,0 +1,44 @@ +package page + +import ( + "math" + "net/http" + "strconv" + + val "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-points-svc/resources" + "gitlab.com/distributed_lab/kit/pgdb" +) + +const pageParamNumber = "page[number]" + +// OffsetParams is a wrapper around pgdb.OffsetPageParams with useful validation and rendering methods +type OffsetParams struct { + pgdb.OffsetPageParams +} + +func (p *OffsetParams) Validate() error { + return val.Errors{ + pageParamLimit: val.Validate(p.Limit, val.Max(maxLimit)), + pageParamNumber: val.Validate(p.PageNumber, val.Max(uint64(math.MaxInt32))), + pageParamOrder: val.Validate(p.Order, val.In(pgdb.OrderTypeAsc, pgdb.OrderTypeDesc)), + }.Filter() +} + +func (p *OffsetParams) GetLinks(r *http.Request) *resources.Links { + result := resources.Links{ + Self: p.getLink(r, p.PageNumber), + Next: p.getLink(r, p.PageNumber+1), + } + return &result +} + +func (p *OffsetParams) getLink(r *http.Request, number uint64) string { + u := r.URL + query := u.Query() + query.Set(pageParamNumber, strconv.FormatUint(number, 10)) + query.Set(pageParamLimit, strconv.FormatUint(p.Limit, 10)) + query.Set(pageParamOrder, p.Order) + u.RawQuery = query.Encode() + return u.String() +} diff --git a/internal/service/page/page_params.go b/internal/service/page/page_params.go deleted file mode 100644 index b69b18d..0000000 --- a/internal/service/page/page_params.go +++ /dev/null @@ -1,35 +0,0 @@ -package page - -import ( - "math" - - val "github.com/go-ozzo/ozzo-validation/v4" - "gitlab.com/distributed_lab/kit/pgdb" -) - -const ( - pageParamLimit = "page[limit]" - pageParamCursor = "page[cursor]" - pageParamOrder = "page[order]" - - maxLimit uint64 = 100 -) - -// CursorParams is a wrapper around pgdb.CursorPageParams with useful validation and rendering methods -type CursorParams struct { - pgdb.CursorPageParams - IsLeaderboard bool // deny ascending order for leaderboard -} - -func (p *CursorParams) Validate() error { - var orderRule val.Rule = val.In(pgdb.OrderTypeAsc, pgdb.OrderTypeDesc) - if p.IsLeaderboard { - orderRule = val.Empty - } - - return val.Errors{ - pageParamCursor: val.Validate(p.Cursor, val.Max(uint64(math.MaxInt32))), - pageParamLimit: val.Validate(p.Limit, val.Max(maxLimit)), - pageParamOrder: val.Validate(p.Order, orderRule), - }.Filter() -} diff --git a/internal/service/requests/leaderboard.go b/internal/service/requests/leaderboard.go index 99ad411..3252f41 100644 --- a/internal/service/requests/leaderboard.go +++ b/internal/service/requests/leaderboard.go @@ -9,30 +9,16 @@ import ( "gitlab.com/distributed_lab/urlval/v4" ) -const leaderboardDefaultLimit = 10 - type Leaderboard struct { - page.CursorParams + page.OffsetParams } func NewLeaderboard(r *http.Request) (req Leaderboard, err error) { if err = urlval.Decode(r.URL.Query(), &req); err != nil { return req, validation.Errors{ - "page[limit]": fmt.Errorf("failed to decode query: %v", err), + "query": fmt.Errorf("failed to decode query: %v", err), } } - req.IsLeaderboard = true - if req.Limit == 0 { - req.Limit = leaderboardDefaultLimit - } - if err = req.Validate(); err != nil { - return - } - - err = validation.Errors{ - "page[limit]": validation.Validate(req.Limit, validation.Min(3), validation.Max(50)), - }.Filter() - - return + return req, req.Validate() } diff --git a/internal/service/requests/list_events.go b/internal/service/requests/list_events.go index 2c03bee..5faa580 100644 --- a/internal/service/requests/list_events.go +++ b/internal/service/requests/list_events.go @@ -25,14 +25,9 @@ func NewListEvents(r *http.Request) (req ListEvents, err error) { } } - if err = req.Validate(); err != nil { - return - } - err = validation.Errors{ "filter[did]": validation.Validate(req.FilterDID, validation.Required), "filter[status]": validation.Validate(req.FilterStatus, validation.Each(validation.In(data.EventOpen, data.EventFulfilled, data.EventClaimed))), }.Filter() - return } From 5f38bcd76c6858d3303d477676705b3084f2fc4c Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 30 Jan 2024 12:45:08 +0200 Subject: [PATCH 44/63] API models improvements, fixes in paths and handlers --- .../spec/components/parameters/pageOrder.yaml | 4 +- docs/spec/components/schemas/ClaimEvent.yaml | 17 -------- .../components/schemas/CreateBalance.yaml | 16 ------- .../components/schemas/CreateBalanceKey.yaml | 5 +++ ...rations@rarime-points-svc@v1@balances.yaml | 3 +- ...ions@rarime-points-svc@v1@events@{id}.yaml | 2 +- internal/service/handlers/create_balance.go | 2 +- internal/service/handlers/get_balance.go | 2 +- internal/service/requests/claim_event.go | 13 +++--- internal/service/requests/create_balance.go | 12 ++++-- internal/service/requests/get_balance.go | 18 +++----- internal/service/router.go | 8 ++-- resources/model_claim_event.go | 43 ------------------- resources/model_claim_event_attributes.go | 10 ----- resources/model_create_balance.go | 43 ------------------- resources/model_create_balance_attributes.go | 10 ----- 16 files changed, 37 insertions(+), 171 deletions(-) delete mode 100644 docs/spec/components/schemas/ClaimEvent.yaml delete mode 100644 docs/spec/components/schemas/CreateBalance.yaml delete mode 100644 resources/model_claim_event.go delete mode 100644 resources/model_claim_event_attributes.go delete mode 100644 resources/model_create_balance.go delete mode 100644 resources/model_create_balance_attributes.go diff --git a/docs/spec/components/parameters/pageOrder.yaml b/docs/spec/components/parameters/pageOrder.yaml index b7fe176..f099007 100644 --- a/docs/spec/components/parameters/pageOrder.yaml +++ b/docs/spec/components/parameters/pageOrder.yaml @@ -7,6 +7,4 @@ schema: - asc - desc default: desc - description: >- - Order of records on the page. If pageOrder is not specified, order of - records is by default sorted by ID. + description: Order of records on the page. diff --git a/docs/spec/components/schemas/ClaimEvent.yaml b/docs/spec/components/schemas/ClaimEvent.yaml deleted file mode 100644 index 25348b4..0000000 --- a/docs/spec/components/schemas/ClaimEvent.yaml +++ /dev/null @@ -1,17 +0,0 @@ -allOf: - - $ref: '#/components/schemas/ClaimEventKey' - - type: object - x-go-is-request: true - required: - - attributes - properties: - attributes: - type: object - required: - - user_did - - status - properties: - status: - type: string - description: New status. Just to be JSON:API compliant. - enum: [ claimed ] diff --git a/docs/spec/components/schemas/CreateBalance.yaml b/docs/spec/components/schemas/CreateBalance.yaml deleted file mode 100644 index d8d51d4..0000000 --- a/docs/spec/components/schemas/CreateBalance.yaml +++ /dev/null @@ -1,16 +0,0 @@ -allOf: - - $ref: '#/components/schemas/CreateBalanceKey' - - type: object - x-go-is-request: true - required: - - attributes - properties: - attributes: - type: object - required: - - user_did - properties: - user_did: - type: string - description: DID of the balance owner - example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" diff --git a/docs/spec/components/schemas/CreateBalanceKey.yaml b/docs/spec/components/schemas/CreateBalanceKey.yaml index 781ec34..ca44323 100644 --- a/docs/spec/components/schemas/CreateBalanceKey.yaml +++ b/docs/spec/components/schemas/CreateBalanceKey.yaml @@ -1,7 +1,12 @@ type: object required: + - id - type properties: + id: + type: string + description: DID of the points owner + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" type: type: string enum: [ create_balance ] diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml index 77ddd0f..9f3345b 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml @@ -16,7 +16,7 @@ post: - data properties: data: - $ref: '#/components/schemas/CreateBalance' + $ref: '#/components/schemas/CreateBalanceKey' responses: 201: description: Created @@ -49,6 +49,7 @@ get: parameters: - $ref: '#/components/parameters/pageCursor' - $ref: '#/components/parameters/pageLimit' + - $ref: '#/components/parameters/pageNumber' responses: 200: description: Success diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml index 6fdd600..2f57890 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml @@ -23,7 +23,7 @@ patch: - data properties: data: - $ref: '#/components/schemas/ClaimEvent' + $ref: '#/components/schemas/ClaimEventKey' responses: 200: description: Event claimed, points accrued diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index fd2f031..3af33b2 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -18,7 +18,7 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - did := req.Data.Attributes.UserDid + did := req.Data.ID balance := getBalanceByDID(did, false, w, r) if balance != nil { ape.RenderErr(w, problems.Conflict()) diff --git a/internal/service/handlers/get_balance.go b/internal/service/handlers/get_balance.go index ed011b0..fdcf138 100644 --- a/internal/service/handlers/get_balance.go +++ b/internal/service/handlers/get_balance.go @@ -18,7 +18,7 @@ func GetBalance(w http.ResponseWriter, r *http.Request) { return } - balance := getBalanceByDID(req.FilterDID, true, w, r) + balance := getBalanceByDID(req.DID, true, w, r) if balance == nil { return } diff --git a/internal/service/requests/claim_event.go b/internal/service/requests/claim_event.go index f74e365..8229ab4 100644 --- a/internal/service/requests/claim_event.go +++ b/internal/service/requests/claim_event.go @@ -7,20 +7,23 @@ import ( "github.com/go-chi/chi" validation "github.com/go-ozzo/ozzo-validation/v4" - "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/resources" ) -func NewClaimEvent(r *http.Request) (req resources.ClaimEventRequest, err error) { +func NewClaimEvent(r *http.Request) (req resources.Relation, err error) { id := chi.URLParam(r, "id") if err = json.NewDecoder(r.Body).Decode(&req); err != nil { err = fmt.Errorf("decode request body: %w", err) return } + if req.Data == nil { + err = validation.Errors{"data": validation.ErrRequired} + return + } + return req, validation.Errors{ - "data/id": validation.Validate(req.Data.ID, validation.Required, validation.In(id)), - "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.CLAIM_EVENT)), - "data/attributes/status": validation.Validate(req.Data.Attributes.Status, validation.Required, validation.In(data.EventClaimed)), + "data/id": validation.Validate(req.Data.ID, validation.Required, validation.In(id)), + "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.CLAIM_EVENT)), }.Filter() } diff --git a/internal/service/requests/create_balance.go b/internal/service/requests/create_balance.go index 298c7c2..04c44a8 100644 --- a/internal/service/requests/create_balance.go +++ b/internal/service/requests/create_balance.go @@ -9,15 +9,19 @@ import ( "github.com/rarimo/rarime-points-svc/resources" ) -func NewCreateBalance(r *http.Request) (req resources.CreateBalanceRequest, err error) { +func NewCreateBalance(r *http.Request) (req resources.Relation, err error) { if err = json.NewDecoder(r.Body).Decode(&req); err != nil { err = fmt.Errorf("decode request body: %w", err) return } + if req.Data == nil { + err = validation.Errors{"data": validation.ErrRequired} + return + } + return req, validation.Errors{ - "data/id": validation.Validate(req.Data.ID, validation.Empty), - "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.CREATE_BALANCE)), - "data/attributes/user_did": validation.Validate(req.Data.Attributes.UserDid, validation.Required), + "data/id": validation.Validate(req.Data.ID, validation.Required), + "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.CREATE_BALANCE)), }.Filter() } diff --git a/internal/service/requests/get_balance.go b/internal/service/requests/get_balance.go index d450a7b..b255f5d 100644 --- a/internal/service/requests/get_balance.go +++ b/internal/service/requests/get_balance.go @@ -1,26 +1,20 @@ package requests import ( - "fmt" "net/http" + "github.com/go-chi/chi" validation "github.com/go-ozzo/ozzo-validation/v4" - "gitlab.com/distributed_lab/urlval/v4" ) type GetBalance struct { - FilterDID string `filter:"did"` + DID string } -func NewGetBalance(r *http.Request) (req GetBalance, err error) { - if err = urlval.Decode(r.URL.Query(), &req); err != nil { - return req, validation.Errors{ - "query": fmt.Errorf("failed to decode query: %w", err), - } - } +func NewGetBalance(r *http.Request) (GetBalance, error) { + did := chi.URLParam(r, "did") - err = validation.Errors{ - "filter[did]": validation.Validate(req.FilterDID, validation.Required), + return GetBalance{did}, validation.Errors{ + "did": validation.Validate(did, validation.Required), }.Filter() - return } diff --git a/internal/service/router.go b/internal/service/router.go index bbb4ab5..ace9218 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -20,15 +20,15 @@ func (s *service) router() chi.Router { handlers.CtxEventTypes(s.cfg.EventTypes()), ), ) - r.Route("/integrations/rarime-points-svc", func(r chi.Router) { + r.Route("/integrations/rarime-points-svc/v1", func(r chi.Router) { r.Group(func(r chi.Router) { r.Use(handlers.AuthMiddleware(s.cfg.Auth(), s.log)) - r.Get("/balance", handlers.GetBalance) - r.Post("/balance", handlers.CreateBalance) + r.Get("/balances/{did}", handlers.GetBalance) + r.Post("/balances", handlers.CreateBalance) r.Get("/events", handlers.ListEvents) r.Patch("/events/{id}", handlers.ClaimEvent) }) - r.Get("/leaderboard", handlers.Leaderboard) + r.Get("/balances", handlers.Leaderboard) }) return r diff --git a/resources/model_claim_event.go b/resources/model_claim_event.go deleted file mode 100644 index 4b8fe7b..0000000 --- a/resources/model_claim_event.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * GENERATED. Do not modify. Your changes might be overwritten! - */ - -package resources - -import "encoding/json" - -type ClaimEvent struct { - Key - Attributes ClaimEventAttributes `json:"attributes"` -} -type ClaimEventRequest struct { - Data ClaimEvent `json:"data"` - Included Included `json:"included"` -} - -type ClaimEventListRequest struct { - Data []ClaimEvent `json:"data"` - Included Included `json:"included"` - Links *Links `json:"links"` - Meta json.RawMessage `json:"meta,omitempty"` -} - -func (r *ClaimEventListRequest) PutMeta(v interface{}) (err error) { - r.Meta, err = json.Marshal(v) - return err -} - -func (r *ClaimEventListRequest) GetMeta(out interface{}) error { - return json.Unmarshal(r.Meta, out) -} - -// MustClaimEvent - returns ClaimEvent from include collection. -// if entry with specified key does not exist - returns nil -// if entry with specified key exists but type or ID mismatches - panics -func (c *Included) MustClaimEvent(key Key) *ClaimEvent { - var claimEvent ClaimEvent - if c.tryFindEntry(key, &claimEvent) { - return &claimEvent - } - return nil -} diff --git a/resources/model_claim_event_attributes.go b/resources/model_claim_event_attributes.go deleted file mode 100644 index ec7e93f..0000000 --- a/resources/model_claim_event_attributes.go +++ /dev/null @@ -1,10 +0,0 @@ -/* - * GENERATED. Do not modify. Your changes might be overwritten! - */ - -package resources - -type ClaimEventAttributes struct { - // New status. Just to be JSON:API compliant. - Status string `json:"status"` -} diff --git a/resources/model_create_balance.go b/resources/model_create_balance.go deleted file mode 100644 index e3ae5ec..0000000 --- a/resources/model_create_balance.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * GENERATED. Do not modify. Your changes might be overwritten! - */ - -package resources - -import "encoding/json" - -type CreateBalance struct { - Key - Attributes CreateBalanceAttributes `json:"attributes"` -} -type CreateBalanceRequest struct { - Data CreateBalance `json:"data"` - Included Included `json:"included"` -} - -type CreateBalanceListRequest struct { - Data []CreateBalance `json:"data"` - Included Included `json:"included"` - Links *Links `json:"links"` - Meta json.RawMessage `json:"meta,omitempty"` -} - -func (r *CreateBalanceListRequest) PutMeta(v interface{}) (err error) { - r.Meta, err = json.Marshal(v) - return err -} - -func (r *CreateBalanceListRequest) GetMeta(out interface{}) error { - return json.Unmarshal(r.Meta, out) -} - -// MustCreateBalance - returns CreateBalance from include collection. -// if entry with specified key does not exist - returns nil -// if entry with specified key exists but type or ID mismatches - panics -func (c *Included) MustCreateBalance(key Key) *CreateBalance { - var createBalance CreateBalance - if c.tryFindEntry(key, &createBalance) { - return &createBalance - } - return nil -} diff --git a/resources/model_create_balance_attributes.go b/resources/model_create_balance_attributes.go deleted file mode 100644 index c9fb8a1..0000000 --- a/resources/model_create_balance_attributes.go +++ /dev/null @@ -1,10 +0,0 @@ -/* - * GENERATED. Do not modify. Your changes might be overwritten! - */ - -package resources - -type CreateBalanceAttributes struct { - // DID of the balance owner - UserDid string `json:"user_did"` -} From c4666638dbb0af92cf8d64243eecfb17a7670a8b Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 24 Jan 2024 21:12:03 +0200 Subject: [PATCH 45/63] Add SBT check config and connector --- config.yaml | 11 + go.mod | 2 +- go.sum | 4 + internal/config/main.go | 10 +- internal/sbtcheck/config.go | 73 +++ internal/sbtcheck/erc721/IERC721.go | 919 ++++++++++++++++++++++++++++ internal/sbtcheck/main.go | 46 ++ internal/service/handlers/ctx.go | 12 + internal/service/router.go | 1 + 9 files changed, 1074 insertions(+), 4 deletions(-) create mode 100644 internal/sbtcheck/config.go create mode 100644 internal/sbtcheck/erc721/IERC721.go create mode 100644 internal/sbtcheck/main.go diff --git a/config.yaml b/config.yaml index fb00bc1..3a7b3ac 100644 --- a/config.yaml +++ b/config.yaml @@ -31,3 +31,14 @@ event_types: auth: addr: http://rarime-auth + +sbt_check: + networks: + - name: polygon + rpc: https://your-rpc + request_timeout: 3s + contract: 0x... + - name: ethereum + rpc: https://your-rpc + request_timeout: 5s + contract: 0x... diff --git a/go.mod b/go.mod index f6dd9f5..a769404 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21.3 require ( github.com/Masterminds/squirrel v1.4.0 github.com/alecthomas/kingpin v2.2.6+incompatible + github.com/ethereum/go-ethereum v1.13.11 github.com/go-chi/chi v4.1.2+incompatible github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/rarimo/rarime-auth-svc v0.0.1-rc9 @@ -30,7 +31,6 @@ require ( github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/ethereum/go-ethereum v1.13.11 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/raven-go v0.2.0 // indirect github.com/getsentry/sentry-go v0.26.0 // indirect diff --git a/go.sum b/go.sum index 5caa962..80b07bb 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= @@ -152,6 +154,8 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= github.com/google/jsonapi v1.0.0 h1:qIGgO5Smu3yJmSs+QlvhQnrscdZfFhiV6S8ryJAglqU= github.com/google/jsonapi v1.0.0/go.mod h1:YYHiRPJT8ARXGER8In9VuLv4qvLfDmA9ULQqptbLE4s= diff --git a/internal/config/main.go b/internal/config/main.go index 95ce2b1..5475c13 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -3,6 +3,7 @@ package config import ( "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" + "github.com/rarimo/rarime-points-svc/internal/sbtcheck" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/copus" "gitlab.com/distributed_lab/kit/copus/types" @@ -15,8 +16,9 @@ type Config interface { pgdb.Databaser types.Copuser comfig.Listenerer - evtypes.EventTypeser auth.Auther + evtypes.EventTypeser + sbtcheck.SbtChecker } type config struct { @@ -24,8 +26,9 @@ type config struct { pgdb.Databaser types.Copuser comfig.Listenerer - evtypes.EventTypeser auth.Auther + evtypes.EventTypeser + sbtcheck.SbtChecker getter kv.Getter } @@ -38,6 +41,7 @@ func New(getter kv.Getter) Config { Listenerer: comfig.NewListenerer(getter), Logger: comfig.NewLogger(getter, comfig.LoggerOpts{}), EventTypeser: evtypes.NewConfig(getter), - Auther: auth.NewAuther(getter), + Auther: auth.NewAuther(getter), //nolint:misspell + SbtChecker: sbtcheck.NewConfig(getter), } } diff --git a/internal/sbtcheck/config.go b/internal/sbtcheck/config.go new file mode 100644 index 0000000..8807c16 --- /dev/null +++ b/internal/sbtcheck/config.go @@ -0,0 +1,73 @@ +package sbtcheck + +import ( + "fmt" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/rarimo/rarime-points-svc/internal/sbtcheck/erc721" + "gitlab.com/distributed_lab/figure/v3" + "gitlab.com/distributed_lab/kit/comfig" + "gitlab.com/distributed_lab/kit/kv" +) + +const baseTimeout = 5 * time.Second + +type SbtChecker interface { + SbtCheck() *Connector +} + +type config struct { + once comfig.Once + getter kv.Getter +} + +func NewConfig(getter kv.Getter) SbtChecker { + return &config{getter: getter} +} + +func (c *config) SbtCheck() *Connector { + return c.once.Do(func() interface{} { + var cfg struct { + Networks []struct { + Name string `fig:"name,required"` + RPC string `fig:"rpc,required"` + Contract string `fig:"contract,required"` + RequestTimeout time.Duration `fig:"request_timeout"` + } `fig:"networks,required"` + } + + err := figure.Out(&cfg). + From(kv.MustGetStringMap(c.getter, "sbt_check")). + Please() + if err != nil { + panic(fmt.Errorf("failed to figure out sbt_check: %s", err)) + } + + nmap := make(map[string]network, len(cfg.Networks)) + for _, net := range cfg.Networks { + + cli, err := ethclient.Dial(net.RPC) + if err != nil { + panic(fmt.Errorf("failed to connect to rpc: %w", err)) + } + + caller, err := erc721.NewIERC721Caller(common.HexToAddress(net.Contract), cli) + if err != nil { + panic(fmt.Errorf("failed to init contract caller: %w", err)) + } + + if net.RequestTimeout == 0 { + net.RequestTimeout = baseTimeout + } + + nmap[net.Name] = network{ + caller: caller, + timeout: net.RequestTimeout, + } + } + + return &Connector{networks: nmap} + }).(*Connector) +} diff --git a/internal/sbtcheck/erc721/IERC721.go b/internal/sbtcheck/erc721/IERC721.go new file mode 100644 index 0000000..bf2e376 --- /dev/null +++ b/internal/sbtcheck/erc721/IERC721.go @@ -0,0 +1,919 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package erc721 + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// IERC721MetaData contains all meta data concerning the IERC721 contract. +var IERC721MetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// IERC721ABI is the input ABI used to generate the binding from. +// Deprecated: Use IERC721MetaData.ABI instead. +var IERC721ABI = IERC721MetaData.ABI + +// IERC721 is an auto generated Go binding around an Ethereum contract. +type IERC721 struct { + IERC721Caller // Read-only binding to the contract + IERC721Transactor // Write-only binding to the contract + IERC721Filterer // Log filterer for contract events +} + +// IERC721Caller is an auto generated read-only Go binding around an Ethereum contract. +type IERC721Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IERC721Transactor is an auto generated write-only Go binding around an Ethereum contract. +type IERC721Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IERC721Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IERC721Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IERC721Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IERC721Session struct { + Contract *IERC721 // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IERC721CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IERC721CallerSession struct { + Contract *IERC721Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IERC721TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IERC721TransactorSession struct { + Contract *IERC721Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IERC721Raw is an auto generated low-level Go binding around an Ethereum contract. +type IERC721Raw struct { + Contract *IERC721 // Generic contract binding to access the raw methods on +} + +// IERC721CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IERC721CallerRaw struct { + Contract *IERC721Caller // Generic read-only contract binding to access the raw methods on +} + +// IERC721TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IERC721TransactorRaw struct { + Contract *IERC721Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewIERC721 creates a new instance of IERC721, bound to a specific deployed contract. +func NewIERC721(address common.Address, backend bind.ContractBackend) (*IERC721, error) { + contract, err := bindIERC721(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IERC721{IERC721Caller: IERC721Caller{contract: contract}, IERC721Transactor: IERC721Transactor{contract: contract}, IERC721Filterer: IERC721Filterer{contract: contract}}, nil +} + +// NewIERC721Caller creates a new read-only instance of IERC721, bound to a specific deployed contract. +func NewIERC721Caller(address common.Address, caller bind.ContractCaller) (*IERC721Caller, error) { + contract, err := bindIERC721(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IERC721Caller{contract: contract}, nil +} + +// NewIERC721Transactor creates a new write-only instance of IERC721, bound to a specific deployed contract. +func NewIERC721Transactor(address common.Address, transactor bind.ContractTransactor) (*IERC721Transactor, error) { + contract, err := bindIERC721(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IERC721Transactor{contract: contract}, nil +} + +// NewIERC721Filterer creates a new log filterer instance of IERC721, bound to a specific deployed contract. +func NewIERC721Filterer(address common.Address, filterer bind.ContractFilterer) (*IERC721Filterer, error) { + contract, err := bindIERC721(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IERC721Filterer{contract: contract}, nil +} + +// bindIERC721 binds a generic wrapper to an already deployed contract. +func bindIERC721(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IERC721MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IERC721 *IERC721Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IERC721.Contract.IERC721Caller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IERC721 *IERC721Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IERC721.Contract.IERC721Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IERC721 *IERC721Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IERC721.Contract.IERC721Transactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IERC721 *IERC721CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IERC721.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IERC721 *IERC721TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IERC721.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IERC721 *IERC721TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IERC721.Contract.contract.Transact(opts, method, params...) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address owner) view returns(uint256 balance) +func (_IERC721 *IERC721Caller) BalanceOf(opts *bind.CallOpts, owner common.Address) (*big.Int, error) { + var out []interface{} + err := _IERC721.contract.Call(opts, &out, "balanceOf", owner) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address owner) view returns(uint256 balance) +func (_IERC721 *IERC721Session) BalanceOf(owner common.Address) (*big.Int, error) { + return _IERC721.Contract.BalanceOf(&_IERC721.CallOpts, owner) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address owner) view returns(uint256 balance) +func (_IERC721 *IERC721CallerSession) BalanceOf(owner common.Address) (*big.Int, error) { + return _IERC721.Contract.BalanceOf(&_IERC721.CallOpts, owner) +} + +// GetApproved is a free data retrieval call binding the contract method 0x081812fc. +// +// Solidity: function getApproved(uint256 tokenId) view returns(address operator) +func (_IERC721 *IERC721Caller) GetApproved(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { + var out []interface{} + err := _IERC721.contract.Call(opts, &out, "getApproved", tokenId) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetApproved is a free data retrieval call binding the contract method 0x081812fc. +// +// Solidity: function getApproved(uint256 tokenId) view returns(address operator) +func (_IERC721 *IERC721Session) GetApproved(tokenId *big.Int) (common.Address, error) { + return _IERC721.Contract.GetApproved(&_IERC721.CallOpts, tokenId) +} + +// GetApproved is a free data retrieval call binding the contract method 0x081812fc. +// +// Solidity: function getApproved(uint256 tokenId) view returns(address operator) +func (_IERC721 *IERC721CallerSession) GetApproved(tokenId *big.Int) (common.Address, error) { + return _IERC721.Contract.GetApproved(&_IERC721.CallOpts, tokenId) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_IERC721 *IERC721Caller) IsApprovedForAll(opts *bind.CallOpts, owner common.Address, operator common.Address) (bool, error) { + var out []interface{} + err := _IERC721.contract.Call(opts, &out, "isApprovedForAll", owner, operator) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_IERC721 *IERC721Session) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { + return _IERC721.Contract.IsApprovedForAll(&_IERC721.CallOpts, owner, operator) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_IERC721 *IERC721CallerSession) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { + return _IERC721.Contract.IsApprovedForAll(&_IERC721.CallOpts, owner, operator) +} + +// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. +// +// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) +func (_IERC721 *IERC721Caller) OwnerOf(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { + var out []interface{} + err := _IERC721.contract.Call(opts, &out, "ownerOf", tokenId) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. +// +// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) +func (_IERC721 *IERC721Session) OwnerOf(tokenId *big.Int) (common.Address, error) { + return _IERC721.Contract.OwnerOf(&_IERC721.CallOpts, tokenId) +} + +// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. +// +// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) +func (_IERC721 *IERC721CallerSession) OwnerOf(tokenId *big.Int) (common.Address, error) { + return _IERC721.Contract.OwnerOf(&_IERC721.CallOpts, tokenId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_IERC721 *IERC721Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _IERC721.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_IERC721 *IERC721Session) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _IERC721.Contract.SupportsInterface(&_IERC721.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_IERC721 *IERC721CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _IERC721.Contract.SupportsInterface(&_IERC721.CallOpts, interfaceId) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address to, uint256 tokenId) returns() +func (_IERC721 *IERC721Transactor) Approve(opts *bind.TransactOpts, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.contract.Transact(opts, "approve", to, tokenId) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address to, uint256 tokenId) returns() +func (_IERC721 *IERC721Session) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.Contract.Approve(&_IERC721.TransactOpts, to, tokenId) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address to, uint256 tokenId) returns() +func (_IERC721 *IERC721TransactorSession) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.Contract.Approve(&_IERC721.TransactOpts, to, tokenId) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() +func (_IERC721 *IERC721Transactor) SafeTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.contract.Transact(opts, "safeTransferFrom", from, to, tokenId) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() +func (_IERC721 *IERC721Session) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.Contract.SafeTransferFrom(&_IERC721.TransactOpts, from, to, tokenId) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() +func (_IERC721 *IERC721TransactorSession) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.Contract.SafeTransferFrom(&_IERC721.TransactOpts, from, to, tokenId) +} + +// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() +func (_IERC721 *IERC721Transactor) SafeTransferFrom0(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { + return _IERC721.contract.Transact(opts, "safeTransferFrom0", from, to, tokenId, data) +} + +// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() +func (_IERC721 *IERC721Session) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { + return _IERC721.Contract.SafeTransferFrom0(&_IERC721.TransactOpts, from, to, tokenId, data) +} + +// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() +func (_IERC721 *IERC721TransactorSession) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { + return _IERC721.Contract.SafeTransferFrom0(&_IERC721.TransactOpts, from, to, tokenId, data) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_IERC721 *IERC721Transactor) SetApprovalForAll(opts *bind.TransactOpts, operator common.Address, approved bool) (*types.Transaction, error) { + return _IERC721.contract.Transact(opts, "setApprovalForAll", operator, approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_IERC721 *IERC721Session) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { + return _IERC721.Contract.SetApprovalForAll(&_IERC721.TransactOpts, operator, approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool approved) returns() +func (_IERC721 *IERC721TransactorSession) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { + return _IERC721.Contract.SetApprovalForAll(&_IERC721.TransactOpts, operator, approved) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() +func (_IERC721 *IERC721Transactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.contract.Transact(opts, "transferFrom", from, to, tokenId) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() +func (_IERC721 *IERC721Session) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.Contract.TransferFrom(&_IERC721.TransactOpts, from, to, tokenId) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() +func (_IERC721 *IERC721TransactorSession) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _IERC721.Contract.TransferFrom(&_IERC721.TransactOpts, from, to, tokenId) +} + +// IERC721ApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the IERC721 contract. +type IERC721ApprovalIterator struct { + Event *IERC721Approval // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IERC721ApprovalIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IERC721Approval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IERC721Approval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IERC721ApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IERC721ApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IERC721Approval represents a Approval event raised by the IERC721 contract. +type IERC721Approval struct { + Owner common.Address + Approved common.Address + TokenId *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) +func (_IERC721 *IERC721Filterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, approved []common.Address, tokenId []*big.Int) (*IERC721ApprovalIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var approvedRule []interface{} + for _, approvedItem := range approved { + approvedRule = append(approvedRule, approvedItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _IERC721.contract.FilterLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) + if err != nil { + return nil, err + } + return &IERC721ApprovalIterator{contract: _IERC721.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) +func (_IERC721 *IERC721Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *IERC721Approval, owner []common.Address, approved []common.Address, tokenId []*big.Int) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var approvedRule []interface{} + for _, approvedItem := range approved { + approvedRule = append(approvedRule, approvedItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _IERC721.contract.WatchLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IERC721Approval) + if err := _IERC721.contract.UnpackLog(event, "Approval", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) +func (_IERC721 *IERC721Filterer) ParseApproval(log types.Log) (*IERC721Approval, error) { + event := new(IERC721Approval) + if err := _IERC721.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IERC721ApprovalForAllIterator is returned from FilterApprovalForAll and is used to iterate over the raw logs and unpacked data for ApprovalForAll events raised by the IERC721 contract. +type IERC721ApprovalForAllIterator struct { + Event *IERC721ApprovalForAll // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IERC721ApprovalForAllIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IERC721ApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IERC721ApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IERC721ApprovalForAllIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IERC721ApprovalForAllIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IERC721ApprovalForAll represents a ApprovalForAll event raised by the IERC721 contract. +type IERC721ApprovalForAll struct { + Owner common.Address + Operator common.Address + Approved bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApprovalForAll is a free log retrieval operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) +func (_IERC721 *IERC721Filterer) FilterApprovalForAll(opts *bind.FilterOpts, owner []common.Address, operator []common.Address) (*IERC721ApprovalForAllIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _IERC721.contract.FilterLogs(opts, "ApprovalForAll", ownerRule, operatorRule) + if err != nil { + return nil, err + } + return &IERC721ApprovalForAllIterator{contract: _IERC721.contract, event: "ApprovalForAll", logs: logs, sub: sub}, nil +} + +// WatchApprovalForAll is a free log subscription operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) +func (_IERC721 *IERC721Filterer) WatchApprovalForAll(opts *bind.WatchOpts, sink chan<- *IERC721ApprovalForAll, owner []common.Address, operator []common.Address) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _IERC721.contract.WatchLogs(opts, "ApprovalForAll", ownerRule, operatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IERC721ApprovalForAll) + if err := _IERC721.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApprovalForAll is a log parse operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) +func (_IERC721 *IERC721Filterer) ParseApprovalForAll(log types.Log) (*IERC721ApprovalForAll, error) { + event := new(IERC721ApprovalForAll) + if err := _IERC721.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IERC721TransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the IERC721 contract. +type IERC721TransferIterator struct { + Event *IERC721Transfer // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IERC721TransferIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IERC721Transfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IERC721Transfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IERC721TransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IERC721TransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IERC721Transfer represents a Transfer event raised by the IERC721 contract. +type IERC721Transfer struct { + From common.Address + To common.Address + TokenId *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) +func (_IERC721 *IERC721Filterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address, tokenId []*big.Int) (*IERC721TransferIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _IERC721.contract.FilterLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) + if err != nil { + return nil, err + } + return &IERC721TransferIterator{contract: _IERC721.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) +func (_IERC721 *IERC721Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *IERC721Transfer, from []common.Address, to []common.Address, tokenId []*big.Int) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _IERC721.contract.WatchLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IERC721Transfer) + if err := _IERC721.contract.UnpackLog(event, "Transfer", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) +func (_IERC721 *IERC721Filterer) ParseTransfer(log types.Log) (*IERC721Transfer, error) { + event := new(IERC721Transfer) + if err := _IERC721.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go new file mode 100644 index 0000000..d491842 --- /dev/null +++ b/internal/sbtcheck/main.go @@ -0,0 +1,46 @@ +package sbtcheck + +import ( + "context" + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/rarimo/rarime-points-svc/internal/sbtcheck/erc721" +) + +var ErrUnsupportedNetwork = errors.New("unsupported network") + +type Connector struct { + networks map[string]network +} + +type network struct { + caller *erc721.IERC721Caller + timeout time.Duration +} + +func (c *Connector) IsSbtOwner(ctx context.Context, network, userAddress string) (bool, error) { + net, ok := c.networks[network] + if !ok { + return false, fmt.Errorf("%w: %s", ErrUnsupportedNetwork, network) + } + + toCtx, cancel := context.WithTimeout(ctx, net.timeout) + defer cancel() + + balance, err := net.caller.BalanceOf(&bind.CallOpts{Context: toCtx}, common.HexToAddress(userAddress)) + if err != nil { + return false, fmt.Errorf("check ERC721 SBT balance (network=%s userAddress=%s]: %w", network, userAddress, err) + } + + return balance.Cmp(big.NewInt(0)) == 1, nil +} + +func (c *Connector) IsNetworkSupported(network string) bool { + _, ok := c.networks[network] + return ok +} diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index 16b5fb3..b3f0e77 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -7,6 +7,7 @@ import ( "github.com/rarimo/rarime-auth-svc/resources" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" + "github.com/rarimo/rarime-points-svc/internal/sbtcheck" "gitlab.com/distributed_lab/logan/v3" ) @@ -18,6 +19,7 @@ const ( balancesQCtxKey eventTypesCtxKey userClaimsCtxKey + sbtCheckCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -69,3 +71,13 @@ func CtxUserClaims(claim []resources.Claim) func(context.Context) context.Contex func UserClaims(r *http.Request) []resources.Claim { return r.Context().Value(userClaimsCtxKey).([]resources.Claim) } + +func CtxSbtCheck(sbtCheck *sbtcheck.Connector) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, sbtCheckCtxKey, sbtCheck) + } +} + +func SbtCheck(r *http.Request) *sbtcheck.Connector { + return r.Context().Value(sbtCheckCtxKey).(*sbtcheck.Connector) +} diff --git a/internal/service/router.go b/internal/service/router.go index ace9218..e4686e3 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -18,6 +18,7 @@ func (s *service) router() chi.Router { handlers.CtxEventsQ(pg.NewEvents(s.cfg.DB())), handlers.CtxBalancesQ(pg.NewBalances(s.cfg.DB())), handlers.CtxEventTypes(s.cfg.EventTypes()), + handlers.CtxSbtCheck(s.cfg.SbtCheck()), ), ) r.Route("/integrations/rarime-points-svc/v1", func(r chi.Router) { From dbe92e5a9ca265e22261a3f19f7ac1a9c2a0914c Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 25 Jan 2024 16:07:22 +0200 Subject: [PATCH 46/63] Fully rewrite PoH SBT logic to runner --- config.yaml | 5 + ...ions@rarime-points-svc@v1@events@{id}.yaml | 2 + go.mod | 3 + go.sum | 6 + internal/cli/main.go | 10 +- internal/data/evtypes/config.go | 4 + internal/data/evtypes/main.go | 25 + internal/sbtcheck/config.go | 21 +- internal/sbtcheck/erc721/IERC721.go | 919 ---------- internal/sbtcheck/main.go | 199 +- .../sbtcheck/verifiers/SBTIdentityVerifier.go | 1605 +++++++++++++++++ internal/service/handlers/create_balance.go | 24 +- internal/service/handlers/ctx.go | 6 +- 13 files changed, 1858 insertions(+), 971 deletions(-) delete mode 100644 internal/sbtcheck/erc721/IERC721.go create mode 100644 internal/sbtcheck/verifiers/SBTIdentityVerifier.go diff --git a/config.yaml b/config.yaml index 3a7b3ac..7264868 100644 --- a/config.yaml +++ b/config.yaml @@ -42,3 +42,8 @@ sbt_check: rpc: https://your-rpc request_timeout: 5s contract: 0x... + - name: disabled_sample + disabled: true + rpc: https://your-rpc + request_timeout: 5s + contract: 0x... diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml index 2f57890..864447f 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@events@{id}.yaml @@ -45,5 +45,7 @@ patch: $ref: '#/components/responses/invalidParameter' 401: $ref: '#/components/responses/invalidAuth' + 404: + $ref: '#/components/responses/notFound' 500: $ref: '#/components/responses/internalError' diff --git a/go.mod b/go.mod index a769404..c804b70 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/ethereum/go-ethereum v1.13.11 github.com/go-chi/chi v4.1.2+incompatible github.com/go-ozzo/ozzo-validation/v4 v4.3.0 + github.com/iden3/go-iden3-core/v2 v2.0.3 github.com/rarimo/rarime-auth-svc v0.0.1-rc9 github.com/rubenv/sql-migrate v1.6.1 gitlab.com/distributed_lab/ape v1.7.1 @@ -42,6 +43,7 @@ require ( github.com/gorilla/websocket v1.4.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect + github.com/iden3/go-iden3-crypto v0.0.15 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -49,6 +51,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect diff --git a/go.sum b/go.sum index 80b07bb..6148ed7 100644 --- a/go.sum +++ b/go.sum @@ -180,6 +180,10 @@ github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/iden3/go-iden3-core/v2 v2.0.3 h1:ce9Jbw10zDsinWXFc05SiK2Hof/wu4zV4/ai5gQy29k= +github.com/iden3/go-iden3-core/v2 v2.0.3/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw= +github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= +github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -262,6 +266,8 @@ github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFV github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= diff --git a/internal/cli/main.go b/internal/cli/main.go index 41bddf0..78ce6dc 100644 --- a/internal/cli/main.go +++ b/internal/cli/main.go @@ -1,6 +1,8 @@ package cli import ( + "context" + "github.com/alecthomas/kingpin" "github.com/rarimo/rarime-points-svc/internal/config" "github.com/rarimo/rarime-points-svc/internal/service" @@ -29,8 +31,6 @@ func Run(args []string) bool { migrateUpCmd := migrateCmd.Command("up", "migrate db up") migrateDownCmd := migrateCmd.Command("down", "migrate db down") - // custom commands go here... - cmd, err := app.Parse(args[1:]) if err != nil { log.WithError(err).Error("failed to parse arguments") @@ -39,12 +39,16 @@ func Run(args []string) bool { switch cmd { case serviceCmd.FullCommand(): + if err = cfg.SbtCheck().Run(context.Background()); err != nil { + log.WithError(err).Error("Failed to run sbt checker") + return false + } service.Run(cfg) + case migrateUpCmd.FullCommand(): err = MigrateUp(cfg) case migrateDownCmd.FullCommand(): err = MigrateDown(cfg) - // handle any custom commands here in the same way default: log.Errorf("unknown command %s", cmd) return false diff --git a/internal/data/evtypes/config.go b/internal/data/evtypes/config.go index a918106..57357b2 100644 --- a/internal/data/evtypes/config.go +++ b/internal/data/evtypes/config.go @@ -59,6 +59,10 @@ func (c *config) EventTypes() Types { } } + if _, ok := inner[TypeGetPoH]; !ok { + panic(fmt.Errorf("event_types: missing %s entry", TypeGetPoH)) + } + return Types{inner} }).(Types) } diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index 125cd12..700f95b 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -1,8 +1,10 @@ package evtypes import ( + "database/sql" "time" + "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/resources" ) @@ -20,6 +22,8 @@ const ( Custom Frequency = "custom" ) +const TypeGetPoH = "get_poh" + type Types struct { inner map[string]resources.EventStaticMeta } @@ -37,6 +41,27 @@ func (t Types) Get(name string) *resources.EventStaticMeta { return &v } +func (t Types) PrepareOpenEvents(balanceID string) []data.Event { + evTypes := t.List() + events := make([]data.Event, len(evTypes)) + + for i, evType := range evTypes { + // TODO: add advanced logic for specific event types + // for example, proof verification events should appear after the proof was issued + events[i] = data.Event{ + BalanceID: balanceID, + Type: evType.Name, + Status: data.EventOpen, + PointsAmount: sql.NullInt32{ + Int32: evType.Reward, + Valid: true, + }, + } + } + + return events +} + // List returns non-expired event types func (t Types) List() []resources.EventStaticMeta { if t.inner == nil { diff --git a/internal/sbtcheck/config.go b/internal/sbtcheck/config.go index 8807c16..2ba9e3d 100644 --- a/internal/sbtcheck/config.go +++ b/internal/sbtcheck/config.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/rarimo/rarime-points-svc/internal/sbtcheck/erc721" + "github.com/rarimo/rarime-points-svc/internal/sbtcheck/verifiers" "gitlab.com/distributed_lab/figure/v3" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/kv" @@ -15,7 +15,7 @@ import ( const baseTimeout = 5 * time.Second type SbtChecker interface { - SbtCheck() *Connector + SbtCheck() *Runner } type config struct { @@ -27,7 +27,7 @@ func NewConfig(getter kv.Getter) SbtChecker { return &config{getter: getter} } -func (c *config) SbtCheck() *Connector { +func (c *config) SbtCheck() *Runner { return c.once.Do(func() interface{} { var cfg struct { Networks []struct { @@ -35,6 +35,7 @@ func (c *config) SbtCheck() *Connector { RPC string `fig:"rpc,required"` Contract string `fig:"contract,required"` RequestTimeout time.Duration `fig:"request_timeout"` + Disabled bool `fig:"disabled"` } `fig:"networks,required"` } @@ -47,15 +48,19 @@ func (c *config) SbtCheck() *Connector { nmap := make(map[string]network, len(cfg.Networks)) for _, net := range cfg.Networks { + if net.Disabled { + nmap[net.Name] = network{disabled: true} + continue + } cli, err := ethclient.Dial(net.RPC) if err != nil { panic(fmt.Errorf("failed to connect to rpc: %w", err)) } - caller, err := erc721.NewIERC721Caller(common.HexToAddress(net.Contract), cli) + filterer, err := verifiers.NewSBTIdentityVerifierFilterer(common.HexToAddress(net.Contract), cli) if err != nil { - panic(fmt.Errorf("failed to init contract caller: %w", err)) + panic(fmt.Errorf("failed to init contract filterer: %w", err)) } if net.RequestTimeout == 0 { @@ -63,11 +68,11 @@ func (c *config) SbtCheck() *Connector { } nmap[net.Name] = network{ - caller: caller, + events: filterer, timeout: net.RequestTimeout, } } - return &Connector{networks: nmap} - }).(*Connector) + return &Runner{networks: nmap} + }).(*Runner) } diff --git a/internal/sbtcheck/erc721/IERC721.go b/internal/sbtcheck/erc721/IERC721.go deleted file mode 100644 index bf2e376..0000000 --- a/internal/sbtcheck/erc721/IERC721.go +++ /dev/null @@ -1,919 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package erc721 - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// IERC721MetaData contains all meta data concerning the IERC721 contract. -var IERC721MetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", -} - -// IERC721ABI is the input ABI used to generate the binding from. -// Deprecated: Use IERC721MetaData.ABI instead. -var IERC721ABI = IERC721MetaData.ABI - -// IERC721 is an auto generated Go binding around an Ethereum contract. -type IERC721 struct { - IERC721Caller // Read-only binding to the contract - IERC721Transactor // Write-only binding to the contract - IERC721Filterer // Log filterer for contract events -} - -// IERC721Caller is an auto generated read-only Go binding around an Ethereum contract. -type IERC721Caller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IERC721Transactor is an auto generated write-only Go binding around an Ethereum contract. -type IERC721Transactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IERC721Filterer is an auto generated log filtering Go binding around an Ethereum contract events. -type IERC721Filterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IERC721Session is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type IERC721Session struct { - Contract *IERC721 // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IERC721CallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type IERC721CallerSession struct { - Contract *IERC721Caller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// IERC721TransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type IERC721TransactorSession struct { - Contract *IERC721Transactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IERC721Raw is an auto generated low-level Go binding around an Ethereum contract. -type IERC721Raw struct { - Contract *IERC721 // Generic contract binding to access the raw methods on -} - -// IERC721CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type IERC721CallerRaw struct { - Contract *IERC721Caller // Generic read-only contract binding to access the raw methods on -} - -// IERC721TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type IERC721TransactorRaw struct { - Contract *IERC721Transactor // Generic write-only contract binding to access the raw methods on -} - -// NewIERC721 creates a new instance of IERC721, bound to a specific deployed contract. -func NewIERC721(address common.Address, backend bind.ContractBackend) (*IERC721, error) { - contract, err := bindIERC721(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &IERC721{IERC721Caller: IERC721Caller{contract: contract}, IERC721Transactor: IERC721Transactor{contract: contract}, IERC721Filterer: IERC721Filterer{contract: contract}}, nil -} - -// NewIERC721Caller creates a new read-only instance of IERC721, bound to a specific deployed contract. -func NewIERC721Caller(address common.Address, caller bind.ContractCaller) (*IERC721Caller, error) { - contract, err := bindIERC721(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &IERC721Caller{contract: contract}, nil -} - -// NewIERC721Transactor creates a new write-only instance of IERC721, bound to a specific deployed contract. -func NewIERC721Transactor(address common.Address, transactor bind.ContractTransactor) (*IERC721Transactor, error) { - contract, err := bindIERC721(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &IERC721Transactor{contract: contract}, nil -} - -// NewIERC721Filterer creates a new log filterer instance of IERC721, bound to a specific deployed contract. -func NewIERC721Filterer(address common.Address, filterer bind.ContractFilterer) (*IERC721Filterer, error) { - contract, err := bindIERC721(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &IERC721Filterer{contract: contract}, nil -} - -// bindIERC721 binds a generic wrapper to an already deployed contract. -func bindIERC721(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := IERC721MetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_IERC721 *IERC721Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IERC721.Contract.IERC721Caller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_IERC721 *IERC721Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IERC721.Contract.IERC721Transactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_IERC721 *IERC721Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IERC721.Contract.IERC721Transactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_IERC721 *IERC721CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IERC721.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_IERC721 *IERC721TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IERC721.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_IERC721 *IERC721TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IERC721.Contract.contract.Transact(opts, method, params...) -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address owner) view returns(uint256 balance) -func (_IERC721 *IERC721Caller) BalanceOf(opts *bind.CallOpts, owner common.Address) (*big.Int, error) { - var out []interface{} - err := _IERC721.contract.Call(opts, &out, "balanceOf", owner) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address owner) view returns(uint256 balance) -func (_IERC721 *IERC721Session) BalanceOf(owner common.Address) (*big.Int, error) { - return _IERC721.Contract.BalanceOf(&_IERC721.CallOpts, owner) -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address owner) view returns(uint256 balance) -func (_IERC721 *IERC721CallerSession) BalanceOf(owner common.Address) (*big.Int, error) { - return _IERC721.Contract.BalanceOf(&_IERC721.CallOpts, owner) -} - -// GetApproved is a free data retrieval call binding the contract method 0x081812fc. -// -// Solidity: function getApproved(uint256 tokenId) view returns(address operator) -func (_IERC721 *IERC721Caller) GetApproved(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { - var out []interface{} - err := _IERC721.contract.Call(opts, &out, "getApproved", tokenId) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GetApproved is a free data retrieval call binding the contract method 0x081812fc. -// -// Solidity: function getApproved(uint256 tokenId) view returns(address operator) -func (_IERC721 *IERC721Session) GetApproved(tokenId *big.Int) (common.Address, error) { - return _IERC721.Contract.GetApproved(&_IERC721.CallOpts, tokenId) -} - -// GetApproved is a free data retrieval call binding the contract method 0x081812fc. -// -// Solidity: function getApproved(uint256 tokenId) view returns(address operator) -func (_IERC721 *IERC721CallerSession) GetApproved(tokenId *big.Int) (common.Address, error) { - return _IERC721.Contract.GetApproved(&_IERC721.CallOpts, tokenId) -} - -// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. -// -// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) -func (_IERC721 *IERC721Caller) IsApprovedForAll(opts *bind.CallOpts, owner common.Address, operator common.Address) (bool, error) { - var out []interface{} - err := _IERC721.contract.Call(opts, &out, "isApprovedForAll", owner, operator) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. -// -// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) -func (_IERC721 *IERC721Session) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { - return _IERC721.Contract.IsApprovedForAll(&_IERC721.CallOpts, owner, operator) -} - -// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. -// -// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) -func (_IERC721 *IERC721CallerSession) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { - return _IERC721.Contract.IsApprovedForAll(&_IERC721.CallOpts, owner, operator) -} - -// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. -// -// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) -func (_IERC721 *IERC721Caller) OwnerOf(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { - var out []interface{} - err := _IERC721.contract.Call(opts, &out, "ownerOf", tokenId) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. -// -// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) -func (_IERC721 *IERC721Session) OwnerOf(tokenId *big.Int) (common.Address, error) { - return _IERC721.Contract.OwnerOf(&_IERC721.CallOpts, tokenId) -} - -// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. -// -// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) -func (_IERC721 *IERC721CallerSession) OwnerOf(tokenId *big.Int) (common.Address, error) { - return _IERC721.Contract.OwnerOf(&_IERC721.CallOpts, tokenId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_IERC721 *IERC721Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _IERC721.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_IERC721 *IERC721Session) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _IERC721.Contract.SupportsInterface(&_IERC721.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_IERC721 *IERC721CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _IERC721.Contract.SupportsInterface(&_IERC721.CallOpts, interfaceId) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address to, uint256 tokenId) returns() -func (_IERC721 *IERC721Transactor) Approve(opts *bind.TransactOpts, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.contract.Transact(opts, "approve", to, tokenId) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address to, uint256 tokenId) returns() -func (_IERC721 *IERC721Session) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.Contract.Approve(&_IERC721.TransactOpts, to, tokenId) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address to, uint256 tokenId) returns() -func (_IERC721 *IERC721TransactorSession) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.Contract.Approve(&_IERC721.TransactOpts, to, tokenId) -} - -// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() -func (_IERC721 *IERC721Transactor) SafeTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.contract.Transact(opts, "safeTransferFrom", from, to, tokenId) -} - -// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() -func (_IERC721 *IERC721Session) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.Contract.SafeTransferFrom(&_IERC721.TransactOpts, from, to, tokenId) -} - -// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() -func (_IERC721 *IERC721TransactorSession) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.Contract.SafeTransferFrom(&_IERC721.TransactOpts, from, to, tokenId) -} - -// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() -func (_IERC721 *IERC721Transactor) SafeTransferFrom0(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { - return _IERC721.contract.Transact(opts, "safeTransferFrom0", from, to, tokenId, data) -} - -// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() -func (_IERC721 *IERC721Session) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { - return _IERC721.Contract.SafeTransferFrom0(&_IERC721.TransactOpts, from, to, tokenId, data) -} - -// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() -func (_IERC721 *IERC721TransactorSession) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { - return _IERC721.Contract.SafeTransferFrom0(&_IERC721.TransactOpts, from, to, tokenId, data) -} - -// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. -// -// Solidity: function setApprovalForAll(address operator, bool approved) returns() -func (_IERC721 *IERC721Transactor) SetApprovalForAll(opts *bind.TransactOpts, operator common.Address, approved bool) (*types.Transaction, error) { - return _IERC721.contract.Transact(opts, "setApprovalForAll", operator, approved) -} - -// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. -// -// Solidity: function setApprovalForAll(address operator, bool approved) returns() -func (_IERC721 *IERC721Session) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { - return _IERC721.Contract.SetApprovalForAll(&_IERC721.TransactOpts, operator, approved) -} - -// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. -// -// Solidity: function setApprovalForAll(address operator, bool approved) returns() -func (_IERC721 *IERC721TransactorSession) SetApprovalForAll(operator common.Address, approved bool) (*types.Transaction, error) { - return _IERC721.Contract.SetApprovalForAll(&_IERC721.TransactOpts, operator, approved) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() -func (_IERC721 *IERC721Transactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.contract.Transact(opts, "transferFrom", from, to, tokenId) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() -func (_IERC721 *IERC721Session) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.Contract.TransferFrom(&_IERC721.TransactOpts, from, to, tokenId) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() -func (_IERC721 *IERC721TransactorSession) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _IERC721.Contract.TransferFrom(&_IERC721.TransactOpts, from, to, tokenId) -} - -// IERC721ApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the IERC721 contract. -type IERC721ApprovalIterator struct { - Event *IERC721Approval // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IERC721ApprovalIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IERC721Approval) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IERC721Approval) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IERC721ApprovalIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IERC721ApprovalIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// IERC721Approval represents a Approval event raised by the IERC721 contract. -type IERC721Approval struct { - Owner common.Address - Approved common.Address - TokenId *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) -func (_IERC721 *IERC721Filterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, approved []common.Address, tokenId []*big.Int) (*IERC721ApprovalIterator, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var approvedRule []interface{} - for _, approvedItem := range approved { - approvedRule = append(approvedRule, approvedItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _IERC721.contract.FilterLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) - if err != nil { - return nil, err - } - return &IERC721ApprovalIterator{contract: _IERC721.contract, event: "Approval", logs: logs, sub: sub}, nil -} - -// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) -func (_IERC721 *IERC721Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *IERC721Approval, owner []common.Address, approved []common.Address, tokenId []*big.Int) (event.Subscription, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var approvedRule []interface{} - for _, approvedItem := range approved { - approvedRule = append(approvedRule, approvedItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _IERC721.contract.WatchLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IERC721Approval) - if err := _IERC721.contract.UnpackLog(event, "Approval", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) -func (_IERC721 *IERC721Filterer) ParseApproval(log types.Log) (*IERC721Approval, error) { - event := new(IERC721Approval) - if err := _IERC721.contract.UnpackLog(event, "Approval", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// IERC721ApprovalForAllIterator is returned from FilterApprovalForAll and is used to iterate over the raw logs and unpacked data for ApprovalForAll events raised by the IERC721 contract. -type IERC721ApprovalForAllIterator struct { - Event *IERC721ApprovalForAll // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IERC721ApprovalForAllIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IERC721ApprovalForAll) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IERC721ApprovalForAll) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IERC721ApprovalForAllIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IERC721ApprovalForAllIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// IERC721ApprovalForAll represents a ApprovalForAll event raised by the IERC721 contract. -type IERC721ApprovalForAll struct { - Owner common.Address - Operator common.Address - Approved bool - Raw types.Log // Blockchain specific contextual infos -} - -// FilterApprovalForAll is a free log retrieval operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. -// -// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) -func (_IERC721 *IERC721Filterer) FilterApprovalForAll(opts *bind.FilterOpts, owner []common.Address, operator []common.Address) (*IERC721ApprovalForAllIterator, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var operatorRule []interface{} - for _, operatorItem := range operator { - operatorRule = append(operatorRule, operatorItem) - } - - logs, sub, err := _IERC721.contract.FilterLogs(opts, "ApprovalForAll", ownerRule, operatorRule) - if err != nil { - return nil, err - } - return &IERC721ApprovalForAllIterator{contract: _IERC721.contract, event: "ApprovalForAll", logs: logs, sub: sub}, nil -} - -// WatchApprovalForAll is a free log subscription operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. -// -// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) -func (_IERC721 *IERC721Filterer) WatchApprovalForAll(opts *bind.WatchOpts, sink chan<- *IERC721ApprovalForAll, owner []common.Address, operator []common.Address) (event.Subscription, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var operatorRule []interface{} - for _, operatorItem := range operator { - operatorRule = append(operatorRule, operatorItem) - } - - logs, sub, err := _IERC721.contract.WatchLogs(opts, "ApprovalForAll", ownerRule, operatorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IERC721ApprovalForAll) - if err := _IERC721.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseApprovalForAll is a log parse operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. -// -// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) -func (_IERC721 *IERC721Filterer) ParseApprovalForAll(log types.Log) (*IERC721ApprovalForAll, error) { - event := new(IERC721ApprovalForAll) - if err := _IERC721.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// IERC721TransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the IERC721 contract. -type IERC721TransferIterator struct { - Event *IERC721Transfer // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *IERC721TransferIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(IERC721Transfer) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(IERC721Transfer) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *IERC721TransferIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *IERC721TransferIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// IERC721Transfer represents a Transfer event raised by the IERC721 contract. -type IERC721Transfer struct { - From common.Address - To common.Address - TokenId *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) -func (_IERC721 *IERC721Filterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address, tokenId []*big.Int) (*IERC721TransferIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _IERC721.contract.FilterLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) - if err != nil { - return nil, err - } - return &IERC721TransferIterator{contract: _IERC721.contract, event: "Transfer", logs: logs, sub: sub}, nil -} - -// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) -func (_IERC721 *IERC721Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *IERC721Transfer, from []common.Address, to []common.Address, tokenId []*big.Int) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _IERC721.contract.WatchLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(IERC721Transfer) - if err := _IERC721.contract.UnpackLog(event, "Transfer", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) -func (_IERC721 *IERC721Filterer) ParseTransfer(log types.Log) (*IERC721Transfer, error) { - event := new(IERC721Transfer) - if err := _IERC721.contract.UnpackLog(event, "Transfer", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go index d491842..422015a 100644 --- a/internal/sbtcheck/main.go +++ b/internal/sbtcheck/main.go @@ -2,45 +2,210 @@ package sbtcheck import ( "context" - "errors" + "database/sql" "fmt" "math/big" + "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/rarimo/rarime-points-svc/internal/sbtcheck/erc721" + "github.com/ethereum/go-ethereum/event" + iden3 "github.com/iden3/go-iden3-core/v2" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/data/evtypes" + "github.com/rarimo/rarime-points-svc/internal/sbtcheck/verifiers" + "gitlab.com/distributed_lab/logan/v3" + "gitlab.com/distributed_lab/running" ) -var ErrUnsupportedNetwork = errors.New("unsupported network") +// all retries of runner are done on failures +const abnormalPeriod = 5 * time.Second -type Connector struct { +type Runner struct { networks map[string]network + // ensure to always call .New() for balancesQ and eventsQ + balancesQ data.BalancesQ + eventsQ data.EventsQ + types *evtypes.Types + log *logan.Entry } type network struct { - caller *erc721.IERC721Caller - timeout time.Duration + events *verifiers.SBTIdentityVerifierFilterer + timeout time.Duration + disabled bool } -func (c *Connector) IsSbtOwner(ctx context.Context, network, userAddress string) (bool, error) { - net, ok := c.networks[network] - if !ok { - return false, fmt.Errorf("%w: %s", ErrUnsupportedNetwork, network) +func (r *Runner) Run(ctx context.Context) error { + var wg sync.WaitGroup + for name, net := range r.networks { + if net.disabled { + r.log.Infof("SBT check: network %s disabled", name) + continue + } + + r.log.Infof("SBT check: running for network %s", name) + wg.Add(1) + + if err := r.run(ctx, net, &wg); err != nil { + return fmt.Errorf("run checker for network %s: %w", name, err) + } } + wg.Wait() + r.log.Infof("SBT check: all network checkers stopped") + return nil +} + +func (r *Runner) run(ctx context.Context, net network, wg *sync.WaitGroup) error { + sink := make(chan *verifiers.SBTIdentityVerifierSBTIdentityProved) + toCtx, cancel := context.WithTimeout(ctx, net.timeout) defer cancel() - balance, err := net.caller.BalanceOf(&bind.CallOpts{Context: toCtx}, common.HexToAddress(userAddress)) + sub, err := net.events.WatchSBTIdentityProved(&bind.WatchOpts{Context: toCtx}, sink, nil) + if err != nil { + return fmt.Errorf("subscribe to SBTIdentityProved event: %w", err) + } + + go running.UntilSuccess(ctx, r.log, "sbt-checker", func(ctx context.Context) (bool, error) { + err = r.subscribe(ctx, sub, sink) + if err == nil { + wg.Done() + } + return err == nil, err + }, abnormalPeriod, abnormalPeriod) + + return nil +} + +func (r *Runner) subscribe( + ctx context.Context, + sub event.Subscription, + sink chan *verifiers.SBTIdentityVerifierSBTIdentityProved, +) error { + + for { + select { + case <-ctx.Done(): + r.log.Info("SBTIdentityProved subscription stopped") + return nil + case err := <-sub.Err(): + return fmt.Errorf("SBTIdentityProved subscription error: %w", err) + case evt := <-sink: + if evt == nil { + r.log.Debug("Got nil SBTIdentityProved event from subscription, continue") + continue + } + if err := r.handleEvent(*evt); err != nil { + return fmt.Errorf("handle event: %w", err) + } + } + } +} + +func (r *Runner) handleEvent(evt verifiers.SBTIdentityVerifierSBTIdentityProved) error { + did, err := parseDidFromUint256(evt.IdentityId) + if err != nil { + return fmt.Errorf("parse did from uint256 (identityId=%s): %w", evt.IdentityId, err) + } + + balanceID, err := r.getOrCreateBalance(did) + if err != nil { + return fmt.Errorf("get or create balance (did=%s): %w", did, err) + } + + poh, err := r.findPohEvent(balanceID) + if err != nil { + return fmt.Errorf("find PoH event (balanceID=%s): %w", balanceID, err) + } + if err = r.fulfillPohEvent(*poh); err != nil { + return fmt.Errorf("update PoH event status to fulfilled: %w", err) + } + + r.log.Infof("Event %s was fulfilled for DID %s", evtypes.TypeGetPoH, did) + return nil +} + +func (r *Runner) getOrCreateBalance(did string) (string, error) { + balance, err := r.balancesQ.New().FilterByUserDID(did).Get() + if err != nil { + return "", fmt.Errorf("get balance: %w", err) + } + if balance != nil { + r.log.Debugf("Balance exists for DID %s", did) + return balance.ID, nil + } + + r.log.Debugf("Balance not found for DID %s, creating new one", did) + id, err := r.createBalance(did) + if err != nil { + return "", fmt.Errorf("create balance: %w", err) + } + + return id, nil +} + +func (r *Runner) findPohEvent(bid string) (*data.Event, error) { + poh, err := r.eventsQ.New(). + FilterByBalanceID(bid). + FilterByType(evtypes.TypeGetPoH). + FilterByStatus(data.EventOpen). + Get() if err != nil { - return false, fmt.Errorf("check ERC721 SBT balance (network=%s userAddress=%s]: %w", network, userAddress, err) + return nil, fmt.Errorf("get open PoH event: %w", err) + } + if poh == nil { + return nil, fmt.Errorf("PoH event was not properly added on balance creation") } - return balance.Cmp(big.NewInt(0)) == 1, nil + return poh, nil } -func (c *Connector) IsNetworkSupported(network string) bool { - _, ok := c.networks[network] - return ok +func (r *Runner) fulfillPohEvent(poh data.Event) error { + getPoh := r.types.Get(evtypes.TypeGetPoH) + if getPoh == nil { + return fmt.Errorf("event types were not correctly initialized: missing %s", evtypes.TypeGetPoH) + } + + return r.eventsQ.New().FilterByID(poh.ID).Update(data.Event{ + Status: data.EventFulfilled, + PointsAmount: sql.NullInt32{ + Int32: getPoh.Reward, + Valid: true, + }, + }) +} + +func (r *Runner) createBalance(did string) (string, error) { + err := r.balancesQ.New().Insert(data.Balance{DID: did}) + if err != nil { + return "", fmt.Errorf("insert balance: %w", err) + } + + balance, err := r.balancesQ.New().FilterByUserDID(did).Get() + if err != nil { + return "", fmt.Errorf("get balance back: %w", err) + } + + err = r.eventsQ.New().Insert(r.types.PrepareOpenEvents(balance.ID)...) + if err != nil { + return "", fmt.Errorf("insert open events: %w", err) + } + + return balance.ID, nil +} + +func parseDidFromUint256(raw *big.Int) (string, error) { + id, err := iden3.IDFromInt(raw) + if err != nil { + return "", fmt.Errorf("parse iden3 ID from bigInt: %w", err) + } + + did, err := iden3.ParseDIDFromID(id) + if err != nil { + return "", fmt.Errorf("parse DID from iden3 ID (id=%s): %w", id, err) + } + + return did.String(), nil } diff --git a/internal/sbtcheck/verifiers/SBTIdentityVerifier.go b/internal/sbtcheck/verifiers/SBTIdentityVerifier.go new file mode 100644 index 0000000..43b4c6c --- /dev/null +++ b/internal/sbtcheck/verifiers/SBTIdentityVerifier.go @@ -0,0 +1,1605 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package verifiers + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// IBaseVerifierProveIdentityParams is an auto generated low-level Go binding around an user-defined struct. +type IBaseVerifierProveIdentityParams struct { + StatesMerkleData ILightweightStateStatesMerkleData + Inputs []*big.Int + A [2]*big.Int + B [2][2]*big.Int + C [2]*big.Int +} + +// IBaseVerifierTransitStateParams is an auto generated low-level Go binding around an user-defined struct. +type IBaseVerifierTransitStateParams struct { + NewIdentitiesStatesRoot [32]byte + GistData ILightweightStateGistRootData + Proof []byte +} + +// ILightweightStateGistRootData is an auto generated low-level Go binding around an user-defined struct. +type ILightweightStateGistRootData struct { + Root *big.Int + CreatedAtTimestamp *big.Int +} + +// ILightweightStateStatesMerkleData is an auto generated low-level Go binding around an user-defined struct. +type ILightweightStateStatesMerkleData struct { + IssuerId *big.Int + IssuerState *big.Int + CreatedAtTimestamp *big.Int + MerkleProof [][32]byte +} + +// ISBTIdentityVerifierSBTIdentityProofInfo is an auto generated low-level Go binding around an user-defined struct. +type ISBTIdentityVerifierSBTIdentityProofInfo struct { + SenderAddr common.Address + SbtTokenId *big.Int + IsProved bool +} + +// SBTIdentityVerifierMetaData contains all meta data concerning the SBTIdentityVerifier contract. +var SBTIdentityVerifierMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"identityId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"senderAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenID\",\"type\":\"uint256\"}],\"name\":\"SBTIdentityProved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SBT_IDENTITY_PROOF_QUERY_ID\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIZKPQueriesStorage\",\"name\":\"zkpQueriesStorage_\",\"type\":\"address\"},{\"internalType\":\"contractIVerifiedSBT\",\"name\":\"sbtToken_\",\"type\":\"address\"}],\"name\":\"__SBTIdentityVerifier_init\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"addressToIdentityId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"schema_\",\"type\":\"uint256\"}],\"name\":\"getAllowedIssuers\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"identityId_\",\"type\":\"uint256\"}],\"name\":\"getIdentityProofInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"senderAddr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"sbtTokenId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isProved\",\"type\":\"bool\"}],\"internalType\":\"structISBTIdentityVerifier.SBTIdentityProofInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"schema_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"issuerId_\",\"type\":\"uint256\"}],\"name\":\"isAllowedIssuer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"userAddr_\",\"type\":\"address\"}],\"name\":\"isIdentityProved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"identityId_\",\"type\":\"uint256\"}],\"name\":\"isIdentityProved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"issuerId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"issuerState\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"createdAtTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"merkleProof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structILightweightState.StatesMerkleData\",\"name\":\"statesMerkleData\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"inputs\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[2]\",\"name\":\"a\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2][2]\",\"name\":\"b\",\"type\":\"uint256[2][2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"c\",\"type\":\"uint256[2]\"}],\"internalType\":\"structIBaseVerifier.ProveIdentityParams\",\"name\":\"proveIdentityParams_\",\"type\":\"tuple\"}],\"name\":\"proveIdentity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sbtToken\",\"outputs\":[{\"internalType\":\"contractIVerifiedSBT\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIZKPQueriesStorage\",\"name\":\"newZKPQueriesStorage_\",\"type\":\"address\"}],\"name\":\"setZKPQueriesStorage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"issuerId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"issuerState\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"createdAtTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"merkleProof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structILightweightState.StatesMerkleData\",\"name\":\"statesMerkleData\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"inputs\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[2]\",\"name\":\"a\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2][2]\",\"name\":\"b\",\"type\":\"uint256[2][2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"c\",\"type\":\"uint256[2]\"}],\"internalType\":\"structIBaseVerifier.ProveIdentityParams\",\"name\":\"proveIdentityParams_\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"newIdentitiesStatesRoot\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"root\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"createdAtTimestamp\",\"type\":\"uint256\"}],\"internalType\":\"structILightweightState.GistRootData\",\"name\":\"gistData\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"internalType\":\"structIBaseVerifier.TransitStateParams\",\"name\":\"transitStateParams_\",\"type\":\"tuple\"}],\"name\":\"transitStateAndProveIdentity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"schema_\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"issuerIds_\",\"type\":\"uint256[]\"},{\"internalType\":\"bool\",\"name\":\"isAdding_\",\"type\":\"bool\"}],\"name\":\"updateAllowedIssuers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zkpQueriesStorage\",\"outputs\":[{\"internalType\":\"contractIZKPQueriesStorage\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", +} + +// SBTIdentityVerifierABI is the input ABI used to generate the binding from. +// Deprecated: Use SBTIdentityVerifierMetaData.ABI instead. +var SBTIdentityVerifierABI = SBTIdentityVerifierMetaData.ABI + +// SBTIdentityVerifier is an auto generated Go binding around an Ethereum contract. +type SBTIdentityVerifier struct { + SBTIdentityVerifierCaller // Read-only binding to the contract + SBTIdentityVerifierTransactor // Write-only binding to the contract + SBTIdentityVerifierFilterer // Log filterer for contract events +} + +// SBTIdentityVerifierCaller is an auto generated read-only Go binding around an Ethereum contract. +type SBTIdentityVerifierCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SBTIdentityVerifierTransactor is an auto generated write-only Go binding around an Ethereum contract. +type SBTIdentityVerifierTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SBTIdentityVerifierFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type SBTIdentityVerifierFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// SBTIdentityVerifierSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type SBTIdentityVerifierSession struct { + Contract *SBTIdentityVerifier // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// SBTIdentityVerifierCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type SBTIdentityVerifierCallerSession struct { + Contract *SBTIdentityVerifierCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// SBTIdentityVerifierTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type SBTIdentityVerifierTransactorSession struct { + Contract *SBTIdentityVerifierTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// SBTIdentityVerifierRaw is an auto generated low-level Go binding around an Ethereum contract. +type SBTIdentityVerifierRaw struct { + Contract *SBTIdentityVerifier // Generic contract binding to access the raw methods on +} + +// SBTIdentityVerifierCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type SBTIdentityVerifierCallerRaw struct { + Contract *SBTIdentityVerifierCaller // Generic read-only contract binding to access the raw methods on +} + +// SBTIdentityVerifierTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type SBTIdentityVerifierTransactorRaw struct { + Contract *SBTIdentityVerifierTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewSBTIdentityVerifier creates a new instance of SBTIdentityVerifier, bound to a specific deployed contract. +func NewSBTIdentityVerifier(address common.Address, backend bind.ContractBackend) (*SBTIdentityVerifier, error) { + contract, err := bindSBTIdentityVerifier(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &SBTIdentityVerifier{SBTIdentityVerifierCaller: SBTIdentityVerifierCaller{contract: contract}, SBTIdentityVerifierTransactor: SBTIdentityVerifierTransactor{contract: contract}, SBTIdentityVerifierFilterer: SBTIdentityVerifierFilterer{contract: contract}}, nil +} + +// NewSBTIdentityVerifierCaller creates a new read-only instance of SBTIdentityVerifier, bound to a specific deployed contract. +func NewSBTIdentityVerifierCaller(address common.Address, caller bind.ContractCaller) (*SBTIdentityVerifierCaller, error) { + contract, err := bindSBTIdentityVerifier(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &SBTIdentityVerifierCaller{contract: contract}, nil +} + +// NewSBTIdentityVerifierTransactor creates a new write-only instance of SBTIdentityVerifier, bound to a specific deployed contract. +func NewSBTIdentityVerifierTransactor(address common.Address, transactor bind.ContractTransactor) (*SBTIdentityVerifierTransactor, error) { + contract, err := bindSBTIdentityVerifier(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &SBTIdentityVerifierTransactor{contract: contract}, nil +} + +// NewSBTIdentityVerifierFilterer creates a new log filterer instance of SBTIdentityVerifier, bound to a specific deployed contract. +func NewSBTIdentityVerifierFilterer(address common.Address, filterer bind.ContractFilterer) (*SBTIdentityVerifierFilterer, error) { + contract, err := bindSBTIdentityVerifier(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &SBTIdentityVerifierFilterer{contract: contract}, nil +} + +// bindSBTIdentityVerifier binds a generic wrapper to an already deployed contract. +func bindSBTIdentityVerifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := SBTIdentityVerifierMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_SBTIdentityVerifier *SBTIdentityVerifierRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SBTIdentityVerifier.Contract.SBTIdentityVerifierCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_SBTIdentityVerifier *SBTIdentityVerifierRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.SBTIdentityVerifierTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_SBTIdentityVerifier *SBTIdentityVerifierRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.SBTIdentityVerifierTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SBTIdentityVerifier.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.contract.Transact(opts, method, params...) +} + +// SBTIDENTITYPROOFQUERYID is a free data retrieval call binding the contract method 0x2dff9de4. +// +// Solidity: function SBT_IDENTITY_PROOF_QUERY_ID() view returns(string) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) SBTIDENTITYPROOFQUERYID(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "SBT_IDENTITY_PROOF_QUERY_ID") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// SBTIDENTITYPROOFQUERYID is a free data retrieval call binding the contract method 0x2dff9de4. +// +// Solidity: function SBT_IDENTITY_PROOF_QUERY_ID() view returns(string) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) SBTIDENTITYPROOFQUERYID() (string, error) { + return _SBTIdentityVerifier.Contract.SBTIDENTITYPROOFQUERYID(&_SBTIdentityVerifier.CallOpts) +} + +// SBTIDENTITYPROOFQUERYID is a free data retrieval call binding the contract method 0x2dff9de4. +// +// Solidity: function SBT_IDENTITY_PROOF_QUERY_ID() view returns(string) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) SBTIDENTITYPROOFQUERYID() (string, error) { + return _SBTIdentityVerifier.Contract.SBTIDENTITYPROOFQUERYID(&_SBTIdentityVerifier.CallOpts) +} + +// AddressToIdentityId is a free data retrieval call binding the contract method 0xb4528ff9. +// +// Solidity: function addressToIdentityId(address ) view returns(uint256) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) AddressToIdentityId(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "addressToIdentityId", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// AddressToIdentityId is a free data retrieval call binding the contract method 0xb4528ff9. +// +// Solidity: function addressToIdentityId(address ) view returns(uint256) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) AddressToIdentityId(arg0 common.Address) (*big.Int, error) { + return _SBTIdentityVerifier.Contract.AddressToIdentityId(&_SBTIdentityVerifier.CallOpts, arg0) +} + +// AddressToIdentityId is a free data retrieval call binding the contract method 0xb4528ff9. +// +// Solidity: function addressToIdentityId(address ) view returns(uint256) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) AddressToIdentityId(arg0 common.Address) (*big.Int, error) { + return _SBTIdentityVerifier.Contract.AddressToIdentityId(&_SBTIdentityVerifier.CallOpts, arg0) +} + +// GetAllowedIssuers is a free data retrieval call binding the contract method 0xef8dbdd3. +// +// Solidity: function getAllowedIssuers(uint256 schema_) view returns(uint256[]) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) GetAllowedIssuers(opts *bind.CallOpts, schema_ *big.Int) ([]*big.Int, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "getAllowedIssuers", schema_) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +// GetAllowedIssuers is a free data retrieval call binding the contract method 0xef8dbdd3. +// +// Solidity: function getAllowedIssuers(uint256 schema_) view returns(uint256[]) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) GetAllowedIssuers(schema_ *big.Int) ([]*big.Int, error) { + return _SBTIdentityVerifier.Contract.GetAllowedIssuers(&_SBTIdentityVerifier.CallOpts, schema_) +} + +// GetAllowedIssuers is a free data retrieval call binding the contract method 0xef8dbdd3. +// +// Solidity: function getAllowedIssuers(uint256 schema_) view returns(uint256[]) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) GetAllowedIssuers(schema_ *big.Int) ([]*big.Int, error) { + return _SBTIdentityVerifier.Contract.GetAllowedIssuers(&_SBTIdentityVerifier.CallOpts, schema_) +} + +// GetIdentityProofInfo is a free data retrieval call binding the contract method 0x5332d5ec. +// +// Solidity: function getIdentityProofInfo(uint256 identityId_) view returns((address,uint256,bool)) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) GetIdentityProofInfo(opts *bind.CallOpts, identityId_ *big.Int) (ISBTIdentityVerifierSBTIdentityProofInfo, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "getIdentityProofInfo", identityId_) + + if err != nil { + return *new(ISBTIdentityVerifierSBTIdentityProofInfo), err + } + + out0 := *abi.ConvertType(out[0], new(ISBTIdentityVerifierSBTIdentityProofInfo)).(*ISBTIdentityVerifierSBTIdentityProofInfo) + + return out0, err + +} + +// GetIdentityProofInfo is a free data retrieval call binding the contract method 0x5332d5ec. +// +// Solidity: function getIdentityProofInfo(uint256 identityId_) view returns((address,uint256,bool)) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) GetIdentityProofInfo(identityId_ *big.Int) (ISBTIdentityVerifierSBTIdentityProofInfo, error) { + return _SBTIdentityVerifier.Contract.GetIdentityProofInfo(&_SBTIdentityVerifier.CallOpts, identityId_) +} + +// GetIdentityProofInfo is a free data retrieval call binding the contract method 0x5332d5ec. +// +// Solidity: function getIdentityProofInfo(uint256 identityId_) view returns((address,uint256,bool)) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) GetIdentityProofInfo(identityId_ *big.Int) (ISBTIdentityVerifierSBTIdentityProofInfo, error) { + return _SBTIdentityVerifier.Contract.GetIdentityProofInfo(&_SBTIdentityVerifier.CallOpts, identityId_) +} + +// IsAllowedIssuer is a free data retrieval call binding the contract method 0x969f407e. +// +// Solidity: function isAllowedIssuer(uint256 schema_, uint256 issuerId_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) IsAllowedIssuer(opts *bind.CallOpts, schema_ *big.Int, issuerId_ *big.Int) (bool, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "isAllowedIssuer", schema_, issuerId_) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsAllowedIssuer is a free data retrieval call binding the contract method 0x969f407e. +// +// Solidity: function isAllowedIssuer(uint256 schema_, uint256 issuerId_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) IsAllowedIssuer(schema_ *big.Int, issuerId_ *big.Int) (bool, error) { + return _SBTIdentityVerifier.Contract.IsAllowedIssuer(&_SBTIdentityVerifier.CallOpts, schema_, issuerId_) +} + +// IsAllowedIssuer is a free data retrieval call binding the contract method 0x969f407e. +// +// Solidity: function isAllowedIssuer(uint256 schema_, uint256 issuerId_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) IsAllowedIssuer(schema_ *big.Int, issuerId_ *big.Int) (bool, error) { + return _SBTIdentityVerifier.Contract.IsAllowedIssuer(&_SBTIdentityVerifier.CallOpts, schema_, issuerId_) +} + +// IsIdentityProved is a free data retrieval call binding the contract method 0x413a3b43. +// +// Solidity: function isIdentityProved(address userAddr_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) IsIdentityProved(opts *bind.CallOpts, userAddr_ common.Address) (bool, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "isIdentityProved", userAddr_) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsIdentityProved is a free data retrieval call binding the contract method 0x413a3b43. +// +// Solidity: function isIdentityProved(address userAddr_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) IsIdentityProved(userAddr_ common.Address) (bool, error) { + return _SBTIdentityVerifier.Contract.IsIdentityProved(&_SBTIdentityVerifier.CallOpts, userAddr_) +} + +// IsIdentityProved is a free data retrieval call binding the contract method 0x413a3b43. +// +// Solidity: function isIdentityProved(address userAddr_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) IsIdentityProved(userAddr_ common.Address) (bool, error) { + return _SBTIdentityVerifier.Contract.IsIdentityProved(&_SBTIdentityVerifier.CallOpts, userAddr_) +} + +// IsIdentityProved0 is a free data retrieval call binding the contract method 0x5428764d. +// +// Solidity: function isIdentityProved(uint256 identityId_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) IsIdentityProved0(opts *bind.CallOpts, identityId_ *big.Int) (bool, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "isIdentityProved0", identityId_) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsIdentityProved0 is a free data retrieval call binding the contract method 0x5428764d. +// +// Solidity: function isIdentityProved(uint256 identityId_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) IsIdentityProved0(identityId_ *big.Int) (bool, error) { + return _SBTIdentityVerifier.Contract.IsIdentityProved0(&_SBTIdentityVerifier.CallOpts, identityId_) +} + +// IsIdentityProved0 is a free data retrieval call binding the contract method 0x5428764d. +// +// Solidity: function isIdentityProved(uint256 identityId_) view returns(bool) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) IsIdentityProved0(identityId_ *big.Int) (bool, error) { + return _SBTIdentityVerifier.Contract.IsIdentityProved0(&_SBTIdentityVerifier.CallOpts, identityId_) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) Owner() (common.Address, error) { + return _SBTIdentityVerifier.Contract.Owner(&_SBTIdentityVerifier.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) Owner() (common.Address, error) { + return _SBTIdentityVerifier.Contract.Owner(&_SBTIdentityVerifier.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) ProxiableUUID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "proxiableUUID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) ProxiableUUID() ([32]byte, error) { + return _SBTIdentityVerifier.Contract.ProxiableUUID(&_SBTIdentityVerifier.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) ProxiableUUID() ([32]byte, error) { + return _SBTIdentityVerifier.Contract.ProxiableUUID(&_SBTIdentityVerifier.CallOpts) +} + +// SbtToken is a free data retrieval call binding the contract method 0xe359d997. +// +// Solidity: function sbtToken() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) SbtToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "sbtToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// SbtToken is a free data retrieval call binding the contract method 0xe359d997. +// +// Solidity: function sbtToken() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) SbtToken() (common.Address, error) { + return _SBTIdentityVerifier.Contract.SbtToken(&_SBTIdentityVerifier.CallOpts) +} + +// SbtToken is a free data retrieval call binding the contract method 0xe359d997. +// +// Solidity: function sbtToken() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) SbtToken() (common.Address, error) { + return _SBTIdentityVerifier.Contract.SbtToken(&_SBTIdentityVerifier.CallOpts) +} + +// ZkpQueriesStorage is a free data retrieval call binding the contract method 0xb4db08cc. +// +// Solidity: function zkpQueriesStorage() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierCaller) ZkpQueriesStorage(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SBTIdentityVerifier.contract.Call(opts, &out, "zkpQueriesStorage") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// ZkpQueriesStorage is a free data retrieval call binding the contract method 0xb4db08cc. +// +// Solidity: function zkpQueriesStorage() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) ZkpQueriesStorage() (common.Address, error) { + return _SBTIdentityVerifier.Contract.ZkpQueriesStorage(&_SBTIdentityVerifier.CallOpts) +} + +// ZkpQueriesStorage is a free data retrieval call binding the contract method 0xb4db08cc. +// +// Solidity: function zkpQueriesStorage() view returns(address) +func (_SBTIdentityVerifier *SBTIdentityVerifierCallerSession) ZkpQueriesStorage() (common.Address, error) { + return _SBTIdentityVerifier.Contract.ZkpQueriesStorage(&_SBTIdentityVerifier.CallOpts) +} + +// SBTIdentityVerifierInit is a paid mutator transaction binding the contract method 0x935454d3. +// +// Solidity: function __SBTIdentityVerifier_init(address zkpQueriesStorage_, address sbtToken_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) SBTIdentityVerifierInit(opts *bind.TransactOpts, zkpQueriesStorage_ common.Address, sbtToken_ common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "__SBTIdentityVerifier_init", zkpQueriesStorage_, sbtToken_) +} + +// SBTIdentityVerifierInit is a paid mutator transaction binding the contract method 0x935454d3. +// +// Solidity: function __SBTIdentityVerifier_init(address zkpQueriesStorage_, address sbtToken_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) SBTIdentityVerifierInit(zkpQueriesStorage_ common.Address, sbtToken_ common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.SBTIdentityVerifierInit(&_SBTIdentityVerifier.TransactOpts, zkpQueriesStorage_, sbtToken_) +} + +// SBTIdentityVerifierInit is a paid mutator transaction binding the contract method 0x935454d3. +// +// Solidity: function __SBTIdentityVerifier_init(address zkpQueriesStorage_, address sbtToken_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) SBTIdentityVerifierInit(zkpQueriesStorage_ common.Address, sbtToken_ common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.SBTIdentityVerifierInit(&_SBTIdentityVerifier.TransactOpts, zkpQueriesStorage_, sbtToken_) +} + +// ProveIdentity is a paid mutator transaction binding the contract method 0x008b9130. +// +// Solidity: function proveIdentity(((uint256,uint256,uint256,bytes32[]),uint256[],uint256[2],uint256[2][2],uint256[2]) proveIdentityParams_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) ProveIdentity(opts *bind.TransactOpts, proveIdentityParams_ IBaseVerifierProveIdentityParams) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "proveIdentity", proveIdentityParams_) +} + +// ProveIdentity is a paid mutator transaction binding the contract method 0x008b9130. +// +// Solidity: function proveIdentity(((uint256,uint256,uint256,bytes32[]),uint256[],uint256[2],uint256[2][2],uint256[2]) proveIdentityParams_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) ProveIdentity(proveIdentityParams_ IBaseVerifierProveIdentityParams) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.ProveIdentity(&_SBTIdentityVerifier.TransactOpts, proveIdentityParams_) +} + +// ProveIdentity is a paid mutator transaction binding the contract method 0x008b9130. +// +// Solidity: function proveIdentity(((uint256,uint256,uint256,bytes32[]),uint256[],uint256[2],uint256[2][2],uint256[2]) proveIdentityParams_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) ProveIdentity(proveIdentityParams_ IBaseVerifierProveIdentityParams) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.ProveIdentity(&_SBTIdentityVerifier.TransactOpts, proveIdentityParams_) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) RenounceOwnership() (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.RenounceOwnership(&_SBTIdentityVerifier.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.RenounceOwnership(&_SBTIdentityVerifier.TransactOpts) +} + +// SetZKPQueriesStorage is a paid mutator transaction binding the contract method 0xddebe5c0. +// +// Solidity: function setZKPQueriesStorage(address newZKPQueriesStorage_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) SetZKPQueriesStorage(opts *bind.TransactOpts, newZKPQueriesStorage_ common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "setZKPQueriesStorage", newZKPQueriesStorage_) +} + +// SetZKPQueriesStorage is a paid mutator transaction binding the contract method 0xddebe5c0. +// +// Solidity: function setZKPQueriesStorage(address newZKPQueriesStorage_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) SetZKPQueriesStorage(newZKPQueriesStorage_ common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.SetZKPQueriesStorage(&_SBTIdentityVerifier.TransactOpts, newZKPQueriesStorage_) +} + +// SetZKPQueriesStorage is a paid mutator transaction binding the contract method 0xddebe5c0. +// +// Solidity: function setZKPQueriesStorage(address newZKPQueriesStorage_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) SetZKPQueriesStorage(newZKPQueriesStorage_ common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.SetZKPQueriesStorage(&_SBTIdentityVerifier.TransactOpts, newZKPQueriesStorage_) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.TransferOwnership(&_SBTIdentityVerifier.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.TransferOwnership(&_SBTIdentityVerifier.TransactOpts, newOwner) +} + +// TransitStateAndProveIdentity is a paid mutator transaction binding the contract method 0xd2fbb694. +// +// Solidity: function transitStateAndProveIdentity(((uint256,uint256,uint256,bytes32[]),uint256[],uint256[2],uint256[2][2],uint256[2]) proveIdentityParams_, (bytes32,(uint256,uint256),bytes) transitStateParams_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) TransitStateAndProveIdentity(opts *bind.TransactOpts, proveIdentityParams_ IBaseVerifierProveIdentityParams, transitStateParams_ IBaseVerifierTransitStateParams) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "transitStateAndProveIdentity", proveIdentityParams_, transitStateParams_) +} + +// TransitStateAndProveIdentity is a paid mutator transaction binding the contract method 0xd2fbb694. +// +// Solidity: function transitStateAndProveIdentity(((uint256,uint256,uint256,bytes32[]),uint256[],uint256[2],uint256[2][2],uint256[2]) proveIdentityParams_, (bytes32,(uint256,uint256),bytes) transitStateParams_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) TransitStateAndProveIdentity(proveIdentityParams_ IBaseVerifierProveIdentityParams, transitStateParams_ IBaseVerifierTransitStateParams) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.TransitStateAndProveIdentity(&_SBTIdentityVerifier.TransactOpts, proveIdentityParams_, transitStateParams_) +} + +// TransitStateAndProveIdentity is a paid mutator transaction binding the contract method 0xd2fbb694. +// +// Solidity: function transitStateAndProveIdentity(((uint256,uint256,uint256,bytes32[]),uint256[],uint256[2],uint256[2][2],uint256[2]) proveIdentityParams_, (bytes32,(uint256,uint256),bytes) transitStateParams_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) TransitStateAndProveIdentity(proveIdentityParams_ IBaseVerifierProveIdentityParams, transitStateParams_ IBaseVerifierTransitStateParams) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.TransitStateAndProveIdentity(&_SBTIdentityVerifier.TransactOpts, proveIdentityParams_, transitStateParams_) +} + +// UpdateAllowedIssuers is a paid mutator transaction binding the contract method 0x051788a5. +// +// Solidity: function updateAllowedIssuers(uint256 schema_, uint256[] issuerIds_, bool isAdding_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) UpdateAllowedIssuers(opts *bind.TransactOpts, schema_ *big.Int, issuerIds_ []*big.Int, isAdding_ bool) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "updateAllowedIssuers", schema_, issuerIds_, isAdding_) +} + +// UpdateAllowedIssuers is a paid mutator transaction binding the contract method 0x051788a5. +// +// Solidity: function updateAllowedIssuers(uint256 schema_, uint256[] issuerIds_, bool isAdding_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) UpdateAllowedIssuers(schema_ *big.Int, issuerIds_ []*big.Int, isAdding_ bool) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.UpdateAllowedIssuers(&_SBTIdentityVerifier.TransactOpts, schema_, issuerIds_, isAdding_) +} + +// UpdateAllowedIssuers is a paid mutator transaction binding the contract method 0x051788a5. +// +// Solidity: function updateAllowedIssuers(uint256 schema_, uint256[] issuerIds_, bool isAdding_) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) UpdateAllowedIssuers(schema_ *big.Int, issuerIds_ []*big.Int, isAdding_ bool) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.UpdateAllowedIssuers(&_SBTIdentityVerifier.TransactOpts, schema_, issuerIds_, isAdding_) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6. +// +// Solidity: function upgradeTo(address newImplementation) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) UpgradeTo(opts *bind.TransactOpts, newImplementation common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "upgradeTo", newImplementation) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6. +// +// Solidity: function upgradeTo(address newImplementation) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) UpgradeTo(newImplementation common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.UpgradeTo(&_SBTIdentityVerifier.TransactOpts, newImplementation) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6. +// +// Solidity: function upgradeTo(address newImplementation) returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) UpgradeTo(newImplementation common.Address) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.UpgradeTo(&_SBTIdentityVerifier.TransactOpts, newImplementation) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactor) UpgradeToAndCall(opts *bind.TransactOpts, newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _SBTIdentityVerifier.contract.Transact(opts, "upgradeToAndCall", newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.UpgradeToAndCall(&_SBTIdentityVerifier.TransactOpts, newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_SBTIdentityVerifier *SBTIdentityVerifierTransactorSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _SBTIdentityVerifier.Contract.UpgradeToAndCall(&_SBTIdentityVerifier.TransactOpts, newImplementation, data) +} + +// SBTIdentityVerifierAdminChangedIterator is returned from FilterAdminChanged and is used to iterate over the raw logs and unpacked data for AdminChanged events raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierAdminChangedIterator struct { + Event *SBTIdentityVerifierAdminChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SBTIdentityVerifierAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SBTIdentityVerifierAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SBTIdentityVerifierAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SBTIdentityVerifierAdminChanged represents a AdminChanged event raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierAdminChanged struct { + PreviousAdmin common.Address + NewAdmin common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAdminChanged is a free log retrieval operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) FilterAdminChanged(opts *bind.FilterOpts) (*SBTIdentityVerifierAdminChangedIterator, error) { + + logs, sub, err := _SBTIdentityVerifier.contract.FilterLogs(opts, "AdminChanged") + if err != nil { + return nil, err + } + return &SBTIdentityVerifierAdminChangedIterator{contract: _SBTIdentityVerifier.contract, event: "AdminChanged", logs: logs, sub: sub}, nil +} + +// WatchAdminChanged is a free log subscription operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) WatchAdminChanged(opts *bind.WatchOpts, sink chan<- *SBTIdentityVerifierAdminChanged) (event.Subscription, error) { + + logs, sub, err := _SBTIdentityVerifier.contract.WatchLogs(opts, "AdminChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SBTIdentityVerifierAdminChanged) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "AdminChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAdminChanged is a log parse operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f. +// +// Solidity: event AdminChanged(address previousAdmin, address newAdmin) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) ParseAdminChanged(log types.Log) (*SBTIdentityVerifierAdminChanged, error) { + event := new(SBTIdentityVerifierAdminChanged) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "AdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SBTIdentityVerifierBeaconUpgradedIterator is returned from FilterBeaconUpgraded and is used to iterate over the raw logs and unpacked data for BeaconUpgraded events raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierBeaconUpgradedIterator struct { + Event *SBTIdentityVerifierBeaconUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SBTIdentityVerifierBeaconUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierBeaconUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierBeaconUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SBTIdentityVerifierBeaconUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SBTIdentityVerifierBeaconUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SBTIdentityVerifierBeaconUpgraded represents a BeaconUpgraded event raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierBeaconUpgraded struct { + Beacon common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBeaconUpgraded is a free log retrieval operation binding the contract event 0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e. +// +// Solidity: event BeaconUpgraded(address indexed beacon) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) FilterBeaconUpgraded(opts *bind.FilterOpts, beacon []common.Address) (*SBTIdentityVerifierBeaconUpgradedIterator, error) { + + var beaconRule []interface{} + for _, beaconItem := range beacon { + beaconRule = append(beaconRule, beaconItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.FilterLogs(opts, "BeaconUpgraded", beaconRule) + if err != nil { + return nil, err + } + return &SBTIdentityVerifierBeaconUpgradedIterator{contract: _SBTIdentityVerifier.contract, event: "BeaconUpgraded", logs: logs, sub: sub}, nil +} + +// WatchBeaconUpgraded is a free log subscription operation binding the contract event 0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e. +// +// Solidity: event BeaconUpgraded(address indexed beacon) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) WatchBeaconUpgraded(opts *bind.WatchOpts, sink chan<- *SBTIdentityVerifierBeaconUpgraded, beacon []common.Address) (event.Subscription, error) { + + var beaconRule []interface{} + for _, beaconItem := range beacon { + beaconRule = append(beaconRule, beaconItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.WatchLogs(opts, "BeaconUpgraded", beaconRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SBTIdentityVerifierBeaconUpgraded) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "BeaconUpgraded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseBeaconUpgraded is a log parse operation binding the contract event 0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e. +// +// Solidity: event BeaconUpgraded(address indexed beacon) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) ParseBeaconUpgraded(log types.Log) (*SBTIdentityVerifierBeaconUpgraded, error) { + event := new(SBTIdentityVerifierBeaconUpgraded) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "BeaconUpgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SBTIdentityVerifierInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierInitializedIterator struct { + Event *SBTIdentityVerifierInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SBTIdentityVerifierInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SBTIdentityVerifierInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SBTIdentityVerifierInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SBTIdentityVerifierInitialized represents a Initialized event raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) FilterInitialized(opts *bind.FilterOpts) (*SBTIdentityVerifierInitializedIterator, error) { + + logs, sub, err := _SBTIdentityVerifier.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &SBTIdentityVerifierInitializedIterator{contract: _SBTIdentityVerifier.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *SBTIdentityVerifierInitialized) (event.Subscription, error) { + + logs, sub, err := _SBTIdentityVerifier.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SBTIdentityVerifierInitialized) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) ParseInitialized(log types.Log) (*SBTIdentityVerifierInitialized, error) { + event := new(SBTIdentityVerifierInitialized) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SBTIdentityVerifierOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierOwnershipTransferredIterator struct { + Event *SBTIdentityVerifierOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SBTIdentityVerifierOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SBTIdentityVerifierOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SBTIdentityVerifierOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SBTIdentityVerifierOwnershipTransferred represents a OwnershipTransferred event raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*SBTIdentityVerifierOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &SBTIdentityVerifierOwnershipTransferredIterator{contract: _SBTIdentityVerifier.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *SBTIdentityVerifierOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SBTIdentityVerifierOwnershipTransferred) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) ParseOwnershipTransferred(log types.Log) (*SBTIdentityVerifierOwnershipTransferred, error) { + event := new(SBTIdentityVerifierOwnershipTransferred) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SBTIdentityVerifierSBTIdentityProvedIterator is returned from FilterSBTIdentityProved and is used to iterate over the raw logs and unpacked data for SBTIdentityProved events raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierSBTIdentityProvedIterator struct { + Event *SBTIdentityVerifierSBTIdentityProved // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SBTIdentityVerifierSBTIdentityProvedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierSBTIdentityProved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierSBTIdentityProved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SBTIdentityVerifierSBTIdentityProvedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SBTIdentityVerifierSBTIdentityProvedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SBTIdentityVerifierSBTIdentityProved represents a SBTIdentityProved event raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierSBTIdentityProved struct { + IdentityId *big.Int + SenderAddr common.Address + TokenAddr common.Address + TokenID *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSBTIdentityProved is a free log retrieval operation binding the contract event 0x33d963db6181e83a89d884ce98977f9cf447ffef066289de3ced2d2006441391. +// +// Solidity: event SBTIdentityProved(uint256 indexed identityId, address senderAddr, address tokenAddr, uint256 tokenID) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) FilterSBTIdentityProved(opts *bind.FilterOpts, identityId []*big.Int) (*SBTIdentityVerifierSBTIdentityProvedIterator, error) { + + var identityIdRule []interface{} + for _, identityIdItem := range identityId { + identityIdRule = append(identityIdRule, identityIdItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.FilterLogs(opts, "SBTIdentityProved", identityIdRule) + if err != nil { + return nil, err + } + return &SBTIdentityVerifierSBTIdentityProvedIterator{contract: _SBTIdentityVerifier.contract, event: "SBTIdentityProved", logs: logs, sub: sub}, nil +} + +// WatchSBTIdentityProved is a free log subscription operation binding the contract event 0x33d963db6181e83a89d884ce98977f9cf447ffef066289de3ced2d2006441391. +// +// Solidity: event SBTIdentityProved(uint256 indexed identityId, address senderAddr, address tokenAddr, uint256 tokenID) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) WatchSBTIdentityProved(opts *bind.WatchOpts, sink chan<- *SBTIdentityVerifierSBTIdentityProved, identityId []*big.Int) (event.Subscription, error) { + + var identityIdRule []interface{} + for _, identityIdItem := range identityId { + identityIdRule = append(identityIdRule, identityIdItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.WatchLogs(opts, "SBTIdentityProved", identityIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SBTIdentityVerifierSBTIdentityProved) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "SBTIdentityProved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSBTIdentityProved is a log parse operation binding the contract event 0x33d963db6181e83a89d884ce98977f9cf447ffef066289de3ced2d2006441391. +// +// Solidity: event SBTIdentityProved(uint256 indexed identityId, address senderAddr, address tokenAddr, uint256 tokenID) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) ParseSBTIdentityProved(log types.Log) (*SBTIdentityVerifierSBTIdentityProved, error) { + event := new(SBTIdentityVerifierSBTIdentityProved) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "SBTIdentityProved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// SBTIdentityVerifierUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierUpgradedIterator struct { + Event *SBTIdentityVerifierUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *SBTIdentityVerifierUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(SBTIdentityVerifierUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *SBTIdentityVerifierUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *SBTIdentityVerifierUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// SBTIdentityVerifierUpgraded represents a Upgraded event raised by the SBTIdentityVerifier contract. +type SBTIdentityVerifierUpgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*SBTIdentityVerifierUpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &SBTIdentityVerifierUpgradedIterator{contract: _SBTIdentityVerifier.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *SBTIdentityVerifierUpgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _SBTIdentityVerifier.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(SBTIdentityVerifierUpgraded) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "Upgraded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_SBTIdentityVerifier *SBTIdentityVerifierFilterer) ParseUpgraded(log types.Log) (*SBTIdentityVerifierUpgraded, error) { + event := new(SBTIdentityVerifierUpgraded) + if err := _SBTIdentityVerifier.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index 3af33b2..e2c2f35 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -1,12 +1,10 @@ package handlers import ( - "database/sql" "net/http" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/service/requests" - "github.com/rarimo/rarime-points-svc/resources" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" ) @@ -18,14 +16,14 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - did := req.Data.ID + did := req.Data.Attributes.UserDid balance := getBalanceByDID(did, false, w, r) if balance != nil { ape.RenderErr(w, problems.Conflict()) return } - if err = BalancesQ(r).Insert(did); err != nil { + if err = BalancesQ(r).Insert(data.Balance{DID: did}); err != nil { Log(r).WithError(err).Error("Failed to create balance") ape.RenderErr(w, problems.InternalError()) return @@ -38,7 +36,7 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - err = EventsQ(r).Insert(prepareOpenEvents(balance.DID, EventTypes(r).List())...) + err = EventsQ(r).Insert(EventTypes(r).PrepareOpenEvents(balance.DID)...) if err != nil { Log(r).WithError(err).Error("Failed to add open events") ape.RenderErr(w, problems.InternalError()) @@ -47,19 +45,3 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { ape.Render(w, newBalanceModel(*balance)) } - -func prepareOpenEvents(did string, evTypes []resources.EventStaticMeta) []data.Event { - events := make([]data.Event, len(evTypes)) - for i, evType := range evTypes { - events[i] = data.Event{ - UserDID: did, - Type: evType.Name, - Status: data.EventOpen, - PointsAmount: sql.NullInt32{ - Int32: evType.Reward, - Valid: true, - }, - } - } - return events -} diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index b3f0e77..b9f0b98 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -72,12 +72,12 @@ func UserClaims(r *http.Request) []resources.Claim { return r.Context().Value(userClaimsCtxKey).([]resources.Claim) } -func CtxSbtCheck(sbtCheck *sbtcheck.Connector) func(context.Context) context.Context { +func CtxSbtCheck(sbtCheck *sbtcheck.Runner) func(context.Context) context.Context { return func(ctx context.Context) context.Context { return context.WithValue(ctx, sbtCheckCtxKey, sbtCheck) } } -func SbtCheck(r *http.Request) *sbtcheck.Connector { - return r.Context().Value(sbtCheckCtxKey).(*sbtcheck.Connector) +func SbtCheck(r *http.Request) *sbtcheck.Runner { + return r.Context().Value(sbtCheckCtxKey).(*sbtcheck.Runner) } From 7bd70f96fc796df3935ca0e6d31810ae200c5b6c Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 25 Jan 2024 17:45:37 +0200 Subject: [PATCH 47/63] =?UTF-8?q?Forgot=20to=20init=20SBT=20runner=20?= =?UTF-8?q?=F0=9F=98=A8=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yaml | 6 +++--- internal/cli/main.go | 11 ++++++++++- internal/sbtcheck/config.go | 12 ++++++++---- internal/sbtcheck/main.go | 18 +++++++++++++++++- internal/service/handlers/ctx.go | 12 ------------ internal/service/router.go | 1 - 6 files changed, 38 insertions(+), 22 deletions(-) diff --git a/config.yaml b/config.yaml index 7264868..8b9d314 100644 --- a/config.yaml +++ b/config.yaml @@ -35,15 +35,15 @@ auth: sbt_check: networks: - name: polygon - rpc: https://your-rpc + rpc: wss://your-rpc request_timeout: 3s contract: 0x... - name: ethereum - rpc: https://your-rpc + rpc: wss://your-rpc request_timeout: 5s contract: 0x... - name: disabled_sample disabled: true - rpc: https://your-rpc + rpc: wss://your-rpc request_timeout: 5s contract: 0x... diff --git a/internal/cli/main.go b/internal/cli/main.go index 78ce6dc..0a05e4b 100644 --- a/internal/cli/main.go +++ b/internal/cli/main.go @@ -5,6 +5,8 @@ import ( "github.com/alecthomas/kingpin" "github.com/rarimo/rarime-points-svc/internal/config" + "github.com/rarimo/rarime-points-svc/internal/data/pg" + "github.com/rarimo/rarime-points-svc/internal/sbtcheck" "github.com/rarimo/rarime-points-svc/internal/service" "gitlab.com/distributed_lab/kit/kv" "gitlab.com/distributed_lab/logan/v3" @@ -39,7 +41,14 @@ func Run(args []string) bool { switch cmd { case serviceCmd.FullCommand(): - if err = cfg.SbtCheck().Run(context.Background()); err != nil { + err = sbtcheck.NewRunner( + cfg.SbtCheck(), + pg.NewBalances(cfg.DB()), + pg.NewEvents(cfg.DB()), + cfg.EventTypes(), + log.WithField("service", "sbt-checker"), + ).Run(context.Background()) + if err != nil { log.WithError(err).Error("Failed to run sbt checker") return false } diff --git a/internal/sbtcheck/config.go b/internal/sbtcheck/config.go index 2ba9e3d..e1df69d 100644 --- a/internal/sbtcheck/config.go +++ b/internal/sbtcheck/config.go @@ -15,7 +15,11 @@ import ( const baseTimeout = 5 * time.Second type SbtChecker interface { - SbtCheck() *Runner + SbtCheck() Config +} + +type Config struct { + networks map[string]network } type config struct { @@ -27,7 +31,7 @@ func NewConfig(getter kv.Getter) SbtChecker { return &config{getter: getter} } -func (c *config) SbtCheck() *Runner { +func (c *config) SbtCheck() Config { return c.once.Do(func() interface{} { var cfg struct { Networks []struct { @@ -73,6 +77,6 @@ func (c *config) SbtCheck() *Runner { } } - return &Runner{networks: nmap} - }).(*Runner) + return Config{networks: nmap} + }).(Config) } diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go index 422015a..6014923 100644 --- a/internal/sbtcheck/main.go +++ b/internal/sbtcheck/main.go @@ -26,7 +26,7 @@ type Runner struct { // ensure to always call .New() for balancesQ and eventsQ balancesQ data.BalancesQ eventsQ data.EventsQ - types *evtypes.Types + types evtypes.Types log *logan.Entry } @@ -36,6 +36,22 @@ type network struct { disabled bool } +func NewRunner( + cfg Config, + balancesQ data.BalancesQ, + eventsQ data.EventsQ, + types evtypes.Types, + log *logan.Entry, +) *Runner { + return &Runner{ + networks: cfg.networks, + balancesQ: balancesQ, + eventsQ: eventsQ, + types: types, + log: log, + } +} + func (r *Runner) Run(ctx context.Context) error { var wg sync.WaitGroup for name, net := range r.networks { diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index b9f0b98..16b5fb3 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -7,7 +7,6 @@ import ( "github.com/rarimo/rarime-auth-svc/resources" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" - "github.com/rarimo/rarime-points-svc/internal/sbtcheck" "gitlab.com/distributed_lab/logan/v3" ) @@ -19,7 +18,6 @@ const ( balancesQCtxKey eventTypesCtxKey userClaimsCtxKey - sbtCheckCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -71,13 +69,3 @@ func CtxUserClaims(claim []resources.Claim) func(context.Context) context.Contex func UserClaims(r *http.Request) []resources.Claim { return r.Context().Value(userClaimsCtxKey).([]resources.Claim) } - -func CtxSbtCheck(sbtCheck *sbtcheck.Runner) func(context.Context) context.Context { - return func(ctx context.Context) context.Context { - return context.WithValue(ctx, sbtCheckCtxKey, sbtCheck) - } -} - -func SbtCheck(r *http.Request) *sbtcheck.Runner { - return r.Context().Value(sbtCheckCtxKey).(*sbtcheck.Runner) -} diff --git a/internal/service/router.go b/internal/service/router.go index e4686e3..ace9218 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -18,7 +18,6 @@ func (s *service) router() chi.Router { handlers.CtxEventsQ(pg.NewEvents(s.cfg.DB())), handlers.CtxBalancesQ(pg.NewBalances(s.cfg.DB())), handlers.CtxEventTypes(s.cfg.EventTypes()), - handlers.CtxSbtCheck(s.cfg.SbtCheck()), ), ) r.Route("/integrations/rarime-points-svc/v1", func(r chi.Router) { From 93b9438098d358c336c60dc5c3ca41833a1e60bb Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Fri, 26 Jan 2024 17:36:40 +0200 Subject: [PATCH 48/63] =?UTF-8?q?Fully=20rewrite=20=E2=9C=8D=EF=B8=8F=20SB?= =?UTF-8?q?T=20runner=20from=20to=20HTTP=20due=20to=20bad=20WS=20implement?= =?UTF-8?q?ation=20=F0=9F=AB=A4=20in=20Geth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yaml | 15 ++- internal/cli/main.go | 11 +- internal/sbtcheck/config.go | 26 +++-- internal/sbtcheck/main.go | 216 +++++++++++++++++++++++------------- 4 files changed, 164 insertions(+), 104 deletions(-) diff --git a/config.yaml b/config.yaml index 8b9d314..bd71b6f 100644 --- a/config.yaml +++ b/config.yaml @@ -35,15 +35,18 @@ auth: sbt_check: networks: - name: polygon - rpc: wss://your-rpc - request_timeout: 3s + rpc: https://your-rpc contract: 0x... - - name: ethereum - rpc: wss://your-rpc request_timeout: 5s + start_from_block: 48984542 + block_window: 3 + max_blocks_per_request: 5000 + - name: ethereum + rpc: https://your-rpc contract: 0x... + request_timeout: 5s - name: disabled_sample disabled: true - rpc: wss://your-rpc - request_timeout: 5s + rpc: https://your-rpc contract: 0x... + request_timeout: 5s diff --git a/internal/cli/main.go b/internal/cli/main.go index 0a05e4b..19a5f3d 100644 --- a/internal/cli/main.go +++ b/internal/cli/main.go @@ -5,7 +5,6 @@ import ( "github.com/alecthomas/kingpin" "github.com/rarimo/rarime-points-svc/internal/config" - "github.com/rarimo/rarime-points-svc/internal/data/pg" "github.com/rarimo/rarime-points-svc/internal/sbtcheck" "github.com/rarimo/rarime-points-svc/internal/service" "gitlab.com/distributed_lab/kit/kv" @@ -27,7 +26,7 @@ func Run(args []string) bool { app := kingpin.New("rarime-points-svc", "") runCmd := app.Command("run", "run command") - serviceCmd := runCmd.Command("service", "run service") // you can insert custom help + serviceCmd := runCmd.Command("service", "run service") migrateCmd := app.Command("migrate", "migrate command") migrateUpCmd := migrateCmd.Command("up", "migrate db up") @@ -41,13 +40,7 @@ func Run(args []string) bool { switch cmd { case serviceCmd.FullCommand(): - err = sbtcheck.NewRunner( - cfg.SbtCheck(), - pg.NewBalances(cfg.DB()), - pg.NewEvents(cfg.DB()), - cfg.EventTypes(), - log.WithField("service", "sbt-checker"), - ).Run(context.Background()) + err = sbtcheck.Run(context.Background(), cfg) if err != nil { log.WithError(err).Error("Failed to run sbt checker") return false diff --git a/internal/sbtcheck/config.go b/internal/sbtcheck/config.go index e1df69d..4e57ba1 100644 --- a/internal/sbtcheck/config.go +++ b/internal/sbtcheck/config.go @@ -35,11 +35,14 @@ func (c *config) SbtCheck() Config { return c.once.Do(func() interface{} { var cfg struct { Networks []struct { - Name string `fig:"name,required"` - RPC string `fig:"rpc,required"` - Contract string `fig:"contract,required"` - RequestTimeout time.Duration `fig:"request_timeout"` - Disabled bool `fig:"disabled"` + Name string `fig:"name,required"` + RPC string `fig:"rpc,required"` + Contract string `fig:"contract,required"` + RequestTimeout time.Duration `fig:"request_timeout"` + StartFromBlock uint64 `fig:"start_from_block"` + BlockWindow uint64 `fig:"block_window"` + MaxBlocksPerRequest uint64 `fig:"max_blocks_per_request"` + Disabled bool `fig:"disabled"` } `fig:"networks,required"` } @@ -53,7 +56,7 @@ func (c *config) SbtCheck() Config { nmap := make(map[string]network, len(cfg.Networks)) for _, net := range cfg.Networks { if net.Disabled { - nmap[net.Name] = network{disabled: true} + nmap[net.Name] = network{name: net.Name, disabled: true} continue } @@ -62,7 +65,7 @@ func (c *config) SbtCheck() Config { panic(fmt.Errorf("failed to connect to rpc: %w", err)) } - filterer, err := verifiers.NewSBTIdentityVerifierFilterer(common.HexToAddress(net.Contract), cli) + filter, err := verifiers.NewSBTIdentityVerifierFilterer(common.HexToAddress(net.Contract), cli) if err != nil { panic(fmt.Errorf("failed to init contract filterer: %w", err)) } @@ -72,8 +75,13 @@ func (c *config) SbtCheck() Config { } nmap[net.Name] = network{ - events: filterer, - timeout: net.RequestTimeout, + name: net.Name, + blockHandler: cli, + filterer: filter, + timeout: net.RequestTimeout, + fromBlock: net.StartFromBlock, + blockWindow: net.BlockWindow, + maxBlocks: net.MaxBlocksPerRequest, } } diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go index 6014923..43223c9 100644 --- a/internal/sbtcheck/main.go +++ b/internal/sbtcheck/main.go @@ -9,118 +9,166 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/event" iden3 "github.com/iden3/go-iden3-core/v2" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" + "github.com/rarimo/rarime-points-svc/internal/data/pg" "github.com/rarimo/rarime-points-svc/internal/sbtcheck/verifiers" + "gitlab.com/distributed_lab/kit/comfig" + "gitlab.com/distributed_lab/kit/pgdb" "gitlab.com/distributed_lab/logan/v3" "gitlab.com/distributed_lab/running" ) -// all retries of runner are done on failures -const abnormalPeriod = 5 * time.Second - -type Runner struct { - networks map[string]network - // ensure to always call .New() for balancesQ and eventsQ - balancesQ data.BalancesQ - eventsQ data.EventsQ - types evtypes.Types - log *logan.Entry +type runner struct { + network + db *pgdb.DB + types evtypes.Types + log *logan.Entry } type network struct { - events *verifiers.SBTIdentityVerifierFilterer - timeout time.Duration - disabled bool + name string + filterer filterer + blockHandler blockHandler + timeout time.Duration + fromBlock uint64 + blockWindow uint64 + maxBlocks uint64 + disabled bool } -func NewRunner( - cfg Config, - balancesQ data.BalancesQ, - eventsQ data.EventsQ, - types evtypes.Types, - log *logan.Entry, -) *Runner { - return &Runner{ - networks: cfg.networks, - balancesQ: balancesQ, - eventsQ: eventsQ, - types: types, - log: log, - } +type blockHandler interface { + BlockNumber(ctx context.Context) (uint64, error) +} + +type filterer interface { + FilterSBTIdentityProved(opts *bind.FilterOpts, identityId []*big.Int) (*verifiers.SBTIdentityVerifierSBTIdentityProvedIterator, error) +} + +type extConfig interface { + comfig.Logger + pgdb.Databaser + evtypes.EventTypeser + SbtChecker } -func (r *Runner) Run(ctx context.Context) error { +func Run(ctx context.Context, cfg extConfig) error { + log := cfg.Log().WithField("who", "sbt-checker") var wg sync.WaitGroup - for name, net := range r.networks { + + for name, net := range cfg.SbtCheck().networks { if net.disabled { - r.log.Infof("SBT check: network %s disabled", name) + log.Infof("SBT check: network %s disabled", name) continue } - r.log.Infof("SBT check: running for network %s", name) + log.Infof("SBT check: running for network %s", name) wg.Add(1) - if err := r.run(ctx, net, &wg); err != nil { - return fmt.Errorf("run checker for network %s: %w", name, err) + r := &runner{ + network: net, + db: cfg.DB(), + types: cfg.EventTypes(), + log: log.WithField("network", name), } + + runnerName := fmt.Sprintf("sbt-checker[%s]", net.name) + go func() { + running.WithBackOff(ctx, r.log, runnerName, r.subscription, + 30*time.Second, 5*time.Second, 30*time.Second) + wg.Done() + }() } wg.Wait() - r.log.Infof("SBT check: all network checkers stopped") + log.Infof("SBT check: all network checkers stopped") return nil } -func (r *Runner) run(ctx context.Context, net network, wg *sync.WaitGroup) error { - sink := make(chan *verifiers.SBTIdentityVerifierSBTIdentityProved) +func (r *runner) subscription(ctx context.Context) error { + toBlock, err := r.getLastBlock(ctx) + if err != nil { + return fmt.Errorf("get last block: %w", err) + } + if toBlock == nil { + return nil + } + + r.log.Infof("Starting subscription from %d to %d", r.fromBlock, toBlock) + defer r.log.Info("Subscription finished") - toCtx, cancel := context.WithTimeout(ctx, net.timeout) + ctx2, cancel := context.WithTimeout(ctx, r.timeout) defer cancel() - sub, err := net.events.WatchSBTIdentityProved(&bind.WatchOpts{Context: toCtx}, sink, nil) + return r.filterEvents(ctx2, toBlock) +} + +func (r *runner) getLastBlock(ctx context.Context) (*uint64, error) { + ctx2, cancel := context.WithTimeout(ctx, r.timeout) + defer cancel() + + lastBlock, err := r.blockHandler.BlockNumber(ctx2) if err != nil { - return fmt.Errorf("subscribe to SBTIdentityProved event: %w", err) + return nil, fmt.Errorf("get last block number: %w", err) } - go running.UntilSuccess(ctx, r.log, "sbt-checker", func(ctx context.Context) (bool, error) { - err = r.subscribe(ctx, sub, sink) - if err == nil { - wg.Done() - } - return err == nil, err - }, abnormalPeriod, abnormalPeriod) + lastBlock -= r.blockWindow - return nil + if lastBlock < r.fromBlock { + r.log.Infof("Skipping window: start=%d > finish=%d", r.fromBlock, lastBlock) + return nil, nil + } + + if r.fromBlock+r.maxBlocks < lastBlock { + r.log.Debugf("maxBlockPerRequest limit exceeded: setting last block to %d instead of %d", r.fromBlock+r.maxBlocks, lastBlock) + lastBlock = r.fromBlock + r.maxBlocks + } + + return &lastBlock, nil } -func (r *Runner) subscribe( - ctx context.Context, - sub event.Subscription, - sink chan *verifiers.SBTIdentityVerifierSBTIdentityProved, -) error { - - for { - select { - case <-ctx.Done(): - r.log.Info("SBTIdentityProved subscription stopped") - return nil - case err := <-sub.Err(): - return fmt.Errorf("SBTIdentityProved subscription error: %w", err) - case evt := <-sink: - if evt == nil { - r.log.Debug("Got nil SBTIdentityProved event from subscription, continue") - continue - } - if err := r.handleEvent(*evt); err != nil { - return fmt.Errorf("handle event: %w", err) - } +func (r *runner) filterEvents(ctx context.Context, toBlock *uint64) error { + it, err := r.filterer.FilterSBTIdentityProved(&bind.FilterOpts{ + Start: r.fromBlock, + End: toBlock, + Context: ctx, + }, nil) + if err != nil { + return fmt.Errorf("filter SBTIdentityProved events: %w", err) + } + + defer func() { + // https://ethereum.stackexchange.com/questions/8199/are-both-the-eth-newfilter-from-to-fields-inclusive + // End in FilterLogs is inclusive + r.fromBlock = *toBlock + 1 + _ = it.Close() + }() + + for it.Next() { + evt := it.Event + if evt == nil { + r.log.Error("Got nil event") + continue + } + + if err = r.handleEvent(*evt); err != nil { + r.log.WithError(err).Error("Failed to handle event") + continue } } + + return nil } -func (r *Runner) handleEvent(evt verifiers.SBTIdentityVerifierSBTIdentityProved) error { +func (r *runner) handleEvent(evt verifiers.SBTIdentityVerifierSBTIdentityProved) error { + r.log.WithFields(map[string]any{ + "tx_hash": evt.Raw.TxHash, + "tx_index": evt.Raw.TxIndex, + "log_index": evt.Raw.Index, + "block": evt.Raw.BlockNumber, + }).Debugf("Got SBTIdentityProved event (identityId=%s)", evt.IdentityId) + did, err := parseDidFromUint256(evt.IdentityId) if err != nil { return fmt.Errorf("parse did from uint256 (identityId=%s): %w", evt.IdentityId, err) @@ -143,8 +191,8 @@ func (r *Runner) handleEvent(evt verifiers.SBTIdentityVerifierSBTIdentityProved) return nil } -func (r *Runner) getOrCreateBalance(did string) (string, error) { - balance, err := r.balancesQ.New().FilterByUserDID(did).Get() +func (r *runner) getOrCreateBalance(did string) (string, error) { + balance, err := r.balancesQ().FilterByUserDID(did).Get() if err != nil { return "", fmt.Errorf("get balance: %w", err) } @@ -162,8 +210,8 @@ func (r *Runner) getOrCreateBalance(did string) (string, error) { return id, nil } -func (r *Runner) findPohEvent(bid string) (*data.Event, error) { - poh, err := r.eventsQ.New(). +func (r *runner) findPohEvent(bid string) (*data.Event, error) { + poh, err := r.eventsQ(). FilterByBalanceID(bid). FilterByType(evtypes.TypeGetPoH). FilterByStatus(data.EventOpen). @@ -178,13 +226,13 @@ func (r *Runner) findPohEvent(bid string) (*data.Event, error) { return poh, nil } -func (r *Runner) fulfillPohEvent(poh data.Event) error { +func (r *runner) fulfillPohEvent(poh data.Event) error { getPoh := r.types.Get(evtypes.TypeGetPoH) if getPoh == nil { return fmt.Errorf("event types were not correctly initialized: missing %s", evtypes.TypeGetPoH) } - return r.eventsQ.New().FilterByID(poh.ID).Update(data.Event{ + return r.eventsQ().FilterByID(poh.ID).Update(data.Event{ Status: data.EventFulfilled, PointsAmount: sql.NullInt32{ Int32: getPoh.Reward, @@ -193,18 +241,18 @@ func (r *Runner) fulfillPohEvent(poh data.Event) error { }) } -func (r *Runner) createBalance(did string) (string, error) { - err := r.balancesQ.New().Insert(data.Balance{DID: did}) +func (r *runner) createBalance(did string) (string, error) { + err := r.balancesQ().Insert(data.Balance{DID: did}) if err != nil { return "", fmt.Errorf("insert balance: %w", err) } - balance, err := r.balancesQ.New().FilterByUserDID(did).Get() + balance, err := r.balancesQ().FilterByUserDID(did).Get() if err != nil { return "", fmt.Errorf("get balance back: %w", err) } - err = r.eventsQ.New().Insert(r.types.PrepareOpenEvents(balance.ID)...) + err = r.eventsQ().Insert(r.types.PrepareOpenEvents(balance.ID)...) if err != nil { return "", fmt.Errorf("insert open events: %w", err) } @@ -225,3 +273,11 @@ func parseDidFromUint256(raw *big.Int) (string, error) { return did.String(), nil } + +func (r *runner) balancesQ() data.BalancesQ { + return pg.NewBalances(r.db.Clone()) +} + +func (r *runner) eventsQ() data.EventsQ { + return pg.NewEvents(r.db.Clone()) +} From 4b25bec4d996fd851b6c6cdb0753d8d4e9d92b41 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Fri, 26 Jan 2024 18:06:07 +0200 Subject: [PATCH 49/63] Fix multiple errors in events fetching and DB --- internal/data/evtypes/main.go | 9 +++++++++ internal/sbtcheck/main.go | 23 ++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index 700f95b..aa3ef89 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -79,6 +79,15 @@ func (t Types) List() []resources.EventStaticMeta { return res } +func (t Types) IsExpired(name string) bool { + evType := t.Get(name) + if evType == nil { + return false + } + + return isExpiredEvent(*evType) +} + func isExpiredEvent(ev resources.EventStaticMeta) bool { return ev.ExpiresAt != nil && ev.ExpiresAt.Before(time.Now().UTC()) } diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go index 43223c9..e59b5c1 100644 --- a/internal/sbtcheck/main.go +++ b/internal/sbtcheck/main.go @@ -55,8 +55,12 @@ type extConfig interface { func Run(ctx context.Context, cfg extConfig) error { log := cfg.Log().WithField("who", "sbt-checker") - var wg sync.WaitGroup + if cfg.EventTypes().IsExpired(evtypes.TypeGetPoH) { + log.Warn("PoH event is expired, SBT check will not run") + return nil + } + var wg sync.WaitGroup for name, net := range cfg.SbtCheck().networks { if net.disabled { log.Infof("SBT check: network %s disabled", name) @@ -95,8 +99,8 @@ func (r *runner) subscription(ctx context.Context) error { return nil } - r.log.Infof("Starting subscription from %d to %d", r.fromBlock, toBlock) - defer r.log.Info("Subscription finished") + r.log.Debugf("Starting subscription from %d to %d", r.fromBlock, toBlock) + defer r.log.Debugf("Subscription finished") ctx2, cancel := context.WithTimeout(ctx, r.timeout) defer cancel() @@ -183,6 +187,10 @@ func (r *runner) handleEvent(evt verifiers.SBTIdentityVerifierSBTIdentityProved) if err != nil { return fmt.Errorf("find PoH event (balanceID=%s): %w", balanceID, err) } + if poh == nil { + return nil + } + if err = r.fulfillPohEvent(*poh); err != nil { return fmt.Errorf("update PoH event status to fulfilled: %w", err) } @@ -214,15 +222,20 @@ func (r *runner) findPohEvent(bid string) (*data.Event, error) { poh, err := r.eventsQ(). FilterByBalanceID(bid). FilterByType(evtypes.TypeGetPoH). - FilterByStatus(data.EventOpen). Get() if err != nil { - return nil, fmt.Errorf("get open PoH event: %w", err) + return nil, fmt.Errorf("get PoH event: %w", err) } if poh == nil { return nil, fmt.Errorf("PoH event was not properly added on balance creation") } + if poh.Status != data.EventOpen { + r.log.Infof("Balance %s is not eligible for another PoH event (id=%s status=%s)", + poh.BalanceID, poh.ID, poh.Status) + return nil, nil + } + return poh, nil } From f3c0fe0ed246a5fea963bbb89396d9446df87733 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Wed, 31 Jan 2024 13:49:03 +0200 Subject: [PATCH 50/63] Minor fixes after rebasing --- internal/data/evtypes/main.go | 8 +-- internal/sbtcheck/main.go | 62 +++++++++------------ internal/service/handlers/create_balance.go | 5 +- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index aa3ef89..d73258e 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -41,7 +41,7 @@ func (t Types) Get(name string) *resources.EventStaticMeta { return &v } -func (t Types) PrepareOpenEvents(balanceID string) []data.Event { +func (t Types) PrepareOpenEvents(userDID string) []data.Event { evTypes := t.List() events := make([]data.Event, len(evTypes)) @@ -49,9 +49,9 @@ func (t Types) PrepareOpenEvents(balanceID string) []data.Event { // TODO: add advanced logic for specific event types // for example, proof verification events should appear after the proof was issued events[i] = data.Event{ - BalanceID: balanceID, - Type: evType.Name, - Status: data.EventOpen, + UserDID: userDID, + Type: evType.Name, + Status: data.EventOpen, PointsAmount: sql.NullInt32{ Int32: evType.Reward, Valid: true, diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go index e59b5c1..aab179f 100644 --- a/internal/sbtcheck/main.go +++ b/internal/sbtcheck/main.go @@ -2,7 +2,6 @@ package sbtcheck import ( "context" - "database/sql" "fmt" "math/big" "sync" @@ -178,49 +177,47 @@ func (r *runner) handleEvent(evt verifiers.SBTIdentityVerifierSBTIdentityProved) return fmt.Errorf("parse did from uint256 (identityId=%s): %w", evt.IdentityId, err) } - balanceID, err := r.getOrCreateBalance(did) - if err != nil { + if err = r.createBalanceIfAbsent(did); err != nil { return fmt.Errorf("get or create balance (did=%s): %w", did, err) } - poh, err := r.findPohEvent(balanceID) + poh, err := r.findPohEvent(did) if err != nil { - return fmt.Errorf("find PoH event (balanceID=%s): %w", balanceID, err) + return fmt.Errorf("find PoH event (did=%s): %w", did, err) } if poh == nil { return nil } if err = r.fulfillPohEvent(*poh); err != nil { - return fmt.Errorf("update PoH event status to fulfilled: %w", err) + return fmt.Errorf("fulfill PoH event: %w", err) } r.log.Infof("Event %s was fulfilled for DID %s", evtypes.TypeGetPoH, did) return nil } -func (r *runner) getOrCreateBalance(did string) (string, error) { - balance, err := r.balancesQ().FilterByUserDID(did).Get() +func (r *runner) createBalanceIfAbsent(did string) error { + balance, err := r.balancesQ().FilterByDID(did).Get() if err != nil { - return "", fmt.Errorf("get balance: %w", err) + return fmt.Errorf("get balance: %w", err) } if balance != nil { r.log.Debugf("Balance exists for DID %s", did) - return balance.ID, nil + return nil } r.log.Debugf("Balance not found for DID %s, creating new one", did) - id, err := r.createBalance(did) - if err != nil { - return "", fmt.Errorf("create balance: %w", err) + if err = r.createBalance(did); err != nil { + return fmt.Errorf("create balance: %w", err) } - return id, nil + return nil } -func (r *runner) findPohEvent(bid string) (*data.Event, error) { +func (r *runner) findPohEvent(did string) (*data.Event, error) { poh, err := r.eventsQ(). - FilterByBalanceID(bid). + FilterByUserDID(did). FilterByType(evtypes.TypeGetPoH). Get() if err != nil { @@ -231,8 +228,8 @@ func (r *runner) findPohEvent(bid string) (*data.Event, error) { } if poh.Status != data.EventOpen { - r.log.Infof("Balance %s is not eligible for another PoH event (id=%s status=%s)", - poh.BalanceID, poh.ID, poh.Status) + r.log.Infof("User %s is not eligible for another PoH event (did=%s status=%s)", + poh.UserDID, poh.ID, poh.Status) return nil, nil } @@ -245,32 +242,25 @@ func (r *runner) fulfillPohEvent(poh data.Event) error { return fmt.Errorf("event types were not correctly initialized: missing %s", evtypes.TypeGetPoH) } - return r.eventsQ().FilterByID(poh.ID).Update(data.Event{ - Status: data.EventFulfilled, - PointsAmount: sql.NullInt32{ - Int32: getPoh.Reward, - Valid: true, - }, - }) -} - -func (r *runner) createBalance(did string) (string, error) { - err := r.balancesQ().Insert(data.Balance{DID: did}) + _, err := r.eventsQ().FilterByID(poh.ID).Update(data.EventFulfilled, nil, &getPoh.Reward) if err != nil { - return "", fmt.Errorf("insert balance: %w", err) + return fmt.Errorf("update PoH event status and reward: %w", err) } - balance, err := r.balancesQ().FilterByUserDID(did).Get() - if err != nil { - return "", fmt.Errorf("get balance back: %w", err) + return nil +} + +func (r *runner) createBalance(did string) error { + if err := r.balancesQ().Insert(did); err != nil { + return fmt.Errorf("insert balance: %w", err) } - err = r.eventsQ().Insert(r.types.PrepareOpenEvents(balance.ID)...) + err := r.eventsQ().Insert(r.types.PrepareOpenEvents(did)...) if err != nil { - return "", fmt.Errorf("insert open events: %w", err) + return fmt.Errorf("insert open events: %w", err) } - return balance.ID, nil + return nil } func parseDidFromUint256(raw *big.Int) (string, error) { diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index e2c2f35..9e7138c 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -3,7 +3,6 @@ package handlers import ( "net/http" - "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/service/requests" "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/ape/problems" @@ -16,14 +15,14 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - did := req.Data.Attributes.UserDid + did := req.Data.ID balance := getBalanceByDID(did, false, w, r) if balance != nil { ape.RenderErr(w, problems.Conflict()) return } - if err = BalancesQ(r).Insert(data.Balance{DID: did}); err != nil { + if err = BalancesQ(r).Insert(did); err != nil { Log(r).WithError(err).Error("Failed to create balance") ape.RenderErr(w, problems.InternalError()) return From c757e70521439b279556f2abb5de3afbacdeaf77 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 16:26:06 +0200 Subject: [PATCH 51/63] Add broadcaster config and Rarimo address for balance --- config.yaml | 4 + go.mod | 96 +- go.sum | 1646 +++++++++++++++++++- internal/assets/migrations/001_initial.sql | 3 +- internal/config/main.go | 18 +- internal/data/main.go | 14 +- internal/data/pg/balances.go | 12 +- internal/service/handlers/claim_event.go | 9 +- internal/service/handlers/ctx.go | 12 + internal/service/router.go | 1 + 10 files changed, 1772 insertions(+), 43 deletions(-) diff --git a/config.yaml b/config.yaml index fb00bc1..084766a 100644 --- a/config.yaml +++ b/config.yaml @@ -31,3 +31,7 @@ event_types: auth: addr: http://rarime-auth + +broadcaster: + addr: "http://broadcaster" + sender_account: "rarimo1..." diff --git a/go.mod b/go.mod index f6dd9f5..6a5d814 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/go-chi/chi v4.1.2+incompatible github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/rarimo/rarime-auth-svc v0.0.1-rc9 + github.com/rarimo/saver-grpc-lib v1.0.0 github.com/rubenv/sql-migrate v1.6.1 gitlab.com/distributed_lab/ape v1.7.1 gitlab.com/distributed_lab/figure/v3 v3.1.3 @@ -17,66 +18,159 @@ require ( ) require ( + cosmossdk.io/errors v1.0.0-beta.7 // indirect + cosmossdk.io/math v1.0.1 // indirect + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.1 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd v0.23.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect + github.com/cosmos/cosmos-sdk v0.46.12 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gorocksdb v1.2.0 // indirect + github.com/cosmos/iavl v0.19.5 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 // indirect + github.com/dgraph-io/ristretto v0.1.0 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/ethereum/go-ethereum v1.13.11 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/raven-go v0.2.0 // indirect github.com/getsentry/sentry-go v0.26.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/protobuf v1.3.3 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect + github.com/golang/glog v1.1.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/btree v1.1.2 // indirect github.com/google/jsonapi v1.0.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect github.com/holiman/uint256 v1.2.4 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.7 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/mtibben/percent v0.2.1 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/rarimo/broadcaster-svc v1.0.2 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect + github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tendermint/btcd v0.1.1 // indirect + github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tendermint/tendermint v0.34.27 // indirect + github.com/tendermint/tm-db v0.6.7 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect + github.com/zondax/hid v0.9.1 // indirect + github.com/zondax/ledger-go v0.14.1 // indirect gitlab.com/distributed_lab/figure v2.1.0+incompatible // indirect gitlab.com/distributed_lab/lorem v0.2.1 // indirect gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c // indirect + go.etcd.io/bbolt v1.3.6 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.17.0 // indirect + google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) + +replace ( + github.com/agl/ed25519 => github.com/bnb-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43 + github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.0-beta + github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 + github.com/cosmos/cosmos-sdk => github.com/rarimo/cosmos-sdk v0.46.7 + github.com/cosmos/iavl => github.com/cosmos/iavl v0.19.4 + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + github.com/tendermint/tendermint => github.com/tendermint/tendermint v0.34.24 + google.golang.org/grpc => google.golang.org/grpc v1.55.0 + ) diff --git a/go.sum b/go.sum index 5caa962..3aa80e5 100644 --- a/go.sum +++ b/go.sum @@ -1,44 +1,641 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= +cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= +cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= +cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= +cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= +cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= +cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= +github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= github.com/Masterminds/squirrel v1.4.0 h1:he5i/EXixZxrBUWcxzDYMiju9WZ3ld/l7QBNuo/eN3w= github.com/Masterminds/squirrel v1.4.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig= +github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs= github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI= +github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= @@ -52,6 +649,8 @@ github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= +github.com/coinbase/rosetta-sdk-go v0.7.9/go.mod h1:0/knutI7XGVqXmmH4OQD8OckFrbQ8yMsUZTG7FXCR2M= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= @@ -59,6 +658,21 @@ github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5U github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= +github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= +github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 h1:iKclrn3YEOwk4jQHT2ulgzuXyxmzmPczUalMwW4XH9k= +github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= +github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= +github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok= +github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= +github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= +github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= @@ -67,7 +681,11 @@ github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUp github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM= +github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -78,25 +696,58 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= +github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= +github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac h1:opbrjaN/L8gg6Xh5D04Tem+8xVcz6ajZlGCs49mQgyg= +github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= +github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.11 h1:b51Dsm+rEg7anFRUMGB8hODXHvNfcRKzz9vcj8wSdUs= github.com/ethereum/go-ethereum v1.13.11/go.mod h1:gFtlVORuUcT+UUIcJ/veCNjkuOSujCi338uSHJrYAew= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= @@ -109,6 +760,7 @@ github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49P github.com/getsentry/sentry-go v0.7.0/go.mod h1:pLFpD2Y5RHIKF9Bw3KH6/68DeN2K/XBJd8awjdPnUwg= github.com/getsentry/sentry-go v0.26.0 h1:IX3++sF6/4B5JcevhdZfdKIHfyvMmAq/UnqcyT2H6mA= github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= @@ -117,8 +769,28 @@ github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxm github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= +github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= @@ -126,47 +798,198 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW github.com/go-ozzo/ozzo-validation/v4 v4.2.1/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= +github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7/go.mod h1:XSx4m2SziAqk9DXY9nz659easTq4q6TyrpYd9tHSm0g= github.com/google/jsonapi v1.0.0 h1:qIGgO5Smu3yJmSs+QlvhQnrscdZfFhiV6S8ryJAglqU= github.com/google/jsonapi v1.0.0/go.mod h1:YYHiRPJT8ARXGER8In9VuLv4qvLfDmA9ULQqptbLE4s= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.6.1 h1:NASsgP4q6tL94WH6nJxKWj8As2H/2kop/bB1d8JMyRY= +github.com/hashicorp/go-getter v1.6.1/go.mod h1:IZCrswsZPeWv9IkVnLElzRU/gz/QPi6pZHn4tv6vbwA= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= +github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU= +github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -176,33 +999,64 @@ github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk= github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U= github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw= github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -224,29 +1078,49 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= +github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -255,64 +1129,128 @@ github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= -github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= -github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rarimo/broadcaster-svc v1.0.2 h1:ExQcjjWCRP5+POLDlZHrTD1ffUsBH+Dgv5FAgcP3BXc= +github.com/rarimo/broadcaster-svc v1.0.2/go.mod h1:lYIHy+X4IqQt4eBdtMN/V352H3EV0/gO8G+32SFwUWI= +github.com/rarimo/cosmos-sdk v0.46.7 h1:jU2PiWzc+19SF02cXM0O0puKPeH1C6Q6t2lzJ9s1ejc= +github.com/rarimo/cosmos-sdk v0.46.7/go.mod h1:fqKqz39U5IlEFb4nbQ72951myztsDzFKKDtffYJ63nk= github.com/rarimo/rarime-auth-svc v0.0.1-rc9 h1:JZfq1q3WaaLwa8ICk8RHEx4+ojl/JBE8N5zJ/uHZUwM= github.com/rarimo/rarime-auth-svc v0.0.1-rc9/go.mod h1:48c8FsJixnLeWx8F8MDy79FvhU1r0oTU11mwP3JPngQ= +github.com/rarimo/saver-grpc-lib v1.0.0 h1:MGUVjYg7unmodYczVsLqlqZNkT4CIgKqdo6aQtL1qdE= +github.com/rarimo/saver-grpc-lib v1.0.0/go.mod h1:DpugWK5B7Hi0bdC3MPe/9FD2zCxaRwsyykdwxtF1Zgg= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= +github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= +github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= +github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/rubenv/sql-migrate v1.6.1 h1:bo6/sjsan9HaXAsNxYP/jCEDUGibHp8JmOBw7NTGRos= github.com/rubenv/sql-migrate v1.6.1/go.mod h1:tPzespupJS0jacLfhbwto/UjSX+8h2FdWB7ar+QlHa0= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -320,7 +1258,12 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -328,6 +1271,8 @@ github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155 github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -338,7 +1283,9 @@ github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMV github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -347,6 +1294,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -355,16 +1303,29 @@ github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbe github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= +github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tendermint/tendermint v0.34.24 h1:879MKKJWYYPJEMMKME+DWUTY4V9f/FBpnZDI82ky+4k= +github.com/tendermint/tendermint v0.34.24/go.mod h1:rXVrl4OYzmIa1I91av3iLv2HS0fGSiucyW9J4aMTpKI= +github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= +github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= +github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= @@ -382,6 +1343,19 @@ github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmv github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= +github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= +github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= gitlab.com/distributed_lab/ape v1.6.1/go.mod h1:Qy9Y2arL0hmZIpVpctGEFhdrVsjWtyVJ5G+bZWcFT4s= gitlab.com/distributed_lab/ape v1.7.1 h1:LpTmZgG7Lvx6ulopQbH2aWI3s8ey9FsKVjbic3ZQIy4= gitlab.com/distributed_lab/ape v1.7.1/go.mod h1:Qy9Y2arL0hmZIpVpctGEFhdrVsjWtyVJ5G+bZWcFT4s= @@ -402,69 +1376,646 @@ gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c h1:cpIjV8C gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c/go.mod h1:4TnADX84dQjQMRHKIMPCVL0L97rD/Jxv0xDbrN6aKzk= gitlab.com/distributed_lab/urlval/v4 v4.0.3 h1:ZgdSBcvaoHBYmgze/u0bYfvq5Xx47pGTdfFmMYxn27s= gitlab.com/distributed_lab/urlval/v4 v4.0.3/go.mod h1:IdRM8gOyzpXNoAkIKWVwN+dChh6+1TioS/SVhTGvRFA= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -476,10 +2027,15 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -487,5 +2043,55 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index 439d801..c9b45e5 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -8,7 +8,8 @@ CREATE TABLE IF NOT EXISTS balances did text PRIMARY KEY, amount integer not null default 0, created_at integer not null default EXTRACT('EPOCH' FROM NOW()), - updated_at integer not null default EXTRACT('EPOCH' FROM NOW()) + updated_at integer not null default EXTRACT('EPOCH' FROM NOW()), + address text ); CREATE INDEX IF NOT EXISTS balances_amount_index ON balances using btree (amount); diff --git a/internal/config/main.go b/internal/config/main.go index 95ce2b1..6531276 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -3,6 +3,7 @@ package config import ( "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" + "github.com/rarimo/saver-grpc-lib/broadcaster" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/copus" "gitlab.com/distributed_lab/kit/copus/types" @@ -17,6 +18,7 @@ type Config interface { comfig.Listenerer evtypes.EventTypeser auth.Auther + broadcaster.Broadcasterer } type config struct { @@ -26,18 +28,20 @@ type config struct { comfig.Listenerer evtypes.EventTypeser auth.Auther + broadcaster.Broadcasterer getter kv.Getter } func New(getter kv.Getter) Config { return &config{ - getter: getter, - Databaser: pgdb.NewDatabaser(getter), - Copuser: copus.NewCopuser(getter), - Listenerer: comfig.NewListenerer(getter), - Logger: comfig.NewLogger(getter, comfig.LoggerOpts{}), - EventTypeser: evtypes.NewConfig(getter), - Auther: auth.NewAuther(getter), + getter: getter, + Databaser: pgdb.NewDatabaser(getter), + Copuser: copus.NewCopuser(getter), + Listenerer: comfig.NewListenerer(getter), + Logger: comfig.NewLogger(getter, comfig.LoggerOpts{}), + EventTypeser: evtypes.NewConfig(getter), + Auther: auth.NewAuther(getter), + Broadcasterer: broadcaster.New(getter), } } diff --git a/internal/data/main.go b/internal/data/main.go index 9e64ed8..30bd70c 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -38,7 +38,8 @@ type EventsQ interface { type BalancesQ interface { New() BalancesQ Insert(did string) error - AddAmount(points int32) error + UpdateAmountBy(points int32) error + SetAddress(string) error Page(*pgdb.OffsetPageParams) BalancesQ Select() ([]Balance, error) @@ -60,9 +61,10 @@ type Event struct { } type Balance struct { - DID string `db:"did"` - Amount int `db:"amount"` - CreatedAt int32 `db:"created_at"` - UpdatedAt int32 `db:"updated_at"` - Rank *int `db:"rank"` + DID string `db:"did"` + Amount int `db:"amount"` + CreatedAt int32 `db:"created_at"` + UpdatedAt int32 `db:"updated_at"` + Address sql.NullString `db:"address"` + Rank *int `db:"rank"` } diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index f5bc5a1..594981e 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -40,7 +40,7 @@ func (q *balances) Insert(did string) error { return nil } -func (q *balances) AddAmount(points int32) error { +func (q *balances) UpdateAmountBy(points int32) error { stmt := q.updater.Set("amount", squirrel.Expr("amount + ?", points)) if err := q.db.Exec(stmt); err != nil { @@ -50,6 +50,16 @@ func (q *balances) AddAmount(points int32) error { return nil } +func (q *balances) SetAddress(addr string) error { + stmt := q.updater.Set("address", addr) + + if err := q.db.Exec(stmt); err != nil { + return fmt.Errorf("set address %s: %w", addr, err) + } + + return nil +} + func (q *balances) Page(page *pgdb.OffsetPageParams) data.BalancesQ { q.selector = page.ApplyTo(q.selector, "amount") return q diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index 38dc62a..f188c75 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -3,7 +3,6 @@ package handlers import ( "net/http" - "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/service/requests" "github.com/rarimo/rarime-points-svc/resources" @@ -61,15 +60,11 @@ func getEventToClaim(id string, w http.ResponseWriter, r *http.Request) *data.Ev return nil } - if !auth.Authenticates(UserClaims(r), auth.UserGrant(event.UserDID)) { - ape.RenderErr(w, problems.Unauthorized()) - return nil - } - return event } func claimEventWithPoints(event data.Event, reward int32, w http.ResponseWriter, r *http.Request) *data.Event { + claimed, err := EventsQ(r).FilterByID(event.ID).Update(data.EventClaimed, nil, &reward) if err != nil { Log(r).WithError(err).Error("Failed to claim event") @@ -77,7 +72,7 @@ func claimEventWithPoints(event data.Event, reward int32, w http.ResponseWriter, return nil } - err = BalancesQ(r).FilterByDID(event.UserDID).AddAmount(reward) + err = BalancesQ(r).FilterByDID(event.UserDID).UpdateAmountBy(reward) if err != nil { Log(r).WithError(err).Error("Failed to accrue points to the balance") ape.RenderErr(w, problems.InternalError()) diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index 16b5fb3..e05c911 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -7,6 +7,7 @@ import ( "github.com/rarimo/rarime-auth-svc/resources" "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" + "github.com/rarimo/saver-grpc-lib/broadcaster" "gitlab.com/distributed_lab/logan/v3" ) @@ -18,6 +19,7 @@ const ( balancesQCtxKey eventTypesCtxKey userClaimsCtxKey + broadcasterCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -69,3 +71,13 @@ func CtxUserClaims(claim []resources.Claim) func(context.Context) context.Contex func UserClaims(r *http.Request) []resources.Claim { return r.Context().Value(userClaimsCtxKey).([]resources.Claim) } + +func CtxBroadcaster(broadcaster broadcaster.Broadcaster) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, broadcasterCtxKey, broadcaster) + } +} + +func Broadcaster(r *http.Request) broadcaster.Broadcaster { + return r.Context().Value(broadcasterCtxKey).(broadcaster.Broadcaster) +} diff --git a/internal/service/router.go b/internal/service/router.go index ace9218..17c49c4 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -18,6 +18,7 @@ func (s *service) router() chi.Router { handlers.CtxEventsQ(pg.NewEvents(s.cfg.DB())), handlers.CtxBalancesQ(pg.NewBalances(s.cfg.DB())), handlers.CtxEventTypes(s.cfg.EventTypes()), + handlers.CtxBroadcaster(s.cfg.Broadcaster()), ), ) r.Route("/integrations/rarime-points-svc/v1", func(r chi.Router) { From 1dc20c1f36866407a855a5ff313b1269fe352e09 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 16:47:26 +0200 Subject: [PATCH 52/63] Withdrawal endpoint docs --- config.yaml | 2 +- docs/spec/components/parameters/pathDID.yaml | 6 +++ docs/spec/components/schemas/Withdraw.yaml | 21 +++++++++ docs/spec/components/schemas/WithdrawKey.yaml | 12 +++++ ...s@rarime-points-svc@v1@balances@{did}.yaml | 45 ++++++++++++++++--- internal/config/main.go | 2 +- resources/model_resource_type.go | 1 + resources/model_withdraw.go | 43 ++++++++++++++++++ resources/model_withdraw_attributes.go | 12 +++++ 9 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 docs/spec/components/parameters/pathDID.yaml create mode 100644 docs/spec/components/schemas/Withdraw.yaml create mode 100644 docs/spec/components/schemas/WithdrawKey.yaml create mode 100644 resources/model_withdraw.go create mode 100644 resources/model_withdraw_attributes.go diff --git a/config.yaml b/config.yaml index 084766a..7eac38f 100644 --- a/config.yaml +++ b/config.yaml @@ -34,4 +34,4 @@ auth: broadcaster: addr: "http://broadcaster" - sender_account: "rarimo1..." + sender_account: "rarimo15hcd6tv7pe8hk2re7hu0zg0aphqdm2dtjrs0ds" diff --git a/docs/spec/components/parameters/pathDID.yaml b/docs/spec/components/parameters/pathDID.yaml new file mode 100644 index 0000000..8c9423a --- /dev/null +++ b/docs/spec/components/parameters/pathDID.yaml @@ -0,0 +1,6 @@ +in: path +name: 'did' +required: true +schema: + type: string + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" diff --git a/docs/spec/components/schemas/Withdraw.yaml b/docs/spec/components/schemas/Withdraw.yaml new file mode 100644 index 0000000..2322b25 --- /dev/null +++ b/docs/spec/components/schemas/Withdraw.yaml @@ -0,0 +1,21 @@ +allOf: + - $ref: '#/components/schemas/WithdrawKey' + - type: object + x-go-is-request: true + required: + - attributes + properties: + attributes: + type: object + required: + - amount + - address + properties: + amount: + type: integer + description: Amount of points to withdraw + example: 580 + address: + type: string + description: Rarimo address to withdraw to. Can be any valid address. + example: rarimo15hcd6tv7pe8hk2re7hu0zg0aphqdm2dtjrs0ds diff --git a/docs/spec/components/schemas/WithdrawKey.yaml b/docs/spec/components/schemas/WithdrawKey.yaml new file mode 100644 index 0000000..751eeb8 --- /dev/null +++ b/docs/spec/components/schemas/WithdrawKey.yaml @@ -0,0 +1,12 @@ +type: object +required: + - id + - type +properties: + id: + type: string + description: DID of the points owner + example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" + type: + type: string + enum: [ withdraw ] diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml index 20ed389..15b99b5 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml @@ -7,12 +7,45 @@ get: You should create new balance for the new user by making POST request. operationId: getPointsBalance parameters: - - in: path - name: 'did' - required: true - schema: - type: string - example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" + - $ref: '#/components/parameters/pathDID' + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Balance' + 400: + $ref: '#/components/responses/invalidParameter' + 401: + $ref: '#/components/responses/invalidAuth' + 500: + $ref: '#/components/responses/internalError' + +patch: + tags: + - Points balance + summary: Withdraw points to RMO + description: Convert points to RMO by exchange rate and withdraw to user wallet + operationId: withdrawPoints + parameters: + - $ref: '#/components/parameters/pathDID' + requestBody: + required: true + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Withdraw' responses: 200: description: Success diff --git a/internal/config/main.go b/internal/config/main.go index 6531276..e6af64a 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -41,7 +41,7 @@ func New(getter kv.Getter) Config { Listenerer: comfig.NewListenerer(getter), Logger: comfig.NewLogger(getter, comfig.LoggerOpts{}), EventTypeser: evtypes.NewConfig(getter), - Auther: auth.NewAuther(getter), + Auther: auth.NewAuther(getter), //nolint:misspell Broadcasterer: broadcaster.New(getter), } } diff --git a/resources/model_resource_type.go b/resources/model_resource_type.go index a029c42..0571d68 100644 --- a/resources/model_resource_type.go +++ b/resources/model_resource_type.go @@ -12,4 +12,5 @@ const ( CLAIM_EVENT ResourceType = "claim_event" CREATE_BALANCE ResourceType = "create_balance" EVENT ResourceType = "event" + WITHDRAW ResourceType = "withdraw" ) diff --git a/resources/model_withdraw.go b/resources/model_withdraw.go new file mode 100644 index 0000000..4cbc57a --- /dev/null +++ b/resources/model_withdraw.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type Withdraw struct { + Key + Attributes WithdrawAttributes `json:"attributes"` +} +type WithdrawRequest struct { + Data Withdraw `json:"data"` + Included Included `json:"included"` +} + +type WithdrawListRequest struct { + Data []Withdraw `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *WithdrawListRequest) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *WithdrawListRequest) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustWithdraw - returns Withdraw from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustWithdraw(key Key) *Withdraw { + var withdraw Withdraw + if c.tryFindEntry(key, &withdraw) { + return &withdraw + } + return nil +} diff --git a/resources/model_withdraw_attributes.go b/resources/model_withdraw_attributes.go new file mode 100644 index 0000000..9bbea67 --- /dev/null +++ b/resources/model_withdraw_attributes.go @@ -0,0 +1,12 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type WithdrawAttributes struct { + // Rarimo address to withdraw to. Can be any valid address. + Address string `json:"address"` + // Amount of points to withdraw + Amount int32 `json:"amount"` +} From d13f71aa16b6da1e9d4220c77bcc70b56dfe8433 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 17:17:50 +0200 Subject: [PATCH 53/63] Withdrawal handler --- docs/spec/components/schemas/Balance.yaml | 1 - internal/data/main.go | 2 +- internal/service/handlers/withdraw.go | 78 +++++++++++++++++++++++ internal/service/requests/withdraw.go | 27 ++++++++ internal/service/router.go | 7 +- resources/model_balance_attributes.go | 2 +- 6 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 internal/service/handlers/withdraw.go create mode 100644 internal/service/requests/withdraw.go diff --git a/docs/spec/components/schemas/Balance.yaml b/docs/spec/components/schemas/Balance.yaml index dd44edb..155e908 100644 --- a/docs/spec/components/schemas/Balance.yaml +++ b/docs/spec/components/schemas/Balance.yaml @@ -13,7 +13,6 @@ allOf: properties: amount: type: integer - format: int description: Amount of points example: 580 created_at: diff --git a/internal/data/main.go b/internal/data/main.go index 30bd70c..0667f77 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -62,7 +62,7 @@ type Event struct { type Balance struct { DID string `db:"did"` - Amount int `db:"amount"` + Amount int32 `db:"amount"` CreatedAt int32 `db:"created_at"` UpdatedAt int32 `db:"updated_at"` Address sql.NullString `db:"address"` diff --git a/internal/service/handlers/withdraw.go b/internal/service/handlers/withdraw.go new file mode 100644 index 0000000..1eb3f51 --- /dev/null +++ b/internal/service/handlers/withdraw.go @@ -0,0 +1,78 @@ +package handlers + +import ( + "fmt" + "net/http" + + cosmos "github.com/cosmos/cosmos-sdk/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-points-svc/internal/service/requests" + "github.com/rarimo/rarime-points-svc/resources" + "gitlab.com/distributed_lab/ape" + "gitlab.com/distributed_lab/ape/problems" +) + +func Withdraw(w http.ResponseWriter, r *http.Request) { + req, err := requests.NewWithdraw(r) + if err != nil { + ape.RenderErr(w, problems.BadRequest(err)...) + return + } + + if !isEnoughPoints(req, w, r) { + return + } + + err = BalancesQ(r).FilterByDID(req.Data.ID).UpdateAmountBy(-req.Data.Attributes.Amount) + if err != nil { + Log(r).WithError(err).Error("Failed to update balance") + ape.RenderErr(w, problems.InternalError()) + return + } + + if !broadcastWithdrawalTx(req, r) { + ape.RenderErr(w, problems.InternalError()) + return + } + + // see create_balance.go for explanation + balance := getBalanceByDID(req.Data.ID, true, w, r) + if balance == nil { + return + } + + ape.Render(w, newBalanceModel(*balance)) +} + +func isEnoughPoints(req resources.WithdrawRequest, w http.ResponseWriter, r *http.Request) bool { + balance := getBalanceByDID(req.Data.ID, false, w, r) + if balance == nil { + return false + } + + if balance.Amount < req.Data.Attributes.Amount { + ape.RenderErr(w, problems.BadRequest(validation.Errors{ + "data/attributes/amount": fmt.Errorf("insufficient balance: %d", balance.Amount), + })...) + return false + } + + return true +} + +func broadcastWithdrawalTx(req resources.WithdrawRequest, r *http.Request) bool { + var ( + from = cosmos.MustAccAddressFromBech32(Broadcaster(r).Sender()) + to = cosmos.MustAccAddressFromBech32(req.Data.Attributes.Address) + coins = cosmos.NewCoins(cosmos.NewInt64Coin("urmo", int64(req.Data.Attributes.Amount))) + ) + + err := Broadcaster(r).BroadcastTx(r.Context(), bank.NewMsgSend(from, to, coins)) + if err != nil { + Log(r).WithError(err).Error("Failed to broadcast transaction") + return false + } + + return true +} diff --git a/internal/service/requests/withdraw.go b/internal/service/requests/withdraw.go new file mode 100644 index 0000000..3a67afb --- /dev/null +++ b/internal/service/requests/withdraw.go @@ -0,0 +1,27 @@ +package requests + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/go-chi/chi" + validation "github.com/go-ozzo/ozzo-validation/v4" + "github.com/rarimo/rarime-points-svc/resources" +) + +func NewWithdraw(r *http.Request) (req resources.WithdrawRequest, err error) { + did := chi.URLParam(r, "did") + + if err = json.NewDecoder(r.Body).Decode(&req); err != nil { + err = fmt.Errorf("decode request body: %w", err) + return + } + + return req, validation.Errors{ + "data/id": validation.Validate(req.Data.ID, validation.Required, validation.In(did)), + "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.WITHDRAW)), + "data/attributes/amount": validation.Validate(req.Data.Attributes.Amount, validation.Required, validation.Min(1)), + "data/attributes/address": validation.Validate(req.Data.Attributes.Address, validation.Required), + }.Filter() +} diff --git a/internal/service/router.go b/internal/service/router.go index 17c49c4..25bd582 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -24,8 +24,11 @@ func (s *service) router() chi.Router { r.Route("/integrations/rarime-points-svc/v1", func(r chi.Router) { r.Group(func(r chi.Router) { r.Use(handlers.AuthMiddleware(s.cfg.Auth(), s.log)) - r.Get("/balances/{did}", handlers.GetBalance) - r.Post("/balances", handlers.CreateBalance) + r.Route("/balances", func(r chi.Router) { + r.Post("/", handlers.CreateBalance) + r.Get("/{did}", handlers.GetBalance) + r.Patch("/{did}", handlers.Withdraw) + }) r.Get("/events", handlers.ListEvents) r.Patch("/events/{id}", handlers.ClaimEvent) }) diff --git a/resources/model_balance_attributes.go b/resources/model_balance_attributes.go index af5f3ff..6990db7 100644 --- a/resources/model_balance_attributes.go +++ b/resources/model_balance_attributes.go @@ -6,7 +6,7 @@ package resources type BalanceAttributes struct { // Amount of points - Amount int `json:"amount"` + Amount int32 `json:"amount"` // Unix timestamp of balance creation CreatedAt int32 `json:"created_at"` // Rank of the user in the full leaderboard. Returned only for the single user. From 187396e207975f5622a6bbe7ff5f06ae0c2ab957 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 17:35:03 +0200 Subject: [PATCH 54/63] Configurable point price in urmo --- config.yaml | 3 +++ internal/config/main.go | 5 ++++- internal/config/point_price.go | 25 +++++++++++++++++++++++++ internal/service/handlers/ctx.go | 11 +++++++++++ internal/service/handlers/withdraw.go | 3 ++- internal/service/router.go | 1 + 6 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 internal/config/point_price.go diff --git a/config.yaml b/config.yaml index 7eac38f..40c2975 100644 --- a/config.yaml +++ b/config.yaml @@ -35,3 +35,6 @@ auth: broadcaster: addr: "http://broadcaster" sender_account: "rarimo15hcd6tv7pe8hk2re7hu0zg0aphqdm2dtjrs0ds" + +withdrawal: + point_price_urmo: 100 \ No newline at end of file diff --git a/internal/config/main.go b/internal/config/main.go index e6af64a..57993cc 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -19,6 +19,8 @@ type Config interface { evtypes.EventTypeser auth.Auther broadcaster.Broadcasterer + + PointPrice() int32 } type config struct { @@ -30,7 +32,8 @@ type config struct { auth.Auther broadcaster.Broadcasterer - getter kv.Getter + pointPrice comfig.Once + getter kv.Getter } func New(getter kv.Getter) Config { diff --git a/internal/config/point_price.go b/internal/config/point_price.go new file mode 100644 index 0000000..27c211b --- /dev/null +++ b/internal/config/point_price.go @@ -0,0 +1,25 @@ +package config + +import ( + "fmt" + + "gitlab.com/distributed_lab/figure/v3" + "gitlab.com/distributed_lab/kit/kv" +) + +func (c *config) PointPrice() int32 { + return c.pointPrice.Do(func() interface{} { + var cfg struct { + PointPriceURMO int32 `fig:"point_price_urmo,required"` + } + + err := figure.Out(&cfg). + From(kv.MustGetStringMap(c.getter, "withdrawal")). + Please() + if err != nil { + panic(fmt.Errorf("failed to figure out withdrawal point price: %w", err)) + } + + return cfg.PointPriceURMO + }).(int32) +} diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index e05c911..14c6ac2 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -20,6 +20,7 @@ const ( eventTypesCtxKey userClaimsCtxKey broadcasterCtxKey + pointPriceCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -81,3 +82,13 @@ func CtxBroadcaster(broadcaster broadcaster.Broadcaster) func(context.Context) c func Broadcaster(r *http.Request) broadcaster.Broadcaster { return r.Context().Value(broadcasterCtxKey).(broadcaster.Broadcaster) } + +func CtxPointPrice(price int32) func(context.Context) context.Context { + return func(ctx context.Context) context.Context { + return context.WithValue(ctx, pointPriceCtxKey, price) + } +} + +func PointPrice(r *http.Request) int32 { + return r.Context().Value(pointPriceCtxKey).(int32) +} diff --git a/internal/service/handlers/withdraw.go b/internal/service/handlers/withdraw.go index 1eb3f51..3e9ca55 100644 --- a/internal/service/handlers/withdraw.go +++ b/internal/service/handlers/withdraw.go @@ -65,7 +65,8 @@ func broadcastWithdrawalTx(req resources.WithdrawRequest, r *http.Request) bool var ( from = cosmos.MustAccAddressFromBech32(Broadcaster(r).Sender()) to = cosmos.MustAccAddressFromBech32(req.Data.Attributes.Address) - coins = cosmos.NewCoins(cosmos.NewInt64Coin("urmo", int64(req.Data.Attributes.Amount))) + urmo = req.Data.Attributes.Amount * PointPrice(r) + coins = cosmos.NewCoins(cosmos.NewInt64Coin("urmo", int64(urmo))) ) err := Broadcaster(r).BroadcastTx(r.Context(), bank.NewMsgSend(from, to, coins)) diff --git a/internal/service/router.go b/internal/service/router.go index 25bd582..01cfdbb 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -19,6 +19,7 @@ func (s *service) router() chi.Router { handlers.CtxBalancesQ(pg.NewBalances(s.cfg.DB())), handlers.CtxEventTypes(s.cfg.EventTypes()), handlers.CtxBroadcaster(s.cfg.Broadcaster()), + handlers.CtxPointPrice(s.cfg.PointPrice()), ), ) r.Route("/integrations/rarime-points-svc/v1", func(r chi.Router) { From 083954830411ef4c8756849e440fe550a076f4ca Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 17:42:05 +0200 Subject: [PATCH 55/63] Drop unnecessary address from DB --- internal/assets/migrations/001_initial.sql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/assets/migrations/001_initial.sql b/internal/assets/migrations/001_initial.sql index c9b45e5..439d801 100644 --- a/internal/assets/migrations/001_initial.sql +++ b/internal/assets/migrations/001_initial.sql @@ -8,8 +8,7 @@ CREATE TABLE IF NOT EXISTS balances did text PRIMARY KEY, amount integer not null default 0, created_at integer not null default EXTRACT('EPOCH' FROM NOW()), - updated_at integer not null default EXTRACT('EPOCH' FROM NOW()), - address text + updated_at integer not null default EXTRACT('EPOCH' FROM NOW()) ); CREATE INDEX IF NOT EXISTS balances_amount_index ON balances using btree (amount); From 224064b1a14d2dbb069fa0fd5ffe1deb05f0bc40 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 18:27:44 +0200 Subject: [PATCH 56/63] Drop unnecessary address from DB model too --- internal/data/main.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/internal/data/main.go b/internal/data/main.go index 0667f77..93dc640 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -61,10 +61,9 @@ type Event struct { } type Balance struct { - DID string `db:"did"` - Amount int32 `db:"amount"` - CreatedAt int32 `db:"created_at"` - UpdatedAt int32 `db:"updated_at"` - Address sql.NullString `db:"address"` - Rank *int `db:"rank"` + DID string `db:"did"` + Amount int32 `db:"amount"` + CreatedAt int32 `db:"created_at"` + UpdatedAt int32 `db:"updated_at"` + Rank *int `db:"rank"` } From ea64812c792789bfc58800c83ffa4a6ed1ecebb0 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 18:44:54 +0200 Subject: [PATCH 57/63] Add option to disable open event auto-creation on balance creation --- config.yaml | 6 ++++++ .../components/schemas/EventStaticMeta.yaml | 17 ++++++++++++----- internal/data/evtypes/config.go | 2 ++ internal/data/evtypes/main.go | 4 ++-- resources/model_event_static_meta.go | 4 +++- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/config.yaml b/config.yaml index 40c2975..e3e54dd 100644 --- a/config.yaml +++ b/config.yaml @@ -28,6 +28,12 @@ event_types: reward: 5 frequency: daily description: Lorem ipsum dolor sit amet + - name: verify_proof + title: Verify proof {:id} + reward: 10 + frequency: unlimited + description: Lorem ipsum dolor sit amet + no_auto_open: true auth: addr: http://rarime-auth diff --git a/docs/spec/components/schemas/EventStaticMeta.yaml b/docs/spec/components/schemas/EventStaticMeta.yaml index bd847b1..d5249c5 100644 --- a/docs/spec/components/schemas/EventStaticMeta.yaml +++ b/docs/spec/components/schemas/EventStaticMeta.yaml @@ -8,6 +8,7 @@ required: - title - description - frequency + - no_auto_open properties: name: type: string @@ -17,11 +18,6 @@ properties: type: integer description: Reward amount in points example: 50 - expires_at: - type: string - format: time.Time - description: General event expiration date - example: 2020-01-01T00:00:00Z title: type: string example: Get PoH credential @@ -34,3 +30,14 @@ properties: Event frequency, which means how often you can fulfill certain task and claim the reward. enum: [one-time, daily, weekly, unlimited, custom] + no_auto_open: + type: boolean + description: | + If true, the event will not be created with `open` status automatically + when user creates the balance. + example: true + expires_at: + type: string + format: time.Time + description: General event expiration date (UTC RFC3339) + example: 2020-01-01T00:00:00Z diff --git a/internal/data/evtypes/config.go b/internal/data/evtypes/config.go index a918106..e6113ed 100644 --- a/internal/data/evtypes/config.go +++ b/internal/data/evtypes/config.go @@ -33,6 +33,7 @@ func (c *config) EventTypes() Types { Title string `fig:"title,required"` Frequency Frequency `fig:"frequency,required"` ExpiresAt *time.Time `fig:"expires_at"` + NoAutoOpen bool `fig:"no_auto_open"` } `fig:"types,required"` } @@ -56,6 +57,7 @@ func (c *config) EventTypes() Types { Title: t.Title, Frequency: t.Frequency.String(), ExpiresAt: t.ExpiresAt, + NoAutoOpen: t.NoAutoOpen, } } diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index 125cd12..25d72d6 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -37,7 +37,7 @@ func (t Types) Get(name string) *resources.EventStaticMeta { return &v } -// List returns non-expired event types +// List returns non-expired and auto-opening event types func (t Types) List() []resources.EventStaticMeta { if t.inner == nil { panic("event types are not correctly initialized") @@ -45,7 +45,7 @@ func (t Types) List() []resources.EventStaticMeta { res := make([]resources.EventStaticMeta, 0, len(t.inner)) for _, v := range t.inner { - if isExpiredEvent(v) { + if v.NoAutoOpen || isExpiredEvent(v) { continue } res = append(res, v) diff --git a/resources/model_event_static_meta.go b/resources/model_event_static_meta.go index e7c3be4..659e1be 100644 --- a/resources/model_event_static_meta.go +++ b/resources/model_event_static_meta.go @@ -9,12 +9,14 @@ import "time" // Primary event metadata in plain JSON. This is a template to be filled by `dynamic` when it's present. type EventStaticMeta struct { Description string `json:"description"` - // General event expiration date + // General event expiration date (UTC RFC3339) ExpiresAt *time.Time `json:"expires_at,omitempty"` // Event frequency, which means how often you can fulfill certain task and claim the reward. Frequency string `json:"frequency"` // Unique event code name Name string `json:"name"` + // If true, the event will not be created with `open` status automatically when user creates the balance. + NoAutoOpen bool `json:"no_auto_open"` // Reward amount in points Reward int32 `json:"reward"` Title string `json:"title"` From 6b93676b740a9b0d0303e187b79e36584498ab3a Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 19:46:32 +0200 Subject: [PATCH 58/63] Fix numerous errors in DB API --- go.mod | 9 ++++-- go.sum | 8 +++++ internal/data/jsonb.go | 21 ++++++++++++++ internal/data/main.go | 18 ++++++------ internal/data/pg/events.go | 37 +++++++++++++++--------- internal/sbtcheck/main.go | 2 +- internal/service/handlers/list_events.go | 3 +- 7 files changed, 70 insertions(+), 28 deletions(-) create mode 100644 internal/data/jsonb.go diff --git a/go.mod b/go.mod index 6a5d814..cf9f0df 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,11 @@ go 1.21.3 require ( github.com/Masterminds/squirrel v1.4.0 github.com/alecthomas/kingpin v2.2.6+incompatible + github.com/cosmos/cosmos-sdk v0.46.12 + github.com/ethereum/go-ethereum v1.13.11 github.com/go-chi/chi v4.1.2+incompatible github.com/go-ozzo/ozzo-validation/v4 v4.3.0 + github.com/iden3/go-iden3-core/v2 v2.0.4 github.com/rarimo/rarime-auth-svc v0.0.1-rc9 github.com/rarimo/saver-grpc-lib v1.0.0 github.com/rubenv/sql-migrate v1.6.1 @@ -14,6 +17,7 @@ require ( gitlab.com/distributed_lab/figure/v3 v3.1.3 gitlab.com/distributed_lab/kit v1.11.2 gitlab.com/distributed_lab/logan v3.8.1+incompatible + gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c gitlab.com/distributed_lab/urlval/v4 v4.0.3 ) @@ -42,7 +46,6 @@ require ( github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect - github.com/cosmos/cosmos-sdk v0.46.12 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.19.5 // indirect @@ -58,7 +61,6 @@ require ( github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/ethereum/go-ethereum v1.13.11 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/raven-go v0.2.0 // indirect github.com/getsentry/sentry-go v0.26.0 // indirect @@ -87,6 +89,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect github.com/holiman/uint256 v1.2.4 // indirect + github.com/iden3/go-iden3-crypto v0.0.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect @@ -101,6 +104,7 @@ require ( github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect @@ -139,7 +143,6 @@ require ( github.com/zondax/ledger-go v0.14.1 // indirect gitlab.com/distributed_lab/figure v2.1.0+incompatible // indirect gitlab.com/distributed_lab/lorem v0.2.1 // indirect - gitlab.com/distributed_lab/running v0.0.0-20200706131153-4af0e83eb96c // indirect go.etcd.io/bbolt v1.3.6 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.18.0 // indirect diff --git a/go.sum b/go.sum index 3aa80e5..231ecc1 100644 --- a/go.sum +++ b/go.sum @@ -616,6 +616,8 @@ github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91 github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -1002,6 +1004,10 @@ github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFck github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/iden3/go-iden3-core/v2 v2.0.4 h1:ggzC2zgOWgJAAcuG9X8bQG1r4gAoHZWqY7aLV8b1qgc= +github.com/iden3/go-iden3-core/v2 v2.0.4/go.mod h1:L9PxhWPvoS9qTb3inEkZBm1RpjHBt+VTwvxssdzbAdw= +github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= +github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= @@ -1134,6 +1140,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= diff --git a/internal/data/jsonb.go b/internal/data/jsonb.go new file mode 100644 index 0000000..f3759ae --- /dev/null +++ b/internal/data/jsonb.go @@ -0,0 +1,21 @@ +package data + +import ( + "database/sql/driver" + "encoding/json" + + "gitlab.com/distributed_lab/kit/pgdb" +) + +type Jsonb json.RawMessage + +func (j *Jsonb) Value() (driver.Value, error) { + if j == nil || len(*j) == 0 { + return nil, nil + } + return pgdb.JSONValue(j) +} + +func (j *Jsonb) Scan(src interface{}) error { + return pgdb.JSONScan(src, j) +} diff --git a/internal/data/main.go b/internal/data/main.go index 93dc640..129f8d9 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -22,7 +22,7 @@ func (s EventStatus) String() string { type EventsQ interface { New() EventsQ Insert(...Event) error - Update(status EventStatus, meta []json.RawMessage, points *int32) (*Event, error) + Update(status EventStatus, meta json.RawMessage, points *int32) (*Event, error) Page(*pgdb.CursorPageParams) EventsQ Select() ([]Event, error) @@ -50,14 +50,14 @@ type BalancesQ interface { } type Event struct { - ID string `db:"id"` - UserDID string `db:"user_did"` - Type string `db:"type"` - Status EventStatus `db:"status"` - CreatedAt int32 `db:"created_at"` - UpdatedAt int32 `db:"updated_at"` - Meta json.RawMessage `db:"meta"` - PointsAmount sql.NullInt32 `db:"points_amount"` + ID string `db:"id"` + UserDID string `db:"user_did"` + Type string `db:"type"` + Status EventStatus `db:"status"` + CreatedAt int32 `db:"created_at"` + UpdatedAt int32 `db:"updated_at"` + Meta Jsonb `db:"meta"` + PointsAmount sql.NullInt32 `db:"points_amount"` } type Balance struct { diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 1782f69..e10b99a 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -3,6 +3,7 @@ package pg import ( "database/sql" "encoding/json" + "errors" "fmt" "github.com/Masterminds/squirrel" @@ -15,6 +16,7 @@ const eventsTable = "events" type events struct { db *pgdb.DB selector squirrel.SelectBuilder + updater squirrel.UpdateBuilder counter squirrel.SelectBuilder } @@ -22,6 +24,7 @@ func NewEvents(db *pgdb.DB) data.EventsQ { return &events{ db: db, selector: squirrel.Select("*").From(eventsTable), + updater: squirrel.Update(eventsTable), counter: squirrel.Select("count(id) AS count").From(eventsTable), } } @@ -38,7 +41,11 @@ func (q *events) Insert(events ...data.Event) error { stmt := squirrel.Insert(eventsTable). Columns("user_did", "type", "status", "meta", "points_amount") for _, event := range events { - stmt = stmt.Values(event.UserDID, event.Type, event.Status, event.Meta, event.PointsAmount) + var meta any + if len(event.Meta) != 0 { + meta = event.Meta + } + stmt = stmt.Values(event.UserDID, event.Type, event.Status, meta, event.PointsAmount) } if err := q.db.Exec(stmt); err != nil { @@ -48,7 +55,7 @@ func (q *events) Insert(events ...data.Event) error { return nil } -func (q *events) Update(status data.EventStatus, meta []json.RawMessage, points *int32) (*data.Event, error) { +func (q *events) Update(status data.EventStatus, meta json.RawMessage, points *int32) (*data.Event, error) { umap := map[string]any{ "status": status, } @@ -60,7 +67,7 @@ func (q *events) Update(status data.EventStatus, meta []json.RawMessage, points } var res data.Event - stmt := squirrel.Update(eventsTable).SetMap(umap) + stmt := q.updater.SetMap(umap).Suffix("RETURNING *") if err := q.db.Get(&res, stmt); err != nil { return nil, fmt.Errorf("update event with map %+v: %w", umap, err) @@ -88,6 +95,9 @@ func (q *events) Get() (*data.Event, error) { var res data.Event if err := q.db.Get(&res, q.selector); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } return nil, fmt.Errorf("get event: %w", err) } @@ -107,31 +117,30 @@ func (q *events) Count() (int, error) { } func (q *events) FilterByID(id string) data.EventsQ { - q.selector = q.selector.Where(squirrel.Eq{"id": id}) - q.counter = q.counter.Where(squirrel.Eq{"id": id}) - return q + return q.applyCondition(squirrel.Eq{"id": id}) } func (q *events) FilterByUserDID(did string) data.EventsQ { - q.selector = q.selector.Where(squirrel.Eq{"user_did": did}) - q.counter = q.counter.Where(squirrel.Eq{"user_did": did}) - return q + return q.applyCondition(squirrel.Eq{"user_did": did}) } func (q *events) FilterByStatus(statuses ...data.EventStatus) data.EventsQ { if len(statuses) == 0 { return q } - q.selector = q.selector.Where(squirrel.Eq{"status": statuses}) - q.counter = q.counter.Where(squirrel.Eq{"status": statuses}) - return q + return q.applyCondition(squirrel.Eq{"status": statuses}) } func (q *events) FilterByType(types ...string) data.EventsQ { if len(types) == 0 { return q } - q.selector = q.selector.Where(squirrel.Eq{"type": types}) - q.counter = q.counter.Where(squirrel.Eq{"type": types}) + return q.applyCondition(squirrel.Eq{"type": types}) +} + +func (q *events) applyCondition(cond squirrel.Eq) data.EventsQ { + q.selector = q.selector.Where(cond) + q.updater = q.updater.Where(cond) + q.counter = q.counter.Where(cond) return q } diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go index aab179f..a99ced6 100644 --- a/internal/sbtcheck/main.go +++ b/internal/sbtcheck/main.go @@ -228,7 +228,7 @@ func (r *runner) findPohEvent(did string) (*data.Event, error) { } if poh.Status != data.EventOpen { - r.log.Infof("User %s is not eligible for another PoH event (did=%s status=%s)", + r.log.Infof("User %s is not eligible for another PoH event (id=%s status=%s)", poh.UserDID, poh.ID, poh.Status) return nil, nil } diff --git a/internal/service/handlers/list_events.go b/internal/service/handlers/list_events.go index 3aad5e6..a8712b0 100644 --- a/internal/service/handlers/list_events.go +++ b/internal/service/handlers/list_events.go @@ -1,6 +1,7 @@ package handlers import ( + "encoding/json" "net/http" "github.com/rarimo/rarime-auth-svc/pkg/auth" @@ -101,7 +102,7 @@ func newEventModel(event data.Event, meta resources.EventStaticMeta) resources.E UpdatedAt: event.UpdatedAt, Meta: resources.EventMeta{ Static: meta, - Dynamic: &event.Meta, + Dynamic: (*json.RawMessage)(&event.Meta), }, Status: event.Status.String(), PointsAmount: points, From 47b6d28bd8e071308e4a3534fd2ffbf3f337b7b3 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Thu, 1 Feb 2024 20:43:49 +0200 Subject: [PATCH 59/63] =?UTF-8?q?Wrap=20some=20operations=20in=20atomic=20?= =?UTF-8?q?transaction=20=E2=9A=9B=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/config/main.go | 2 +- internal/data/main.go | 2 +- internal/data/pg/balances.go | 12 +--------- internal/data/pg/events.go | 4 ++++ internal/sbtcheck/main.go | 21 ++++++++++------- internal/service/handlers/claim_event.go | 26 +++++++++++++-------- internal/service/handlers/create_balance.go | 25 ++++++++++---------- internal/service/handlers/withdraw.go | 26 ++++++++++++--------- 8 files changed, 62 insertions(+), 56 deletions(-) diff --git a/internal/config/main.go b/internal/config/main.go index 4a9a298..2e00fbd 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -49,6 +49,6 @@ func New(getter kv.Getter) Config { Auther: auth.NewAuther(getter), //nolint:misspell Broadcasterer: broadcaster.New(getter), EventTypeser: evtypes.NewConfig(getter), - SbtChecker: sbtcheck.NewConfig(getter), + SbtChecker: sbtcheck.NewConfig(getter), } } diff --git a/internal/data/main.go b/internal/data/main.go index 129f8d9..a2cb240 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -23,6 +23,7 @@ type EventsQ interface { New() EventsQ Insert(...Event) error Update(status EventStatus, meta json.RawMessage, points *int32) (*Event, error) + Transaction(func() error) error Page(*pgdb.CursorPageParams) EventsQ Select() ([]Event, error) @@ -39,7 +40,6 @@ type BalancesQ interface { New() BalancesQ Insert(did string) error UpdateAmountBy(points int32) error - SetAddress(string) error Page(*pgdb.OffsetPageParams) BalancesQ Select() ([]Balance, error) diff --git a/internal/data/pg/balances.go b/internal/data/pg/balances.go index 594981e..72b9c6b 100644 --- a/internal/data/pg/balances.go +++ b/internal/data/pg/balances.go @@ -44,17 +44,7 @@ func (q *balances) UpdateAmountBy(points int32) error { stmt := q.updater.Set("amount", squirrel.Expr("amount + ?", points)) if err := q.db.Exec(stmt); err != nil { - return fmt.Errorf("add %d points: %w", points, err) - } - - return nil -} - -func (q *balances) SetAddress(addr string) error { - stmt := q.updater.Set("address", addr) - - if err := q.db.Exec(stmt); err != nil { - return fmt.Errorf("set address %s: %w", addr, err) + return fmt.Errorf("update amount by %d points: %w", points, err) } return nil diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index e10b99a..7871c76 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -81,6 +81,10 @@ func (q *events) Page(page *pgdb.CursorPageParams) data.EventsQ { return q } +func (q *events) Transaction(f func() error) error { + return q.db.Transaction(f) +} + func (q *events) Select() ([]data.Event, error) { var res []data.Event diff --git a/internal/sbtcheck/main.go b/internal/sbtcheck/main.go index a99ced6..7abf5bb 100644 --- a/internal/sbtcheck/main.go +++ b/internal/sbtcheck/main.go @@ -42,7 +42,7 @@ type blockHandler interface { } type filterer interface { - FilterSBTIdentityProved(opts *bind.FilterOpts, identityId []*big.Int) (*verifiers.SBTIdentityVerifierSBTIdentityProvedIterator, error) + FilterSBTIdentityProved(*bind.FilterOpts, []*big.Int) (*verifiers.SBTIdentityVerifierSBTIdentityProvedIterator, error) } type extConfig interface { @@ -251,16 +251,19 @@ func (r *runner) fulfillPohEvent(poh data.Event) error { } func (r *runner) createBalance(did string) error { - if err := r.balancesQ().Insert(did); err != nil { - return fmt.Errorf("insert balance: %w", err) - } + return r.eventsQ().Transaction(func() error { - err := r.eventsQ().Insert(r.types.PrepareOpenEvents(did)...) - if err != nil { - return fmt.Errorf("insert open events: %w", err) - } + if err := r.balancesQ().Insert(did); err != nil { + return fmt.Errorf("insert balance: %w", err) + } - return nil + err := r.eventsQ().Insert(r.types.PrepareOpenEvents(did)...) + if err != nil { + return fmt.Errorf("insert open events: %w", err) + } + + return nil + }) } func parseDidFromUint256(raw *big.Int) (string, error) { diff --git a/internal/service/handlers/claim_event.go b/internal/service/handlers/claim_event.go index f188c75..d1487dc 100644 --- a/internal/service/handlers/claim_event.go +++ b/internal/service/handlers/claim_event.go @@ -1,6 +1,7 @@ package handlers import ( + "fmt" "net/http" "github.com/rarimo/rarime-points-svc/internal/data" @@ -63,23 +64,28 @@ func getEventToClaim(id string, w http.ResponseWriter, r *http.Request) *data.Ev return event } -func claimEventWithPoints(event data.Event, reward int32, w http.ResponseWriter, r *http.Request) *data.Event { +func claimEventWithPoints(event data.Event, reward int32, w http.ResponseWriter, r *http.Request) (claimed *data.Event) { + err := EventsQ(r).Transaction(func() error { + updated, err := EventsQ(r).FilterByID(event.ID).Update(data.EventClaimed, nil, &reward) + if err != nil { + return fmt.Errorf("update event status: %w", err) + } - claimed, err := EventsQ(r).FilterByID(event.ID).Update(data.EventClaimed, nil, &reward) - if err != nil { - Log(r).WithError(err).Error("Failed to claim event") - ape.RenderErr(w, problems.InternalError()) + err = BalancesQ(r).FilterByDID(event.UserDID).UpdateAmountBy(reward) + if err != nil { + return fmt.Errorf("update balance amount: %w", err) + } + + claimed = updated return nil - } + }) - err = BalancesQ(r).FilterByDID(event.UserDID).UpdateAmountBy(reward) if err != nil { - Log(r).WithError(err).Error("Failed to accrue points to the balance") + Log(r).WithError(err).Error("Failed to claim event and accrue points to the balance") ape.RenderErr(w, problems.InternalError()) - return nil } - return claimed + return } func newClaimEventResponse( diff --git a/internal/service/handlers/create_balance.go b/internal/service/handlers/create_balance.go index 9e7138c..6709887 100644 --- a/internal/service/handlers/create_balance.go +++ b/internal/service/handlers/create_balance.go @@ -1,6 +1,7 @@ package handlers import ( + "fmt" "net/http" "github.com/rarimo/rarime-points-svc/internal/service/requests" @@ -22,11 +23,17 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { return } - if err = BalancesQ(r).Insert(did); err != nil { - Log(r).WithError(err).Error("Failed to create balance") - ape.RenderErr(w, problems.InternalError()) - return - } + err = EventsQ(r).Transaction(func() error { + if err = BalancesQ(r).Insert(did); err != nil { + return fmt.Errorf("add balance: %w", err) + } + err = EventsQ(r).Insert(EventTypes(r).PrepareOpenEvents(balance.DID)...) + if err != nil { + return fmt.Errorf("add open events: %w", err) + } + return nil + }) + // We can't return inserted balance in a single query, because we can't calculate // rank in transaction: RANK() is a window function allowed on a set of rows, // while with RETURNING we operate a single one. @@ -34,13 +41,5 @@ func CreateBalance(w http.ResponseWriter, r *http.Request) { if balance == nil { return } - - err = EventsQ(r).Insert(EventTypes(r).PrepareOpenEvents(balance.DID)...) - if err != nil { - Log(r).WithError(err).Error("Failed to add open events") - ape.RenderErr(w, problems.InternalError()) - return - } - ape.Render(w, newBalanceModel(*balance)) } diff --git a/internal/service/handlers/withdraw.go b/internal/service/handlers/withdraw.go index 3e9ca55..b2828ef 100644 --- a/internal/service/handlers/withdraw.go +++ b/internal/service/handlers/withdraw.go @@ -24,14 +24,19 @@ func Withdraw(w http.ResponseWriter, r *http.Request) { return } - err = BalancesQ(r).FilterByDID(req.Data.ID).UpdateAmountBy(-req.Data.Attributes.Amount) - if err != nil { - Log(r).WithError(err).Error("Failed to update balance") - ape.RenderErr(w, problems.InternalError()) - return - } + err = EventsQ(r).Transaction(func() error { + err = BalancesQ(r).FilterByDID(req.Data.ID).UpdateAmountBy(-req.Data.Attributes.Amount) + if err != nil { + return fmt.Errorf("decrease points amount: %w", err) + } + if err = broadcastWithdrawalTx(req, r); err != nil { + return fmt.Errorf("broadcast transfer tx: %w", err) + } + return nil + }) - if !broadcastWithdrawalTx(req, r) { + if err != nil { + Log(r).WithError(err).Error("Failed to decrease balance and broadcast tx") ape.RenderErr(w, problems.InternalError()) return } @@ -61,7 +66,7 @@ func isEnoughPoints(req resources.WithdrawRequest, w http.ResponseWriter, r *htt return true } -func broadcastWithdrawalTx(req resources.WithdrawRequest, r *http.Request) bool { +func broadcastWithdrawalTx(req resources.WithdrawRequest, r *http.Request) error { var ( from = cosmos.MustAccAddressFromBech32(Broadcaster(r).Sender()) to = cosmos.MustAccAddressFromBech32(req.Data.Attributes.Address) @@ -71,9 +76,8 @@ func broadcastWithdrawalTx(req resources.WithdrawRequest, r *http.Request) bool err := Broadcaster(r).BroadcastTx(r.Context(), bank.NewMsgSend(from, to, coins)) if err != nil { - Log(r).WithError(err).Error("Failed to broadcast transaction") - return false + return fmt.Errorf("broadcast withdrawal tx: %w", err) } - return true + return nil } From 265e3b4026dc5bd91271ad678319474abe745b12 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 5 Feb 2024 14:50:49 +0200 Subject: [PATCH 60/63] =?UTF-8?q?Add=20basic=20cron=E2=8F=B3=20job=20to=20?= =?UTF-8?q?reopen=20claimed=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 3 + go.sum | 8 ++ internal/cli/main.go | 2 +- internal/config/main.go | 2 +- internal/data/evtypes/main.go | 16 ++++ internal/data/main.go | 1 + internal/data/pg/events.go | 27 +++++- internal/service/workers/reopener/log.go | 30 ++++++ internal/service/workers/reopener/main.go | 96 +++++++++++++++++++ .../{ => service/workers}/sbtcheck/config.go | 2 +- .../{ => service/workers}/sbtcheck/main.go | 2 +- .../sbtcheck/verifiers/SBTIdentityVerifier.go | 0 12 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 internal/service/workers/reopener/log.go create mode 100644 internal/service/workers/reopener/main.go rename internal/{ => service/workers}/sbtcheck/config.go (96%) rename internal/{ => service/workers}/sbtcheck/main.go (98%) rename internal/{ => service/workers}/sbtcheck/verifiers/SBTIdentityVerifier.go (100%) diff --git a/go.mod b/go.mod index cf9f0df..265b4fa 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/cosmos/cosmos-sdk v0.46.12 github.com/ethereum/go-ethereum v1.13.11 github.com/go-chi/chi v4.1.2+incompatible + github.com/go-co-op/gocron/v2 v2.2.2 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/iden3/go-iden3-core/v2 v2.0.4 github.com/rarimo/rarime-auth-svc v0.0.1-rc9 @@ -93,6 +94,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/jmoiron/sqlx v1.2.0 // indirect + github.com/jonboulle/clockwork v0.4.0 // indirect github.com/klauspost/compress v1.17.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -117,6 +119,7 @@ require ( github.com/prometheus/procfs v0.9.0 // indirect github.com/rarimo/broadcaster-svc v1.0.2 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect diff --git a/go.sum b/go.sum index 231ecc1..4089299 100644 --- a/go.sum +++ b/go.sum @@ -768,6 +768,8 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-co-op/gocron/v2 v2.2.2 h1:XgQIiocDrdSX/B2AICR0FWk4ZeyJzeK5LVmLRoou3F0= +github.com/go-co-op/gocron/v2 v2.2.2/go.mod h1:igssOwzZkfcnu3m2kwnCf/mYj4SmhP9ecSgmYjCOHkk= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= @@ -1027,6 +1029,8 @@ github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -1229,6 +1233,8 @@ github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -1398,6 +1404,8 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= diff --git a/internal/cli/main.go b/internal/cli/main.go index 19a5f3d..bc62783 100644 --- a/internal/cli/main.go +++ b/internal/cli/main.go @@ -5,8 +5,8 @@ import ( "github.com/alecthomas/kingpin" "github.com/rarimo/rarime-points-svc/internal/config" - "github.com/rarimo/rarime-points-svc/internal/sbtcheck" "github.com/rarimo/rarime-points-svc/internal/service" + "github.com/rarimo/rarime-points-svc/internal/service/workers/sbtcheck" "gitlab.com/distributed_lab/kit/kv" "gitlab.com/distributed_lab/logan/v3" ) diff --git a/internal/config/main.go b/internal/config/main.go index 2e00fbd..f2384af 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -3,7 +3,7 @@ package config import ( "github.com/rarimo/rarime-auth-svc/pkg/auth" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" - "github.com/rarimo/rarime-points-svc/internal/sbtcheck" + "github.com/rarimo/rarime-points-svc/internal/service/workers/sbtcheck" "github.com/rarimo/saver-grpc-lib/broadcaster" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/copus" diff --git a/internal/data/evtypes/main.go b/internal/data/evtypes/main.go index fd29844..8a42c8a 100644 --- a/internal/data/evtypes/main.go +++ b/internal/data/evtypes/main.go @@ -77,6 +77,22 @@ func (t Types) List() []resources.EventStaticMeta { return res } +func (t Types) NamesByFrequency(f Frequency) []string { + if t.inner == nil { + panic("event types are not correctly initialized") + } + + res := make([]string, 0, len(t.inner)) + for _, v := range t.inner { + if v.Frequency != f.String() || isExpiredEvent(v) { + continue + } + res = append(res, v.Name) + } + + return res +} + func (t Types) IsExpired(name string) bool { evType := t.Get(name) if evType == nil { diff --git a/internal/data/main.go b/internal/data/main.go index a2cb240..8d65bca 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -23,6 +23,7 @@ type EventsQ interface { New() EventsQ Insert(...Event) error Update(status EventStatus, meta json.RawMessage, points *int32) (*Event, error) + Reopen() (count uint, err error) Transaction(func() error) error Page(*pgdb.CursorPageParams) EventsQ diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 7871c76..188de25 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -59,12 +59,12 @@ func (q *events) Update(status data.EventStatus, meta json.RawMessage, points *i umap := map[string]any{ "status": status, } - if points != nil { - umap["points_amount"] = sql.NullInt32{Int32: *points, Valid: true} - } if len(meta) != 0 { umap["meta"] = meta } + if points != nil { + umap["points_amount"] = sql.NullInt32{Int32: *points, Valid: true} + } var res data.Event stmt := q.updater.SetMap(umap).Suffix("RETURNING *") @@ -76,6 +76,27 @@ func (q *events) Update(status data.EventStatus, meta json.RawMessage, points *i return &res, nil } +func (q *events) Reopen() (count uint, err error) { + stmt := q.updater.SetMap(map[string]any{"status": data.EventOpen}) + defer func() { + if errors.Is(err, sql.ErrNoRows) { + err = nil + } + }() + + res, err := q.db.ExecWithResult(stmt) + if err != nil { + return 0, fmt.Errorf("update status to open with result: %w", err) + } + + rows, err := res.RowsAffected() + if err != nil { + return 0, fmt.Errorf("get rows affected: %w", err) + } + + return uint(rows), nil +} + func (q *events) Page(page *pgdb.CursorPageParams) data.EventsQ { q.selector = page.ApplyTo(q.selector, "updated_at") return q diff --git a/internal/service/workers/reopener/log.go b/internal/service/workers/reopener/log.go new file mode 100644 index 0000000..6bfd4bf --- /dev/null +++ b/internal/service/workers/reopener/log.go @@ -0,0 +1,30 @@ +package reopener + +import ( + "reflect" + + "github.com/go-co-op/gocron/v2" + "github.com/sirupsen/logrus" + "gitlab.com/distributed_lab/logan/v3" +) + +// Reflect was better option than re-implementing methods, because gocron library +// is adjusted to its own logger, despite supporting custom ones. +func getLogLevel(log *logan.Entry) gocron.LogLevel { + var ( + val = reflect.ValueOf(log).Elem() + entry = val.FieldByName("entry") + level = entry.FieldByName("Level").Interface().(logrus.Level) + ) + + switch level { + case logrus.DebugLevel: + return gocron.LogLevelDebug + case logrus.InfoLevel: + return gocron.LogLevelInfo + case logrus.WarnLevel: + return gocron.LogLevelWarn + default: + return gocron.LogLevelError + } +} diff --git a/internal/service/workers/reopener/main.go b/internal/service/workers/reopener/main.go new file mode 100644 index 0000000..eaa6ce6 --- /dev/null +++ b/internal/service/workers/reopener/main.go @@ -0,0 +1,96 @@ +package reopener + +import ( + "context" + "fmt" + "time" + + "github.com/go-co-op/gocron/v2" + "github.com/rarimo/rarime-points-svc/internal/config" + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/data/evtypes" + "github.com/rarimo/rarime-points-svc/internal/data/pg" + "gitlab.com/distributed_lab/logan/v3" + "gitlab.com/distributed_lab/running" +) + +type worker struct { + name string + freq evtypes.Frequency + types evtypes.Types + q data.EventsQ + log *logan.Entry +} + +func Run(ctx context.Context, cfg config.Config) error { + scheduler, err := gocron.NewScheduler( + gocron.WithLocation(time.UTC), + gocron.WithLogger(gocron.NewLogger(getLogLevel(cfg.Log()))), + ) + if err != nil { + return fmt.Errorf("initialize scheduler: %w", err) + } + + var ( + atUTC = gocron.NewAtTimes(gocron.NewAtTime(0, 0, 0)) + daily = newWorker(cfg, evtypes.Daily) + weekly = newWorker(cfg, evtypes.Weekly) + ) + _, err = scheduler.NewJob( + gocron.DailyJob(1, atUTC), + gocron.NewTask(daily.job, ctx), + ) + if err != nil { + return fmt.Errorf("initialize daily job: %w", err) + } + _, err = scheduler.NewJob( + gocron.WeeklyJob(1, gocron.NewWeekdays(time.Monday), atUTC), + gocron.NewTask(weekly.job, ctx), + ) + if err != nil { + return fmt.Errorf("initialize weekly job: %w", err) + } + + scheduler.Start() + go func() { + <-ctx.Done() + if err = scheduler.Shutdown(); err != nil { + cfg.Log().WithError(err).Error("Scheduler shutdown failed") + } + }() + + return nil +} + +func newWorker(cfg config.Config, freq evtypes.Frequency) *worker { + name := fmt.Sprintf("reopener[%s]", freq.String()) + return &worker{ + name: name, + freq: freq, + types: cfg.EventTypes(), + q: pg.NewEvents(cfg.DB().Clone()), + log: cfg.Log().WithField("who", name), + } +} + +func (w *worker) job(ctx context.Context) { + types := w.types.NamesByFrequency(w.freq) // types might expire, that's why we get them right here + if len(types) == 0 { + w.log.Info("No events to reopen: all types expired or no types with frequency exist") + return + } + + running.WithThreshold(ctx, w.log, w.name, func(context.Context) (bool, error) { + count, err := w.q.New(). + FilterByType(types...). + FilterByStatus(data.EventClaimed). + Reopen() + + if err != nil { + return false, fmt.Errorf("reopen events: %w", err) + } + + w.log.Infof("Reopened %d events", count) + return true, nil + }, 5*time.Minute, 5*time.Minute, 12) +} diff --git a/internal/sbtcheck/config.go b/internal/service/workers/sbtcheck/config.go similarity index 96% rename from internal/sbtcheck/config.go rename to internal/service/workers/sbtcheck/config.go index 4e57ba1..1536420 100644 --- a/internal/sbtcheck/config.go +++ b/internal/service/workers/sbtcheck/config.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/rarimo/rarime-points-svc/internal/sbtcheck/verifiers" + "github.com/rarimo/rarime-points-svc/internal/service/workers/sbtcheck/verifiers" "gitlab.com/distributed_lab/figure/v3" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/kv" diff --git a/internal/sbtcheck/main.go b/internal/service/workers/sbtcheck/main.go similarity index 98% rename from internal/sbtcheck/main.go rename to internal/service/workers/sbtcheck/main.go index 7abf5bb..5926e98 100644 --- a/internal/sbtcheck/main.go +++ b/internal/service/workers/sbtcheck/main.go @@ -12,7 +12,7 @@ import ( "github.com/rarimo/rarime-points-svc/internal/data" "github.com/rarimo/rarime-points-svc/internal/data/evtypes" "github.com/rarimo/rarime-points-svc/internal/data/pg" - "github.com/rarimo/rarime-points-svc/internal/sbtcheck/verifiers" + "github.com/rarimo/rarime-points-svc/internal/service/workers/sbtcheck/verifiers" "gitlab.com/distributed_lab/kit/comfig" "gitlab.com/distributed_lab/kit/pgdb" "gitlab.com/distributed_lab/logan/v3" diff --git a/internal/sbtcheck/verifiers/SBTIdentityVerifier.go b/internal/service/workers/sbtcheck/verifiers/SBTIdentityVerifier.go similarity index 100% rename from internal/sbtcheck/verifiers/SBTIdentityVerifier.go rename to internal/service/workers/sbtcheck/verifiers/SBTIdentityVerifier.go From 20b3a777d7ee318c177c60ad77a733584b425626 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 5 Feb 2024 16:54:36 +0200 Subject: [PATCH 61/63] Fix reopener logger, fix and improve background running in cli package --- internal/cli/main.go | 71 ++++++++++++++++------- internal/service/main.go | 31 +++++----- internal/service/workers/reopener/log.go | 49 ++++++++-------- internal/service/workers/reopener/main.go | 24 ++++---- internal/service/workers/sbtcheck/main.go | 5 +- 5 files changed, 104 insertions(+), 76 deletions(-) diff --git a/internal/cli/main.go b/internal/cli/main.go index bc62783..c776c23 100644 --- a/internal/cli/main.go +++ b/internal/cli/main.go @@ -2,35 +2,37 @@ package cli import ( "context" + "os" + "os/signal" + "sync" + "syscall" "github.com/alecthomas/kingpin" "github.com/rarimo/rarime-points-svc/internal/config" "github.com/rarimo/rarime-points-svc/internal/service" + "github.com/rarimo/rarime-points-svc/internal/service/workers/reopener" "github.com/rarimo/rarime-points-svc/internal/service/workers/sbtcheck" "gitlab.com/distributed_lab/kit/kv" "gitlab.com/distributed_lab/logan/v3" ) func Run(args []string) bool { - log := logan.New() - defer func() { if rvr := recover(); rvr != nil { - log.WithRecover(rvr).Error("app panicked") + logan.New().WithRecover(rvr).Error("app panicked") } }() - cfg := config.New(kv.MustFromEnv()) - log = cfg.Log() - - app := kingpin.New("rarime-points-svc", "") - - runCmd := app.Command("run", "run command") - serviceCmd := runCmd.Command("service", "run service") - - migrateCmd := app.Command("migrate", "migrate command") - migrateUpCmd := migrateCmd.Command("up", "migrate db up") - migrateDownCmd := migrateCmd.Command("down", "migrate db down") + var ( + cfg = config.New(kv.MustFromEnv()) + log = cfg.Log() + app = kingpin.New("rarime-points-svc", "") + runCmd = app.Command("run", "run command") + serviceCmd = runCmd.Command("service", "run service") + migrateCmd = app.Command("migrate", "migrate command") + migrateUpCmd = migrateCmd.Command("up", "migrate db up") + migrateDownCmd = migrateCmd.Command("down", "migrate db down") + ) cmd, err := app.Parse(args[1:]) if err != nil { @@ -38,15 +40,23 @@ func Run(args []string) bool { return false } + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() + + var wg sync.WaitGroup + run := func(f func(context.Context, config.Config)) { + wg.Add(1) + go func() { + f(ctx, cfg) + wg.Done() + }() + } + switch cmd { case serviceCmd.FullCommand(): - err = sbtcheck.Run(context.Background(), cfg) - if err != nil { - log.WithError(err).Error("Failed to run sbt checker") - return false - } - service.Run(cfg) - + run(func(context.Context, config.Config) { sbtcheck.Run(ctx, cfg) }) + run(reopener.Run) + run(service.Run) case migrateUpCmd.FullCommand(): err = MigrateUp(cfg) case migrateDownCmd.FullCommand(): @@ -59,5 +69,24 @@ func Run(args []string) bool { log.WithError(err).Error("failed to exec cmd") return false } + + gracefulStop := make(chan os.Signal, 1) + signal.Notify(gracefulStop, syscall.SIGTERM, syscall.SIGINT) + + wgch := make(chan struct{}) + go func() { + wg.Wait() + close(wgch) + }() + + select { + case <-ctx.Done(): + cfg.Log().WithError(ctx.Err()).Info("Interrupt signal received") + stop() + <-wgch + case <-wgch: + cfg.Log().Warn("all services stopped") + } + return true } diff --git a/internal/service/main.go b/internal/service/main.go index aed0a15..d3fc6fa 100644 --- a/internal/service/main.go +++ b/internal/service/main.go @@ -1,44 +1,43 @@ package service import ( - "net" - "net/http" + "context" + "fmt" "github.com/rarimo/rarime-points-svc/internal/config" + "gitlab.com/distributed_lab/ape" "gitlab.com/distributed_lab/kit/copus/types" "gitlab.com/distributed_lab/logan/v3" - "gitlab.com/distributed_lab/logan/v3/errors" ) type service struct { - log *logan.Entry - copus types.Copus - listener net.Listener - cfg config.Config + log *logan.Entry + copus types.Copus + cfg config.Config } -func (s *service) run() error { +func (s *service) run(ctx context.Context) error { s.log.Info("Service started") r := s.router() if err := s.copus.RegisterChi(r); err != nil { - return errors.Wrap(err, "cop failed") + return fmt.Errorf("cop failed: %w", err) } - return http.Serve(s.listener, r) + ape.Serve(ctx, r, s.cfg, ape.ServeOpts{}) + return nil } func newService(cfg config.Config) *service { return &service{ - log: cfg.Log(), - copus: cfg.Copus(), - listener: cfg.Listener(), - cfg: cfg, + log: cfg.Log(), + copus: cfg.Copus(), + cfg: cfg, } } -func Run(cfg config.Config) { - if err := newService(cfg).run(); err != nil { +func Run(ctx context.Context, cfg config.Config) { + if err := newService(cfg).run(ctx); err != nil { panic(err) } } diff --git a/internal/service/workers/reopener/log.go b/internal/service/workers/reopener/log.go index 6bfd4bf..30e2c50 100644 --- a/internal/service/workers/reopener/log.go +++ b/internal/service/workers/reopener/log.go @@ -1,30 +1,33 @@ package reopener import ( - "reflect" - - "github.com/go-co-op/gocron/v2" - "github.com/sirupsen/logrus" "gitlab.com/distributed_lab/logan/v3" ) -// Reflect was better option than re-implementing methods, because gocron library -// is adjusted to its own logger, despite supporting custom ones. -func getLogLevel(log *logan.Entry) gocron.LogLevel { - var ( - val = reflect.ValueOf(log).Elem() - entry = val.FieldByName("entry") - level = entry.FieldByName("Level").Interface().(logrus.Level) - ) - - switch level { - case logrus.DebugLevel: - return gocron.LogLevelDebug - case logrus.InfoLevel: - return gocron.LogLevelInfo - case logrus.WarnLevel: - return gocron.LogLevelWarn - default: - return gocron.LogLevelError - } +type logger struct { + in *logan.Entry +} + +func newLogger(in *logan.Entry) *logger { + return &logger{in: in.WithField("who", "gocron-scheduler")} +} + +func (l *logger) Debug(msg string, args ...any) { + l.in.Debug(l.toLoganArgs(msg, args)...) +} + +func (l *logger) Info(msg string, args ...any) { + l.in.Info(l.toLoganArgs(msg, args)...) +} + +func (l *logger) Warn(msg string, args ...any) { + l.in.Warn(l.toLoganArgs(msg, args)...) +} + +func (l *logger) Error(msg string, args ...any) { + l.in.Error(l.toLoganArgs(msg, args)...) +} + +func (l *logger) toLoganArgs(msg string, args []any) []any { + return append([]any{msg}, args...) } diff --git a/internal/service/workers/reopener/main.go b/internal/service/workers/reopener/main.go index eaa6ce6..aa0d490 100644 --- a/internal/service/workers/reopener/main.go +++ b/internal/service/workers/reopener/main.go @@ -22,13 +22,13 @@ type worker struct { log *logan.Entry } -func Run(ctx context.Context, cfg config.Config) error { +func Run(ctx context.Context, cfg config.Config) { scheduler, err := gocron.NewScheduler( gocron.WithLocation(time.UTC), - gocron.WithLogger(gocron.NewLogger(getLogLevel(cfg.Log()))), + gocron.WithLogger(newLogger(cfg.Log())), ) if err != nil { - return fmt.Errorf("initialize scheduler: %w", err) + panic(fmt.Errorf("failed to initialize scheduler: %w", err)) } var ( @@ -41,25 +41,23 @@ func Run(ctx context.Context, cfg config.Config) error { gocron.NewTask(daily.job, ctx), ) if err != nil { - return fmt.Errorf("initialize daily job: %w", err) + panic(fmt.Errorf("failed to initialize daily job: %w", err)) } _, err = scheduler.NewJob( gocron.WeeklyJob(1, gocron.NewWeekdays(time.Monday), atUTC), gocron.NewTask(weekly.job, ctx), ) if err != nil { - return fmt.Errorf("initialize weekly job: %w", err) + panic(fmt.Errorf("failed to initialize weekly job: %w", err)) } scheduler.Start() - go func() { - <-ctx.Done() - if err = scheduler.Shutdown(); err != nil { - cfg.Log().WithError(err).Error("Scheduler shutdown failed") - } - }() - - return nil + <-ctx.Done() + if err = scheduler.Shutdown(); err != nil { + cfg.Log().WithError(err).Error("Scheduler shutdown failed") + return + } + cfg.Log().Info("Scheduler shutdown succeeded") } func newWorker(cfg config.Config, freq evtypes.Frequency) *worker { diff --git a/internal/service/workers/sbtcheck/main.go b/internal/service/workers/sbtcheck/main.go index 5926e98..af24b0f 100644 --- a/internal/service/workers/sbtcheck/main.go +++ b/internal/service/workers/sbtcheck/main.go @@ -52,11 +52,11 @@ type extConfig interface { SbtChecker } -func Run(ctx context.Context, cfg extConfig) error { +func Run(ctx context.Context, cfg extConfig) { log := cfg.Log().WithField("who", "sbt-checker") if cfg.EventTypes().IsExpired(evtypes.TypeGetPoH) { log.Warn("PoH event is expired, SBT check will not run") - return nil + return } var wg sync.WaitGroup @@ -86,7 +86,6 @@ func Run(ctx context.Context, cfg extConfig) error { wg.Wait() log.Infof("SBT check: all network checkers stopped") - return nil } func (r *runner) subscription(ctx context.Context) error { From e57d65fec430eb33500c5d3c815b4dbee684a5d9 Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Mon, 5 Feb 2024 18:56:44 +0200 Subject: [PATCH 62/63] Add initial run of reopener before scheduling job to perform update after downtime --- internal/data/main.go | 1 + internal/data/pg/events.go | 6 ++- internal/service/workers/reopener/init.go | 50 +++++++++++++++++++++++ internal/service/workers/reopener/main.go | 25 ++++++++---- 4 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 internal/service/workers/reopener/init.go diff --git a/internal/data/main.go b/internal/data/main.go index 8d65bca..7854b79 100644 --- a/internal/data/main.go +++ b/internal/data/main.go @@ -35,6 +35,7 @@ type EventsQ interface { FilterByUserDID(string) EventsQ FilterByStatus(...EventStatus) EventsQ FilterByType(...string) EventsQ + FilterByUpdatedAtBefore(int64) EventsQ } type BalancesQ interface { diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 188de25..c67d1a7 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -163,7 +163,11 @@ func (q *events) FilterByType(types ...string) data.EventsQ { return q.applyCondition(squirrel.Eq{"type": types}) } -func (q *events) applyCondition(cond squirrel.Eq) data.EventsQ { +func (q *events) FilterByUpdatedAtBefore(unix int64) data.EventsQ { + return q.applyCondition(squirrel.Lt{"updated_at": unix}) +} + +func (q *events) applyCondition(cond squirrel.Sqlizer) data.EventsQ { q.selector = q.selector.Where(cond) q.updater = q.updater.Where(cond) q.counter = q.counter.Where(cond) diff --git a/internal/service/workers/reopener/init.go b/internal/service/workers/reopener/init.go new file mode 100644 index 0000000..1e0dc24 --- /dev/null +++ b/internal/service/workers/reopener/init.go @@ -0,0 +1,50 @@ +package reopener + +import ( + "fmt" + "time" + + "github.com/rarimo/rarime-points-svc/internal/data" + "github.com/rarimo/rarime-points-svc/internal/data/evtypes" +) + +func (w *worker) initialRun() error { + types := w.types.NamesByFrequency(w.freq) + if len(types) == 0 { + w.log.Info("No events to reopen: all types expired or no types with frequency exist") + return nil + } + + filter := w.beforeTimeFilter() + w.log.WithField("event_types", types). + Debugf("Reopening claimed events before %s", time.Unix(filter, 0).UTC()) + + count, err := w.q.New(). + FilterByType(types...). + FilterByStatus(data.EventClaimed). + FilterByUpdatedAtBefore(filter). + Reopen() + + if err != nil { + return fmt.Errorf("reopen events: %w", err) + } + + w.log.Infof("Reopened %d events on initial run", count) + return nil +} + +func (w *worker) beforeTimeFilter() int64 { + now := time.Now().UTC() + midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + + switch w.freq { + case evtypes.Daily: + return midnight.Unix() + case evtypes.Weekly: + // current_day + (monday - current_day) = monday + offset := int(time.Monday - now.Weekday()) + return midnight.AddDate(0, 0, offset).Unix() + default: + panic(fmt.Errorf("unexpected frequency: %s", w.freq)) + } +} diff --git a/internal/service/workers/reopener/main.go b/internal/service/workers/reopener/main.go index aa0d490..82afd36 100644 --- a/internal/service/workers/reopener/main.go +++ b/internal/service/workers/reopener/main.go @@ -14,6 +14,8 @@ import ( "gitlab.com/distributed_lab/running" ) +const retryPeriod = 5 * time.Minute + type worker struct { name string freq evtypes.Frequency @@ -23,6 +25,18 @@ type worker struct { } func Run(ctx context.Context, cfg config.Config) { + var ( + atUTC = gocron.NewAtTimes(gocron.NewAtTime(0, 0, 0)) + daily = newWorker(cfg, evtypes.Daily) + weekly = newWorker(cfg, evtypes.Weekly) + ) + if err := daily.initialRun(); err != nil { + panic(fmt.Errorf("failed to do initial run for daily events: %w", err)) + } + if err := weekly.initialRun(); err != nil { + panic(fmt.Errorf("failed to do initial run for weekly events: %w", err)) + } + scheduler, err := gocron.NewScheduler( gocron.WithLocation(time.UTC), gocron.WithLogger(newLogger(cfg.Log())), @@ -31,11 +45,6 @@ func Run(ctx context.Context, cfg config.Config) { panic(fmt.Errorf("failed to initialize scheduler: %w", err)) } - var ( - atUTC = gocron.NewAtTimes(gocron.NewAtTime(0, 0, 0)) - daily = newWorker(cfg, evtypes.Daily) - weekly = newWorker(cfg, evtypes.Weekly) - ) _, err = scheduler.NewJob( gocron.DailyJob(1, atUTC), gocron.NewTask(daily.job, ctx), @@ -72,11 +81,13 @@ func newWorker(cfg config.Config, freq evtypes.Frequency) *worker { } func (w *worker) job(ctx context.Context) { - types := w.types.NamesByFrequency(w.freq) // types might expire, that's why we get them right here + // types might expire, so it's required to get them before each run + types := w.types.NamesByFrequency(w.freq) if len(types) == 0 { w.log.Info("No events to reopen: all types expired or no types with frequency exist") return } + w.log.WithField("event_types", types).Debug("Reopening claimed events") running.WithThreshold(ctx, w.log, w.name, func(context.Context) (bool, error) { count, err := w.q.New(). @@ -90,5 +101,5 @@ func (w *worker) job(ctx context.Context) { w.log.Infof("Reopened %d events", count) return true, nil - }, 5*time.Minute, 5*time.Minute, 12) + }, retryPeriod, retryPeriod, 12) } From fc8668ee8247423daea0b4d47caeccc7d6b57d4a Mon Sep 17 00:00:00 2001 From: violog <51th.apprent1ce.f0rce@gmail.com> Date: Tue, 6 Feb 2024 12:14:38 +0200 Subject: [PATCH 63/63] Withdrawal history docs and models --- docs/spec/components/schemas/WithdrawKey.yaml | 4 - docs/spec/components/schemas/Withdrawal.yaml | 25 +++++++ .../components/schemas/WithdrawalKey.yaml | 11 +++ ...rations@rarime-points-svc@v1@balances.yaml | 2 +- ...s@rarime-points-svc@v1@balances@{did}.yaml | 38 ---------- ...nts-svc@v1@balances@{did}@withdrawals.yaml | 74 +++++++++++++++++++ resources/model_resource_type.go | 1 + resources/model_withdrawal.go | 43 +++++++++++ resources/model_withdrawal_attributes.go | 14 ++++ 9 files changed, 169 insertions(+), 43 deletions(-) create mode 100644 docs/spec/components/schemas/Withdrawal.yaml create mode 100644 docs/spec/components/schemas/WithdrawalKey.yaml create mode 100644 docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}@withdrawals.yaml create mode 100644 resources/model_withdrawal.go create mode 100644 resources/model_withdrawal_attributes.go diff --git a/docs/spec/components/schemas/WithdrawKey.yaml b/docs/spec/components/schemas/WithdrawKey.yaml index 751eeb8..026f033 100644 --- a/docs/spec/components/schemas/WithdrawKey.yaml +++ b/docs/spec/components/schemas/WithdrawKey.yaml @@ -3,10 +3,6 @@ required: - id - type properties: - id: - type: string - description: DID of the points owner - example: "did:iden3:readonly:tUDjWxnVJNi7t3FudukqrUcNwF5KVGoWgim5pp2jV" type: type: string enum: [ withdraw ] diff --git a/docs/spec/components/schemas/Withdrawal.yaml b/docs/spec/components/schemas/Withdrawal.yaml new file mode 100644 index 0000000..9079c08 --- /dev/null +++ b/docs/spec/components/schemas/Withdrawal.yaml @@ -0,0 +1,25 @@ +allOf: + - $ref: '#/components/schemas/WithdrawalKey' + - type: object + required: + - attributes + properties: + attributes: + type: object + required: + - amount + - address + - created_at + properties: + amount: + type: integer + description: Amount of points withdrawn + example: 580 + address: + type: string + description: Rarimo address which points were withdrawn to. Can be any valid address. + example: rarimo15hcd6tv7pe8hk2re7hu0zg0aphqdm2dtjrs0ds + created_at: + type: integer + description: Unix timestamp of withdrawal creation + example: 1706531218 diff --git a/docs/spec/components/schemas/WithdrawalKey.yaml b/docs/spec/components/schemas/WithdrawalKey.yaml new file mode 100644 index 0000000..f1f2dac --- /dev/null +++ b/docs/spec/components/schemas/WithdrawalKey.yaml @@ -0,0 +1,11 @@ +type: object +required: + - id + - type +properties: + id: + type: string + example: "059c81dd-2a54-44a8-8142-c15ad8f88949" + type: + type: string + enum: [ withdrawal ] diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml index 9f3345b..3cacf85 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@balances.yaml @@ -47,9 +47,9 @@ get: description: Returns leaders sorted by points in descending order. operationId: getLeaderboard parameters: - - $ref: '#/components/parameters/pageCursor' - $ref: '#/components/parameters/pageLimit' - $ref: '#/components/parameters/pageNumber' + - $ref: '#/components/parameters/pageOrder' responses: 200: description: Success diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml index 15b99b5..8b5eeae 100644 --- a/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}.yaml @@ -26,41 +26,3 @@ get: $ref: '#/components/responses/invalidAuth' 500: $ref: '#/components/responses/internalError' - -patch: - tags: - - Points balance - summary: Withdraw points to RMO - description: Convert points to RMO by exchange rate and withdraw to user wallet - operationId: withdrawPoints - parameters: - - $ref: '#/components/parameters/pathDID' - requestBody: - required: true - content: - application/vnd.api+json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Withdraw' - responses: - 200: - description: Success - content: - application/vnd.api+json: - schema: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/Balance' - 400: - $ref: '#/components/responses/invalidParameter' - 401: - $ref: '#/components/responses/invalidAuth' - 500: - $ref: '#/components/responses/internalError' diff --git a/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}@withdrawals.yaml b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}@withdrawals.yaml new file mode 100644 index 0000000..5d1b27d --- /dev/null +++ b/docs/spec/paths/integrations@rarime-points-svc@v1@balances@{did}@withdrawals.yaml @@ -0,0 +1,74 @@ +get: + tags: + - Points balance + summary: Withdrawal history + description: Points withdrawal history of the user + operationId: getWithdrawalHistory + parameters: + - $ref: '#/components/parameters/pathDID' + - $ref: '#/components/parameters/pageCursor' + - $ref: '#/components/parameters/pageLimit' + - $ref: '#/components/parameters/pageOrder' + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/Withdrawal' + 400: + $ref: '#/components/responses/invalidParameter' + 401: + $ref: '#/components/responses/invalidAuth' + 500: + $ref: '#/components/responses/internalError' + +post: + tags: + - Points balance + summary: Withdraw points + description: Convert points to RMO by exchange rate and withdraw to user wallet + operationId: withdrawPoints + parameters: + - $ref: '#/components/parameters/pathDID' + requestBody: + required: true + content: + application/vnd.api+json: + schema: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/Withdraw' + responses: + 200: + description: Success + content: + application/vnd.api+json: + schema: + type: object + required: + - data + - included + properties: + data: + $ref: '#/components/schemas/Withdrawal' + included: + type: array + items: + $ref: '#/components/schemas/Balance' + 400: + $ref: '#/components/responses/invalidParameter' + 401: + $ref: '#/components/responses/invalidAuth' + 500: + $ref: '#/components/responses/internalError' diff --git a/resources/model_resource_type.go b/resources/model_resource_type.go index 0571d68..fc73c4a 100644 --- a/resources/model_resource_type.go +++ b/resources/model_resource_type.go @@ -13,4 +13,5 @@ const ( CREATE_BALANCE ResourceType = "create_balance" EVENT ResourceType = "event" WITHDRAW ResourceType = "withdraw" + WITHDRAWAL ResourceType = "withdrawal" ) diff --git a/resources/model_withdrawal.go b/resources/model_withdrawal.go new file mode 100644 index 0000000..dfc8561 --- /dev/null +++ b/resources/model_withdrawal.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type Withdrawal struct { + Key + Attributes WithdrawalAttributes `json:"attributes"` +} +type WithdrawalResponse struct { + Data Withdrawal `json:"data"` + Included Included `json:"included"` +} + +type WithdrawalListResponse struct { + Data []Withdrawal `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *WithdrawalListResponse) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *WithdrawalListResponse) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustWithdrawal - returns Withdrawal from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustWithdrawal(key Key) *Withdrawal { + var withdrawal Withdrawal + if c.tryFindEntry(key, &withdrawal) { + return &withdrawal + } + return nil +} diff --git a/resources/model_withdrawal_attributes.go b/resources/model_withdrawal_attributes.go new file mode 100644 index 0000000..60af863 --- /dev/null +++ b/resources/model_withdrawal_attributes.go @@ -0,0 +1,14 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +type WithdrawalAttributes struct { + // Rarimo address which points were withdrawn to. Can be any valid address. + Address string `json:"address"` + // Amount of points withdrawn + Amount int32 `json:"amount"` + // Unix timestamp of withdrawal creation + CreatedAt int32 `json:"created_at"` +}