diff --git a/package-lock.json b/package-lock.json index 18e3f115..5a6c34cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "grpc-tools": "^1.11.2", "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", - "nostr-tools": "^0.24.1", + "nostr-tools": "^1.9.0", "pg": "^8.4.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", @@ -48,6 +48,7 @@ "@types/jsonwebtoken": "^8.5.9", "@types/lodash": "^4.14.182", "@types/node": "^16.11.10", + "@types/node-fetch": "^2.6.3", "@types/uuid": "^8.3.4", "nodemon": "^2.0.20", "ts-node": "10.7.0", @@ -130,15 +131,24 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, - "node_modules/@noble/hashes": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.9.tgz", - "integrity": "sha512-7lN1Qh6d8DUGmfN36XRsbN/WcGIPNtTGhkw26vWId/DlCIGsYJJootTtPGghTLcn/AaXPx2Q0b3cacrwXa7OVw==" + "node_modules/@noble/curves": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", + "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "1.3.0" + } }, - "node_modules/@noble/secp256k1": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.0.tgz", - "integrity": "sha512-kbacwGSsH/CTout0ZnZWxnW1B+jH/7r/WAAKLBtrRJ/+CUH7lgmQzl3GTrQua3SGKWNSDsS6lmjnDpIJ5Dxyaw==", + "node_modules/@noble/hashes": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", "funding": [ { "type": "individual", @@ -338,6 +348,48 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@scure/bip32": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.0.tgz", + "integrity": "sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/curves": "~1.0.0", + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.0.tgz", + "integrity": "sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, "node_modules/@sqltools/formatter": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", @@ -472,6 +524,30 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==" }, + "node_modules/@types/node-fetch": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/object-hash": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz", @@ -875,6 +951,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "optional": true, "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -884,27 +961,6 @@ "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/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -944,19 +1000,8 @@ "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "node_modules/bufferutil": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", - "integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "optional": true }, "node_modules/bytes": { "version": "3.1.2", @@ -1086,6 +1131,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "optional": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -1246,6 +1292,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "optional": true, "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -1274,23 +1321,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "devOptional": true }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "node_modules/dataloader": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", @@ -1348,15 +1378,6 @@ "node": ">= 0.8" } }, - "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.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -1546,44 +1567,11 @@ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "optional": true }, - "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, "node_modules/es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1609,6 +1597,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "optional": true, "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -1655,19 +1644,6 @@ "node": ">= 0.10.0" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -1962,6 +1938,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "optional": true, "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -1975,6 +1952,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -1988,6 +1966,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -2268,11 +2247,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -2476,6 +2450,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "optional": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -2511,33 +2486,6 @@ "node": ">= 0.6" } }, - "node_modules/micro-base": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/micro-base/-/micro-base-0.10.2.tgz", - "integrity": "sha512-lqqJrT7lfJtDmmiQ4zRLZuIJBk96t0RAc5pCrrWpL9zDeH5i/SUL85mku9HqzTI/OCZ8EQ3aicbMW+eK5Nyu5w==", - "deprecated": "Switch to @scure/base for audited version of the lib & updates" - }, - "node_modules/micro-bip32": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/micro-bip32/-/micro-bip32-0.1.0.tgz", - "integrity": "sha512-HxwYJzokbObqPHUqQuzRpCEqZ3EE4uHKrGlLX5ylt0ktD6m9LeS3RkWuQ1HApXEgrGMs3XgykN5Bic2YHE0f6Q==", - "deprecated": "Switch to @scure/bip32 for audited version of the lib & updates", - "dependencies": { - "@noble/hashes": "^0.5.7", - "@noble/secp256k1": "^1.3.4", - "micro-base": "^0.10.1" - } - }, - "node_modules/micro-bip39": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/micro-bip39/-/micro-bip39-0.1.3.tgz", - "integrity": "sha512-lEaRG/MKxFQvG19lfJfPkLIG0rgT28nWud3otN+VgAbrozGqXn2PLaZuYPsy9guQjIZWBTvoLw/HDJQxmMXjMA==", - "deprecated": "Switch to @scure/bip39 for audited version of the lib & updates", - "dependencies": { - "@noble/hashes": "^0.5.5", - "micro-base": "^0.10.1" - } - }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -2728,11 +2676,6 @@ "node": ">= 0.6" } }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -2967,19 +2910,15 @@ } }, "node_modules/nostr-tools": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-0.24.1.tgz", - "integrity": "sha512-+aUWblwNTYra8ZsjmfzxStr4XSKAb0gPsehNP3oBiSouLevqD3FWngc++kh8l+zfMYEPPGS6kS0i9iaq/5ZF6A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.9.0.tgz", + "integrity": "sha512-ZvFf1uiBqWLWhLBHD2nY0KsdSdNWKb3PrQUmYMWxSzfT4k48cDrDJu2qgULkOhQbFX7oty8IpaKnLvixhqefqA==", "dependencies": { - "@noble/hashes": "^0.5.7", - "@noble/secp256k1": "^1.5.2", - "browserify-cipher": ">=1", - "buffer": ">=5", - "create-hash": "^1.2.0", - "cross-fetch": "^3.1.4", - "micro-bip32": "^0.1.0", - "micro-bip39": "^0.1.3", - "websocket-polyfill": "^0.0.3" + "@noble/curves": "1.0.0", + "@noble/hashes": "1.3.0", + "@scure/base": "1.1.1", + "@scure/bip32": "1.3.0", + "@scure/bip39": "1.2.0" } }, "node_modules/npmlog": { @@ -3428,6 +3367,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "optional": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -4060,16 +4000,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, - "node_modules/tstl": { - "version": "2.5.13", - "resolved": "https://registry.npmjs.org/tstl/-/tstl-2.5.13.tgz", - "integrity": "sha512-h9wayHHFI5+yqt8iau0vqH96cTNhezhZ/Fk/hrIdpfkiMu3lg9nzyvMfs5bIdX51IVzZO6DudLqhkL/rVXpT6g==" - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4090,14 +4020,6 @@ "node": ">= 0.6" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typeorm": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.10.tgz", @@ -4317,18 +4239,6 @@ "node": ">=8" } }, - "node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4369,31 +4279,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "node_modules/websocket": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", - "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", - "dependencies": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/websocket-polyfill": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/websocket-polyfill/-/websocket-polyfill-0.0.3.tgz", - "integrity": "sha512-pF3kR8Uaoau78MpUmFfzbIRxXj9PeQrCuPepGE6JIsfsJ/o/iXr07Q2iQNzKSSblQJ0FiGWlS64N4pVSm+O3Dg==", - "dependencies": { - "tstl": "^2.0.7", - "websocket": "^1.0.28" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -4483,14 +4368,6 @@ "node": ">=10" } }, - "node_modules/yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", - "engines": { - "node": ">=0.10.32" - } - }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -4590,15 +4467,18 @@ "tar": "^6.1.11" } }, - "@noble/hashes": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.9.tgz", - "integrity": "sha512-7lN1Qh6d8DUGmfN36XRsbN/WcGIPNtTGhkw26vWId/DlCIGsYJJootTtPGghTLcn/AaXPx2Q0b3cacrwXa7OVw==" + "@noble/curves": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz", + "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==", + "requires": { + "@noble/hashes": "1.3.0" + } }, - "@noble/secp256k1": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.0.tgz", - "integrity": "sha512-kbacwGSsH/CTout0ZnZWxnW1B+jH/7r/WAAKLBtrRJ/+CUH7lgmQzl3GTrQua3SGKWNSDsS6lmjnDpIJ5Dxyaw==" + "@noble/hashes": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==" }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -4759,6 +4639,30 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==" + }, + "@scure/bip32": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.0.tgz", + "integrity": "sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q==", + "requires": { + "@noble/curves": "~1.0.0", + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, + "@scure/bip39": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.0.tgz", + "integrity": "sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==", + "requires": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + } + }, "@sqltools/formatter": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", @@ -4890,6 +4794,29 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==" }, + "@types/node-fetch": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", + "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@types/object-hash": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz", @@ -5211,6 +5138,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "optional": true, "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -5220,27 +5148,6 @@ "safe-buffer": "^5.0.1" } }, - "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==", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "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==", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, "buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -5263,15 +5170,8 @@ "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "bufferutil": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", - "integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==", - "requires": { - "node-gyp-build": "^4.3.0" - } + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "optional": true }, "bytes": { "version": "3.1.2", @@ -5366,6 +5266,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "optional": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -5491,6 +5392,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "optional": true, "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -5519,23 +5421,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "devOptional": true }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "requires": { - "node-fetch": "2.6.7" - } - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "dataloader": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", @@ -5577,15 +5462,6 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -5740,40 +5616,11 @@ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "optional": true }, - "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -5793,6 +5640,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "optional": true, "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -5836,21 +5684,6 @@ "vary": "~1.1.2" } }, - "ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "requires": { - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - } - } - }, "fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -6059,6 +5892,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "optional": true, "requires": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -6069,6 +5903,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6079,6 +5914,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, "requires": { "safe-buffer": "~5.2.0" } @@ -6293,11 +6129,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -6480,6 +6311,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "optional": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -6506,30 +6338,6 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, - "micro-base": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/micro-base/-/micro-base-0.10.2.tgz", - "integrity": "sha512-lqqJrT7lfJtDmmiQ4zRLZuIJBk96t0RAc5pCrrWpL9zDeH5i/SUL85mku9HqzTI/OCZ8EQ3aicbMW+eK5Nyu5w==" - }, - "micro-bip32": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/micro-bip32/-/micro-bip32-0.1.0.tgz", - "integrity": "sha512-HxwYJzokbObqPHUqQuzRpCEqZ3EE4uHKrGlLX5ylt0ktD6m9LeS3RkWuQ1HApXEgrGMs3XgykN5Bic2YHE0f6Q==", - "requires": { - "@noble/hashes": "^0.5.7", - "@noble/secp256k1": "^1.3.4", - "micro-base": "^0.10.1" - } - }, - "micro-bip39": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/micro-bip39/-/micro-bip39-0.1.3.tgz", - "integrity": "sha512-lEaRG/MKxFQvG19lfJfPkLIG0rgT28nWud3otN+VgAbrozGqXn2PLaZuYPsy9guQjIZWBTvoLw/HDJQxmMXjMA==", - "requires": { - "@noble/hashes": "^0.5.5", - "micro-base": "^0.10.1" - } - }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -6670,11 +6478,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, "node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -6851,19 +6654,15 @@ "dev": true }, "nostr-tools": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-0.24.1.tgz", - "integrity": "sha512-+aUWblwNTYra8ZsjmfzxStr4XSKAb0gPsehNP3oBiSouLevqD3FWngc++kh8l+zfMYEPPGS6kS0i9iaq/5ZF6A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.9.0.tgz", + "integrity": "sha512-ZvFf1uiBqWLWhLBHD2nY0KsdSdNWKb3PrQUmYMWxSzfT4k48cDrDJu2qgULkOhQbFX7oty8IpaKnLvixhqefqA==", "requires": { - "@noble/hashes": "^0.5.7", - "@noble/secp256k1": "^1.5.2", - "browserify-cipher": ">=1", - "buffer": ">=5", - "create-hash": "^1.2.0", - "cross-fetch": "^3.1.4", - "micro-bip32": "^0.1.0", - "micro-bip39": "^0.1.3", - "websocket-polyfill": "^0.0.3" + "@noble/curves": "1.0.0", + "@noble/hashes": "1.3.0", + "@scure/base": "1.1.1", + "@scure/bip32": "1.3.0", + "@scure/bip39": "1.2.0" } }, "npmlog": { @@ -7194,6 +6993,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "optional": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -7672,16 +7472,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, - "tstl": { - "version": "2.5.13", - "resolved": "https://registry.npmjs.org/tstl/-/tstl-2.5.13.tgz", - "integrity": "sha512-h9wayHHFI5+yqt8iau0vqH96cTNhezhZ/Fk/hrIdpfkiMu3lg9nzyvMfs5bIdX51IVzZO6DudLqhkL/rVXpT6g==" - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -7696,14 +7486,6 @@ "mime-types": "~2.1.24" } }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } - }, "typeorm": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.10.tgz", @@ -7812,14 +7594,6 @@ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==" }, - "utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7851,28 +7625,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "websocket": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", - "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", - "requires": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - } - }, - "websocket-polyfill": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/websocket-polyfill/-/websocket-polyfill-0.0.3.tgz", - "integrity": "sha512-pF3kR8Uaoau78MpUmFfzbIRxXj9PeQrCuPepGE6JIsfsJ/o/iXr07Q2iQNzKSSblQJ0FiGWlS64N4pVSm+O3Dg==", - "requires": { - "tstl": "^2.0.7", - "websocket": "^1.0.28" - } - }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -7938,11 +7690,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==" - }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 30b006c4..984ce5b2 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "grpc-tools": "^1.11.2", "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", - "nostr-tools": "^0.24.1", + "nostr-tools": "^1.9.0", "pg": "^8.4.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", @@ -63,9 +63,10 @@ "@types/jsonwebtoken": "^8.5.9", "@types/lodash": "^4.14.182", "@types/node": "^16.11.10", + "@types/node-fetch": "^2.6.3", "@types/uuid": "^8.3.4", "nodemon": "^2.0.20", "ts-node": "10.7.0", "typescript": "4.5.2" } -} \ No newline at end of file +} diff --git a/proto/autogenerated/debug.txt b/proto/autogenerated/debug.txt index 367c56e9..135475c0 100644 --- a/proto/autogenerated/debug.txt +++ b/proto/autogenerated/debug.txt @@ -1,5 +1,5 @@ -([]*main.Method) (len=21 cap=32) { - (*main.Method)(0xc0000700a0)({ +([]*main.Method) (len=29 cap=32) { + (*main.Method)(0xc0002ee050)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -9,8 +9,8 @@ name: (string) (len=5) "Empty", hasZeroFields: (bool) true }, - opts: (*main.methodOptions)(0xc0002a0fc0)({ - authType: (*main.supportedAuth)(0xc000031560)({ + opts: (*main.methodOptions)(0xc0002fbaa0)({ + authType: (*main.supportedAuth)(0xc0005452c0)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -22,11 +22,10 @@ route: (string) (len=11) "/api/health", params: ([]string) }, - query: ([]string) , - nostr: (bool) false + query: ([]string) }) }), - (*main.Method)(0xc0000700f0)({ + (*main.Method)(0xc0002ee0a0)({ in: (main.MethodMessage) { name: (string) (len=25) "EncryptionExchangeRequest", hasZeroFields: (bool) false @@ -36,8 +35,8 @@ name: (string) (len=5) "Empty", hasZeroFields: (bool) true }, - opts: (*main.methodOptions)(0xc0002a1140)({ - authType: (*main.supportedAuth)(0xc000031620)({ + opts: (*main.methodOptions)(0xc0002fbc20)({ + authType: (*main.supportedAuth)(0xc0005453b0)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -49,11 +48,10 @@ route: (string) (len=24) "/api/encryption/exchange", params: ([]string) }, - query: ([]string) , - nostr: (bool) false + query: ([]string) }) }), - (*main.Method)(0xc000070140)({ + (*main.Method)(0xc0002ee460)({ in: (main.MethodMessage) { name: (string) (len=17) "LndGetInfoRequest", hasZeroFields: (bool) false @@ -63,25 +61,240 @@ name: (string) (len=18) "LndGetInfoResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0002a12c0)({ - authType: (*main.supportedAuth)(0xc0000316b0)({ + opts: (*main.methodOptions)(0xc0002fbda0)({ + authType: (*main.supportedAuth)(0xc000545470)({ id: (string) (len=5) "admin", name: (string) (len=5) "Admin", - encrypted: (bool) true, + encrypted: (bool) false, context: (map[string]string) (len=1) { (string) (len=8) "admin_id": (string) (len=6) "string" } }), method: (string) (len=4) "post", route: (main.decodedRoute) { - route: (string) (len=16) "/api/lnd/getinfo", + route: (string) (len=22) "/api/admin/lnd/getinfo", params: ([]string) }, - query: ([]string) , - nostr: (bool) false + query: ([]string) }) }), - (*main.Method)(0xc000070190)({ + (*main.Method)(0xc0002ee6e0)({ + in: (main.MethodMessage) { + name: (string) (len=13) "AddAppRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=6) "AddApp", + out: (main.MethodMessage) { + name: (string) (len=14) "AddAppResponse", + hasZeroFields: (bool) false + }, + opts: (*main.methodOptions)(0xc0002fbf20)({ + authType: (*main.supportedAuth)(0xc000545530)({ + id: (string) (len=5) "admin", + name: (string) (len=5) "Admin", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=8) "admin_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=18) "/api/admin/app/add", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002ee870)({ + in: (main.MethodMessage) { + name: (string) (len=17) "AddAppUserRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=10) "AddAppUser", + out: (main.MethodMessage) { + name: (string) (len=7) "AppUser", + hasZeroFields: (bool) false + }, + opts: (*main.methodOptions)(0xc0000905a0)({ + authType: (*main.supportedAuth)(0xc0005455f0)({ + id: (string) (len=3) "app", + name: (string) (len=3) "App", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=6) "app_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=17) "/api/app/user/add", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002ee910)({ + in: (main.MethodMessage) { + name: (string) (len=20) "AddAppInvoiceRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=13) "AddAppInvoice", + out: (main.MethodMessage) { + name: (string) (len=18) "NewInvoiceResponse", + hasZeroFields: (bool) false + }, + opts: (*main.methodOptions)(0xc000090780)({ + authType: (*main.supportedAuth)(0xc0005456b0)({ + id: (string) (len=3) "app", + name: (string) (len=3) "App", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=6) "app_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=20) "/api/app/add/invoice", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002ee960)({ + in: (main.MethodMessage) { + name: (string) (len=24) "AddAppUserInvoiceRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=17) "AddAppUserInvoice", + out: (main.MethodMessage) { + name: (string) (len=18) "NewInvoiceResponse", + hasZeroFields: (bool) false + }, + opts: (*main.methodOptions)(0xc000090960)({ + authType: (*main.supportedAuth)(0xc000545770)({ + id: (string) (len=3) "app", + name: (string) (len=3) "App", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=6) "app_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=25) "/api/app/user/add/invoice", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002eea00)({ + in: (main.MethodMessage) { + name: (string) (len=17) "GetAppUserRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=10) "GetAppUser", + out: (main.MethodMessage) { + name: (string) (len=7) "AppUser", + hasZeroFields: (bool) false + }, + opts: (*main.methodOptions)(0xc000090ae0)({ + authType: (*main.supportedAuth)(0xc000545830)({ + id: (string) (len=3) "app", + name: (string) (len=3) "App", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=6) "app_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=17) "/api/app/user/get", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002eeaa0)({ + in: (main.MethodMessage) { + name: (string) (len=24) "PayAppUserInvoiceRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=17) "PayAppUserInvoice", + out: (main.MethodMessage) { + name: (string) (len=25) "PayAppUserInvoiceResponse", + hasZeroFields: (bool) false + }, + opts: (*main.methodOptions)(0xc000090c60)({ + authType: (*main.supportedAuth)(0xc0005458f0)({ + id: (string) (len=3) "app", + name: (string) (len=3) "App", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=6) "app_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=20) "/api/app/invoice/pay", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002eeaf0)({ + in: (main.MethodMessage) { + name: (string) (len=34) "SendAppUserToAppUserPaymentRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=27) "SendAppUserToAppUserPayment", + out: (main.MethodMessage) { + name: (string) (len=5) "Empty", + hasZeroFields: (bool) true + }, + opts: (*main.methodOptions)(0xc000090e40)({ + authType: (*main.supportedAuth)(0xc0005459b0)({ + id: (string) (len=3) "app", + name: (string) (len=3) "App", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=6) "app_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=26) "/api/app/user/internal/pay", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002eeb90)({ + in: (main.MethodMessage) { + name: (string) (len=30) "SendAppUserToAppPaymentRequest", + hasZeroFields: (bool) false + }, + name: (string) (len=23) "SendAppUserToAppPayment", + out: (main.MethodMessage) { + name: (string) (len=5) "Empty", + hasZeroFields: (bool) true + }, + opts: (*main.methodOptions)(0xc000091020)({ + authType: (*main.supportedAuth)(0xc000545a70)({ + id: (string) (len=3) "app", + name: (string) (len=3) "App", + encrypted: (bool) false, + context: (map[string]string) (len=1) { + (string) (len=6) "app_id": (string) (len=6) "string" + } + }), + method: (string) (len=4) "post", + route: (main.decodedRoute) { + route: (string) (len=21) "/api/app/internal/pay", + params: ([]string) + }, + query: ([]string) + }) + }), + (*main.Method)(0xc0002eebe0)({ in: (main.MethodMessage) { name: (string) (len=14) "AddUserRequest", hasZeroFields: (bool) false @@ -91,8 +304,8 @@ name: (string) (len=15) "AddUserResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0002a1440)({ - authType: (*main.supportedAuth)(0xc000031740)({ + opts: (*main.methodOptions)(0xc000091200)({ + authType: (*main.supportedAuth)(0xc000545b30)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -104,11 +317,10 @@ route: (string) (len=13) "/api/user/add", params: ([]string) }, - query: ([]string) , - nostr: (bool) false + query: ([]string) }) }), - (*main.Method)(0xc0000701e0)({ + (*main.Method)(0xc0002eec30)({ in: (main.MethodMessage) { name: (string) (len=15) "AuthUserRequest", hasZeroFields: (bool) false @@ -118,8 +330,8 @@ name: (string) (len=16) "AuthUserResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0002a15c0)({ - authType: (*main.supportedAuth)(0xc0000317d0)({ + opts: (*main.methodOptions)(0xc000091380)({ + authType: (*main.supportedAuth)(0xc000545bf0)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -131,11 +343,10 @@ route: (string) (len=14) "/api/user/auth", params: ([]string) }, - query: ([]string) , - nostr: (bool) false + query: ([]string) }) }), - (*main.Method)(0xc000070230)({ + (*main.Method)(0xc0002eec80)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -145,8 +356,8 @@ name: (string) (len=8) "UserInfo", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0002a17a0)({ - authType: (*main.supportedAuth)(0xc000031890)({ + opts: (*main.methodOptions)(0xc00054c060)({ + authType: (*main.supportedAuth)(0xc000545ce0)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -159,11 +370,10 @@ route: (string) (len=14) "/api/user/info", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc0000702d0)({ + (*main.Method)(0xc0002eed20)({ in: (main.MethodMessage) { name: (string) (len=17) "AddProductRequest", hasZeroFields: (bool) false @@ -173,8 +383,8 @@ name: (string) (len=7) "Product", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0002a1980)({ - authType: (*main.supportedAuth)(0xc000031920)({ + opts: (*main.methodOptions)(0xc00054c240)({ + authType: (*main.supportedAuth)(0xc000545da0)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -187,11 +397,10 @@ route: (string) (len=21) "/api/user/product/add", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc000070320)({ + (*main.Method)(0xc0002eed70)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -201,8 +410,8 @@ name: (string) (len=18) "NewInvoiceResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0002a1e00)({ - authType: (*main.supportedAuth)(0xc000031a40)({ + opts: (*main.methodOptions)(0xc00054c6c0)({ + authType: (*main.supportedAuth)(0xc000545ef0)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -217,11 +426,10 @@ }, query: ([]string) (len=1 cap=1) { (string) (len=2) "id" - }, - nostr: (bool) true + } }) }), - (*main.Method)(0xc000070370)({ + (*main.Method)(0xc0002eedc0)({ in: (main.MethodMessage) { name: (string) (len=24) "GetUserOperationsRequest", hasZeroFields: (bool) false @@ -231,8 +439,8 @@ name: (string) (len=25) "GetUserOperationsResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0000360c0)({ - authType: (*main.supportedAuth)(0xc000031ad0)({ + opts: (*main.methodOptions)(0xc00054c8a0)({ + authType: (*main.supportedAuth)(0xc000545fb0)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -245,11 +453,10 @@ route: (string) (len=20) "/api/user/operations", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc000070410)({ + (*main.Method)(0xc0002eee60)({ in: (main.MethodMessage) { name: (string) (len=17) "NewAddressRequest", hasZeroFields: (bool) false @@ -259,8 +466,8 @@ name: (string) (len=18) "NewAddressResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc0000362a0)({ - authType: (*main.supportedAuth)(0xc000031b60)({ + opts: (*main.methodOptions)(0xc00054ca80)({ + authType: (*main.supportedAuth)(0xc00054e090)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -273,11 +480,10 @@ route: (string) (len=19) "/api/user/chain/new", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc0000704b0)({ + (*main.Method)(0xc0002eef00)({ in: (main.MethodMessage) { name: (string) (len=17) "PayAddressRequest", hasZeroFields: (bool) false @@ -287,8 +493,8 @@ name: (string) (len=18) "PayAddressResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000036480)({ - authType: (*main.supportedAuth)(0xc000031bf0)({ + opts: (*main.methodOptions)(0xc00054cc60)({ + authType: (*main.supportedAuth)(0xc00054e150)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -301,11 +507,10 @@ route: (string) (len=19) "/api/user/chain/pay", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc000070550)({ + (*main.Method)(0xc0002eefa0)({ in: (main.MethodMessage) { name: (string) (len=17) "NewInvoiceRequest", hasZeroFields: (bool) false @@ -315,8 +520,8 @@ name: (string) (len=18) "NewInvoiceResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000036660)({ - authType: (*main.supportedAuth)(0xc000031c80)({ + opts: (*main.methodOptions)(0xc00054ce40)({ + authType: (*main.supportedAuth)(0xc00054e210)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -329,11 +534,10 @@ route: (string) (len=21) "/api/user/invoice/new", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc0000705f0)({ + (*main.Method)(0xc0002ef040)({ in: (main.MethodMessage) { name: (string) (len=20) "DecodeInvoiceRequest", hasZeroFields: (bool) false @@ -343,8 +547,8 @@ name: (string) (len=21) "DecodeInvoiceResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000036840)({ - authType: (*main.supportedAuth)(0xc000031d10)({ + opts: (*main.methodOptions)(0xc00054d020)({ + authType: (*main.supportedAuth)(0xc00054e2d0)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -357,11 +561,10 @@ route: (string) (len=24) "/api/user/invoice/decode", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc000070690)({ + (*main.Method)(0xc0002ef0e0)({ in: (main.MethodMessage) { name: (string) (len=17) "PayInvoiceRequest", hasZeroFields: (bool) false @@ -371,8 +574,8 @@ name: (string) (len=18) "PayInvoiceResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000036a20)({ - authType: (*main.supportedAuth)(0xc000031da0)({ + opts: (*main.methodOptions)(0xc00054d200)({ + authType: (*main.supportedAuth)(0xc00054e390)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -385,11 +588,10 @@ route: (string) (len=21) "/api/user/invoice/pay", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc000070730)({ + (*main.Method)(0xc0002ef180)({ in: (main.MethodMessage) { name: (string) (len=18) "OpenChannelRequest", hasZeroFields: (bool) false @@ -399,8 +601,8 @@ name: (string) (len=19) "OpenChannelResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000036c00)({ - authType: (*main.supportedAuth)(0xc000031e30)({ + opts: (*main.methodOptions)(0xc00054d3e0)({ + authType: (*main.supportedAuth)(0xc00054e450)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -413,11 +615,10 @@ route: (string) (len=22) "/api/user/open/channel", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc0000707d0)({ + (*main.Method)(0xc0002ef220)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -427,8 +628,8 @@ name: (string) (len=17) "LnurlLinkResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000036de0)({ - authType: (*main.supportedAuth)(0xc000031ec0)({ + opts: (*main.methodOptions)(0xc00054d5c0)({ + authType: (*main.supportedAuth)(0xc00054e510)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -441,11 +642,10 @@ route: (string) (len=29) "/api/user/lnurl_withdraw/link", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }), - (*main.Method)(0xc000070870)({ + (*main.Method)(0xc0002ef2c0)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -455,8 +655,8 @@ name: (string) (len=25) "LnurlWithdrawInfoResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000037140)({ - authType: (*main.supportedAuth)(0xc000422090)({ + opts: (*main.methodOptions)(0xc00054d920)({ + authType: (*main.supportedAuth)(0xc00054e660)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -470,11 +670,10 @@ }, query: ([]string) (len=1 cap=1) { (string) (len=2) "k1" - }, - nostr: (bool) false + } }) }), - (*main.Method)(0xc000070910)({ + (*main.Method)(0xc0002ef360)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -484,8 +683,8 @@ name: (string) (len=5) "Empty", hasZeroFields: (bool) true }, - opts: (*main.methodOptions)(0xc0000374a0)({ - authType: (*main.supportedAuth)(0xc0004221e0)({ + opts: (*main.methodOptions)(0xc00054dc80)({ + authType: (*main.supportedAuth)(0xc00054e7e0)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -500,11 +699,10 @@ query: ([]string) (len=2 cap=2) { (string) (len=2) "k1", (string) (len=2) "pr" - }, - nostr: (bool) false + } }) }), - (*main.Method)(0xc0000709b0)({ + (*main.Method)(0xc0002ef400)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -514,8 +712,8 @@ name: (string) (len=20) "LnurlPayInfoResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000037800)({ - authType: (*main.supportedAuth)(0xc000422300)({ + opts: (*main.methodOptions)(0xc000552000)({ + authType: (*main.supportedAuth)(0xc00054e930)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -529,11 +727,10 @@ }, query: ([]string) (len=1 cap=1) { (string) (len=2) "k1" - }, - nostr: (bool) false + } }) }), - (*main.Method)(0xc000070a50)({ + (*main.Method)(0xc0002ef4a0)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -543,8 +740,8 @@ name: (string) (len=22) "HandleLnurlPayResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000037b60)({ - authType: (*main.supportedAuth)(0xc000422450)({ + opts: (*main.methodOptions)(0xc000552360)({ + authType: (*main.supportedAuth)(0xc00054eab0)({ id: (string) (len=5) "guest", name: (string) (len=5) "Guest", encrypted: (bool) false, @@ -559,11 +756,10 @@ query: ([]string) (len=2 cap=2) { (string) (len=2) "k1", (string) (len=6) "amount" - }, - nostr: (bool) false + } }) }), - (*main.Method)(0xc000070af0)({ + (*main.Method)(0xc0002ef540)({ in: (main.MethodMessage) { name: (string) (len=5) "Empty", hasZeroFields: (bool) true @@ -573,8 +769,8 @@ name: (string) (len=17) "LnurlLinkResponse", hasZeroFields: (bool) false }, - opts: (*main.methodOptions)(0xc000037d40)({ - authType: (*main.supportedAuth)(0xc0004224e0)({ + opts: (*main.methodOptions)(0xc000552540)({ + authType: (*main.supportedAuth)(0xc00054eb70)({ id: (string) (len=4) "user", name: (string) (len=4) "User", encrypted: (bool) false, @@ -587,14 +783,13 @@ route: (string) (len=27) "/api/user/lnurl_channel/url", params: ([]string) }, - query: ([]string) , - nostr: (bool) true + query: ([]string) }) }) } ([]*main.Enum) (len=2 cap=2) { - (*main.Enum)(0xc000030de0)({ + (*main.Enum)(0xc0005449c0)({ name: (string) (len=11) "AddressType", values: ([]main.EnumValue) (len=3 cap=4) { (main.EnumValue) { @@ -611,9 +806,9 @@ } } }), - (*main.Enum)(0xc000030e40)({ + (*main.Enum)(0xc000544a20)({ name: (string) (len=17) "UserOperationType", - values: ([]main.EnumValue) (len=4 cap=4) { + values: ([]main.EnumValue) (len=6 cap=8) { (main.EnumValue) { number: (int64) 0, name: (string) (len=11) "INCOMING_TX" @@ -629,215 +824,25 @@ (main.EnumValue) { number: (int64) 3, name: (string) (len=16) "OUTGOING_INVOICE" + }, + (main.EnumValue) { + number: (int64) 4, + name: (string) (len=21) "OUTGOING_USER_TO_USER" + }, + (main.EnumValue) { + number: (int64) 5, + name: (string) (len=21) "INCOMING_USER_TO_USER" } } }) } -(map[string]*main.Message) (len=32) { - (string) (len=15) "AddUserResponse": (*main.Message)(0xc000215280)({ - fullName: (string) (len=15) "AddUserResponse", - name: (string) (len=15) "AddUserResponse", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030840)({ - name: (string) (len=6) "userId", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030870)({ - name: (string) (len=9) "authToken", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=16) "AuthUserResponse": (*main.Message)(0xc000215300)({ - fullName: (string) (len=16) "AuthUserResponse", - name: (string) (len=16) "AuthUserResponse", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030900)({ - name: (string) (len=6) "userId", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030930)({ - name: (string) (len=9) "authToken", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=25) "GetUserOperationsResponse": (*main.Message)(0xc000215440)({ - fullName: (string) (len=25) "GetUserOperationsResponse", - name: (string) (len=25) "GetUserOperationsResponse", - fields: ([]*main.Field) (len=4 cap=4) { - (*main.Field)(0xc000030bd0)({ - name: (string) (len=31) "latestOutgoingInvoiceOperations", - kind: (string) (len=14) "UserOperations", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) true, - isOptional: (bool) false - }), - (*main.Field)(0xc000030c00)({ - name: (string) (len=31) "latestIncomingInvoiceOperations", - kind: (string) (len=14) "UserOperations", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) true, - isOptional: (bool) false - }), - (*main.Field)(0xc000030c30)({ - name: (string) (len=26) "latestOutgoingTxOperations", - kind: (string) (len=14) "UserOperations", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) true, - isOptional: (bool) false - }), - (*main.Field)(0xc000030c60)({ - name: (string) (len=26) "latestIncomingTxOperations", - kind: (string) (len=14) "UserOperations", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) true, - isOptional: (bool) false - }) - } - }), - (string) (len=17) "LndGetInfoRequest": (*main.Message)(0xc000214580)({ - fullName: (string) (len=17) "LndGetInfoRequest", - name: (string) (len=17) "LndGetInfoRequest", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc000030090)({ - name: (string) (len=6) "nodeId", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=18) "LndGetInfoResponse": (*main.Message)(0xc0002145c0)({ - fullName: (string) (len=18) "LndGetInfoResponse", - name: (string) (len=18) "LndGetInfoResponse", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc0000300c0)({ - name: (string) (len=5) "alias", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=25) "LnurlWithdrawInfoResponse": (*main.Message)(0xc000214ec0)({ - fullName: (string) (len=25) "LnurlWithdrawInfoResponse", - name: (string) (len=25) "LnurlWithdrawInfoResponse", - fields: ([]*main.Field) (len=8 cap=8) { - (*main.Field)(0xc0000304e0)({ - name: (string) (len=3) "tag", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030510)({ - name: (string) (len=8) "callback", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030540)({ - name: (string) (len=2) "k1", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030570)({ - name: (string) (len=18) "defaultDescription", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000305a0)({ - name: (string) (len=15) "minWithdrawable", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000305d0)({ - name: (string) (len=15) "maxWithdrawable", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030600)({ - name: (string) (len=12) "balanceCheck", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030630)({ - name: (string) (len=7) "payLink", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=25) "GetProductBuyLinkResponse": (*main.Message)(0xc000215500)({ +(map[string]*main.Message) (len=43) { + (string) (len=25) "GetProductBuyLinkResponse": (*main.Message)(0xc00013adc0)({ fullName: (string) (len=25) "GetProductBuyLinkResponse", name: (string) (len=25) "GetProductBuyLinkResponse", fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc000030d80)({ + (*main.Field)(0xc000544960)({ name: (string) (len=4) "link", kind: (string) (len=6) "string", isMap: (bool) false, @@ -848,21 +853,12 @@ }) } }), - (string) (len=17) "PayInvoiceRequest": (*main.Message)(0xc000214c40)({ - fullName: (string) (len=17) "PayInvoiceRequest", - name: (string) (len=17) "PayInvoiceRequest", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030300)({ - name: (string) (len=7) "invoice", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030330)({ - name: (string) (len=6) "amount", + (string) (len=17) "LndGetInfoRequest": (*main.Message)(0xc00013a2c0)({ + fullName: (string) (len=17) "LndGetInfoRequest", + name: (string) (len=17) "LndGetInfoRequest", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc0000a5890)({ + name: (string) (len=6) "nodeId", kind: (string) (len=5) "int64", isMap: (bool) false, isArray: (bool) false, @@ -872,86 +868,11 @@ }) } }), - (string) (len=14) "AddUserRequest": (*main.Message)(0xc000215240)({ - fullName: (string) (len=14) "AddUserRequest", - name: (string) (len=14) "AddUserRequest", - fields: ([]*main.Field) (len=3 cap=4) { - (*main.Field)(0xc0000307b0)({ - name: (string) (len=11) "callbackUrl", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000307e0)({ - name: (string) (len=4) "name", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030810)({ - name: (string) (len=6) "secret", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=13) "UserOperation": (*main.Message)(0xc0002153c0)({ - fullName: (string) (len=13) "UserOperation", - name: (string) (len=13) "UserOperation", - fields: ([]*main.Field) (len=4 cap=4) { - (*main.Field)(0xc000030a80)({ - name: (string) (len=10) "paidAtUnix", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030ab0)({ - name: (string) (len=4) "type", - kind: (string) (len=17) "UserOperationType", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) true, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030ae0)({ - name: (string) (len=7) "inbound", - kind: (string) (len=4) "bool", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030b10)({ - name: (string) (len=6) "amount", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=17) "NewAddressRequest": (*main.Message)(0xc000214880)({ + (string) (len=17) "NewAddressRequest": (*main.Message)(0xc00013a600)({ fullName: (string) (len=17) "NewAddressRequest", name: (string) (len=17) "NewAddressRequest", fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc0000300f0)({ + (*main.Field)(0xc00024acc0)({ name: (string) (len=11) "addressType", kind: (string) (len=11) "AddressType", isMap: (bool) false, @@ -962,11 +883,11 @@ }) } }), - (string) (len=18) "NewAddressResponse": (*main.Message)(0xc0002148c0)({ + (string) (len=18) "NewAddressResponse": (*main.Message)(0xc00013a640)({ fullName: (string) (len=18) "NewAddressResponse", name: (string) (len=18) "NewAddressResponse", fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc000030120)({ + (*main.Field)(0xc00024acf0)({ name: (string) (len=7) "address", kind: (string) (len=6) "string", isMap: (bool) false, @@ -977,398 +898,11 @@ }) } }), - (string) (len=18) "PayAddressResponse": (*main.Message)(0xc0002149c0)({ - fullName: (string) (len=18) "PayAddressResponse", - name: (string) (len=18) "PayAddressResponse", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc0000301e0)({ - name: (string) (len=4) "txId", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=21) "DecodeInvoiceResponse": (*main.Message)(0xc000214b40)({ - fullName: (string) (len=21) "DecodeInvoiceResponse", - name: (string) (len=21) "DecodeInvoiceResponse", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc0000302d0)({ - name: (string) (len=6) "amount", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=20) "LnurlPayInfoResponse": (*main.Message)(0xc0002150c0)({ - fullName: (string) (len=20) "LnurlPayInfoResponse", - name: (string) (len=20) "LnurlPayInfoResponse", - fields: ([]*main.Field) (len=5 cap=8) { - (*main.Field)(0xc000030660)({ - name: (string) (len=3) "tag", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030690)({ - name: (string) (len=8) "callback", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000306c0)({ - name: (string) (len=11) "maxSendable", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000306f0)({ - name: (string) (len=11) "minSendable", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030720)({ - name: (string) (len=8) "metadata", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=18) "PayInvoiceResponse": (*main.Message)(0xc000214d00)({ - fullName: (string) (len=18) "PayInvoiceResponse", - name: (string) (len=18) "PayInvoiceResponse", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc000030360)({ - name: (string) (len=8) "preimage", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=19) "OpenChannelResponse": (*main.Message)(0xc000214e00)({ - fullName: (string) (len=19) "OpenChannelResponse", - name: (string) (len=19) "OpenChannelResponse", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc000030450)({ - name: (string) (len=9) "channelId", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=8) "UserInfo": (*main.Message)(0xc000215340)({ - fullName: (string) (len=8) "UserInfo", - name: (string) (len=8) "UserInfo", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030960)({ - name: (string) (len=6) "userId", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030990)({ - name: (string) (len=7) "balance", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=24) "GetUserOperationsRequest": (*main.Message)(0xc000215380)({ - fullName: (string) (len=24) "GetUserOperationsRequest", - name: (string) (len=24) "GetUserOperationsRequest", - fields: ([]*main.Field) (len=4 cap=4) { - (*main.Field)(0xc0000309c0)({ - name: (string) (len=21) "latestIncomingInvoice", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000309f0)({ - name: (string) (len=21) "latestOutgoingInvoice", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030a20)({ - name: (string) (len=16) "latestIncomingTx", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030a50)({ - name: (string) (len=16) "latestOutgoingTx", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=17) "AddProductRequest": (*main.Message)(0xc000215480)({ - fullName: (string) (len=17) "AddProductRequest", - name: (string) (len=17) "AddProductRequest", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030c90)({ - name: (string) (len=4) "name", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030cc0)({ - name: (string) (len=10) "price_sats", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=7) "Product": (*main.Message)(0xc0002154c0)({ - fullName: (string) (len=7) "Product", - name: (string) (len=7) "Product", - fields: ([]*main.Field) (len=3 cap=4) { - (*main.Field)(0xc000030cf0)({ - name: (string) (len=2) "id", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030d20)({ - name: (string) (len=4) "name", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030d50)({ - name: (string) (len=10) "price_sats", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=25) "EncryptionExchangeRequest": (*main.Message)(0xc0002144c0)({ - fullName: (string) (len=25) "EncryptionExchangeRequest", - name: (string) (len=25) "EncryptionExchangeRequest", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030030)({ - name: (string) (len=9) "publicKey", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030060)({ - name: (string) (len=8) "deviceId", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=17) "NewInvoiceRequest": (*main.Message)(0xc000214a00)({ - fullName: (string) (len=17) "NewInvoiceRequest", - name: (string) (len=17) "NewInvoiceRequest", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030210)({ - name: (string) (len=10) "amountSats", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030240)({ - name: (string) (len=4) "memo", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=17) "LnurlLinkResponse": (*main.Message)(0xc000214e40)({ - fullName: (string) (len=17) "LnurlLinkResponse", - name: (string) (len=17) "LnurlLinkResponse", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030480)({ - name: (string) (len=5) "lnurl", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000304b0)({ - name: (string) (len=2) "k1", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=22) "HandleLnurlPayResponse": (*main.Message)(0xc000215200)({ - fullName: (string) (len=22) "HandleLnurlPayResponse", - name: (string) (len=22) "HandleLnurlPayResponse", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc000030750)({ - name: (string) (len=2) "pr", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030780)({ - name: (string) (len=6) "routes", - kind: (string) (len=5) "Empty", - isMap: (bool) false, - isArray: (bool) true, - isEnum: (bool) false, - isMessage: (bool) true, - isOptional: (bool) false - }) - } - }), - (string) (len=15) "AuthUserRequest": (*main.Message)(0xc0002152c0)({ - fullName: (string) (len=15) "AuthUserRequest", - name: (string) (len=15) "AuthUserRequest", - fields: ([]*main.Field) (len=2 cap=2) { - (*main.Field)(0xc0000308a0)({ - name: (string) (len=4) "name", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc0000308d0)({ - name: (string) (len=6) "secret", - kind: (string) (len=6) "string", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }) - } - }), - (string) (len=14) "UserOperations": (*main.Message)(0xc000215400)({ - fullName: (string) (len=14) "UserOperations", - name: (string) (len=14) "UserOperations", - fields: ([]*main.Field) (len=3 cap=4) { - (*main.Field)(0xc000030b40)({ - name: (string) (len=9) "fromIndex", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030b70)({ - name: (string) (len=7) "toIndex", - kind: (string) (len=5) "int64", - isMap: (bool) false, - isArray: (bool) false, - isEnum: (bool) false, - isMessage: (bool) false, - isOptional: (bool) false - }), - (*main.Field)(0xc000030ba0)({ - name: (string) (len=10) "operations", - kind: (string) (len=13) "UserOperation", - isMap: (bool) false, - isArray: (bool) true, - isEnum: (bool) false, - isMessage: (bool) true, - isOptional: (bool) false - }) - } - }), - (string) (len=17) "PayAddressRequest": (*main.Message)(0xc000214980)({ + (string) (len=17) "PayAddressRequest": (*main.Message)(0xc00013a680)({ fullName: (string) (len=17) "PayAddressRequest", name: (string) (len=17) "PayAddressRequest", fields: ([]*main.Field) (len=3 cap=4) { - (*main.Field)(0xc000030150)({ + (*main.Field)(0xc00024b350)({ name: (string) (len=7) "address", kind: (string) (len=6) "string", isMap: (bool) false, @@ -1377,7 +911,7 @@ isMessage: (bool) false, isOptional: (bool) false }), - (*main.Field)(0xc000030180)({ + (*main.Field)(0xc00024b380)({ name: (string) (len=9) "amoutSats", kind: (string) (len=5) "int64", isMap: (bool) false, @@ -1386,7 +920,7 @@ isMessage: (bool) false, isOptional: (bool) false }), - (*main.Field)(0xc0000301b0)({ + (*main.Field)(0xc00024b3b0)({ name: (string) (len=10) "targetConf", kind: (string) (len=5) "int64", isMap: (bool) false, @@ -1397,11 +931,673 @@ }) } }), - (string) (len=18) "OpenChannelRequest": (*main.Message)(0xc000214dc0)({ + (string) (len=8) "UserInfo": (*main.Message)(0xc00013ab80)({ + fullName: (string) (len=8) "UserInfo", + name: (string) (len=8) "UserInfo", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc000544480)({ + name: (string) (len=6) "userId", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005444b0)({ + name: (string) (len=7) "balance", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=24) "AddAppUserInvoiceRequest": (*main.Message)(0xc00013a480)({ + fullName: (string) (len=24) "AddAppUserInvoiceRequest", + name: (string) (len=24) "AddAppUserInvoiceRequest", + fields: ([]*main.Field) (len=4 cap=4) { + (*main.Field)(0xc00024a090)({ + name: (string) (len=19) "receiver_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a360)({ + name: (string) (len=16) "payer_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a390)({ + name: (string) (len=17) "http_callback_url", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a3c0)({ + name: (string) (len=11) "invoice_req", + kind: (string) (len=17) "NewInvoiceRequest", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }) + } + }), + (string) (len=17) "GetAppUserRequest": (*main.Message)(0xc00013a4c0)({ + fullName: (string) (len=17) "GetAppUserRequest", + name: (string) (len=17) "GetAppUserRequest", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc00024a3f0)({ + name: (string) (len=15) "user_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=15) "AuthUserRequest": (*main.Message)(0xc00013ab00)({ + fullName: (string) (len=15) "AuthUserRequest", + name: (string) (len=15) "AuthUserRequest", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc0005443c0)({ + name: (string) (len=4) "name", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005443f0)({ + name: (string) (len=6) "secret", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=14) "UserOperations": (*main.Message)(0xc00013ac80)({ + fullName: (string) (len=14) "UserOperations", + name: (string) (len=14) "UserOperations", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc0005446c0)({ + name: (string) (len=9) "fromIndex", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005446f0)({ + name: (string) (len=7) "toIndex", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544720)({ + name: (string) (len=10) "operations", + kind: (string) (len=13) "UserOperation", + isMap: (bool) false, + isArray: (bool) true, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }) + } + }), + (string) (len=5) "Empty": (*main.Message)(0xc00013a240)({ + fullName: (string) (len=5) "Empty", + name: (string) (len=5) "Empty", + fields: ([]*main.Field) + }), + (string) (len=25) "PayAppUserInvoiceResponse": (*main.Message)(0xc00013a540)({ + fullName: (string) (len=25) "PayAppUserInvoiceResponse", + name: (string) (len=25) "PayAppUserInvoiceResponse", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc00024a600)({ + name: (string) (len=8) "preimage", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a7b0)({ + name: (string) (len=11) "amount_paid", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=19) "OpenChannelResponse": (*main.Message)(0xc00013a8c0)({ + fullName: (string) (len=19) "OpenChannelResponse", + name: (string) (len=19) "OpenChannelResponse", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc0002f8660)({ + name: (string) (len=9) "channelId", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=15) "AddUserResponse": (*main.Message)(0xc00013aac0)({ + fullName: (string) (len=15) "AddUserResponse", + name: (string) (len=15) "AddUserResponse", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc000544360)({ + name: (string) (len=6) "userId", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544390)({ + name: (string) (len=9) "authToken", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=17) "PayInvoiceRequest": (*main.Message)(0xc00013a800)({ + fullName: (string) (len=17) "PayInvoiceRequest", + name: (string) (len=17) "PayInvoiceRequest", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc00024b980)({ + name: (string) (len=7) "invoice", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024b9b0)({ + name: (string) (len=6) "amount", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=18) "PayInvoiceResponse": (*main.Message)(0xc00013a840)({ + fullName: (string) (len=18) "PayInvoiceResponse", + name: (string) (len=18) "PayInvoiceResponse", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc00024b9e0)({ + name: (string) (len=8) "preimage", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024bb30)({ + name: (string) (len=11) "amount_paid", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=25) "GetUserOperationsResponse": (*main.Message)(0xc00013ad00)({ + fullName: (string) (len=25) "GetUserOperationsResponse", + name: (string) (len=25) "GetUserOperationsResponse", + fields: ([]*main.Field) (len=6 cap=8) { + (*main.Field)(0xc000544750)({ + name: (string) (len=31) "latestOutgoingInvoiceOperations", + kind: (string) (len=14) "UserOperations", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }), + (*main.Field)(0xc000544780)({ + name: (string) (len=31) "latestIncomingInvoiceOperations", + kind: (string) (len=14) "UserOperations", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }), + (*main.Field)(0xc0005447b0)({ + name: (string) (len=26) "latestOutgoingTxOperations", + kind: (string) (len=14) "UserOperations", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }), + (*main.Field)(0xc0005447e0)({ + name: (string) (len=26) "latestIncomingTxOperations", + kind: (string) (len=14) "UserOperations", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }), + (*main.Field)(0xc000544810)({ + name: (string) (len=32) "latestOutgoingUserToUserPayemnts", + kind: (string) (len=14) "UserOperations", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }), + (*main.Field)(0xc000544840)({ + name: (string) (len=32) "latestIncomingUserToUserPayemnts", + kind: (string) (len=14) "UserOperations", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }) + } + }), + (string) (len=18) "LndGetInfoResponse": (*main.Message)(0xc00013a300)({ + fullName: (string) (len=18) "LndGetInfoResponse", + name: (string) (len=18) "LndGetInfoResponse", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc0000a58c0)({ + name: (string) (len=5) "alias", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=17) "AddAppUserRequest": (*main.Message)(0xc00013a3c0)({ + fullName: (string) (len=17) "AddAppUserRequest", + name: (string) (len=17) "AddAppUserRequest", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc0000a5b30)({ + name: (string) (len=10) "identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0000a5b60)({ + name: (string) (len=14) "fail_if_exists", + kind: (string) (len=4) "bool", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0000a5dd0)({ + name: (string) (len=7) "balance", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=20) "AddAppInvoiceRequest": (*main.Message)(0xc00013a440)({ + fullName: (string) (len=20) "AddAppInvoiceRequest", + name: (string) (len=20) "AddAppInvoiceRequest", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc00024a000)({ + name: (string) (len=16) "payer_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a030)({ + name: (string) (len=17) "http_callback_url", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a060)({ + name: (string) (len=11) "invoice_req", + kind: (string) (len=17) "NewInvoiceRequest", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }) + } + }), + (string) (len=18) "NewInvoiceResponse": (*main.Message)(0xc00013a740)({ + fullName: (string) (len=18) "NewInvoiceResponse", + name: (string) (len=18) "NewInvoiceResponse", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc00024b530)({ + name: (string) (len=7) "invoice", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=20) "DecodeInvoiceRequest": (*main.Message)(0xc00013a780)({ + fullName: (string) (len=20) "DecodeInvoiceRequest", + name: (string) (len=20) "DecodeInvoiceRequest", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc00024b560)({ + name: (string) (len=7) "invoice", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=14) "AddUserRequest": (*main.Message)(0xc00013aa80)({ + fullName: (string) (len=14) "AddUserRequest", + name: (string) (len=14) "AddUserRequest", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc0005442d0)({ + name: (string) (len=11) "callbackUrl", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544300)({ + name: (string) (len=4) "name", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544330)({ + name: (string) (len=6) "secret", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=14) "AddAppResponse": (*main.Message)(0xc00013a380)({ + fullName: (string) (len=14) "AddAppResponse", + name: (string) (len=14) "AddAppResponse", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc0000a5920)({ + name: (string) (len=4) "name", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0000a5ad0)({ + name: (string) (len=2) "id", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0000a5b00)({ + name: (string) (len=10) "auth_token", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=24) "PayAppUserInvoiceRequest": (*main.Message)(0xc00013a500)({ + fullName: (string) (len=24) "PayAppUserInvoiceRequest", + name: (string) (len=24) "PayAppUserInvoiceRequest", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc00024a570)({ + name: (string) (len=15) "user_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a5a0)({ + name: (string) (len=7) "invoice", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a5d0)({ + name: (string) (len=6) "amount", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=34) "SendAppUserToAppUserPaymentRequest": (*main.Message)(0xc00013a580)({ + fullName: (string) (len=34) "SendAppUserToAppUserPaymentRequest", + name: (string) (len=34) "SendAppUserToAppUserPaymentRequest", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc00024a7e0)({ + name: (string) (len=20) "from_user_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a810)({ + name: (string) (len=18) "to_user_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024a840)({ + name: (string) (len=6) "amount", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=21) "DecodeInvoiceResponse": (*main.Message)(0xc00013a7c0)({ + fullName: (string) (len=21) "DecodeInvoiceResponse", + name: (string) (len=21) "DecodeInvoiceResponse", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc00024b950)({ + name: (string) (len=6) "amount", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=7) "Product": (*main.Message)(0xc00013ad80)({ + fullName: (string) (len=7) "Product", + name: (string) (len=7) "Product", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc0005448d0)({ + name: (string) (len=2) "id", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544900)({ + name: (string) (len=4) "name", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544930)({ + name: (string) (len=10) "price_sats", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=25) "EncryptionExchangeRequest": (*main.Message)(0xc00013a280)({ + fullName: (string) (len=25) "EncryptionExchangeRequest", + name: (string) (len=25) "EncryptionExchangeRequest", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc0000a5830)({ + name: (string) (len=9) "publicKey", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0000a5860)({ + name: (string) (len=8) "deviceId", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=7) "AppUser": (*main.Message)(0xc00013a400)({ + fullName: (string) (len=7) "AppUser", + name: (string) (len=7) "AppUser", + fields: ([]*main.Field) (len=3 cap=4) { + (*main.Field)(0xc0000a5e00)({ + name: (string) (len=10) "identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0000a5e30)({ + name: (string) (len=4) "info", + kind: (string) (len=8) "UserInfo", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }), + (*main.Field)(0xc0000a5e60)({ + name: (string) (len=16) "max_withdrawable", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=18) "OpenChannelRequest": (*main.Message)(0xc00013a880)({ fullName: (string) (len=18) "OpenChannelRequest", name: (string) (len=18) "OpenChannelRequest", fields: ([]*main.Field) (len=4 cap=4) { - (*main.Field)(0xc000030390)({ + (*main.Field)(0xc00024bb60)({ name: (string) (len=11) "destination", kind: (string) (len=6) "string", isMap: (bool) false, @@ -1410,7 +1606,7 @@ isMessage: (bool) false, isOptional: (bool) false }), - (*main.Field)(0xc0000303c0)({ + (*main.Field)(0xc00024bb90)({ name: (string) (len=13) "fundingAmount", kind: (string) (len=5) "int64", isMap: (bool) false, @@ -1419,7 +1615,7 @@ isMessage: (bool) false, isOptional: (bool) false }), - (*main.Field)(0xc0000303f0)({ + (*main.Field)(0xc00024bbc0)({ name: (string) (len=10) "pushAmount", kind: (string) (len=5) "int64", isMap: (bool) false, @@ -1428,7 +1624,7 @@ isMessage: (bool) false, isOptional: (bool) false }), - (*main.Field)(0xc000030420)({ + (*main.Field)(0xc0002f8630)({ name: (string) (len=12) "closeAddress", kind: (string) (len=6) "string", isMap: (bool) false, @@ -1439,12 +1635,135 @@ }) } }), - (string) (len=20) "DecodeInvoiceRequest": (*main.Message)(0xc000214b00)({ - fullName: (string) (len=20) "DecodeInvoiceRequest", - name: (string) (len=20) "DecodeInvoiceRequest", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc0000302a0)({ - name: (string) (len=7) "invoice", + (string) (len=24) "GetUserOperationsRequest": (*main.Message)(0xc00013ac00)({ + fullName: (string) (len=24) "GetUserOperationsRequest", + name: (string) (len=24) "GetUserOperationsRequest", + fields: ([]*main.Field) (len=6 cap=8) { + (*main.Field)(0xc0005444e0)({ + name: (string) (len=21) "latestIncomingInvoice", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544510)({ + name: (string) (len=21) "latestOutgoingInvoice", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544540)({ + name: (string) (len=16) "latestIncomingTx", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544570)({ + name: (string) (len=16) "latestOutgoingTx", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005445a0)({ + name: (string) (len=31) "latestIncomingUserToUserPayment", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005445d0)({ + name: (string) (len=31) "latestOutgoingUserToUserPayment", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=25) "LnurlWithdrawInfoResponse": (*main.Message)(0xc00013a980)({ + fullName: (string) (len=25) "LnurlWithdrawInfoResponse", + name: (string) (len=25) "LnurlWithdrawInfoResponse", + fields: ([]*main.Field) (len=8 cap=8) { + (*main.Field)(0xc000544000)({ + name: (string) (len=3) "tag", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544030)({ + name: (string) (len=8) "callback", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544060)({ + name: (string) (len=2) "k1", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544090)({ + name: (string) (len=18) "defaultDescription", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005440c0)({ + name: (string) (len=15) "minWithdrawable", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005440f0)({ + name: (string) (len=15) "maxWithdrawable", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544120)({ + name: (string) (len=12) "balanceCheck", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544150)({ + name: (string) (len=7) "payLink", kind: (string) (len=6) "string", isMap: (bool) false, isArray: (bool) false, @@ -1454,29 +1773,276 @@ }) } }), - (string) (len=5) "Empty": (*main.Message)(0xc000214440)({ - fullName: (string) (len=5) "Empty", - name: (string) (len=5) "Empty", - fields: ([]*main.Field) - }), - (string) (len=18) "NewInvoiceResponse": (*main.Message)(0xc000214ac0)({ - fullName: (string) (len=18) "NewInvoiceResponse", - name: (string) (len=18) "NewInvoiceResponse", - fields: ([]*main.Field) (len=1 cap=1) { - (*main.Field)(0xc000030270)({ - name: (string) (len=7) "invoice", + (string) (len=20) "LnurlPayInfoResponse": (*main.Message)(0xc00013aa00)({ + fullName: (string) (len=20) "LnurlPayInfoResponse", + name: (string) (len=20) "LnurlPayInfoResponse", + fields: ([]*main.Field) (len=5 cap=8) { + (*main.Field)(0xc000544180)({ + name: (string) (len=3) "tag", kind: (string) (len=6) "string", isMap: (bool) false, isArray: (bool) false, isEnum: (bool) false, isMessage: (bool) false, isOptional: (bool) false + }), + (*main.Field)(0xc0005441b0)({ + name: (string) (len=8) "callback", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005441e0)({ + name: (string) (len=11) "maxSendable", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544210)({ + name: (string) (len=11) "minSendable", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544240)({ + name: (string) (len=8) "metadata", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=22) "HandleLnurlPayResponse": (*main.Message)(0xc00013aa40)({ + fullName: (string) (len=22) "HandleLnurlPayResponse", + name: (string) (len=22) "HandleLnurlPayResponse", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc000544270)({ + name: (string) (len=2) "pr", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005442a0)({ + name: (string) (len=6) "routes", + kind: (string) (len=5) "Empty", + isMap: (bool) false, + isArray: (bool) true, + isEnum: (bool) false, + isMessage: (bool) true, + isOptional: (bool) false + }) + } + }), + (string) (len=13) "AddAppRequest": (*main.Message)(0xc00013a340)({ + fullName: (string) (len=13) "AddAppRequest", + name: (string) (len=13) "AddAppRequest", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc0000a58f0)({ + name: (string) (len=4) "name", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=30) "SendAppUserToAppPaymentRequest": (*main.Message)(0xc00013a5c0)({ + fullName: (string) (len=30) "SendAppUserToAppPaymentRequest", + name: (string) (len=30) "SendAppUserToAppPaymentRequest", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc00024ac60)({ + name: (string) (len=20) "from_user_identifier", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024ac90)({ + name: (string) (len=6) "amount", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=18) "PayAddressResponse": (*main.Message)(0xc00013a6c0)({ + fullName: (string) (len=18) "PayAddressResponse", + name: (string) (len=18) "PayAddressResponse", + fields: ([]*main.Field) (len=1 cap=1) { + (*main.Field)(0xc00024b3e0)({ + name: (string) (len=4) "txId", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=17) "NewInvoiceRequest": (*main.Message)(0xc00013a700)({ + fullName: (string) (len=17) "NewInvoiceRequest", + name: (string) (len=17) "NewInvoiceRequest", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc00024b4d0)({ + name: (string) (len=10) "amountSats", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc00024b500)({ + name: (string) (len=4) "memo", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=17) "LnurlLinkResponse": (*main.Message)(0xc00013a900)({ + fullName: (string) (len=17) "LnurlLinkResponse", + name: (string) (len=17) "LnurlLinkResponse", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc0002f9e90)({ + name: (string) (len=5) "lnurl", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0002f9ec0)({ + name: (string) (len=2) "k1", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=16) "AuthUserResponse": (*main.Message)(0xc00013ab40)({ + fullName: (string) (len=16) "AuthUserResponse", + name: (string) (len=16) "AuthUserResponse", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc000544420)({ + name: (string) (len=6) "userId", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544450)({ + name: (string) (len=9) "authToken", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=13) "UserOperation": (*main.Message)(0xc00013ac40)({ + fullName: (string) (len=13) "UserOperation", + name: (string) (len=13) "UserOperation", + fields: ([]*main.Field) (len=4 cap=4) { + (*main.Field)(0xc000544600)({ + name: (string) (len=10) "paidAtUnix", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544630)({ + name: (string) (len=4) "type", + kind: (string) (len=17) "UserOperationType", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) true, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544660)({ + name: (string) (len=7) "inbound", + kind: (string) (len=4) "bool", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc000544690)({ + name: (string) (len=6) "amount", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }) + } + }), + (string) (len=17) "AddProductRequest": (*main.Message)(0xc00013ad40)({ + fullName: (string) (len=17) "AddProductRequest", + name: (string) (len=17) "AddProductRequest", + fields: ([]*main.Field) (len=2 cap=2) { + (*main.Field)(0xc000544870)({ + name: (string) (len=4) "name", + kind: (string) (len=6) "string", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false + }), + (*main.Field)(0xc0005448a0)({ + name: (string) (len=10) "price_sats", + kind: (string) (len=5) "int64", + isMap: (bool) false, + isArray: (bool) false, + isEnum: (bool) false, + isMessage: (bool) false, + isOptional: (bool) false }) } }) } -parsing file: structs 32 +parsing file: structs 43 parsing file: methods 2 --> [{guest Guest false map[]} {user User false map[user_id:string]} {admin Admin true map[admin_id:string]}] +-> [{guest Guest false map[]} {user User false map[user_id:string]} {admin Admin false map[admin_id:string]} {app App false map[app_id:string]}] diff --git a/proto/autogenerated/ts/express_server.ts b/proto/autogenerated/ts/express_server.ts index ab26395e..443db085 100644 --- a/proto/autogenerated/ts/express_server.ts +++ b/proto/autogenerated/ts/express_server.ts @@ -7,12 +7,13 @@ export type Logger = { log: (v: any) => void, error: (v: any) => void } export type ServerOptions = { allowCors?: true staticFiles?: string - allowNotImplementedMethods?: true + allowNotImplementedMethods?: number logger?: Logger throwErrors?: true GuestAuthGuard: (authorizationHeader?: string) => Promise UserAuthGuard: (authorizationHeader?: string) => Promise AdminAuthGuard: (authorizationHeader?: string) => Promise + AppAuthGuard: (authorizationHeader?: string) => Promise decryptCallback: (encryptionDeviceId: string, body: any) => Promise encryptCallback: (encryptionDeviceId: string, plain: any) => Promise } @@ -51,19 +52,129 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => { } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } }) if (!opts.allowNotImplementedMethods && !methods.LndGetInfo) throw new Error('method: LndGetInfo is not implemented') - app.post('/api/lnd/getinfo', async (req, res) => { + app.post('/api/admin/lnd/getinfo', async (req, res) => { try { if (!methods.LndGetInfo) throw new Error('method: LndGetInfo is not implemented') const authContext = await opts.AdminAuthGuard(req.headers['authorization']) - const encryptionDeviceId = req.headers['x-e2ee-device-id-x'] - if (typeof encryptionDeviceId !== 'string' || encryptionDeviceId === '') throw new Error('invalid encryption header provided') - const request = await opts.decryptCallback(encryptionDeviceId, req.body) + const request = req.body const error = Types.LndGetInfoRequestValidate(request) if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) const query = req.query const params = req.params const response = await methods.LndGetInfo({ ...authContext, ...query, ...params }, request) - res.json({status: 'OK', ...await opts.encryptCallback(encryptionDeviceId, response)}) + res.json({status: 'OK', ...response}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.AddApp) throw new Error('method: AddApp is not implemented') + app.post('/api/admin/app/add', async (req, res) => { + try { + if (!methods.AddApp) throw new Error('method: AddApp is not implemented') + const authContext = await opts.AdminAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.AddAppRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + const response = await methods.AddApp({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK', ...response}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.AddAppUser) throw new Error('method: AddAppUser is not implemented') + app.post('/api/app/user/add', async (req, res) => { + try { + if (!methods.AddAppUser) throw new Error('method: AddAppUser is not implemented') + const authContext = await opts.AppAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.AddAppUserRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + const response = await methods.AddAppUser({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK', ...response}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.AddAppInvoice) throw new Error('method: AddAppInvoice is not implemented') + app.post('/api/app/add/invoice', async (req, res) => { + try { + if (!methods.AddAppInvoice) throw new Error('method: AddAppInvoice is not implemented') + const authContext = await opts.AppAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.AddAppInvoiceRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + const response = await methods.AddAppInvoice({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK', ...response}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.AddAppUserInvoice) throw new Error('method: AddAppUserInvoice is not implemented') + app.post('/api/app/user/add/invoice', async (req, res) => { + try { + if (!methods.AddAppUserInvoice) throw new Error('method: AddAppUserInvoice is not implemented') + const authContext = await opts.AppAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.AddAppUserInvoiceRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + const response = await methods.AddAppUserInvoice({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK', ...response}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.GetAppUser) throw new Error('method: GetAppUser is not implemented') + app.post('/api/app/user/get', async (req, res) => { + try { + if (!methods.GetAppUser) throw new Error('method: GetAppUser is not implemented') + const authContext = await opts.AppAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.GetAppUserRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + const response = await methods.GetAppUser({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK', ...response}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.PayAppUserInvoice) throw new Error('method: PayAppUserInvoice is not implemented') + app.post('/api/app/invoice/pay', async (req, res) => { + try { + if (!methods.PayAppUserInvoice) throw new Error('method: PayAppUserInvoice is not implemented') + const authContext = await opts.AppAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.PayAppUserInvoiceRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + const response = await methods.PayAppUserInvoice({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK', ...response}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.SendAppUserToAppUserPayment) throw new Error('method: SendAppUserToAppUserPayment is not implemented') + app.post('/api/app/user/internal/pay', async (req, res) => { + try { + if (!methods.SendAppUserToAppUserPayment) throw new Error('method: SendAppUserToAppUserPayment is not implemented') + const authContext = await opts.AppAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.SendAppUserToAppUserPaymentRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + await methods.SendAppUserToAppUserPayment({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK'}) + } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } + }) + if (!opts.allowNotImplementedMethods && !methods.SendAppUserToAppPayment) throw new Error('method: SendAppUserToAppPayment is not implemented') + app.post('/api/app/internal/pay', async (req, res) => { + try { + if (!methods.SendAppUserToAppPayment) throw new Error('method: SendAppUserToAppPayment is not implemented') + const authContext = await opts.AppAuthGuard(req.headers['authorization']) + const request = req.body + const error = Types.SendAppUserToAppPaymentRequestValidate(request) + if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger) + const query = req.query + const params = req.params + await methods.SendAppUserToAppPayment({ ...authContext, ...query, ...params }, request) + res.json({status: 'OK'}) } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e } }) if (!opts.allowNotImplementedMethods && !methods.AddUser) throw new Error('method: AddUser is not implemented') diff --git a/proto/autogenerated/ts/http_client.ts b/proto/autogenerated/ts/http_client.ts index 844a5355..0beaaad8 100644 --- a/proto/autogenerated/ts/http_client.ts +++ b/proto/autogenerated/ts/http_client.ts @@ -8,6 +8,7 @@ export type ClientParams = { retrieveGuestAuth: () => Promise retrieveUserAuth: () => Promise retrieveAdminAuth: () => Promise + retrieveAppAuth: () => Promise encryptCallback: (plain: any) => Promise decryptCallback: (encrypted: any) => Promise deviceId: string @@ -39,17 +40,123 @@ export default (params: ClientParams) => ({ LndGetInfo: async (request: Types.LndGetInfoRequest): Promise => { const auth = await params.retrieveAdminAuth() if (auth === null) throw new Error('retrieveAdminAuth() returned null') - let finalRoute = '/api/lnd/getinfo' - const { data } = await axios.post(params.baseUrl + finalRoute, await params.encryptCallback(request), { headers: { 'authorization': auth, 'x-e2ee-device-id-x': params.deviceId } }) + let finalRoute = '/api/admin/lnd/getinfo' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'OK') { - const result = await params.decryptCallback(data) + const result = data if(!params.checkResult) return { status: 'OK', ...result } const error = Types.LndGetInfoResponseValidate(result) if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } } return { status: 'ERROR', reason: 'invalid response' } }, + AddApp: async (request: Types.AddAppRequest): Promise => { + const auth = await params.retrieveAdminAuth() + if (auth === null) throw new Error('retrieveAdminAuth() returned null') + let finalRoute = '/api/admin/app/add' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AddAppResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + AddAppUser: async (request: Types.AddAppUserRequest): Promise => { + const auth = await params.retrieveAppAuth() + if (auth === null) throw new Error('retrieveAppAuth() returned null') + let finalRoute = '/api/app/user/add' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AppUserValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + AddAppInvoice: async (request: Types.AddAppInvoiceRequest): Promise => { + const auth = await params.retrieveAppAuth() + if (auth === null) throw new Error('retrieveAppAuth() returned null') + let finalRoute = '/api/app/add/invoice' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.NewInvoiceResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + AddAppUserInvoice: async (request: Types.AddAppUserInvoiceRequest): Promise => { + const auth = await params.retrieveAppAuth() + if (auth === null) throw new Error('retrieveAppAuth() returned null') + let finalRoute = '/api/app/user/add/invoice' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.NewInvoiceResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + GetAppUser: async (request: Types.GetAppUserRequest): Promise => { + const auth = await params.retrieveAppAuth() + if (auth === null) throw new Error('retrieveAppAuth() returned null') + let finalRoute = '/api/app/user/get' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.AppUserValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + PayAppUserInvoice: async (request: Types.PayAppUserInvoiceRequest): Promise => { + const auth = await params.retrieveAppAuth() + if (auth === null) throw new Error('retrieveAppAuth() returned null') + let finalRoute = '/api/app/invoice/pay' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + const result = data + if(!params.checkResult) return { status: 'OK', ...result } + const error = Types.PayAppUserInvoiceResponseValidate(result) + if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message } + } + return { status: 'ERROR', reason: 'invalid response' } + }, + SendAppUserToAppUserPayment: async (request: Types.SendAppUserToAppUserPaymentRequest): Promise => { + const auth = await params.retrieveAppAuth() + if (auth === null) throw new Error('retrieveAppAuth() returned null') + let finalRoute = '/api/app/user/internal/pay' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + return data + } + return { status: 'ERROR', reason: 'invalid response' } + }, + SendAppUserToAppPayment: async (request: Types.SendAppUserToAppPaymentRequest): Promise => { + const auth = await params.retrieveAppAuth() + if (auth === null) throw new Error('retrieveAppAuth() returned null') + let finalRoute = '/api/app/internal/pay' + const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } }) + if (data.status === 'ERROR' && typeof data.reason === 'string') return data + if (data.status === 'OK') { + return data + } + return { status: 'ERROR', reason: 'invalid response' } + }, AddUser: async (request: Types.AddUserRequest): Promise => { const auth = await params.retrieveGuestAuth() if (auth === null) throw new Error('retrieveGuestAuth() returned null') diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index 7c03210c..dc2f61a7 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -8,7 +8,10 @@ export type UserContext = { export type AdminContext = { admin_id: string } -export type AuthContext = GuestContext | UserContext | AdminContext +export type AppContext = { + app_id: string +} +export type AuthContext = GuestContext | UserContext | AdminContext | AppContext export type Health_Query = { } @@ -25,6 +28,46 @@ export type LndGetInfo_Query = { export type LndGetInfo_RouteParams = { } export type LndGetInfo_Context = LndGetInfo_Query & LndGetInfo_RouteParams & AdminContext +export type AddApp_Query = { +} +export type AddApp_RouteParams = { +} +export type AddApp_Context = AddApp_Query & AddApp_RouteParams & AdminContext +export type AddAppUser_Query = { +} +export type AddAppUser_RouteParams = { +} +export type AddAppUser_Context = AddAppUser_Query & AddAppUser_RouteParams & AppContext +export type AddAppInvoice_Query = { +} +export type AddAppInvoice_RouteParams = { +} +export type AddAppInvoice_Context = AddAppInvoice_Query & AddAppInvoice_RouteParams & AppContext +export type AddAppUserInvoice_Query = { +} +export type AddAppUserInvoice_RouteParams = { +} +export type AddAppUserInvoice_Context = AddAppUserInvoice_Query & AddAppUserInvoice_RouteParams & AppContext +export type GetAppUser_Query = { +} +export type GetAppUser_RouteParams = { +} +export type GetAppUser_Context = GetAppUser_Query & GetAppUser_RouteParams & AppContext +export type PayAppUserInvoice_Query = { +} +export type PayAppUserInvoice_RouteParams = { +} +export type PayAppUserInvoice_Context = PayAppUserInvoice_Query & PayAppUserInvoice_RouteParams & AppContext +export type SendAppUserToAppUserPayment_Query = { +} +export type SendAppUserToAppUserPayment_RouteParams = { +} +export type SendAppUserToAppUserPayment_Context = SendAppUserToAppUserPayment_Query & SendAppUserToAppUserPayment_RouteParams & AppContext +export type SendAppUserToAppPayment_Query = { +} +export type SendAppUserToAppPayment_RouteParams = { +} +export type SendAppUserToAppPayment_Context = SendAppUserToAppPayment_Query & SendAppUserToAppPayment_RouteParams & AppContext export type AddUser_Query = { } export type AddUser_RouteParams = { @@ -126,6 +169,14 @@ export type ServerMethods = { Health?: (ctx: Health_Context) => Promise EncryptionExchange?: (ctx: EncryptionExchange_Context, req: EncryptionExchangeRequest) => Promise LndGetInfo?: (ctx: LndGetInfo_Context, req: LndGetInfoRequest) => Promise + AddApp?: (ctx: AddApp_Context, req: AddAppRequest) => Promise + AddAppUser?: (ctx: AddAppUser_Context, req: AddAppUserRequest) => Promise + AddAppInvoice?: (ctx: AddAppInvoice_Context, req: AddAppInvoiceRequest) => Promise + AddAppUserInvoice?: (ctx: AddAppUserInvoice_Context, req: AddAppUserInvoiceRequest) => Promise + GetAppUser?: (ctx: GetAppUser_Context, req: GetAppUserRequest) => Promise + PayAppUserInvoice?: (ctx: PayAppUserInvoice_Context, req: PayAppUserInvoiceRequest) => Promise + SendAppUserToAppUserPayment?: (ctx: SendAppUserToAppUserPayment_Context, req: SendAppUserToAppUserPaymentRequest) => Promise + SendAppUserToAppPayment?: (ctx: SendAppUserToAppPayment_Context, req: SendAppUserToAppPaymentRequest) => Promise AddUser?: (ctx: AddUser_Context, req: AddUserRequest) => Promise AuthUser?: (ctx: AuthUser_Context, req: AuthUserRequest) => Promise GetUserInfo?: (ctx: GetUserInfo_Context) => Promise @@ -160,6 +211,8 @@ export enum UserOperationType { OUTGOING_TX = 'OUTGOING_TX', INCOMING_INVOICE = 'INCOMING_INVOICE', OUTGOING_INVOICE = 'OUTGOING_INVOICE', + OUTGOING_USER_TO_USER = 'OUTGOING_USER_TO_USER', + INCOMING_USER_TO_USER = 'INCOMING_USER_TO_USER', } const enumCheckUserOperationType = (e?: UserOperationType): boolean => { for (const v in UserOperationType) if (e === v) return true @@ -170,6 +223,338 @@ export type OptionsBaseMessage = { allOptionalsAreSet?: true } +export type AddUserRequest = { + callbackUrl: string + name: string + secret: string +} +export const AddUserRequestOptionalFields: [] = [] +export type AddUserRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + callbackUrl_CustomCheck?: (v: string) => boolean + name_CustomCheck?: (v: string) => boolean + secret_CustomCheck?: (v: string) => boolean +} +export const AddUserRequestValidate = (o?: AddUserRequest, opts: AddUserRequestOptions = {}, path: string = 'AddUserRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.callbackUrl !== 'string') return new Error(`${path}.callbackUrl: is not a string`) + if (opts.callbackUrl_CustomCheck && !opts.callbackUrl_CustomCheck(o.callbackUrl)) return new Error(`${path}.callbackUrl: custom check failed`) + + if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`) + if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`) + + if (typeof o.secret !== 'string') return new Error(`${path}.secret: is not a string`) + if (opts.secret_CustomCheck && !opts.secret_CustomCheck(o.secret)) return new Error(`${path}.secret: custom check failed`) + + return null +} + +export type DecodeInvoiceResponse = { + amount: number +} +export const DecodeInvoiceResponseOptionalFields: [] = [] +export type DecodeInvoiceResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + amount_CustomCheck?: (v: number) => boolean +} +export const DecodeInvoiceResponseValidate = (o?: DecodeInvoiceResponse, opts: DecodeInvoiceResponseOptions = {}, path: string = 'DecodeInvoiceResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) + + return null +} + +export type Product = { + id: string + name: string + price_sats: number +} +export const ProductOptionalFields: [] = [] +export type ProductOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + id_CustomCheck?: (v: string) => boolean + name_CustomCheck?: (v: string) => boolean + price_sats_CustomCheck?: (v: number) => boolean +} +export const ProductValidate = (o?: Product, opts: ProductOptions = {}, path: string = 'Product::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.id !== 'string') return new Error(`${path}.id: is not a string`) + if (opts.id_CustomCheck && !opts.id_CustomCheck(o.id)) return new Error(`${path}.id: custom check failed`) + + if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`) + if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`) + + if (typeof o.price_sats !== 'number') return new Error(`${path}.price_sats: is not a number`) + if (opts.price_sats_CustomCheck && !opts.price_sats_CustomCheck(o.price_sats)) return new Error(`${path}.price_sats: custom check failed`) + + return null +} + +export type AddAppResponse = { + name: string + id: string + auth_token: string +} +export const AddAppResponseOptionalFields: [] = [] +export type AddAppResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + name_CustomCheck?: (v: string) => boolean + id_CustomCheck?: (v: string) => boolean + auth_token_CustomCheck?: (v: string) => boolean +} +export const AddAppResponseValidate = (o?: AddAppResponse, opts: AddAppResponseOptions = {}, path: string = 'AddAppResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`) + if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`) + + if (typeof o.id !== 'string') return new Error(`${path}.id: is not a string`) + if (opts.id_CustomCheck && !opts.id_CustomCheck(o.id)) return new Error(`${path}.id: custom check failed`) + + if (typeof o.auth_token !== 'string') return new Error(`${path}.auth_token: is not a string`) + if (opts.auth_token_CustomCheck && !opts.auth_token_CustomCheck(o.auth_token)) return new Error(`${path}.auth_token: custom check failed`) + + return null +} + +export type PayAppUserInvoiceRequest = { + user_identifier: string + invoice: string + amount: number +} +export const PayAppUserInvoiceRequestOptionalFields: [] = [] +export type PayAppUserInvoiceRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + user_identifier_CustomCheck?: (v: string) => boolean + invoice_CustomCheck?: (v: string) => boolean + amount_CustomCheck?: (v: number) => boolean +} +export const PayAppUserInvoiceRequestValidate = (o?: PayAppUserInvoiceRequest, opts: PayAppUserInvoiceRequestOptions = {}, path: string = 'PayAppUserInvoiceRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.user_identifier !== 'string') return new Error(`${path}.user_identifier: is not a string`) + if (opts.user_identifier_CustomCheck && !opts.user_identifier_CustomCheck(o.user_identifier)) return new Error(`${path}.user_identifier: custom check failed`) + + if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`) + if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`) + + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) + + return null +} + +export type SendAppUserToAppUserPaymentRequest = { + from_user_identifier: string + to_user_identifier: string + amount: number +} +export const SendAppUserToAppUserPaymentRequestOptionalFields: [] = [] +export type SendAppUserToAppUserPaymentRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + from_user_identifier_CustomCheck?: (v: string) => boolean + to_user_identifier_CustomCheck?: (v: string) => boolean + amount_CustomCheck?: (v: number) => boolean +} +export const SendAppUserToAppUserPaymentRequestValidate = (o?: SendAppUserToAppUserPaymentRequest, opts: SendAppUserToAppUserPaymentRequestOptions = {}, path: string = 'SendAppUserToAppUserPaymentRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.from_user_identifier !== 'string') return new Error(`${path}.from_user_identifier: is not a string`) + if (opts.from_user_identifier_CustomCheck && !opts.from_user_identifier_CustomCheck(o.from_user_identifier)) return new Error(`${path}.from_user_identifier: custom check failed`) + + if (typeof o.to_user_identifier !== 'string') return new Error(`${path}.to_user_identifier: is not a string`) + if (opts.to_user_identifier_CustomCheck && !opts.to_user_identifier_CustomCheck(o.to_user_identifier)) return new Error(`${path}.to_user_identifier: custom check failed`) + + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) + + return null +} + +export type GetUserOperationsRequest = { + latestIncomingInvoice: number + latestOutgoingInvoice: number + latestIncomingTx: number + latestOutgoingTx: number + latestIncomingUserToUserPayment: number + latestOutgoingUserToUserPayment: number +} +export const GetUserOperationsRequestOptionalFields: [] = [] +export type GetUserOperationsRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + latestIncomingInvoice_CustomCheck?: (v: number) => boolean + latestOutgoingInvoice_CustomCheck?: (v: number) => boolean + latestIncomingTx_CustomCheck?: (v: number) => boolean + latestOutgoingTx_CustomCheck?: (v: number) => boolean + latestIncomingUserToUserPayment_CustomCheck?: (v: number) => boolean + latestOutgoingUserToUserPayment_CustomCheck?: (v: number) => boolean +} +export const GetUserOperationsRequestValidate = (o?: GetUserOperationsRequest, opts: GetUserOperationsRequestOptions = {}, path: string = 'GetUserOperationsRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.latestIncomingInvoice !== 'number') return new Error(`${path}.latestIncomingInvoice: is not a number`) + if (opts.latestIncomingInvoice_CustomCheck && !opts.latestIncomingInvoice_CustomCheck(o.latestIncomingInvoice)) return new Error(`${path}.latestIncomingInvoice: custom check failed`) + + if (typeof o.latestOutgoingInvoice !== 'number') return new Error(`${path}.latestOutgoingInvoice: is not a number`) + if (opts.latestOutgoingInvoice_CustomCheck && !opts.latestOutgoingInvoice_CustomCheck(o.latestOutgoingInvoice)) return new Error(`${path}.latestOutgoingInvoice: custom check failed`) + + if (typeof o.latestIncomingTx !== 'number') return new Error(`${path}.latestIncomingTx: is not a number`) + if (opts.latestIncomingTx_CustomCheck && !opts.latestIncomingTx_CustomCheck(o.latestIncomingTx)) return new Error(`${path}.latestIncomingTx: custom check failed`) + + if (typeof o.latestOutgoingTx !== 'number') return new Error(`${path}.latestOutgoingTx: is not a number`) + if (opts.latestOutgoingTx_CustomCheck && !opts.latestOutgoingTx_CustomCheck(o.latestOutgoingTx)) return new Error(`${path}.latestOutgoingTx: custom check failed`) + + if (typeof o.latestIncomingUserToUserPayment !== 'number') return new Error(`${path}.latestIncomingUserToUserPayment: is not a number`) + if (opts.latestIncomingUserToUserPayment_CustomCheck && !opts.latestIncomingUserToUserPayment_CustomCheck(o.latestIncomingUserToUserPayment)) return new Error(`${path}.latestIncomingUserToUserPayment: custom check failed`) + + if (typeof o.latestOutgoingUserToUserPayment !== 'number') return new Error(`${path}.latestOutgoingUserToUserPayment: is not a number`) + if (opts.latestOutgoingUserToUserPayment_CustomCheck && !opts.latestOutgoingUserToUserPayment_CustomCheck(o.latestOutgoingUserToUserPayment)) return new Error(`${path}.latestOutgoingUserToUserPayment: custom check failed`) + + return null +} + +export type EncryptionExchangeRequest = { + publicKey: string + deviceId: string +} +export const EncryptionExchangeRequestOptionalFields: [] = [] +export type EncryptionExchangeRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + publicKey_CustomCheck?: (v: string) => boolean + deviceId_CustomCheck?: (v: string) => boolean +} +export const EncryptionExchangeRequestValidate = (o?: EncryptionExchangeRequest, opts: EncryptionExchangeRequestOptions = {}, path: string = 'EncryptionExchangeRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.publicKey !== 'string') return new Error(`${path}.publicKey: is not a string`) + if (opts.publicKey_CustomCheck && !opts.publicKey_CustomCheck(o.publicKey)) return new Error(`${path}.publicKey: custom check failed`) + + if (typeof o.deviceId !== 'string') return new Error(`${path}.deviceId: is not a string`) + if (opts.deviceId_CustomCheck && !opts.deviceId_CustomCheck(o.deviceId)) return new Error(`${path}.deviceId: custom check failed`) + + return null +} + +export type AppUser = { + identifier: string + info: UserInfo + max_withdrawable: number +} +export const AppUserOptionalFields: [] = [] +export type AppUserOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + identifier_CustomCheck?: (v: string) => boolean + info_Options?: UserInfoOptions + max_withdrawable_CustomCheck?: (v: number) => boolean +} +export const AppUserValidate = (o?: AppUser, opts: AppUserOptions = {}, path: string = 'AppUser::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.identifier !== 'string') return new Error(`${path}.identifier: is not a string`) + if (opts.identifier_CustomCheck && !opts.identifier_CustomCheck(o.identifier)) return new Error(`${path}.identifier: custom check failed`) + + const infoErr = UserInfoValidate(o.info, opts.info_Options, `${path}.info`) + if (infoErr !== null) return infoErr + + + if (typeof o.max_withdrawable !== 'number') return new Error(`${path}.max_withdrawable: is not a number`) + if (opts.max_withdrawable_CustomCheck && !opts.max_withdrawable_CustomCheck(o.max_withdrawable)) return new Error(`${path}.max_withdrawable: custom check failed`) + + return null +} + +export type OpenChannelRequest = { + destination: string + fundingAmount: number + pushAmount: number + closeAddress: string +} +export const OpenChannelRequestOptionalFields: [] = [] +export type OpenChannelRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + destination_CustomCheck?: (v: string) => boolean + fundingAmount_CustomCheck?: (v: number) => boolean + pushAmount_CustomCheck?: (v: number) => boolean + closeAddress_CustomCheck?: (v: string) => boolean +} +export const OpenChannelRequestValidate = (o?: OpenChannelRequest, opts: OpenChannelRequestOptions = {}, path: string = 'OpenChannelRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.destination !== 'string') return new Error(`${path}.destination: is not a string`) + if (opts.destination_CustomCheck && !opts.destination_CustomCheck(o.destination)) return new Error(`${path}.destination: custom check failed`) + + if (typeof o.fundingAmount !== 'number') return new Error(`${path}.fundingAmount: is not a number`) + if (opts.fundingAmount_CustomCheck && !opts.fundingAmount_CustomCheck(o.fundingAmount)) return new Error(`${path}.fundingAmount: custom check failed`) + + if (typeof o.pushAmount !== 'number') return new Error(`${path}.pushAmount: is not a number`) + if (opts.pushAmount_CustomCheck && !opts.pushAmount_CustomCheck(o.pushAmount)) return new Error(`${path}.pushAmount: custom check failed`) + + if (typeof o.closeAddress !== 'string') return new Error(`${path}.closeAddress: is not a string`) + if (opts.closeAddress_CustomCheck && !opts.closeAddress_CustomCheck(o.closeAddress)) return new Error(`${path}.closeAddress: custom check failed`) + + return null +} + +export type NewInvoiceRequest = { + amountSats: number + memo: string +} +export const NewInvoiceRequestOptionalFields: [] = [] +export type NewInvoiceRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + amountSats_CustomCheck?: (v: number) => boolean + memo_CustomCheck?: (v: string) => boolean +} +export const NewInvoiceRequestValidate = (o?: NewInvoiceRequest, opts: NewInvoiceRequestOptions = {}, path: string = 'NewInvoiceRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.amountSats !== 'number') return new Error(`${path}.amountSats: is not a number`) + if (opts.amountSats_CustomCheck && !opts.amountSats_CustomCheck(o.amountSats)) return new Error(`${path}.amountSats: custom check failed`) + + if (typeof o.memo !== 'string') return new Error(`${path}.memo: is not a string`) + if (opts.memo_CustomCheck && !opts.memo_CustomCheck(o.memo)) return new Error(`${path}.memo: custom check failed`) + + return null +} + +export type LnurlLinkResponse = { + lnurl: string + k1: string +} +export const LnurlLinkResponseOptionalFields: [] = [] +export type LnurlLinkResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + lnurl_CustomCheck?: (v: string) => boolean + k1_CustomCheck?: (v: string) => boolean +} +export const LnurlLinkResponseValidate = (o?: LnurlLinkResponse, opts: LnurlLinkResponseOptions = {}, path: string = 'LnurlLinkResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.lnurl !== 'string') return new Error(`${path}.lnurl: is not a string`) + if (opts.lnurl_CustomCheck && !opts.lnurl_CustomCheck(o.lnurl)) return new Error(`${path}.lnurl: custom check failed`) + + if (typeof o.k1 !== 'string') return new Error(`${path}.k1: is not a string`) + if (opts.k1_CustomCheck && !opts.k1_CustomCheck(o.k1)) return new Error(`${path}.k1: custom check failed`) + + return null +} + export type LnurlWithdrawInfoResponse = { tag: string callback: string @@ -223,180 +608,6 @@ export const LnurlWithdrawInfoResponseValidate = (o?: LnurlWithdrawInfoResponse, return null } -export type GetProductBuyLinkResponse = { - link: string -} -export const GetProductBuyLinkResponseOptionalFields: [] = [] -export type GetProductBuyLinkResponseOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - link_CustomCheck?: (v: string) => boolean -} -export const GetProductBuyLinkResponseValidate = (o?: GetProductBuyLinkResponse, opts: GetProductBuyLinkResponseOptions = {}, path: string = 'GetProductBuyLinkResponse::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.link !== 'string') return new Error(`${path}.link: is not a string`) - if (opts.link_CustomCheck && !opts.link_CustomCheck(o.link)) return new Error(`${path}.link: custom check failed`) - - return null -} - -export type NewAddressRequest = { - addressType: AddressType -} -export const NewAddressRequestOptionalFields: [] = [] -export type NewAddressRequestOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - addressType_CustomCheck?: (v: AddressType) => boolean -} -export const NewAddressRequestValidate = (o?: NewAddressRequest, opts: NewAddressRequestOptions = {}, path: string = 'NewAddressRequest::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (!enumCheckAddressType(o.addressType)) return new Error(`${path}.addressType: is not a valid AddressType`) - if (opts.addressType_CustomCheck && !opts.addressType_CustomCheck(o.addressType)) return new Error(`${path}.addressType: custom check failed`) - - return null -} - -export type NewAddressResponse = { - address: string -} -export const NewAddressResponseOptionalFields: [] = [] -export type NewAddressResponseOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - address_CustomCheck?: (v: string) => boolean -} -export const NewAddressResponseValidate = (o?: NewAddressResponse, opts: NewAddressResponseOptions = {}, path: string = 'NewAddressResponse::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.address !== 'string') return new Error(`${path}.address: is not a string`) - if (opts.address_CustomCheck && !opts.address_CustomCheck(o.address)) return new Error(`${path}.address: custom check failed`) - - return null -} - -export type PayInvoiceRequest = { - invoice: string - amount: number -} -export const PayInvoiceRequestOptionalFields: [] = [] -export type PayInvoiceRequestOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - invoice_CustomCheck?: (v: string) => boolean - amount_CustomCheck?: (v: number) => boolean -} -export const PayInvoiceRequestValidate = (o?: PayInvoiceRequest, opts: PayInvoiceRequestOptions = {}, path: string = 'PayInvoiceRequest::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`) - if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`) - - if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) - if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) - - return null -} - -export type AddUserRequest = { - callbackUrl: string - name: string - secret: string -} -export const AddUserRequestOptionalFields: [] = [] -export type AddUserRequestOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - callbackUrl_CustomCheck?: (v: string) => boolean - name_CustomCheck?: (v: string) => boolean - secret_CustomCheck?: (v: string) => boolean -} -export const AddUserRequestValidate = (o?: AddUserRequest, opts: AddUserRequestOptions = {}, path: string = 'AddUserRequest::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.callbackUrl !== 'string') return new Error(`${path}.callbackUrl: is not a string`) - if (opts.callbackUrl_CustomCheck && !opts.callbackUrl_CustomCheck(o.callbackUrl)) return new Error(`${path}.callbackUrl: custom check failed`) - - if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`) - if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`) - - if (typeof o.secret !== 'string') return new Error(`${path}.secret: is not a string`) - if (opts.secret_CustomCheck && !opts.secret_CustomCheck(o.secret)) return new Error(`${path}.secret: custom check failed`) - - return null -} - -export type UserOperation = { - paidAtUnix: number - type: UserOperationType - inbound: boolean - amount: number -} -export const UserOperationOptionalFields: [] = [] -export type UserOperationOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - paidAtUnix_CustomCheck?: (v: number) => boolean - type_CustomCheck?: (v: UserOperationType) => boolean - inbound_CustomCheck?: (v: boolean) => boolean - amount_CustomCheck?: (v: number) => boolean -} -export const UserOperationValidate = (o?: UserOperation, opts: UserOperationOptions = {}, path: string = 'UserOperation::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.paidAtUnix !== 'number') return new Error(`${path}.paidAtUnix: is not a number`) - if (opts.paidAtUnix_CustomCheck && !opts.paidAtUnix_CustomCheck(o.paidAtUnix)) return new Error(`${path}.paidAtUnix: custom check failed`) - - if (!enumCheckUserOperationType(o.type)) return new Error(`${path}.type: is not a valid UserOperationType`) - if (opts.type_CustomCheck && !opts.type_CustomCheck(o.type)) return new Error(`${path}.type: custom check failed`) - - if (typeof o.inbound !== 'boolean') return new Error(`${path}.inbound: is not a boolean`) - if (opts.inbound_CustomCheck && !opts.inbound_CustomCheck(o.inbound)) return new Error(`${path}.inbound: custom check failed`) - - if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) - if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) - - return null -} - -export type PayAddressResponse = { - txId: string -} -export const PayAddressResponseOptionalFields: [] = [] -export type PayAddressResponseOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - txId_CustomCheck?: (v: string) => boolean -} -export const PayAddressResponseValidate = (o?: PayAddressResponse, opts: PayAddressResponseOptions = {}, path: string = 'PayAddressResponse::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.txId !== 'string') return new Error(`${path}.txId: is not a string`) - if (opts.txId_CustomCheck && !opts.txId_CustomCheck(o.txId)) return new Error(`${path}.txId: custom check failed`) - - return null -} - -export type DecodeInvoiceResponse = { - amount: number -} -export const DecodeInvoiceResponseOptionalFields: [] = [] -export type DecodeInvoiceResponseOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - amount_CustomCheck?: (v: number) => boolean -} -export const DecodeInvoiceResponseValidate = (o?: DecodeInvoiceResponse, opts: DecodeInvoiceResponseOptions = {}, path: string = 'DecodeInvoiceResponse::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) - if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) - - return null -} - export type LnurlPayInfoResponse = { tag: string callback: string @@ -435,168 +646,145 @@ export const LnurlPayInfoResponseValidate = (o?: LnurlPayInfoResponse, opts: Lnu return null } -export type Product = { - id: string - name: string - price_sats: number +export type HandleLnurlPayResponse = { + pr: string + routes: Empty[] } -export const ProductOptionalFields: [] = [] -export type ProductOptions = OptionsBaseMessage & { +export const HandleLnurlPayResponseOptionalFields: [] = [] +export type HandleLnurlPayResponseOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - id_CustomCheck?: (v: string) => boolean - name_CustomCheck?: (v: string) => boolean - price_sats_CustomCheck?: (v: number) => boolean + pr_CustomCheck?: (v: string) => boolean + routes_ItemOptions?: EmptyOptions + routes_CustomCheck?: (v: Empty[]) => boolean } -export const ProductValidate = (o?: Product, opts: ProductOptions = {}, path: string = 'Product::root.'): Error | null => { +export const HandleLnurlPayResponseValidate = (o?: HandleLnurlPayResponse, opts: HandleLnurlPayResponseOptions = {}, path: string = 'HandleLnurlPayResponse::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.id !== 'string') return new Error(`${path}.id: is not a string`) - if (opts.id_CustomCheck && !opts.id_CustomCheck(o.id)) return new Error(`${path}.id: custom check failed`) + if (typeof o.pr !== 'string') return new Error(`${path}.pr: is not a string`) + if (opts.pr_CustomCheck && !opts.pr_CustomCheck(o.pr)) return new Error(`${path}.pr: custom check failed`) + + if (!Array.isArray(o.routes)) return new Error(`${path}.routes: is not an array`) + for (let index = 0; index < o.routes.length; index++) { + const routesErr = EmptyValidate(o.routes[index], opts.routes_ItemOptions, `${path}.routes[${index}]`) + if (routesErr !== null) return routesErr + } + if (opts.routes_CustomCheck && !opts.routes_CustomCheck(o.routes)) return new Error(`${path}.routes: custom check failed`) + + return null +} + +export type AddAppRequest = { + name: string +} +export const AddAppRequestOptionalFields: [] = [] +export type AddAppRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + name_CustomCheck?: (v: string) => boolean +} +export const AddAppRequestValidate = (o?: AddAppRequest, opts: AddAppRequestOptions = {}, path: string = 'AddAppRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`) if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`) - if (typeof o.price_sats !== 'number') return new Error(`${path}.price_sats: is not a number`) - if (opts.price_sats_CustomCheck && !opts.price_sats_CustomCheck(o.price_sats)) return new Error(`${path}.price_sats: custom check failed`) - return null } -export type EncryptionExchangeRequest = { - publicKey: string - deviceId: string +export type SendAppUserToAppPaymentRequest = { + from_user_identifier: string + amount: number } -export const EncryptionExchangeRequestOptionalFields: [] = [] -export type EncryptionExchangeRequestOptions = OptionsBaseMessage & { +export const SendAppUserToAppPaymentRequestOptionalFields: [] = [] +export type SendAppUserToAppPaymentRequestOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - publicKey_CustomCheck?: (v: string) => boolean - deviceId_CustomCheck?: (v: string) => boolean + from_user_identifier_CustomCheck?: (v: string) => boolean + amount_CustomCheck?: (v: number) => boolean } -export const EncryptionExchangeRequestValidate = (o?: EncryptionExchangeRequest, opts: EncryptionExchangeRequestOptions = {}, path: string = 'EncryptionExchangeRequest::root.'): Error | null => { +export const SendAppUserToAppPaymentRequestValidate = (o?: SendAppUserToAppPaymentRequest, opts: SendAppUserToAppPaymentRequestOptions = {}, path: string = 'SendAppUserToAppPaymentRequest::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.publicKey !== 'string') return new Error(`${path}.publicKey: is not a string`) - if (opts.publicKey_CustomCheck && !opts.publicKey_CustomCheck(o.publicKey)) return new Error(`${path}.publicKey: custom check failed`) + if (typeof o.from_user_identifier !== 'string') return new Error(`${path}.from_user_identifier: is not a string`) + if (opts.from_user_identifier_CustomCheck && !opts.from_user_identifier_CustomCheck(o.from_user_identifier)) return new Error(`${path}.from_user_identifier: custom check failed`) - if (typeof o.deviceId !== 'string') return new Error(`${path}.deviceId: is not a string`) - if (opts.deviceId_CustomCheck && !opts.deviceId_CustomCheck(o.deviceId)) return new Error(`${path}.deviceId: custom check failed`) + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) return null } -export type NewInvoiceRequest = { - amountSats: number - memo: string +export type PayAddressResponse = { + txId: string } -export const NewInvoiceRequestOptionalFields: [] = [] -export type NewInvoiceRequestOptions = OptionsBaseMessage & { +export const PayAddressResponseOptionalFields: [] = [] +export type PayAddressResponseOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - amountSats_CustomCheck?: (v: number) => boolean - memo_CustomCheck?: (v: string) => boolean + txId_CustomCheck?: (v: string) => boolean } -export const NewInvoiceRequestValidate = (o?: NewInvoiceRequest, opts: NewInvoiceRequestOptions = {}, path: string = 'NewInvoiceRequest::root.'): Error | null => { +export const PayAddressResponseValidate = (o?: PayAddressResponse, opts: PayAddressResponseOptions = {}, path: string = 'PayAddressResponse::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.amountSats !== 'number') return new Error(`${path}.amountSats: is not a number`) - if (opts.amountSats_CustomCheck && !opts.amountSats_CustomCheck(o.amountSats)) return new Error(`${path}.amountSats: custom check failed`) - - if (typeof o.memo !== 'string') return new Error(`${path}.memo: is not a string`) - if (opts.memo_CustomCheck && !opts.memo_CustomCheck(o.memo)) return new Error(`${path}.memo: custom check failed`) + if (typeof o.txId !== 'string') return new Error(`${path}.txId: is not a string`) + if (opts.txId_CustomCheck && !opts.txId_CustomCheck(o.txId)) return new Error(`${path}.txId: custom check failed`) return null } -export type PayInvoiceResponse = { - preimage: string -} -export const PayInvoiceResponseOptionalFields: [] = [] -export type PayInvoiceResponseOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - preimage_CustomCheck?: (v: string) => boolean -} -export const PayInvoiceResponseValidate = (o?: PayInvoiceResponse, opts: PayInvoiceResponseOptions = {}, path: string = 'PayInvoiceResponse::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.preimage !== 'string') return new Error(`${path}.preimage: is not a string`) - if (opts.preimage_CustomCheck && !opts.preimage_CustomCheck(o.preimage)) return new Error(`${path}.preimage: custom check failed`) - - return null -} - -export type OpenChannelResponse = { - channelId: string -} -export const OpenChannelResponseOptionalFields: [] = [] -export type OpenChannelResponseOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - channelId_CustomCheck?: (v: string) => boolean -} -export const OpenChannelResponseValidate = (o?: OpenChannelResponse, opts: OpenChannelResponseOptions = {}, path: string = 'OpenChannelResponse::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - if (typeof o.channelId !== 'string') return new Error(`${path}.channelId: is not a string`) - if (opts.channelId_CustomCheck && !opts.channelId_CustomCheck(o.channelId)) return new Error(`${path}.channelId: custom check failed`) - - return null -} - -export type UserInfo = { +export type AuthUserResponse = { userId: string - balance: number + authToken: string } -export const UserInfoOptionalFields: [] = [] -export type UserInfoOptions = OptionsBaseMessage & { +export const AuthUserResponseOptionalFields: [] = [] +export type AuthUserResponseOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] userId_CustomCheck?: (v: string) => boolean - balance_CustomCheck?: (v: number) => boolean + authToken_CustomCheck?: (v: string) => boolean } -export const UserInfoValidate = (o?: UserInfo, opts: UserInfoOptions = {}, path: string = 'UserInfo::root.'): Error | null => { +export const AuthUserResponseValidate = (o?: AuthUserResponse, opts: AuthUserResponseOptions = {}, path: string = 'AuthUserResponse::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') if (typeof o.userId !== 'string') return new Error(`${path}.userId: is not a string`) if (opts.userId_CustomCheck && !opts.userId_CustomCheck(o.userId)) return new Error(`${path}.userId: custom check failed`) - if (typeof o.balance !== 'number') return new Error(`${path}.balance: is not a number`) - if (opts.balance_CustomCheck && !opts.balance_CustomCheck(o.balance)) return new Error(`${path}.balance: custom check failed`) + if (typeof o.authToken !== 'string') return new Error(`${path}.authToken: is not a string`) + if (opts.authToken_CustomCheck && !opts.authToken_CustomCheck(o.authToken)) return new Error(`${path}.authToken: custom check failed`) return null } -export type GetUserOperationsRequest = { - latestIncomingInvoice: number - latestOutgoingInvoice: number - latestIncomingTx: number - latestOutgoingTx: number +export type UserOperation = { + paidAtUnix: number + type: UserOperationType + inbound: boolean + amount: number } -export const GetUserOperationsRequestOptionalFields: [] = [] -export type GetUserOperationsRequestOptions = OptionsBaseMessage & { +export const UserOperationOptionalFields: [] = [] +export type UserOperationOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - latestIncomingInvoice_CustomCheck?: (v: number) => boolean - latestOutgoingInvoice_CustomCheck?: (v: number) => boolean - latestIncomingTx_CustomCheck?: (v: number) => boolean - latestOutgoingTx_CustomCheck?: (v: number) => boolean + paidAtUnix_CustomCheck?: (v: number) => boolean + type_CustomCheck?: (v: UserOperationType) => boolean + inbound_CustomCheck?: (v: boolean) => boolean + amount_CustomCheck?: (v: number) => boolean } -export const GetUserOperationsRequestValidate = (o?: GetUserOperationsRequest, opts: GetUserOperationsRequestOptions = {}, path: string = 'GetUserOperationsRequest::root.'): Error | null => { +export const UserOperationValidate = (o?: UserOperation, opts: UserOperationOptions = {}, path: string = 'UserOperation::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.latestIncomingInvoice !== 'number') return new Error(`${path}.latestIncomingInvoice: is not a number`) - if (opts.latestIncomingInvoice_CustomCheck && !opts.latestIncomingInvoice_CustomCheck(o.latestIncomingInvoice)) return new Error(`${path}.latestIncomingInvoice: custom check failed`) + if (typeof o.paidAtUnix !== 'number') return new Error(`${path}.paidAtUnix: is not a number`) + if (opts.paidAtUnix_CustomCheck && !opts.paidAtUnix_CustomCheck(o.paidAtUnix)) return new Error(`${path}.paidAtUnix: custom check failed`) - if (typeof o.latestOutgoingInvoice !== 'number') return new Error(`${path}.latestOutgoingInvoice: is not a number`) - if (opts.latestOutgoingInvoice_CustomCheck && !opts.latestOutgoingInvoice_CustomCheck(o.latestOutgoingInvoice)) return new Error(`${path}.latestOutgoingInvoice: custom check failed`) + if (!enumCheckUserOperationType(o.type)) return new Error(`${path}.type: is not a valid UserOperationType`) + if (opts.type_CustomCheck && !opts.type_CustomCheck(o.type)) return new Error(`${path}.type: custom check failed`) - if (typeof o.latestIncomingTx !== 'number') return new Error(`${path}.latestIncomingTx: is not a number`) - if (opts.latestIncomingTx_CustomCheck && !opts.latestIncomingTx_CustomCheck(o.latestIncomingTx)) return new Error(`${path}.latestIncomingTx: custom check failed`) + if (typeof o.inbound !== 'boolean') return new Error(`${path}.inbound: is not a boolean`) + if (opts.inbound_CustomCheck && !opts.inbound_CustomCheck(o.inbound)) return new Error(`${path}.inbound: custom check failed`) - if (typeof o.latestOutgoingTx !== 'number') return new Error(`${path}.latestOutgoingTx: is not a number`) - if (opts.latestOutgoingTx_CustomCheck && !opts.latestOutgoingTx_CustomCheck(o.latestOutgoingTx)) return new Error(`${path}.latestOutgoingTx: custom check failed`) + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) return null } @@ -652,109 +840,97 @@ export const PayAddressRequestValidate = (o?: PayAddressRequest, opts: PayAddres return null } -export type OpenChannelRequest = { - destination: string - fundingAmount: number - pushAmount: number - closeAddress: string +export type UserInfo = { + userId: string + balance: number } -export const OpenChannelRequestOptionalFields: [] = [] -export type OpenChannelRequestOptions = OptionsBaseMessage & { +export const UserInfoOptionalFields: [] = [] +export type UserInfoOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - destination_CustomCheck?: (v: string) => boolean - fundingAmount_CustomCheck?: (v: number) => boolean - pushAmount_CustomCheck?: (v: number) => boolean - closeAddress_CustomCheck?: (v: string) => boolean + userId_CustomCheck?: (v: string) => boolean + balance_CustomCheck?: (v: number) => boolean } -export const OpenChannelRequestValidate = (o?: OpenChannelRequest, opts: OpenChannelRequestOptions = {}, path: string = 'OpenChannelRequest::root.'): Error | null => { +export const UserInfoValidate = (o?: UserInfo, opts: UserInfoOptions = {}, path: string = 'UserInfo::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.destination !== 'string') return new Error(`${path}.destination: is not a string`) - if (opts.destination_CustomCheck && !opts.destination_CustomCheck(o.destination)) return new Error(`${path}.destination: custom check failed`) + if (typeof o.userId !== 'string') return new Error(`${path}.userId: is not a string`) + if (opts.userId_CustomCheck && !opts.userId_CustomCheck(o.userId)) return new Error(`${path}.userId: custom check failed`) - if (typeof o.fundingAmount !== 'number') return new Error(`${path}.fundingAmount: is not a number`) - if (opts.fundingAmount_CustomCheck && !opts.fundingAmount_CustomCheck(o.fundingAmount)) return new Error(`${path}.fundingAmount: custom check failed`) - - if (typeof o.pushAmount !== 'number') return new Error(`${path}.pushAmount: is not a number`) - if (opts.pushAmount_CustomCheck && !opts.pushAmount_CustomCheck(o.pushAmount)) return new Error(`${path}.pushAmount: custom check failed`) - - if (typeof o.closeAddress !== 'string') return new Error(`${path}.closeAddress: is not a string`) - if (opts.closeAddress_CustomCheck && !opts.closeAddress_CustomCheck(o.closeAddress)) return new Error(`${path}.closeAddress: custom check failed`) + if (typeof o.balance !== 'number') return new Error(`${path}.balance: is not a number`) + if (opts.balance_CustomCheck && !opts.balance_CustomCheck(o.balance)) return new Error(`${path}.balance: custom check failed`) return null } -export type LnurlLinkResponse = { - lnurl: string - k1: string +export type GetProductBuyLinkResponse = { + link: string } -export const LnurlLinkResponseOptionalFields: [] = [] -export type LnurlLinkResponseOptions = OptionsBaseMessage & { +export const GetProductBuyLinkResponseOptionalFields: [] = [] +export type GetProductBuyLinkResponseOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - lnurl_CustomCheck?: (v: string) => boolean - k1_CustomCheck?: (v: string) => boolean + link_CustomCheck?: (v: string) => boolean } -export const LnurlLinkResponseValidate = (o?: LnurlLinkResponse, opts: LnurlLinkResponseOptions = {}, path: string = 'LnurlLinkResponse::root.'): Error | null => { +export const GetProductBuyLinkResponseValidate = (o?: GetProductBuyLinkResponse, opts: GetProductBuyLinkResponseOptions = {}, path: string = 'GetProductBuyLinkResponse::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.lnurl !== 'string') return new Error(`${path}.lnurl: is not a string`) - if (opts.lnurl_CustomCheck && !opts.lnurl_CustomCheck(o.lnurl)) return new Error(`${path}.lnurl: custom check failed`) - - if (typeof o.k1 !== 'string') return new Error(`${path}.k1: is not a string`) - if (opts.k1_CustomCheck && !opts.k1_CustomCheck(o.k1)) return new Error(`${path}.k1: custom check failed`) + if (typeof o.link !== 'string') return new Error(`${path}.link: is not a string`) + if (opts.link_CustomCheck && !opts.link_CustomCheck(o.link)) return new Error(`${path}.link: custom check failed`) return null } -export type HandleLnurlPayResponse = { - pr: string - routes: Empty[] +export type LndGetInfoRequest = { + nodeId: number } -export const HandleLnurlPayResponseOptionalFields: [] = [] -export type HandleLnurlPayResponseOptions = OptionsBaseMessage & { +export const LndGetInfoRequestOptionalFields: [] = [] +export type LndGetInfoRequestOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - pr_CustomCheck?: (v: string) => boolean - routes_ItemOptions?: EmptyOptions - routes_CustomCheck?: (v: Empty[]) => boolean + nodeId_CustomCheck?: (v: number) => boolean } -export const HandleLnurlPayResponseValidate = (o?: HandleLnurlPayResponse, opts: HandleLnurlPayResponseOptions = {}, path: string = 'HandleLnurlPayResponse::root.'): Error | null => { +export const LndGetInfoRequestValidate = (o?: LndGetInfoRequest, opts: LndGetInfoRequestOptions = {}, path: string = 'LndGetInfoRequest::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.pr !== 'string') return new Error(`${path}.pr: is not a string`) - if (opts.pr_CustomCheck && !opts.pr_CustomCheck(o.pr)) return new Error(`${path}.pr: custom check failed`) - - if (!Array.isArray(o.routes)) return new Error(`${path}.routes: is not an array`) - for (let index = 0; index < o.routes.length; index++) { - const routesErr = EmptyValidate(o.routes[index], opts.routes_ItemOptions, `${path}.routes[${index}]`) - if (routesErr !== null) return routesErr - } - if (opts.routes_CustomCheck && !opts.routes_CustomCheck(o.routes)) return new Error(`${path}.routes: custom check failed`) + if (typeof o.nodeId !== 'number') return new Error(`${path}.nodeId: is not a number`) + if (opts.nodeId_CustomCheck && !opts.nodeId_CustomCheck(o.nodeId)) return new Error(`${path}.nodeId: custom check failed`) return null } -export type AuthUserRequest = { - name: string - secret: string +export type NewAddressRequest = { + addressType: AddressType } -export const AuthUserRequestOptionalFields: [] = [] -export type AuthUserRequestOptions = OptionsBaseMessage & { +export const NewAddressRequestOptionalFields: [] = [] +export type NewAddressRequestOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - name_CustomCheck?: (v: string) => boolean - secret_CustomCheck?: (v: string) => boolean + addressType_CustomCheck?: (v: AddressType) => boolean } -export const AuthUserRequestValidate = (o?: AuthUserRequest, opts: AuthUserRequestOptions = {}, path: string = 'AuthUserRequest::root.'): Error | null => { +export const NewAddressRequestValidate = (o?: NewAddressRequest, opts: NewAddressRequestOptions = {}, path: string = 'NewAddressRequest::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`) - if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`) + if (!enumCheckAddressType(o.addressType)) return new Error(`${path}.addressType: is not a valid AddressType`) + if (opts.addressType_CustomCheck && !opts.addressType_CustomCheck(o.addressType)) return new Error(`${path}.addressType: custom check failed`) - if (typeof o.secret !== 'string') return new Error(`${path}.secret: is not a string`) - if (opts.secret_CustomCheck && !opts.secret_CustomCheck(o.secret)) return new Error(`${path}.secret: custom check failed`) + return null +} + +export type NewAddressResponse = { + address: string +} +export const NewAddressResponseOptionalFields: [] = [] +export type NewAddressResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + address_CustomCheck?: (v: string) => boolean +} +export const NewAddressResponseValidate = (o?: NewAddressResponse, opts: NewAddressResponseOptions = {}, path: string = 'NewAddressResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.address !== 'string') return new Error(`${path}.address: is not a string`) + if (opts.address_CustomCheck && !opts.address_CustomCheck(o.address)) return new Error(`${path}.address: custom check failed`) return null } @@ -792,6 +968,104 @@ export const UserOperationsValidate = (o?: UserOperations, opts: UserOperationsO return null } +export type AddAppUserInvoiceRequest = { + receiver_identifier: string + payer_identifier: string + http_callback_url: string + invoice_req: NewInvoiceRequest +} +export const AddAppUserInvoiceRequestOptionalFields: [] = [] +export type AddAppUserInvoiceRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + receiver_identifier_CustomCheck?: (v: string) => boolean + payer_identifier_CustomCheck?: (v: string) => boolean + http_callback_url_CustomCheck?: (v: string) => boolean + invoice_req_Options?: NewInvoiceRequestOptions +} +export const AddAppUserInvoiceRequestValidate = (o?: AddAppUserInvoiceRequest, opts: AddAppUserInvoiceRequestOptions = {}, path: string = 'AddAppUserInvoiceRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.receiver_identifier !== 'string') return new Error(`${path}.receiver_identifier: is not a string`) + if (opts.receiver_identifier_CustomCheck && !opts.receiver_identifier_CustomCheck(o.receiver_identifier)) return new Error(`${path}.receiver_identifier: custom check failed`) + + if (typeof o.payer_identifier !== 'string') return new Error(`${path}.payer_identifier: is not a string`) + if (opts.payer_identifier_CustomCheck && !opts.payer_identifier_CustomCheck(o.payer_identifier)) return new Error(`${path}.payer_identifier: custom check failed`) + + if (typeof o.http_callback_url !== 'string') return new Error(`${path}.http_callback_url: is not a string`) + if (opts.http_callback_url_CustomCheck && !opts.http_callback_url_CustomCheck(o.http_callback_url)) return new Error(`${path}.http_callback_url: custom check failed`) + + const invoice_reqErr = NewInvoiceRequestValidate(o.invoice_req, opts.invoice_req_Options, `${path}.invoice_req`) + if (invoice_reqErr !== null) return invoice_reqErr + + + return null +} + +export type GetAppUserRequest = { + user_identifier: string +} +export const GetAppUserRequestOptionalFields: [] = [] +export type GetAppUserRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + user_identifier_CustomCheck?: (v: string) => boolean +} +export const GetAppUserRequestValidate = (o?: GetAppUserRequest, opts: GetAppUserRequestOptions = {}, path: string = 'GetAppUserRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.user_identifier !== 'string') return new Error(`${path}.user_identifier: is not a string`) + if (opts.user_identifier_CustomCheck && !opts.user_identifier_CustomCheck(o.user_identifier)) return new Error(`${path}.user_identifier: custom check failed`) + + return null +} + +export type AuthUserRequest = { + name: string + secret: string +} +export const AuthUserRequestOptionalFields: [] = [] +export type AuthUserRequestOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + name_CustomCheck?: (v: string) => boolean + secret_CustomCheck?: (v: string) => boolean +} +export const AuthUserRequestValidate = (o?: AuthUserRequest, opts: AuthUserRequestOptions = {}, path: string = 'AuthUserRequest::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`) + if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`) + + if (typeof o.secret !== 'string') return new Error(`${path}.secret: is not a string`) + if (opts.secret_CustomCheck && !opts.secret_CustomCheck(o.secret)) return new Error(`${path}.secret: custom check failed`) + + return null +} + +export type AddUserResponse = { + userId: string + authToken: string +} +export const AddUserResponseOptionalFields: [] = [] +export type AddUserResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + userId_CustomCheck?: (v: string) => boolean + authToken_CustomCheck?: (v: string) => boolean +} +export const AddUserResponseValidate = (o?: AddUserResponse, opts: AddUserResponseOptions = {}, path: string = 'AddUserResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.userId !== 'string') return new Error(`${path}.userId: is not a string`) + if (opts.userId_CustomCheck && !opts.userId_CustomCheck(o.userId)) return new Error(`${path}.userId: custom check failed`) + + if (typeof o.authToken !== 'string') return new Error(`${path}.authToken: is not a string`) + if (opts.authToken_CustomCheck && !opts.authToken_CustomCheck(o.authToken)) return new Error(`${path}.authToken: custom check failed`) + + return null +} + export type Empty = { } export const EmptyOptionalFields: [] = [] @@ -805,6 +1079,47 @@ export const EmptyValidate = (o?: Empty, opts: EmptyOptions = {}, path: string = return null } +export type PayAppUserInvoiceResponse = { + preimage: string + amount_paid: number +} +export const PayAppUserInvoiceResponseOptionalFields: [] = [] +export type PayAppUserInvoiceResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + preimage_CustomCheck?: (v: string) => boolean + amount_paid_CustomCheck?: (v: number) => boolean +} +export const PayAppUserInvoiceResponseValidate = (o?: PayAppUserInvoiceResponse, opts: PayAppUserInvoiceResponseOptions = {}, path: string = 'PayAppUserInvoiceResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.preimage !== 'string') return new Error(`${path}.preimage: is not a string`) + if (opts.preimage_CustomCheck && !opts.preimage_CustomCheck(o.preimage)) return new Error(`${path}.preimage: custom check failed`) + + if (typeof o.amount_paid !== 'number') return new Error(`${path}.amount_paid: is not a number`) + if (opts.amount_paid_CustomCheck && !opts.amount_paid_CustomCheck(o.amount_paid)) return new Error(`${path}.amount_paid: custom check failed`) + + return null +} + +export type OpenChannelResponse = { + channelId: string +} +export const OpenChannelResponseOptionalFields: [] = [] +export type OpenChannelResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + channelId_CustomCheck?: (v: string) => boolean +} +export const OpenChannelResponseValidate = (o?: OpenChannelResponse, opts: OpenChannelResponseOptions = {}, path: string = 'OpenChannelResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.channelId !== 'string') return new Error(`${path}.channelId: is not a string`) + if (opts.channelId_CustomCheck && !opts.channelId_CustomCheck(o.channelId)) return new Error(`${path}.channelId: custom check failed`) + + return null +} + export type NewInvoiceResponse = { invoice: string } @@ -841,20 +1156,97 @@ export const DecodeInvoiceRequestValidate = (o?: DecodeInvoiceRequest, opts: Dec return null } -export type LndGetInfoRequest = { - nodeId: number +export type PayInvoiceRequest = { + invoice: string + amount: number } -export const LndGetInfoRequestOptionalFields: [] = [] -export type LndGetInfoRequestOptions = OptionsBaseMessage & { +export const PayInvoiceRequestOptionalFields: [] = [] +export type PayInvoiceRequestOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - nodeId_CustomCheck?: (v: number) => boolean + invoice_CustomCheck?: (v: string) => boolean + amount_CustomCheck?: (v: number) => boolean } -export const LndGetInfoRequestValidate = (o?: LndGetInfoRequest, opts: LndGetInfoRequestOptions = {}, path: string = 'LndGetInfoRequest::root.'): Error | null => { +export const PayInvoiceRequestValidate = (o?: PayInvoiceRequest, opts: PayInvoiceRequestOptions = {}, path: string = 'PayInvoiceRequest::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.nodeId !== 'number') return new Error(`${path}.nodeId: is not a number`) - if (opts.nodeId_CustomCheck && !opts.nodeId_CustomCheck(o.nodeId)) return new Error(`${path}.nodeId: custom check failed`) + if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`) + if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`) + + if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`) + if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`) + + return null +} + +export type PayInvoiceResponse = { + preimage: string + amount_paid: number +} +export const PayInvoiceResponseOptionalFields: [] = [] +export type PayInvoiceResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + preimage_CustomCheck?: (v: string) => boolean + amount_paid_CustomCheck?: (v: number) => boolean +} +export const PayInvoiceResponseValidate = (o?: PayInvoiceResponse, opts: PayInvoiceResponseOptions = {}, path: string = 'PayInvoiceResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + if (typeof o.preimage !== 'string') return new Error(`${path}.preimage: is not a string`) + if (opts.preimage_CustomCheck && !opts.preimage_CustomCheck(o.preimage)) return new Error(`${path}.preimage: custom check failed`) + + if (typeof o.amount_paid !== 'number') return new Error(`${path}.amount_paid: is not a number`) + if (opts.amount_paid_CustomCheck && !opts.amount_paid_CustomCheck(o.amount_paid)) return new Error(`${path}.amount_paid: custom check failed`) + + return null +} + +export type GetUserOperationsResponse = { + latestOutgoingInvoiceOperations: UserOperations + latestIncomingInvoiceOperations: UserOperations + latestOutgoingTxOperations: UserOperations + latestIncomingTxOperations: UserOperations + latestOutgoingUserToUserPayemnts: UserOperations + latestIncomingUserToUserPayemnts: UserOperations +} +export const GetUserOperationsResponseOptionalFields: [] = [] +export type GetUserOperationsResponseOptions = OptionsBaseMessage & { + checkOptionalsAreSet?: [] + latestOutgoingInvoiceOperations_Options?: UserOperationsOptions + latestIncomingInvoiceOperations_Options?: UserOperationsOptions + latestOutgoingTxOperations_Options?: UserOperationsOptions + latestIncomingTxOperations_Options?: UserOperationsOptions + latestOutgoingUserToUserPayemnts_Options?: UserOperationsOptions + latestIncomingUserToUserPayemnts_Options?: UserOperationsOptions +} +export const GetUserOperationsResponseValidate = (o?: GetUserOperationsResponse, opts: GetUserOperationsResponseOptions = {}, path: string = 'GetUserOperationsResponse::root.'): Error | null => { + if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') + if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') + + const latestOutgoingInvoiceOperationsErr = UserOperationsValidate(o.latestOutgoingInvoiceOperations, opts.latestOutgoingInvoiceOperations_Options, `${path}.latestOutgoingInvoiceOperations`) + if (latestOutgoingInvoiceOperationsErr !== null) return latestOutgoingInvoiceOperationsErr + + + const latestIncomingInvoiceOperationsErr = UserOperationsValidate(o.latestIncomingInvoiceOperations, opts.latestIncomingInvoiceOperations_Options, `${path}.latestIncomingInvoiceOperations`) + if (latestIncomingInvoiceOperationsErr !== null) return latestIncomingInvoiceOperationsErr + + + const latestOutgoingTxOperationsErr = UserOperationsValidate(o.latestOutgoingTxOperations, opts.latestOutgoingTxOperations_Options, `${path}.latestOutgoingTxOperations`) + if (latestOutgoingTxOperationsErr !== null) return latestOutgoingTxOperationsErr + + + const latestIncomingTxOperationsErr = UserOperationsValidate(o.latestIncomingTxOperations, opts.latestIncomingTxOperations_Options, `${path}.latestIncomingTxOperations`) + if (latestIncomingTxOperationsErr !== null) return latestIncomingTxOperationsErr + + + const latestOutgoingUserToUserPayemntsErr = UserOperationsValidate(o.latestOutgoingUserToUserPayemnts, opts.latestOutgoingUserToUserPayemnts_Options, `${path}.latestOutgoingUserToUserPayemnts`) + if (latestOutgoingUserToUserPayemntsErr !== null) return latestOutgoingUserToUserPayemntsErr + + + const latestIncomingUserToUserPayemntsErr = UserOperationsValidate(o.latestIncomingUserToUserPayemnts, opts.latestIncomingUserToUserPayemnts_Options, `${path}.latestIncomingUserToUserPayemnts`) + if (latestIncomingUserToUserPayemntsErr !== null) return latestIncomingUserToUserPayemntsErr + return null } @@ -877,84 +1269,58 @@ export const LndGetInfoResponseValidate = (o?: LndGetInfoResponse, opts: LndGetI return null } -export type AddUserResponse = { - userId: string - authToken: string +export type AddAppUserRequest = { + identifier: string + fail_if_exists: boolean + balance: number } -export const AddUserResponseOptionalFields: [] = [] -export type AddUserResponseOptions = OptionsBaseMessage & { +export const AddAppUserRequestOptionalFields: [] = [] +export type AddAppUserRequestOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - userId_CustomCheck?: (v: string) => boolean - authToken_CustomCheck?: (v: string) => boolean + identifier_CustomCheck?: (v: string) => boolean + fail_if_exists_CustomCheck?: (v: boolean) => boolean + balance_CustomCheck?: (v: number) => boolean } -export const AddUserResponseValidate = (o?: AddUserResponse, opts: AddUserResponseOptions = {}, path: string = 'AddUserResponse::root.'): Error | null => { +export const AddAppUserRequestValidate = (o?: AddAppUserRequest, opts: AddAppUserRequestOptions = {}, path: string = 'AddAppUserRequest::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.userId !== 'string') return new Error(`${path}.userId: is not a string`) - if (opts.userId_CustomCheck && !opts.userId_CustomCheck(o.userId)) return new Error(`${path}.userId: custom check failed`) + if (typeof o.identifier !== 'string') return new Error(`${path}.identifier: is not a string`) + if (opts.identifier_CustomCheck && !opts.identifier_CustomCheck(o.identifier)) return new Error(`${path}.identifier: custom check failed`) - if (typeof o.authToken !== 'string') return new Error(`${path}.authToken: is not a string`) - if (opts.authToken_CustomCheck && !opts.authToken_CustomCheck(o.authToken)) return new Error(`${path}.authToken: custom check failed`) + if (typeof o.fail_if_exists !== 'boolean') return new Error(`${path}.fail_if_exists: is not a boolean`) + if (opts.fail_if_exists_CustomCheck && !opts.fail_if_exists_CustomCheck(o.fail_if_exists)) return new Error(`${path}.fail_if_exists: custom check failed`) + + if (typeof o.balance !== 'number') return new Error(`${path}.balance: is not a number`) + if (opts.balance_CustomCheck && !opts.balance_CustomCheck(o.balance)) return new Error(`${path}.balance: custom check failed`) return null } -export type AuthUserResponse = { - userId: string - authToken: string +export type AddAppInvoiceRequest = { + payer_identifier: string + http_callback_url: string + invoice_req: NewInvoiceRequest } -export const AuthUserResponseOptionalFields: [] = [] -export type AuthUserResponseOptions = OptionsBaseMessage & { +export const AddAppInvoiceRequestOptionalFields: [] = [] +export type AddAppInvoiceRequestOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - userId_CustomCheck?: (v: string) => boolean - authToken_CustomCheck?: (v: string) => boolean + payer_identifier_CustomCheck?: (v: string) => boolean + http_callback_url_CustomCheck?: (v: string) => boolean + invoice_req_Options?: NewInvoiceRequestOptions } -export const AuthUserResponseValidate = (o?: AuthUserResponse, opts: AuthUserResponseOptions = {}, path: string = 'AuthUserResponse::root.'): Error | null => { +export const AddAppInvoiceRequestValidate = (o?: AddAppInvoiceRequest, opts: AddAppInvoiceRequestOptions = {}, path: string = 'AddAppInvoiceRequest::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.userId !== 'string') return new Error(`${path}.userId: is not a string`) - if (opts.userId_CustomCheck && !opts.userId_CustomCheck(o.userId)) return new Error(`${path}.userId: custom check failed`) + if (typeof o.payer_identifier !== 'string') return new Error(`${path}.payer_identifier: is not a string`) + if (opts.payer_identifier_CustomCheck && !opts.payer_identifier_CustomCheck(o.payer_identifier)) return new Error(`${path}.payer_identifier: custom check failed`) - if (typeof o.authToken !== 'string') return new Error(`${path}.authToken: is not a string`) - if (opts.authToken_CustomCheck && !opts.authToken_CustomCheck(o.authToken)) return new Error(`${path}.authToken: custom check failed`) + if (typeof o.http_callback_url !== 'string') return new Error(`${path}.http_callback_url: is not a string`) + if (opts.http_callback_url_CustomCheck && !opts.http_callback_url_CustomCheck(o.http_callback_url)) return new Error(`${path}.http_callback_url: custom check failed`) - return null -} - -export type GetUserOperationsResponse = { - latestOutgoingInvoiceOperations: UserOperations - latestIncomingInvoiceOperations: UserOperations - latestOutgoingTxOperations: UserOperations - latestIncomingTxOperations: UserOperations -} -export const GetUserOperationsResponseOptionalFields: [] = [] -export type GetUserOperationsResponseOptions = OptionsBaseMessage & { - checkOptionalsAreSet?: [] - latestOutgoingInvoiceOperations_Options?: UserOperationsOptions - latestIncomingInvoiceOperations_Options?: UserOperationsOptions - latestOutgoingTxOperations_Options?: UserOperationsOptions - latestIncomingTxOperations_Options?: UserOperationsOptions -} -export const GetUserOperationsResponseValidate = (o?: GetUserOperationsResponse, opts: GetUserOperationsResponseOptions = {}, path: string = 'GetUserOperationsResponse::root.'): Error | null => { - if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') - if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - - const latestOutgoingInvoiceOperationsErr = UserOperationsValidate(o.latestOutgoingInvoiceOperations, opts.latestOutgoingInvoiceOperations_Options, `${path}.latestOutgoingInvoiceOperations`) - if (latestOutgoingInvoiceOperationsErr !== null) return latestOutgoingInvoiceOperationsErr - - - const latestIncomingInvoiceOperationsErr = UserOperationsValidate(o.latestIncomingInvoiceOperations, opts.latestIncomingInvoiceOperations_Options, `${path}.latestIncomingInvoiceOperations`) - if (latestIncomingInvoiceOperationsErr !== null) return latestIncomingInvoiceOperationsErr - - - const latestOutgoingTxOperationsErr = UserOperationsValidate(o.latestOutgoingTxOperations, opts.latestOutgoingTxOperations_Options, `${path}.latestOutgoingTxOperations`) - if (latestOutgoingTxOperationsErr !== null) return latestOutgoingTxOperationsErr - - - const latestIncomingTxOperationsErr = UserOperationsValidate(o.latestIncomingTxOperations, opts.latestIncomingTxOperations_Options, `${path}.latestIncomingTxOperations`) - if (latestIncomingTxOperationsErr !== null) return latestIncomingTxOperationsErr + const invoice_reqErr = NewInvoiceRequestValidate(o.invoice_req, opts.invoice_req_Options, `${path}.invoice_req`) + if (invoice_reqErr !== null) return invoice_reqErr return null diff --git a/proto/protoc-gen-pub.exe b/proto/protoc-gen-pub old mode 100644 new mode 100755 similarity index 52% rename from proto/protoc-gen-pub.exe rename to proto/protoc-gen-pub index d2d94ec4..fe77f433 Binary files a/proto/protoc-gen-pub.exe and b/proto/protoc-gen-pub differ diff --git a/proto/service/methods.proto b/proto/service/methods.proto index 918cfb7f..de135c8e 100644 --- a/proto/service/methods.proto +++ b/proto/service/methods.proto @@ -25,11 +25,19 @@ option (file_options) = { { id: "admin", name: "Admin", - encrypted:true, + //encrypted:true, context:{ key:"admin_id", value:"string" } + }, + { + id:"app", + name:"App", + context:{ + key:"app_id", + value: "string" + } } ]; }; @@ -73,11 +81,65 @@ service LightningPub { option (http_method) = "post"; option (http_route) = "/api/encryption/exchange"; }; + rpc LndGetInfo(structs.LndGetInfoRequest) returns (structs.LndGetInfoResponse){ option (auth_type) = "Admin"; option (http_method) = "post"; - option (http_route) = "/api/lnd/getinfo"; + option (http_route) = "/api/admin/lnd/getinfo"; }; + + // + + rpc AddApp(structs.AddAppRequest) returns (structs.AddAppResponse) { + option (auth_type) = "Admin"; + option (http_method) = "post"; + option (http_route) = "/api/admin/app/add"; + }; + + rpc AddAppUser(structs.AddAppUserRequest)returns (structs.AppUser) { + option (auth_type) = "App"; + option (http_method) = "post"; + option (http_route) = "/api/app/user/add"; + }; + + rpc AddAppInvoice(structs.AddAppInvoiceRequest) returns (structs.NewInvoiceResponse) { + option (auth_type) = "App"; + option (http_method) = "post"; + option (http_route) = "/api/app/add/invoice"; + } + + rpc AddAppUserInvoice(structs.AddAppUserInvoiceRequest) returns (structs.NewInvoiceResponse) { + option (auth_type) = "App"; + option (http_method) = "post"; + option (http_route) = "/api/app/user/add/invoice"; + } + + rpc GetAppUser(structs.GetAppUserRequest) returns (structs.AppUser) { + option (auth_type) = "App"; + option (http_method) = "post"; + option (http_route) = "/api/app/user/get"; + } + + rpc PayAppUserInvoice(structs.PayAppUserInvoiceRequest) returns (structs.PayAppUserInvoiceResponse) { + option (auth_type) = "App"; + option (http_method) = "post"; + option (http_route) = "/api/app/invoice/pay"; + } + + rpc SendAppUserToAppUserPayment(structs.SendAppUserToAppUserPaymentRequest) returns (structs.Empty) { + option (auth_type) = "App"; + option (http_method) = "post"; + option (http_route) = "/api/app/user/internal/pay"; + } + + rpc SendAppUserToAppPayment(structs.SendAppUserToAppPaymentRequest) returns (structs.Empty) { + option (auth_type) = "App"; + option (http_method) = "post"; + option (http_route) = "/api/app/internal/pay"; + } + + // + rpc AddUser(structs.AddUserRequest)returns (structs.AddUserResponse){ option (auth_type) = "Guest"; option (http_method) = "post"; diff --git a/proto/service/structs.proto b/proto/service/structs.proto index 984f13ff..3047553a 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -19,6 +19,69 @@ message LndGetInfoRequest { message LndGetInfoResponse { string alias = 1; } + +message AddAppRequest { + string name = 1; +} + +message AddAppResponse { + string name = 1; + string id = 2; + string auth_token = 3; +} + +message AddAppUserRequest { + string identifier = 1; + bool fail_if_exists = 2; + int64 balance = 3; +} + +message AppUser { + string identifier = 1; + UserInfo info = 2; + int64 max_withdrawable = 3; +} + +message AddAppInvoiceRequest { + string payer_identifier = 1; + string http_callback_url = 2; + NewInvoiceRequest invoice_req = 3; +} + +message AddAppUserInvoiceRequest { + string receiver_identifier = 1; + string payer_identifier = 2; + string http_callback_url = 3; + NewInvoiceRequest invoice_req = 4; +} + +message GetAppUserRequest { + string user_identifier = 1; +} + +message PayAppUserInvoiceRequest { + string user_identifier = 1; + string invoice = 2; + int64 amount = 3; +} + +message PayAppUserInvoiceResponse { + string preimage = 1; + int64 amount_paid = 2; +} + + +message SendAppUserToAppUserPaymentRequest { + string from_user_identifier = 1; + string to_user_identifier = 2; + int64 amount = 3; +} + +message SendAppUserToAppPaymentRequest { + string from_user_identifier = 1; + int64 amount = 2; +} + enum AddressType { WITNESS_PUBKEY_HASH = 0; NESTED_PUBKEY_HASH = 1; @@ -61,6 +124,7 @@ message PayInvoiceRequest{ message PayInvoiceResponse{ string preimage = 1; + int64 amount_paid = 2; } message OpenChannelRequest{ @@ -129,13 +193,18 @@ message GetUserOperationsRequest{ int64 latestOutgoingInvoice = 2; int64 latestIncomingTx = 3; int64 latestOutgoingTx = 4; + int64 latestIncomingUserToUserPayment = 5; + int64 latestOutgoingUserToUserPayment = 6; } enum UserOperationType { INCOMING_TX =0; OUTGOING_TX =1; INCOMING_INVOICE =2; OUTGOING_INVOICE=3; + OUTGOING_USER_TO_USER=4; + INCOMING_USER_TO_USER=5; } + message UserOperation{ int64 paidAtUnix=1; UserOperationType type = 2; @@ -144,14 +213,16 @@ message UserOperation{ } message UserOperations { int64 fromIndex=1; - int64 toIndex=2; - repeated UserOperation operations=3; + int64 toIndex=2; + repeated UserOperation operations=3; } message GetUserOperationsResponse{ UserOperations latestOutgoingInvoiceOperations=1; UserOperations latestIncomingInvoiceOperations=2; UserOperations latestOutgoingTxOperations=3; UserOperations latestIncomingTxOperations=4; + UserOperations latestOutgoingUserToUserPayemnts=5; + UserOperations latestIncomingUserToUserPayemnts=6 ; } message AddProductRequest { diff --git a/src/auth.ts b/src/auth.ts index 20ad2704..a0fa62f1 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,13 +1,34 @@ import { ServerOptions } from "../proto/autogenerated/ts/express_server"; +import { AdminContext } from "../proto/autogenerated/ts/types"; import Main from './services/main' const serverOptions = (mainHandler: Main): ServerOptions => { return { - AdminAuthGuard: async (authHeader) => { console.log("admin auth login with header: " + authHeader); return { admin_id: "__Admin__" } }, - UserAuthGuard: async (authHeader) => { return { user_id: mainHandler.DecodeUserToken(authHeader) } }, + AdminAuthGuard: adminAuth, + AppAuthGuard: async (authHeader) => { return { app_id: mainHandler.applicationManager.DecodeAppToken(authHeader) } }, + UserAuthGuard: async (authHeader) => { return { user_id: mainHandler.userManager.DecodeUserToken(authHeader) } }, GuestAuthGuard: async (_) => ({}), encryptCallback: async (_, b) => b, decryptCallback: async (_, b) => b, - throwErrors: true + //throwErrors: true } } + +const adminAuth = async (header: string | undefined): Promise => { + const AdminToken = process.env.ADMIN_TOKEN + if (!AdminToken) { + throw new Error("admin auth disabled") + } + if (!header) { + throw new Error("admin header not found") + } + let h = header + + if (header.startsWith("Bearer ")) { + h = header.substring("Bearer ".length) + } + if (h !== AdminToken) { + throw new Error("admin token invalid") + } + return { admin_id: "admin1" } +} export default serverOptions \ No newline at end of file diff --git a/src/index.spec.ts b/src/index.spec.ts index df1a7d9b..e28de54e 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -18,10 +18,10 @@ import { NostrRequest } from '../proto/autogenerated/ts/nostr_transport.js'; const settings = LoadNosrtSettingsFromEnv(true) const clientPrivateKey = generatePrivateKey() -const clientPublicKey = getPublicKey(Buffer.from(clientPrivateKey, "hex")) +const clientPublicKey = getPublicKey(clientPrivateKey) const serverPrivateKey = generatePrivateKey() -const serverPublicKey = getPublicKey(Buffer.from(serverPrivateKey, "hex")) +const serverPublicKey = getPublicKey(serverPrivateKey) const testPort = 4000 var userAuthHeader = "" @@ -30,6 +30,7 @@ const client = NewClient({ retrieveAdminAuth: async () => (""), retrieveGuestAuth: async () => (""), retrieveUserAuth: async () => userAuthHeader, + retrieveAppAuth: async () => (""), decryptCallback: async (b) => b, encryptCallback: async (b) => b, deviceId: "device0" @@ -111,7 +112,7 @@ export default async (d: (message: string, failure?: boolean) => void) => { const res = await client.AddUser({ name: "test", callbackUrl: "http://...", secret: "shhhhhht" }) if (res.status === 'ERROR') throw new Error(res.reason) console.log(res) - const user = await mainHandler.storage.GetUser(res.userId) + const user = await mainHandler.storage.userStorage.GetUser(res.userId) console.log(user) userAuthHeader = res.authToken d("create user ok") diff --git a/src/nostrMiddleware.ts b/src/nostrMiddleware.ts index 615bdfa9..368590e6 100644 --- a/src/nostrMiddleware.ts +++ b/src/nostrMiddleware.ts @@ -11,9 +11,9 @@ export default (serverMethods: Types.ServerMethods, mainHandler: Main, nostrSett if (!pub || !nostrSettings.allowedPubs.includes(pub)) { throw new Error("nostr pub invalid or not allowed" + pub) } - let nostrUser = await mainHandler.storage.FindNostrUser(pub) + let nostrUser = await mainHandler.storage.userStorage.FindNostrUser(pub) if (!nostrUser) { // TODO: add POW - nostrUser = await mainHandler.storage.AddNostrUser(pub) + nostrUser = await mainHandler.storage.userStorage.AddNostrUser(pub) } return { user_id: nostrUser.user.user_id } } diff --git a/src/services/lnd/addInvoiceReq.ts b/src/services/lnd/addInvoiceReq.ts index f981598b..cd350b4a 100644 --- a/src/services/lnd/addInvoiceReq.ts +++ b/src/services/lnd/addInvoiceReq.ts @@ -1,6 +1,6 @@ import { OpenChannelRequest, Invoice } from "../../../proto/lnd/lightning"; -export const AddInvoiceReq = (value: number, memo = "", privateHints = false, expiry = 60 * 60): Invoice => ({ +export const AddInvoiceReq = (value: number, memo = "", expiry = 60 * 60, privateHints = false): Invoice => ({ expiry: BigInt(expiry), memo: memo, private: privateHints, diff --git a/src/services/lnd/index.spec.ts b/src/services/lnd/index.spec.ts index cc792d12..1c5150bf 100644 --- a/src/services/lnd/index.spec.ts +++ b/src/services/lnd/index.spec.ts @@ -21,7 +21,7 @@ export default async (d: (message: string, failure?: boolean) => void) => { console.log(addr) d("new address ok") - const invoice = await lnd.NewInvoice(1000, "") + const invoice = await lnd.NewInvoice(1000, "", 60 * 60) console.log(invoice) d("new invoice ok") diff --git a/src/services/lnd/index.ts b/src/services/lnd/index.ts index 574c7e4a..fd365a41 100644 --- a/src/services/lnd/index.ts +++ b/src/services/lnd/index.ts @@ -80,6 +80,16 @@ export default class { const res = await this.lightning.getInfo({}, DeadLineMetadata()) return res.response } + + async Health() { + if (!this.ready) { + throw new Error("not ready") + } + const info = await this.GetInfo() + if (!info.syncedToChain || !info.syncedToGraph) { + throw new Error("not ready") + } + } checkReady() { if (!this.ready) throw new Error("lnd not ready, warmup required before usage") } @@ -141,9 +151,9 @@ export default class { return res.response } - async NewInvoice(value: number, memo: string): Promise { + async NewInvoice(value: number, memo: string, expiry: number): Promise { this.checkReady() - const res = await this.lightning.addInvoice(AddInvoiceReq(value, memo), DeadLineMetadata()) + const res = await this.lightning.addInvoice(AddInvoiceReq(value, memo, expiry), DeadLineMetadata()) return res.response } diff --git a/src/services/main/applicationManager.ts b/src/services/main/applicationManager.ts new file mode 100644 index 00000000..0422c9e2 --- /dev/null +++ b/src/services/main/applicationManager.ts @@ -0,0 +1,103 @@ +import jwt from 'jsonwebtoken' +import Storage from '../storage/index.js' +import * as Types from '../../../proto/autogenerated/ts/types.js' +import UserManager from './userManager.js' +import { MainSettings } from './settings.js' +import PaymentManager from './paymentManager.js' +import { InboundOptionals, defaultInvoiceExpiry } from '../storage/paymentStorage.js' +import { ApplicationUser } from '../storage/entity/ApplicationUser.js' +export default class { + storage: Storage + settings: MainSettings + userManager: UserManager + paymentManager: PaymentManager + constructor(storage: Storage, settings: MainSettings, userManager: UserManager, paymentManager: PaymentManager) { + this.storage = storage + this.settings = settings + this.userManager = userManager + this.paymentManager = paymentManager + } + SignAppToken(appId: string): string { + return jwt.sign({ appId }, this.settings.jwtSecret); + } + DecodeAppToken(token?: string): string { + if (!token) throw new Error("empty app token provided") + let t = token + if (token.startsWith("Bearer ")) { + t = token.substring("Bearer ".length) + } + if (!t) throw new Error("no app token provided") + return (jwt.verify(token, this.settings.jwtSecret) as { appId: string }).appId + } + + + async AddApp(req: Types.AddAppRequest): Promise { + const app = await this.storage.applicationStorage.AddApplication(req.name) + return { + id: app.app_id, + name: app.name, + auth_token: this.SignAppToken(app.app_id) + } + } + + async AddAppUser(appId: string, req: Types.AddAppUserRequest): Promise { + let u: ApplicationUser + if (req.fail_if_exists) { + u = await this.storage.applicationStorage.AddApplicationUser(appId, req.identifier, req.balance) + } else { + u = await this.storage.applicationStorage.GetOrCreateApplicationUser(appId, req.identifier, req.balance) + } + return { + identifier: u.identifier, + info: { + userId: u.user.user_id, + balance: u.user.balance_sats + }, + max_withdrawable: this.paymentManager.GetMaxPayableInvoice(u.user.balance_sats) + } + } + + async AddAppInvoice(appId: string, req: Types.AddAppInvoiceRequest): Promise { + const app = await this.storage.applicationStorage.GetApplication(appId) + const payer = await this.storage.applicationStorage.GetOrCreateApplicationUser(appId, req.payer_identifier, 0) + const opts: InboundOptionals = { callbackUrl: req.http_callback_url, expiry: defaultInvoiceExpiry, expectedPayer: payer.user } + return this.paymentManager.NewInvoice(app.owner.user_id, req.invoice_req, opts) + } + + async AddAppUserInvoice(appId: string, req: Types.AddAppUserInvoiceRequest): Promise { + const receiver = await this.storage.applicationStorage.GetApplicationUser(appId, req.receiver_identifier) + const payer = await this.storage.applicationStorage.GetOrCreateApplicationUser(appId, req.payer_identifier, 0) + const opts: InboundOptionals = { callbackUrl: req.http_callback_url, expiry: defaultInvoiceExpiry, expectedPayer: payer.user } + const appUserInvoice = await this.paymentManager.NewInvoice(receiver.user.user_id, req.invoice_req, opts) + return { + invoice: appUserInvoice.invoice + } + } + + async GetAppUser(appId: string, req: Types.GetAppUserRequest): Promise { + const user = await this.storage.applicationStorage.GetApplicationUser(appId, req.user_identifier) + const max = this.paymentManager.GetMaxPayableInvoice(user.user.balance_sats) + return { + max_withdrawable: max, identifier: req.user_identifier, info: { + userId: user.user.user_id, balance: user.user.balance_sats + } + } + } + + async PayAppUserInvoice(appId: string, req: Types.PayAppUserInvoiceRequest): Promise { + const appUser = await this.storage.applicationStorage.GetApplicationUser(appId, req.user_identifier) + return this.paymentManager.PayInvoice(appUser.user.user_id, req) + } + + async SendAppUserToAppUserPayment(appId: string, req: Types.SendAppUserToAppUserPaymentRequest): Promise { + const fromUser = await this.storage.applicationStorage.GetApplicationUser(appId, req.from_user_identifier) + const toUser = await this.storage.applicationStorage.GetApplicationUser(appId, req.to_user_identifier) + await this.paymentManager.SendUserToUserPayment(fromUser.user.user_id, toUser.user.user_id, req.amount) + } + + async SendAppUserToAppPayment(appId: string, req: Types.SendAppUserToAppPaymentRequest): Promise { + const fromUser = await this.storage.applicationStorage.GetApplicationUser(appId, req.from_user_identifier) + const app = await this.storage.applicationStorage.GetApplication(appId) + await this.paymentManager.SendUserToUserPayment(fromUser.user.user_id, app.owner.user_id, req.amount) + } +} \ No newline at end of file diff --git a/src/services/main/index.ts b/src/services/main/index.ts index 2d39c54d..1aaf8603 100644 --- a/src/services/main/index.ts +++ b/src/services/main/index.ts @@ -1,11 +1,12 @@ -import jwt from 'jsonwebtoken' -import { bech32 } from 'bech32' -import Storage, { LoadStorageSettingsFromEnv, StorageSettings } from '../storage/index.js' +import fetch from "node-fetch" +import Storage, { LoadStorageSettingsFromEnv } from '../storage/index.js' import * as Types from '../../../proto/autogenerated/ts/types.js' -import LND, { AddressPaidCb, InvoicePaidCb, LndSettings, LoadLndSettingsFromEnv } from '../lnd/index.js' +import LND, { AddressPaidCb, InvoicePaidCb, LoadLndSettingsFromEnv } from '../lnd/index.js' import { EnvMustBeInteger, EnvMustBeNonEmptyString } from '../helpers/envParser.js' -import { UserReceivingInvoice } from '../storage/entity/UserReceivingInvoice.js' -import ProductManager from './product.js' +import ProductManager from './productManager.js' +import ApplicationManager from './applicationManager.js' +import UserManager from './userManager.js' +import PaymentManager from './paymentManager.js' import { MainSettings } from './settings.js' export const LoadMainSettingsFromEnv = (test = false): MainSettings => { return { @@ -16,6 +17,7 @@ export const LoadMainSettingsFromEnv = (test = false): MainSettings => { outgoingTxFee: EnvMustBeInteger("SERVICE_FEE_OUTGOING_TX_PERCENT") / 100, incomingInvoiceFee: EnvMustBeInteger("SERVICE_FEE_INCOMING_INVOICE_PERCENT") / 100, outgoingInvoiceFee: EnvMustBeInteger("SERVICE_FEE_OUTGOING_INVOICE_PERCENT") / 100, + userToUserFee: EnvMustBeInteger("SERVICE_FEE_USER_TO_USER_PERCENT") / 100, serviceUrl: EnvMustBeNonEmptyString("SERVICE_URL") } } @@ -27,280 +29,69 @@ type UserOperationsSub = { newIncomingTx: (operation: Types.UserOperation) => void newOutgoingTx: (operation: Types.UserOperation) => void } -interface UserOperationInfo { - serial_id: number - paid_amount: number - paid_at_unix: number -} -const defaultLnurlPayMetadata = '[["text/plain", "lnurl pay to Lightning.pub"]]' + export default class { storage: Storage lnd: LND settings: MainSettings userOperationsSub: UserOperationsSub | null = null productManager: ProductManager + applicationManager: ApplicationManager + userManager: UserManager + paymentManager: PaymentManager + constructor(settings: MainSettings) { this.settings = settings this.storage = new Storage(settings.storageSettings) this.lnd = new LND(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb) - this.productManager = new ProductManager(this.storage, this.lnd, this.settings) - } - getServiceFee(action: Types.UserOperationType, amount: number): number { - switch (action) { - case Types.UserOperationType.INCOMING_TX: - return Math.ceil(this.settings.incomingTxFee * amount) - case Types.UserOperationType.OUTGOING_TX: - return Math.ceil(this.settings.outgoingTxFee * amount) - case Types.UserOperationType.INCOMING_INVOICE: - return Math.ceil(this.settings.incomingInvoiceFee * amount) - case Types.UserOperationType.OUTGOING_INVOICE: - return Math.ceil(this.settings.outgoingInvoiceFee * amount) - default: - throw new Error("Unknown service action type") - } + + this.userManager = new UserManager(this.storage, this.settings) + this.paymentManager = new PaymentManager(this.storage, this.lnd, this.settings) + this.productManager = new ProductManager(this.storage, this.paymentManager, this.settings) + this.applicationManager = new ApplicationManager(this.storage, this.settings, this.userManager, this.paymentManager) } + addressPaidCb: AddressPaidCb = (txOutput, address, amount) => { this.storage.StartTransaction(async tx => { - const userAddress = await this.storage.GetAddressOwner(address, tx) + const userAddress = await this.storage.paymentStorage.GetAddressOwner(address, tx) if (!userAddress) { return } - const fee = this.getServiceFee(Types.UserOperationType.INCOMING_TX, amount) + const fee = this.paymentManager.getServiceFee(Types.UserOperationType.INCOMING_TX, amount) try { // This call will fail if the transaction is already registered - const addedTx = await this.storage.AddAddressReceivingTransaction(userAddress, txOutput.hash, txOutput.index, amount, fee, tx) - await this.storage.IncrementUserBalance(userAddress.user.user_id, addedTx.paid_amount, tx) + const addedTx = await this.storage.paymentStorage.AddAddressReceivingTransaction(userAddress, txOutput.hash, txOutput.index, amount, fee, tx) + await this.storage.userStorage.IncrementUserBalance(userAddress.user.user_id, addedTx.paid_amount - fee, tx) } catch { } }) } - invoicePaidCb: InvoicePaidCb = (paymentRequest, amount) => { + invoicePaidCb: InvoicePaidCb = (paymentRequest, amount) => { this.storage.StartTransaction(async tx => { - const userInvoice = await this.storage.GetInvoiceOwner(paymentRequest, tx) + const userInvoice = await this.storage.paymentStorage.GetInvoiceOwner(paymentRequest, tx) if (!userInvoice || userInvoice.paid_at_unix > 0) { return } - const fee = this.getServiceFee(Types.UserOperationType.INCOMING_INVOICE, amount) + const fee = this.paymentManager.getServiceFee(Types.UserOperationType.INCOMING_INVOICE, amount) + const maybeApp = await this.storage.applicationStorage.IsApplicationUser(userInvoice.user.user_id) try { // This call will fail if the invoice is already registered - await this.storage.FlagInvoiceAsPaid(userInvoice, amount, fee, tx) - await this.storage.IncrementUserBalance(userInvoice.user.user_id, amount, tx) - } catch { } - }) - } - SignUserToken(userId: string): string { - return jwt.sign({ userId }, this.settings.jwtSecret); - } - - DecodeUserToken(token?: string): string { - if (!token) throw new Error("empty auth token provided") - return (jwt.verify(token, this.settings.jwtSecret) as { userId: string }).userId - } - - async AddBasicUser(req: Types.AddUserRequest): Promise { - const { user } = await this.storage.AddBasicUser(req.name, req.secret) - return { - userId: user.user_id, - authToken: this.SignUserToken(user.user_id) - } - } - - async NewAddress(userId: string, req: Types.NewAddressRequest): Promise { - const res = await this.lnd.NewAddress(req.addressType) - const userAddress = await this.storage.AddUserAddress(userId, res.address) - return { - address: userAddress.address - } - } - - async NewInvoice(userId: string, req: Types.NewInvoiceRequest): Promise { - const user = await this.storage.GetUser(userId) - const res = await this.lnd.NewInvoice(req.amountSats, req.memo) - const userInvoice = await this.storage.AddUserInvoice(user, res.paymentRequest) - return { - invoice: userInvoice.invoice - } - } - - async lockUserWithMinBalance(userId: string, minBalance: number) { - return this.storage.StartTransaction(async tx => { - const user = await this.storage.GetUser(userId, tx) - if (user.balance_sats < minBalance) { - throw new Error("insufficient balance") + await this.storage.paymentStorage.FlagInvoiceAsPaid(userInvoice, amount, fee, tx) + await this.storage.userStorage.IncrementUserBalance(userInvoice.user.user_id, amount - fee, tx) + await this.triggerPaidCallback(userInvoice.callbackUrl) + } catch { + //TODO } - // this call will fail if the user is already locked - await this.storage.LockUser(userId, tx) }) } - GetMaxPayableInvoice(balance: number): number { - const maxWithinServiceFee = Math.max(0, Math.floor(balance * (1 - this.settings.outgoingInvoiceFee))) - return this.lnd.GetMaxWithinLimit(maxWithinServiceFee) - } - async DecodeInvoice(req: Types.DecodeInvoiceRequest): Promise { - const decoded = await this.lnd.DecodeInvoice(req.invoice) - return { - amount: Number(decoded.numSatoshis) + async triggerPaidCallback(url: string) { + console.log(url) + if (!url) { + return } - } - async PayInvoice(userId: string, req: Types.PayInvoiceRequest): Promise { - const decoded = await this.lnd.DecodeInvoice(req.invoice) - if (decoded.numSatoshis !== 0n && req.amount !== 0) { - throw new Error("invoice has value, do not provide amount the the request") + try { + await fetch(url + "&ok=true") + } catch (err: any) { + console.log("error sending cb", err) } - if (decoded.numSatoshis === 0n && req.amount === 0) { - throw new Error("invoice has no value, an amount must be provided in the request") - } - const payAmount = req.amount !== 0 ? req.amount : Number(decoded.numSatoshis) - const serviceFee = this.getServiceFee(Types.UserOperationType.OUTGOING_INVOICE, payAmount) - const totalAmountToDecrement = payAmount + serviceFee - - - const routingFeeLimit = this.lnd.GetFeeLimitAmount(payAmount) - await this.lockUserWithMinBalance(userId, totalAmountToDecrement + routingFeeLimit) - const payment = await this.lnd.PayInvoice(req.invoice, req.amount, routingFeeLimit) - await this.storage.DecrementUserBalance(userId, totalAmountToDecrement + Number(payment.feeSat)) - await this.storage.UnlockUser(userId) - await this.storage.AddUserInvoicePayment(userId, req.invoice, payAmount, Number(payment.feeSat), serviceFee) - return { - preimage: payment.paymentPreimage - } - } - - async PayAddress(userId: string, req: Types.PayAddressRequest): Promise { - const estimate = await this.lnd.EstimateChainFees(req.address, req.amoutSats, req.targetConf) - const satPerVByte = Number(estimate.satPerVbyte) - const chainFees = Number(estimate.feeSat) - const total = req.amoutSats + chainFees - const serviceFee = this.getServiceFee(Types.UserOperationType.OUTGOING_INVOICE, req.amoutSats) - await this.lockUserWithMinBalance(userId, total + serviceFee) - const payment = await this.lnd.PayAddress(req.address, req.amoutSats, satPerVByte) - await this.storage.DecrementUserBalance(userId, total + serviceFee) - await this.storage.UnlockUser(userId) - await this.storage.AddUserTransactionPayment(userId, req.address, payment.txid, 0, req.amoutSats, chainFees, serviceFee) - return { - txId: payment.txid - } - } - - balanceCheckUrl(k1: string): string { - return `${this.settings.serviceUrl}/api/guest/lnurl_withdraw/info?k1=${k1}` - } - - async GetLnurlChannelLink(userId: string): Promise { - const key = await this.storage.AddUserEphemeralKey(userId, 'balanceCheck') - return { - lnurl: this.encodeLnurl(this.balanceCheckUrl(key.key)), - k1: key.key - } - } - - async GetLnurlWithdrawInfo(balanceCheckK1: string): Promise { - const key = await this.storage.UseUserEphemeralKey(balanceCheckK1, 'balanceCheck') - const maxWithdrawable = this.GetMaxPayableInvoice(key.user.balance_sats) - const callbackK1 = await this.storage.AddUserEphemeralKey(key.user.user_id, 'withdraw') - const newBalanceCheckK1 = await this.storage.AddUserEphemeralKey(key.user.user_id, 'balanceCheck') - const payInfoK1 = await this.storage.AddUserEphemeralKey(key.user.user_id, 'pay') - return { - tag: "withdrawRequest", - callback: `${this.settings.serviceUrl}/api/guest/lnurl_withdraw/handle`, - defaultDescription: "lnurl withdraw from lightning.pub", - k1: callbackK1.key, - maxWithdrawable: maxWithdrawable, - minWithdrawable: 0, - balanceCheck: this.balanceCheckUrl(newBalanceCheckK1.key), - payLink: `${this.settings.serviceUrl}/api/guest/lnurl_pay/info?k1=${payInfoK1.key}`, - } - } - - async HandleLnurlWithdraw(k1: string, invoice: string): Promise { - const key = await this.storage.UseUserEphemeralKey(k1, 'withdraw') - this.PayInvoice(key.user.user_id, { - invoice: invoice, - amount: 0 - }).catch(err => { - console.error("error sending payment for lnurl withdraw to ", key.user.user_id, err) - }) - } - - async GetLnurlPayInfo(payInfoK1: string): Promise { - const key = await this.storage.UseUserEphemeralKey(payInfoK1, 'payInfo') - const payK1 = await this.storage.AddUserEphemeralKey(key.user.user_id, 'pay') - return { - tag: 'payRequest', - callback: `${this.settings.serviceUrl}/api/guest/lnurl_pay/handle?k1=${payK1.key}`, - maxSendable: 10000000, - minSendable: 0, - metadata: defaultLnurlPayMetadata - } - } - - async HandleLnurlPay(payK1: string, amountMillis: number): Promise { - const key = await this.storage.UseUserEphemeralKey(payK1, 'pay') - const sats = amountMillis / 1000 - if (!Number.isInteger(sats)) { - throw new Error("millisats amount must be integer sats amount") - } - const invoice = await this.NewInvoice(key.user.user_id, { - amountSats: sats, - memo: defaultLnurlPayMetadata - }) - return { - pr: invoice.invoice, - routes: [] - } - } - - - async OpenChannel(userId: string, req: Types.OpenChannelRequest): Promise { throw new Error("WIP") } - - - mapOperations(operations: UserOperationInfo[], type: Types.UserOperationType, inbound: boolean): Types.UserOperations { - if (operations.length === 0) { - return { - fromIndex: 0, - toIndex: 0, - operations: [] - } - } - return { - toIndex: operations[0].serial_id, - fromIndex: operations[operations.length - 1].serial_id, - operations: operations.map((o: UserOperationInfo): Types.UserOperation => ({ - inbound, - type, - amount: o.paid_amount, - paidAtUnix: o.paid_at_unix - })) - } - } - - async GetUserInfo(userId: string): Promise { - const user = await this.storage.GetUser(userId) - return { - userId: userId, - balance: user.balance_sats - } - } - - async GetUserOperations(userId: string, req: Types.GetUserOperationsRequest): Promise { - const [outgoingInvoices, outgoingTransactions, incomingInvoices, incomingTransactions] = await Promise.all([ - this.storage.GetUserInvoicePayments(userId, req.latestOutgoingInvoice), - this.storage.GetUserTransactionPayments(userId, req.latestOutgoingTx), - this.storage.GetUserInvoicesFlaggedAsPaid(userId, req.latestIncomingInvoice), - this.storage.GetUserReceivingTransactions(userId, req.latestIncomingTx) - ]) - return { - latestIncomingInvoiceOperations: this.mapOperations(incomingInvoices, Types.UserOperationType.INCOMING_INVOICE, true), - latestIncomingTxOperations: this.mapOperations(incomingTransactions, Types.UserOperationType.INCOMING_TX, true), - latestOutgoingInvoiceOperations: this.mapOperations(outgoingInvoices, Types.UserOperationType.OUTGOING_INVOICE, false), - latestOutgoingTxOperations: this.mapOperations(outgoingTransactions, Types.UserOperationType.OUTGOING_TX, false) - } - } - - encodeLnurl(base: string) { - if (!base || typeof base !== 'string') { - throw new Error("provided string for lnurl encode is not a string or is an empty string") - } - let words = bech32.toWords(Buffer.from(base, 'utf8')); - return bech32.encode('lnurl', words, 1023); } } \ No newline at end of file diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts new file mode 100644 index 00000000..6f6a310a --- /dev/null +++ b/src/services/main/paymentManager.ts @@ -0,0 +1,252 @@ +import { bech32 } from 'bech32' +import Storage from '../storage/index.js' +import * as Types from '../../../proto/autogenerated/ts/types.js' +import LND from '../lnd/index.js' +import { MainSettings } from './settings.js' +import { InboundOptionals, defaultInvoiceExpiry } from '../storage/paymentStorage.js' +interface UserOperationInfo { + serial_id: number + paid_amount: number + paid_at_unix: number +} +const defaultLnurlPayMetadata = '[["text/plain", "lnurl pay to Lightning.pub"]]' + +export default class { + storage: Storage + settings: MainSettings + lnd: LND + constructor(storage: Storage, lnd: LND, settings: MainSettings) { + this.storage = storage + this.settings = settings + this.lnd = lnd + } + getServiceFee(action: Types.UserOperationType, amount: number): number { + switch (action) { + case Types.UserOperationType.INCOMING_TX: + return Math.ceil(this.settings.incomingTxFee * amount) + case Types.UserOperationType.OUTGOING_TX: + return Math.ceil(this.settings.outgoingTxFee * amount) + case Types.UserOperationType.INCOMING_INVOICE: + return Math.ceil(this.settings.incomingInvoiceFee * amount) + case Types.UserOperationType.OUTGOING_INVOICE: + return Math.ceil(this.settings.outgoingInvoiceFee * amount) + case Types.UserOperationType.OUTGOING_USER_TO_USER || Types.UserOperationType.INCOMING_USER_TO_USER: + return Math.ceil(this.settings.userToUserFee * amount) + default: + throw new Error("Unknown service action type") + } + } + + async NewAddress(userId: string, req: Types.NewAddressRequest): Promise { + const res = await this.lnd.NewAddress(req.addressType) + const userAddress = await this.storage.paymentStorage.AddUserAddress(userId, res.address) + return { + address: userAddress.address + } + } + + async NewInvoice(userId: string, req: Types.NewInvoiceRequest, options: InboundOptionals = { expiry: defaultInvoiceExpiry }): Promise { + const user = await this.storage.userStorage.GetUser(userId) + const res = await this.lnd.NewInvoice(req.amountSats, req.memo, options.expiry) + const userInvoice = await this.storage.paymentStorage.AddUserInvoice(user, res.paymentRequest, options) + return { + invoice: userInvoice.invoice + } + } + + async lockUserWithMinBalance(userId: string, minBalance: number) { + return this.storage.StartTransaction(async tx => { + const user = await this.storage.userStorage.GetUser(userId, tx) + if (user.balance_sats < minBalance) { + throw new Error("insufficient balance") + } + // this call will fail if the user is already locked + await this.storage.userStorage.LockUser(userId, tx) + }) + } + + GetMaxPayableInvoice(balance: number): number { + const maxWithinServiceFee = Math.max(0, Math.floor(balance * (1 - this.settings.outgoingInvoiceFee))) + return this.lnd.GetMaxWithinLimit(maxWithinServiceFee) + } + async DecodeInvoice(req: Types.DecodeInvoiceRequest): Promise { + const decoded = await this.lnd.DecodeInvoice(req.invoice) + return { + amount: Number(decoded.numSatoshis) + } + } + async PayInvoice(userId: string, req: Types.PayInvoiceRequest): Promise { + const decoded = await this.lnd.DecodeInvoice(req.invoice) + if (decoded.numSatoshis !== 0n && req.amount !== 0) { + throw new Error("invoice has value, do not provide amount the the request") + } + if (decoded.numSatoshis === 0n && req.amount === 0) { + throw new Error("invoice has no value, an amount must be provided in the request") + } + const payAmount = req.amount !== 0 ? req.amount : Number(decoded.numSatoshis) + const serviceFee = this.getServiceFee(Types.UserOperationType.OUTGOING_INVOICE, payAmount) + const totalAmountToDecrement = payAmount + serviceFee + + + const routingFeeLimit = this.lnd.GetFeeLimitAmount(payAmount) + await this.lockUserWithMinBalance(userId, totalAmountToDecrement + routingFeeLimit) + const payment = await this.lnd.PayInvoice(req.invoice, req.amount, routingFeeLimit) + await this.storage.userStorage.DecrementUserBalance(userId, totalAmountToDecrement + Number(payment.feeSat)) + await this.storage.userStorage.UnlockUser(userId) + await this.storage.paymentStorage.AddUserInvoicePayment(userId, req.invoice, payAmount, Number(payment.feeSat), serviceFee) + return { + preimage: payment.paymentPreimage, + amount_paid: Number(payment.valueSat) + } + } + + async PayAddress(userId: string, req: Types.PayAddressRequest): Promise { + const estimate = await this.lnd.EstimateChainFees(req.address, req.amoutSats, req.targetConf) + const satPerVByte = Number(estimate.satPerVbyte) + const chainFees = Number(estimate.feeSat) + const total = req.amoutSats + chainFees + const serviceFee = this.getServiceFee(Types.UserOperationType.OUTGOING_INVOICE, req.amoutSats) + await this.lockUserWithMinBalance(userId, total + serviceFee) + const payment = await this.lnd.PayAddress(req.address, req.amoutSats, satPerVByte) + await this.storage.userStorage.DecrementUserBalance(userId, total + serviceFee) + await this.storage.userStorage.UnlockUser(userId) + await this.storage.paymentStorage.AddUserTransactionPayment(userId, req.address, payment.txid, 0, req.amoutSats, chainFees, serviceFee) + return { + txId: payment.txid + } + } + + balanceCheckUrl(k1: string): string { + return `${this.settings.serviceUrl}/api/guest/lnurl_withdraw/info?k1=${k1}` + } + + async GetLnurlChannelLink(userId: string): Promise { + const key = await this.storage.paymentStorage.AddUserEphemeralKey(userId, 'balanceCheck') + return { + lnurl: this.encodeLnurl(this.balanceCheckUrl(key.key)), + k1: key.key + } + } + + async GetLnurlWithdrawInfo(balanceCheckK1: string): Promise { + const key = await this.storage.paymentStorage.UseUserEphemeralKey(balanceCheckK1, 'balanceCheck') + const maxWithdrawable = this.GetMaxPayableInvoice(key.user.balance_sats) + const callbackK1 = await this.storage.paymentStorage.AddUserEphemeralKey(key.user.user_id, 'withdraw') + const newBalanceCheckK1 = await this.storage.paymentStorage.AddUserEphemeralKey(key.user.user_id, 'balanceCheck') + const payInfoK1 = await this.storage.paymentStorage.AddUserEphemeralKey(key.user.user_id, 'pay') + return { + tag: "withdrawRequest", + callback: `${this.settings.serviceUrl}/api/guest/lnurl_withdraw/handle`, + defaultDescription: "lnurl withdraw from lightning.pub", + k1: callbackK1.key, + maxWithdrawable: maxWithdrawable, + minWithdrawable: 0, + balanceCheck: this.balanceCheckUrl(newBalanceCheckK1.key), + payLink: `${this.settings.serviceUrl}/api/guest/lnurl_pay/info?k1=${payInfoK1.key}`, + } + } + + async HandleLnurlWithdraw(k1: string, invoice: string): Promise { + const key = await this.storage.paymentStorage.UseUserEphemeralKey(k1, 'withdraw') + this.PayInvoice(key.user.user_id, { + invoice: invoice, + amount: 0 + }).catch(err => { + console.error("error sending payment for lnurl withdraw to ", key.user.user_id, err) + }) + } + + async GetLnurlPayInfo(payInfoK1: string): Promise { + const key = await this.storage.paymentStorage.UseUserEphemeralKey(payInfoK1, 'payInfo') + const payK1 = await this.storage.paymentStorage.AddUserEphemeralKey(key.user.user_id, 'pay') + return { + tag: 'payRequest', + callback: `${this.settings.serviceUrl}/api/guest/lnurl_pay/handle?k1=${payK1.key}`, + maxSendable: 10000000, + minSendable: 0, + metadata: defaultLnurlPayMetadata + } + } + + async HandleLnurlPay(payK1: string, amountMillis: number): Promise { + const key = await this.storage.paymentStorage.UseUserEphemeralKey(payK1, 'pay') + const sats = amountMillis / 1000 + if (!Number.isInteger(sats)) { + throw new Error("millisats amount must be integer sats amount") + } + const invoice = await this.NewInvoice(key.user.user_id, { + amountSats: sats, + memo: defaultLnurlPayMetadata + }) + return { + pr: invoice.invoice, + routes: [] + } + } + + + async OpenChannel(userId: string, req: Types.OpenChannelRequest): Promise { throw new Error("WIP") } + + + mapOperations(operations: UserOperationInfo[], type: Types.UserOperationType, inbound: boolean): Types.UserOperations { + if (operations.length === 0) { + return { + fromIndex: 0, + toIndex: 0, + operations: [] + } + } + return { + toIndex: operations[0].serial_id, + fromIndex: operations[operations.length - 1].serial_id, + operations: operations.map((o: UserOperationInfo): Types.UserOperation => ({ + inbound, + type, + amount: o.paid_amount, + paidAtUnix: o.paid_at_unix + })) + } + } + + async GetUserOperations(userId: string, req: Types.GetUserOperationsRequest): Promise { + const [outgoingInvoices, outgoingTransactions, incomingInvoices, incomingTransactions, incomingUserToUser, outgoingUserToUser] = await Promise.all([ + this.storage.paymentStorage.GetUserInvoicePayments(userId, req.latestOutgoingInvoice), + this.storage.paymentStorage.GetUserTransactionPayments(userId, req.latestOutgoingTx), + this.storage.paymentStorage.GetUserInvoicesFlaggedAsPaid(userId, req.latestIncomingInvoice), + this.storage.paymentStorage.GetUserReceivingTransactions(userId, req.latestIncomingTx), + this.storage.paymentStorage.GetUserToUserReceivedPayments(userId, req.latestIncomingUserToUserPayment), + this.storage.paymentStorage.GetUserToUserSentPayments(userId, req.latestOutgoingUserToUserPayment) + ]) + return { + latestIncomingInvoiceOperations: this.mapOperations(incomingInvoices, Types.UserOperationType.INCOMING_INVOICE, true), + latestIncomingTxOperations: this.mapOperations(incomingTransactions, Types.UserOperationType.INCOMING_TX, true), + latestOutgoingInvoiceOperations: this.mapOperations(outgoingInvoices, Types.UserOperationType.OUTGOING_INVOICE, false), + latestOutgoingTxOperations: this.mapOperations(outgoingTransactions, Types.UserOperationType.OUTGOING_TX, false), + latestIncomingUserToUserPayemnts: this.mapOperations(incomingUserToUser, Types.UserOperationType.INCOMING_USER_TO_USER, true), + latestOutgoingUserToUserPayemnts: this.mapOperations(outgoingUserToUser, Types.UserOperationType.OUTGOING_USER_TO_USER, false) + } + } + + async SendUserToUserPayment(fromUserId: string, toUserId: string, amount: number) { + await this.storage.StartTransaction(async tx => { + const fromUser = await this.storage.userStorage.GetUser(fromUserId, tx) + const toUser = await this.storage.userStorage.GetUser(toUserId, tx) + if (fromUser.balance_sats < amount) { + throw new Error("not enough balance to send user to user payment") + } + const fee = this.getServiceFee(Types.UserOperationType.OUTGOING_USER_TO_USER, amount) + const toIncrement = amount - fee + await this.storage.userStorage.DecrementUserBalance(fromUser.user_id, amount, tx) + await this.storage.userStorage.IncrementUserBalance(toUser.user_id, toIncrement, tx) + await this.storage.paymentStorage.AddUserToUserPayment(fromUserId, toUserId, amount, fee) + }) + } + + encodeLnurl(base: string) { + if (!base || typeof base !== 'string') { + throw new Error("provided string for lnurl encode is not a string or is an empty string") + } + let words = bech32.toWords(Buffer.from(base, 'utf8')); + return bech32.encode('lnurl', words, 1023); + } +} \ No newline at end of file diff --git a/src/services/main/product.ts b/src/services/main/productManager.ts similarity index 58% rename from src/services/main/product.ts rename to src/services/main/productManager.ts index cb466999..b2d08238 100644 --- a/src/services/main/product.ts +++ b/src/services/main/productManager.ts @@ -3,20 +3,22 @@ import * as Types from '../../../proto/autogenerated/ts/types.js' import LND from '../lnd/index.js' import { MainSettings } from './settings.js' +import PaymentManager from './paymentManager.js' +import { defaultInvoiceExpiry } from '../storage/paymentStorage.js' export default class { - storage: Storage settings: MainSettings - lnd: LND - constructor(storage: Storage, lnd: LND, settings: MainSettings) { + paymentManager: PaymentManager + + constructor(storage: Storage, paymentManager: PaymentManager, settings: MainSettings) { this.storage = storage this.settings = settings - this.lnd = lnd + this.paymentManager = paymentManager } async AddProduct(userId: string, req: Types.AddProductRequest): Promise { - const user = await this.storage.GetUser(userId) + const user = await this.storage.userStorage.GetUser(userId) const newProduct = await this.storage.productStorage.AddProduct(req.name, req.price_sats, user) return { id: newProduct.product_id, @@ -27,10 +29,11 @@ export default class { async NewProductInvoice(id: string): Promise { const product = await this.storage.productStorage.GetProduct(id) - const newInvoice = await this.lnd.NewInvoice(product.price_sats, product.name) - await this.storage.AddUserInvoice(product.owner, newInvoice.paymentRequest, product) + const productInvoice = await this.paymentManager.NewInvoice(product.owner.user_id, { + amountSats: product.price_sats, memo: product.name + }, { product, expiry: defaultInvoiceExpiry }) return { - invoice: newInvoice.paymentRequest + invoice: productInvoice.invoice } } } \ No newline at end of file diff --git a/src/services/main/settings.ts b/src/services/main/settings.ts index 6965351b..b1e9ebb8 100644 --- a/src/services/main/settings.ts +++ b/src/services/main/settings.ts @@ -8,5 +8,7 @@ export type MainSettings = { outgoingTxFee: number incomingInvoiceFee: number outgoingInvoiceFee: number + userToUserFee: number serviceUrl: string + } \ No newline at end of file diff --git a/src/services/main/userManager.ts b/src/services/main/userManager.ts new file mode 100644 index 00000000..ca5dfffd --- /dev/null +++ b/src/services/main/userManager.ts @@ -0,0 +1,41 @@ +import jwt from 'jsonwebtoken' +import Storage from '../storage/index.js' +import * as Types from '../../../proto/autogenerated/ts/types.js' + +import { MainSettings } from './settings.js' +export default class { + storage: Storage + settings: MainSettings + constructor(storage: Storage, settings: MainSettings) { + this.storage = storage + this.settings = settings + } + SignUserToken(userId: string): string { + return jwt.sign({ userId }, this.settings.jwtSecret); + } + + DecodeUserToken(token?: string): string { + if (!token) throw new Error("empty user token provided") + let t = token + if (token.startsWith("Bearer ")) { + t = token.substring("Bearer ".length) + } + if (!t) throw new Error("no user token provided") + return (jwt.verify(token, this.settings.jwtSecret) as { userId: string }).userId + } + + async AddBasicUser(req: Types.AddUserRequest): Promise { + const { user } = await this.storage.userStorage.AddBasicUser(req.name, req.secret) + return { + userId: user.user_id, + authToken: this.SignUserToken(user.user_id) + } + } + async GetUserInfo(userId: string): Promise { + const user = await this.storage.userStorage.GetUser(userId) + return { + userId: userId, + balance: user.balance_sats + } + } +} \ No newline at end of file diff --git a/src/services/nostr/handler.ts b/src/services/nostr/handler.ts index 5031c867..052e8394 100644 --- a/src/services/nostr/handler.ts +++ b/src/services/nostr/handler.ts @@ -1,6 +1,4 @@ -import { relayPool, Subscription, Event } from 'nostr-tools' -//@ts-ignore -import { decrypt, encrypt } from 'nostr-tools/nip04.js' +import { SimplePool, Sub, Event, UnsignedEvent, nip04, getEventHash, signEvent } from 'nostr-tools' const handledEvents: string[] = [] // TODO: - big memory leak here, add TTL export type NostrSettings = { privateKey: string @@ -74,52 +72,46 @@ const sendToNostr = (pub: string, message: string) => { send({ type: 'ready' }) export default class Handler { - pool = relayPool() + pool = new SimplePool() settings: NostrSettings - sub: Subscription + sub: Sub constructor(settings: NostrSettings, eventCallback: (event: NostrEvent) => void) { this.settings = settings - this.pool.setPrivateKey(settings.privateKey) - settings.relays.forEach(relay => { - try { - this.pool.addRelay(relay, { read: true, write: true }) - } catch (e) { - console.error("cannot add relay:", relay) - } - }); - this.sub = this.pool.sub({ - //@ts-ignore - filter: { + console.log(settings) + this.sub = this.pool.sub(settings.relays, [ + { since: Math.ceil(Date.now() / 1000), kinds: [4], '#p': [settings.publicKey], - }, - cb: async (e, relay) => { - if (e.kind !== 4 || !e.pubkey) { - return - } - //@ts-ignore - const eventId = e.id as string - if (handledEvents.includes(eventId)) { - console.log("event already handled") - return - } - handledEvents.push(eventId) - eventCallback({ id: eventId, content: decrypt(this.settings.privateKey, e.pubkey, e.content), pub: e.pubkey }) } + ]) + this.sub.on("event", async (e) => { + if (e.kind !== 4 || !e.pubkey) { + return + } + //@ts-ignore + const eventId = e.id as string + if (handledEvents.includes(eventId)) { + console.log("event already handled") + return + } + handledEvents.push(eventId) + eventCallback({ id: eventId, content: await nip04.decrypt(this.settings.privateKey, e.pubkey, e.content), pub: e.pubkey }) }) } - Send(nostrPub: string, message: string) { - this.pool.publish({ - content: encrypt(this.settings.privateKey, nostrPub, message), + async Send(nostrPub: string, message: string) { + const event: UnsignedEvent = { + content: await nip04.encrypt(this.settings.privateKey, nostrPub, message), created_at: Math.floor(Date.now() / 1000), kind: 4, pubkey: this.settings.publicKey, - //@ts-ignore - tags: [['p', nostrPub]] - }, (status, url) => { - console.log("sent message to", nostrPub) // TODO - }) + tags: [['p', nostrPub]], + } + const eventId = getEventHash(event) + const sign = signEvent(event, this.settings.privateKey) + const op = this.pool.publish(this.settings.relays, + { ...event, id: eventId, sig: sign }) + op.on('failed', (reason: string) => { console.log('failed to send message cuz: ', reason) }) } } \ No newline at end of file diff --git a/src/services/nostr/index.spec.ts b/src/services/nostr/index.spec.ts index 0b556508..72dfbf4c 100644 --- a/src/services/nostr/index.spec.ts +++ b/src/services/nostr/index.spec.ts @@ -8,10 +8,10 @@ export const ignore = true const settings = LoadNosrtSettingsFromEnv(true) const clientPrivateKey = generatePrivateKey() -const clientPublicKey = getPublicKey(Buffer.from(clientPrivateKey, "hex")) +const clientPublicKey = getPublicKey(clientPrivateKey) const serverPrivateKey = generatePrivateKey() -const serverPublicKey = getPublicKey(Buffer.from(serverPrivateKey, "hex")) +const serverPublicKey = getPublicKey(serverPrivateKey) let clientNostr: NostrHandler let serverNostr: NostrHandler diff --git a/src/services/serverMethods/index.ts b/src/services/serverMethods/index.ts index 98026917..b4f278f3 100644 --- a/src/services/serverMethods/index.ts +++ b/src/services/serverMethods/index.ts @@ -3,7 +3,7 @@ import Main from '../main/index.js' export default (mainHandler: Main): Types.ServerMethods => { return { EncryptionExchange: async (ctx, req) => { }, - Health: async (ctx) => { }, + Health: async (ctx) => { await mainHandler.lnd.Health() }, LndGetInfo: async (ctx) => { const info = await mainHandler.lnd.GetInfo() return { alias: info.alias } @@ -15,16 +15,16 @@ export default (mainHandler: Main): Types.ServerMethods => { secret_CustomCheck: secret => secret.length >= 8 }) if (err != null) throw new Error(err.message) - return mainHandler.AddBasicUser(req) + return mainHandler.userManager.AddBasicUser(req) }, AuthUser: async (ctx, req) => { throw new Error("unimplemented") }, GetUserInfo: async (ctx) => { - return mainHandler.GetUserInfo(ctx.user_id) + return mainHandler.userManager.GetUserInfo(ctx.user_id) }, GetUserOperations: async (ctx, req) => { - return mainHandler.GetUserOperations(ctx.user_id, req) + return mainHandler.paymentManager.GetUserOperations(ctx.user_id, req) }, OpenChannel: async (ctx, req) => { const err = Types.OpenChannelRequestValidate(req, { @@ -33,10 +33,10 @@ export default (mainHandler: Main): Types.ServerMethods => { destination_CustomCheck: dest => dest !== "" }) if (err != null) throw new Error(err.message) - return mainHandler.OpenChannel(ctx.user_id, req) + return mainHandler.paymentManager.OpenChannel(ctx.user_id, req) }, NewAddress: async (ctx, req) => { - return mainHandler.NewAddress(ctx.user_id, req) + return mainHandler.paymentManager.NewAddress(ctx.user_id, req) }, PayAddress: async (ctx, req) => { const err = Types.PayAddressRequestValidate(req, { @@ -45,41 +45,41 @@ export default (mainHandler: Main): Types.ServerMethods => { targetConf_CustomCheck: target => target > 0 }) if (err != null) throw new Error(err.message) - return mainHandler.PayAddress(ctx.user_id, req) + return mainHandler.paymentManager.PayAddress(ctx.user_id, req) }, NewInvoice: async (ctx, req) => { - return mainHandler.NewInvoice(ctx.user_id, req) + return mainHandler.paymentManager.NewInvoice(ctx.user_id, req) }, DecodeInvoice: async (ctx, req) => { - return mainHandler.DecodeInvoice(req) + return mainHandler.paymentManager.DecodeInvoice(req) }, PayInvoice: async (ctx, req) => { const err = Types.PayInvoiceRequestValidate(req, { invoice_CustomCheck: invoice => invoice !== '' }) if (err != null) throw new Error(err.message) - return mainHandler.PayInvoice(ctx.user_id, req) + return mainHandler.paymentManager.PayInvoice(ctx.user_id, req) }, GetLnurlWithdrawLink: async (ctx) => { - return mainHandler.GetLnurlChannelLink(ctx.user_id) + return mainHandler.paymentManager.GetLnurlChannelLink(ctx.user_id) }, GetLnurlWithdrawInfo: async (ctx) => { if (!ctx.k1) { throw new Error("invalid lnurl withdraw to get info") } - return mainHandler.GetLnurlWithdrawInfo(ctx.k1) + return mainHandler.paymentManager.GetLnurlWithdrawInfo(ctx.k1) }, HandleLnurlWithdraw: async (ctx) => { if (!ctx.k1 || !ctx.pr) { throw new Error("invalid lnurl withdraw to handle") } - return mainHandler.HandleLnurlWithdraw(ctx.k1, ctx.pr) + return mainHandler.paymentManager.HandleLnurlWithdraw(ctx.k1, ctx.pr) }, GetLnurlPayInfo: async (ctx) => { if (!ctx.k1) { throw new Error("invalid lnurl pay to get info") } - return mainHandler.GetLnurlPayInfo(ctx.k1) + return mainHandler.paymentManager.GetLnurlPayInfo(ctx.k1) }, HandleLnurlPay: async (ctx) => { if (!ctx.k1 || !ctx.amount) { @@ -88,7 +88,7 @@ export default (mainHandler: Main): Types.ServerMethods => { if (isNaN(+ctx.amount)) { throw new Error("invalid amount in lnurl pay to handle") } - return mainHandler.HandleLnurlPay(ctx.k1, +ctx.amount) + return mainHandler.paymentManager.HandleLnurlPay(ctx.k1, +ctx.amount) }, AddProduct: async (ctx, req) => { return mainHandler.productManager.AddProduct(ctx.user_id, req) @@ -102,5 +102,66 @@ export default (mainHandler: Main): Types.ServerMethods => { GetLNURLChannelLink: async (ctx) => { throw new Error("unimplemented") }, + AddApp: async (ctx, req) => { + const err = Types.AddAppRequestValidate(req, { + name_CustomCheck: name => name !== '' + }) + if (err != null) throw new Error(err.message) + return mainHandler.applicationManager.AddApp(req) + }, + AddAppUser: async (ctx, req) => { + const err = Types.AddAppUserRequestValidate(req, { + identifier_CustomCheck: id => id !== '' + }) + if (err != null) throw new Error(err.message) + return mainHandler.applicationManager.AddAppUser(ctx.app_id, req) + }, + AddAppInvoice: async (ctx, req) => { + const err = Types.AddAppInvoiceRequestValidate(req, { + payer_identifier_CustomCheck: id => id !== '', + }) + if (err != null) throw new Error(err.message) + console.log(req) + return mainHandler.applicationManager.AddAppInvoice(ctx.app_id, req) + }, + AddAppUserInvoice: async (ctx, req) => { + const err = Types.AddAppUserInvoiceRequestValidate(req, { + payer_identifier_CustomCheck: id => id !== '', + receiver_identifier_CustomCheck: id => id !== '', + }) + if (err != null) throw new Error(err.message) + return mainHandler.applicationManager.AddAppUserInvoice(ctx.app_id, req) + }, + GetAppUser: async (ctx, req) => { + const err = Types.GetAppUserRequestValidate(req, { + user_identifier_CustomCheck: id => id !== '', + }) + if (err != null) throw new Error(err.message) + return mainHandler.applicationManager.GetAppUser(ctx.app_id, req) + }, + PayAppUserInvoice: async (ctx, req) => { + const err = Types.PayAppUserInvoiceRequestValidate(req, { + user_identifier_CustomCheck: id => id !== '', + }) + if (err != null) throw new Error(err.message) + return mainHandler.applicationManager.PayAppUserInvoice(ctx.app_id, req) + }, + SendAppUserToAppUserPayment: async (ctx, req) => { + const err = Types.SendAppUserToAppUserPaymentRequestValidate(req, { + to_user_identifier_CustomCheck: id => id !== '', + from_user_identifier_CustomCheck: id => id !== '', + amount_CustomCheck: amount => amount > 0 + }) + if (err != null) throw new Error(err.message) + mainHandler.applicationManager.SendAppUserToAppUserPayment(ctx.app_id, req) + }, + SendAppUserToAppPayment: async (ctx, req) => { + const err = Types.SendAppUserToAppPaymentRequestValidate(req, { + from_user_identifier_CustomCheck: id => id !== '', + amount_CustomCheck: amount => amount > 0 + }) + if (err != null) throw new Error(err.message) + mainHandler.applicationManager.SendAppUserToAppPayment(ctx.app_id, req) + } } } \ No newline at end of file diff --git a/src/services/storage/applicationStorage.ts b/src/services/storage/applicationStorage.ts new file mode 100644 index 00000000..6ce542e5 --- /dev/null +++ b/src/services/storage/applicationStorage.ts @@ -0,0 +1,78 @@ +import crypto from 'crypto'; +import { DataSource, EntityManager } from "typeorm" +import { Application } from "./entity/Application.js" +import UserStorage from './userStorage.js'; +import { ApplicationUser } from './entity/ApplicationUser.js'; +export default class { + DB: DataSource | EntityManager + userStorage: UserStorage + constructor(DB: DataSource | EntityManager, userStorage: UserStorage) { + this.DB = DB + this.userStorage = userStorage + } + + async AddApplication(name: string, entityManager = this.DB): Promise { + const owner = await this.userStorage.AddUser(0, entityManager) + const repo = entityManager.getRepository(Application) + const newApplication = repo.create({ + app_id: crypto.randomBytes(32).toString('hex'), + name, + owner + }) + return repo.save(newApplication) + } + + async GetApplication(appId: string, entityManager = this.DB): Promise { + const found = await entityManager.getRepository(Application).findOne({ + where: { + app_id: appId + } + }) + if (!found) { + throw new Error(`application ${appId} not found`) + } + return found + } + + async AddApplicationUser(appId: string, userIdentifier: string, balance: number) { + return this.DB.transaction(async tx => { + const user = await this.userStorage.AddUser(balance, tx) + const repo = tx.getRepository(ApplicationUser) + const appUser = repo.create({ + user: user, + application: await this.GetApplication(appId), + identifier: userIdentifier, + }) + return repo.save(appUser) + }) + } + + GetApplicationUserIfExists(appId: string, userIdentifier: string, entityManager = this.DB): Promise { + return entityManager.getRepository(ApplicationUser).findOne({ where: { identifier: userIdentifier, application: { app_id: appId } } }) + } + + async GetOrCreateApplicationUser(appId: string, userIdentifier: string, balance: number, entityManager = this.DB): Promise { + const found = await this.GetApplicationUserIfExists(appId, userIdentifier, entityManager) + if (found) { + return found + } + return this.AddApplicationUser(appId, userIdentifier, balance) + } + + async GetApplicationUser(appId: string, userIdentifier: string, entityManager = this.DB): Promise { + const found = await this.GetApplicationUserIfExists(appId, userIdentifier, entityManager) + if (!found) { + throw new Error(`application user ${userIdentifier} not found`) + } + + if (found.application.app_id !== appId) { + console.log(found, appId) + throw new Error("requested user does not belong to requestor application") + } + return found + } + + async IsApplicationUser(userId: string, entityManager = this.DB): Promise { + return await entityManager.getRepository(ApplicationUser).findOne({ where: { user: { user_id: userId } } }) + } +} \ No newline at end of file diff --git a/src/services/storage/db.ts b/src/services/storage/db.ts index f0f93e05..f75c618b 100644 --- a/src/services/storage/db.ts +++ b/src/services/storage/db.ts @@ -11,6 +11,9 @@ import { UserNostrAuth } from "./entity/UserNostrAuth.js" import { UserBasicAuth } from "./entity/UserBasicAuth.js" import { UserEphemeralKey } from "./entity/UserEphemeralKey.js" import { Product } from "./entity/Product.js" +import { UserToUserPayment } from "./entity/UserToUserPayment.js" +import { Application } from "./entity/Application.js" +import { ApplicationUser } from "./entity/ApplicationUser.js" export type DbSettings = { databaseFile: string } @@ -22,7 +25,7 @@ export default async (settings: DbSettings) => { type: "sqlite", database: settings.databaseFile, //logging: true, - entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserNostrAuth, UserBasicAuth, UserEphemeralKey, Product], - synchronize: true + entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserNostrAuth, UserBasicAuth, UserEphemeralKey, Product, UserToUserPayment, Application, ApplicationUser, UserToUserPayment], + synchronize: true, }).initialize() -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/services/storage/entity/AddressReceivingTransaction.ts b/src/services/storage/entity/AddressReceivingTransaction.ts index 399d5b6e..acac712b 100644 --- a/src/services/storage/entity/AddressReceivingTransaction.ts +++ b/src/services/storage/entity/AddressReceivingTransaction.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm" import { UserReceivingAddress } from "./UserReceivingAddress.js" @@ -27,4 +27,10 @@ export class AddressReceivingTransaction { @Column() paid_at_unix: number + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/Application.ts b/src/services/storage/entity/Application.ts new file mode 100644 index 00000000..4bea325e --- /dev/null +++ b/src/services/storage/entity/Application.ts @@ -0,0 +1,26 @@ +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, CreateDateColumn, UpdateDateColumn, JoinColumn, ManyToOne } from "typeorm" +import { User } from "./User.js" + +@Entity() +export class Application { + + @PrimaryGeneratedColumn() + serial_id: number + + @Column() + @Index({ unique: true }) + app_id: string + + @Column({ unique: true }) + name: string + + @ManyToOne(type => User, { eager: true }) + @JoinColumn() + owner: User + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date +} diff --git a/src/services/storage/entity/ApplicationUser.ts b/src/services/storage/entity/ApplicationUser.ts new file mode 100644 index 00000000..733ea538 --- /dev/null +++ b/src/services/storage/entity/ApplicationUser.ts @@ -0,0 +1,28 @@ +import { Entity, PrimaryGeneratedColumn, Column, Index, JoinColumn, OneToOne, OneToMany, ManyToOne, CreateDateColumn, UpdateDateColumn } from "typeorm" +import { User } from "./User.js" +import { Application } from "./Application.js" + +@Entity() +export class ApplicationUser { + + @PrimaryGeneratedColumn() + serial_id: number + + @OneToOne(type => User, { eager: true }) + @JoinColumn() + user: User + + @ManyToOne(type => Application, { eager: true }) + @JoinColumn() + application: Application + + @Column() + @Index({ unique: true }) + identifier: string + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date +} diff --git a/src/services/storage/entity/Product.ts b/src/services/storage/entity/Product.ts index 3b4fe047..792779c8 100644 --- a/src/services/storage/entity/Product.ts +++ b/src/services/storage/entity/Product.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, CreateDateColumn, UpdateDateColumn } from "typeorm" import { User } from "./User.js" @Entity() @@ -15,4 +15,10 @@ export class Product { @Column() price_sats: number + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/User.ts b/src/services/storage/entity/User.ts index c5911f86..cd1300e9 100644 --- a/src/services/storage/entity/User.ts +++ b/src/services/storage/entity/User.ts @@ -1,8 +1,7 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, CreateDateColumn, UpdateDateColumn } from "typeorm" @Entity() export class User { - @PrimaryGeneratedColumn() serial_id: number @@ -15,4 +14,10 @@ export class User { @Column({ default: false }) locked: boolean + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/UserBasicAuth.ts b/src/services/storage/entity/UserBasicAuth.ts index 8e7e1e3e..ff1f57f3 100644 --- a/src/services/storage/entity/UserBasicAuth.ts +++ b/src/services/storage/entity/UserBasicAuth.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, JoinColumn, OneToOne, CreateDateColumn, UpdateDateColumn } from "typeorm" import { User } from "./User.js" @Entity() @@ -7,7 +7,7 @@ export class UserBasicAuth { @PrimaryGeneratedColumn() serial_id: number - @ManyToOne(type => User, { eager: true }) + @OneToOne(type => User, { eager: true }) @JoinColumn() user: User @@ -17,4 +17,10 @@ export class UserBasicAuth { @Column() secret_sha256: string + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/UserEphemeralKey.ts b/src/services/storage/entity/UserEphemeralKey.ts index fd32a4ed..f81ac131 100644 --- a/src/services/storage/entity/UserEphemeralKey.ts +++ b/src/services/storage/entity/UserEphemeralKey.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm" import { User } from "./User.js" export type EphemeralKeyType = 'balanceCheck' | 'payInfo' | 'pay' | 'withdraw' @Entity() @@ -17,4 +17,10 @@ export class UserEphemeralKey { @Column() type: EphemeralKeyType + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/UserInvoicePayment.ts b/src/services/storage/entity/UserInvoicePayment.ts index 7c28b214..b7489d48 100644 --- a/src/services/storage/entity/UserInvoicePayment.ts +++ b/src/services/storage/entity/UserInvoicePayment.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm" import { User } from "./User.js" @Entity() @@ -26,4 +26,10 @@ export class UserInvoicePayment { @Column() paid_at_unix: number + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/UserNostrAuth.ts b/src/services/storage/entity/UserNostrAuth.ts index 1493e4db..2e32c79f 100644 --- a/src/services/storage/entity/UserNostrAuth.ts +++ b/src/services/storage/entity/UserNostrAuth.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, JoinColumn, OneToOne, CreateDateColumn, UpdateDateColumn } from "typeorm" import { User } from "./User.js" @Entity() @@ -7,11 +7,17 @@ export class UserNostrAuth { @PrimaryGeneratedColumn() serial_id: number - @ManyToOne(type => User, { eager: true }) + @OneToOne(type => User, { eager: true }) @JoinColumn() user: User @Column() @Index({ unique: true }) nostr_pub: string + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/UserReceivingAddress.ts b/src/services/storage/entity/UserReceivingAddress.ts index 7c4acc65..2d3f73d9 100644 --- a/src/services/storage/entity/UserReceivingAddress.ts +++ b/src/services/storage/entity/UserReceivingAddress.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm" import { User } from "./User.js" @Entity() @@ -17,4 +17,10 @@ export class UserReceivingAddress { @Column() callbackUrl: string + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/UserReceivingInvoice.ts b/src/services/storage/entity/UserReceivingInvoice.ts index 10c711e4..5219773f 100644 --- a/src/services/storage/entity/UserReceivingInvoice.ts +++ b/src/services/storage/entity/UserReceivingInvoice.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm" import { Product } from "./Product.js" import { User } from "./User.js" @@ -16,10 +16,13 @@ export class UserReceivingInvoice { @Index({ unique: true }) invoice: string + @Column() + expires_at_unix: number + @Column({ default: 0 }) paid_at_unix: number - @Column() + @Column({ default: "" }) callbackUrl: string @Column({ default: 0 }) @@ -30,4 +33,13 @@ export class UserReceivingInvoice { @ManyToOne(type => Product, { eager: true }) product: Product | null + + @ManyToOne(type => User, { eager: true }) + payer: User | null + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/entity/UserToUserPayment.ts b/src/services/storage/entity/UserToUserPayment.ts new file mode 100644 index 00000000..98438151 --- /dev/null +++ b/src/services/storage/entity/UserToUserPayment.ts @@ -0,0 +1,32 @@ +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm" +import { User } from "./User.js" + +@Entity() +export class UserToUserPayment { + + @PrimaryGeneratedColumn() + serial_id: number + + @ManyToOne(type => User, { eager: true }) + @JoinColumn() + from_user: User + + @ManyToOne(type => User, { eager: true }) + @JoinColumn() + to_user: User + + @Column() + paid_amount: number + + @Column() + service_fees: number + + @Column() + paid_at_unix: number + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date +} diff --git a/src/services/storage/entity/UserTransactionPayment.ts b/src/services/storage/entity/UserTransactionPayment.ts index e4305e63..4be0a02f 100644 --- a/src/services/storage/entity/UserTransactionPayment.ts +++ b/src/services/storage/entity/UserTransactionPayment.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm" +import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn } from "typeorm" import { User } from "./User.js" @Entity() @@ -32,4 +32,10 @@ export class UserTransactionPayment { @Column() paid_at_unix: number + + @CreateDateColumn() + created_at: Date + + @UpdateDateColumn() + updated_at: Date } diff --git a/src/services/storage/index.ts b/src/services/storage/index.ts index 968eaf98..16352b9d 100644 --- a/src/services/storage/index.ts +++ b/src/services/storage/index.ts @@ -11,7 +11,10 @@ import { UserNostrAuth } from "./entity/UserNostrAuth.js"; import { UserBasicAuth } from "./entity/UserBasicAuth.js"; import { EphemeralKeyType, UserEphemeralKey } from "./entity/UserEphemeralKey.js"; import ProductStorage from './productStorage.js' +import ApplicationStorage from './applicationStorage.js' import { Product } from "./entity/Product.js"; +import UserStorage from "./userStorage.js"; +import PaymentStorage from "./paymentStorage.js"; export type StorageSettings = { dbSettings: DbSettings } @@ -23,255 +26,20 @@ export default class { DB: DataSource | EntityManager settings: StorageSettings productStorage: ProductStorage + applicationStorage: ApplicationStorage + userStorage: UserStorage + paymentStorage: PaymentStorage constructor(settings: StorageSettings) { this.settings = settings } async Connect() { this.DB = await NewDB(this.settings.dbSettings) + this.userStorage = new UserStorage(this.DB) this.productStorage = new ProductStorage(this.DB) + this.applicationStorage = new ApplicationStorage(this.DB, this.userStorage) + this.paymentStorage = new PaymentStorage(this.DB, this.userStorage) } StartTransaction(exec: (entityManager: EntityManager) => Promise) { return this.DB.transaction(exec) } - async AddUser(entityManager = this.DB): Promise { - - const newUser = entityManager.getRepository(User).create({ - user_id: crypto.randomBytes(32).toString('hex') - }) - return entityManager.getRepository(User).save(newUser) - } - async AddBasicUser(name: string, secret: string): Promise { - return this.DB.transaction(async tx => { - const user = await this.AddUser(tx) - const newUserAuth = tx.getRepository(UserBasicAuth).create({ - user: user, - name: name, - secret_sha256: crypto.createHash('sha256').update(secret).digest('base64') - }) - return tx.getRepository(UserBasicAuth).save(newUserAuth) - }) - - } - FindUser(userId: string, entityManager = this.DB) { - return entityManager.getRepository(User).findOne({ - where: { - user_id: userId - } - }) - } - async GetUser(userId: string, entityManager = this.DB): Promise { - const user = await this.FindUser(userId, entityManager) - if (!user) { - throw new Error(`user ${userId} not found`) // TODO: fix logs doxing - } - return user - } - - async FindNostrUser(nostrPub: string, entityManager = this.DB): Promise { - return entityManager.getRepository(UserNostrAuth).findOne({ - where: { nostr_pub: nostrPub } - }) - - } - async AddNostrUser(nostrPub: string): Promise { - return this.DB.transaction(async tx => { - const user = await this.AddUser(tx) - const newAuth = tx.getRepository(UserNostrAuth).create({ - user: user, - nostr_pub: nostrPub - }) - return tx.getRepository(UserNostrAuth).save(newAuth) - }) - - } - - async AddAddressReceivingTransaction(address: UserReceivingAddress, txHash: string, outputIndex: number, amount: number, serviceFee: number, entityManager = this.DB) { - const newAddressTransaction = entityManager.getRepository(AddressReceivingTransaction).create({ - user_address: address, - tx_hash: txHash, - output_index: outputIndex, - paid_amount: amount, - service_fee: serviceFee, - paid_at_unix: Math.floor(Date.now() / 1000) - }) - return entityManager.getRepository(AddressReceivingTransaction).save(newAddressTransaction) - } - - GetUserReceivingTransactions(userId: string, fromIndex: number, entityManager = this.DB): Promise { - return entityManager.getRepository(AddressReceivingTransaction).find({ - where: { - user_address: { user: { user_id: userId } }, - serial_id: MoreThanOrEqual(fromIndex), - paid_at_unix: MoreThan(0), - }, - order: { - paid_at_unix: 'DESC' - } - }) - } - - async AddUserAddress(userId: string, address: string, callbackUrl = "", entityManager = this.DB): Promise { - const newUserAddress = entityManager.getRepository(UserReceivingAddress).create({ - address, - callbackUrl, - user: await this.GetUser(userId, entityManager) - }) - return entityManager.getRepository(UserReceivingAddress).save(newUserAddress) - } - - async FlagInvoiceAsPaid(invoice: UserReceivingInvoice, amount: number, serviceFee: number, entityManager = this.DB) { - return entityManager.getRepository(UserReceivingInvoice).update(invoice.serial_id, { paid_at_unix: Math.floor(Date.now() / 1000), paid_amount: amount, service_fee: serviceFee }) - } - - GetUserInvoicesFlaggedAsPaid(userId: string, fromIndex: number, entityManager = this.DB): Promise { - return entityManager.getRepository(UserReceivingInvoice).find({ - where: { - user: { - user_id: userId - }, - serial_id: MoreThanOrEqual(fromIndex), - paid_at_unix: MoreThan(0), - }, - order: { - paid_at_unix: 'DESC' - } - }) - } - - async AddUserInvoice(user: User, invoice: string, product?: Product, callbackUrl = "", entityManager = this.DB): Promise { - const newUserInvoice = entityManager.getRepository(UserReceivingInvoice).create({ - invoice: invoice, - callbackUrl, - user: user, - product: product - }) - return entityManager.getRepository(UserReceivingInvoice).save(newUserInvoice) - } - - async GetAddressOwner(address: string, entityManager = this.DB): Promise { - return entityManager.getRepository(UserReceivingAddress).findOne({ - where: { - address - } - }) - } - - async GetInvoiceOwner(paymentRequest: string, entityManager = this.DB): Promise { - return entityManager.getRepository(UserReceivingInvoice).findOne({ - where: { - invoice: paymentRequest - } - }) - } - - async AddUserInvoicePayment(userId: string, invoice: string, amount: number, routingFees: number, serviceFees: number, entityManager = this.DB): Promise { - const newPayment = entityManager.getRepository(UserInvoicePayment).create({ - user: await this.GetUser(userId), - paid_amount: amount, - invoice, - routing_fees: routingFees, - service_fees: serviceFees, - paid_at_unix: Math.floor(Date.now() / 1000) - }) - return entityManager.getRepository(UserInvoicePayment).save(newPayment) - } - - GetUserInvoicePayments(userId: string, fromIndex: number, entityManager = this.DB): Promise { - return entityManager.getRepository(UserInvoicePayment).find({ - where: { - user: { - user_id: userId - }, - serial_id: MoreThanOrEqual(fromIndex), - paid_at_unix: MoreThan(0), - }, - order: { - paid_at_unix: 'DESC' - } - }) - } - - async AddUserTransactionPayment(userId: string, address: string, txHash: string, txOutput: number, amount: number, chainFees: number, serviceFees: number, entityManager = this.DB): Promise { - const newTx = entityManager.getRepository(UserTransactionPayment).create({ - user: await this.GetUser(userId), - address, - paid_amount: amount, - chain_fees: chainFees, - output_index: txOutput, - tx_hash: txHash, - service_fees: serviceFees, - paid_at_unix: Math.floor(Date.now() / 1000) - }) - return entityManager.getRepository(UserTransactionPayment).save(newTx) - } - - GetUserTransactionPayments(userId: string, fromIndex: number, entityManager = this.DB): Promise { - return entityManager.getRepository(UserTransactionPayment).find({ - where: { - user: { - user_id: userId - }, - serial_id: MoreThanOrEqual(fromIndex), - paid_at_unix: MoreThan(0), - }, - order: { - paid_at_unix: 'DESC' - } - }) - } - async LockUser(userId: string, entityManager = this.DB) { - const res = await entityManager.getRepository(User).update({ - user_id: userId - }, { locked: true }) - if (!res.affected) { - throw new Error("unaffected user lock for " + userId) // TODO: fix logs doxing - } - } - async UnlockUser(userId: string, entityManager = this.DB) { - const res = await entityManager.getRepository(User).update({ - user_id: userId - }, { locked: false }) - if (!res.affected) { - throw new Error("unaffected user unlock for " + userId) // TODO: fix logs doxing - } - } - async IncrementUserBalance(userId: string, increment: number, entityManager = this.DB) { - const res = await entityManager.getRepository(User).increment({ - user_id: userId, - }, "balance_sats", increment) - if (!res.affected) { - throw new Error("unaffected balance increment for " + userId) // TODO: fix logs doxing - } - } - async DecrementUserBalance(userId: string, decrement: number, entityManager = this.DB) { - const res = await entityManager.getRepository(User).decrement({ - user_id: userId, - }, "balance_sats", decrement) - if (!res.affected) { - throw new Error("unaffected balance decrement for " + userId) // TODO: fix logs doxing - } - } - - async AddUserEphemeralKey(userId: string, keyType: EphemeralKeyType, entityManager = this.DB): Promise { - const newKey = entityManager.getRepository(UserEphemeralKey).create({ - user: await this.GetUser(userId, entityManager), - key: crypto.randomBytes(31).toString('hex'), - type: keyType - }) - return entityManager.getRepository(UserEphemeralKey).save(newKey) - } - - async UseUserEphemeralKey(key: string, keyType: EphemeralKeyType, entityManager = this.DB): Promise { - const found = await entityManager.getRepository(UserEphemeralKey).findOne({ - where: { - key: key, - type: keyType - } - }) - if (!found) { - throw new Error("the provided ephemeral key is invalid") - } - await entityManager.getRepository(UserEphemeralKey).delete(found.serial_id) - return found - } } \ No newline at end of file diff --git a/src/services/storage/paymentStorage.ts b/src/services/storage/paymentStorage.ts new file mode 100644 index 00000000..2a473ea2 --- /dev/null +++ b/src/services/storage/paymentStorage.ts @@ -0,0 +1,228 @@ +import crypto from 'crypto'; +import { DataSource, EntityManager, MoreThan, MoreThanOrEqual } from "typeorm" +import { User } from './entity/User.js'; +import { UserBasicAuth } from './entity/UserBasicAuth.js'; +import { UserNostrAuth } from './entity/UserNostrAuth.js'; +import { UserTransactionPayment } from './entity/UserTransactionPayment.js'; +import { EphemeralKeyType, UserEphemeralKey } from './entity/UserEphemeralKey.js'; +import { UserReceivingInvoice } from './entity/UserReceivingInvoice.js'; +import { UserReceivingAddress } from './entity/UserReceivingAddress.js'; +import { Product } from './entity/Product.js'; +import UserStorage from './userStorage.js'; +import { AddressReceivingTransaction } from './entity/AddressReceivingTransaction.js'; +import { UserInvoicePayment } from './entity/UserInvoicePayment.js'; +import { UserToUserPayment } from './entity/UserToUserPayment.js'; +export type InboundOptionals = { product?: Product, callbackUrl?: string, expiry: number, expectedPayer?: User } +export const defaultInvoiceExpiry = 60 * 60 +export default class { + DB: DataSource | EntityManager + userStorage: UserStorage + constructor(DB: DataSource | EntityManager, userStorage: UserStorage) { + this.DB = DB + this.userStorage = userStorage + } + async AddAddressReceivingTransaction(address: UserReceivingAddress, txHash: string, outputIndex: number, amount: number, serviceFee: number, entityManager = this.DB) { + const newAddressTransaction = entityManager.getRepository(AddressReceivingTransaction).create({ + user_address: address, + tx_hash: txHash, + output_index: outputIndex, + paid_amount: amount, + service_fee: serviceFee, + paid_at_unix: Math.floor(Date.now() / 1000) + }) + return entityManager.getRepository(AddressReceivingTransaction).save(newAddressTransaction) + } + + GetUserReceivingTransactions(userId: string, fromIndex: number, entityManager = this.DB): Promise { + return entityManager.getRepository(AddressReceivingTransaction).find({ + where: { + user_address: { user: { user_id: userId } }, + serial_id: MoreThanOrEqual(fromIndex), + paid_at_unix: MoreThan(0), + }, + order: { + paid_at_unix: 'DESC' + } + }) + } + + + + async AddUserAddress(userId: string, address: string, callbackUrl = "", entityManager = this.DB): Promise { + const newUserAddress = entityManager.getRepository(UserReceivingAddress).create({ + address, + callbackUrl, + user: await this.userStorage.GetUser(userId, entityManager) + }) + return entityManager.getRepository(UserReceivingAddress).save(newUserAddress) + } + + async FlagInvoiceAsPaid(invoice: UserReceivingInvoice, amount: number, serviceFee: number, entityManager = this.DB) { + return entityManager.getRepository(UserReceivingInvoice).update(invoice.serial_id, { paid_at_unix: Math.floor(Date.now() / 1000), paid_amount: amount, service_fee: serviceFee }) + } + + GetUserInvoicesFlaggedAsPaid(userId: string, fromIndex: number, entityManager = this.DB): Promise { + return entityManager.getRepository(UserReceivingInvoice).find({ + where: { + user: { + user_id: userId + }, + serial_id: MoreThanOrEqual(fromIndex), + paid_at_unix: MoreThan(0), + }, + order: { + paid_at_unix: 'DESC' + } + }) + } + + async AddUserInvoice(user: User, invoice: string, options: InboundOptionals = { expiry: defaultInvoiceExpiry }, entityManager = this.DB): Promise { + const newUserInvoice = entityManager.getRepository(UserReceivingInvoice).create({ + invoice: invoice, + callbackUrl: options.callbackUrl, + user: user, + product: options.product, + expires_at_unix: Math.floor(Date.now() / 1000) + options.expiry, + payer: options.expectedPayer + }) + return entityManager.getRepository(UserReceivingInvoice).save(newUserInvoice) + } + + async GetAddressOwner(address: string, entityManager = this.DB): Promise { + return entityManager.getRepository(UserReceivingAddress).findOne({ + where: { + address + } + }) + } + + async GetInvoiceOwner(paymentRequest: string, entityManager = this.DB): Promise { + return entityManager.getRepository(UserReceivingInvoice).findOne({ + where: { + invoice: paymentRequest + } + }) + } + + async AddUserInvoicePayment(userId: string, invoice: string, amount: number, routingFees: number, serviceFees: number, entityManager = this.DB): Promise { + const newPayment = entityManager.getRepository(UserInvoicePayment).create({ + user: await this.userStorage.GetUser(userId), + paid_amount: amount, + invoice, + routing_fees: routingFees, + service_fees: serviceFees, + paid_at_unix: Math.floor(Date.now() / 1000) + }) + return entityManager.getRepository(UserInvoicePayment).save(newPayment) + } + + GetUserInvoicePayments(userId: string, fromIndex: number, entityManager = this.DB): Promise { + return entityManager.getRepository(UserInvoicePayment).find({ + where: { + user: { + user_id: userId + }, + serial_id: MoreThanOrEqual(fromIndex), + paid_at_unix: MoreThan(0), + }, + order: { + paid_at_unix: 'DESC' + } + }) + } + + async AddUserTransactionPayment(userId: string, address: string, txHash: string, txOutput: number, amount: number, chainFees: number, serviceFees: number, entityManager = this.DB): Promise { + const newTx = entityManager.getRepository(UserTransactionPayment).create({ + user: await this.userStorage.GetUser(userId), + address, + paid_amount: amount, + chain_fees: chainFees, + output_index: txOutput, + tx_hash: txHash, + service_fees: serviceFees, + paid_at_unix: Math.floor(Date.now() / 1000) + }) + return entityManager.getRepository(UserTransactionPayment).save(newTx) + } + + GetUserTransactionPayments(userId: string, fromIndex: number, entityManager = this.DB): Promise { + return entityManager.getRepository(UserTransactionPayment).find({ + where: { + user: { + user_id: userId + }, + serial_id: MoreThanOrEqual(fromIndex), + paid_at_unix: MoreThan(0), + }, + order: { + paid_at_unix: 'DESC' + } + }) + } + + + async AddUserEphemeralKey(userId: string, keyType: EphemeralKeyType, entityManager = this.DB): Promise { + const newKey = entityManager.getRepository(UserEphemeralKey).create({ + user: await this.userStorage.GetUser(userId, entityManager), + key: crypto.randomBytes(31).toString('hex'), + type: keyType + }) + return entityManager.getRepository(UserEphemeralKey).save(newKey) + } + + async UseUserEphemeralKey(key: string, keyType: EphemeralKeyType, entityManager = this.DB): Promise { + const found = await entityManager.getRepository(UserEphemeralKey).findOne({ + where: { + key: key, + type: keyType + } + }) + if (!found) { + throw new Error("the provided ephemeral key is invalid") + } + await entityManager.getRepository(UserEphemeralKey).delete(found.serial_id) + return found + } + + async AddUserToUserPayment(fromUserId: string, toUserId: string, amount: number, fee: number, entityManager = this.DB) { + const newKey = entityManager.getRepository(UserToUserPayment).create({ + from_user: await this.userStorage.GetUser(fromUserId, entityManager), + to_user: await this.userStorage.GetUser(toUserId, entityManager), + paid_at_unix: Math.floor(Date.now() / 1000), + paid_amount: amount, + service_fees: fee + }) + return entityManager.getRepository(UserToUserPayment).save(newKey) + } + + GetUserToUserReceivedPayments(userId: string, fromIndex: number, entityManager = this.DB) { + return entityManager.getRepository(UserToUserPayment).find({ + where: { + to_user: { + user_id: userId + }, + serial_id: MoreThanOrEqual(fromIndex), + paid_at_unix: MoreThan(0), + }, + order: { + paid_at_unix: 'DESC' + } + }) + } + + GetUserToUserSentPayments(userId: string, fromIndex: number, entityManager = this.DB) { + return entityManager.getRepository(UserToUserPayment).find({ + where: { + from_user: { + user_id: userId + }, + serial_id: MoreThanOrEqual(fromIndex), + paid_at_unix: MoreThan(0), + }, + order: { + paid_at_unix: 'DESC' + } + }) + } + +} \ No newline at end of file diff --git a/src/services/storage/userStorage.ts b/src/services/storage/userStorage.ts new file mode 100644 index 00000000..cb7d0a20 --- /dev/null +++ b/src/services/storage/userStorage.ts @@ -0,0 +1,105 @@ +import crypto from 'crypto'; +import { DataSource, EntityManager } from "typeorm" +import { User } from './entity/User.js'; +import { UserBasicAuth } from './entity/UserBasicAuth.js'; +import { UserNostrAuth } from './entity/UserNostrAuth.js'; +export default class { + DB: DataSource | EntityManager + constructor(DB: DataSource | EntityManager) { + this.DB = DB + } + async AddUser(balance: number, entityManager = this.DB): Promise { + if (balance && process.env.ALLOW_BALANCE_MIGRATION !== 'true') { + throw new Error("balance migration is not allowed") + } + console.log("Adding user with balance", balance) + const newUser = entityManager.getRepository(User).create({ + user_id: crypto.randomBytes(32).toString('hex'), + balance_sats: balance + }) + return entityManager.getRepository(User).save(newUser) + } + + + async AddBasicUser(name: string, secret: string): Promise { + return this.DB.transaction(async tx => { + const user = await this.AddUser(0, tx) + const newUserAuth = tx.getRepository(UserBasicAuth).create({ + user: user, + name: name, + secret_sha256: crypto.createHash('sha256').update(secret).digest('base64') + }) + return tx.getRepository(UserBasicAuth).save(newUserAuth) + }) + + } + FindUser(userId: string, entityManager = this.DB) { + return entityManager.getRepository(User).findOne({ + where: { + user_id: userId + } + }) + } + async GetUser(userId: string, entityManager = this.DB): Promise { + const user = await this.FindUser(userId, entityManager) + if (!user) { + throw new Error(`user ${userId} not found`) // TODO: fix logs doxing + } + return user + } + + async FindNostrUser(nostrPub: string, entityManager = this.DB): Promise { + return entityManager.getRepository(UserNostrAuth).findOne({ + where: { nostr_pub: nostrPub } + }) + + } + async AddNostrUser(nostrPub: string): Promise { + return this.DB.transaction(async tx => { + const user = await this.AddUser(0, tx) + const newAuth = tx.getRepository(UserNostrAuth).create({ + user: user, + nostr_pub: nostrPub + }) + return tx.getRepository(UserNostrAuth).save(newAuth) + }) + + } + + async LockUser(userId: string, entityManager = this.DB) { + const res = await entityManager.getRepository(User).update({ + user_id: userId + }, { locked: true }) + if (!res.affected) { + throw new Error("unaffected user lock for " + userId) // TODO: fix logs doxing + } + } + async UnlockUser(userId: string, entityManager = this.DB) { + const res = await entityManager.getRepository(User).update({ + user_id: userId + }, { locked: false }) + if (!res.affected) { + throw new Error("unaffected user unlock for " + userId) // TODO: fix logs doxing + } + } + async IncrementUserBalance(userId: string, increment: number, entityManager = this.DB) { + const res = await entityManager.getRepository(User).increment({ + user_id: userId, + }, "balance_sats", increment) + if (!res.affected) { + throw new Error("unaffected balance increment for " + userId) // TODO: fix logs doxing + } + } + async DecrementUserBalance(userId: string, decrement: number, entityManager = this.DB) { + const user = await this.GetUser(userId, entityManager) + if (!user || user.balance_sats < decrement) { + throw new Error("not enough balance to decrement") + } + const res = await entityManager.getRepository(User).decrement({ + user_id: userId, + }, "balance_sats", decrement) + if (!res.affected) { + throw new Error("unaffected balance decrement for " + userId) // TODO: fix logs doxing + } + } +} \ No newline at end of file