From cb5e9db5ef65b524136d09fd17e95277ef2be995 Mon Sep 17 00:00:00 2001 From: optclblast Date: Tue, 7 May 2024 00:41:22 +0300 Subject: [PATCH] users interactor init, user create repository method implemented --- backend/.gitignore | 3 +- backend/.vscode/launch.json | 27 + backend/docker-compose.yaml | 1 - backend/go.mod | 22 +- backend/go.sum | 163 ++++- .../factory/{service.go => interface.go} | 23 +- backend/internal/factory/repositories.go | 18 + backend/internal/factory/wire.go | 22 + backend/internal/factory/wire_gen.go | 61 +- .../interface/rest/controllers/auth.go | 35 +- backend/internal/interface/rest/server.go | 2 + backend/internal/pkg/hdwallet/hdwaller.go | 562 ++++++++++++++++++ backend/internal/pkg/models/user.go | 13 +- backend/internal/pkg/sqlutils/tx.go | 10 +- .../usecase/interactors/users/interactor.go | 100 ++++ backend/internal/usecase/repository/db.go | 31 + .../repository/transactions/repository.go | 4 +- .../usecase/repository/users/repository.go | 23 +- 18 files changed, 1019 insertions(+), 101 deletions(-) create mode 100644 backend/.vscode/launch.json rename backend/internal/factory/{service.go => interface.go} (78%) create mode 100644 backend/internal/factory/repositories.go create mode 100644 backend/internal/factory/wire.go create mode 100644 backend/internal/pkg/hdwallet/hdwaller.go create mode 100644 backend/internal/usecase/interactors/users/interactor.go create mode 100644 backend/internal/usecase/repository/db.go diff --git a/backend/.gitignore b/backend/.gitignore index e08d30f..25e1a8d 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1 +1,2 @@ -build/blockd \ No newline at end of file +build/blockd +*__debug_* \ No newline at end of file diff --git a/backend/.vscode/launch.json b/backend/.vscode/launch.json new file mode 100644 index 0000000..5f0bf69 --- /dev/null +++ b/backend/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "debug", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceRoot}/cmd/main.go", + "args": [ + "-log-level=debug", + "-log-local=true", + "-log-add-source=true", + + "-rest-address=localhost:8080", + "-db-host=localhost:8432", + "-db-database=blockd", + "-db-user=blockd", + "-db-secret=blockd", + "-db-enable-tls=false" + ] + } + ] +} \ No newline at end of file diff --git a/backend/docker-compose.yaml b/backend/docker-compose.yaml index 655a4fe..1016615 100644 --- a/backend/docker-compose.yaml +++ b/backend/docker-compose.yaml @@ -1,7 +1,6 @@ version: '3' networks: blockd-net: - external: true name: blockd-net driver: bridge diff --git a/backend/go.mod b/backend/go.mod index b70f3d5..ff46df1 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -4,24 +4,42 @@ go 1.22.2 require ( github.com/Masterminds/squirrel v1.5.4 + github.com/btcsuite/btcd v0.22.3 + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce + github.com/ethereum/go-ethereum v1.14.0 github.com/fatih/color v1.16.0 github.com/go-chi/chi/v5 v5.0.12 github.com/go-chi/render v1.0.3 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/uuid v1.6.0 github.com/google/wire v0.6.0 + github.com/lib/pq v1.10.9 + github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.27.2 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.22.0 ) require ( github.com/ajg/form v1.5.1 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/holiman/uint256 v1.2.4 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 8cbf579..9b1f75c 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,54 +1,192 @@ +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.3 h1:kYNaWFvOw6xvqP0vR20RP1Zq1DVMBxEO8QN5d1/EfNg= +github.com/btcsuite/btcd v0.22.3/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= +github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.14.0 h1:xRWC5NlB6g1x7vNy4HDBLuqVNbtLrc7v8S6+Uxim1LU= +github.com/ethereum/go-ethereum v1.14.0/go.mod h1:1STrq471D0BQbCX9He0hUj4bHxX2k6mt5nOQJhDNOJ8= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -56,12 +194,17 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -71,8 +214,9 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -85,6 +229,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -93,3 +238,15 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/backend/internal/factory/service.go b/backend/internal/factory/interface.go similarity index 78% rename from backend/internal/factory/service.go rename to backend/internal/factory/interface.go index e21bf52..fcb79fe 100644 --- a/backend/internal/factory/service.go +++ b/backend/internal/factory/interface.go @@ -1,6 +1,3 @@ -//go:build wireinject -// +build wireinject - package factory import ( @@ -12,21 +9,10 @@ import ( "github.com/emochka2007/block-accounting/internal/interface/rest/presenters" "github.com/emochka2007/block-accounting/internal/pkg/config" "github.com/emochka2007/block-accounting/internal/pkg/logger" - "github.com/emochka2007/block-accounting/internal/service" - "github.com/google/wire" + "github.com/emochka2007/block-accounting/internal/usecase/interactors/users" + urepo "github.com/emochka2007/block-accounting/internal/usecase/repository/users" ) -func ProvideService(c config.Config) (service.Service, func(), error) { - wire.Build( - provideLogger, - provideControllers, - provideRestServer, - service.NewService, - ) - - return &service.ServiceImpl{}, func() {}, nil -} - func provideLogger(c config.Config) *slog.Logger { lb := new(logger.LoggerBuilder).WithLevel(logger.MapLevel(c.Common.LogLevel)).WithWriter(os.Stdout) @@ -52,12 +38,17 @@ func provideLogger(c config.Config) *slog.Logger { func provideControllers( log *slog.Logger, + usersRepo urepo.Repository, ) *controllers.RootController { return &controllers.RootController{ Ping: controllers.NewPingController(log.WithGroup("ping-controller")), Auth: controllers.NewAuthController( log.WithGroup("auth-controller"), presenters.NewAuthPresenter(), + users.NewUsersInteractor( + log.WithGroup("users-interactor"), + usersRepo, + ), ), } } diff --git a/backend/internal/factory/repositories.go b/backend/internal/factory/repositories.go new file mode 100644 index 0000000..1ce9bc0 --- /dev/null +++ b/backend/internal/factory/repositories.go @@ -0,0 +1,18 @@ +package factory + +import ( + "fmt" + + "github.com/emochka2007/block-accounting/internal/pkg/config" + "github.com/emochka2007/block-accounting/internal/usecase/repository" + "github.com/emochka2007/block-accounting/internal/usecase/repository/users" +) + +func provideUsersRepository(c config.Config) (users.Repository, func(), error) { + db, close, err := repository.ProvideDatabaseConnection(c) + if err != nil { + return nil, func() {}, fmt.Errorf("error connect to database. %w", err) + } + + return users.NewRepository(db), close, nil +} diff --git a/backend/internal/factory/wire.go b/backend/internal/factory/wire.go new file mode 100644 index 0000000..ccd520c --- /dev/null +++ b/backend/internal/factory/wire.go @@ -0,0 +1,22 @@ +//go:build wireinject +// +build wireinject + +package factory + +import ( + "github.com/emochka2007/block-accounting/internal/pkg/config" + "github.com/emochka2007/block-accounting/internal/service" + "github.com/google/wire" +) + +func ProvideService(c config.Config) (service.Service, func(), error) { + wire.Build( + provideUsersRepository, + provideLogger, + provideControllers, + provideRestServer, + service.NewService, + ) + + return &service.ServiceImpl{}, func() {}, nil +} diff --git a/backend/internal/factory/wire_gen.go b/backend/internal/factory/wire_gen.go index 7bc10d6..2ce4f6e 100644 --- a/backend/internal/factory/wire_gen.go +++ b/backend/internal/factory/wire_gen.go @@ -7,69 +7,22 @@ package factory import ( - "github.com/emochka2007/block-accounting/internal/interface/rest" - "github.com/emochka2007/block-accounting/internal/interface/rest/controllers" - "github.com/emochka2007/block-accounting/internal/interface/rest/presenters" "github.com/emochka2007/block-accounting/internal/pkg/config" - "github.com/emochka2007/block-accounting/internal/pkg/logger" "github.com/emochka2007/block-accounting/internal/service" - "log/slog" - "os" ) -// Injectors from service.go: +// Injectors from wire.go: func ProvideService(c config.Config) (service.Service, func(), error) { logger := provideLogger(c) - rootController := provideControllers(logger) + repository, cleanup, err := provideUsersRepository(c) + if err != nil { + return nil, nil, err + } + rootController := provideControllers(logger, repository) server := provideRestServer(logger, rootController, c) serviceService := service.NewService(logger, server) return serviceService, func() { + cleanup() }, nil } - -// service.go: - -func provideLogger(c config.Config) *slog.Logger { - lb := new(logger.LoggerBuilder).WithLevel(logger.MapLevel(c.Common.LogLevel)).WithWriter(os.Stdout) - - if c.Common.LogLocal { - lb.Local() - } - - if c.Common.LogFile != "" { - logFile, err := os.Open(c.Common.LogFile) - if err != nil { - panic(err) - } - - lb.WithWriter(logFile) - } - - if c.Common.LogAddSource { - lb.WithSource() - } - - return lb.Build() -} - -func provideControllers( - log *slog.Logger, -) *controllers.RootController { - return &controllers.RootController{ - Ping: controllers.NewPingController(log.WithGroup("ping-controller")), - Auth: controllers.NewAuthController( - log.WithGroup("auth-controller"), presenters.NewAuthPresenter(), - ), - } -} - -func provideRestServer( - log *slog.Logger, controllers2 *controllers.RootController, - c config.Config, -) *rest.Server { - return rest.NewServer( - log.WithGroup("rest"), - c.Rest, controllers2, - ) -} diff --git a/backend/internal/interface/rest/controllers/auth.go b/backend/internal/interface/rest/controllers/auth.go index 919e7dd..dfacdf4 100644 --- a/backend/internal/interface/rest/controllers/auth.go +++ b/backend/internal/interface/rest/controllers/auth.go @@ -1,13 +1,16 @@ package controllers import ( + "context" "errors" "fmt" "log/slog" "net/http" + "time" "github.com/emochka2007/block-accounting/internal/interface/rest/presenters" "github.com/emochka2007/block-accounting/internal/pkg/bip32" + "github.com/emochka2007/block-accounting/internal/usecase/interactors/users" ) var ( @@ -16,28 +19,29 @@ var ( type AuthController interface { Join(w http.ResponseWriter, req *http.Request) error + JoinWithInvite(w http.ResponseWriter, req *http.Request) error Login(w http.ResponseWriter, req *http.Request) error Invite(w http.ResponseWriter, req *http.Request) error } type authController struct { - log *slog.Logger - presenter presenters.AuthPresenter - // interactors ... + log *slog.Logger + presenter presenters.AuthPresenter + usersInteractor users.UsersInteractor } func NewAuthController( log *slog.Logger, presenter presenters.AuthPresenter, + usersInteractor users.UsersInteractor, ) AuthController { return &authController{ - log: log, - presenter: presenter, + log: log, + presenter: presenter, + usersInteractor: usersInteractor, } } -const mnemonicEntropyBitSize int = 256 - func (c *authController) Join(w http.ResponseWriter, req *http.Request) error { request, err := c.presenter.CreateJoinRequest(req) if err != nil { @@ -50,15 +54,30 @@ func (c *authController) Join(w http.ResponseWriter, req *http.Request) error { return fmt.Errorf("error invalid mnemonic. %w", ErrorAuthInvalidMnemonic) } - // todo create user + ctx, cancel := context.WithTimeout(req.Context(), 5*time.Second) + defer cancel() + + if _, err = c.usersInteractor.Create(ctx, users.CreateParams{ + Mnemonic: request.Mnemonic, + IsAdmin: true, + Activate: true, + }); err != nil { + return fmt.Errorf("error create new user. %w", err) + } return nil } +func (c *authController) JoinWithInvite(w http.ResponseWriter, req *http.Request) error { + return nil // implement +} + func (c *authController) Login(w http.ResponseWriter, req *http.Request) error { return nil // implement } +const mnemonicEntropyBitSize int = 256 + func (c *authController) Invite(w http.ResponseWriter, req *http.Request) error { return nil // implement } diff --git a/backend/internal/interface/rest/server.go b/backend/internal/interface/rest/server.go index f0e8711..469942e 100644 --- a/backend/internal/interface/rest/server.go +++ b/backend/internal/interface/rest/server.go @@ -105,6 +105,8 @@ func (s *Server) buildRouter() { } func (s *Server) responseError(w http.ResponseWriter, e error) { + s.log.Error("error handle request", logger.Err(e)) + apiErr := mapError(e) out, err := json.Marshal(apiErr) diff --git a/backend/internal/pkg/hdwallet/hdwaller.go b/backend/internal/pkg/hdwallet/hdwaller.go new file mode 100644 index 0000000..e8d6762 --- /dev/null +++ b/backend/internal/pkg/hdwallet/hdwaller.go @@ -0,0 +1,562 @@ +package hdwallet + +import ( + "crypto/ecdsa" + "crypto/rand" + "errors" + "fmt" + "math/big" + "os" + "sync" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcutil/hdkeychain" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/tyler-smith/go-bip39" +) + +// DefaultRootDerivationPath is the root path to which custom derivation endpoints +// are appended. As such, the first account will be at m/44'/60'/0'/0, the second +// at m/44'/60'/0'/1, etc. +var DefaultRootDerivationPath = accounts.DefaultRootDerivationPath + +// DefaultBaseDerivationPath is the base path from which custom derivation endpoints +// are incremented. As such, the first account will be at m/44'/60'/0'/0, the second +// at m/44'/60'/0'/1, etc +var DefaultBaseDerivationPath = accounts.DefaultBaseDerivationPath + +const issue179FixEnvar = "GO_ETHEREUM_HDWALLET_FIX_ISSUE_179" + +// Wallet is the underlying wallet struct. +type Wallet struct { + mnemonic string + masterKey *hdkeychain.ExtendedKey + seed []byte + url accounts.URL + paths map[common.Address]accounts.DerivationPath + accounts []accounts.Account + stateLock sync.RWMutex + fixIssue172 bool +} + +func newWallet(seed []byte) (*Wallet, error) { + masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) + if err != nil { + return nil, err + } + + return &Wallet{ + masterKey: masterKey, + seed: seed, + accounts: []accounts.Account{}, + paths: map[common.Address]accounts.DerivationPath{}, + fixIssue172: false || len(os.Getenv(issue179FixEnvar)) > 0, + }, nil +} + +// NewFromMnemonic returns a new wallet from a BIP-39 mnemonic. +func NewFromMnemonic(mnemonic string, passOpt ...string) (*Wallet, error) { + if mnemonic == "" { + return nil, errors.New("mnemonic is required") + } + + if !bip39.IsMnemonicValid(mnemonic) { + return nil, errors.New("mnemonic is invalid") + } + + seed, err := NewSeedFromMnemonic(mnemonic, passOpt...) + if err != nil { + return nil, err + } + + wallet, err := newWallet(seed) + if err != nil { + return nil, err + } + wallet.mnemonic = mnemonic + + return wallet, nil +} + +// NewFromSeed returns a new wallet from a BIP-39 seed. +func NewFromSeed(seed []byte) (*Wallet, error) { + if len(seed) == 0 { + return nil, errors.New("seed is required") + } + + return newWallet(seed) +} + +// URL implements accounts.Wallet, returning the URL of the device that +// the wallet is on, however this does nothing since this is not a hardware device. +func (w *Wallet) URL() accounts.URL { + return w.url +} + +// Status implements accounts.Wallet, returning a custom status message +// from the underlying vendor-specific hardware wallet implementation, +// however this does nothing since this is not a hardware device. +func (w *Wallet) Status() (string, error) { + return "ok", nil +} + +// Open implements accounts.Wallet, however this does nothing since this +// is not a hardware device. +func (w *Wallet) Open(passphrase string) error { + return nil +} + +// Close implements accounts.Wallet, however this does nothing since this +// is not a hardware device. +func (w *Wallet) Close() error { + return nil +} + +// Accounts implements accounts.Wallet, returning the list of accounts pinned to +// the wallet. If self-derivation was enabled, the account list is +// periodically expanded based on current chain state. +func (w *Wallet) Accounts() []accounts.Account { + // Attempt self-derivation if it's running + // Return whatever account list we ended up with + w.stateLock.RLock() + defer w.stateLock.RUnlock() + + cpy := make([]accounts.Account, len(w.accounts)) + copy(cpy, w.accounts) + return cpy +} + +// Contains implements accounts.Wallet, returning whether a particular account is +// or is not pinned into this wallet instance. +func (w *Wallet) Contains(account accounts.Account) bool { + w.stateLock.RLock() + defer w.stateLock.RUnlock() + + _, exists := w.paths[account.Address] + return exists +} + +// Unpin unpins account from list of pinned accounts. +func (w *Wallet) Unpin(account accounts.Account) error { + w.stateLock.RLock() + defer w.stateLock.RUnlock() + + for i, acct := range w.accounts { + if acct.Address.String() == account.Address.String() { + w.accounts = removeAtIndex(w.accounts, i) + delete(w.paths, account.Address) + return nil + } + } + + return errors.New("account not found") +} + +// SetFixIssue172 determines whether the standard (correct) bip39 +// derivation path was used, or if derivation should be affected by +// Issue172 [0] which was how this library was originally implemented. +// [0] https://github.com/btcsuite/btcutil/pull/182/files +func (w *Wallet) SetFixIssue172(fixIssue172 bool) { + w.fixIssue172 = fixIssue172 +} + +// Derive implements accounts.Wallet, deriving a new account at the specific +// derivation path. If pin is set to true, the account will be added to the list +// of tracked accounts. +func (w *Wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { + // Try to derive the actual account and update its URL if successful + w.stateLock.RLock() // Avoid device disappearing during derivation + + address, err := w.deriveAddress(path) + + w.stateLock.RUnlock() + + // If an error occurred or no pinning was requested, return + if err != nil { + return accounts.Account{}, err + } + + account := accounts.Account{ + Address: address, + URL: accounts.URL{ + Scheme: "", + Path: path.String(), + }, + } + + if !pin { + return account, nil + } + + // Pinning needs to modify the state + w.stateLock.Lock() + defer w.stateLock.Unlock() + + if _, ok := w.paths[address]; !ok { + w.accounts = append(w.accounts, account) + w.paths[address] = path + } + + return account, nil +} + +// SelfDerive implements accounts.Wallet, trying to discover accounts that the +// user used previously (based on the chain state), but ones that he/she did not +// explicitly pin to the wallet manually. To avoid chain head monitoring, self +// derivation only runs during account listing (and even then throttled). +func (w *Wallet) SelfDerive(base []accounts.DerivationPath, chain ethereum.ChainStateReader) { + // TODO: self derivation +} + +// SignHash implements accounts.Wallet, which allows signing arbitrary data. +func (w *Wallet) SignHash(account accounts.Account, hash []byte) ([]byte, error) { + // Make sure the requested account is contained within + path, ok := w.paths[account.Address] + if !ok { + return nil, accounts.ErrUnknownAccount + } + + privateKey, err := w.derivePrivateKey(path) + if err != nil { + return nil, err + } + + return crypto.Sign(hash, privateKey) +} + +// SignTxEIP155 implements accounts.Wallet, which allows the account to sign an ERC-20 transaction. +func (w *Wallet) SignTxEIP155(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + w.stateLock.RLock() // Comms have own mutex, this is for the state fields + defer w.stateLock.RUnlock() + + // Make sure the requested account is contained within + path, ok := w.paths[account.Address] + if !ok { + return nil, accounts.ErrUnknownAccount + } + + privateKey, err := w.derivePrivateKey(path) + if err != nil { + return nil, err + } + + signer := types.NewEIP155Signer(chainID) + // Sign the transaction and verify the sender to avoid hardware fault surprises + signedTx, err := types.SignTx(tx, signer, privateKey) + if err != nil { + return nil, err + } + + sender, err := types.Sender(signer, signedTx) + if err != nil { + return nil, err + } + + if sender != account.Address { + return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex()) + } + + return signedTx, nil +} + +// SignTx implements accounts.Wallet, which allows the account to sign an Ethereum transaction. +func (w *Wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + w.stateLock.RLock() // Comms have own mutex, this is for the state fields + defer w.stateLock.RUnlock() + + // Make sure the requested account is contained within + path, ok := w.paths[account.Address] + if !ok { + return nil, accounts.ErrUnknownAccount + } + + privateKey, err := w.derivePrivateKey(path) + if err != nil { + return nil, err + } + + signer := types.LatestSignerForChainID(chainID) + + // Sign the transaction and verify the sender to avoid hardware fault surprises + signedTx, err := types.SignTx(tx, signer, privateKey) + if err != nil { + return nil, err + } + + sender, err := types.Sender(signer, signedTx) + if err != nil { + return nil, err + } + + if sender != account.Address { + return nil, fmt.Errorf("signer mismatch: expected %s, got %s", account.Address.Hex(), sender.Hex()) + } + + return signedTx, nil +} + +// SignHashWithPassphrase implements accounts.Wallet, attempting +// to sign the given hash with the given account using the +// passphrase as extra authentication. +func (w *Wallet) SignHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { + return w.SignHash(account, hash) +} + +// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given +// transaction with the given account using passphrase as extra authentication. +func (w *Wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + return w.SignTx(account, tx, chainID) +} + +// PrivateKey returns the ECDSA private key of the account. +func (w *Wallet) PrivateKey(account accounts.Account) (*ecdsa.PrivateKey, error) { + path, err := ParseDerivationPath(account.URL.Path) + if err != nil { + return nil, err + } + + return w.derivePrivateKey(path) +} + +// PrivateKeyBytes returns the ECDSA private key in bytes format of the account. +func (w *Wallet) PrivateKeyBytes(account accounts.Account) ([]byte, error) { + privateKey, err := w.PrivateKey(account) + if err != nil { + return nil, err + } + + return crypto.FromECDSA(privateKey), nil +} + +// PrivateKeyHex return the ECDSA private key in hex string format of the account. +func (w *Wallet) PrivateKeyHex(account accounts.Account) (string, error) { + privateKeyBytes, err := w.PrivateKeyBytes(account) + if err != nil { + return "", err + } + + return hexutil.Encode(privateKeyBytes)[2:], nil +} + +// PublicKey returns the ECDSA public key of the account. +func (w *Wallet) PublicKey(account accounts.Account) (*ecdsa.PublicKey, error) { + path, err := ParseDerivationPath(account.URL.Path) + if err != nil { + return nil, err + } + + return w.derivePublicKey(path) +} + +// PublicKeyBytes returns the ECDSA public key in bytes format of the account. +func (w *Wallet) PublicKeyBytes(account accounts.Account) ([]byte, error) { + publicKey, err := w.PublicKey(account) + if err != nil { + return nil, err + } + + return crypto.FromECDSAPub(publicKey), nil +} + +// PublicKeyHex return the ECDSA public key in hex string format of the account. +func (w *Wallet) PublicKeyHex(account accounts.Account) (string, error) { + publicKeyBytes, err := w.PublicKeyBytes(account) + if err != nil { + return "", err + } + + return hexutil.Encode(publicKeyBytes)[4:], nil +} + +// Address returns the address of the account. +func (w *Wallet) Address(account accounts.Account) (common.Address, error) { + publicKey, err := w.PublicKey(account) + if err != nil { + return common.Address{}, err + } + + return crypto.PubkeyToAddress(*publicKey), nil +} + +// AddressBytes returns the address in bytes format of the account. +func (w *Wallet) AddressBytes(account accounts.Account) ([]byte, error) { + address, err := w.Address(account) + if err != nil { + return nil, err + } + return address.Bytes(), nil +} + +// AddressHex returns the address in hex string format of the account. +func (w *Wallet) AddressHex(account accounts.Account) (string, error) { + address, err := w.Address(account) + if err != nil { + return "", err + } + return address.Hex(), nil +} + +// Path return the derivation path of the account. +func (w *Wallet) Path(account accounts.Account) (string, error) { + return account.URL.Path, nil +} + +// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *Wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { + // Make sure the requested account is contained within + if !w.Contains(account) { + return nil, accounts.ErrUnknownAccount + } + + return w.SignHash(account, crypto.Keccak256(data)) +} + +// SignDataWithPassphrase signs keccak256(data). The mimetype parameter describes the type of data being signed +func (w *Wallet) SignDataWithPassphrase(account accounts.Account, passphrase, mimeType string, data []byte) ([]byte, error) { + // Make sure the requested account is contained within + if !w.Contains(account) { + return nil, accounts.ErrUnknownAccount + } + + return w.SignHashWithPassphrase(account, passphrase, crypto.Keccak256(data)) +} + +// SignText requests the wallet to sign the hash of a given piece of data, prefixed +// the needed details via SignHashWithPassphrase, or by other means (e.g. unlock +// the account in a keystore). +func (w *Wallet) SignText(account accounts.Account, text []byte) ([]byte, error) { + // Make sure the requested account is contained within + if !w.Contains(account) { + return nil, accounts.ErrUnknownAccount + } + + return w.SignHash(account, accounts.TextHash(text)) +} + +// SignTextWithPassphrase implements accounts.Wallet, attempting to sign the +// given text (which is hashed) with the given account using passphrase as extra authentication. +func (w *Wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) { + // Make sure the requested account is contained within + if !w.Contains(account) { + return nil, accounts.ErrUnknownAccount + } + + return w.SignHashWithPassphrase(account, passphrase, accounts.TextHash(text)) +} + +// ParseDerivationPath parses the derivation path in string format into []uint32 +func ParseDerivationPath(path string) (accounts.DerivationPath, error) { + return accounts.ParseDerivationPath(path) +} + +// MustParseDerivationPath parses the derivation path in string format into +// []uint32 but will panic if it can't parse it. +func MustParseDerivationPath(path string) accounts.DerivationPath { + parsed, err := accounts.ParseDerivationPath(path) + if err != nil { + panic(err) + } + + return parsed +} + +// NewMnemonic returns a randomly generated BIP-39 mnemonic using 128-256 bits of entropy. +func NewMnemonic(bits int) (string, error) { + entropy, err := bip39.NewEntropy(bits) + if err != nil { + return "", err + } + return bip39.NewMnemonic(entropy) +} + +// NewMnemonicFromEntropy returns a BIP-39 mnemonic from entropy. +func NewMnemonicFromEntropy(entropy []byte) (string, error) { + return bip39.NewMnemonic(entropy) +} + +// NewEntropy returns a randomly generated entropy. +func NewEntropy(bits int) ([]byte, error) { + return bip39.NewEntropy(bits) +} + +// NewSeed returns a randomly generated BIP-39 seed. +func NewSeed() ([]byte, error) { + b := make([]byte, 64) + _, err := rand.Read(b) + return b, err +} + +// NewSeedFromMnemonic returns a BIP-39 seed based on a BIP-39 mnemonic. +func NewSeedFromMnemonic(mnemonic string, passOpt ...string) ([]byte, error) { + if mnemonic == "" { + return nil, errors.New("mnemonic is required") + } + + password := "" + if len(passOpt) > 0 { + password = passOpt[0] + } + + return bip39.NewSeedWithErrorChecking(mnemonic, password) +} + +// DerivePrivateKey derives the private key of the derivation path. +func (w *Wallet) derivePrivateKey(path accounts.DerivationPath) (*ecdsa.PrivateKey, error) { + var err error + key := w.masterKey + for _, n := range path { + if w.fixIssue172 && key.IsAffectedByIssue172() { + key, err = key.Derive(n) + } else { + key, err = key.DeriveNonStandard(n) + } + if err != nil { + return nil, err + } + } + + privateKey, err := key.ECPrivKey() + privateKeyECDSA := privateKey.ToECDSA() + if err != nil { + return nil, err + } + + return privateKeyECDSA, nil +} + +// DerivePublicKey derives the public key of the derivation path. +func (w *Wallet) derivePublicKey(path accounts.DerivationPath) (*ecdsa.PublicKey, error) { + privateKeyECDSA, err := w.derivePrivateKey(path) + if err != nil { + return nil, err + } + + publicKey := privateKeyECDSA.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + return nil, errors.New("failed to get public key") + } + + return publicKeyECDSA, nil +} + +// DeriveAddress derives the account address of the derivation path. +func (w *Wallet) deriveAddress(path accounts.DerivationPath) (common.Address, error) { + publicKeyECDSA, err := w.derivePublicKey(path) + if err != nil { + return common.Address{}, err + } + + address := crypto.PubkeyToAddress(*publicKeyECDSA) + return address, nil +} + +// removeAtIndex removes an account at index. +func removeAtIndex(accts []accounts.Account, index int) []accounts.Account { + return append(accts[:index], accts[index+1:]...) +} diff --git a/backend/internal/pkg/models/user.go b/backend/internal/pkg/models/user.go index dd2650c..812f6b3 100644 --- a/backend/internal/pkg/models/user.go +++ b/backend/internal/pkg/models/user.go @@ -17,13 +17,22 @@ type User struct { Bip32Seed []byte Admin bool Activated bool - CteatedAt time.Time + CreatedAt time.Time } -func NewUser(id uuid.UUID, seed []byte) *User { +func NewUser( + id uuid.UUID, + seed []byte, + isAdmin bool, + activated bool, + createdAt time.Time, +) *User { return &User{ ID: id, Bip32Seed: seed, + Admin: isAdmin, + Activated: activated, + CreatedAt: createdAt, } } diff --git a/backend/internal/pkg/sqlutils/tx.go b/backend/internal/pkg/sqlutils/tx.go index 84aa9d6..e04a4b2 100644 --- a/backend/internal/pkg/sqlutils/tx.go +++ b/backend/internal/pkg/sqlutils/tx.go @@ -21,11 +21,11 @@ type TransactionalStorage interface { Conn(ctx context.Context) DBTX } -type TxCtxKey struct{} +type txCtxKey struct{} -func Transaction(ctx context.Context, db *sql.DB, fn func(context.Context) error) error { - var err error +var TxCtxKey = txCtxKey{} +func Transaction(ctx context.Context, db *sql.DB, fn func(context.Context) error) (err error) { var tx *sql.Tx = new(sql.Tx) hasExternalTx := hasExternalTransaction(ctx) @@ -70,14 +70,14 @@ func Transaction(ctx context.Context, db *sql.DB, fn func(context.Context) error return fmt.Errorf("error begin transaction. %w", err) } - ctx = context.WithValue(ctx, TxCtxKey{}, tx) + ctx = context.WithValue(ctx, TxCtxKey, tx) } return fn(ctx) } func hasExternalTransaction(ctx context.Context) bool { - if _, ok := ctx.Value(TxCtxKey{}).(*sql.Tx); ok { + if _, ok := ctx.Value(TxCtxKey).(*sql.Tx); ok { return true } diff --git a/backend/internal/usecase/interactors/users/interactor.go b/backend/internal/usecase/interactors/users/interactor.go new file mode 100644 index 0000000..9f51405 --- /dev/null +++ b/backend/internal/usecase/interactors/users/interactor.go @@ -0,0 +1,100 @@ +package users + +import ( + "context" + "fmt" + "log/slog" + "time" + + "github.com/emochka2007/block-accounting/internal/pkg/hdwallet" + "github.com/emochka2007/block-accounting/internal/pkg/models" + "github.com/emochka2007/block-accounting/internal/usecase/repository/users" + "github.com/google/uuid" +) + +type CreateParams struct { + Mnemonic string + IsAdmin bool + Activate bool +} + +type GetParams struct { + Ids uuid.UUIDs + OrganizationId uuid.UUID + Mnemonic string + Seed []byte +} + +type DeleteParams struct { + Id uuid.UUID + OrganizationId uuid.UUID +} + +type ActivateParams struct { + Id uuid.UUID + OrganizationId uuid.UUID +} + +type UsersInteractor interface { + Create(ctx context.Context, params CreateParams) (*models.User, error) + Update(ctx context.Context, newState models.User) error + Activate(ctx context.Context, params ActivateParams) error + Get(ctx context.Context, params GetParams) ([]*models.User, error) + Delete(ctx context.Context, params DeleteParams) error +} + +type usersInteractor struct { + log *slog.Logger + usersRepo users.Repository +} + +func NewUsersInteractor( + log *slog.Logger, + usersRepo users.Repository, +) UsersInteractor { + return &usersInteractor{ + log: log, + usersRepo: usersRepo, + } +} + +func (i *usersInteractor) Create(ctx context.Context, params CreateParams) (*models.User, error) { + seed, err := hdwallet.NewSeedFromMnemonic(params.Mnemonic) + if err != nil { + return nil, fmt.Errorf("error convert mnemonic into a bytes. %w", err) + } + + user := models.NewUser( + uuid.New(), + seed, + params.IsAdmin, + params.Activate, + time.Now(), + ) + + w, _ := hdwallet.NewFromSeed(seed) + + fmt.Println(w) + + if err = i.usersRepo.Create(ctx, user); err != nil { + return nil, fmt.Errorf("error create new user. %w", err) + } + + return user, nil +} + +func (i *usersInteractor) Update(ctx context.Context, newState models.User) error { + return nil +} + +func (i *usersInteractor) Activate(ctx context.Context, params ActivateParams) error { + return nil +} + +func (i *usersInteractor) Get(ctx context.Context, params GetParams) ([]*models.User, error) { + return nil, nil +} + +func (i *usersInteractor) Delete(ctx context.Context, params DeleteParams) error { + return nil +} diff --git a/backend/internal/usecase/repository/db.go b/backend/internal/usecase/repository/db.go new file mode 100644 index 0000000..b782d87 --- /dev/null +++ b/backend/internal/usecase/repository/db.go @@ -0,0 +1,31 @@ +package repository + +import ( + "database/sql" + "fmt" + + "github.com/emochka2007/block-accounting/internal/pkg/config" + + _ "github.com/lib/pq" +) + +func ProvideDatabaseConnection(c config.Config) (*sql.DB, func(), error) { + sslmode := "disable" + if c.DB.EnableSSL { + sslmode = "enable" + } + + connStr := fmt.Sprintf( + "postgresql://%s:%s@%s/%s?sslmode=%s", + c.DB.User, c.DB.Secret, c.DB.Host, c.DB.Database, sslmode, + ) + + db, err := sql.Open("postgres", connStr) + if err != nil { + return nil, func() {}, fmt.Errorf("error connecting to database: %w", err) + } + + return db, func() { + db.Close() + }, nil +} diff --git a/backend/internal/usecase/repository/transactions/repository.go b/backend/internal/usecase/repository/transactions/repository.go index 1bfea7c..76b9d69 100644 --- a/backend/internal/usecase/repository/transactions/repository.go +++ b/backend/internal/usecase/repository/transactions/repository.go @@ -59,7 +59,7 @@ type repositorySQL struct { } func (s *repositorySQL) Conn(ctx context.Context) sqltools.DBTX { - if tx, ok := ctx.Value(sqltools.TxCtxKey{}).(*sql.Tx); ok { + if tx, ok := ctx.Value(sqltools.TxCtxKey).(*sql.Tx); ok { return tx } @@ -260,7 +260,7 @@ func buildGetTransactionsQuery(params GetTransactionsParams) sq.SelectBuilder { InnerJoin("users as u on u.id = t.created_by"). Where(sq.Eq{ "t.organization_id": params.OrganizationId, - }) + }).PlaceholderFormat(sq.Dollar) if len(params.Ids) > 0 { query = query.Where(sq.Eq{ diff --git a/backend/internal/usecase/repository/users/repository.go b/backend/internal/usecase/repository/users/repository.go index 39e163b..42197b1 100644 --- a/backend/internal/usecase/repository/users/repository.go +++ b/backend/internal/usecase/repository/users/repository.go @@ -37,7 +37,7 @@ func NewRepository(db *sql.DB) Repository { } func (s *repositorySQL) Conn(ctx context.Context) sqltools.DBTX { - if tx, ok := ctx.Value(sqltools.TxCtxKey{}).(*sql.Tx); ok { + if tx, ok := ctx.Value(sqltools.TxCtxKey).(*sql.Tx); ok { return tx } @@ -58,18 +58,27 @@ func (r *repositorySQL) Get(ctx context.Context, params GetParams) (*models.User func (r *repositorySQL) Create(ctx context.Context, user *models.User) error { if err := sqltools.Transaction(ctx, r.db, func(ctx context.Context) error { - query := sq.Insert("users").Columns( - "id", "seed", "created_at", - ).Values( + columns := []string{"id", "seed", "created_at"} + + values := []any{ user.ID, user.Bip32Seed, - user.CteatedAt, - ) + user.CreatedAt, + } if user.Activated { - query = query.Columns("activated_at").Values(user.CteatedAt) + columns = append(columns, "activated_at") + values = append(values, user.CreatedAt) } + query := sq.Insert("users").Columns( + columns..., + ).Values( + values..., + ).PlaceholderFormat(sq.Dollar) + + fmt.Println(query.ToSql()) + if _, err := query.RunWith(r.Conn(ctx)).ExecContext(ctx); err != nil { return fmt.Errorf("error insert new user. %w", err) }