diff --git a/package-lock.json b/package-lock.json index f3eb3b3..b29d642 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,13 @@ "data/project-templates/*" ], "dependencies": { - "@golem-sdk/golem-js": "^1.0.1", + "@golem-sdk/golem-js": "^2.0.0-beta.16", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", + "chalk": "^4.1.2", "commander": "^11.1.0", + "console-table-printer": "^2.12.0", + "decimal.js-light": "^2.5.1", "enquirer": "^2.4.1", "lodash": "^4.17.21", "luxon": "^3.4.4", @@ -74,6 +77,54 @@ "@golem-sdk/cli": "^2.0.1" } }, + "data/project-templates/js-node-esm/node_modules/@golem-sdk/golem-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.3.tgz", + "integrity": "sha512-d6vk1LOXTiEjB9DkdmQtlhwGEizVtKIBlQ/7wCTORWITZRp2b4EWRrWdXXo2yCnMeeyHLnFOY3IdnvXb781I6Q==", + "dependencies": { + "async-lock": "^1.4.0", + "axios": "^1.6.2", + "bottleneck": "^2.19.5", + "collect.js": "^4.36.1", + "eventemitter3": "^5.0.1", + "eventsource": "^2.0.2", + "flatbuffers": "^23.5.26", + "ip-num": "^1.5.1", + "js-sha3": "^0.9.2", + "pino": "^8.16.2", + "pino-pretty": "^10.2.3", + "tmp": "^0.2.1", + "uuid": "^9.0.1", + "ya-ts-client": "^0.5.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "data/project-templates/js-node/node_modules/@golem-sdk/golem-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.3.tgz", + "integrity": "sha512-d6vk1LOXTiEjB9DkdmQtlhwGEizVtKIBlQ/7wCTORWITZRp2b4EWRrWdXXo2yCnMeeyHLnFOY3IdnvXb781I6Q==", + "dependencies": { + "async-lock": "^1.4.0", + "axios": "^1.6.2", + "bottleneck": "^2.19.5", + "collect.js": "^4.36.1", + "eventemitter3": "^5.0.1", + "eventsource": "^2.0.2", + "flatbuffers": "^23.5.26", + "ip-num": "^1.5.1", + "js-sha3": "^0.9.2", + "pino": "^8.16.2", + "pino-pretty": "^10.2.3", + "tmp": "^0.2.1", + "uuid": "^9.0.1", + "ya-ts-client": "^0.5.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "data/project-templates/react-js": { "name": "react-js-golem-app", "version": "0.0.0", @@ -94,6 +145,30 @@ "vite": "^5.0.10" } }, + "data/project-templates/react-js/node_modules/@golem-sdk/golem-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.3.tgz", + "integrity": "sha512-d6vk1LOXTiEjB9DkdmQtlhwGEizVtKIBlQ/7wCTORWITZRp2b4EWRrWdXXo2yCnMeeyHLnFOY3IdnvXb781I6Q==", + "dependencies": { + "async-lock": "^1.4.0", + "axios": "^1.6.2", + "bottleneck": "^2.19.5", + "collect.js": "^4.36.1", + "eventemitter3": "^5.0.1", + "eventsource": "^2.0.2", + "flatbuffers": "^23.5.26", + "ip-num": "^1.5.1", + "js-sha3": "^0.9.2", + "pino": "^8.16.2", + "pino-pretty": "^10.2.3", + "tmp": "^0.2.1", + "uuid": "^9.0.1", + "ya-ts-client": "^0.5.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "data/project-templates/react-ts": { "name": "react-ts-golem-app", "version": "0.0.0", @@ -116,6 +191,30 @@ "vite": "^5.0.10" } }, + "data/project-templates/react-ts/node_modules/@golem-sdk/golem-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.3.tgz", + "integrity": "sha512-d6vk1LOXTiEjB9DkdmQtlhwGEizVtKIBlQ/7wCTORWITZRp2b4EWRrWdXXo2yCnMeeyHLnFOY3IdnvXb781I6Q==", + "dependencies": { + "async-lock": "^1.4.0", + "axios": "^1.6.2", + "bottleneck": "^2.19.5", + "collect.js": "^4.36.1", + "eventemitter3": "^5.0.1", + "eventsource": "^2.0.2", + "flatbuffers": "^23.5.26", + "ip-num": "^1.5.1", + "js-sha3": "^0.9.2", + "pino": "^8.16.2", + "pino-pretty": "^10.2.3", + "tmp": "^0.2.1", + "uuid": "^9.0.1", + "ya-ts-client": "^0.5.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "data/project-templates/ts-node": { "name": "ts-node-golem-app", "version": "1.0.0", @@ -140,6 +239,54 @@ "@golem-sdk/cli": "^2.0.1" } }, + "data/project-templates/ts-node-esm/node_modules/@golem-sdk/golem-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.3.tgz", + "integrity": "sha512-d6vk1LOXTiEjB9DkdmQtlhwGEizVtKIBlQ/7wCTORWITZRp2b4EWRrWdXXo2yCnMeeyHLnFOY3IdnvXb781I6Q==", + "dependencies": { + "async-lock": "^1.4.0", + "axios": "^1.6.2", + "bottleneck": "^2.19.5", + "collect.js": "^4.36.1", + "eventemitter3": "^5.0.1", + "eventsource": "^2.0.2", + "flatbuffers": "^23.5.26", + "ip-num": "^1.5.1", + "js-sha3": "^0.9.2", + "pino": "^8.16.2", + "pino-pretty": "^10.2.3", + "tmp": "^0.2.1", + "uuid": "^9.0.1", + "ya-ts-client": "^0.5.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "data/project-templates/ts-node/node_modules/@golem-sdk/golem-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.3.tgz", + "integrity": "sha512-d6vk1LOXTiEjB9DkdmQtlhwGEizVtKIBlQ/7wCTORWITZRp2b4EWRrWdXXo2yCnMeeyHLnFOY3IdnvXb781I6Q==", + "dependencies": { + "async-lock": "^1.4.0", + "axios": "^1.6.2", + "bottleneck": "^2.19.5", + "collect.js": "^4.36.1", + "eventemitter3": "^5.0.1", + "eventsource": "^2.0.2", + "flatbuffers": "^23.5.26", + "ip-num": "^1.5.1", + "js-sha3": "^0.9.2", + "pino": "^8.16.2", + "pino-pretty": "^10.2.3", + "tmp": "^0.2.1", + "uuid": "^9.0.1", + "ya-ts-client": "^0.5.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -1559,11 +1706,13 @@ "node": ">=18.0.0" } }, - "node_modules/@golem-sdk/golem-js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.1.tgz", - "integrity": "sha512-vrrWWXlZWOf5DzsCHwBKdzrf0s1ZGthHIJK4fLvFJCj59RbntCgOeCSTKAO/qf/SJtF5LSF3hdlMIi7CIIx7eA==", + "node_modules/@golem-sdk/cli/node_modules/@golem-sdk/golem-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-1.0.3.tgz", + "integrity": "sha512-d6vk1LOXTiEjB9DkdmQtlhwGEizVtKIBlQ/7wCTORWITZRp2b4EWRrWdXXo2yCnMeeyHLnFOY3IdnvXb781I6Q==", + "dev": true, "dependencies": { + "async-lock": "^1.4.0", "axios": "^1.6.2", "bottleneck": "^2.19.5", "collect.js": "^4.36.1", @@ -1582,6 +1731,33 @@ "node": ">=18.0.0" } }, + "node_modules/@golem-sdk/golem-js": { + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@golem-sdk/golem-js/-/golem-js-2.0.0-beta.16.tgz", + "integrity": "sha512-msGQ/he5ieSePOGHpIxOzg2o4sygcDHyYbjg/MFdafUICQu4ujQeRyoHnrYmDhFHJaLD3cGdJNLwuAvD7AHr9w==", + "dependencies": { + "async-lock": "^1.4.0", + "axios": "^1.6.2", + "bottleneck": "^2.19.5", + "collect.js": "^4.36.1", + "debug": "^4.3.4", + "decimal.js-light": "^2.5.1", + "eventemitter3": "^5.0.1", + "eventsource": "^2.0.2", + "flatbuffers": "^23.5.26", + "ip-num": "^1.5.1", + "js-sha3": "^0.9.3", + "pino": "^8.17.1", + "pino-pretty": "^10.3.0", + "semver": "^7.5.4", + "tmp": "^0.2.1", + "uuid": "^9.0.1", + "ya-ts-client": "^0.5.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@golem-sdk/react": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@golem-sdk/react/-/react-2.0.0.tgz", @@ -3470,7 +3646,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -3638,6 +3813,11 @@ "node": ">=0.10.0" } }, + "node_modules/async-lock": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==" + }, "node_modules/asynciterator.prototype": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", @@ -4010,7 +4190,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4138,7 +4317,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4149,8 +4327,7 @@ "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==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "2.0.20", @@ -4201,6 +4378,14 @@ "proto-list": "~1.2.1" } }, + "node_modules/console-table-printer": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.12.0.tgz", + "integrity": "sha512-Q/Ax+UOpZw0oPZGmv8bH8/W5NpC2rAYy6cX20BVLGQ45v944oL+srmLTZAse/5a3vWDl0MXR/0GTEdsz2dDTbg==", + "dependencies": { + "simple-wcswidth": "^1.0.1" + } + }, "node_modules/conventional-changelog-angular": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", @@ -4462,6 +4647,11 @@ "node": ">=0.10.0" } }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, "node_modules/dedent": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", @@ -6276,7 +6466,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -6345,63 +6534,9 @@ } }, "node_modules/help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/help-me/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/help-me/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/help-me/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/help-me/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" }, "node_modules/hook-std": { "version": "3.0.0", @@ -7764,9 +7899,9 @@ "link": true }, "node_modules/js-sha3": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.2.tgz", - "integrity": "sha512-8kgvwd03wNGQG1GRvl3yy1Yt40sICAcIMsDU2ZLgoL0Z6z9rkRmf9Vd+bi/gYSzgAqMUGl/jiDKu0J8AWFd+BQ==" + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz", + "integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -11861,16 +11996,16 @@ } }, "node_modules/pino": { - "version": "8.16.2", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.16.2.tgz", - "integrity": "sha512-2advCDGVEvkKu9TTVSa/kWW7Z3htI/sBKEZpqiHk6ive0i/7f5b1rsU8jn0aimxqfnSz5bj/nOYkwhBUn5xxvg==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.2.tgz", + "integrity": "sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "v1.1.0", "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0", + "process-warning": "^3.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", @@ -11891,15 +12026,15 @@ } }, "node_modules/pino-pretty": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.3.tgz", - "integrity": "sha512-4jfIUc8TC1GPUfDyMSlW1STeORqkoxec71yhxIpLDQapUu8WOuoz2TTCoidrIssyz78LZC69whBMPIKCMbi3cw==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz", + "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==", "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^3.0.0", "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", + "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", @@ -12179,9 +12314,9 @@ "dev": true }, "node_modules/process-warning": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.2.tgz", - "integrity": "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" }, "node_modules/prompts": { "version": "2.4.2", @@ -12953,7 +13088,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -12995,7 +13129,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -13006,8 +13139,7 @@ "node_modules/semver/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/set-function-length": { "version": "1.1.1", @@ -13184,6 +13316,11 @@ "node": ">=4" } }, + "node_modules/simple-wcswidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz", + "integrity": "sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -13516,7 +13653,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -14010,7 +14146,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "node_modules/uuid": { "version": "9.0.1", diff --git a/package.json b/package.json index 4e73dc4..24fcd85 100644 --- a/package.json +++ b/package.json @@ -40,10 +40,13 @@ "node": ">=18.0.0" }, "dependencies": { - "@golem-sdk/golem-js": "^1.0.1", + "@golem-sdk/golem-js": "^2.0.0-beta.16", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", + "chalk": "^4.1.2", "commander": "^11.1.0", + "console-table-printer": "^2.12.0", + "decimal.js-light": "^2.5.1", "enquirer": "^2.4.1", "lodash": "^4.17.21", "luxon": "^3.4.4", diff --git a/src/main.ts b/src/main.ts index 36eff98..f2d1ee8 100755 --- a/src/main.ts +++ b/src/main.ts @@ -4,6 +4,7 @@ import { version } from "./lib/version"; import { manifestCommand } from "./manifest/manifest.command"; import { newCommand } from "./new/new.command"; import { runOnGolemCommand } from "./run-on-golem/run-on-golem.command"; +import { invoiceCommand } from "./payment/invoice.command"; const program = new Command("golem-sdk"); program.version(version); @@ -12,6 +13,6 @@ program.version(version); // chalk.level = 0; // }); -program.addCommand(manifestCommand).addCommand(newCommand).addCommand(runOnGolemCommand); +program.addCommand(manifestCommand).addCommand(newCommand).addCommand(runOnGolemCommand).addCommand(invoiceCommand); program.parse(); diff --git a/src/payment/common.ts b/src/payment/common.ts new file mode 100644 index 0000000..6ef3138 --- /dev/null +++ b/src/payment/common.ts @@ -0,0 +1,69 @@ +import { Command, InvalidArgumentError, Option } from "commander"; +import { InvoiceSearchOptions } from "./invoice.options"; +import { InvoiceProcessor } from "@golem-sdk/golem-js"; + +function parseIntOrThrow(value: string) { + const parsedValue = parseInt(value, 10); + if (isNaN(parsedValue) || parsedValue < 0) { + throw new InvalidArgumentError("Not a valid positive integer."); + } + return parsedValue; +} +function parseDateOrThrow(value: string) { + const parsedValue = new Date(value); + if (isNaN(parsedValue.getTime())) { + throw new InvalidArgumentError("Not a valid date."); + } + return parsedValue; +} + +export function createInvoiceCommand(name: string): Command { + return new Command(name) + .addOption(new Option("-k, --yagna-appkey ", "Yagna app key").env("YAGNA_APPKEY").makeOptionMandatory()) + .addOption( + new Option("--after ", "Search for invoices after this date") + .default(new Date(0)) + .argParser(parseDateOrThrow), + ) + .addOption( + new Option("--limit ", "Limit the number of invoices returned by the search") + .default(50) + .argParser(parseIntOrThrow), + ) + .addOption(new Option("--provider [provider...]", "Search by provider ID")) + .option( + "--columns [columns...]", + "Columns to display. Valid options are: id, status, amount, timestamp, platform, payer, issuer, providerId", + ["id", "status", "amount", "timestamp", "providerId", "platform"], + ) + .option("--wallet [wallet...]", "Search by wallet address") + .option("--min-amount ", "Search by minimum invoice amount") + .option("--max-amount ", "Search by maximum invoice amount") + .option( + "--status [status...]", + "Search by invoice status. For example to search for invoices you received but did not accept yet, use `--status RECEIVED`. Valid options are: ISSUED, RECEIVED, ACCEPTED, REJECTED, FAILED, SETTLED, CANCELLED.", + ["RECEIVED", "ACCEPTED", "SETTLED"], + ) + .option("--payment-platform [paymentPlatform...]", "Search by payment platform") + .option( + "-i --invoice [invoice...]", + "Instead of searching, fetch specific invoices by ID. If this option is used, all other search options are ignored.", + ) + .option("-f, --format ", "Output format: table, json, csv.", "table"); +} + +export async function fetchInvoices(options: InvoiceSearchOptions, processor: InvoiceProcessor) { + if (options.invoice && options.invoice.length > 0) { + return Promise.all(options.invoice.map(async (invoiceId) => processor.fetchSingleInvoice(invoiceId))); + } + return processor.collectInvoices({ + limit: options.limit, + after: options.after, + statuses: options.status, + providerIds: options.provider, + providerWallets: options.wallet, + minAmount: options.minAmount, + maxAmount: options.maxAmount, + paymentPlatforms: options.paymentPlatform, + }); +} diff --git a/src/payment/invoice-accept.action.ts b/src/payment/invoice-accept.action.ts new file mode 100644 index 0000000..c6d6afc --- /dev/null +++ b/src/payment/invoice-accept.action.ts @@ -0,0 +1,158 @@ +import { prompt } from "enquirer"; +import Decimal from "decimal.js-light"; +import { Table } from "console-table-printer"; +import { Invoice } from "ya-ts-client/dist/ya-payment"; +import chalk from "chalk"; +import { InvoiceAcceptOptions } from "./invoice.options"; +import { InvoiceAcceptResult, InvoiceProcessor } from "@golem-sdk/golem-js"; +import { fetchInvoices } from "./common"; +import _ from "lodash"; + +async function askForConfirmation(invoices: Invoice[], columns: InvoiceAcceptOptions["columns"]) { + const invoicesToPay = []; + + let i = 0; + for (const invoice of invoices) { + const allColumns = { + id: invoice.invoiceId, + accepted: invoice.status !== "RECEIVED" ? "accepted" : "not accepted", + status: invoice.status, + amount: invoice.amount, + timestamp: invoice.timestamp, + platform: invoice.paymentPlatform, + payer: invoice.payerAddr, + issuer: invoice.payeeAddr, + providerId: invoice.issuerId, + }; + const selectedColumns = _.pick(allColumns, columns); + + console.log( + `${++i}/${invoices.length}:\n` + + Object.entries(selectedColumns) + .map(([key, value]) => ` - ${chalk.bold(key)}:\t${value}`) + .join("\n"), + ); + const { decision } = (await prompt({ + type: "confirm", + name: "decision", + message: "Add this invoice to the list of invoices to accept?", + })) as { decision: boolean }; + if (decision) { + invoicesToPay.push(invoice); + } + } + return invoicesToPay; +} + +export async function acceptAction(options: InvoiceAcceptOptions) { + const paymentProcessor = await InvoiceProcessor.create({ + apiKey: options.yagnaAppkey, + }); + let invoices: Invoice[]; + try { + invoices = await fetchInvoices(options, paymentProcessor); + } catch (e) { + console.error(e); + console.log(chalk.red("Failed to fetch invoices, check your parameters and try again.")); + process.exitCode = 1; + return; + } + + if (invoices.length === 0) { + if (!options.silent) { + console.log(chalk.blue.bold("No unaccepted invoices found")); + } + return; + } + const invoicesToPay = []; + + if (options.yes) { + invoicesToPay.push(...invoices); + } else { + console.log(chalk.blue.bold(`Found ${invoices.length} unaccepted invoices:`)); + try { + invoicesToPay.push(...(await askForConfirmation(invoices, options.columns))); + + if (invoicesToPay.length === 0) { + console.log(chalk.blue.bold("No invoices selected")); + return; + } + + const invoicesOnTestnet = invoicesToPay.filter((invoice) => + invoice.paymentPlatform.toLowerCase().endsWith("-tglm"), + ); + const invoicesOnMainnet = invoicesToPay.filter((invoice) => + invoice.paymentPlatform.toLowerCase().endsWith("-glm"), + ); + if (invoicesOnTestnet.length > 0) { + const totalTestGLM = invoicesOnTestnet.reduce((acc, invoice) => acc.add(invoice.amount), new Decimal(0)); + console.log( + chalk.blue.bold( + `Selected ${invoicesOnTestnet.length} invoices on Testnet for a total of ${totalTestGLM} tGLM`, + ), + ); + } + if (invoicesOnMainnet.length > 0) { + const totalRealGLM = invoicesOnMainnet.reduce((acc, invoice) => acc.add(invoice.amount), new Decimal(0)); + console.log( + chalk.blue.bold( + `Selected ${invoicesOnMainnet.length} invoices on Mainnet for a total of ${totalRealGLM} GLM`, + ), + ); + } + const { decision } = (await prompt({ + type: "confirm", + name: "decision", + message: + invoicesToPay.length === 1 + ? "Do you want to accept this invoice?" + : `Do you want to accept these ${invoicesToPay.length} invoices?`, + })) as { decision: boolean }; + if (!decision) { + return; + } + } catch { + process.exitCode = 1; + console.log(chalk.red("Script cancelled")); + return; + } + } + + const paymentResults = await paymentProcessor.acceptManyInvoices({ + invoices: invoicesToPay, + dryRun: options.dryRun, + }); + + if (options.silent) { + return; + } + + const getRow = (result: InvoiceAcceptResult) => { + return { + invoiceId: result.invoiceId, + status: (result.success ? "success" : "failed") + (result.dryRun ? " (dry run)" : ""), + amount: result.amount, + platform: result.allocation.paymentPlatform, + }; + }; + + if (options.format === "table") { + const summaryTable = new Table(); + paymentResults.forEach((result) => + summaryTable.addRow(getRow(result), { + color: result.dryRun ? "yellow" : result.success ? "green" : "red", + }), + ); + summaryTable.printTable(); + } + + if (options.format === "json") { + console.log(JSON.stringify(paymentResults.map(getRow))); + } + + if (options.format === "csv") { + const rows = paymentResults.map(getRow); + console.log(Object.keys(rows[0]).join(",")); + console.log(rows.map((row) => Object.values(row).join(",")).join("\n")); + } +} diff --git a/src/payment/invoice-search.action.ts b/src/payment/invoice-search.action.ts new file mode 100644 index 0000000..d55af2e --- /dev/null +++ b/src/payment/invoice-search.action.ts @@ -0,0 +1,69 @@ +import { InvoiceProcessor } from "@golem-sdk/golem-js"; +import { Invoice } from "ya-ts-client/dist/ya-payment"; +import { Table } from "console-table-printer"; +import { InvoiceSearchOptions } from "./invoice.options"; +import _ from "lodash"; +import chalk from "chalk"; +import { fetchInvoices } from "./common"; + +function printRows(invoices: Invoice[], options: InvoiceSearchOptions) { + const getRow = (invoice: Invoice) => { + const allColumns = { + id: invoice.invoiceId, + status: invoice.status, + amount: invoice.amount, + timestamp: invoice.timestamp, + platform: invoice.paymentPlatform, + payer: invoice.payerAddr, + issuer: invoice.payeeAddr, + providerId: invoice.issuerId, + }; + return _.pick(allColumns, options.columns); + }; + + if (options.format === "table") { + if (invoices.length === 0) { + console.log(chalk.red("No invoices found")); + return; + } + const table = new Table(); + invoices.forEach((invoice) => { + const isHighlighted = invoice.status === "RECEIVED" || invoice.status === "ISSUED"; + const row = getRow(invoice); + table.addRow(row, { + color: isHighlighted ? "red" : "green", + }); + }); + + table.printTable(); + return; + } + if (options.format === "json") { + console.log(JSON.stringify(invoices.map(getRow))); + return; + } + if (options.format === "csv") { + console.log(options.columns); + console.log( + invoices + .map(getRow) + .map((row) => Object.values(row).join(",")) + .join("\n"), + ); + return; + } +} + +export async function searchAction(options: InvoiceSearchOptions) { + const paymentProcessor = await InvoiceProcessor.create({ + apiKey: options.yagnaAppkey, + }); + let invoices: Invoice[]; + try { + invoices = await fetchInvoices(options, paymentProcessor); + } catch { + console.log(chalk.red("Failed to fetch invoices, check your parameters and try again")); + return; + } + printRows(invoices, options); +} diff --git a/src/payment/invoice.command.ts b/src/payment/invoice.command.ts new file mode 100644 index 0000000..afde83f --- /dev/null +++ b/src/payment/invoice.command.ts @@ -0,0 +1,52 @@ +import { Command, Option } from "commander"; +import { InvoiceAcceptOptions, InvoiceSearchOptions } from "./invoice.options"; +import { createInvoiceCommand } from "./common"; + +export const invoiceCommand = new Command("invoice").summary("Search and accept invoices.").addHelpText( + "after", + ` +Examples: + +Search for the first 10 invoices after 2023-01-01: +$ golem-sdk invoice search -k yagna-appkey --after 2023-01-01 --limit 10 + +Search for invoices issued by provider 0x1234 with status RECEIVED and print them in JSON format: +$ golem-sdk invoice search -k yagna-appkey --provider 0x1234 --status RECEIVED --format json + +Search for invoices above 0.5 GLM on payment platform erc20-polygon-glm: +$ golem-sdk invoice search -k yagna-appkey --min-amount 0.5 --payment-platform erc20-polygon-glm + +Search for invoices by their ID and only list their id, timestamp and payment platform: +$ golem-sdk invoice search -k yagna-appkey --invoice 0x1234 0x5678 --columns id timestamp platform + +Accept all invoices from provider 0x1234 (interactive): +$ golem-sdk invoice accept -k yagna-appkey --provider 0x1234 + +Accept all invoices from provider 0x1234 (auto-accept): +$ golem-sdk invoice accept -k yagna-appkey --provider 0x1234 --yes + +Accept all invoices from provider 0x1234 (dry run): +$ golem-sdk invoice accept -k yagna-appkey --provider 0x1234 --dry-run +`, +); + +const searchCommand = createInvoiceCommand("search") + .summary("Search for invoices.") + .allowUnknownOption(false) + .action(async (options: InvoiceSearchOptions) => { + const action = await import("./invoice-search.action.js"); + await action.default.searchAction(options); + }); + +const payCommand = createInvoiceCommand("accept") + .summary("Accept invoices. This command is interactive by default and takes the same options as search.") + .addOption(new Option("-y --yes", "Skip confirmation").default(false)) + .addOption(new Option("--dry-run", "Dry run").default(false)) + .addOption(new Option("-s, --silent", "Don't print anything to stdout").default(false)) + .allowUnknownOption(false) + .action(async (options: InvoiceAcceptOptions) => { + const action = await import("./invoice-accept.action.js"); + await action.default.acceptAction(options); + }); + +invoiceCommand.addCommand(searchCommand).addCommand(payCommand); diff --git a/src/payment/invoice.options.ts b/src/payment/invoice.options.ts new file mode 100644 index 0000000..50cb503 --- /dev/null +++ b/src/payment/invoice.options.ts @@ -0,0 +1,20 @@ +export interface InvoiceSearchOptions { + yagnaAppkey: string; + after: Date; + limit: number; + provider?: string[]; + wallet?: string[]; + minAmount?: number; + maxAmount?: number; + paymentPlatform?: string[]; + columns: string[]; + status: string[]; + invoice?: string[]; + format: "table" | "json" | "csv"; +} + +export interface InvoiceAcceptOptions extends InvoiceSearchOptions { + yes: boolean; + dryRun: boolean; + silent: boolean; +} diff --git a/src/run-on-golem/run-on-golem.action.ts b/src/run-on-golem/run-on-golem.action.ts index 08ff854..028015b 100644 --- a/src/run-on-golem/run-on-golem.action.ts +++ b/src/run-on-golem/run-on-golem.action.ts @@ -3,7 +3,7 @@ import { createInterface } from "readline/promises"; import { parse, ParseEntry } from "shell-quote"; import { CommanderError } from "commander"; import { ParseError, ShellError } from "./errors"; -import { EventType, ExecutorOptions, TaskExecutor } from "@golem-sdk/golem-js"; +import { EVENT_TYPE, ExecutorOptions, TaskExecutor } from "@golem-sdk/golem-js"; import { assertFileExists, checkFileExists } from "../lib/file"; import { readFile } from "fs/promises"; import { TaskAPIContext, VarsType } from "./shell-context"; @@ -241,7 +241,7 @@ function installSignalHandlers(context: TaskAPIContext, et: EventTarget) { // This is used to detect if the activity was terminated by the provider, error or timeout. // If it is, TaskExecutor is already shutting down. Make sure we terminate the shell. - et.addEventListener(EventType, async (e) => { + et.addEventListener(EVENT_TYPE, async (e) => { // FIXME: Will be fixed after JST-526 if (e instanceof Events.ActivityDestroyed) { // // This will happen on activity timeout