From 84502e7b2a00b61cc745432291e3dc8449dccdba Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 13 May 2024 22:26:58 +0800 Subject: [PATCH 01/23] update go.mod --- go.mod | 14 +------------- go.sum | 60 ++++++++++++---------------------------------------------- 2 files changed, 13 insertions(+), 61 deletions(-) diff --git a/go.mod b/go.mod index 80736515..c31bbc71 100644 --- a/go.mod +++ b/go.mod @@ -25,26 +25,14 @@ require ( github.com/NethermindEth/juno v0.3.1 // indirect github.com/fxamacker/cbor/v2 v2.4.0 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect - github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/joho/godotenv v1.5.1 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.18.2 // indirect - github.com/subosito/gotenv v1.6.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/test-go/testify v1.1.4 // indirect github.com/x448/float16 v0.8.4 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect ) require ( diff --git a/go.sum b/go.sum index eebfdc2f..b9871cf8 100644 --- a/go.sum +++ b/go.sum @@ -37,14 +37,14 @@ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpV github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/cockroachdb/errors v1.9.0 h1:B48dYem5SlAY7iU8AKsgedb4gH6mo+bDkbtLIvM/a88= -github.com/cockroachdb/errors v1.9.0/go.mod h1:vaNcEYYqbIqB5JhKBhFV9CneUqeuEbB2OYJBK4GBNYQ= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f h1:6jduT9Hfc0njg5jJ1DdKCFPdMBrp/mdZfCpa5h+WM74= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +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= @@ -55,12 +55,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/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 v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,12 +67,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/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.13.14 h1:EwiY3FZP94derMCIam1iW4HFVrSgIcpsu0HwTQtm6CQ= -github.com/ethereum/go-ethereum v1.13.14/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU= github.com/ethereum/go-ethereum v1.14.3 h1:5zvnAqLtnCZrU9uod1JCvHWJbPMURzYFHfc2eHz4PHA= github.com/ethereum/go-ethereum v1.14.3/go.mod h1:1STrq471D0BQbCX9He0hUj4bHxX2k6mt5nOQJhDNOJ8= github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= @@ -92,8 +85,8 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqG github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= -github.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo= -github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0= +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/gin-contrib/cors v1.7.1 h1:s9SIppU/rk8enVvkzwiC2VK3UZ/0NNGsWfUKvV55rqs= github.com/gin-contrib/cors v1.7.1/go.mod h1:n/Zj7B4xyrgk/cX1WCX2dkzFfaNm/xJb6oIUk7WTtps= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= @@ -157,8 +150,6 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -170,16 +161,14 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -194,8 +183,6 @@ github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -236,7 +223,6 @@ github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeB github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -256,24 +242,10 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/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/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -288,8 +260,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= @@ -327,10 +297,6 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -414,8 +380,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= From c80f2b191ff6571d33f1f349b48ebe3b963a1726 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 17 May 2024 17:22:58 +0800 Subject: [PATCH 02/23] update relay model --- cmd/server/main.go | 2 + common/global_const/common_const.go | 6 + common/global_const/token.go | 9 +- common/model/api_key_info.go | 1 + common/model/api_request.go | 15 +- common/model/secret_config.go | 15 ++ common/model/strategy.go | 16 ++- config/basic_config.go | 4 + config/basic_strategy_config.go | 2 +- config/secret_config.go | 28 ++++ docs/swagger.json | 6 +- gas_executor/gas_computor_test.go | 5 +- go.mod | 10 ++ go.sum | 22 +++ rpc_server/api/v1/paymaster.go | 4 +- rpc_server/middlewares/auth.go | 41 +++++- rpc_server/middlewares/rate_limit.go | 15 +- rpc_server/middlewares/rate_limit_test.go | 5 +- .../dashboard_service/dashboard_service.go | 132 ++++++++++++++++-- service/operator/try_pay_user_op_execute.go | 21 ++- 20 files changed, 300 insertions(+), 59 deletions(-) create mode 100644 common/model/api_key_info.go diff --git a/cmd/server/main.go b/cmd/server/main.go index 4c29167f..28a5ffbc 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -4,6 +4,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/config" "AAStarCommunity/EthPaymaster_BackService/envirment" "AAStarCommunity/EthPaymaster_BackService/rpc_server/routers" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "flag" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" @@ -67,6 +68,7 @@ func initEngine(strategyPath string, basicConfigPath string, secretPath string) } else { logrus.SetLevel(logrus.InfoLevel) } + dashboard_service.Init() logrus.Infof("Environment: %s", envirment.Environment.Name) logrus.Infof("Debugger: %v", envirment.Environment.Debugger) Engine = routers.SetRouters() diff --git a/common/global_const/common_const.go b/common/global_const/common_const.go index 97d2c421..258e1967 100644 --- a/common/global_const/common_const.go +++ b/common/global_const/common_const.go @@ -9,6 +9,8 @@ import ( "math/big" ) +type StrategyStatus string + const ( DummyPrivateKeyText = "0a82406dc7fcf16090e05215ff394c7465608dd1a698632471b1eb37b8ece2f7" DummySignature = "0x3054659b5e29460a8f3ac9afc3d5fcbe4b76f92aed454b944e9b29e55d80fde807716530b739540e95cfa4880d69f710a9d45910f2951a227675dc1fb0fdf2c71c" @@ -17,6 +19,10 @@ const ( DummyVerificationGas = 50000 DummyPaymasterPostOpGasLimit = 2000000 DummyPaymasterVerificationGasLimit = 5000000 + + ContextKeyApiMoDel = "api_model" + StrategyStatusDisable StrategyStatus = "disable" + StrategyStatusAchieve StrategyStatus = "achieve" ) var ( diff --git a/common/global_const/token.go b/common/global_const/token.go index 69ab4fd6..36f5fb81 100644 --- a/common/global_const/token.go +++ b/common/global_const/token.go @@ -22,8 +22,9 @@ func IsStableToken(token TokenType) bool { } const ( - TokenTypeUSDT TokenType = "USDT" - TokenTypeUSDC TokenType = "USDC" - TokenTypeETH TokenType = "ETH" - TokenTypeOP TokenType = "OP" + TokenTypeUSDT TokenType = "USDT" + TokenTypeUSDC TokenType = "USDC" + TokenTypeETH TokenType = "ETH" + TokenTypeOP TokenType = "OP" + TokenTypeAAStar TokenType = "AAStar" ) diff --git a/common/model/api_key_info.go b/common/model/api_key_info.go new file mode 100644 index 00000000..8b537907 --- /dev/null +++ b/common/model/api_key_info.go @@ -0,0 +1 @@ +package model diff --git a/common/model/api_request.go b/common/model/api_request.go index b068f33b..5f789c35 100644 --- a/common/model/api_request.go +++ b/common/model/api_request.go @@ -5,14 +5,13 @@ import ( ) type UserOpRequest struct { - ForceStrategyId string `json:"force_strategy_id"` - ForceNetwork global_const.Network `json:"force_network"` - Erc20Token global_const.TokenType `json:"force_token"` - ForceEntryPointAddress string `json:"force_entrypoint_address"` - UserOp map[string]any `json:"user_operation"` - Extra interface{} `json:"extra"` - EstimateOpGas bool `json:"estimate_op_gas"` - EntryPointVersion global_const.EntrypointVersion `json:"entrypoint_version"` + ForceStrategyId string `json:"force_strategy_id"` + Network global_const.Network `json:"force_network"` + Erc20Token global_const.TokenType `json:"force_token"` + UserOp map[string]any `json:"user_operation"` + Extra interface{} `json:"extra"` + EstimateOpGas bool `json:"estimate_op_gas"` + EntryPointVersion global_const.EntrypointVersion `json:"entrypoint_version"` } type JsonRpcRequest struct { JsonRpc string `json:"jsonrpc"` diff --git a/common/model/secret_config.go b/common/model/secret_config.go index cf7c7542..5f8a4f81 100644 --- a/common/model/secret_config.go +++ b/common/model/secret_config.go @@ -1,9 +1,24 @@ package model +type DBConfig struct { + Host string `json:"host"` + Port int `json:"port"` + User string `json:"user"` + Password string `json:"password"` + DBName string `json:"db_name"` + TimeZone string `json:"tz"` + SslMode string `json:"ssl_mode"` +} + type SecretConfig struct { PriceOracleApiKey string `json:"price_oracle_api_key"` NetWorkSecretConfigMap map[string]NetWorkSecretConfig `json:"network_secret_configs"` + + ConfigDBConfig DBConfig `json:"config_db_config"` + RelayDBConfig DBConfig `json:"relay_db_config"` + ApiKeyTableName string `json:"api_key_table_name"` + StrategyConfigTableName string `json:"strategy_config_table_name"` } type NetWorkSecretConfig struct { diff --git a/common/model/strategy.go b/common/model/strategy.go index 80f761f3..309329dd 100644 --- a/common/model/strategy.go +++ b/common/model/strategy.go @@ -15,15 +15,17 @@ type Strategy struct { EntryPointInfo *EntryPointInfo `json:"entrypoint_info"` Description string `json:"description"` ExecuteRestriction StrategyExecuteRestriction `json:"execute_restriction"` - Erc20TokenType global_const.TokenType + + Erc20TokenType global_const.TokenType } type PaymasterInfo struct { - PayMasterAddress *common.Address `json:"paymaster_address"` - PayType global_const.PayType `json:"pay_type"` + PayMasterAddress *common.Address `json:"paymaster_address"` + PayType global_const.PayType `json:"pay_type"` + IsProjectErc20PayEnable bool `json:"is_project_erc20_pay_enable"` } type NetWorkInfo struct { - NetWork global_const.Network `json:"network"` - Token global_const.TokenType `json:"tokens"` + NetWork global_const.Network `json:"network"` + GasToken global_const.TokenType `json:"tokens"` } type EntryPointInfo struct { EntryPointAddress *common.Address `json:"entrypoint_address"` @@ -41,7 +43,7 @@ func (strategy *Strategy) GetNewWork() global_const.Network { } func (strategy *Strategy) GetUseToken() global_const.TokenType { - return strategy.NetWorkInfo.Token + return strategy.NetWorkInfo.GasToken } func (strategy *Strategy) GetPayType() global_const.PayType { return strategy.PaymasterInfo.PayType @@ -49,7 +51,7 @@ func (strategy *Strategy) GetPayType() global_const.PayType { func (strategy *Strategy) GetStrategyEntrypointVersion() global_const.EntrypointVersion { return strategy.EntryPointInfo.EntryPointVersion } -func (strategy Strategy) IsCurrencyPayEnable() bool { +func (strategy *Strategy) IsCurrencyPayEnable() bool { return false } diff --git a/config/basic_config.go b/config/basic_config.go index ca6e57dc..6f4dfcbe 100644 --- a/config/basic_config.go +++ b/config/basic_config.go @@ -170,8 +170,12 @@ var ( global_const.ScrollMainnet: common.HexToAddress("0x5300000000000000000000000000000000000002"), } Disable1559Chain = mapset.NewSet(global_const.ScrollSepolia, global_const.ScrollMainnet) + PErc20TokenSet = mapset.NewSet(global_const.TokenTypeAAStar) ) +func IsPErc20Token(token global_const.TokenType) bool { + return PErc20TokenSet.Contains(token) +} func IsDisable1559Chain(network global_const.Network) bool { return Disable1559Chain.Contains(network) } diff --git a/config/basic_strategy_config.go b/config/basic_strategy_config.go index 2462970d..cd4debba 100644 --- a/config/basic_strategy_config.go +++ b/config/basic_strategy_config.go @@ -90,7 +90,7 @@ func convertMapToStrategyConfig(data map[string]map[string]any) (map[string]*mod } if strategy.GetPayType() == global_const.PayTypeERC20 { erc20TokenStr := value["access_erc20"].(string) - strategy.NetWorkInfo.Token = global_const.TokenType(erc20TokenStr) + strategy.NetWorkInfo.GasToken = global_const.TokenType(erc20TokenStr) strategy.ExecuteRestriction.AccessErc20 = utils.ConvertStringToSet(erc20TokenStr, ",") } diff --git a/config/secret_config.go b/config/secret_config.go index 9148b405..22e6c284 100644 --- a/config/secret_config.go +++ b/config/secret_config.go @@ -8,6 +8,8 @@ import ( "os" ) +var dsnTemplate = "host=%s port=%v user=%s password=%s dbname=%s TimeZone=%s sslmode=%s" + var secretConfig *model.SecretConfig var signerConfig = make(SignerConfigMap) @@ -54,3 +56,29 @@ func GetSignerKey(network global_const.Network) string { func GetSigner(network global_const.Network) *global_const.EOA { return signerConfig[network] } +func GetAPIKeyTableName() string { + return secretConfig.ApiKeyTableName +} +func GetStrategyConfigTableName() string { + return secretConfig.StrategyConfigTableName +} +func GetConfigDBDSN() string { + return fmt.Sprintf(dsnTemplate, + secretConfig.ConfigDBConfig.Host, + secretConfig.ConfigDBConfig.Port, + secretConfig.ConfigDBConfig.User, + secretConfig.ConfigDBConfig.Password, + secretConfig.ConfigDBConfig.DBName, + secretConfig.ConfigDBConfig.TimeZone, + secretConfig.ConfigDBConfig.SslMode) +} +func GetRelayDBDSN() string { + return fmt.Sprintf(dsnTemplate, + secretConfig.RelayDBConfig.Host, + secretConfig.RelayDBConfig.Port, + secretConfig.RelayDBConfig.User, + secretConfig.RelayDBConfig.Password, + secretConfig.RelayDBConfig.DBName, + secretConfig.RelayDBConfig.TimeZone, + secretConfig.RelayDBConfig.SslMode) +} diff --git a/docs/swagger.json b/docs/swagger.json index f813c38c..39da748c 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -4,7 +4,9 @@ "contact": { "name": "AAStar Support", "url": "https://aastar.xyz" - } + }, + "version": "", + "title": "" }, "paths": { "/api/auth": { @@ -119,4 +121,4 @@ "in": "header" } } -} \ No newline at end of file +} diff --git a/gas_executor/gas_computor_test.go b/gas_executor/gas_computor_test.go index 26107316..1fd6f008 100644 --- a/gas_executor/gas_computor_test.go +++ b/gas_executor/gas_computor_test.go @@ -7,7 +7,6 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/user_op" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/config" - "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "encoding/json" "github.com/sirupsen/logrus" "math/big" @@ -73,7 +72,7 @@ func TestComputeGas(t *testing.T) { { "testEstimateVerificationGasLimit", func(*testing.T) { - strategy := dashboard_service.GetStrategyByCode("Ethereum_Sepolia_v06_verifyPaymaster") + strategy := config.GetBasicStrategyConfig("Ethereum_Sepolia_v06_verifyPaymaster") if strategy == nil { t.Fatal("strategy is nil") } @@ -84,7 +83,7 @@ func TestComputeGas(t *testing.T) { "testScrollGetUserOpEstimateGas", func(*testing.T) { - strategy := dashboard_service.GetStrategyByCode(string(global_const.StrategyCodeScrollSepoliaV06Verify)) + strategy := config.GetBasicStrategyConfig(global_const.StrategyCodeScrollSepoliaV06Verify) testGetUserOpEstimateGas(t, opFor1559NotSupport, strategy) }, diff --git a/go.mod b/go.mod index 80736515..abd3b8c3 100644 --- a/go.mod +++ b/go.mod @@ -24,11 +24,17 @@ require ( require ( github.com/NethermindEth/juno v0.3.1 // indirect github.com/fxamacker/cbor/v2 v2.4.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -45,6 +51,10 @@ require ( go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.9.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gorm.io/datatypes v1.2.0 // indirect + gorm.io/driver/mysql v1.4.7 // indirect + gorm.io/driver/postgres v1.5.7 // indirect + gorm.io/gorm v1.25.10 // indirect ) require ( diff --git a/go.sum b/go.sum index eebfdc2f..aa24711c 100644 --- a/go.sum +++ b/go.sum @@ -121,6 +121,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= @@ -168,8 +170,19 @@ github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXei github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -427,6 +440,15 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco= +gorm.io/datatypes v1.2.0/go.mod h1:o1dh0ZvjIjhH/bngTpypG6lVRJ5chTBxE09FH/71k04= +gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y= +gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/rpc_server/api/v1/paymaster.go b/rpc_server/api/v1/paymaster.go index 18ad6cc7..3824c85c 100644 --- a/rpc_server/api/v1/paymaster.go +++ b/rpc_server/api/v1/paymaster.go @@ -168,7 +168,7 @@ func parseTryPayUserOperationParams(params []interface{}) (*model.UserOpRequest, result.ForceStrategyId = extra["strategy_code"].(string) } if extra["network"] != nil { - result.ForceNetwork = extra["network"].(global_const.Network) + result.Network = extra["network"].(global_const.Network) } if extra["token"] != nil { result.Erc20Token = extra["token"].(global_const.TokenType) @@ -183,7 +183,7 @@ func validateUserOpRequest(request *model.UserOpRequest) error { if request.ForceStrategyId != "" { return nil } - if request.ForceNetwork == "" { + if request.Network == "" { return xerrors.Errorf("ForceNetwork is empty") } diff --git a/rpc_server/middlewares/auth.go b/rpc_server/middlewares/auth.go index 472bca3c..9b6c8982 100644 --- a/rpc_server/middlewares/auth.go +++ b/rpc_server/middlewares/auth.go @@ -1,9 +1,13 @@ package middlewares import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/envirment" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" jwt "github.com/appleboy/gin-jwt/v2" "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" + "golang.org/x/xerrors" "time" ) @@ -37,18 +41,47 @@ func AuthHandler() gin.HandlerFunc { if err := c.ShouldBind(&apiKey); err != nil { return "", jwt.ErrMissingLoginValues } + // TODO check APIKey is UseFul - // TODO: verify if the key is correct return apiKey.Key, nil // if incorrect //return nil, jwt.ErrFailedAuthentication }, + //every Request will be checked Authorizator: func(data interface{}, c *gin.Context) bool { // always return true unless the permission feature started + if data == nil { + logrus.Errorf("Authorizator id is nil") + return false + } + apiKey := data.(string) + if apiKey == "" { + logrus.Errorf("Authorizator id is nil") + return false + } + + apiModel, err := dashboard_service.GetAPiInfoByApiKey(apiKey) + if err != nil { + c.Set("ERROR_REASON", err.Error()) + return false + } + if apiModel == nil { + c.Set("ERROR_REASON", "API Key is not found") + return false + } + err = CheckAPIKeyAvailable(apiModel) + if err != nil { + c.Set("ERROR_REASON", err.Error()) + return false + } + c.Set(global_const.ContextKeyApiMoDel, apiModel) return true }, Unauthorized: func(c *gin.Context, code int, message string) { + if c.GetString("ERROR_REASON") != "" { + message = c.GetString("ERROR_REASON") + } c.JSON(code, gin.H{ "code": code, "message": message, @@ -66,3 +99,9 @@ func AuthHandler() gin.HandlerFunc { return m.MiddlewareFunc() } +func CheckAPIKeyAvailable(apiModel *dashboard_service.ApiKeyModel) error { + if apiModel.Disable { + return xerrors.Errorf("API Key is disabled") + } + return nil +} diff --git a/rpc_server/middlewares/rate_limit.go b/rpc_server/middlewares/rate_limit.go index 5c1ea090..853340d2 100644 --- a/rpc_server/middlewares/rate_limit.go +++ b/rpc_server/middlewares/rate_limit.go @@ -1,7 +1,9 @@ package middlewares import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/rpc_server/api/utils" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "errors" "github.com/gin-gonic/gin" "golang.org/x/time/rate" @@ -19,8 +21,12 @@ var limiter map[string]*rate.Limiter func RateLimiterByApiKeyHandler() gin.HandlerFunc { return func(ctx *gin.Context) { if exists, current := utils.CurrentUser(ctx); exists { - - if limiting(¤t) { + apiKeyModel, _ := ctx.Get(global_const.ContextKeyApiMoDel) + defaultLimit := DefaultLimit + if apiKeyModel != nil { + defaultLimit = apiKeyModel.(*dashboard_service.ApiKeyModel).GetRateLimit() + } + if limiting(¤t, defaultLimit) { ctx.Next() } else { _ = ctx.AbortWithError(http.StatusTooManyRequests, errors.New("too many requests")) @@ -34,14 +40,13 @@ func clearLimiter(apiKey *string) { delete(limiter, *apiKey) } -func limiting(apiKey *string) bool { +func limiting(apiKey *string, defaultLimit rate.Limit) bool { var l *rate.Limiter if limit, ok := limiter[*apiKey]; ok { l = limit } else { - // TODO: different rate config for each current(apiKey) should get from dashboard service - l = rate.NewLimiter(DefaultLimit, DefaultBurst) + l = rate.NewLimiter(defaultLimit, DefaultBurst) limiter[*apiKey] = l } diff --git a/rpc_server/middlewares/rate_limit_test.go b/rpc_server/middlewares/rate_limit_test.go index e7d86dbc..f46d1063 100644 --- a/rpc_server/middlewares/rate_limit_test.go +++ b/rpc_server/middlewares/rate_limit_test.go @@ -33,10 +33,9 @@ func TestLimit(t *testing.T) { func testRateLimitShouldPreventRequestWhenOverDefaultLimit(t *testing.T) { mockApiKey := "TestingAipKey" - // assuming this for loop taking less than 1 second to finish for i := 0; i < int(DefaultLimit)+5; i++ { - b := limiting(&mockApiKey) + b := limiting(&mockApiKey, DefaultLimit) if i < int(DefaultLimit) { assert.Equal(t, true, b) } else { @@ -55,7 +54,7 @@ func testRateLimiterShouldAllowDefaultLimitPerSecond(t *testing.T) { for x := 1; x <= 2; x++ { for i := 0; i < int(DefaultLimit)+5; i++ { - b := limiting(&mockApiKey) + b := limiting(&mockApiKey, DefaultLimit) if i < int(DefaultLimit) { assert.Equal(t, true, b) } else { diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index a49ea4f3..cc24abad 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -5,33 +5,117 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/config" "errors" + "golang.org/x/time/rate" + "golang.org/x/xerrors" + "gorm.io/datatypes" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "sync" ) -func GetStrategyByCode(strategyCode string) *model.Strategy { - strategy := config.GetBasicStrategyConfig(global_const.BasicStrategyCode(strategyCode)) +var ( + configDB *gorm.DB + relayDB *gorm.DB + onlyOnce = sync.Once{} +) + +func Init() { + onlyOnce.Do(func() { + configDBDsn := config.GetConfigDBDSN() + relayDBDsn := config.GetRelayDBDSN() + + configDBVar, err := gorm.Open(postgres.Open(configDBDsn), &gorm.Config{}) + if err != nil { + panic(err) + } + configDB = configDBVar + + relayDBVar, err := gorm.Open(postgres.Open(relayDBDsn), &gorm.Config{}) + if err != nil { + panic(err) + } + relayDB = relayDBVar + }) + +} + +type StrategyDBModel struct { + Description string `gorm:"type:varchar(500)" json:"description"` + StrategyCode string `gorm:"type:varchar(255)" json:"strategy_code"` + ProjectCode string `gorm:"type:varchar(255)" json:"project_code"` + StrategyName string `gorm:"type:varchar(255)" json:"strategy_name"` + UserId string `gorm:"type:varchar(255)" json:"user_id"` + Status global_const.StrategyStatus `gorm:"type:varchar(20)" json:"status"` + ExecuteRestriction datatypes.JSON `gorm:"type:json" json:"execute_restriction"` + Extra datatypes.JSON `gorm:"type:json" json:"extra"` +} + +func (StrategyDBModel) TableName() string { + return config.GetStrategyConfigTableName() +} + +// GetStrategyByCode is Sponsor Type , need GasTank +func GetStrategyByCode(strategyCode string, entryPointVersion global_const.EntrypointVersion, chain global_const.Network) (*model.Strategy, error) { + + strategyDbModel := &StrategyDBModel{} + tx := configDB.Where("strategy_code = ?", strategyCode).First(&strategyDbModel) + if tx.Error != nil { + return nil, tx.Error + } + + strategy, err := convertStrategyDBModelToStrategy(strategyDbModel) + if err != nil { + return nil, err + } paymasterAddress := config.GetPaymasterAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) strategy.PaymasterInfo.PayMasterAddress = &paymasterAddress entryPointAddress := config.GetEntrypointAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) strategy.EntryPointInfo.EntryPointAddress = &entryPointAddress - return strategy + return strategy, nil } -func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain global_const.Network, payType global_const.PayType) (*model.Strategy, error) { +func convertStrategyDBModelToStrategy(strategyDBModel *StrategyDBModel) (*model.Strategy, error) { + return &model.Strategy{}, nil +} + +// GetSuitableStrategy get suitable strategy by entryPointVersion, chain, +// +// For Offical StrategyConfig, +func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain global_const.Network, gasUseToken global_const.TokenType) (*model.Strategy, error) { if entryPointVersion == "" { entryPointVersion = global_const.EntrypointV06 } - strategy, err := config.GetSuitableStrategy(entryPointVersion, chain, payType) - if err != nil { - return nil, err + gasToken := config.GetGasToken(chain) + entryPointAddress := config.GetEntrypointAddress(chain, entryPointVersion) + paymasterAddress := config.GetPaymasterAddress(chain, entryPointVersion) + payType := global_const.PayTypeVerifying + isPerc20Enable := false + if gasUseToken != "" { + payType = global_const.PayTypeERC20 + if config.IsPErc20Token(gasUseToken) { + isPerc20Enable = true + } } + strategy := &model.Strategy{ + NetWorkInfo: &model.NetWorkInfo{ + NetWork: chain, + GasToken: gasToken, + }, + EntryPointInfo: &model.EntryPointInfo{ + EntryPointVersion: entryPointVersion, + EntryPointAddress: &entryPointAddress, + }, + PaymasterInfo: &model.PaymasterInfo{ + PayMasterAddress: &paymasterAddress, + PayType: payType, + IsProjectErc20PayEnable: isPerc20Enable, + }, + Erc20TokenType: gasUseToken, + } if strategy == nil { return nil, errors.New("strategy not found") } - paymasterAddress := config.GetPaymasterAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) - strategy.PaymasterInfo.PayMasterAddress = &paymasterAddress - entryPointAddress := config.GetEntrypointAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) - strategy.EntryPointInfo.EntryPointAddress = &entryPointAddress return strategy, nil } @@ -50,3 +134,29 @@ func IsPayMasterSupport(address string, chain global_const.Network) bool { return supportPayMasterSet.Contains(address) } + +type ApiKeyModel struct { + Disable bool `gorm:"column:disable;type:bool" json:"disable"` + ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"` + KeyName string `gorm:"column:key_name;type:varchar(255)" json:"key_name"` + Extra datatypes.JSON `gorm:"column:extra" json:"extra"` +} + +func (*ApiKeyModel) TableName() string { + return config.GetAPIKeyTableName() +} + +func (m *ApiKeyModel) GetRateLimit() rate.Limit { + return 10 +} +func GetAPiInfoByApiKey(apiKey string) (apikeyModel *ApiKeyModel, err error) { + apikeyModel = &ApiKeyModel{} + tx := configDB.Where("api_key = ?", apiKey).First(&apikeyModel) + if tx.Error != nil { + if errors.Is(tx.Error, gorm.ErrRecordNotFound) { + return nil, tx.Error + } + return apikeyModel, xerrors.Errorf("error when finding apikey: %w", tx.Error) + } + return apikeyModel, nil +} diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 0981134d..565890ac 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -142,13 +142,17 @@ func StrategyGenerate(request *model.UserOpRequest) (*model.Strategy, error) { var strategyResult *model.Strategy if forceStrategyId := request.ForceStrategyId; forceStrategyId != "" { //force strategy - if strategy := dashboard_service.GetStrategyByCode(forceStrategyId); strategy == nil { - return nil, xerrors.Errorf("Not Support Strategy ID: [%w]", forceStrategyId) - } else { - strategyResult = strategy + strategy, err := dashboard_service.GetStrategyByCode(forceStrategyId, request.EntryPointVersion, request.Network) + if err != nil { + return nil, err + } + if strategy == nil { + return nil, xerrors.Errorf("Empty Strategies") } + strategyResult = strategy + } else { - suitableStrategy, err := dashboard_service.GetSuitableStrategy(request.EntryPointVersion, request.ForceNetwork, global_const.PayTypeSuperVerifying) //TODO + suitableStrategy, err := dashboard_service.GetSuitableStrategy(request.EntryPointVersion, request.Network, request.Erc20Token) //TODO if err != nil { return nil, err } @@ -158,12 +162,5 @@ func StrategyGenerate(request *model.UserOpRequest) (*model.Strategy, error) { strategyResult = suitableStrategy } - if strategyResult.GetPayType() == global_const.PayTypeERC20 { - if request.Erc20Token == "" { - return nil, xerrors.Errorf("Empty Erc20Token") - } - strategyResult.Erc20TokenType = request.Erc20Token - - } return strategyResult, nil } From 45a67c04b1d97906bc4dbf6be984e37910982409 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 17 May 2024 17:39:29 +0800 Subject: [PATCH 03/23] update relay model --- common/model/api_key_info.go | 8 +++++++ rpc_server/middlewares/auth.go | 16 +++++++++----- rpc_server/middlewares/rate_limit.go | 4 ++-- .../dashboard_service/dashboard_service.go | 22 +++++++++++++------ 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/common/model/api_key_info.go b/common/model/api_key_info.go index 8b537907..42b287d8 100644 --- a/common/model/api_key_info.go +++ b/common/model/api_key_info.go @@ -1 +1,9 @@ package model + +import "golang.org/x/time/rate" + +type ApiKeyModel struct { + Disable bool `gorm:"column:disable;type:bool" json:"disable"` + ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"` + RateLimit rate.Limit `gorm:"column:rate_limit;type:int" json:"rate_limit"` +} diff --git a/rpc_server/middlewares/auth.go b/rpc_server/middlewares/auth.go index 9b6c8982..40ccf278 100644 --- a/rpc_server/middlewares/auth.go +++ b/rpc_server/middlewares/auth.go @@ -2,6 +2,7 @@ package middlewares import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/envirment" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" jwt "github.com/appleboy/gin-jwt/v2" @@ -41,12 +42,15 @@ func AuthHandler() gin.HandlerFunc { if err := c.ShouldBind(&apiKey); err != nil { return "", jwt.ErrMissingLoginValues } - // TODO check APIKey is UseFul - + apiModel, err := dashboard_service.GetAPiInfoByApiKey(apiKey.Key) + if err != nil { + return "", err + } + err = CheckAPIKeyAvailable(apiModel) + if err != nil { + return "", err + } return apiKey.Key, nil - - // if incorrect - //return nil, jwt.ErrFailedAuthentication }, //every Request will be checked Authorizator: func(data interface{}, c *gin.Context) bool { @@ -99,7 +103,7 @@ func AuthHandler() gin.HandlerFunc { return m.MiddlewareFunc() } -func CheckAPIKeyAvailable(apiModel *dashboard_service.ApiKeyModel) error { +func CheckAPIKeyAvailable(apiModel *model.ApiKeyModel) error { if apiModel.Disable { return xerrors.Errorf("API Key is disabled") } diff --git a/rpc_server/middlewares/rate_limit.go b/rpc_server/middlewares/rate_limit.go index 853340d2..b8f1c4ad 100644 --- a/rpc_server/middlewares/rate_limit.go +++ b/rpc_server/middlewares/rate_limit.go @@ -2,8 +2,8 @@ package middlewares import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/rpc_server/api/utils" - "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" "errors" "github.com/gin-gonic/gin" "golang.org/x/time/rate" @@ -24,7 +24,7 @@ func RateLimiterByApiKeyHandler() gin.HandlerFunc { apiKeyModel, _ := ctx.Get(global_const.ContextKeyApiMoDel) defaultLimit := DefaultLimit if apiKeyModel != nil { - defaultLimit = apiKeyModel.(*dashboard_service.ApiKeyModel).GetRateLimit() + defaultLimit = apiKeyModel.(*model.ApiKeyModel).RateLimit } if limiting(¤t, defaultLimit) { ctx.Next() diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index cc24abad..9575cd2c 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -135,28 +135,36 @@ func IsPayMasterSupport(address string, chain global_const.Network) bool { return supportPayMasterSet.Contains(address) } -type ApiKeyModel struct { +type ApiKeyDbModel struct { Disable bool `gorm:"column:disable;type:bool" json:"disable"` ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"` KeyName string `gorm:"column:key_name;type:varchar(255)" json:"key_name"` Extra datatypes.JSON `gorm:"column:extra" json:"extra"` } -func (*ApiKeyModel) TableName() string { +func (*ApiKeyDbModel) TableName() string { return config.GetAPIKeyTableName() } -func (m *ApiKeyModel) GetRateLimit() rate.Limit { +func (m *ApiKeyDbModel) GetRateLimit() rate.Limit { return 10 } -func GetAPiInfoByApiKey(apiKey string) (apikeyModel *ApiKeyModel, err error) { - apikeyModel = &ApiKeyModel{} +func convertApiKeyDbModelToApiKeyModel(apiKeyDbModel *ApiKeyDbModel) *model.ApiKeyModel { + return &model.ApiKeyModel{ + Disable: apiKeyDbModel.Disable, + ApiKey: apiKeyDbModel.ApiKey, + RateLimit: 10, + } +} +func GetAPiInfoByApiKey(apiKey string) (*model.ApiKeyModel, error) { + apikeyModel := &ApiKeyDbModel{} tx := configDB.Where("api_key = ?", apiKey).First(&apikeyModel) if tx.Error != nil { if errors.Is(tx.Error, gorm.ErrRecordNotFound) { return nil, tx.Error } - return apikeyModel, xerrors.Errorf("error when finding apikey: %w", tx.Error) + return nil, xerrors.Errorf("error when finding apikey: %w", tx.Error) } - return apikeyModel, nil + apikeyRes := convertApiKeyDbModelToApiKeyModel(apikeyModel) + return apikeyRes, nil } From f863ebf506b63fd1f771c5873bf60c29b6457b52 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 20 May 2024 17:36:54 +0800 Subject: [PATCH 04/23] Strategy Restriction --- common/model/api_request.go | 6 +- common/model/strategy.go | 29 +++-- config/basic_config.go | 12 +- config/basic_strategy_config.go | 6 +- rpc_server/api/v1/paymaster.go | 6 +- .../dashboard_service/dashboard_service.go | 107 +++++++++++++++--- .../dashboard_service_test.go | 50 +++++++- service/operator/operator_test.go | 26 ++--- service/operator/try_pay_user_op_execute.go | 12 +- service/validator_service/basic_validator.go | 27 ++++- 10 files changed, 215 insertions(+), 66 deletions(-) diff --git a/common/model/api_request.go b/common/model/api_request.go index 5f789c35..e983d19c 100644 --- a/common/model/api_request.go +++ b/common/model/api_request.go @@ -5,9 +5,9 @@ import ( ) type UserOpRequest struct { - ForceStrategyId string `json:"force_strategy_id"` - Network global_const.Network `json:"force_network"` - Erc20Token global_const.TokenType `json:"force_token"` + StrategyCode string `json:"strategy_code"` + Network global_const.Network `json:"network"` + UserPayErc20Token global_const.TokenType `json:"user_pay_erc20_token"` UserOp map[string]any `json:"user_operation"` Extra interface{} `json:"extra"` EstimateOpGas bool `json:"estimate_op_gas"` diff --git a/common/model/strategy.go b/common/model/strategy.go index 309329dd..37633226 100644 --- a/common/model/strategy.go +++ b/common/model/strategy.go @@ -8,13 +8,13 @@ import ( ) type Strategy struct { - Id string `json:"id"` - StrategyCode string `json:"strategy_code"` - PaymasterInfo *PaymasterInfo `json:"paymaster_info"` - NetWorkInfo *NetWorkInfo `json:"network_info"` - EntryPointInfo *EntryPointInfo `json:"entrypoint_info"` - Description string `json:"description"` - ExecuteRestriction StrategyExecuteRestriction `json:"execute_restriction"` + Id string `json:"id"` + StrategyCode string `json:"strategy_code"` + PaymasterInfo *PaymasterInfo `json:"paymaster_info"` + NetWorkInfo *NetWorkInfo `json:"network_info"` + EntryPointInfo *EntryPointInfo `json:"entrypoint_info"` + Description string `json:"description"` + ExecuteRestriction *StrategyExecuteRestriction `json:"execute_restriction"` Erc20TokenType global_const.TokenType } @@ -56,16 +56,15 @@ func (strategy *Strategy) IsCurrencyPayEnable() bool { } type StrategyExecuteRestriction struct { - BanSenderAddress string `json:"ban_sender_address"` - EffectiveStartTime *big.Int `json:"effective_start_time"` - EffectiveEndTime *big.Int `json:"effective_end_time"` - GlobalMaxUSD int64 `json:"global_max_usd"` - GlobalMaxOpCount int64 `json:"global_max_op_count"` - DayMaxUSD int64 `json:"day_max_usd"` - StartTime int64 `json:"start_time"` - EndTime int64 `json:"end_time"` + BanSenderAddress mapset.Set[string] `json:"ban_sender_address"` + EffectiveStartTime *big.Int `json:"start_time"` + EffectiveEndTime *big.Int `json:"end_time"` + GlobalMaxUSD *big.Int `json:"global_max_usd"` + GlobalMaxOpCount *big.Int `json:"global_max_op_count"` + DayMaxUSD *big.Int `json:"day_max_usd"` AccessProject mapset.Set[string] `json:"access_project"` AccessErc20 mapset.Set[string] `json:"access_erc20"` + ChainIdWhiteList mapset.Set[string] `json:"chain_id_whitelist"` } type StrategyValidateConfig struct { diff --git a/config/basic_config.go b/config/basic_config.go index 6f4dfcbe..c4c5d520 100644 --- a/config/basic_config.go +++ b/config/basic_config.go @@ -133,20 +133,20 @@ func GetChainId(networkParam global_const.Network) string { return networkConfig.ChainId } -func GetPaymasterAddress(network global_const.Network, version global_const.EntrypointVersion) common.Address { +func GetPaymasterAddress(network global_const.Network, version global_const.EntrypointVersion) *common.Address { networkConfig := basicConfig.NetworkConfigMap[network] if version == global_const.EntrypointV07 { - return networkConfig.V07PaymasterAddress + return &networkConfig.V07PaymasterAddress } - return networkConfig.V06PaymasterAddress + return &networkConfig.V06PaymasterAddress } -func GetEntrypointAddress(network global_const.Network, version global_const.EntrypointVersion) common.Address { +func GetEntrypointAddress(network global_const.Network, version global_const.EntrypointVersion) *common.Address { networkConfig := basicConfig.NetworkConfigMap[network] if version == global_const.EntrypointV07 { - return networkConfig.V07EntryPointAddress + return &networkConfig.V07EntryPointAddress } - return networkConfig.V06EntryPointAddress + return &networkConfig.V06EntryPointAddress } diff --git a/config/basic_strategy_config.go b/config/basic_strategy_config.go index cd4debba..8b5a2dbf 100644 --- a/config/basic_strategy_config.go +++ b/config/basic_strategy_config.go @@ -19,9 +19,9 @@ var suitableStrategyMap = make(map[global_const.Network]map[global_const.Entrypo func GetBasicStrategyConfig(strategyCode global_const.BasicStrategyCode) *model.Strategy { strategy := basicStrategyConfig[string(strategyCode)] paymasterAddress := GetPaymasterAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) - strategy.PaymasterInfo.PayMasterAddress = &paymasterAddress + strategy.PaymasterInfo.PayMasterAddress = paymasterAddress entryPointAddress := GetEntrypointAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) - strategy.EntryPointInfo.EntryPointAddress = &entryPointAddress + strategy.EntryPointInfo.EntryPointAddress = entryPointAddress return strategy } @@ -79,7 +79,7 @@ func convertMapToStrategyConfig(data map[string]map[string]any) (map[string]*mod EntryPointVersion: global_const.EntrypointVersion(value["entrypoint_version"].(string)), }, - ExecuteRestriction: model.StrategyExecuteRestriction{ + ExecuteRestriction: &model.StrategyExecuteRestriction{ EffectiveStartTime: effectiveStartTime, EffectiveEndTime: effectiveEndTime, AccessProject: utils.ConvertStringToSet(accessProjectStr, ","), diff --git a/rpc_server/api/v1/paymaster.go b/rpc_server/api/v1/paymaster.go index 3824c85c..d7a1d86a 100644 --- a/rpc_server/api/v1/paymaster.go +++ b/rpc_server/api/v1/paymaster.go @@ -165,13 +165,13 @@ func parseTryPayUserOperationParams(params []interface{}) (*model.UserOpRequest, } extra := extraParam.(map[string]any) if extra["strategy_code"] != nil { - result.ForceStrategyId = extra["strategy_code"].(string) + result.StrategyCode = extra["strategy_code"].(string) } if extra["network"] != nil { result.Network = extra["network"].(global_const.Network) } if extra["token"] != nil { - result.Erc20Token = extra["token"].(global_const.TokenType) + result.UserPayErc20Token = extra["token"].(global_const.TokenType) } if extra["version"] != nil { result.EntryPointVersion = extra["version"].(global_const.EntrypointVersion) @@ -180,7 +180,7 @@ func parseTryPayUserOperationParams(params []interface{}) (*model.UserOpRequest, } func validateUserOpRequest(request *model.UserOpRequest) error { - if request.ForceStrategyId != "" { + if request.StrategyCode != "" { return nil } if request.Network == "" { diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 9575cd2c..1ef1497c 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -4,12 +4,15 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/config" + "encoding/json" "errors" + mapset "github.com/deckarep/golang-set/v2" "golang.org/x/time/rate" "golang.org/x/xerrors" "gorm.io/datatypes" "gorm.io/driver/postgres" "gorm.io/gorm" + "math/big" "sync" ) @@ -55,27 +58,105 @@ func (StrategyDBModel) TableName() string { } // GetStrategyByCode is Sponsor Type , need GasTank -func GetStrategyByCode(strategyCode string, entryPointVersion global_const.EntrypointVersion, chain global_const.Network) (*model.Strategy, error) { - +func GetStrategyByCode(strategyCode string, entryPointVersion global_const.EntrypointVersion, network global_const.Network) (*model.Strategy, error) { + if entryPointVersion == "" { + entryPointVersion = global_const.EntrypointV06 + } strategyDbModel := &StrategyDBModel{} tx := configDB.Where("strategy_code = ?", strategyCode).First(&strategyDbModel) if tx.Error != nil { - return nil, tx.Error + if errors.Is(tx.Error, gorm.ErrRecordNotFound) { + return nil, xerrors.Errorf("strategy not found: %w", tx.Error) + } else { + return nil, xerrors.Errorf("error when finding strategy: %w", tx.Error) + } } - - strategy, err := convertStrategyDBModelToStrategy(strategyDbModel) + strategy, err := convertStrategyDBModelToStrategy(strategyDbModel, entryPointVersion, network) if err != nil { return nil, err } - paymasterAddress := config.GetPaymasterAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) - strategy.PaymasterInfo.PayMasterAddress = &paymasterAddress - entryPointAddress := config.GetEntrypointAddress(strategy.GetNewWork(), strategy.GetStrategyEntrypointVersion()) - strategy.EntryPointInfo.EntryPointAddress = &entryPointAddress + return strategy, nil } -func convertStrategyDBModelToStrategy(strategyDBModel *StrategyDBModel) (*model.Strategy, error) { - return &model.Strategy{}, nil +func convertStrategyDBModelToStrategy(strategyDBModel *StrategyDBModel, entryPointVersion global_const.EntrypointVersion, network global_const.Network) (*model.Strategy, error) { + entryPointAddress := config.GetEntrypointAddress(network, entryPointVersion) + + if entryPointAddress == nil { + return nil, errors.New("entryPointAddress not found") + } + paymasterAddress := config.GetPaymasterAddress(network, entryPointVersion) + if paymasterAddress == nil { + return nil, errors.New("paymasterAddress not found") + } + strategyExecuteRestrictionJson := StrategyExecuteRestrictionJson{} + if strategyDBModel.ExecuteRestriction != nil { + eJson, _ := strategyDBModel.ExecuteRestriction.MarshalJSON() + err := json.Unmarshal(eJson, &strategyExecuteRestrictionJson) + if err != nil { + return nil, xerrors.Errorf("error when unmarshal strategyExecuteRestriction: %w", err) + } + + if err != nil { + return nil, xerrors.Errorf("error when unmarshal strategyExecuteRestriction: %w", err) + } + } + strategyExecuteRestriction := &model.StrategyExecuteRestriction{ + EffectiveStartTime: big.NewInt(strategyExecuteRestrictionJson.EffectiveStartTime), + EffectiveEndTime: big.NewInt(strategyExecuteRestrictionJson.EffectiveEndTime), + GlobalMaxUSD: big.NewInt(strategyExecuteRestrictionJson.GlobalMaxUSD), + GlobalMaxOpCount: big.NewInt(strategyExecuteRestrictionJson.GlobalMaxOpCount), + DayMaxUSD: big.NewInt(strategyExecuteRestrictionJson.DayMaxUSD), + } + if strategyExecuteRestrictionJson.BanSenderAddress != nil { + strategyExecuteRestriction.BanSenderAddress = mapset.NewSetWithSize[string](len(strategyExecuteRestrictionJson.BanSenderAddress)) + for _, v := range strategyExecuteRestrictionJson.BanSenderAddress { + strategyExecuteRestriction.BanSenderAddress.Add(v) + } + } + if strategyExecuteRestrictionJson.AccessProject != nil { + strategyExecuteRestriction.AccessProject = mapset.NewSetWithSize[string](len(strategyExecuteRestrictionJson.AccessProject)) + for _, v := range strategyExecuteRestrictionJson.AccessProject { + strategyExecuteRestriction.AccessProject.Add(v) + } + } + if strategyExecuteRestrictionJson.ChainIdWhiteList != nil { + strategyExecuteRestriction.ChainIdWhiteList = mapset.NewSetWithSize[string](len(strategyExecuteRestrictionJson.ChainIdWhiteList)) + for _, v := range strategyExecuteRestrictionJson.ChainIdWhiteList { + strategyExecuteRestriction.ChainIdWhiteList.Add(v) + } + } + + return &model.Strategy{ + StrategyCode: strategyDBModel.StrategyCode, + Description: strategyDBModel.Description, + NetWorkInfo: &model.NetWorkInfo{ + NetWork: network, + GasToken: config.GetGasToken(network), + }, + EntryPointInfo: &model.EntryPointInfo{ + EntryPointVersion: entryPointVersion, + EntryPointAddress: config.GetEntrypointAddress(network, entryPointVersion), + }, + PaymasterInfo: &model.PaymasterInfo{ + PayMasterAddress: config.GetPaymasterAddress(network, entryPointVersion), + PayType: global_const.PayTypeVerifying, + IsProjectErc20PayEnable: false, + }, + ExecuteRestriction: strategyExecuteRestriction, + }, nil +} + +type StrategyExecuteRestrictionJson struct { + BanSenderAddress []string `json:"ban_sender_address"` + EffectiveStartTime int64 `json:"start_time"` + EffectiveEndTime int64 `json:"end_time"` + GlobalMaxUSD int64 `json:"global_max_usd"` + GlobalMaxOpCount int64 `json:"global_max_op_count"` + DayMaxUSD int64 `json:"day_max_usd"` + AccessProject []string `json:"access_project"` + AccessErc20 []string `json:"access_erc20"` + ChainIdWhiteList []string `json:"chain_id_whitelist"` } // GetSuitableStrategy get suitable strategy by entryPointVersion, chain, @@ -104,10 +185,10 @@ func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain }, EntryPointInfo: &model.EntryPointInfo{ EntryPointVersion: entryPointVersion, - EntryPointAddress: &entryPointAddress, + EntryPointAddress: entryPointAddress, }, PaymasterInfo: &model.PaymasterInfo{ - PayMasterAddress: &paymasterAddress, + PayMasterAddress: paymasterAddress, PayType: payType, IsProjectErc20PayEnable: isPerc20Enable, }, diff --git a/service/dashboard_service/dashboard_service_test.go b/service/dashboard_service/dashboard_service_test.go index 8bdb5ee5..19f72b35 100644 --- a/service/dashboard_service/dashboard_service_test.go +++ b/service/dashboard_service/dashboard_service_test.go @@ -2,11 +2,53 @@ package dashboard_service import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" - "fmt" + "AAStarCommunity/EthPaymaster_BackService/config" + "encoding/json" "testing" ) -func TestGetSuitableStrategy(t *testing.T) { - x := global_const.Network("Ethereum") - fmt.Println(x) +func TestDashBoardService(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + //t.Run("TestGetSuitableStrategy", TestGetSuitableStrategy) + config.InitConfig("../../config/basic_strategy_config.json", "../../config/basic_config.json", "../../config/secret_config.json") + Init() + tests := []struct { + name string + test func(t *testing.T) + }{ + { + "TestGetSuitableStrategy", + func(t *testing.T) { + testGetStrategyByCode(t) + }, + }, + { + "TestGetSuitableStrategy", + func(t *testing.T) { + testGetSuitableStrategy(t) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, tt.test) + } +} +func testGetSuitableStrategy(t *testing.T) { + strategy, err := GetSuitableStrategy("", global_const.EthereumSepolia, global_const.TokenTypeOP) + if err != nil { + t.Error(err) + } + jsonByte, _ := json.Marshal(strategy) + t.Logf("Strategy: %s", string(jsonByte)) +} +func testGetStrategyByCode(t *testing.T) { + strategy, err := GetStrategyByCode("demo_with_white_list_6bd-4dec-b8e7-a224cdd5a965_YF4tWsoJir", "", global_const.ArbitrumSpeolia) + if err != nil { + t.Error(err) + } + jsonByte, _ := json.Marshal(strategy) + + t.Logf("Strategy: %s", string(jsonByte)) } diff --git a/service/operator/operator_test.go b/service/operator/operator_test.go index 195c45a8..a7dbdadc 100644 --- a/service/operator/operator_test.go +++ b/service/operator/operator_test.go @@ -49,7 +49,7 @@ func TestOperator(t *testing.T) { { "Test_ScrollSepoliaV06Verify_TryPayUserOpExecute", func(t *testing.T) { - mockRequestNotSupport1559.ForceStrategyId = string(global_const.StrategyCodeScrollSepoliaV06Verify) + mockRequestNotSupport1559.StrategyCode = string(global_const.StrategyCodeScrollSepoliaV06Verify) mockRequest := getMockTryPayUserOpRequest() testTryPayUserOpExecute(t, mockRequest) @@ -60,7 +60,7 @@ func TestOperator(t *testing.T) { func(t *testing.T) { mockRequest := getMockTryPayUserOpRequest() - mockRequest.ForceStrategyId = string(global_const.StrategyCodeEthereumSepoliaV06Verify) + mockRequest.StrategyCode = string(global_const.StrategyCodeEthereumSepoliaV06Verify) testTryPayUserOpExecute(t, mockRequest) }, @@ -70,7 +70,7 @@ func TestOperator(t *testing.T) { func(t *testing.T) { mockRequest := getMockTryPayUserOpRequest() - mockRequest.ForceStrategyId = string(global_const.StrategyCodeOptimismSepoliaV06Verify) + mockRequest.StrategyCode = string(global_const.StrategyCodeOptimismSepoliaV06Verify) testTryPayUserOpExecute(t, mockRequest) }, @@ -80,7 +80,7 @@ func TestOperator(t *testing.T) { func(t *testing.T) { mockRequest := getMockTryPayUserOpRequest() - mockRequest.ForceStrategyId = string(global_const.StrategyCodeArbitrumSepoliaV06Verify) + mockRequest.StrategyCode = string(global_const.StrategyCodeArbitrumSepoliaV06Verify) testTryPayUserOpExecute(t, mockRequest) }, @@ -89,7 +89,7 @@ func TestOperator(t *testing.T) { "Test_BaseSepoliaV06Verify_TryPayUserOpExecute", func(t *testing.T) { mockRequest := getMockTryPayUserOpRequest() - mockRequest.ForceStrategyId = string(global_const.StrategyCodeArbitrumSepoliaV06Verify) + mockRequest.StrategyCode = string(global_const.StrategyCodeArbitrumSepoliaV06Verify) testTryPayUserOpExecute(t, mockRequest) }, @@ -99,8 +99,8 @@ func TestOperator(t *testing.T) { func(t *testing.T) { mockRequest := getMockTryPayUserOpRequest() - mockRequest.Erc20Token = global_const.TokenTypeUSDT - mockRequest.ForceStrategyId = string(global_const.StrategyCodeEthereumSepoliaV06Erc20) + mockRequest.UserPayErc20Token = global_const.TokenTypeUSDT + mockRequest.StrategyCode = string(global_const.StrategyCodeEthereumSepoliaV06Erc20) testTryPayUserOpExecute(t, mockRequest) }, }, @@ -109,8 +109,8 @@ func TestOperator(t *testing.T) { func(t *testing.T) { mockRequest := getMockTryPayUserOpRequest() - mockRequest.Erc20Token = global_const.TokenTypeUSDT - mockRequest.ForceStrategyId = string(global_const.StrategyCodeOptimismSepoliaV06Erc20) + mockRequest.UserPayErc20Token = global_const.TokenTypeUSDT + mockRequest.StrategyCode = string(global_const.StrategyCodeOptimismSepoliaV06Erc20) testTryPayUserOpExecute(t, mockRequest) }, }, @@ -118,8 +118,8 @@ func TestOperator(t *testing.T) { "Test_ArbSepoliaV06Erc20_TryPayUserOpExecute", func(t *testing.T) { mockRequest := getMockTryPayUserOpRequest() - mockRequest.Erc20Token = global_const.TokenTypeUSDT - mockRequest.ForceStrategyId = string(global_const.StrategyCodeArbitrumSepoliaV06Erc20) + mockRequest.UserPayErc20Token = global_const.TokenTypeUSDT + mockRequest.StrategyCode = string(global_const.StrategyCodeArbitrumSepoliaV06Erc20) testTryPayUserOpExecute(t, mockRequest) }, }, @@ -209,7 +209,7 @@ func testTryPayUserOpExecute(t *testing.T, request *model.UserOpRequest) { func getMockTryPayUserOpRequest() *model.UserOpRequest { return &model.UserOpRequest{ - ForceStrategyId: "Ethereum_Sepolia_v06_verifyPaymaster", - UserOp: *utils.GenerateMockUservOperation(), + StrategyCode: "Ethereum_Sepolia_v06_verifyPaymaster", + UserOp: *utils.GenerateMockUservOperation(), } } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 565890ac..e8fbc539 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -49,13 +49,15 @@ func prepareExecute(request *model.UserOpRequest) (*user_op.UserOpInput, *model. return nil, nil, nil, generateErr } - userOp, err := user_op.NewUserOp(&request.UserOp) - if err != nil { + if err := validator_service.ValidateStrategy(strategy, request); err != nil { return nil, nil, nil, err } - if err := validator_service.ValidateStrategy(strategy); err != nil { + + userOp, err := user_op.NewUserOp(&request.UserOp) + if err != nil { return nil, nil, nil, err } + if err := validator_service.ValidateUserOp(userOp, strategy); err != nil { return nil, nil, nil, err } @@ -140,7 +142,7 @@ func postExecute(userOp *user_op.UserOpInput, strategy *model.Strategy, gasRespo func StrategyGenerate(request *model.UserOpRequest) (*model.Strategy, error) { var strategyResult *model.Strategy - if forceStrategyId := request.ForceStrategyId; forceStrategyId != "" { + if forceStrategyId := request.StrategyCode; forceStrategyId != "" { //force strategy strategy, err := dashboard_service.GetStrategyByCode(forceStrategyId, request.EntryPointVersion, request.Network) if err != nil { @@ -152,7 +154,7 @@ func StrategyGenerate(request *model.UserOpRequest) (*model.Strategy, error) { strategyResult = strategy } else { - suitableStrategy, err := dashboard_service.GetSuitableStrategy(request.EntryPointVersion, request.Network, request.Erc20Token) //TODO + suitableStrategy, err := dashboard_service.GetSuitableStrategy(request.EntryPointVersion, request.Network, request.UserPayErc20Token) if err != nil { return nil, err } diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index 3240355d..0443c301 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -7,9 +7,10 @@ import ( "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" + "time" ) -func ValidateStrategy(strategy *model.Strategy) error { +func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) error { if strategy == nil { return xerrors.Errorf("empty strategy") } @@ -26,6 +27,24 @@ func ValidateStrategy(strategy *model.Strategy) error { if err != nil { return err } + curTime := time.Now().Unix() + //check Time + if strategy.ExecuteRestriction.EffectiveStartTime != nil { + if curTime < strategy.ExecuteRestriction.EffectiveStartTime.Int64() { + return xerrors.Errorf("strategy is not effective") + } + } + if strategy.ExecuteRestriction.EffectiveEndTime != nil { + if curTime > strategy.ExecuteRestriction.EffectiveEndTime.Int64() { + return xerrors.Errorf("strategy is expired") + } + } + if strategy.ExecuteRestriction.AccessErc20 != nil && request.UserPayErc20Token != "" { + if !strategy.ExecuteRestriction.AccessErc20.Contains(string(request.UserPayErc20Token)) { + return xerrors.Errorf("strategy not support erc20 token") + } + } + return nil } @@ -37,6 +56,12 @@ func ValidateUserOp(userOpParam *user_op.UserOpInput, strategy *model.Strategy) if !userOpValue.Nonce.IsInt64() { return xerrors.Errorf("nonce is not in uint64 range") } + if strategy.ExecuteRestriction.BanSenderAddress != nil { + if strategy.ExecuteRestriction.BanSenderAddress.Contains(userOpValue.Sender.String()) { + return xerrors.Errorf("sender is banned") + + } + } //If initCode is not empty, parse its first 20 bytes as a factory address. Record whether the factory is staked, in case the later simulation indicates that it needs to be. If the factory accesses global state, it must be staked - see reputation, throttling and banning section for details. //The verificationGasLimit is sufficiently low (<= MAX_VERIFICATION_GAS) and the preVerificationGas is sufficiently high (enough to pay for the calldata gas cost of serializing the UserOperationV06 plus PRE_VERIFICATION_OVERHEAD_GAS) return nil From 4f6cae7c2d989d93818edb9848dd228f1e71f1dd Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 11:24:22 +0800 Subject: [PATCH 05/23] Strategy Restriction --- common/model/strategy.go | 8 ++-- .../dashboard_service/dashboard_service.go | 13 ++++-- service/validator_service/basic_validator.go | 41 ++++++++++++++++++- service/validator_service/validator_test.go | 1 + 4 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 service/validator_service/validator_test.go diff --git a/common/model/strategy.go b/common/model/strategy.go index 37633226..92aaa487 100644 --- a/common/model/strategy.go +++ b/common/model/strategy.go @@ -15,8 +15,7 @@ type Strategy struct { EntryPointInfo *EntryPointInfo `json:"entrypoint_info"` Description string `json:"description"` ExecuteRestriction *StrategyExecuteRestriction `json:"execute_restriction"` - - Erc20TokenType global_const.TokenType + Erc20TokenType global_const.TokenType } type PaymasterInfo struct { PayMasterAddress *common.Address `json:"paymaster_address"` @@ -59,12 +58,13 @@ type StrategyExecuteRestriction struct { BanSenderAddress mapset.Set[string] `json:"ban_sender_address"` EffectiveStartTime *big.Int `json:"start_time"` EffectiveEndTime *big.Int `json:"end_time"` - GlobalMaxUSD *big.Int `json:"global_max_usd"` + GlobalMaxUSD *big.Float `json:"global_max_usd"` GlobalMaxOpCount *big.Int `json:"global_max_op_count"` - DayMaxUSD *big.Int `json:"day_max_usd"` + DayMaxUSD *big.Float `json:"day_max_usd"` AccessProject mapset.Set[string] `json:"access_project"` AccessErc20 mapset.Set[string] `json:"access_erc20"` ChainIdWhiteList mapset.Set[string] `json:"chain_id_whitelist"` + Status global_const.StrategyStatus } type StrategyValidateConfig struct { diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 1ef1497c..196a7bc3 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -89,6 +89,10 @@ func convertStrategyDBModelToStrategy(strategyDBModel *StrategyDBModel, entryPoi if paymasterAddress == nil { return nil, errors.New("paymasterAddress not found") } + + if strategyDBModel.Status == "" { + strategyDBModel.Status = global_const.StrategyStatusDisable + } strategyExecuteRestrictionJson := StrategyExecuteRestrictionJson{} if strategyDBModel.ExecuteRestriction != nil { eJson, _ := strategyDBModel.ExecuteRestriction.MarshalJSON() @@ -104,9 +108,10 @@ func convertStrategyDBModelToStrategy(strategyDBModel *StrategyDBModel, entryPoi strategyExecuteRestriction := &model.StrategyExecuteRestriction{ EffectiveStartTime: big.NewInt(strategyExecuteRestrictionJson.EffectiveStartTime), EffectiveEndTime: big.NewInt(strategyExecuteRestrictionJson.EffectiveEndTime), - GlobalMaxUSD: big.NewInt(strategyExecuteRestrictionJson.GlobalMaxUSD), + GlobalMaxUSD: big.NewFloat(strategyExecuteRestrictionJson.GlobalMaxUSD), GlobalMaxOpCount: big.NewInt(strategyExecuteRestrictionJson.GlobalMaxOpCount), - DayMaxUSD: big.NewInt(strategyExecuteRestrictionJson.DayMaxUSD), + DayMaxUSD: big.NewFloat(strategyExecuteRestrictionJson.DayMaxUSD), + Status: strategyDBModel.Status, } if strategyExecuteRestrictionJson.BanSenderAddress != nil { strategyExecuteRestriction.BanSenderAddress = mapset.NewSetWithSize[string](len(strategyExecuteRestrictionJson.BanSenderAddress)) @@ -151,9 +156,9 @@ type StrategyExecuteRestrictionJson struct { BanSenderAddress []string `json:"ban_sender_address"` EffectiveStartTime int64 `json:"start_time"` EffectiveEndTime int64 `json:"end_time"` - GlobalMaxUSD int64 `json:"global_max_usd"` + GlobalMaxUSD float64 `json:"global_max_usd"` GlobalMaxOpCount int64 `json:"global_max_op_count"` - DayMaxUSD int64 `json:"day_max_usd"` + DayMaxUSD float64 `json:"day_max_usd"` AccessProject []string `json:"access_project"` AccessErc20 []string `json:"access_erc20"` ChainIdWhiteList []string `json:"chain_id_whitelist"` diff --git a/service/validator_service/basic_validator.go b/service/validator_service/basic_validator.go index 0443c301..578b7457 100644 --- a/service/validator_service/basic_validator.go +++ b/service/validator_service/basic_validator.go @@ -7,6 +7,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/service/chain_service" "github.com/ethereum/go-ethereum/common" "golang.org/x/xerrors" + "math/big" "time" ) @@ -17,6 +18,7 @@ func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) er if strategy.GetNewWork() == "" { return xerrors.Errorf("empty strategy network") } + // check Paymaster _, err := chain_service.CheckContractAddressAccess(strategy.GetPaymasterAddress(), strategy.GetNewWork()) if err != nil { @@ -27,16 +29,23 @@ func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) er if err != nil { return err } + + if strategy.ExecuteRestriction == nil { + return nil + } + if strategy.ExecuteRestriction.Status != global_const.StrategyStatusAchieve { + return xerrors.Errorf("strategy status is not active") + } curTime := time.Now().Unix() //check Time if strategy.ExecuteRestriction.EffectiveStartTime != nil { if curTime < strategy.ExecuteRestriction.EffectiveStartTime.Int64() { - return xerrors.Errorf("strategy is not effective") + return xerrors.Errorf("curTime [%s] is OutOff EffectiveStartTime [%s]", curTime, strategy.ExecuteRestriction.EffectiveStartTime.Int64()) } } if strategy.ExecuteRestriction.EffectiveEndTime != nil { if curTime > strategy.ExecuteRestriction.EffectiveEndTime.Int64() { - return xerrors.Errorf("strategy is expired") + return xerrors.Errorf("curTime [%s] is OutOff EffectiveEndTime [%s]", curTime, strategy.ExecuteRestriction.EffectiveEndTime.Int64()) } } if strategy.ExecuteRestriction.AccessErc20 != nil && request.UserPayErc20Token != "" { @@ -44,8 +53,36 @@ func ValidateStrategy(strategy *model.Strategy, request *model.UserOpRequest) er return xerrors.Errorf("strategy not support erc20 token") } } + if strategy.ExecuteRestriction.GlobalMaxUSD != nil || strategy.ExecuteRestriction.GlobalMaxUSD.Sign() != 0 { + curGlobalUse, err := GetStrategyGlobalUse(strategy) + if err != nil { + return err + } + if strategy.ExecuteRestriction.GlobalMaxUSD.Cmp(curGlobalUse) < 0 { + return xerrors.Errorf("strategy global max usd use out of limit") + } + } + if strategy.ExecuteRestriction.DayMaxUSD != nil || strategy.ExecuteRestriction.DayMaxUSD.Sign() != 0 { + curDayUse, err := GetStrategyDayUse(strategy) + if err != nil { + return err + } + if strategy.ExecuteRestriction.DayMaxUSD.Cmp(curDayUse) < 0 { + return xerrors.Errorf("strategy day max usd use out of limit") + } + } return nil + +} + +func GetStrategyDayUse(strategy *model.Strategy) (*big.Float, error) { + //TODO + return big.NewFloat(0), nil +} +func GetStrategyGlobalUse(strategy *model.Strategy) (*big.Float, error) { + //TODO + return big.NewFloat(0), nil } func ValidateUserOp(userOpParam *user_op.UserOpInput, strategy *model.Strategy) error { diff --git a/service/validator_service/validator_test.go b/service/validator_service/validator_test.go new file mode 100644 index 00000000..cb6263b0 --- /dev/null +++ b/service/validator_service/validator_test.go @@ -0,0 +1 @@ +package validator_service From 1d82fee97ec269ccf2f657d72f293695e123b799 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 11:50:02 +0800 Subject: [PATCH 06/23] Strategy Restriction --- common/global_const/common_const.go | 2 +- .../dashboard_service_test.go | 2 +- service/validator_service/validator_test.go | 51 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/common/global_const/common_const.go b/common/global_const/common_const.go index 258e1967..fb5b7675 100644 --- a/common/global_const/common_const.go +++ b/common/global_const/common_const.go @@ -22,7 +22,7 @@ const ( ContextKeyApiMoDel = "api_model" StrategyStatusDisable StrategyStatus = "disable" - StrategyStatusAchieve StrategyStatus = "achieve" + StrategyStatusAchieve StrategyStatus = "enable" ) var ( diff --git a/service/dashboard_service/dashboard_service_test.go b/service/dashboard_service/dashboard_service_test.go index 19f72b35..0e47bfd6 100644 --- a/service/dashboard_service/dashboard_service_test.go +++ b/service/dashboard_service/dashboard_service_test.go @@ -44,7 +44,7 @@ func testGetSuitableStrategy(t *testing.T) { t.Logf("Strategy: %s", string(jsonByte)) } func testGetStrategyByCode(t *testing.T) { - strategy, err := GetStrategyByCode("demo_with_white_list_6bd-4dec-b8e7-a224cdd5a965_YF4tWsoJir", "", global_const.ArbitrumSpeolia) + strategy, err := GetStrategyByCode("basic_arb_strategy__vHUZk", "", global_const.ArbitrumSpeolia) if err != nil { t.Error(err) } diff --git a/service/validator_service/validator_test.go b/service/validator_service/validator_test.go index cb6263b0..b619c8d2 100644 --- a/service/validator_service/validator_test.go +++ b/service/validator_service/validator_test.go @@ -1 +1,52 @@ package validator_service + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/utils" + "AAStarCommunity/EthPaymaster_BackService/config" + "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" + "testing" +) + +func TestValidatorService(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + config.InitConfig("../../config/basic_strategy_config.json", "../../config/basic_config.json", "../../config/secret_config.json") + dashboard_service.Init() + strategyCode := "basic_arb_strategy__vHUZk" + strategy, err := dashboard_service.GetStrategyByCode(strategyCode, "", global_const.ArbitrumSpeolia) + request := getMockTryPayUserOpRequest(strategyCode, global_const.ArbitrumSpeolia) + if err != nil { + t.Fatalf("GetStrategyByCode error: %v", err) + } + tests := []struct { + name string + test func(t *testing.T) + }{ + { + "TestValidateStrategy", + func(t *testing.T) { + testValidateStrategy(t, strategy, request) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, tt.test) + } +} + +func testValidateStrategy(t *testing.T, strategy *model.Strategy, request *model.UserOpRequest) { + if err := ValidateStrategy(strategy, request); err != nil { + t.Fatalf("ValidateStrategy error: %v", err) + } +} + +func getMockTryPayUserOpRequest(strategyCode string, network global_const.Network) *model.UserOpRequest { + return &model.UserOpRequest{ + StrategyCode: strategyCode, + Network: network, + UserOp: *utils.GenerateMockUservOperation(), + } +} From 1e8de6f7dd3ad565198360c090a3ddcbfcbff433 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 12:04:02 +0800 Subject: [PATCH 07/23] mod init add DeleteAt --- docs/swagger.json | 6 +- go.mod | 20 ++---- go.sum | 72 +++++++------------ .../dashboard_service/dashboard_service.go | 10 +-- 4 files changed, 36 insertions(+), 72 deletions(-) diff --git a/docs/swagger.json b/docs/swagger.json index 39da748c..f813c38c 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -4,9 +4,7 @@ "contact": { "name": "AAStar Support", "url": "https://aastar.xyz" - }, - "version": "", - "title": "" + } }, "paths": { "/api/auth": { @@ -121,4 +119,4 @@ "in": "header" } } -} +} \ No newline at end of file diff --git a/go.mod b/go.mod index abd3b8c3..81248241 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,9 @@ require ( github.com/swaggo/swag v1.16.3 golang.org/x/time v0.5.0 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 + gorm.io/datatypes v1.2.0 + gorm.io/driver/postgres v1.5.7 + gorm.io/gorm v1.25.10 k8s.io/apimachinery v0.29.3 ) @@ -26,7 +29,6 @@ require ( github.com/fxamacker/cbor/v2 v2.4.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect - github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -36,25 +38,11 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/joho/godotenv v1.5.1 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.18.2 // indirect - github.com/subosito/gotenv v1.6.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/test-go/testify v1.1.4 // indirect github.com/x448/float16 v0.8.4 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gorm.io/datatypes v1.2.0 // indirect gorm.io/driver/mysql v1.4.7 // indirect - gorm.io/driver/postgres v1.5.7 // indirect - gorm.io/gorm v1.25.10 // indirect ) require ( diff --git a/go.sum b/go.sum index aa24711c..f869e08e 100644 --- a/go.sum +++ b/go.sum @@ -37,14 +37,14 @@ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpV github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/cockroachdb/errors v1.9.0 h1:B48dYem5SlAY7iU8AKsgedb4gH6mo+bDkbtLIvM/a88= -github.com/cockroachdb/errors v1.9.0/go.mod h1:vaNcEYYqbIqB5JhKBhFV9CneUqeuEbB2OYJBK4GBNYQ= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f h1:6jduT9Hfc0njg5jJ1DdKCFPdMBrp/mdZfCpa5h+WM74= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +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= @@ -55,12 +55,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/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 v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,12 +67,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/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.13.14 h1:EwiY3FZP94derMCIam1iW4HFVrSgIcpsu0HwTQtm6CQ= -github.com/ethereum/go-ethereum v1.13.14/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU= github.com/ethereum/go-ethereum v1.14.3 h1:5zvnAqLtnCZrU9uod1JCvHWJbPMURzYFHfc2eHz4PHA= github.com/ethereum/go-ethereum v1.14.3/go.mod h1:1STrq471D0BQbCX9He0hUj4bHxX2k6mt5nOQJhDNOJ8= github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= @@ -92,8 +85,8 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqG github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= -github.com/getsentry/sentry-go v0.13.0 h1:20dgTiUSfxRB/EhMPtxcL9ZEbM1ZdR+W/7f7NWD+xWo= -github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0= +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/gin-contrib/cors v1.7.1 h1:s9SIppU/rk8enVvkzwiC2VK3UZ/0NNGsWfUKvV55rqs= github.com/gin-contrib/cors v1.7.1/go.mod h1:n/Zj7B4xyrgk/cX1WCX2dkzFfaNm/xJb6oIUk7WTtps= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= @@ -131,6 +124,10 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -159,8 +156,6 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -183,16 +178,14 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -207,8 +200,6 @@ github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -217,8 +208,12 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE 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/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 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/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -249,7 +244,6 @@ github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeB github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -269,24 +263,10 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/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/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -301,8 +281,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= @@ -340,10 +318,6 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -427,8 +401,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -446,6 +418,10 @@ gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y= gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= +gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= +gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= +gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 196a7bc3..2b5d69f0 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -43,6 +43,7 @@ func Init() { } type StrategyDBModel struct { + DeletedAt gorm.DeletedAt `gorm:"softDelete:flag" json:"deleted_at"` Description string `gorm:"type:varchar(500)" json:"description"` StrategyCode string `gorm:"type:varchar(255)" json:"strategy_code"` ProjectCode string `gorm:"type:varchar(255)" json:"project_code"` @@ -222,10 +223,11 @@ func IsPayMasterSupport(address string, chain global_const.Network) bool { } type ApiKeyDbModel struct { - Disable bool `gorm:"column:disable;type:bool" json:"disable"` - ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"` - KeyName string `gorm:"column:key_name;type:varchar(255)" json:"key_name"` - Extra datatypes.JSON `gorm:"column:extra" json:"extra"` + Disable bool `gorm:"column:disable;type:bool" json:"disable"` + ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"` + KeyName string `gorm:"column:key_name;type:varchar(255)" json:"key_name"` + DeletedAt gorm.DeletedAt `gorm:"softDelete:flag" json:"deleted_at"` + Extra datatypes.JSON `gorm:"column:extra" json:"extra"` } func (*ApiKeyDbModel) TableName() string { From 317455dfcd76094bbad8ae79ebf1a7749b83dd87 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 12:12:46 +0800 Subject: [PATCH 08/23] go mod init --- go.mod | 28 ++++++++++++++------------- go.sum | 61 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/go.mod b/go.mod index 81248241..cdc2ee6d 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,8 @@ require ( github.com/deckarep/golang-set/v2 v2.6.0 github.com/ethereum/go-ethereum v1.14.3 github.com/gin-contrib/cors v1.7.1 - github.com/gin-gonic/gin v1.9.1 - github.com/go-playground/validator/v10 v10.19.0 + github.com/gin-gonic/gin v1.10.0 + github.com/go-playground/validator/v10 v10.20.0 github.com/mitchellh/mapstructure v1.5.0 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 @@ -26,6 +26,9 @@ require ( require ( github.com/NethermindEth/juno v0.3.1 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect github.com/fxamacker/cbor/v2 v2.4.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -33,7 +36,8 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.4.3 // indirect + github.com/jackc/pgx/v5 v5.5.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect @@ -50,9 +54,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/bytedance/sonic v1.11.3 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect - github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/bytedance/sonic v1.11.6 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect; indirect(force degrade) @@ -82,7 +84,7 @@ require ( github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/supranational/blst v0.3.11 // indirect @@ -91,16 +93,16 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/net v0.25.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect golang.org/x/tools v0.20.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index f869e08e..bf71db54 100644 --- a/go.sum +++ b/go.sum @@ -22,21 +22,18 @@ github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= -github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= -github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= -github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= 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= @@ -93,8 +90,8 @@ github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -112,8 +109,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= -github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= @@ -169,8 +166,10 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= -github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -240,8 +239,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= -github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= 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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -319,13 +318,13 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -339,8 +338,8 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R 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= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -365,8 +364,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.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= @@ -375,8 +374,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -395,8 +394,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 69d948b9343720a0aebefad713ebb1a2d3cd9bef Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 13:29:52 +0800 Subject: [PATCH 09/23] optimize API --- common/model/api_request.go | 9 +++---- config/secret_config.go | 4 ++++ docs/docs.go | 9 ++++++- docs/swagger.json | 9 ++++++- docs/swagger.yaml | 7 +++++- rpc_server/api/v1/paymaster.go | 40 +++++++++++++++---------------- rpc_server/routers/routers_map.go | 2 +- 7 files changed, 52 insertions(+), 28 deletions(-) diff --git a/common/model/api_request.go b/common/model/api_request.go index e983d19c..62e16c79 100644 --- a/common/model/api_request.go +++ b/common/model/api_request.go @@ -14,10 +14,11 @@ type UserOpRequest struct { EntryPointVersion global_const.EntrypointVersion `json:"entrypoint_version"` } type JsonRpcRequest struct { - JsonRpc string `json:"jsonrpc"` - Method string `json:"method"` - Params []interface{} `json:"params"` - Id int `json:"id"` + JsonRpc string `json:"jsonrpc"` + Method string `json:"method"` + Params []interface{} `json:"params"` + Id int `json:"id"` + Network global_const.Network `json:"-"` } type ClientCredential struct { ApiKey string `json:"apiKey"` diff --git a/config/secret_config.go b/config/secret_config.go index 22e6c284..98017d11 100644 --- a/config/secret_config.go +++ b/config/secret_config.go @@ -44,6 +44,10 @@ func GetNetworkSecretConfig(network global_const.Network) model.NetWorkSecretCon return secretConfig.NetWorkSecretConfigMap[string(network)] } +func CheckNetworkSupport(network global_const.Network) bool { + _, ok := secretConfig.NetWorkSecretConfigMap[string(network)] + return ok +} func GetPriceOracleApiKey() string { return secretConfig.PriceOracleApiKey } diff --git a/docs/docs.go b/docs/docs.go index ab889b9e..daf5f24b 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -61,7 +61,7 @@ const docTemplate = `{ } } }, - "/api/v1/paymaster": { + "/api/v1/paymaster{network}": { "post": { "security": [ { @@ -76,6 +76,13 @@ const docTemplate = `{ "Paymaster" ], "parameters": [ + { + "type": "string", + "description": "Network", + "name": "network", + "in": "path", + "required": true + }, { "description": "JsonRpcRequest Model", "name": "rpcRequest", diff --git a/docs/swagger.json b/docs/swagger.json index f813c38c..04257279 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -50,7 +50,7 @@ } } }, - "/api/v1/paymaster": { + "/api/v1/paymaster{network}": { "post": { "security": [ { @@ -65,6 +65,13 @@ "Paymaster" ], "parameters": [ + { + "type": "string", + "description": "Network", + "name": "network", + "in": "path", + "required": true + }, { "description": "JsonRpcRequest Model", "name": "rpcRequest", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 282e5be6..d3e0676a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -48,12 +48,17 @@ paths: description: OK tags: - Healthz - /api/v1/paymaster: + /api/v1/paymaster{network}: post: consumes: - application/json description: Paymaster JSON-RPC API parameters: + - description: Network + in: path + name: network + required: true + type: string - description: JsonRpcRequest Model in: body name: rpcRequest diff --git a/rpc_server/api/v1/paymaster.go b/rpc_server/api/v1/paymaster.go index d7a1d86a..e1dbfa42 100644 --- a/rpc_server/api/v1/paymaster.go +++ b/rpc_server/api/v1/paymaster.go @@ -29,8 +29,9 @@ func init() { // @Description Paymaster JSON-RPC API // @Accept json // @Product json +// @param network path string true "Network" // @Param rpcRequest body model.JsonRpcRequest true "JsonRpcRequest Model" -// @Router /api/v1/paymaster [post] +// @Router /api/v1/paymaster{network} [post] // @Success 200 // @Security JWT func Paymaster(ctx *gin.Context) { @@ -46,6 +47,18 @@ func Paymaster(ctx *gin.Context) { } }() + network := ctx.Param("network") + if network == "" { + errStr := fmt.Sprintf("Request Error [network is empty]") + response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, errStr) + return + } + if !config.CheckNetworkSupport(global_const.Network(network)) { + errStr := fmt.Sprintf("Request Error [network not support]") + response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, errStr) + return + } + jsonRpcRequest.Network = global_const.Network(network) if err := ctx.ShouldBindJSON(&jsonRpcRequest); err != nil { errStr := fmt.Sprintf("Request Error [%v]", err) @@ -79,14 +92,8 @@ func Paymaster(ctx *gin.Context) { func GetSupportPaymaster() MethodFunctionFunc { return func(ctx *gin.Context, jsonRpcRequest model.JsonRpcRequest) (result interface{}, err error) { - if jsonRpcRequest.Params[0] == nil { - return nil, xerrors.Errorf("Request Error [network is empty]") - } - networkStr, ok := jsonRpcRequest.Params[0].(string) - if !ok { - return nil, xerrors.Errorf("Request Error [network is not string]") - } - paymasterSet, err := config.GetSupportPaymaster(global_const.Network(networkStr)) + + paymasterSet, err := config.GetSupportPaymaster(jsonRpcRequest.Network) if err != nil { return nil, err } @@ -96,14 +103,7 @@ func GetSupportPaymaster() MethodFunctionFunc { func GetSupportEntryPointFunc() MethodFunctionFunc { return func(ctx *gin.Context, jsonRpcRequest model.JsonRpcRequest) (result interface{}, err error) { - if jsonRpcRequest.Params[0] == nil { - return nil, xerrors.Errorf("Request Error [network is empty]") - } - networkStr, ok := jsonRpcRequest.Params[0].(string) - if !ok { - return nil, xerrors.Errorf("Request Error [network is not string]") - } - entryPoints, err := config.GetSupportEntryPoints(global_const.Network(networkStr)) + entryPoints, err := config.GetSupportEntryPoints(jsonRpcRequest.Network) if err != nil { return nil, err } @@ -113,6 +113,7 @@ func GetSupportEntryPointFunc() MethodFunctionFunc { func EstimateUserOpGasFunc() MethodFunctionFunc { return func(ctx *gin.Context, jsonRpcRequest model.JsonRpcRequest) (result interface{}, err error) { request, err := parseTryPayUserOperationParams(jsonRpcRequest.Params) + request.Network = jsonRpcRequest.Network if err != nil { return nil, xerrors.Errorf("parseTryPayUserOperationParams ERROR [%v]", err) } @@ -130,6 +131,7 @@ func EstimateUserOpGasFunc() MethodFunctionFunc { func TryPayUserOperationMethod() MethodFunctionFunc { return func(ctx *gin.Context, jsonRpcRequest model.JsonRpcRequest) (result interface{}, err error) { request, err := parseTryPayUserOperationParams(jsonRpcRequest.Params) + request.Network = jsonRpcRequest.Network logrus.Debug("parseTryPayUserOperationParams result: ", request) if err != nil { @@ -167,9 +169,7 @@ func parseTryPayUserOperationParams(params []interface{}) (*model.UserOpRequest, if extra["strategy_code"] != nil { result.StrategyCode = extra["strategy_code"].(string) } - if extra["network"] != nil { - result.Network = extra["network"].(global_const.Network) - } + if extra["token"] != nil { result.UserPayErc20Token = extra["token"].(global_const.TokenType) } diff --git a/rpc_server/routers/routers_map.go b/rpc_server/routers/routers_map.go index 341b397d..dbb65098 100644 --- a/rpc_server/routers/routers_map.go +++ b/rpc_server/routers/routers_map.go @@ -20,5 +20,5 @@ type Path string const ( Auth Path = "api/auth" Healthz Path = "api/healthz" - Paymaster Path = "api/v1/paymaster" + Paymaster Path = "api/v1/paymaster:network" ) From 2a1f57eeac04bf7fb497d91576003ddd2834f4d7 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 13:40:45 +0800 Subject: [PATCH 10/23] optimize API --- docs/docs.go | 2 +- docs/swagger.json | 2 +- docs/swagger.yaml | 2 +- rpc_server/api/v1/paymaster.go | 2 +- rpc_server/routers/routers_map.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index daf5f24b..c6ae8568 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -61,7 +61,7 @@ const docTemplate = `{ } } }, - "/api/v1/paymaster{network}": { + "/api/v1/paymaster/{network}": { "post": { "security": [ { diff --git a/docs/swagger.json b/docs/swagger.json index 04257279..9eede293 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -50,7 +50,7 @@ } } }, - "/api/v1/paymaster{network}": { + "/api/v1/paymaster/{network}": { "post": { "security": [ { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index d3e0676a..052a2180 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -48,7 +48,7 @@ paths: description: OK tags: - Healthz - /api/v1/paymaster{network}: + /api/v1/paymaster/{network}: post: consumes: - application/json diff --git a/rpc_server/api/v1/paymaster.go b/rpc_server/api/v1/paymaster.go index e1dbfa42..55ec9418 100644 --- a/rpc_server/api/v1/paymaster.go +++ b/rpc_server/api/v1/paymaster.go @@ -31,7 +31,7 @@ func init() { // @Product json // @param network path string true "Network" // @Param rpcRequest body model.JsonRpcRequest true "JsonRpcRequest Model" -// @Router /api/v1/paymaster{network} [post] +// @Router /api/v1/paymaster/{network} [post] // @Success 200 // @Security JWT func Paymaster(ctx *gin.Context) { diff --git a/rpc_server/routers/routers_map.go b/rpc_server/routers/routers_map.go index dbb65098..de13ba27 100644 --- a/rpc_server/routers/routers_map.go +++ b/rpc_server/routers/routers_map.go @@ -20,5 +20,5 @@ type Path string const ( Auth Path = "api/auth" Healthz Path = "api/healthz" - Paymaster Path = "api/v1/paymaster:network" + Paymaster Path = "api/v1/paymaster/:network" ) From 7b1c01d039bfba0662d40f487d694be7a50a768e Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 17:19:40 +0800 Subject: [PATCH 11/23] Gas Tank --- common/data_utils/data_util.go | 2 +- common/model/api_key_info.go | 7 +- common/model/secret_config.go | 1 + common/model/strategy.go | 3 +- common/network/ethereum_adaptable_executor.go | 17 ++-- .../ethereum_adaptable_executor_test.go | 4 +- common/price_compoent/price_util.go | 10 ++ config/secret_config.go | 5 + rpc_server/api/v1/paymaster.go | 4 +- rpc_server/middlewares/rate_limit.go | 6 +- schedulor/UserOpEventListener.go | 98 +++++++++++++++++++ .../dashboard_service/dashboard_service.go | 3 + service/operator/operator_test.go | 2 +- service/operator/try_pay_user_op_execute.go | 87 ++++++++++++---- sponsor_manager/sponsor_repo.go | 27 +++++ 15 files changed, 238 insertions(+), 38 deletions(-) create mode 100644 schedulor/UserOpEventListener.go create mode 100644 sponsor_manager/sponsor_repo.go diff --git a/common/data_utils/data_util.go b/common/data_utils/data_util.go index a3fdf318..0bebead0 100644 --- a/common/data_utils/data_util.go +++ b/common/data_utils/data_util.go @@ -32,7 +32,7 @@ func GetUserOpWithPaymasterAndDataForSimulate(op user_op.UserOpInput, strategy * op.CallGasLimit = global_const.DummyCallGasLimit } - paymasterData, err := executor.GetPaymasterData(&op, strategy, paymasterDataInput) + paymasterData, _, err := executor.GetPaymasterData(&op, strategy, paymasterDataInput) if err != nil { return nil, err } diff --git a/common/model/api_key_info.go b/common/model/api_key_info.go index 42b287d8..a18a33b9 100644 --- a/common/model/api_key_info.go +++ b/common/model/api_key_info.go @@ -3,7 +3,8 @@ package model import "golang.org/x/time/rate" type ApiKeyModel struct { - Disable bool `gorm:"column:disable;type:bool" json:"disable"` - ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"` - RateLimit rate.Limit `gorm:"column:rate_limit;type:int" json:"rate_limit"` + Disable bool `json:"disable"` + ApiKey string `json:"api_key"` + RateLimit rate.Limit `json:"rate_limit"` + UserId int64 `json:"user_id"` } diff --git a/common/model/secret_config.go b/common/model/secret_config.go index 5f8a4f81..c105af47 100644 --- a/common/model/secret_config.go +++ b/common/model/secret_config.go @@ -19,6 +19,7 @@ type SecretConfig struct { RelayDBConfig DBConfig `json:"relay_db_config"` ApiKeyTableName string `json:"api_key_table_name"` StrategyConfigTableName string `json:"strategy_config_table_name"` + FreeSponsorWhitelist []string `json:"free_sponsor_whitelist"` } type NetWorkSecretConfig struct { diff --git a/common/model/strategy.go b/common/model/strategy.go index 92aaa487..ee2528d6 100644 --- a/common/model/strategy.go +++ b/common/model/strategy.go @@ -15,7 +15,8 @@ type Strategy struct { EntryPointInfo *EntryPointInfo `json:"entrypoint_info"` Description string `json:"description"` ExecuteRestriction *StrategyExecuteRestriction `json:"execute_restriction"` - Erc20TokenType global_const.TokenType + Erc20TokenType global_const.TokenType `json:"-"` + ProjectSponsor bool `json:"-"` } type PaymasterInfo struct { PayMasterAddress *common.Address `json:"paymaster_address"` diff --git a/common/network/ethereum_adaptable_executor.go b/common/network/ethereum_adaptable_executor.go index 444f4119..99870b4a 100644 --- a/common/network/ethereum_adaptable_executor.go +++ b/common/network/ethereum_adaptable_executor.go @@ -539,18 +539,21 @@ func (executor *EthereumExecutor) GetUserOpHash(userOp *user_op.UserOpInput, str } } -func (executor *EthereumExecutor) GetPaymasterData(userOp *user_op.UserOpInput, strategy *model.Strategy, paymasterDataInput *paymaster_data.PaymasterDataInput) ([]byte, error) { - userOpHash, _, err := executor.GetUserOpHash(userOp, strategy) - if err != nil { +func (executor *EthereumExecutor) GetPaymasterData(userOp *user_op.UserOpInput, strategy *model.Strategy, paymasterDataInput *paymaster_data.PaymasterDataInput) (paymasterData []byte, userOpHash []byte, err error) { + userOpHash, _, hashErr := executor.GetUserOpHash(userOp, strategy) + if hashErr != nil { logrus.Errorf("GetUserOpHash error [%v]", err) - return nil, err + return nil, nil, err } signer := config.GetSigner(strategy.GetNewWork()) signature, err := utils.GetSign(userOpHash, signer.PrivateKey) if err != nil { - return nil, err + return nil, nil, err } dataGenerateFunc := paymaster_pay_type.GetGenerateFunc(strategy.GetPayType()) - paymasterData, err := dataGenerateFunc(paymasterDataInput, signature) - return paymasterData, err + paymasterData, generateDataErr := dataGenerateFunc(paymasterDataInput, signature) + if generateDataErr != nil { + return nil, nil, generateDataErr + } + return paymasterData, userOpHash, nil } diff --git a/common/network/ethereum_adaptable_executor_test.go b/common/network/ethereum_adaptable_executor_test.go index cb6197f6..379ee7ff 100644 --- a/common/network/ethereum_adaptable_executor_test.go +++ b/common/network/ethereum_adaptable_executor_test.go @@ -283,7 +283,7 @@ func testGetPaymasterData(t *testing.T, chain global_const.Network, input *user_ dataInput := paymaster_data.NewPaymasterDataInput(strategy) dataInput.PaymasterPostOpGasLimit = global_const.DummyPaymasterPostoperativelyBigint dataInput.PaymasterVerificationGasLimit = global_const.DummyPaymasterOversimplificationBigint - paymasterData, err := executor.GetPaymasterData(input, strategy, dataInput) + paymasterData, _, err := executor.GetPaymasterData(input, strategy, dataInput) if err != nil { t.Error(err) return @@ -301,7 +301,7 @@ func testSimulateHandleOp(t *testing.T, chain global_const.Network, strategy *mo dataInput := paymaster_data.NewPaymasterDataInput(strategy) op.AccountGasLimits = user_op.DummyAccountGasLimits op.GasFees = user_op.DummyGasFees - paymasterData, err := sepoliaExector.GetPaymasterData(op, strategy, dataInput) + paymasterData, _, err := sepoliaExector.GetPaymasterData(op, strategy, dataInput) if err != nil { t.Error(err) return diff --git a/common/price_compoent/price_util.go b/common/price_compoent/price_util.go index 61b3d36a..42a7a52f 100644 --- a/common/price_compoent/price_util.go +++ b/common/price_compoent/price_util.go @@ -8,6 +8,7 @@ import ( "io" "io/ioutil" "log" + "math/big" "net/http" "net/url" "os" @@ -29,6 +30,15 @@ func init() { URLMap[global_const.TokenTypeOP] = "https://api.coingecko.com/api/v3/simple/price?ids=optimism&vs_currencies=usd" } +func GetTokenCostInUsd(tokenType global_const.TokenType, amount *big.Float) (*big.Float, error) { + price, err := GetPriceUsd(tokenType) + if err != nil { + return nil, xerrors.Errorf("get price error: %w", err) + } + amountInUsd := new(big.Float).Mul(new(big.Float).SetFloat64(price), amount) + return amountInUsd, nil +} + func GetPriceUsd(tokenType global_const.TokenType) (float64, error) { if global_const.IsStableToken(tokenType) { diff --git a/config/secret_config.go b/config/secret_config.go index 98017d11..d66b7879 100644 --- a/config/secret_config.go +++ b/config/secret_config.go @@ -40,6 +40,11 @@ func secretConfigInit(secretConfigPath string) { signerConfig[global_const.Network(network)] = eoa } } +func IsSponsorWhitelist(address string) bool { + + //TODO + return true +} func GetNetworkSecretConfig(network global_const.Network) model.NetWorkSecretConfig { return secretConfig.NetWorkSecretConfigMap[string(network)] } diff --git a/rpc_server/api/v1/paymaster.go b/rpc_server/api/v1/paymaster.go index 55ec9418..97c5d8bb 100644 --- a/rpc_server/api/v1/paymaster.go +++ b/rpc_server/api/v1/paymaster.go @@ -142,7 +142,9 @@ func TryPayUserOperationMethod() MethodFunctionFunc { } logrus.Debugf("After Validate ") - if result, err := operator.TryPayUserOpExecute(request); err != nil { + apiKeyModel := ctx.MustGet(global_const.ContextKeyApiMoDel) + + if result, err := operator.TryPayUserOpExecute(apiKeyModel.(*model.ApiKeyModel), request); err != nil { return nil, xerrors.Errorf("TryPayUserOpExecute ERROR [%v]", err) } else { return result, nil diff --git a/rpc_server/middlewares/rate_limit.go b/rpc_server/middlewares/rate_limit.go index b8f1c4ad..f3cfdd57 100644 --- a/rpc_server/middlewares/rate_limit.go +++ b/rpc_server/middlewares/rate_limit.go @@ -21,11 +21,9 @@ var limiter map[string]*rate.Limiter func RateLimiterByApiKeyHandler() gin.HandlerFunc { return func(ctx *gin.Context) { if exists, current := utils.CurrentUser(ctx); exists { - apiKeyModel, _ := ctx.Get(global_const.ContextKeyApiMoDel) + apiKeyModel := ctx.MustGet(global_const.ContextKeyApiMoDel) defaultLimit := DefaultLimit - if apiKeyModel != nil { - defaultLimit = apiKeyModel.(*model.ApiKeyModel).RateLimit - } + defaultLimit = apiKeyModel.(*model.ApiKeyModel).RateLimit if limiting(¤t, defaultLimit) { ctx.Next() } else { diff --git a/schedulor/UserOpEventListener.go b/schedulor/UserOpEventListener.go new file mode 100644 index 00000000..e264c94f --- /dev/null +++ b/schedulor/UserOpEventListener.go @@ -0,0 +1,98 @@ +package schedulor + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/price_compoent" + "AAStarCommunity/EthPaymaster_BackService/config" + "AAStarCommunity/EthPaymaster_BackService/sponsor_manager" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/sirupsen/logrus" + "math/big" +) + +func AddListener(client ethclient.Client, network global_const.Network) { + entryPointAddress, _ := config.GetSupportEntryPoints(network) + if entryPointAddress == nil { + logrus.Debugf("Not Support Network %v", network) + return + } + for _, address := range entryPointAddress.ToSlice() { + contractAddress := common.HexToAddress(address) + query := ethereum.FilterQuery{ + Addresses: []common.Address{contractAddress}, + } + sub, err := client.SubscribeFilterLogs(nil, query, nil) + if err != nil { + logrus.Errorf("SubscribeFilterLogs failed: %v", err) + return + } + logs := make(chan types.Log) + go func() { + for { + select { + case err := <-sub.Err(): + logrus.Errorf("SubscribeFilterLogs failed: %v", err) + return + case vLog := <-logs: + if vLog.Removed { + continue + } + //TODO + //UserOpEventComunicate(network, ContractUserOperationEvent{}) + } + } + }() + //TODO + //client.SubscribeFilterLogs() + } + //TODO +} + +type ContractUserOperationEvent struct { + UserOpHash [32]byte + Sender string + Paymaster string + Nonce *big.Int + Success bool + ActualGasCost *big.Int + ActualGasUsed *big.Int + Raw types.Log +} + +func UserOpEventComunicate(network global_const.Network, event ContractUserOperationEvent) { + paymasterAddressSet, _ := config.GetSupportPaymaster(network) + if paymasterAddressSet == nil { + logrus.Debugf("Not Support Network %v", network) + return + } + if !paymasterAddressSet.Contains(event.Paymaster) { + logrus.Debugf("UserOpEventComunicate: paymaster not support, %v", event.Paymaster) + return + } + if !event.Success { + err := sponsor_manager.ReleaseUserOpHashLock(event.UserOpHash[:]) + if err != nil { + logrus.Errorf("ReleaseUserOpHashLock failed: %v", err) + } + return + } + gasCostEther := new(big.Float).SetInt(event.ActualGasCost) + gasCostEther = new(big.Float).Quo(gasCostEther, new(big.Float).SetInt64(1e18)) + //logrus.Infof("UserOpEventComunicate: %v, %v, %v, %v", event.UserOpHash, event.Sender, event.ActualGasCost, gasCostEther) + gasCostUsd, err := price_compoent.GetTokenCostInUsd(global_const.TokenTypeETH, gasCostEther) + if err != nil { + //TODO if is NetWorkError, need retry + logrus.Errorf("GetTokenCostInUsd failed: %v", err) + return + } + + err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender, event.UserOpHash[:], network, gasCostUsd) + if err != nil { + //TODO if is NetWorkError, need retry + logrus.Errorf("ReleaseBalanceWithActualCost failed: %v", err) + return + } +} diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 2b5d69f0..459ccde3 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -76,6 +76,7 @@ func GetStrategyByCode(strategyCode string, entryPointVersion global_const.Entry if err != nil { return nil, err } + strategy.ProjectSponsor = true return strategy, nil } @@ -223,6 +224,7 @@ func IsPayMasterSupport(address string, chain global_const.Network) bool { } type ApiKeyDbModel struct { + UserId int64 `gorm:"column:user_id;type:integer" json:"user_id"` Disable bool `gorm:"column:disable;type:bool" json:"disable"` ApiKey string `gorm:"column:api_key;type:varchar(255)" json:"api_key"` KeyName string `gorm:"column:key_name;type:varchar(255)" json:"key_name"` @@ -242,6 +244,7 @@ func convertApiKeyDbModelToApiKeyModel(apiKeyDbModel *ApiKeyDbModel) *model.ApiK Disable: apiKeyDbModel.Disable, ApiKey: apiKeyDbModel.ApiKey, RateLimit: 10, + UserId: apiKeyDbModel.UserId, } } func GetAPiInfoByApiKey(apiKey string) (*model.ApiKeyModel, error) { diff --git a/service/operator/operator_test.go b/service/operator/operator_test.go index a7dbdadc..521fa033 100644 --- a/service/operator/operator_test.go +++ b/service/operator/operator_test.go @@ -160,7 +160,7 @@ func testGetSupportEntrypointExecute(t *testing.T) { t.Log(res) } func testTryPayUserOpExecute(t *testing.T, request *model.UserOpRequest) { - result, err := TryPayUserOpExecute(request) + result, err := TryPayUserOpExecute(&model.ApiKeyModel{}, request) if err != nil { t.Fatal(err) return diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index e8fbc539..3ea30128 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -5,17 +5,21 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/model" "AAStarCommunity/EthPaymaster_BackService/common/network" "AAStarCommunity/EthPaymaster_BackService/common/paymaster_data" + "AAStarCommunity/EthPaymaster_BackService/common/price_compoent" "AAStarCommunity/EthPaymaster_BackService/common/user_op" "AAStarCommunity/EthPaymaster_BackService/common/utils" + "AAStarCommunity/EthPaymaster_BackService/config" "AAStarCommunity/EthPaymaster_BackService/gas_executor" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" - "AAStarCommunity/EthPaymaster_BackService/service/pay_service" "AAStarCommunity/EthPaymaster_BackService/service/validator_service" + "AAStarCommunity/EthPaymaster_BackService/sponsor_manager" "github.com/sirupsen/logrus" "golang.org/x/xerrors" + "math/big" + "strconv" ) -func TryPayUserOpExecute(request *model.UserOpRequest) (*model.TryPayUserOpResponse, error) { +func TryPayUserOpExecute(apiKeyModel *model.ApiKeyModel, request *model.UserOpRequest) (*model.TryPayUserOpResponse, error) { userOp, strategy, paymasterDataInput, err := prepareExecute(request) if err != nil { return nil, err @@ -29,12 +33,12 @@ func TryPayUserOpExecute(request *model.UserOpRequest) (*model.TryPayUserOpRespo paymasterDataInput.PaymasterVerificationGasLimit = gasResponse.OpEstimateGas.PaymasterVerificationGasLimit paymasterDataInput.PaymasterPostOpGasLimit = gasResponse.OpEstimateGas.PaymasterPostOpGasLimit - payReceipt, err := executePay(strategy, paymasterUserOp, gasResponse) - if err != nil { - return nil, err - } - logrus.Debug("payReceipt:", payReceipt) - result, err := postExecute(paymasterUserOp, strategy, gasResponse, paymasterDataInput) + //payReceipt, err := executePay(strategy, paymasterUserOp, gasResponse) + //if err != nil { + // return nil, err + //} + //logrus.Debug("payReceipt:", payReceipt) + result, err := postExecute(apiKeyModel, paymasterUserOp, strategy, gasResponse, paymasterDataInput) if err != nil { return nil, err } @@ -88,30 +92,77 @@ func ValidateGas(userOp *user_op.UserOpInput, gasComputeResponse *model.ComputeG return nil } -func executePay(strategy *model.Strategy, userOp *user_op.UserOpInput, gasResponse *model.ComputeGasResponse) (*model.PayReceipt, error) { - //1.Recharge - ethereumPayservice := pay_service.EthereumPayService{} - if err := ethereumPayservice.Pay(); err != nil { +func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { + if input.PayType == global_const.PayTypeERC20 { + logrus.Debugf("Not Need ExecutePay In ERC20 PayType") + return nil, nil + } + if config.IsSponsorWhitelist(input.UserOpSender) { + logrus.Debugf("Not Need ExecutePay In SponsorWhitelist") + return nil, nil + } + // Get Deposit Balance + var payUserKey string + if input.ProjectSponsor == true { + payUserKey = input.ProjectUserId + } else { + payUserKey = input.UserOpSender + } + depositBalance, err := sponsor_manager.GetAvailableBalance(payUserKey) + if err != nil { + return nil, err + } + gasUsdCost, err := price_compoent.GetTokenCostInUsd(global_const.TokenTypeETH, input.MaxTxGasCostInEther) + if err != nil { return nil, err } - //2.record account - ethereumPayservice.RecordAccount() - //3.return Receipt - ethereumPayservice.GetReceipt() + if depositBalance.Cmp(gasUsdCost) < 0 { + return nil, xerrors.Errorf("Insufficient balance [%s] not Enough to Pay Cost [%s]", depositBalance.String(), gasUsdCost.String()) + } + //Lock Deposit Balance + err = sponsor_manager.LockBalance(payUserKey, input.UserOpHash, input.Network, + gasUsdCost) + if err != nil { + return nil, err + } + return &model.PayReceipt{ TransactionHash: "0x110406d44ec1681fcdab1df2310181dee26ff43c37167b2c9c496b35cce69437", Sponsor: "aastar", }, nil } -func postExecute(userOp *user_op.UserOpInput, strategy *model.Strategy, gasResponse *model.ComputeGasResponse, paymasterDataInput *paymaster_data.PaymasterDataInput) (*model.TryPayUserOpResponse, error) { +type ExecutePayInput struct { + ProjectUserId string + PayType global_const.PayType + ProjectSponsor bool + UserOpSender string + MaxTxGasCostInEther *big.Float + UserOpHash []byte + Network global_const.Network +} + +func postExecute(apiKeyModel *model.ApiKeyModel, userOp *user_op.UserOpInput, strategy *model.Strategy, gasResponse *model.ComputeGasResponse, paymasterDataInput *paymaster_data.PaymasterDataInput) (*model.TryPayUserOpResponse, error) { + executor := network.GetEthereumExecutor(strategy.GetNewWork()) - paymasterData, err := executor.GetPaymasterData(userOp, strategy, paymasterDataInput) + paymasterData, userOpHash, err := executor.GetPaymasterData(userOp, strategy, paymasterDataInput) if err != nil { return nil, xerrors.Errorf("postExecute GetPaymasterData Error: [%w]", err) } logrus.Debug("postExecute paymasterData:", paymasterData) + _, err = executePay(&ExecutePayInput{ + ProjectUserId: strconv.FormatInt(apiKeyModel.UserId, 10), + PayType: strategy.GetPayType(), + ProjectSponsor: strategy.ProjectSponsor, + UserOpSender: userOp.Sender.String(), + MaxTxGasCostInEther: gasResponse.TotalGasDetail.MaxTxGasCostInEther, + UserOpHash: userOpHash, + Network: strategy.GetNewWork(), + }) + if err != nil { + return nil, xerrors.Errorf("postExecute executePay Error: [%w]", err) + } var result = &model.TryPayUserOpResponse{ StrategyId: strategy.Id, EntryPointAddress: strategy.GetEntryPointAddress().String(), diff --git a/sponsor_manager/sponsor_repo.go b/sponsor_manager/sponsor_repo.go new file mode 100644 index 00000000..fbe553eb --- /dev/null +++ b/sponsor_manager/sponsor_repo.go @@ -0,0 +1,27 @@ +package sponsor_manager + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "math/big" +) + +func GetAvailableBalance(userId string) (balance *big.Float, err error) { + // TODO + return big.NewFloat(12.1), nil +} + +func LockBalance(userId string, userOpHash []byte, network global_const.Network, + lockAmount *big.Float) (err error) { + //TODO + return nil +} + +func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, network global_const.Network, + actualGasCost *big.Float) (err error) { + //TODO + return nil +} +func ReleaseUserOpHashLock(userOpHash []byte) (err error) { + //TODO + return nil +} From 0b9f00fe6296417f8e9a90162c92716a5261abc1 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 21 May 2024 23:30:18 +0800 Subject: [PATCH 12/23] update merge --- .../dashboard_service/dashboard_service.go | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index b7371f2b..1aa668b3 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -203,44 +203,6 @@ func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain }, Erc20TokenType: gasUseToken, } -// GetSuitableStrategy get suitable strategy by entryPointVersion, chain, -// -// For Offical StrategyConfig, -func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain global_const.Network, gasUseToken global_const.TokenType) (*model.Strategy, error) { - if entryPointVersion == "" { - entryPointVersion = global_const.EntrypointV06 - } - gasToken := config.GetGasToken(chain) - entryPointAddress := config.GetEntrypointAddress(chain, entryPointVersion) - paymasterAddress := config.GetPaymasterAddress(chain, entryPointVersion) - payType := global_const.PayTypeVerifying - isPerc20Enable := false - if gasUseToken != "" { - payType = global_const.PayTypeERC20 - if config.IsPErc20Token(gasUseToken) { - isPerc20Enable = true - } - } - - strategy := &model.Strategy{ - NetWorkInfo: &model.NetWorkInfo{ - NetWork: chain, - GasToken: gasToken, - }, - EntryPointInfo: &model.EntryPointInfo{ - EntryPointVersion: entryPointVersion, - EntryPointAddress: entryPointAddress, - }, - PaymasterInfo: &model.PaymasterInfo{ - PayMasterAddress: paymasterAddress, - PayType: payType, - IsProjectErc20PayEnable: isPerc20Enable, - }, - Erc20TokenType: gasUseToken, - } - if strategy == nil { - return nil, errors.New("strategy not found") - } return strategy, nil } @@ -261,7 +223,6 @@ func IsPayMasterSupport(address string, chain global_const.Network) bool { } type ApiKeyDbModel struct { - model.BaseData UserId int64 `gorm:"column:user_id;type:integer" json:"user_id"` Disable bool `gorm:"column:disable;type:bool" json:"disable"` From 2d8fcb5a16badf3d471aa011d11dfec298ee3f5d Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 23 May 2024 17:10:57 +0800 Subject: [PATCH 13/23] add DB --- common/model/strategy.go | 2 +- .../dashboard_service/dashboard_service.go | 7 - service/operator/try_pay_user_op_execute.go | 12 +- sponsor_manager/sponsor_repo.go | 27 ---- sponsor_manager/sponsor_service.go | 136 ++++++++++++++++++ 5 files changed, 146 insertions(+), 38 deletions(-) delete mode 100644 sponsor_manager/sponsor_repo.go create mode 100644 sponsor_manager/sponsor_service.go diff --git a/common/model/strategy.go b/common/model/strategy.go index ee2528d6..6f942d36 100644 --- a/common/model/strategy.go +++ b/common/model/strategy.go @@ -42,7 +42,7 @@ func (strategy *Strategy) GetNewWork() global_const.Network { return strategy.NetWorkInfo.NetWork } -func (strategy *Strategy) GetUseToken() global_const.TokenType { +func (strategy *Strategy) GetGasToken() global_const.TokenType { return strategy.NetWorkInfo.GasToken } func (strategy *Strategy) GetPayType() global_const.PayType { diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 1aa668b3..31fc45d9 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -18,14 +18,12 @@ import ( var ( configDB *gorm.DB - relayDB *gorm.DB onlyOnce = sync.Once{} ) func Init() { onlyOnce.Do(func() { configDBDsn := config.GetConfigDBDSN() - relayDBDsn := config.GetRelayDBDSN() configDBVar, err := gorm.Open(postgres.Open(configDBDsn), &gorm.Config{}) if err != nil { @@ -33,11 +31,6 @@ func Init() { } configDB = configDBVar - relayDBVar, err := gorm.Open(postgres.Open(relayDBDsn), &gorm.Config{}) - if err != nil { - panic(err) - } - relayDB = relayDBVar }) } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 3ea30128..8eed061a 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -98,9 +98,13 @@ func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { return nil, nil } if config.IsSponsorWhitelist(input.UserOpSender) { - logrus.Debugf("Not Need ExecutePay In SponsorWhitelist") + logrus.Debugf("Not Need ExecutePay In SponsorWhitelist [%s]", input.UserOpSender) return nil, nil } + //if config.IsTestNet(input.Network) { + // logrus.Debugf("Not Need ExecutePay In TestNet [%s]", input.Network) + // return nil, nil + //} // Get Deposit Balance var payUserKey string if input.ProjectSponsor == true { @@ -112,7 +116,7 @@ func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { if err != nil { return nil, err } - gasUsdCost, err := price_compoent.GetTokenCostInUsd(global_const.TokenTypeETH, input.MaxTxGasCostInEther) + gasUsdCost, err := price_compoent.GetTokenCostInUsd(input.GasToken, input.MaxTxGasCostInEther) if err != nil { return nil, err } @@ -120,7 +124,7 @@ func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { return nil, xerrors.Errorf("Insufficient balance [%s] not Enough to Pay Cost [%s]", depositBalance.String(), gasUsdCost.String()) } //Lock Deposit Balance - err = sponsor_manager.LockBalance(payUserKey, input.UserOpHash, input.Network, + err = sponsor_manager.LockUserBalance(payUserKey, input.UserOpHash, input.Network, gasUsdCost) if err != nil { return nil, err @@ -140,6 +144,7 @@ type ExecutePayInput struct { MaxTxGasCostInEther *big.Float UserOpHash []byte Network global_const.Network + GasToken global_const.TokenType } func postExecute(apiKeyModel *model.ApiKeyModel, userOp *user_op.UserOpInput, strategy *model.Strategy, gasResponse *model.ComputeGasResponse, paymasterDataInput *paymaster_data.PaymasterDataInput) (*model.TryPayUserOpResponse, error) { @@ -159,6 +164,7 @@ func postExecute(apiKeyModel *model.ApiKeyModel, userOp *user_op.UserOpInput, st MaxTxGasCostInEther: gasResponse.TotalGasDetail.MaxTxGasCostInEther, UserOpHash: userOpHash, Network: strategy.GetNewWork(), + GasToken: strategy.GetGasToken(), }) if err != nil { return nil, xerrors.Errorf("postExecute executePay Error: [%w]", err) diff --git a/sponsor_manager/sponsor_repo.go b/sponsor_manager/sponsor_repo.go deleted file mode 100644 index fbe553eb..00000000 --- a/sponsor_manager/sponsor_repo.go +++ /dev/null @@ -1,27 +0,0 @@ -package sponsor_manager - -import ( - "AAStarCommunity/EthPaymaster_BackService/common/global_const" - "math/big" -) - -func GetAvailableBalance(userId string) (balance *big.Float, err error) { - // TODO - return big.NewFloat(12.1), nil -} - -func LockBalance(userId string, userOpHash []byte, network global_const.Network, - lockAmount *big.Float) (err error) { - //TODO - return nil -} - -func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, network global_const.Network, - actualGasCost *big.Float) (err error) { - //TODO - return nil -} -func ReleaseUserOpHashLock(userOpHash []byte) (err error) { - //TODO - return nil -} diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go new file mode 100644 index 00000000..4458c41d --- /dev/null +++ b/sponsor_manager/sponsor_service.go @@ -0,0 +1,136 @@ +package sponsor_manager + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/config" + "errors" + "golang.org/x/xerrors" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "math/big" + "sync" +) + +var ( + relayDB *gorm.DB + onlyOnce = sync.Once{} +) + +func Init() { + onlyOnce.Do(func() { + relayDBDsn := config.GetRelayDBDSN() + + relayDBVar, err := gorm.Open(postgres.Open(relayDBDsn), &gorm.Config{}) + if err != nil { + panic(err) + } + relayDB = relayDBVar + }) +} + +type UpdateType string +type BalanceType string + +const ( + Deposit UpdateType = "deposit" + Lock UpdateType = "lock" + Withdraw UpdateType = "withdraw" + Release UpdateType = "release" + + AvailableBalance BalanceType = "available_balance" + LockBalance BalanceType = "lock_balance" +) + +type UserSponsorBalanceDBModel struct { + model.BaseData + PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` + AvailableBalance *big.Float `gorm:"type:numeric(30,18)" json:"available_balance"` + LockBalance *big.Float `gorm:"type:numeric(30,18)" json:"lock_balance"` +} + +type DepositBalanceInput struct { + Source string + Signature string + Amount *big.Float + TxReceipt string +} + +func (UserSponsorBalanceDBModel) TableName() string { + return config.GetStrategyConfigTableName() +} + +type UserSponsorBalanceUpdateLogDBModel struct { + model.BaseData + Amount *big.Float `gorm:"type:numeric(30,18)" json:"amount"` + UpdateType UpdateType `gorm:"type:varchar(20)" json:"update_type"` +} + +func (UserSponsorBalanceUpdateLogDBModel) TableName() string { + return config.GetStrategyConfigTableName() +} + +//----------Functions---------- + +func GetAvailableBalance(userId string) (balance *big.Float, err error) { + balanceModel, err := getUserSponsorBalance(userId) + + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, xerrors.Errorf("No Balance Deposit Here ") + } + return nil, err + } + return balanceModel.AvailableBalance, nil +} + +func LockUserBalance(userId string, userOpHash []byte, network global_const.Network, + lockAmount *big.Float) (err error) { + balanceModel, err := getUserSponsorBalance(userId) + if errors.Is(err, gorm.ErrRecordNotFound) { + return xerrors.Errorf("No Balance Deposit Here ") + } + if err != nil { + return err + } + lockBalance := new(big.Float).Add(balanceModel.LockBalance, lockAmount) + availableBalance := new(big.Float).Sub(balanceModel.AvailableBalance, lockAmount) + balanceModel.LockBalance = lockBalance + balanceModel.AvailableBalance = availableBalance + tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).Updates(balanceModel) + if tx.Error != nil { + return tx.Error + } + + return nil +} + +func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, network global_const.Network, + actualGasCost *big.Float) (err error) { + //TODO + return nil +} +func ReleaseUserOpHashLock(userOpHash []byte) (err error) { + //TODO + return nil +} + +func DepositSponsorBalance(input *DepositBalanceInput) (err error) { + //TODO + return nil + +} + +func LogBalanceChange(balanceType BalanceType, data interface{}, amount *big.Float) (err error) { + //TODO + return nil +} + +func getUserSponsorBalance(userId string) (balanceModel *UserSponsorBalanceDBModel, err error) { + relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).First(&balanceModel) + return balanceModel, nil +} +func CreateSponsorBalance(userId string) (err error) { + //TODO + return nil +} From 2498654e00751eac29e125bbc010da519f0163ef Mon Sep 17 00:00:00 2001 From: dylanyang Date: Thu, 23 May 2024 17:39:37 +0800 Subject: [PATCH 14/23] add DB --- sponsor_manager/sponsor_balance_repository.go | 1 + .../sponsor_changelog_repository.go | 1 + sponsor_manager/sponsor_service.go | 42 +++++++++++++++---- 3 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 sponsor_manager/sponsor_balance_repository.go create mode 100644 sponsor_manager/sponsor_changelog_repository.go diff --git a/sponsor_manager/sponsor_balance_repository.go b/sponsor_manager/sponsor_balance_repository.go new file mode 100644 index 00000000..60e225ee --- /dev/null +++ b/sponsor_manager/sponsor_balance_repository.go @@ -0,0 +1 @@ +package sponsor_manager diff --git a/sponsor_manager/sponsor_changelog_repository.go b/sponsor_manager/sponsor_changelog_repository.go new file mode 100644 index 00000000..60e225ee --- /dev/null +++ b/sponsor_manager/sponsor_changelog_repository.go @@ -0,0 +1 @@ +package sponsor_manager diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go index 4458c41d..3acfeb19 100644 --- a/sponsor_manager/sponsor_service.go +++ b/sponsor_manager/sponsor_service.go @@ -54,6 +54,7 @@ type DepositBalanceInput struct { Signature string Amount *big.Float TxReceipt string + PayUserId string } func (UserSponsorBalanceDBModel) TableName() string { @@ -64,6 +65,7 @@ type UserSponsorBalanceUpdateLogDBModel struct { model.BaseData Amount *big.Float `gorm:"type:numeric(30,18)" json:"amount"` UpdateType UpdateType `gorm:"type:varchar(20)" json:"update_type"` + UserOpHash []byte `gorm:"type:bytea" json:"user_op_hash"` } func (UserSponsorBalanceUpdateLogDBModel) TableName() string { @@ -101,6 +103,7 @@ func LockUserBalance(userId string, userOpHash []byte, network global_const.Netw if tx.Error != nil { return tx.Error } + LogBalanceChange(LockBalance, userOpHash, lockAmount) return nil } @@ -110,27 +113,48 @@ func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, network glob //TODO return nil } + +type ReleaseUserOpHashLockInput struct { + UserOpHash []byte +} + func ReleaseUserOpHashLock(userOpHash []byte) (err error) { + // Get ChangeLog By UserOpHash //TODO return nil } func DepositSponsorBalance(input *DepositBalanceInput) (err error) { //TODO + balanceModel, err := getUserSponsorBalance(input.PayUserId) + if errors.Is(err, gorm.ErrRecordNotFound) { + balanceModel.AvailableBalance = input.Amount + balanceModel.PayUserId = input.PayUserId + balanceModel.LockBalance = big.NewFloat(0) + tx := relayDB.Create(&balanceModel) + if tx.Error != nil { + return tx.Error + } + } + if err != nil { + return err + } + newAvaileBalnce := new(big.Float).Add(balanceModel.AvailableBalance, input.Amount) + balanceModel.AvailableBalance = newAvaileBalnce + tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", input.PayUserId).Updates(balanceModel) + if tx.Error != nil { + return tx.Error + } + LogBalanceChange(AvailableBalance, input, input.Amount) return nil - } -func LogBalanceChange(balanceType BalanceType, data interface{}, amount *big.Float) (err error) { +func LogBalanceChange(balanceType BalanceType, data interface{}, amount *big.Float) { //TODO - return nil + return } func getUserSponsorBalance(userId string) (balanceModel *UserSponsorBalanceDBModel, err error) { - relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).First(&balanceModel) - return balanceModel, nil -} -func CreateSponsorBalance(userId string) (err error) { - //TODO - return nil + tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).First(&balanceModel) + return balanceModel, tx.Error } From e7cf691e2aac9cd1aa7b2ea4227d9096ad7e3292 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 24 May 2024 14:58:16 +0800 Subject: [PATCH 15/23] add Sponsor --- common/global_const/sponsor.go | 17 ++++ common/model/sponsor.go | 23 +++++ rpc_server/api/v1/sponsor.go | 99 +++++++++++++++++++ rpc_server/routers/routers_map.go | 12 ++- sponsor_manager/sponsor_balance_repository.go | 35 +++++++ .../sponsor_changelog_repository.go | 35 +++++++ sponsor_manager/sponsor_service.go | 98 ++++++++---------- 7 files changed, 257 insertions(+), 62 deletions(-) create mode 100644 common/global_const/sponsor.go create mode 100644 common/model/sponsor.go create mode 100644 rpc_server/api/v1/sponsor.go diff --git a/common/global_const/sponsor.go b/common/global_const/sponsor.go new file mode 100644 index 00000000..d632d893 --- /dev/null +++ b/common/global_const/sponsor.go @@ -0,0 +1,17 @@ +package global_const + +type UpdateType string + +const ( + UpdateTypeDeposit UpdateType = "deposit" + UpdateTypeLock UpdateType = "lock" + UpdateTypeWithdraw UpdateType = "withdraw" + UpdateTypeRelease UpdateType = "release" +) + +type BalanceType string + +const ( + BalanceTypeAvailableBalance BalanceType = "available_balance" + BalanceTypeLockBalance BalanceType = "lock_balance" +) diff --git a/common/model/sponsor.go b/common/model/sponsor.go new file mode 100644 index 00000000..16d130df --- /dev/null +++ b/common/model/sponsor.go @@ -0,0 +1,23 @@ +package model + +import "math/big" + +type DepositSponsorRequest struct { + Source string + Amount *big.Float + TxReceipt string + PayUserId string +} +type WithdrawSponsorRequest struct { + Source string + Amount *big.Float + TxReceipt string + PayUserId string +} +type GetSponsorTransactionsRequest struct { +} +type GetSponsorMetaDataRequest struct { +} + +type Transaction struct { +} diff --git a/rpc_server/api/v1/sponsor.go b/rpc_server/api/v1/sponsor.go new file mode 100644 index 00000000..bacbf8ec --- /dev/null +++ b/rpc_server/api/v1/sponsor.go @@ -0,0 +1,99 @@ +package v1 + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/sponsor_manager" + "errors" + "fmt" + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "net/http" +) + +// DepositSponsor +// @Tags Sponsor +// @Description Deposit Sponsor +// @Accept json +// @Product json +// @Param request body DepositSponsorRequest true "DepositSponsorRequest Model +// @Router /api/v1/paymaster_sponsor/deposit [post] +// @Success 200 +func DepositSponsor(ctx *gin.Context) { + request := model.DepositSponsorRequest{} + response := model.GetResponse() + if err := ctx.ShouldBindJSON(&request); err != nil { + errStr := fmt.Sprintf("Request Error [%v]", err) + response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, errStr) + return + } + //TODO Add Signature Verification + result, err := sponsor_manager.DepositSponsor(&request) + if err != nil { + response.SetHttpCode(http.StatusInternalServerError).FailCode(ctx, http.StatusInternalServerError, err.Error()) + return + } + response.WithDataSuccess(ctx, result) + return +} + +// WithdrawSponsor +// @Tags Sponsor +// @Description Withdraw Sponsor +// @Accept json +// @Product json +// @Param request body WithdrawSponsorRequest true "WithdrawSponsorRequest Model" +// @Router /api/v1/paymaster_sponsor/withdraw [post] +// @Success 200 +func WithdrawSponsor(ctx *gin.Context) { + request := model.WithdrawSponsorRequest{} + response := model.GetResponse() + if err := ctx.ShouldBindJSON(&request); err != nil { + errStr := fmt.Sprintf("Request Error [%v]", err) + response.SetHttpCode(http.StatusBadRequest).FailCode(ctx, http.StatusBadRequest, errStr) + return + } + //TODO Add Signature Verification + result, err := sponsor_manager.WithDrawSponsor(&request) + if err != nil { + response.SetHttpCode(http.StatusInternalServerError).FailCode(ctx, http.StatusInternalServerError, err.Error()) + return + } + response.WithDataSuccess(ctx, result) + return +} + +type SponsorDepositTransaction struct { + TxHash string `json:"tx_hash"` + Amount string `json:"amount"` + UpdateType global_const.UpdateType `json:"update_type"` +} + +// GetSponsorDepositAndWithdrawTransactions +// @Tags Sponsor +// @Description Get Sponsor Deposit And Withdraw Transactions +// @Accept json +// @Product json +// @Param userId path string true "User Id" +// @Router /api/v1/paymaster_sponsor/deposit_log +// @Success 200 +func GetSponsorDepositAndWithdrawTransactions(ctx *gin.Context) { + userId := ctx.Param("userId") + response := model.GetResponse() + models, err := sponsor_manager.GetDepositAndWithDrawLog(userId) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + response.FailCode(ctx, 301, "No Deposit Transactions") + } + } + trans := make([]SponsorDepositTransaction, 0) + for _, depositModel := range models { + tran := SponsorDepositTransaction{ + TxHash: depositModel.TxHash, + Amount: depositModel.Amount.String(), + } + trans = append(trans, tran) + } + response.WithDataSuccess(ctx, trans) + return +} diff --git a/rpc_server/routers/routers_map.go b/rpc_server/routers/routers_map.go index de13ba27..4d967f3a 100644 --- a/rpc_server/routers/routers_map.go +++ b/rpc_server/routers/routers_map.go @@ -13,12 +13,18 @@ func init() { PrivateRouterMaps = append(PrivateRouterMaps, RouterMap{string(Paymaster), []RestfulMethod{POST}, v1.Paymaster}) PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(Auth), []RestfulMethod{POST}, api.Auth}) PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(Healthz), []RestfulMethod{GET, HEAD, OPTIONS}, api.Healthz}) + PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(GetSponsorLog), []RestfulMethod{GET}, v1.GetSponsorDepositAndWithdrawTransactions}) + PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(DepositSponsor), []RestfulMethod{POST}, v1.DepositSponsor}) + PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(WithdrawSponsor), []RestfulMethod{POST}, v1.WithdrawSponsor}) } type Path string const ( - Auth Path = "api/auth" - Healthz Path = "api/healthz" - Paymaster Path = "api/v1/paymaster/:network" + Auth Path = "api/auth" + Healthz Path = "api/healthz" + Paymaster Path = "api/v1/paymaster/:network" + GetSponsorLog Path = "api/v1/paymaster_sponsor/deposit_log" + DepositSponsor Path = "api/v1/paymaster_sponsor/deposit" + WithdrawSponsor Path = "api/v1/paymaster_sponsor/withdraw" ) diff --git a/sponsor_manager/sponsor_balance_repository.go b/sponsor_manager/sponsor_balance_repository.go index 60e225ee..bb2d5ec3 100644 --- a/sponsor_manager/sponsor_balance_repository.go +++ b/sponsor_manager/sponsor_balance_repository.go @@ -1 +1,36 @@ package sponsor_manager + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/config" + "math/big" +) + +type UserSponsorBalanceDBModel struct { + model.BaseData + PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` + AvailableBalance *big.Float `gorm:"type:numeric(30,18)" json:"available_balance"` + LockBalance *big.Float `gorm:"type:numeric(30,18)" json:"lock_balance"` + Source string `gorm:"type:varchar(255)" json:"source"` + SponsorAddress string `gorm:"type:varchar(255)" json:"sponsor_address"` +} + +func (UserSponsorBalanceDBModel) TableName() string { + return config.GetStrategyConfigTableName() +} + +func CreateSponsorBalance(balanceModel *UserSponsorBalanceDBModel) error { + return relayDB.Create(balanceModel).Error +} +func FindUserSponsorBalance(userId string) (balanceModel *UserSponsorBalanceDBModel, err error) { + balanceModel = &UserSponsorBalanceDBModel{} + tx := relayDB.Where("pay_user_id = ?", userId).First(balanceModel) + if tx.Error != nil { + return nil, tx.Error + } + return balanceModel, nil +} +func UpdateSponsorBalance(balanceModel *UserSponsorBalanceDBModel) error { + tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", balanceModel.PayUserId).Updates(balanceModel) + return tx.Error +} diff --git a/sponsor_manager/sponsor_changelog_repository.go b/sponsor_manager/sponsor_changelog_repository.go index 60e225ee..a1d3abd5 100644 --- a/sponsor_manager/sponsor_changelog_repository.go +++ b/sponsor_manager/sponsor_changelog_repository.go @@ -1 +1,36 @@ package sponsor_manager + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/config" + "gorm.io/datatypes" + "math/big" +) + +type UserSponsorBalanceUpdateLogDBModel struct { + model.BaseData + PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` + Amount *big.Float `gorm:"type:numeric(30,18)" json:"amount"` + UpdateType global_const.UpdateType `gorm:"type:varchar(20)" json:"update_type"` + UserOpHash string `gorm:"type:varchar(255)" json:"user_op_hash"` + TxHash string `gorm:"type:varchar(255)" json:"tx_hash"` + TxInfo datatypes.JSON `gorm:"type:json" json:"tx_info"` + Source string `gorm:"type:varchar(255)" json:"source"` +} + +func (UserSponsorBalanceUpdateLogDBModel) TableName() string { + return config.GetStrategyConfigTableName() +} + +func LogBalanceChange(updateType global_const.UpdateType, balanceType global_const.BalanceType, data interface{}, amount *big.Float) { + //TODO + return +} +func GetDepositAndWithDrawLog(userId string) (models []*UserSponsorBalanceUpdateLogDBModel, err error) { + tx := relayDB.Model(&UserSponsorBalanceUpdateLogDBModel{}).Where("pay_user_id = ?", userId).Where("update_type = ?", global_const.UpdateTypeDeposit).Or("update_type = ?", global_const.UpdateTypeWithdraw).Find(&models) + if tx.Error != nil { + return nil, tx.Error + } + return models, nil +} diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go index 3acfeb19..364479c5 100644 --- a/sponsor_manager/sponsor_service.go +++ b/sponsor_manager/sponsor_service.go @@ -29,49 +29,6 @@ func Init() { }) } -type UpdateType string -type BalanceType string - -const ( - Deposit UpdateType = "deposit" - Lock UpdateType = "lock" - Withdraw UpdateType = "withdraw" - Release UpdateType = "release" - - AvailableBalance BalanceType = "available_balance" - LockBalance BalanceType = "lock_balance" -) - -type UserSponsorBalanceDBModel struct { - model.BaseData - PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` - AvailableBalance *big.Float `gorm:"type:numeric(30,18)" json:"available_balance"` - LockBalance *big.Float `gorm:"type:numeric(30,18)" json:"lock_balance"` -} - -type DepositBalanceInput struct { - Source string - Signature string - Amount *big.Float - TxReceipt string - PayUserId string -} - -func (UserSponsorBalanceDBModel) TableName() string { - return config.GetStrategyConfigTableName() -} - -type UserSponsorBalanceUpdateLogDBModel struct { - model.BaseData - Amount *big.Float `gorm:"type:numeric(30,18)" json:"amount"` - UpdateType UpdateType `gorm:"type:varchar(20)" json:"update_type"` - UserOpHash []byte `gorm:"type:bytea" json:"user_op_hash"` -} - -func (UserSponsorBalanceUpdateLogDBModel) TableName() string { - return config.GetStrategyConfigTableName() -} - //----------Functions---------- func GetAvailableBalance(userId string) (balance *big.Float, err error) { @@ -103,8 +60,7 @@ func LockUserBalance(userId string, userOpHash []byte, network global_const.Netw if tx.Error != nil { return tx.Error } - LogBalanceChange(LockBalance, userOpHash, lockAmount) - + LogBalanceChange(global_const.UpdateTypeLock, global_const.BalanceTypeLockBalance, userOpHash, lockAmount) return nil } @@ -124,37 +80,61 @@ func ReleaseUserOpHashLock(userOpHash []byte) (err error) { return nil } -func DepositSponsorBalance(input *DepositBalanceInput) (err error) { +func getUserSponsorBalance(userId string) (balanceModel *UserSponsorBalanceDBModel, err error) { + tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).First(&balanceModel) + return balanceModel, tx.Error +} + +//----------Functions---------- + +func DepositSponsor(input *model.DepositSponsorRequest) (balanceModel *UserSponsorBalanceDBModel, err error) { //TODO - balanceModel, err := getUserSponsorBalance(input.PayUserId) + balanceModel, err = FindUserSponsorBalance(input.PayUserId) if errors.Is(err, gorm.ErrRecordNotFound) { balanceModel.AvailableBalance = input.Amount balanceModel.PayUserId = input.PayUserId balanceModel.LockBalance = big.NewFloat(0) tx := relayDB.Create(&balanceModel) if tx.Error != nil { - return tx.Error + return nil, tx.Error } } if err != nil { - return err + return nil, err } - newAvaileBalnce := new(big.Float).Add(balanceModel.AvailableBalance, input.Amount) - balanceModel.AvailableBalance = newAvaileBalnce + newAvailableBalance := new(big.Float).Add(balanceModel.AvailableBalance, input.Amount) + balanceModel.AvailableBalance = newAvailableBalance tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", input.PayUserId).Updates(balanceModel) if tx.Error != nil { - return tx.Error + return nil, tx.Error } - LogBalanceChange(AvailableBalance, input, input.Amount) - return nil + LogBalanceChange(global_const.UpdateTypeDeposit, global_const.BalanceTypeAvailableBalance, input, input.Amount) + return balanceModel, nil } -func LogBalanceChange(balanceType BalanceType, data interface{}, amount *big.Float) { +func WithDrawSponsor(input *model.WithdrawSponsorRequest) (balanceModel *UserSponsorBalanceDBModel, err error) { + balanceModel, err = FindUserSponsorBalance(input.PayUserId) + if err != nil { + return nil, err + } + if balanceModel.AvailableBalance.Cmp(input.Amount) < 0 { + return nil, xerrors.Errorf("Insufficient balance [%s] not Enough to Withdraw [%s]", balanceModel.AvailableBalance.String(), input.Amount.String()) + } + newAvailableBalance := new(big.Float).Sub(balanceModel.AvailableBalance, input.Amount) + balanceModel.AvailableBalance = newAvailableBalance + err = UpdateSponsorBalance(balanceModel) + if err != nil { + return nil, err + } + LogBalanceChange(global_const.UpdateTypeWithdraw, global_const.BalanceTypeAvailableBalance, input, input.Amount) + return balanceModel, nil +} +func GetSponsorTransactionList() (err error) { //TODO - return + return nil } -func getUserSponsorBalance(userId string) (balanceModel *UserSponsorBalanceDBModel, err error) { - tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).First(&balanceModel) - return balanceModel, tx.Error +func GetSponsorMetaData() (err error) { + //TODO + return nil } From 499de5e72561beb439393de2d6663486ddd5c696 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Fri, 24 May 2024 16:36:04 +0800 Subject: [PATCH 16/23] update Sponsor --- cmd/server/main.go | 2 + common/global_const/pay_type.go | 3 +- common/model/api_response.go | 5 +- common/model/sponsor.go | 2 + .../paymaster_data_generate.go | 2 +- config/config_test.go | 2 +- gas_executor/gas_validate.go | 2 +- rpc_server/api/v1/sponsor.go | 43 +++++++++++++++- .../dashboard_service/dashboard_service.go | 4 +- service/operator/try_pay_user_op_execute.go | 13 ++--- sponsor_manager/sponsor_balance_repository.go | 13 +++-- .../sponsor_changelog_repository.go | 5 +- sponsor_manager/sponsor_service.go | 51 +++++++------------ 13 files changed, 92 insertions(+), 55 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 28a5ffbc..97475641 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -5,6 +5,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/envirment" "AAStarCommunity/EthPaymaster_BackService/rpc_server/routers" "AAStarCommunity/EthPaymaster_BackService/service/dashboard_service" + "AAStarCommunity/EthPaymaster_BackService/sponsor_manager" "flag" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" @@ -69,6 +70,7 @@ func initEngine(strategyPath string, basicConfigPath string, secretPath string) logrus.SetLevel(logrus.InfoLevel) } dashboard_service.Init() + sponsor_manager.Init() logrus.Infof("Environment: %s", envirment.Environment.Name) logrus.Infof("Debugger: %v", envirment.Environment.Debugger) Engine = routers.SetRouters() diff --git a/common/global_const/pay_type.go b/common/global_const/pay_type.go index 46228e12..02a17ecf 100644 --- a/common/global_const/pay_type.go +++ b/common/global_const/pay_type.go @@ -3,7 +3,8 @@ package global_const type PayType string const ( - PayTypeVerifying PayType = "PayTypeVerifying" + PayTypeProjectSponsor PayType = "PayTypeProjectSponsor" PayTypeERC20 PayType = "PayTypeERC20" PayTypeSuperVerifying PayType = "PayTypeSuperVerifying" + PayTypeUserSponsor PayType = "PayTypeUserSponsor" ) diff --git a/common/model/api_response.go b/common/model/api_response.go index f60390f7..2fd4dff8 100644 --- a/common/model/api_response.go +++ b/common/model/api_response.go @@ -49,9 +49,8 @@ type UserOpEstimateGas struct { PaymasterPostOpGasLimit *big.Int `json:"paymasterPostOpGasLimit" binding:"required"` GasFees *[32]byte `json:"gasFees" binding:"required"` } -type PayReceipt struct { - TransactionHash string `json:"transaction_hash"` - Sponsor string `json:"sponsor"` +type PayResponse struct { + PayType global_const.PayType `json:"pay_type"` } type GetSupportEntryPointResponse struct { diff --git a/common/model/sponsor.go b/common/model/sponsor.go index 16d130df..b321aacd 100644 --- a/common/model/sponsor.go +++ b/common/model/sponsor.go @@ -7,12 +7,14 @@ type DepositSponsorRequest struct { Amount *big.Float TxReceipt string PayUserId string + IsTestNet bool } type WithdrawSponsorRequest struct { Source string Amount *big.Float TxReceipt string PayUserId string + IsTestNet bool } type GetSponsorTransactionsRequest struct { } diff --git a/common/paymaster_pay_type/paymaster_data_generate.go b/common/paymaster_pay_type/paymaster_data_generate.go index c8414179..ebc08ebc 100644 --- a/common/paymaster_pay_type/paymaster_data_generate.go +++ b/common/paymaster_pay_type/paymaster_data_generate.go @@ -38,7 +38,7 @@ var basicPaymasterDataFunc = func(data *paymaster_data.PaymasterDataInput, signa } func init() { - paymasterDataFuncMap[global_const.PayTypeVerifying] = basicPaymasterDataFunc + paymasterDataFuncMap[global_const.PayTypeProjectSponsor] = basicPaymasterDataFunc paymasterDataFuncMap[global_const.PayTypeERC20] = basicPaymasterDataFunc paymasterDataFuncMap[global_const.PayTypeSuperVerifying] = func(data *paymaster_data.PaymasterDataInput, signature []byte) ([]byte, error) { packed, err := BasicPaymasterDataAbiV06.Pack(data.ValidUntil, data.ValidAfter, data.ERC20Token, data.ExchangeRate) diff --git a/config/config_test.go b/config/config_test.go index 1684e669..485e25b2 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -25,7 +25,7 @@ func TestConfigInit(t *testing.T) { t.Error("strategy is nil") return } - strategySuit, err := GetSuitableStrategy(global_const.EntrypointV06, global_const.EthereumSepolia, global_const.PayTypeVerifying) + strategySuit, err := GetSuitableStrategy(global_const.EntrypointV06, global_const.EthereumSepolia, global_const.PayTypeProjectSponsor) if err != nil { t.Error("strategySuit is nil") diff --git a/gas_executor/gas_validate.go b/gas_executor/gas_validate.go index 06fdc274..c8790d45 100644 --- a/gas_executor/gas_validate.go +++ b/gas_executor/gas_validate.go @@ -50,7 +50,7 @@ var ( ) func init() { - gasValidateFuncMap[global_const.PayTypeVerifying] = verifyingGasValidateFunc + gasValidateFuncMap[global_const.PayTypeProjectSponsor] = verifyingGasValidateFunc gasValidateFuncMap[global_const.PayTypeERC20] = erc20GasValidateFunc gasValidateFuncMap[global_const.PayTypeSuperVerifying] = superGasValidateFunc } diff --git a/rpc_server/api/v1/sponsor.go b/rpc_server/api/v1/sponsor.go index bacbf8ec..fe4c09af 100644 --- a/rpc_server/api/v1/sponsor.go +++ b/rpc_server/api/v1/sponsor.go @@ -9,6 +9,7 @@ import ( "github.com/gin-gonic/gin" "gorm.io/gorm" "net/http" + "strconv" ) // DepositSponsor @@ -17,6 +18,7 @@ import ( // @Accept json // @Product json // @Param request body DepositSponsorRequest true "DepositSponsorRequest Model +// @Param is_test_net path boolean true "Is Test Net" // @Router /api/v1/paymaster_sponsor/deposit [post] // @Success 200 func DepositSponsor(ctx *gin.Context) { @@ -43,6 +45,7 @@ func DepositSponsor(ctx *gin.Context) { // @Accept json // @Product json // @Param request body WithdrawSponsorRequest true "WithdrawSponsorRequest Model" +// @Param is_test_net path boolean true "Is Test Net" // @Router /api/v1/paymaster_sponsor/withdraw [post] // @Success 200 func WithdrawSponsor(ctx *gin.Context) { @@ -75,12 +78,16 @@ type SponsorDepositTransaction struct { // @Accept json // @Product json // @Param userId path string true "User Id" +// @Param is_test_net path boolean true "Is Test Net" // @Router /api/v1/paymaster_sponsor/deposit_log // @Success 200 func GetSponsorDepositAndWithdrawTransactions(ctx *gin.Context) { - userId := ctx.Param("userId") + userId := ctx.Param("user_id") + textNet := ctx.Param("is_test_net") + // convertTOBool + isTestNet, _ := strconv.ParseBool(textNet) response := model.GetResponse() - models, err := sponsor_manager.GetDepositAndWithDrawLog(userId) + models, err := sponsor_manager.GetDepositAndWithDrawLog(userId, isTestNet) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { response.FailCode(ctx, 301, "No Deposit Transactions") @@ -97,3 +104,35 @@ func GetSponsorDepositAndWithdrawTransactions(ctx *gin.Context) { response.WithDataSuccess(ctx, trans) return } + +type SponsorMetaResponse struct { + AvailableBalance string `json:"available_balance"` + SponsorAddress string `json:"sponsor_address"` +} + +// GetSponsorMetaData +// @Tags Sponsor +// @Description Get Sponsor Balance +// @Accept json +// @Product json +// @Param userId path string true "User Id" +// @Router /api/v1/paymaster_sponsor/balance/{userId} +// @Success 200 +func GetSponsorMetaData(ctx *gin.Context) { + userId := ctx.Param("userId") + textNet := ctx.Param("is_test_net") + isTestNet, _ := strconv.ParseBool(textNet) + response := model.GetResponse() + balance, err := sponsor_manager.FindUserSponsorBalance(userId, isTestNet) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + response.FailCode(ctx, 301, "No Balance") + } + } + result := SponsorMetaResponse{ + AvailableBalance: balance.AvailableBalance.String(), + SponsorAddress: balance.SponsorAddress, + } + response.WithDataSuccess(ctx, result) + return +} diff --git a/service/dashboard_service/dashboard_service.go b/service/dashboard_service/dashboard_service.go index 31fc45d9..615a00d1 100644 --- a/service/dashboard_service/dashboard_service.go +++ b/service/dashboard_service/dashboard_service.go @@ -142,7 +142,7 @@ func convertStrategyDBModelToStrategy(strategyDBModel *StrategyDBModel, entryPoi }, PaymasterInfo: &model.PaymasterInfo{ PayMasterAddress: config.GetPaymasterAddress(network, entryPointVersion), - PayType: global_const.PayTypeVerifying, + PayType: global_const.PayTypeProjectSponsor, IsProjectErc20PayEnable: false, }, ExecuteRestriction: strategyExecuteRestriction, @@ -171,7 +171,7 @@ func GetSuitableStrategy(entryPointVersion global_const.EntrypointVersion, chain gasToken := config.GetGasToken(chain) entryPointAddress := config.GetEntrypointAddress(chain, entryPointVersion) paymasterAddress := config.GetPaymasterAddress(chain, entryPointVersion) - payType := global_const.PayTypeVerifying + payType := global_const.PayTypeUserSponsor isPerc20Enable := false if gasUseToken != "" { payType = global_const.PayTypeERC20 diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 8eed061a..f42f69d7 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -92,7 +92,7 @@ func ValidateGas(userOp *user_op.UserOpInput, gasComputeResponse *model.ComputeG return nil } -func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { +func executePay(input *ExecutePayInput) (*model.PayResponse, error) { if input.PayType == global_const.PayTypeERC20 { logrus.Debugf("Not Need ExecutePay In ERC20 PayType") return nil, nil @@ -101,6 +101,7 @@ func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { logrus.Debugf("Not Need ExecutePay In SponsorWhitelist [%s]", input.UserOpSender) return nil, nil } + // TODO //if config.IsTestNet(input.Network) { // logrus.Debugf("Not Need ExecutePay In TestNet [%s]", input.Network) // return nil, nil @@ -112,7 +113,8 @@ func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { } else { payUserKey = input.UserOpSender } - depositBalance, err := sponsor_manager.GetAvailableBalance(payUserKey) + isTestNet := config.IsTestNet(input.Network) + depositBalance, err := sponsor_manager.GetAvailableBalance(payUserKey, isTestNet) if err != nil { return nil, err } @@ -124,15 +126,14 @@ func executePay(input *ExecutePayInput) (*model.PayReceipt, error) { return nil, xerrors.Errorf("Insufficient balance [%s] not Enough to Pay Cost [%s]", depositBalance.String(), gasUsdCost.String()) } //Lock Deposit Balance - err = sponsor_manager.LockUserBalance(payUserKey, input.UserOpHash, input.Network, + err = sponsor_manager.LockUserBalance(payUserKey, input.UserOpHash, isTestNet, gasUsdCost) if err != nil { return nil, err } - return &model.PayReceipt{ - TransactionHash: "0x110406d44ec1681fcdab1df2310181dee26ff43c37167b2c9c496b35cce69437", - Sponsor: "aastar", + return &model.PayResponse{ + PayType: input.PayType, }, nil } diff --git a/sponsor_manager/sponsor_balance_repository.go b/sponsor_manager/sponsor_balance_repository.go index bb2d5ec3..4886a4b2 100644 --- a/sponsor_manager/sponsor_balance_repository.go +++ b/sponsor_manager/sponsor_balance_repository.go @@ -13,6 +13,7 @@ type UserSponsorBalanceDBModel struct { LockBalance *big.Float `gorm:"type:numeric(30,18)" json:"lock_balance"` Source string `gorm:"type:varchar(255)" json:"source"` SponsorAddress string `gorm:"type:varchar(255)" json:"sponsor_address"` + IsTestNet bool `gorm:"type:boolean" json:"is_test_net"` } func (UserSponsorBalanceDBModel) TableName() string { @@ -22,15 +23,19 @@ func (UserSponsorBalanceDBModel) TableName() string { func CreateSponsorBalance(balanceModel *UserSponsorBalanceDBModel) error { return relayDB.Create(balanceModel).Error } -func FindUserSponsorBalance(userId string) (balanceModel *UserSponsorBalanceDBModel, err error) { +func FindUserSponsorBalance(userId string, isTestNet bool) (balanceModel *UserSponsorBalanceDBModel, err error) { balanceModel = &UserSponsorBalanceDBModel{} - tx := relayDB.Where("pay_user_id = ?", userId).First(balanceModel) + tx := relayDB.Where("pay_user_id = ?", userId).Where("is_test_net = ?", isTestNet).First(balanceModel) if tx.Error != nil { return nil, tx.Error } return balanceModel, nil } -func UpdateSponsorBalance(balanceModel *UserSponsorBalanceDBModel) error { - tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", balanceModel.PayUserId).Updates(balanceModel) +func UpdateSponsor(balanceModel *UserSponsorBalanceDBModel, isTestNet bool) error { + tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", balanceModel.PayUserId).Where("is_test_net = ?", isTestNet).Updates(balanceModel) return tx.Error } +func getUserSponsorBalance(userId string, isTestNet bool) (balanceModel *UserSponsorBalanceDBModel, err error) { + tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", isTestNet).First(&balanceModel) + return balanceModel, tx.Error +} diff --git a/sponsor_manager/sponsor_changelog_repository.go b/sponsor_manager/sponsor_changelog_repository.go index a1d3abd5..a17197d0 100644 --- a/sponsor_manager/sponsor_changelog_repository.go +++ b/sponsor_manager/sponsor_changelog_repository.go @@ -17,6 +17,7 @@ type UserSponsorBalanceUpdateLogDBModel struct { TxHash string `gorm:"type:varchar(255)" json:"tx_hash"` TxInfo datatypes.JSON `gorm:"type:json" json:"tx_info"` Source string `gorm:"type:varchar(255)" json:"source"` + IsTestNet bool `gorm:"type:boolean" json:"is_test_net"` } func (UserSponsorBalanceUpdateLogDBModel) TableName() string { @@ -27,8 +28,8 @@ func LogBalanceChange(updateType global_const.UpdateType, balanceType global_con //TODO return } -func GetDepositAndWithDrawLog(userId string) (models []*UserSponsorBalanceUpdateLogDBModel, err error) { - tx := relayDB.Model(&UserSponsorBalanceUpdateLogDBModel{}).Where("pay_user_id = ?", userId).Where("update_type = ?", global_const.UpdateTypeDeposit).Or("update_type = ?", global_const.UpdateTypeWithdraw).Find(&models) +func GetDepositAndWithDrawLog(userId string, IsTestNet bool) (models []*UserSponsorBalanceUpdateLogDBModel, err error) { + tx := relayDB.Model(&UserSponsorBalanceUpdateLogDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", IsTestNet).Where("update_type = ?", global_const.UpdateTypeDeposit).Or("update_type = ?", global_const.UpdateTypeWithdraw).Find(&models) if tx.Error != nil { return nil, tx.Error } diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go index 364479c5..793adce2 100644 --- a/sponsor_manager/sponsor_service.go +++ b/sponsor_manager/sponsor_service.go @@ -31,8 +31,8 @@ func Init() { //----------Functions---------- -func GetAvailableBalance(userId string) (balance *big.Float, err error) { - balanceModel, err := getUserSponsorBalance(userId) +func GetAvailableBalance(userId string, isTestNet bool) (balance *big.Float, err error) { + balanceModel, err := getUserSponsorBalance(userId, isTestNet) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -43,9 +43,11 @@ func GetAvailableBalance(userId string) (balance *big.Float, err error) { return balanceModel.AvailableBalance, nil } -func LockUserBalance(userId string, userOpHash []byte, network global_const.Network, +// LockUserBalance +// Reduce AvailableBalance and Increase LockBalance +func LockUserBalance(userId string, userOpHash []byte, isTestNet bool, lockAmount *big.Float) (err error) { - balanceModel, err := getUserSponsorBalance(userId) + balanceModel, err := getUserSponsorBalance(userId, isTestNet) if errors.Is(err, gorm.ErrRecordNotFound) { return xerrors.Errorf("No Balance Deposit Here ") } @@ -56,9 +58,9 @@ func LockUserBalance(userId string, userOpHash []byte, network global_const.Netw availableBalance := new(big.Float).Sub(balanceModel.AvailableBalance, lockAmount) balanceModel.LockBalance = lockBalance balanceModel.AvailableBalance = availableBalance - tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).Updates(balanceModel) - if tx.Error != nil { - return tx.Error + err = UpdateSponsor(balanceModel, isTestNet) + if err != nil { + return err } LogBalanceChange(global_const.UpdateTypeLock, global_const.BalanceTypeLockBalance, userOpHash, lockAmount) return nil @@ -76,27 +78,21 @@ type ReleaseUserOpHashLockInput struct { func ReleaseUserOpHashLock(userOpHash []byte) (err error) { // Get ChangeLog By UserOpHash - //TODO return nil } -func getUserSponsorBalance(userId string) (balanceModel *UserSponsorBalanceDBModel, err error) { - tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).First(&balanceModel) - return balanceModel, tx.Error -} - //----------Functions---------- func DepositSponsor(input *model.DepositSponsorRequest) (balanceModel *UserSponsorBalanceDBModel, err error) { - //TODO - balanceModel, err = FindUserSponsorBalance(input.PayUserId) + balanceModel, err = FindUserSponsorBalance(input.PayUserId, input.IsTestNet) if errors.Is(err, gorm.ErrRecordNotFound) { balanceModel.AvailableBalance = input.Amount balanceModel.PayUserId = input.PayUserId balanceModel.LockBalance = big.NewFloat(0) - tx := relayDB.Create(&balanceModel) - if tx.Error != nil { - return nil, tx.Error + balanceModel.IsTestNet = input.IsTestNet + err = CreateSponsorBalance(balanceModel) + if err != nil { + return nil, err } } if err != nil { @@ -104,16 +100,16 @@ func DepositSponsor(input *model.DepositSponsorRequest) (balanceModel *UserSpons } newAvailableBalance := new(big.Float).Add(balanceModel.AvailableBalance, input.Amount) balanceModel.AvailableBalance = newAvailableBalance - tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", input.PayUserId).Updates(balanceModel) - if tx.Error != nil { - return nil, tx.Error + err = UpdateSponsor(balanceModel, input.IsTestNet) + if err != nil { + return nil, err } LogBalanceChange(global_const.UpdateTypeDeposit, global_const.BalanceTypeAvailableBalance, input, input.Amount) return balanceModel, nil } func WithDrawSponsor(input *model.WithdrawSponsorRequest) (balanceModel *UserSponsorBalanceDBModel, err error) { - balanceModel, err = FindUserSponsorBalance(input.PayUserId) + balanceModel, err = FindUserSponsorBalance(input.PayUserId, input.IsTestNet) if err != nil { return nil, err } @@ -122,19 +118,10 @@ func WithDrawSponsor(input *model.WithdrawSponsorRequest) (balanceModel *UserSpo } newAvailableBalance := new(big.Float).Sub(balanceModel.AvailableBalance, input.Amount) balanceModel.AvailableBalance = newAvailableBalance - err = UpdateSponsorBalance(balanceModel) + err = UpdateSponsor(balanceModel, input.IsTestNet) if err != nil { return nil, err } LogBalanceChange(global_const.UpdateTypeWithdraw, global_const.BalanceTypeAvailableBalance, input, input.Amount) return balanceModel, nil } -func GetSponsorTransactionList() (err error) { - //TODO - return nil -} - -func GetSponsorMetaData() (err error) { - //TODO - return nil -} From 3f6e98e16ad3ae4fbd575e82dc46cad0e0ab3425 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 27 May 2024 18:04:48 +0800 Subject: [PATCH 17/23] update Sponsor --- common/model/sponsor.go | 15 +- .../ethereum_adaptable_executor_test.go | 10 +- common/utils/util.go | 2 +- common/utils/util_test.go | 2 +- rpc_server/routers/routers_map.go | 2 + schedulor/UserOpEventListener.go | 2 +- service/operator/try_pay_user_op_execute.go | 6 +- sponsor_manager/sponsor_balance_repository.go | 59 +++++++- .../sponsor_changelog_repository.go | 37 ++++- sponsor_manager/sponsor_service.go | 129 ++++++++++++++++-- sponsor_manager/sponsor_test.go | 53 +++++++ 11 files changed, 284 insertions(+), 33 deletions(-) create mode 100644 sponsor_manager/sponsor_test.go diff --git a/common/model/sponsor.go b/common/model/sponsor.go index b321aacd..1be53091 100644 --- a/common/model/sponsor.go +++ b/common/model/sponsor.go @@ -3,18 +3,21 @@ package model import "math/big" type DepositSponsorRequest struct { - Source string - Amount *big.Float - TxReceipt string + Source string + Amount *big.Float + TxHash string + + TxInfo map[string]string PayUserId string IsTestNet bool } type WithdrawSponsorRequest struct { - Source string - Amount *big.Float - TxReceipt string + Amount *big.Float + PayUserId string IsTestNet bool + TxInfo map[string]string + TxHash string } type GetSponsorTransactionsRequest struct { } diff --git a/common/network/ethereum_adaptable_executor_test.go b/common/network/ethereum_adaptable_executor_test.go index 379ee7ff..07e01441 100644 --- a/common/network/ethereum_adaptable_executor_test.go +++ b/common/network/ethereum_adaptable_executor_test.go @@ -338,12 +338,12 @@ func parseOpToMapV7(input user_op.UserOpInput) map[string]string { opMap := make(map[string]string) opMap["sender"] = input.Sender.String() opMap["Nonce"] = input.Nonce.String() - opMap["initCode"] = utils.EncodeToStringWithPrefix(input.InitCode[:]) - opMap["accountGasLimits"] = utils.EncodeToStringWithPrefix(input.AccountGasLimits[:]) + opMap["initCode"] = utils.EncodeToHexStringWithPrefix(input.InitCode[:]) + opMap["accountGasLimits"] = utils.EncodeToHexStringWithPrefix(input.AccountGasLimits[:]) opMap["preVerificationGas"] = input.PreVerificationGas.String() - opMap["gasFees"] = utils.EncodeToStringWithPrefix(input.GasFees[:]) - opMap["paymasterAndData"] = utils.EncodeToStringWithPrefix(input.PaymasterAndData[:]) - opMap["signature"] = utils.EncodeToStringWithPrefix(input.Signature[:]) + opMap["gasFees"] = utils.EncodeToHexStringWithPrefix(input.GasFees[:]) + opMap["paymasterAndData"] = utils.EncodeToHexStringWithPrefix(input.PaymasterAndData[:]) + opMap["signature"] = utils.EncodeToHexStringWithPrefix(input.Signature[:]) return opMap } diff --git a/common/utils/util.go b/common/utils/util.go index 246ae7ad..6dada604 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -97,7 +97,7 @@ func GetGasEntryPointGasPrice(maxFeePerGas *big.Int, maxPriorityFeePerGas *big.I return GetMinValue(maxFeePerGas, combineFee) } -func EncodeToStringWithPrefix(data []byte) string { +func EncodeToHexStringWithPrefix(data []byte) string { res := hex.EncodeToString(data) if res[:2] != "0x" { return "0x" + res diff --git a/common/utils/util_test.go b/common/utils/util_test.go index 1445a1b2..cb9d0f4d 100644 --- a/common/utils/util_test.go +++ b/common/utils/util_test.go @@ -41,7 +41,7 @@ func TestPackIntTo32Bytes(t *testing.T) { bytes := PackIntTo32Bytes(big.NewInt(2312), big.NewInt(2312)) - resStr := EncodeToStringWithPrefix(bytes[:]) + resStr := EncodeToHexStringWithPrefix(bytes[:]) t.Logf("resStr: %s\n", resStr) } diff --git a/rpc_server/routers/routers_map.go b/rpc_server/routers/routers_map.go index 4d967f3a..5e4f7c56 100644 --- a/rpc_server/routers/routers_map.go +++ b/rpc_server/routers/routers_map.go @@ -16,6 +16,7 @@ func init() { PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(GetSponsorLog), []RestfulMethod{GET}, v1.GetSponsorDepositAndWithdrawTransactions}) PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(DepositSponsor), []RestfulMethod{POST}, v1.DepositSponsor}) PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(WithdrawSponsor), []RestfulMethod{POST}, v1.WithdrawSponsor}) + PublicRouterMaps = append(PublicRouterMaps, RouterMap{string(GetSponsorData), []RestfulMethod{GET}, v1.GetSponsorMetaData}) } type Path string @@ -27,4 +28,5 @@ const ( GetSponsorLog Path = "api/v1/paymaster_sponsor/deposit_log" DepositSponsor Path = "api/v1/paymaster_sponsor/deposit" WithdrawSponsor Path = "api/v1/paymaster_sponsor/withdraw" + GetSponsorData Path = "api/v1/paymaster_sponsor/data" ) diff --git a/schedulor/UserOpEventListener.go b/schedulor/UserOpEventListener.go index e264c94f..289e35b7 100644 --- a/schedulor/UserOpEventListener.go +++ b/schedulor/UserOpEventListener.go @@ -73,7 +73,7 @@ func UserOpEventComunicate(network global_const.Network, event ContractUserOpera return } if !event.Success { - err := sponsor_manager.ReleaseUserOpHashLock(event.UserOpHash[:]) + err := sponsor_manager.ReleaseUserOpHashLock(event.UserOpHash[:], true) if err != nil { logrus.Errorf("ReleaseUserOpHashLock failed: %v", err) } diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index f42f69d7..1072ac8e 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -179,7 +179,7 @@ func postExecute(apiKeyModel *model.ApiKeyModel, userOp *user_op.UserOpInput, st Erc20TokenCost: gasResponse.Erc20TokenCost, UserOpResponse: &model.UserOpResponse{ - PayMasterAndData: utils.EncodeToStringWithPrefix(paymasterData), + PayMasterAndData: utils.EncodeToHexStringWithPrefix(paymasterData), PreVerificationGas: gasResponse.OpEstimateGas.PreVerificationGas, MaxFeePerGas: gasResponse.OpEstimateGas.MaxFeePerGas, MaxPriorityFeePerGas: gasResponse.OpEstimateGas.MaxPriorityFeePerGas, @@ -189,8 +189,8 @@ func postExecute(apiKeyModel *model.ApiKeyModel, userOp *user_op.UserOpInput, st } if strategy.GetStrategyEntrypointVersion() == global_const.EntrypointV07 { - result.UserOpResponse.AccountGasLimit = utils.EncodeToStringWithPrefix(gasResponse.OpEstimateGas.AccountGasLimit[:]) - result.UserOpResponse.GasFees = utils.EncodeToStringWithPrefix(gasResponse.OpEstimateGas.GasFees[:]) + result.UserOpResponse.AccountGasLimit = utils.EncodeToHexStringWithPrefix(gasResponse.OpEstimateGas.AccountGasLimit[:]) + result.UserOpResponse.GasFees = utils.EncodeToHexStringWithPrefix(gasResponse.OpEstimateGas.GasFees[:]) result.UserOpResponse.PaymasterVerificationGasLimit = gasResponse.OpEstimateGas.PaymasterVerificationGasLimit result.UserOpResponse.PaymasterPostOpGasLimit = gasResponse.OpEstimateGas.PaymasterPostOpGasLimit } diff --git a/sponsor_manager/sponsor_balance_repository.go b/sponsor_manager/sponsor_balance_repository.go index 4886a4b2..6f0353f7 100644 --- a/sponsor_manager/sponsor_balance_repository.go +++ b/sponsor_manager/sponsor_balance_repository.go @@ -2,7 +2,7 @@ package sponsor_manager import ( "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/config" + "fmt" "math/big" ) @@ -17,7 +17,7 @@ type UserSponsorBalanceDBModel struct { } func (UserSponsorBalanceDBModel) TableName() string { - return config.GetStrategyConfigTableName() + return "relay_user_sponsor_balance" } func CreateSponsorBalance(balanceModel *UserSponsorBalanceDBModel) error { @@ -39,3 +39,58 @@ func getUserSponsorBalance(userId string, isTestNet bool) (balanceModel *UserSpo tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", isTestNet).First(&balanceModel) return balanceModel, tx.Error } + +// BigFloat wraps big.Float to implement sql.Scanner +type BigFloat struct { + *big.Float +} + +// Scan implements the sql.Scanner interface for BigFloat +func (b *BigFloat) Scan(value interface{}) error { + if b == nil { + fmt.Println("BigFloat Scan value is nil") + return nil + } + fmt.Println("BigFloat Scan value", value) + switch v := value.(type) { + case string: + + if _, ok := b.SetString(v); !ok { + return fmt.Errorf("failed to parse string as *big.Float: %s", v) + } + case []byte: + fmt.Println("BigFloat Scan value Case Byte", value) + + if _, ok := b.SetString(string(v)); !ok { + return fmt.Errorf("failed to parse byte slice as *big.Float: %s", string(v)) + } + default: + return fmt.Errorf("unsupported type: %T", v) + } + return nil +} + +func SelectUserSponsorBalanceDBModelWithScanList() (userSponsorBalanceDBModelWithScanList []UserSponsorBalanceDBModelWithScan, err error) { + userSponsorBalanceDBModelWithScanList = make([]UserSponsorBalanceDBModelWithScan, 0) + tx := relayDB.Model(&UserSponsorBalanceDBModelWithScan{}).Find(&userSponsorBalanceDBModelWithScanList) + if tx.Error != nil { + err = tx.Error + return + } + fmt.Println(userSponsorBalanceDBModelWithScanList) + return userSponsorBalanceDBModelWithScanList, nil +} + +type UserSponsorBalanceDBModelWithScan struct { + model.BaseData + PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` + AvailableBalance float64 `gorm:"type:numeric(30,18)" json:"available_balance"` + LockBalance float64 `gorm:"type:numeric(30,18)" json:"lock_balance"` + Source string `gorm:"type:varchar(255)" json:"source"` + SponsorAddress string `gorm:"type:varchar(255)" json:"sponsor_address"` + IsTestNet bool `gorm:"type:boolean" json:"is_test_net"` +} + +func (UserSponsorBalanceDBModelWithScan) TableName() string { + return "relay_user_sponsor_balance" +} diff --git a/sponsor_manager/sponsor_changelog_repository.go b/sponsor_manager/sponsor_changelog_repository.go index a17197d0..b9dcba4f 100644 --- a/sponsor_manager/sponsor_changelog_repository.go +++ b/sponsor_manager/sponsor_changelog_repository.go @@ -3,7 +3,6 @@ package sponsor_manager import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/common/model" - "AAStarCommunity/EthPaymaster_BackService/config" "gorm.io/datatypes" "math/big" ) @@ -21,10 +20,14 @@ type UserSponsorBalanceUpdateLogDBModel struct { } func (UserSponsorBalanceUpdateLogDBModel) TableName() string { - return config.GetStrategyConfigTableName() + return "relay_user_sponsor_balance_update_log" } +func AddBalanceChangeLog(changeDbModel *UserSponsorBalanceUpdateLogDBModel) error { + return relayDB.Create(changeDbModel).Error +} func LogBalanceChange(updateType global_const.UpdateType, balanceType global_const.BalanceType, data interface{}, amount *big.Float) { + //TODO return } @@ -35,3 +38,33 @@ func GetDepositAndWithDrawLog(userId string, IsTestNet bool) (models []*UserSpon } return models, nil } +func LockBalanceChangeLog(payUserid string, userOpHash string, amount *big.Float, isTestNet bool, updateReason string) error { + logModel := &UserSponsorBalanceUpdateLogDBModel{ + PayUserId: payUserid, + Amount: amount, + UserOpHash: userOpHash, + Source: "GasTank", + IsTestNet: isTestNet, + } + return relayDB.Create(logModel).Error +} +func GetChangeModel(updateType global_const.UpdateType, payUserId string, txHash string, isTestNet bool) (ChangeModel *UserSponsorBalanceUpdateLogDBModel, err error) { + if updateType == global_const.UpdateTypeDeposit || updateType == global_const.UpdateTypeWithdraw { + + tx := relayDB.Model(ChangeModel).Where("tx_hash = ?", txHash).Where("pay_user_id", payUserId).Where("update_type = ?", global_const.UpdateTypeDeposit).Where("is_test_net", isTestNet).First(&ChangeModel) + if tx.Error != nil { + return nil, tx.Error + } else { + return ChangeModel, nil + } + } else if updateType == global_const.UpdateTypeLock || updateType == global_const.UpdateTypeRelease { + tx := relayDB.Model(ChangeModel).Where("user_op_hash = ?", txHash).Where("update_type = ?", global_const.UpdateTypeLock).Where("is_test_net", isTestNet).First(&ChangeModel) + if tx.Error != nil { + return nil, tx.Error + } else { + return ChangeModel, nil + } + } else { + return nil, nil + } +} diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go index 793adce2..b88c51ee 100644 --- a/sponsor_manager/sponsor_service.go +++ b/sponsor_manager/sponsor_service.go @@ -3,7 +3,9 @@ package sponsor_manager import ( "AAStarCommunity/EthPaymaster_BackService/common/global_const" "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/config" + "encoding/json" "errors" "golang.org/x/xerrors" "gorm.io/driver/postgres" @@ -62,13 +64,51 @@ func LockUserBalance(userId string, userOpHash []byte, isTestNet bool, if err != nil { return err } - LogBalanceChange(global_const.UpdateTypeLock, global_const.BalanceTypeLockBalance, userOpHash, lockAmount) + changeModel := &UserSponsorBalanceUpdateLogDBModel{ + UserOpHash: utils.EncodeToHexStringWithPrefix(userOpHash), + PayUserId: userId, + Amount: lockAmount, + Source: "GasTank", + IsTestNet: isTestNet, + UpdateType: global_const.UpdateTypeLock, + } + err = AddBalanceChangeLog(changeModel) + if err != nil { + return err + } + return nil } func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, network global_const.Network, - actualGasCost *big.Float) (err error) { - //TODO + actualGasCost *big.Float, isTestNet bool) error { + userOpHashHex := utils.EncodeToHexStringWithPrefix(userOpHash) + + changeModel, err := GetChangeModel(global_const.UpdateTypeLock, "", userOpHashHex, isTestNet) + if err != nil { + return err + } + balanceModel, err := getUserSponsorBalance(changeModel.PayUserId, changeModel.IsTestNet) + + lockBalance := changeModel.Amount + balanceModel.LockBalance = new(big.Float).Sub(balanceModel.LockBalance, lockBalance) + refundBalance := new(big.Float).Sub(lockBalance, actualGasCost) + balanceModel.AvailableBalance = new(big.Float).Add(balanceModel.AvailableBalance, refundBalance) + + err = UpdateSponsor(balanceModel, isTestNet) + + if err != nil { + return err + } + changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ + UserOpHash: userOpHashHex, + PayUserId: changeModel.PayUserId, + Amount: refundBalance, + Source: "GasTank", + IsTestNet: isTestNet, + UpdateType: global_const.UpdateTypeRelease, + } + err = AddBalanceChangeLog(changeDBModel) return nil } @@ -76,35 +116,89 @@ type ReleaseUserOpHashLockInput struct { UserOpHash []byte } -func ReleaseUserOpHashLock(userOpHash []byte) (err error) { +func ReleaseUserOpHashLock(userOpHash []byte, isTestNet bool) (err error) { // Get ChangeLog By UserOpHash + userOpHashHex := utils.EncodeToHexStringWithPrefix(userOpHash) + changeModel, err := GetChangeModel(global_const.UpdateTypeLock, "", userOpHashHex, isTestNet) + if err != nil { + return err + } + // Release Lock + balanceModel, err := getUserSponsorBalance(changeModel.PayUserId, changeModel.IsTestNet) + + lockBalance := changeModel.Amount + + balanceModel.LockBalance = new(big.Float).Sub(balanceModel.LockBalance, lockBalance) + balanceModel.AvailableBalance = new(big.Float).Add(balanceModel.AvailableBalance, lockBalance) + + err = UpdateSponsor(balanceModel, isTestNet) + if err != nil { + return err + } + changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ + UserOpHash: userOpHashHex, + PayUserId: changeModel.PayUserId, + Amount: lockBalance, + Source: "GasTank", + IsTestNet: isTestNet, + UpdateType: global_const.UpdateTypeRelease, + } + err = AddBalanceChangeLog(changeDBModel) + if err != nil { + return err + } return nil } //----------Functions---------- -func DepositSponsor(input *model.DepositSponsorRequest) (balanceModel *UserSponsorBalanceDBModel, err error) { - balanceModel, err = FindUserSponsorBalance(input.PayUserId, input.IsTestNet) +func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBModel, error) { + + balanceModel, err := FindUserSponsorBalance(input.PayUserId, input.IsTestNet) + + tx := relayDB.Begin() if errors.Is(err, gorm.ErrRecordNotFound) { + balanceModel = &UserSponsorBalanceDBModel{} balanceModel.AvailableBalance = input.Amount balanceModel.PayUserId = input.PayUserId balanceModel.LockBalance = big.NewFloat(0) balanceModel.IsTestNet = input.IsTestNet - err = CreateSponsorBalance(balanceModel) + err = tx.Create(balanceModel).Error if err != nil { + tx.Rollback() return nil, err } } if err != nil { + tx.Rollback() return nil, err } newAvailableBalance := new(big.Float).Add(balanceModel.AvailableBalance, input.Amount) balanceModel.AvailableBalance = newAvailableBalance - err = UpdateSponsor(balanceModel, input.IsTestNet) - if err != nil { - return nil, err + + if updateErr := tx.Model(balanceModel). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil { + tx.Rollback() + return nil, updateErr + } + + txInfoJSon, _ := json.Marshal(input.TxInfo) + chagneModel := &UserSponsorBalanceUpdateLogDBModel{ + PayUserId: input.PayUserId, + Amount: input.Amount, + Source: "Deposit", + IsTestNet: input.IsTestNet, + UpdateType: global_const.UpdateTypeDeposit, + TxHash: input.TxHash, + TxInfo: txInfoJSon, + } + if createErr := tx.Create(chagneModel).Error; createErr != nil { + tx.Rollback() + return nil, createErr } - LogBalanceChange(global_const.UpdateTypeDeposit, global_const.BalanceTypeAvailableBalance, input, input.Amount) + + tx.Commit() return balanceModel, nil } @@ -122,6 +216,17 @@ func WithDrawSponsor(input *model.WithdrawSponsorRequest) (balanceModel *UserSpo if err != nil { return nil, err } - LogBalanceChange(global_const.UpdateTypeWithdraw, global_const.BalanceTypeAvailableBalance, input, input.Amount) + changeModel := &UserSponsorBalanceUpdateLogDBModel{ + PayUserId: input.PayUserId, + Amount: input.Amount, + Source: "Withdraw", + IsTestNet: input.IsTestNet, + UpdateType: global_const.UpdateTypeWithdraw, + TxHash: input.TxHash, + } + err = AddBalanceChangeLog(changeModel) + if err != nil { + return nil, err + } return balanceModel, nil } diff --git a/sponsor_manager/sponsor_test.go b/sponsor_manager/sponsor_test.go new file mode 100644 index 00000000..cf2f7987 --- /dev/null +++ b/sponsor_manager/sponsor_test.go @@ -0,0 +1,53 @@ +package sponsor_manager + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/config" + "math/big" + "testing" +) + +func TestSponsor(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + config.InitConfig("../config/basic_strategy_config.json", "../config/basic_config.json", "../config/secret_config.json") + Init() + tests := []struct { + name string + test func(t *testing.T) + }{ + { + "TestGetAvailableBalance", + func(t *testing.T) { + request := model.DepositSponsorRequest{ + PayUserId: "test", + Amount: big.NewFloat(1), + IsTestNet: true, + } + result, err := DepositSponsor(&request) + if err != nil { + t.Error(err) + } + if result == nil { + t.Error("DepositSponsor failed") + } + }, + }, + { + "TestLockUserBalanceSt", + func(t *testing.T) { + res, err := SelectUserSponsorBalanceDBModelWithScanList() + if err != nil { + t.Error(err) + } + if res == nil { + t.Error("SelectUserSponsorBalanceDBModelWithScanList failed") + } + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, tt.test) + } +} From c4141cf7f9f4712e0ffea898d2e0a199bb3b7c8e Mon Sep 17 00:00:00 2001 From: dylanyang Date: Mon, 27 May 2024 18:15:41 +0800 Subject: [PATCH 18/23] Fix Float Problem --- sponsor_manager/sponsor_balance_repository.go | 72 +++++++------------ sponsor_manager/sponsor_service.go | 29 ++++---- sponsor_manager/sponsor_test.go | 12 ---- 3 files changed, 42 insertions(+), 71 deletions(-) diff --git a/sponsor_manager/sponsor_balance_repository.go b/sponsor_manager/sponsor_balance_repository.go index 6f0353f7..2482793d 100644 --- a/sponsor_manager/sponsor_balance_repository.go +++ b/sponsor_manager/sponsor_balance_repository.go @@ -2,18 +2,19 @@ package sponsor_manager import ( "AAStarCommunity/EthPaymaster_BackService/common/model" + "database/sql/driver" "fmt" "math/big" ) type UserSponsorBalanceDBModel struct { model.BaseData - PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` - AvailableBalance *big.Float `gorm:"type:numeric(30,18)" json:"available_balance"` - LockBalance *big.Float `gorm:"type:numeric(30,18)" json:"lock_balance"` - Source string `gorm:"type:varchar(255)" json:"source"` - SponsorAddress string `gorm:"type:varchar(255)" json:"sponsor_address"` - IsTestNet bool `gorm:"type:boolean" json:"is_test_net"` + PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` + AvailableBalance BigFloat `gorm:"type:numeric(30,18)" json:"available_balance"` + LockBalance BigFloat `gorm:"type:numeric(30,18)" json:"lock_balance"` + Source string `gorm:"type:varchar(255)" json:"source"` + SponsorAddress string `gorm:"type:varchar(255)" json:"sponsor_address"` + IsTestNet bool `gorm:"type:boolean" json:"is_test_net"` } func (UserSponsorBalanceDBModel) TableName() string { @@ -46,51 +47,32 @@ type BigFloat struct { } // Scan implements the sql.Scanner interface for BigFloat -func (b *BigFloat) Scan(value interface{}) error { - if b == nil { - fmt.Println("BigFloat Scan value is nil") - return nil - } - fmt.Println("BigFloat Scan value", value) +func (bf *BigFloat) Scan(value interface{}) error { switch v := value.(type) { - case string: - - if _, ok := b.SetString(v); !ok { - return fmt.Errorf("failed to parse string as *big.Float: %s", v) - } case []byte: - fmt.Println("BigFloat Scan value Case Byte", value) - - if _, ok := b.SetString(string(v)); !ok { - return fmt.Errorf("failed to parse byte slice as *big.Float: %s", string(v)) + f, _, err := big.ParseFloat(string(v), 10, 256, big.ToNearestEven) + if err != nil { + return err + } + bf.Float = f + case string: + f, _, err := big.ParseFloat(v, 10, 256, big.ToNearestEven) + if err != nil { + return err } + bf.Float = f + case float64: + bf.Float = big.NewFloat(v) + case nil: + bf.Float = nil default: - return fmt.Errorf("unsupported type: %T", v) + return fmt.Errorf("cannot scan type %T into BigFloat", value) } return nil } - -func SelectUserSponsorBalanceDBModelWithScanList() (userSponsorBalanceDBModelWithScanList []UserSponsorBalanceDBModelWithScan, err error) { - userSponsorBalanceDBModelWithScanList = make([]UserSponsorBalanceDBModelWithScan, 0) - tx := relayDB.Model(&UserSponsorBalanceDBModelWithScan{}).Find(&userSponsorBalanceDBModelWithScanList) - if tx.Error != nil { - err = tx.Error - return +func (bf *BigFloat) Value() (driver.Value, error) { + if bf.Float == nil { + return nil, nil } - fmt.Println(userSponsorBalanceDBModelWithScanList) - return userSponsorBalanceDBModelWithScanList, nil -} - -type UserSponsorBalanceDBModelWithScan struct { - model.BaseData - PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` - AvailableBalance float64 `gorm:"type:numeric(30,18)" json:"available_balance"` - LockBalance float64 `gorm:"type:numeric(30,18)" json:"lock_balance"` - Source string `gorm:"type:varchar(255)" json:"source"` - SponsorAddress string `gorm:"type:varchar(255)" json:"sponsor_address"` - IsTestNet bool `gorm:"type:boolean" json:"is_test_net"` -} - -func (UserSponsorBalanceDBModelWithScan) TableName() string { - return "relay_user_sponsor_balance" + return bf.Text('f', -1), nil } diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go index b88c51ee..edf2ac29 100644 --- a/sponsor_manager/sponsor_service.go +++ b/sponsor_manager/sponsor_service.go @@ -42,7 +42,7 @@ func GetAvailableBalance(userId string, isTestNet bool) (balance *big.Float, err } return nil, err } - return balanceModel.AvailableBalance, nil + return balanceModel.AvailableBalance.Float, nil } // LockUserBalance @@ -56,10 +56,10 @@ func LockUserBalance(userId string, userOpHash []byte, isTestNet bool, if err != nil { return err } - lockBalance := new(big.Float).Add(balanceModel.LockBalance, lockAmount) - availableBalance := new(big.Float).Sub(balanceModel.AvailableBalance, lockAmount) - balanceModel.LockBalance = lockBalance - balanceModel.AvailableBalance = availableBalance + lockBalance := new(big.Float).Add(balanceModel.LockBalance.Float, lockAmount) + availableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, lockAmount) + balanceModel.LockBalance = BigFloat{lockBalance} + balanceModel.AvailableBalance = BigFloat{availableBalance} err = UpdateSponsor(balanceModel, isTestNet) if err != nil { return err @@ -91,9 +91,9 @@ func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, network glob balanceModel, err := getUserSponsorBalance(changeModel.PayUserId, changeModel.IsTestNet) lockBalance := changeModel.Amount - balanceModel.LockBalance = new(big.Float).Sub(balanceModel.LockBalance, lockBalance) + balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance)} refundBalance := new(big.Float).Sub(lockBalance, actualGasCost) - balanceModel.AvailableBalance = new(big.Float).Add(balanceModel.AvailableBalance, refundBalance) + balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, refundBalance)} err = UpdateSponsor(balanceModel, isTestNet) @@ -128,8 +128,9 @@ func ReleaseUserOpHashLock(userOpHash []byte, isTestNet bool) (err error) { lockBalance := changeModel.Amount - balanceModel.LockBalance = new(big.Float).Sub(balanceModel.LockBalance, lockBalance) - balanceModel.AvailableBalance = new(big.Float).Add(balanceModel.AvailableBalance, lockBalance) + balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance)} + + balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, lockBalance)} err = UpdateSponsor(balanceModel, isTestNet) if err != nil { @@ -159,9 +160,9 @@ func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBMo tx := relayDB.Begin() if errors.Is(err, gorm.ErrRecordNotFound) { balanceModel = &UserSponsorBalanceDBModel{} - balanceModel.AvailableBalance = input.Amount + balanceModel.AvailableBalance = BigFloat{input.Amount} balanceModel.PayUserId = input.PayUserId - balanceModel.LockBalance = big.NewFloat(0) + balanceModel.LockBalance = BigFloat{big.NewFloat(0)} balanceModel.IsTestNet = input.IsTestNet err = tx.Create(balanceModel).Error if err != nil { @@ -173,7 +174,7 @@ func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBMo tx.Rollback() return nil, err } - newAvailableBalance := new(big.Float).Add(balanceModel.AvailableBalance, input.Amount) + newAvailableBalance := BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, input.Amount)} balanceModel.AvailableBalance = newAvailableBalance if updateErr := tx.Model(balanceModel). @@ -210,8 +211,8 @@ func WithDrawSponsor(input *model.WithdrawSponsorRequest) (balanceModel *UserSpo if balanceModel.AvailableBalance.Cmp(input.Amount) < 0 { return nil, xerrors.Errorf("Insufficient balance [%s] not Enough to Withdraw [%s]", balanceModel.AvailableBalance.String(), input.Amount.String()) } - newAvailableBalance := new(big.Float).Sub(balanceModel.AvailableBalance, input.Amount) - balanceModel.AvailableBalance = newAvailableBalance + newAvailableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, input.Amount) + balanceModel.AvailableBalance = BigFloat{newAvailableBalance} err = UpdateSponsor(balanceModel, input.IsTestNet) if err != nil { return nil, err diff --git a/sponsor_manager/sponsor_test.go b/sponsor_manager/sponsor_test.go index cf2f7987..b22f4041 100644 --- a/sponsor_manager/sponsor_test.go +++ b/sponsor_manager/sponsor_test.go @@ -34,18 +34,6 @@ func TestSponsor(t *testing.T) { } }, }, - { - "TestLockUserBalanceSt", - func(t *testing.T) { - res, err := SelectUserSponsorBalanceDBModelWithScanList() - if err != nil { - t.Error(err) - } - if res == nil { - t.Error("SelectUserSponsorBalanceDBModelWithScanList failed") - } - }, - }, } for _, tt := range tests { t.Run(tt.name, tt.test) From 9754d6de94e8d6ae1802669e070668152c3ba16c Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 28 May 2024 14:44:18 +0800 Subject: [PATCH 19/23] update Sponsor --- schedulor/UserOpEventListener.go | 6 +- sponsor_manager/sponsor_balance_repository.go | 2 +- .../sponsor_changelog_repository.go | 5 +- sponsor_manager/sponsor_service.go | 165 ++++++++++++------ sponsor_manager/sponsor_test.go | 95 +++++++++- 5 files changed, 207 insertions(+), 66 deletions(-) diff --git a/schedulor/UserOpEventListener.go b/schedulor/UserOpEventListener.go index 289e35b7..3befac55 100644 --- a/schedulor/UserOpEventListener.go +++ b/schedulor/UserOpEventListener.go @@ -73,9 +73,9 @@ func UserOpEventComunicate(network global_const.Network, event ContractUserOpera return } if !event.Success { - err := sponsor_manager.ReleaseUserOpHashLock(event.UserOpHash[:], true) + _, err := sponsor_manager.ReleaseUserOpHashLockWhenFail(event.UserOpHash[:], true) if err != nil { - logrus.Errorf("ReleaseUserOpHashLock failed: %v", err) + logrus.Errorf("ReleaseUserOpHashLockWhenFail failed: %v", err) } return } @@ -89,7 +89,7 @@ func UserOpEventComunicate(network global_const.Network, event ContractUserOpera return } - err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender, event.UserOpHash[:], network, gasCostUsd) + err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender, event.UserOpHash[:], network, gasCostUsd, true) if err != nil { //TODO if is NetWorkError, need retry logrus.Errorf("ReleaseBalanceWithActualCost failed: %v", err) diff --git a/sponsor_manager/sponsor_balance_repository.go b/sponsor_manager/sponsor_balance_repository.go index 2482793d..1f87f4e0 100644 --- a/sponsor_manager/sponsor_balance_repository.go +++ b/sponsor_manager/sponsor_balance_repository.go @@ -36,7 +36,7 @@ func UpdateSponsor(balanceModel *UserSponsorBalanceDBModel, isTestNet bool) erro tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", balanceModel.PayUserId).Where("is_test_net = ?", isTestNet).Updates(balanceModel) return tx.Error } -func getUserSponsorBalance(userId string, isTestNet bool) (balanceModel *UserSponsorBalanceDBModel, err error) { +func findUserSponsor(userId string, isTestNet bool) (balanceModel *UserSponsorBalanceDBModel, err error) { tx := relayDB.Model(&UserSponsorBalanceDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", isTestNet).First(&balanceModel) return balanceModel, tx.Error } diff --git a/sponsor_manager/sponsor_changelog_repository.go b/sponsor_manager/sponsor_changelog_repository.go index b9dcba4f..7d0694f4 100644 --- a/sponsor_manager/sponsor_changelog_repository.go +++ b/sponsor_manager/sponsor_changelog_repository.go @@ -10,7 +10,7 @@ import ( type UserSponsorBalanceUpdateLogDBModel struct { model.BaseData PayUserId string `gorm:"type:varchar(255);index" json:"pay_user_id"` - Amount *big.Float `gorm:"type:numeric(30,18)" json:"amount"` + Amount BigFloat `gorm:"type:numeric(30,18)" json:"amount"` UpdateType global_const.UpdateType `gorm:"type:varchar(20)" json:"update_type"` UserOpHash string `gorm:"type:varchar(255)" json:"user_op_hash"` TxHash string `gorm:"type:varchar(255)" json:"tx_hash"` @@ -41,13 +41,14 @@ func GetDepositAndWithDrawLog(userId string, IsTestNet bool) (models []*UserSpon func LockBalanceChangeLog(payUserid string, userOpHash string, amount *big.Float, isTestNet bool, updateReason string) error { logModel := &UserSponsorBalanceUpdateLogDBModel{ PayUserId: payUserid, - Amount: amount, + Amount: BigFloat{amount}, UserOpHash: userOpHash, Source: "GasTank", IsTestNet: isTestNet, } return relayDB.Create(logModel).Error } + func GetChangeModel(updateType global_const.UpdateType, payUserId string, txHash string, isTestNet bool) (ChangeModel *UserSponsorBalanceUpdateLogDBModel, err error) { if updateType == global_const.UpdateTypeDeposit || updateType == global_const.UpdateTypeWithdraw { diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go index edf2ac29..4f6d72f2 100644 --- a/sponsor_manager/sponsor_service.go +++ b/sponsor_manager/sponsor_service.go @@ -14,6 +14,13 @@ import ( "sync" ) +type Source string + +const ( + SourceDashboard Source = "Dashboard" + SourceRacks Source = "Racks" +) + var ( relayDB *gorm.DB onlyOnce = sync.Once{} @@ -34,7 +41,7 @@ func Init() { //----------Functions---------- func GetAvailableBalance(userId string, isTestNet bool) (balance *big.Float, err error) { - balanceModel, err := getUserSponsorBalance(userId, isTestNet) + balanceModel, err := findUserSponsor(userId, isTestNet) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -48,107 +55,138 @@ func GetAvailableBalance(userId string, isTestNet bool) (balance *big.Float, err // LockUserBalance // Reduce AvailableBalance and Increase LockBalance func LockUserBalance(userId string, userOpHash []byte, isTestNet bool, - lockAmount *big.Float) (err error) { - balanceModel, err := getUserSponsorBalance(userId, isTestNet) + lockAmount *big.Float) (*UserSponsorBalanceUpdateLogDBModel, error) { + balanceModel, err := findUserSponsor(userId, isTestNet) if errors.Is(err, gorm.ErrRecordNotFound) { - return xerrors.Errorf("No Balance Deposit Here ") + return nil, xerrors.Errorf("No Balance Deposit Here ") } if err != nil { - return err + return nil, err + } + UserOphashStr := utils.EncodeToHexStringWithPrefix(userOpHash) + _, err = GetChangeModel(global_const.UpdateTypeLock, userId, UserOphashStr, isTestNet) + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, xerrors.Errorf("UserOpHash [%s] Already Lock", UserOphashStr) } + + if balanceModel.AvailableBalance.Cmp(lockAmount) < 0 { + return nil, xerrors.Errorf("Insufficient balance [%s] not Enough to Lock [%s]", balanceModel.AvailableBalance.String(), lockAmount.String()) + } + lockBalance := new(big.Float).Add(balanceModel.LockBalance.Float, lockAmount) availableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, lockAmount) balanceModel.LockBalance = BigFloat{lockBalance} balanceModel.AvailableBalance = BigFloat{availableBalance} - err = UpdateSponsor(balanceModel, isTestNet) - if err != nil { - return err + tx := relayDB.Begin() + if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { + tx.Rollback() + return nil, updateErr } + changeModel := &UserSponsorBalanceUpdateLogDBModel{ - UserOpHash: utils.EncodeToHexStringWithPrefix(userOpHash), + UserOpHash: UserOphashStr, PayUserId: userId, - Amount: lockAmount, - Source: "GasTank", + Amount: BigFloat{lockAmount}, IsTestNet: isTestNet, UpdateType: global_const.UpdateTypeLock, } - err = AddBalanceChangeLog(changeModel) - if err != nil { - return err + if createErr := tx.Create(changeModel).Error; createErr != nil { + tx.Rollback() + return nil, createErr + } + if commitErr := tx.Commit().Error; commitErr != nil { + tx.Rollback() + return nil, commitErr } - return nil + return nil, nil } -func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, network global_const.Network, - actualGasCost *big.Float, isTestNet bool) error { +func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, + actualGasCost *big.Float, isTestNet bool) (*UserSponsorBalanceDBModel, error) { userOpHashHex := utils.EncodeToHexStringWithPrefix(userOpHash) - changeModel, err := GetChangeModel(global_const.UpdateTypeLock, "", userOpHashHex, isTestNet) + changeModel, err := GetChangeModel(global_const.UpdateTypeLock, userId, userOpHashHex, isTestNet) if err != nil { - return err + return nil, err } - balanceModel, err := getUserSponsorBalance(changeModel.PayUserId, changeModel.IsTestNet) + balanceModel, err := findUserSponsor(changeModel.PayUserId, changeModel.IsTestNet) lockBalance := changeModel.Amount - balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance)} - refundBalance := new(big.Float).Sub(lockBalance, actualGasCost) + balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance.Float)} + refundBalance := new(big.Float).Sub(lockBalance.Float, actualGasCost) balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, refundBalance)} - err = UpdateSponsor(balanceModel, isTestNet) - - if err != nil { - return err + tx := relayDB.Begin() + if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). + Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { + tx.Rollback() + return nil, err } + changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ UserOpHash: userOpHashHex, PayUserId: changeModel.PayUserId, - Amount: refundBalance, + Amount: BigFloat{refundBalance}, Source: "GasTank", IsTestNet: isTestNet, UpdateType: global_const.UpdateTypeRelease, } - err = AddBalanceChangeLog(changeDBModel) - return nil + if createErr := tx.Create(changeDBModel).Error; createErr != nil { + tx.Rollback() + return nil, createErr + } + if commitErr := tx.Commit().Error; commitErr != nil { + tx.Rollback() + return nil, commitErr + } + return balanceModel, nil } type ReleaseUserOpHashLockInput struct { UserOpHash []byte } -func ReleaseUserOpHashLock(userOpHash []byte, isTestNet bool) (err error) { +func ReleaseUserOpHashLockWhenFail(userOpHash []byte, isTestNet bool) (*UserSponsorBalanceDBModel, error) { // Get ChangeLog By UserOpHash userOpHashHex := utils.EncodeToHexStringWithPrefix(userOpHash) changeModel, err := GetChangeModel(global_const.UpdateTypeLock, "", userOpHashHex, isTestNet) if err != nil { - return err + return nil, err } // Release Lock - balanceModel, err := getUserSponsorBalance(changeModel.PayUserId, changeModel.IsTestNet) - + balanceModel, err := findUserSponsor(changeModel.PayUserId, changeModel.IsTestNet) lockBalance := changeModel.Amount - - balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance)} - - balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, lockBalance)} - - err = UpdateSponsor(balanceModel, isTestNet) - if err != nil { - return err + balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance.Float)} + balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, lockBalance.Float)} + tx := relayDB.Begin() + if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { + tx.Rollback() + return nil, err } + changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ UserOpHash: userOpHashHex, PayUserId: changeModel.PayUserId, Amount: lockBalance, - Source: "GasTank", IsTestNet: isTestNet, UpdateType: global_const.UpdateTypeRelease, } - err = AddBalanceChangeLog(changeDBModel) - if err != nil { - return err + if createErr := tx.Create(changeDBModel).Error; createErr != nil { + tx.Rollback() + return nil, createErr + } + if commitErr := tx.Commit().Error; commitErr != nil { + tx.Rollback() + return nil, commitErr } - return nil + return nil, err } //----------Functions---------- @@ -159,8 +197,9 @@ func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBMo tx := relayDB.Begin() if errors.Is(err, gorm.ErrRecordNotFound) { + //init Data balanceModel = &UserSponsorBalanceDBModel{} - balanceModel.AvailableBalance = BigFloat{input.Amount} + balanceModel.AvailableBalance = BigFloat{big.NewFloat(0)} balanceModel.PayUserId = input.PayUserId balanceModel.LockBalance = BigFloat{big.NewFloat(0)} balanceModel.IsTestNet = input.IsTestNet @@ -187,7 +226,7 @@ func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBMo txInfoJSon, _ := json.Marshal(input.TxInfo) chagneModel := &UserSponsorBalanceUpdateLogDBModel{ PayUserId: input.PayUserId, - Amount: input.Amount, + Amount: BigFloat{input.Amount}, Source: "Deposit", IsTestNet: input.IsTestNet, UpdateType: global_const.UpdateTypeDeposit, @@ -199,12 +238,15 @@ func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBMo return nil, createErr } - tx.Commit() + if commitErr := tx.Commit().Error; commitErr != nil { + tx.Rollback() + return nil, commitErr + } return balanceModel, nil } -func WithDrawSponsor(input *model.WithdrawSponsorRequest) (balanceModel *UserSponsorBalanceDBModel, err error) { - balanceModel, err = FindUserSponsorBalance(input.PayUserId, input.IsTestNet) +func WithDrawSponsor(input *model.WithdrawSponsorRequest) (*UserSponsorBalanceDBModel, error) { + balanceModel, err := FindUserSponsorBalance(input.PayUserId, input.IsTestNet) if err != nil { return nil, err } @@ -213,21 +255,28 @@ func WithDrawSponsor(input *model.WithdrawSponsorRequest) (balanceModel *UserSpo } newAvailableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, input.Amount) balanceModel.AvailableBalance = BigFloat{newAvailableBalance} - err = UpdateSponsor(balanceModel, input.IsTestNet) - if err != nil { - return nil, err + tx := relayDB.Begin() + if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil { + tx.Rollback() + return nil, updateErr } changeModel := &UserSponsorBalanceUpdateLogDBModel{ PayUserId: input.PayUserId, - Amount: input.Amount, + Amount: BigFloat{input.Amount}, Source: "Withdraw", IsTestNet: input.IsTestNet, UpdateType: global_const.UpdateTypeWithdraw, TxHash: input.TxHash, } - err = AddBalanceChangeLog(changeModel) - if err != nil { - return nil, err + if createErr := tx.Create(changeModel).Error; createErr != nil { + tx.Rollback() + return nil, createErr + } + if commitErr := tx.Commit().Error; commitErr != nil { + tx.Rollback() + return nil, commitErr } return balanceModel, nil } diff --git a/sponsor_manager/sponsor_test.go b/sponsor_manager/sponsor_test.go index b22f4041..9169f8f4 100644 --- a/sponsor_manager/sponsor_test.go +++ b/sponsor_manager/sponsor_test.go @@ -2,7 +2,10 @@ package sponsor_manager import ( "AAStarCommunity/EthPaymaster_BackService/common/model" + "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/config" + + "encoding/json" "math/big" "testing" ) @@ -13,17 +16,23 @@ func TestSponsor(t *testing.T) { } config.InitConfig("../config/basic_strategy_config.json", "../config/basic_config.json", "../config/secret_config.json") Init() + mockUserOpHash, err := utils.DecodeStringWithPrefix("0xc0977a4ed200e8c2e62b906260e57ee2f7dca962089f8a4645117bfee3b1f215") + mockUserOpHash2, err := utils.DecodeStringWithPrefix("0xc0977a4ed200e8c2e62b906260e57ee2f7dca962089f8a4645117bfee3b1f211") + if err != nil { + t.Fatal(err) + } tests := []struct { name string test func(t *testing.T) }{ { - "TestGetAvailableBalance", + "TestDepositSponsor", func(t *testing.T) { request := model.DepositSponsorRequest{ PayUserId: "test", - Amount: big.NewFloat(1), + Amount: big.NewFloat(3), IsTestNet: true, + Source: string(SourceDashboard), } result, err := DepositSponsor(&request) if err != nil { @@ -34,8 +43,90 @@ func TestSponsor(t *testing.T) { } }, }, + { + "TestGetAvaliabeBalance", + func(t *testing.T) { + testFindUserSponsor(t, "test", true) + }, + }, + { + "TestWithdrawSponsor", + func(t *testing.T) { + testWithDrawSponsor(t, "test", true, big.NewFloat(1)) + }, + }, + { + "TestLockUserBalance1", + func(t *testing.T) { + testLockUserBalance(t, "test", mockUserOpHash, true, big.NewFloat(1)) + }, + }, + { + "ReleaseUserOpHashLockWhenFail", + func(t *testing.T) { + testReleaseUserOpHashLockWhenFail(t, "test", mockUserOpHash, true) + }, + }, + { + "TestLockUserBalance2", + func(t *testing.T) { + testLockUserBalance(t, "test", mockUserOpHash2, true, big.NewFloat(1)) + }, + }, + { + "ReleaseBalanceWithActualCost", + func(t *testing.T) { + testReleaseBalanceWithActualCost(t, "test", mockUserOpHash2, true, big.NewFloat(0.5)) + }, + }, } for _, tt := range tests { t.Run(tt.name, tt.test) } } +func testReleaseBalanceWithActualCost(t *testing.T, userId string, userOpHash []byte, isTestNet bool, actualCost *big.Float) { + _, err := ReleaseBalanceWithActualCost(userId, userOpHash, actualCost, isTestNet) + if err != nil { + t.Error(err) + } + +} +func testReleaseUserOpHashLockWhenFail(t *testing.T, userId string, userOpHash []byte, isTestNet bool) { + _, err := ReleaseUserOpHashLockWhenFail(userOpHash, isTestNet) + if err != nil { + t.Error(err) + } +} +func testLockUserBalance(t *testing.T, userId string, userOpHash []byte, isTestNet bool, lockAmount *big.Float) { + _, err := LockUserBalance(userId, userOpHash, isTestNet, lockAmount) + if err != nil { + t.Error(err) + } +} +func testWithDrawSponsor(t *testing.T, userId string, isTestNet bool, amount *big.Float) { + + request := model.WithdrawSponsorRequest{ + PayUserId: userId, + Amount: amount, + IsTestNet: isTestNet, + TxInfo: map[string]string{}, + } + result, err := WithDrawSponsor(&request) + if err != nil { + t.Error(err) + } + if result == nil { + t.Error("WithDrawSponsor failed") + } +} +func testFindUserSponsor(t *testing.T, userId string, isTestNet bool) { + sponsorModel, err := findUserSponsor(userId, isTestNet) + if err != nil { + t.Error(err) + } + if sponsorModel == nil { + t.Error("findUserSponsor failed") + } + jsonSt, _ := json.Marshal(sponsorModel) + t.Log(string(jsonSt)) +} From 3d9736baa6f785622c02335a687c534faf7ea932 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 28 May 2024 14:49:54 +0800 Subject: [PATCH 20/23] update Sponsor --- schedulor/UserOpEventListener.go | 2 +- service/operator/try_pay_user_op_execute.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/schedulor/UserOpEventListener.go b/schedulor/UserOpEventListener.go index 3befac55..c1f12a92 100644 --- a/schedulor/UserOpEventListener.go +++ b/schedulor/UserOpEventListener.go @@ -89,7 +89,7 @@ func UserOpEventComunicate(network global_const.Network, event ContractUserOpera return } - err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender, event.UserOpHash[:], network, gasCostUsd, true) + _, err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender, event.UserOpHash[:], gasCostUsd, true) if err != nil { //TODO if is NetWorkError, need retry logrus.Errorf("ReleaseBalanceWithActualCost failed: %v", err) diff --git a/service/operator/try_pay_user_op_execute.go b/service/operator/try_pay_user_op_execute.go index 1072ac8e..1b907362 100644 --- a/service/operator/try_pay_user_op_execute.go +++ b/service/operator/try_pay_user_op_execute.go @@ -126,7 +126,7 @@ func executePay(input *ExecutePayInput) (*model.PayResponse, error) { return nil, xerrors.Errorf("Insufficient balance [%s] not Enough to Pay Cost [%s]", depositBalance.String(), gasUsdCost.String()) } //Lock Deposit Balance - err = sponsor_manager.LockUserBalance(payUserKey, input.UserOpHash, isTestNet, + _, err = sponsor_manager.LockUserBalance(payUserKey, input.UserOpHash, isTestNet, gasUsdCost) if err != nil { return nil, err From 2ab2e64a44453c0f7f1a314c1edce5fd63c2c23c Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 28 May 2024 19:08:45 +0800 Subject: [PATCH 21/23] update Sponsor --- common/network/ethereum_adaptable_executor.go | 25 +- schedulor/UserOpEventListener.go | 98 -------- schedulor/listener_test.go | 137 +++++++++++ schedulor/user_op_event_listener.go | 220 ++++++++++++++++++ 4 files changed, 374 insertions(+), 106 deletions(-) delete mode 100644 schedulor/UserOpEventListener.go create mode 100644 schedulor/listener_test.go create mode 100644 schedulor/user_op_event_listener.go diff --git a/common/network/ethereum_adaptable_executor.go b/common/network/ethereum_adaptable_executor.go index 99870b4a..39e51a6d 100644 --- a/common/network/ethereum_adaptable_executor.go +++ b/common/network/ethereum_adaptable_executor.go @@ -15,6 +15,7 @@ import ( "AAStarCommunity/EthPaymaster_BackService/common/user_op" "AAStarCommunity/EthPaymaster_BackService/common/utils" "AAStarCommunity/EthPaymaster_BackService/config" + "AAStarCommunity/EthPaymaster_BackService/schedulor" "context" "crypto/ecdsa" "encoding/hex" @@ -59,10 +60,11 @@ func init() { type EthereumExecutor struct { BaseExecutor - Client *ethclient.Client - GethClient *gethclient.Client - network global_const.Network - ChainId *big.Int + Client *ethclient.Client + GethClient *gethclient.Client + network global_const.Network + ChainId *big.Int + eventListener schedulor.EventListener } var mu sync.Mutex @@ -92,12 +94,19 @@ func GetEthereumExecutor(network global_const.Network) *EthereumExecutor { if !success { panic(xerrors.Errorf("chainId %s is invalid", config.GetChainId(network))) } + eventListener, err := schedulor.NewEventListener(client, network) + if err != nil { + panic(err) + } + go eventListener.Listen() + logrus.Debugf("after Lesten network :[%s]", network) geth := gethclient.New(client.Client()) executorMap[network] = &EthereumExecutor{ - network: network, - Client: client, - ChainId: chainId, - GethClient: geth, + network: network, + Client: client, + ChainId: chainId, + GethClient: geth, + eventListener: eventListener, } return executorMap[network] diff --git a/schedulor/UserOpEventListener.go b/schedulor/UserOpEventListener.go deleted file mode 100644 index c1f12a92..00000000 --- a/schedulor/UserOpEventListener.go +++ /dev/null @@ -1,98 +0,0 @@ -package schedulor - -import ( - "AAStarCommunity/EthPaymaster_BackService/common/global_const" - "AAStarCommunity/EthPaymaster_BackService/common/price_compoent" - "AAStarCommunity/EthPaymaster_BackService/config" - "AAStarCommunity/EthPaymaster_BackService/sponsor_manager" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/sirupsen/logrus" - "math/big" -) - -func AddListener(client ethclient.Client, network global_const.Network) { - entryPointAddress, _ := config.GetSupportEntryPoints(network) - if entryPointAddress == nil { - logrus.Debugf("Not Support Network %v", network) - return - } - for _, address := range entryPointAddress.ToSlice() { - contractAddress := common.HexToAddress(address) - query := ethereum.FilterQuery{ - Addresses: []common.Address{contractAddress}, - } - sub, err := client.SubscribeFilterLogs(nil, query, nil) - if err != nil { - logrus.Errorf("SubscribeFilterLogs failed: %v", err) - return - } - logs := make(chan types.Log) - go func() { - for { - select { - case err := <-sub.Err(): - logrus.Errorf("SubscribeFilterLogs failed: %v", err) - return - case vLog := <-logs: - if vLog.Removed { - continue - } - //TODO - //UserOpEventComunicate(network, ContractUserOperationEvent{}) - } - } - }() - //TODO - //client.SubscribeFilterLogs() - } - //TODO -} - -type ContractUserOperationEvent struct { - UserOpHash [32]byte - Sender string - Paymaster string - Nonce *big.Int - Success bool - ActualGasCost *big.Int - ActualGasUsed *big.Int - Raw types.Log -} - -func UserOpEventComunicate(network global_const.Network, event ContractUserOperationEvent) { - paymasterAddressSet, _ := config.GetSupportPaymaster(network) - if paymasterAddressSet == nil { - logrus.Debugf("Not Support Network %v", network) - return - } - if !paymasterAddressSet.Contains(event.Paymaster) { - logrus.Debugf("UserOpEventComunicate: paymaster not support, %v", event.Paymaster) - return - } - if !event.Success { - _, err := sponsor_manager.ReleaseUserOpHashLockWhenFail(event.UserOpHash[:], true) - if err != nil { - logrus.Errorf("ReleaseUserOpHashLockWhenFail failed: %v", err) - } - return - } - gasCostEther := new(big.Float).SetInt(event.ActualGasCost) - gasCostEther = new(big.Float).Quo(gasCostEther, new(big.Float).SetInt64(1e18)) - //logrus.Infof("UserOpEventComunicate: %v, %v, %v, %v", event.UserOpHash, event.Sender, event.ActualGasCost, gasCostEther) - gasCostUsd, err := price_compoent.GetTokenCostInUsd(global_const.TokenTypeETH, gasCostEther) - if err != nil { - //TODO if is NetWorkError, need retry - logrus.Errorf("GetTokenCostInUsd failed: %v", err) - return - } - - _, err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender, event.UserOpHash[:], gasCostUsd, true) - if err != nil { - //TODO if is NetWorkError, need retry - logrus.Errorf("ReleaseBalanceWithActualCost failed: %v", err) - return - } -} diff --git a/schedulor/listener_test.go b/schedulor/listener_test.go new file mode 100644 index 00000000..b6297fdb --- /dev/null +++ b/schedulor/listener_test.go @@ -0,0 +1,137 @@ +package schedulor + +//func TestMyListener(t *testing.T) { +// if testing.Short() { +// t.Skip("skipping test in short mode.") +// } +// logrus.SetLevel(logrus.DebugLevel) +// config.InitConfig("../config/basic_strategy_config.json", "../config/basic_config.json", "../config/secret_config.json") +// client, err := ethclient.Dial("wss://optimism-sepolia.infura.io/ws/v3/0284f5a9fc55476698079b24e2f97909") +// if err != nil { +// panic(err) +// } +// listener := EventListener{ +// logCh: make(chan types.Log, 10), +// entryPointAddresses: []common.Address{common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789")}, +// paymasterAddresses: []common.Address{common.HexToAddress("0x8817340e0a3435E06254f2ed411E6418cd070D6F")}, +// client: client, +// network: global_const.OptimismSepolia, +// } +// +// listener.Listen() +//} +// +//func TestAddListener(t *testing.T) { +// if testing.Short() { +// t.Skip("skipping test in short mode.") +// } +// client, err := ethclient.Dial("wss://optimism-sepolia.infura.io/ws/v3/0284f5a9fc55476698079b24e2f97909") +// if err != nil { +// panic(err) +// } +// chainId, err := client.ChainID(context.Background()) +// if err != nil { +// panic(err) +// } +// t.Logf("chainId: %v", chainId.String()) +// entryPointAdd := common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789") +// //topics := make([][]interface{}, 0) +// eventId := userOpEvent.ID +// var eventIds []interface{} +// eventIds = append(eventIds, eventId) +// querys := make([][]interface{}, 0) +// querys = append(querys, eventIds) +// +// var userOpHashRule []interface{} +// querys = append(querys, userOpHashRule) +// var senderRule []interface{} +// querys = append(querys, senderRule) +// var paymasterRule []interface{} +// paymasterRule = append(paymasterRule, common.HexToAddress("0x8817340e0a3435E06254f2ed411E6418cd070D6F")) +// querys = append(querys, paymasterRule) +// +// //t.Log("event ", eventId.String()) +// //topics = append(topics, []common.Hash{eventId}) +// //payAddress := common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789") +// //topics[3] = []common.Hash{payAddress.Hash()} +// +// topics, err := abi.MakeTopics(querys...) +// query := ethereum.FilterQuery{ +// Addresses: []common.Address{entryPointAdd}, +// Topics: topics, +// } +// +// logs := make(chan types.Log, 11) +// +// sub, err := client.SubscribeFilterLogs(context.Background(), query, logs) +// if err != nil { +// panic(err) +// } +// +// for { +// select { +// case err := <-sub.Err(): +// t.Fatal(err) +// case vLog := <-logs: +// fmt.Println("tx Hash: ", vLog.TxHash.String()) +// if len(vLog.Topics) == 0 { +// t.Logf("vLog.Topics is empty") +// t.Fatal(err) +// } +// if vLog.Topics[0] != eventId { +// t.Logf("vLog.Topics[0] != eventId") +// t.Fatal(err) +// } +// if len(vLog.Topics) < 4 { +// t.Logf("vLog.Topics length < 4") +// t.Fatal(err) +// } +// if len(vLog.Data) > 0 { +// eventObj := &ContractUserOperationEvent{} +// err := entryPointABI.UnpackIntoInterface(eventObj, "UserOperationEvent", vLog.Data) +// t.Logf("Data: %v", hex.EncodeToString(vLog.Data)) +// if err != nil { +// t.Errorf("UnpackIntoInterface failed: %v", err) +// t.Fatal(err) +// } +// eventObj.UserOpHash = common.BytesToHash(vLog.Topics[1].Bytes()) +// eventObj.Sender = common.BytesToAddress(vLog.Topics[2].Bytes()) +// eventObj.Paymaster = common.BytesToAddress(vLog.Topics[3].Bytes()) +// +// jsonStr, _ := json.Marshal(eventObj) +// t.Logf("userOpEvent: %v", string(jsonStr)) +// } +// } +// } +//} +// +//// func TestAddListener2(t *testing.T) { +//// config.InitConfig("../config/basic_strategy_config.json", "../config/basic_config.json", "../config/secret_config.json") +//// +//// add := common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789") +//// entryPpointContract, err := executor.GetEntryPoint06(&add) +//// if err != nil { +//// t.Fatal(err) +//// } +//// it, err := entryPpointContract.FilterUserOperationEvent(&bind.FilterOpts{}, nil, nil, nil) +//// if err != nil { +//// t.Fatal(err) +//// } +//// for { +//// if it.Next() { +//// fmt.Println(it.Event) +//// } +//// } +//// } +//func TestABi(t *testing.T) { +// // 0x +// abi, _ := contract_entrypoint_v06.ContractMetaData.GetAbi() +// event := abi.Events["UserOperationEvent"] +// id := event.ID +// t.Log(id) +// +// abi07, _ := contract_entrypoint_v07.ContractMetaData.GetAbi() +// event07 := abi07.Events["UserOperationEvent"] +// id07 := event07.ID +// t.Log(id07) +//} diff --git a/schedulor/user_op_event_listener.go b/schedulor/user_op_event_listener.go new file mode 100644 index 00000000..23f86620 --- /dev/null +++ b/schedulor/user_op_event_listener.go @@ -0,0 +1,220 @@ +package schedulor + +import ( + "AAStarCommunity/EthPaymaster_BackService/common/ethereum_contract/contract/contract_entrypoint_v06" + "AAStarCommunity/EthPaymaster_BackService/common/global_const" + "AAStarCommunity/EthPaymaster_BackService/common/price_compoent" + "AAStarCommunity/EthPaymaster_BackService/config" + "AAStarCommunity/EthPaymaster_BackService/sponsor_manager" + "context" + "fmt" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/sirupsen/logrus" + "math/big" +) + +var ( + userOpEvent abi.Event + entryPointABI *abi.ABI +) + +func init() { + getAbi, _ := contract_entrypoint_v06.ContractMetaData.GetAbi() + entryPointABI = getAbi + userOpEvent = entryPointABI.Events["UserOperationEvent"] +} + +type EventListener struct { + logCh chan types.Log + entryPointAddresses []common.Address + paymasterAddresses []common.Address + client *ethclient.Client + network global_const.Network +} + +func (listener *EventListener) Listen() { + queryies := make([][]interface{}, 0) + eventId := userOpEvent.ID + var eventIds []interface{} + eventIds = append(eventIds, eventId) + queryies = append(queryies, eventIds) + var userOpHashRule []interface{} + queryies = append(queryies, userOpHashRule) + var senderRule []interface{} + queryies = append(queryies, senderRule) + var paymasterRule []interface{} + for _, paymasterAddress := range listener.paymasterAddresses { + paymasterRule = append(paymasterRule, paymasterAddress) + } + queryies = append(queryies, paymasterRule) + topics, err := abi.MakeTopics(queryies...) + if err != nil { + logrus.Errorf("abi.MakeTopics failed: %v", err) + return + } + addresses := make([]common.Address, 0) + for _, entryPointAdd := range listener.entryPointAddresses { + addresses = append(addresses, entryPointAdd) + } + + query := ethereum.FilterQuery{ + Addresses: addresses, + Topics: topics, + } + fmt.Println("query: ", query) + client := listener.client + + sub, err := client.SubscribeFilterLogs(context.Background(), query, listener.logCh) + + if err != nil { + logrus.Errorf("SubscribeFilterLogs failed: %v", err) + return + } + for { + select { + case err := <-sub.Err(): + logrus.Errorf("SubscribeFilterLogs failed: %v", err) + fmt.Println("SubscribeFilterLogs failed: ", err) + return + case vLog := <-listener.logCh: + if len(vLog.Topics) == 0 { + logrus.Errorf("vLog.Topics is empty") + continue + } + if vLog.Topics[0] != eventId { + logrus.Errorf("vLog.Topics[0] != eventId") + continue + } + if len(vLog.Topics) < 4 { + logrus.Errorf("vLog.Topics length < 4") + continue + } + if len(vLog.Data) > 0 { + eventObj := &ContractUserOperationEvent{} + err := entryPointABI.UnpackIntoInterface(eventObj, "UserOperationEvent", vLog.Data) + if err != nil { + logrus.Errorf("UnpackIntoInterface failed: %v", err) + continue + } + eventObj.UserOpHash = common.BytesToHash(vLog.Topics[1].Bytes()) + eventObj.Sender = common.BytesToAddress(vLog.Topics[2].Bytes()) + eventObj.Paymaster = common.BytesToAddress(vLog.Topics[3].Bytes()) + logrus.Debugf("UserOpEventComunicate: %v, %v, %v, %v", eventObj.UserOpHash, eventObj.Sender, eventObj.ActualGasCost, eventObj.ActualGasUsed) + UserOpEventComunicate(listener.network, *eventObj) + } + } + } + +} + +func NewEventListener(client *ethclient.Client, network global_const.Network) (EventListener, error) { + entryPointAddresses, err := config.GetSupportEntryPoints(network) + if err != nil { + return EventListener{}, err + } + entryPointAddressesArr := make([]common.Address, 2) + for _, address := range entryPointAddresses.ToSlice() { + entryPointAddressesArr = append(entryPointAddressesArr, common.HexToAddress(address)) + } + + paymasterAddresses, err := config.GetSupportPaymaster(network) + if err != nil { + return EventListener{}, err + } + paymasterAddressArr := make([]common.Address, 2) + for _, address := range paymasterAddresses.ToSlice() { + paymasterAddressArr = append(paymasterAddressArr, common.HexToAddress(address)) + } + + return EventListener{ + logCh: make(chan types.Log, 10), + entryPointAddresses: entryPointAddressesArr, + paymasterAddresses: paymasterAddressArr, + client: client, + network: network, + }, nil + //if entryPointAddress == nil { + // logrus.Debugf("Not Support Network %v", network) + // return + //} + //for _, address := range entryPointAddress.ToSlice() { + // contractAddress := common.HexToAddress(address) + // query := ethereum.FilterQuery{ + // Addresses: []common.Address{contractAddress}, + // } + // sub, err := client.SubscribeFilterLogs(nil, query, nil) + // if err != nil { + // logrus.Errorf("SubscribeFilterLogs failed: %v", err) + // return + // } + // logs := make(chan types.Log) + // go func() { + // for { + // select { + // case err := <-sub.Err(): + // logrus.Errorf("SubscribeFilterLogs failed: %v", err) + // return + // case vLog := <-logs: + // if vLog.Removed { + // continue + // } + // //TODO + // //UserOpEventComunicate(network, ContractUserOperationEvent{}) + // } + // } + // }() + // //TODO + // //client.SubscribeFilterLogs() + //} + ////TODO + +} + +type ContractUserOperationEvent struct { + UserOpHash [32]byte + Sender common.Address + Paymaster common.Address + Nonce *big.Int + Success bool + ActualGasCost *big.Int + ActualGasUsed *big.Int +} + +func UserOpEventComunicate(network global_const.Network, event ContractUserOperationEvent) { + paymasterAddressSet, _ := config.GetSupportPaymaster(network) + if paymasterAddressSet == nil { + logrus.Debugf("Not Support Network %v", network) + return + } + //if !paymasterAddressSet.Contains(event.Paymaster) { + // logrus.Debugf("UserOpEventComunicate: paymaster not support, %v", event.Paymaster) + // return + //} + if !event.Success { + _, err := sponsor_manager.ReleaseUserOpHashLockWhenFail(event.UserOpHash[:], true) + if err != nil { + logrus.Errorf("ReleaseUserOpHashLockWhenFail failed: %v", err) + } + return + } + gasCostEther := new(big.Float).SetInt(event.ActualGasCost) + gasCostEther = new(big.Float).Quo(gasCostEther, new(big.Float).SetInt64(1e18)) + //logrus.Infof("UserOpEventComunicate: %v, %v, %v, %v", event.UserOpHash, event.Sender, event.ActualGasCost, gasCostEther) + gasCostUsd, err := price_compoent.GetTokenCostInUsd(global_const.TokenTypeETH, gasCostEther) + if err != nil { + //TODO if is NetWorkError, need retry + logrus.Errorf("GetTokenCostInUsd failed: %v", err) + return + } + + _, err = sponsor_manager.ReleaseBalanceWithActualCost(event.Sender.String(), event.UserOpHash[:], gasCostUsd, true) + if err != nil { + //TODO if is NetWorkError, need retry + logrus.Errorf("ReleaseBalanceWithActualCost failed: %v", err) + return + } +} From 7c7924036d1293a9f9c41e6aa3db9c1c732416d2 Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 28 May 2024 20:22:17 +0800 Subject: [PATCH 22/23] update Sponsor --- common/network/ethereum_adaptable_executor.go | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/common/network/ethereum_adaptable_executor.go b/common/network/ethereum_adaptable_executor.go index 39e51a6d..8a6aab91 100644 --- a/common/network/ethereum_adaptable_executor.go +++ b/common/network/ethereum_adaptable_executor.go @@ -30,6 +30,7 @@ import ( "github.com/sirupsen/logrus" "golang.org/x/xerrors" "math/big" + "strings" "sync" ) @@ -60,11 +61,12 @@ func init() { type EthereumExecutor struct { BaseExecutor - Client *ethclient.Client - GethClient *gethclient.Client - network global_const.Network - ChainId *big.Int - eventListener schedulor.EventListener + Client *ethclient.Client + GethClient *gethclient.Client + network global_const.Network + ChainId *big.Int + eventListener schedulor.EventListener + webSocketClient *ethclient.Client } var mu sync.Mutex @@ -94,7 +96,14 @@ func GetEthereumExecutor(network global_const.Network) *EthereumExecutor { if !success { panic(xerrors.Errorf("chainId %s is invalid", config.GetChainId(network))) } - eventListener, err := schedulor.NewEventListener(client, network) + wsUrl := config.GetNewWorkClientURl(network) + wsUrl = strings.Replace(wsUrl, "https", "wss", 1) + webSocketClient, err := ethclient.Dial(wsUrl) + if err != nil { + panic(err) + } + + eventListener, err := schedulor.NewEventListener(webSocketClient, network) if err != nil { panic(err) } @@ -102,11 +111,12 @@ func GetEthereumExecutor(network global_const.Network) *EthereumExecutor { logrus.Debugf("after Lesten network :[%s]", network) geth := gethclient.New(client.Client()) executorMap[network] = &EthereumExecutor{ - network: network, - Client: client, - ChainId: chainId, - GethClient: geth, - eventListener: eventListener, + network: network, + Client: client, + ChainId: chainId, + GethClient: geth, + eventListener: eventListener, + webSocketClient: webSocketClient, } return executorMap[network] From 6ebd1bdc98afbad4e86900bb7ec6a7f7d7e1981f Mon Sep 17 00:00:00 2001 From: dylanyang Date: Tue, 4 Jun 2024 20:50:05 +0800 Subject: [PATCH 23/23] resolve Comment --- common/utils/util.go | 16 ++ rpc_server/api/v1/sponsor.go | 20 +- .../sponsor_changelog_repository.go | 2 +- sponsor_manager/sponsor_service.go | 255 +++++++++--------- 4 files changed, 152 insertions(+), 141 deletions(-) diff --git a/common/utils/util.go b/common/utils/util.go index 6dada604..25105bc6 100644 --- a/common/utils/util.go +++ b/common/utils/util.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/sirupsen/logrus" "golang.org/x/xerrors" + "gorm.io/gorm" "math/big" "regexp" "runtime" @@ -200,3 +201,18 @@ func GetCurrentGoroutineStack() string { n := runtime.Stack(buf[:], false) return string(buf[:n]) } +func DBTransactional(db *gorm.DB, handle func() error) (err error) { + tx := db.Begin() + defer func() { + if p := recover(); p != nil { + tx.Rollback() + panic(p) + } else if err != nil { + tx.Rollback() + } else { + err = tx.Commit().Error + } + }() + err = handle() + return +} diff --git a/rpc_server/api/v1/sponsor.go b/rpc_server/api/v1/sponsor.go index fe4c09af..35c28ebb 100644 --- a/rpc_server/api/v1/sponsor.go +++ b/rpc_server/api/v1/sponsor.go @@ -66,7 +66,7 @@ func WithdrawSponsor(ctx *gin.Context) { return } -type SponsorDepositTransaction struct { +type sponsorDepositTransaction struct { TxHash string `json:"tx_hash"` Amount string `json:"amount"` UpdateType global_const.UpdateType `json:"update_type"` @@ -90,12 +90,12 @@ func GetSponsorDepositAndWithdrawTransactions(ctx *gin.Context) { models, err := sponsor_manager.GetDepositAndWithDrawLog(userId, isTestNet) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - response.FailCode(ctx, 301, "No Deposit Transactions") + response.FailCode(ctx, 400, "No Deposit Transactions") } } - trans := make([]SponsorDepositTransaction, 0) + trans := make([]sponsorDepositTransaction, 0) for _, depositModel := range models { - tran := SponsorDepositTransaction{ + tran := sponsorDepositTransaction{ TxHash: depositModel.TxHash, Amount: depositModel.Amount.String(), } @@ -105,11 +105,6 @@ func GetSponsorDepositAndWithdrawTransactions(ctx *gin.Context) { return } -type SponsorMetaResponse struct { - AvailableBalance string `json:"available_balance"` - SponsorAddress string `json:"sponsor_address"` -} - // GetSponsorMetaData // @Tags Sponsor // @Description Get Sponsor Balance @@ -126,10 +121,13 @@ func GetSponsorMetaData(ctx *gin.Context) { balance, err := sponsor_manager.FindUserSponsorBalance(userId, isTestNet) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - response.FailCode(ctx, 301, "No Balance") + response.FailCode(ctx, 400, "No Balance") } } - result := SponsorMetaResponse{ + result := struct { + AvailableBalance string `json:"available_balance"` + SponsorAddress string `json:"sponsor_address"` + }{ AvailableBalance: balance.AvailableBalance.String(), SponsorAddress: balance.SponsorAddress, } diff --git a/sponsor_manager/sponsor_changelog_repository.go b/sponsor_manager/sponsor_changelog_repository.go index 7d0694f4..768ed50d 100644 --- a/sponsor_manager/sponsor_changelog_repository.go +++ b/sponsor_manager/sponsor_changelog_repository.go @@ -32,7 +32,7 @@ func LogBalanceChange(updateType global_const.UpdateType, balanceType global_con return } func GetDepositAndWithDrawLog(userId string, IsTestNet bool) (models []*UserSponsorBalanceUpdateLogDBModel, err error) { - tx := relayDB.Model(&UserSponsorBalanceUpdateLogDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", IsTestNet).Where("update_type = ?", global_const.UpdateTypeDeposit).Or("update_type = ?", global_const.UpdateTypeWithdraw).Find(&models) + tx := relayDB.Model(&UserSponsorBalanceUpdateLogDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", IsTestNet).Where("update_type in (?)", []global_const.UpdateType{global_const.UpdateTypeDeposit, global_const.UpdateTypeWithdraw}).Find(&models) if tx.Error != nil { return nil, tx.Error } diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go index 4f6d72f2..009d001c 100644 --- a/sponsor_manager/sponsor_service.go +++ b/sponsor_manager/sponsor_service.go @@ -77,29 +77,25 @@ func LockUserBalance(userId string, userOpHash []byte, isTestNet bool, availableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, lockAmount) balanceModel.LockBalance = BigFloat{lockBalance} balanceModel.AvailableBalance = BigFloat{availableBalance} - tx := relayDB.Begin() - if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). - Where("pay_user_id = ?", balanceModel.PayUserId). - Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { - tx.Rollback() - return nil, updateErr - } + err = utils.DBTransactional(relayDB, func() error { + if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { + return err + } - changeModel := &UserSponsorBalanceUpdateLogDBModel{ - UserOpHash: UserOphashStr, - PayUserId: userId, - Amount: BigFloat{lockAmount}, - IsTestNet: isTestNet, - UpdateType: global_const.UpdateTypeLock, - } - if createErr := tx.Create(changeModel).Error; createErr != nil { - tx.Rollback() - return nil, createErr - } - if commitErr := tx.Commit().Error; commitErr != nil { - tx.Rollback() - return nil, commitErr - } + changeModel := &UserSponsorBalanceUpdateLogDBModel{ + UserOpHash: UserOphashStr, + PayUserId: userId, + Amount: BigFloat{lockAmount}, + IsTestNet: isTestNet, + UpdateType: global_const.UpdateTypeLock, + } + if createErr := relayDB.Create(changeModel).Error; createErr != nil { + return err + } + return nil + }) return nil, nil } @@ -119,31 +115,31 @@ func ReleaseBalanceWithActualCost(userId string, userOpHash []byte, refundBalance := new(big.Float).Sub(lockBalance.Float, actualGasCost) balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, refundBalance)} - tx := relayDB.Begin() - if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). - Model(&UserSponsorBalanceDBModel{}). - Where("pay_user_id = ?", balanceModel.PayUserId). - Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { - tx.Rollback() + err = utils.DBTransactional(relayDB, func() error { + if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}). + Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { + return err + } + + changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ + UserOpHash: userOpHashHex, + PayUserId: changeModel.PayUserId, + Amount: BigFloat{refundBalance}, + Source: "GasTank", + IsTestNet: isTestNet, + UpdateType: global_const.UpdateTypeRelease, + } + if createErr := relayDB.Create(changeDBModel).Error; createErr != nil { + return createErr + } + return nil + }) + if err != nil { return nil, err } - changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ - UserOpHash: userOpHashHex, - PayUserId: changeModel.PayUserId, - Amount: BigFloat{refundBalance}, - Source: "GasTank", - IsTestNet: isTestNet, - UpdateType: global_const.UpdateTypeRelease, - } - if createErr := tx.Create(changeDBModel).Error; createErr != nil { - tx.Rollback() - return nil, createErr - } - if commitErr := tx.Commit().Error; commitErr != nil { - tx.Rollback() - return nil, commitErr - } return balanceModel, nil } @@ -163,30 +159,29 @@ func ReleaseUserOpHashLockWhenFail(userOpHash []byte, isTestNet bool) (*UserSpon lockBalance := changeModel.Amount balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance.Float)} balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, lockBalance.Float)} - tx := relayDB.Begin() - if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). - Where("pay_user_id = ?", balanceModel.PayUserId). - Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { - tx.Rollback() - return nil, err - } + err = utils.DBTransactional(relayDB, func() error { + if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil { + return err + } - changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ - UserOpHash: userOpHashHex, - PayUserId: changeModel.PayUserId, - Amount: lockBalance, - IsTestNet: isTestNet, - UpdateType: global_const.UpdateTypeRelease, - } - if createErr := tx.Create(changeDBModel).Error; createErr != nil { - tx.Rollback() - return nil, createErr - } - if commitErr := tx.Commit().Error; commitErr != nil { - tx.Rollback() - return nil, commitErr + changeDBModel := &UserSponsorBalanceUpdateLogDBModel{ + UserOpHash: userOpHashHex, + PayUserId: changeModel.PayUserId, + Amount: lockBalance, + IsTestNet: isTestNet, + UpdateType: global_const.UpdateTypeRelease, + } + if createErr := relayDB.Create(changeDBModel).Error; createErr != nil { + return createErr + } + return nil + }) + if err != nil { + return nil, err } - return nil, err + return balanceModel, nil } //----------Functions---------- @@ -194,54 +189,57 @@ func ReleaseUserOpHashLockWhenFail(userOpHash []byte, isTestNet bool) (*UserSpon func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBModel, error) { balanceModel, err := FindUserSponsorBalance(input.PayUserId, input.IsTestNet) + if err != nil { + return nil, err + } - tx := relayDB.Begin() - if errors.Is(err, gorm.ErrRecordNotFound) { - //init Data - balanceModel = &UserSponsorBalanceDBModel{} - balanceModel.AvailableBalance = BigFloat{big.NewFloat(0)} - balanceModel.PayUserId = input.PayUserId - balanceModel.LockBalance = BigFloat{big.NewFloat(0)} - balanceModel.IsTestNet = input.IsTestNet - err = tx.Create(balanceModel).Error + err = utils.DBTransactional(relayDB, func() error { + if errors.Is(err, gorm.ErrRecordNotFound) { + //init Data + balanceModel = &UserSponsorBalanceDBModel{} + balanceModel.AvailableBalance = BigFloat{big.NewFloat(0)} + balanceModel.PayUserId = input.PayUserId + balanceModel.LockBalance = BigFloat{big.NewFloat(0)} + balanceModel.IsTestNet = input.IsTestNet + err = relayDB.Create(balanceModel).Error + if err != nil { + + return err + } + } if err != nil { - tx.Rollback() - return nil, err + + return err } - } + newAvailableBalance := BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, input.Amount)} + balanceModel.AvailableBalance = newAvailableBalance + + if updateErr := relayDB.Model(balanceModel). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil { + + return updateErr + } + + txInfoJSon, _ := json.Marshal(input.TxInfo) + changeModel := &UserSponsorBalanceUpdateLogDBModel{ + PayUserId: input.PayUserId, + Amount: BigFloat{input.Amount}, + Source: "Deposit", + IsTestNet: input.IsTestNet, + UpdateType: global_const.UpdateTypeDeposit, + TxHash: input.TxHash, + TxInfo: txInfoJSon, + } + if createErr := relayDB.Create(changeModel).Error; createErr != nil { + return createErr + } + return nil + }) if err != nil { - tx.Rollback() return nil, err } - newAvailableBalance := BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, input.Amount)} - balanceModel.AvailableBalance = newAvailableBalance - - if updateErr := tx.Model(balanceModel). - Where("pay_user_id = ?", balanceModel.PayUserId). - Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil { - tx.Rollback() - return nil, updateErr - } - - txInfoJSon, _ := json.Marshal(input.TxInfo) - chagneModel := &UserSponsorBalanceUpdateLogDBModel{ - PayUserId: input.PayUserId, - Amount: BigFloat{input.Amount}, - Source: "Deposit", - IsTestNet: input.IsTestNet, - UpdateType: global_const.UpdateTypeDeposit, - TxHash: input.TxHash, - TxInfo: txInfoJSon, - } - if createErr := tx.Create(chagneModel).Error; createErr != nil { - tx.Rollback() - return nil, createErr - } - if commitErr := tx.Commit().Error; commitErr != nil { - tx.Rollback() - return nil, commitErr - } return balanceModel, nil } @@ -255,28 +253,27 @@ func WithDrawSponsor(input *model.WithdrawSponsorRequest) (*UserSponsorBalanceDB } newAvailableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, input.Amount) balanceModel.AvailableBalance = BigFloat{newAvailableBalance} - tx := relayDB.Begin() - if updateErr := tx.Model(&UserSponsorBalanceDBModel{}). - Where("pay_user_id = ?", balanceModel.PayUserId). - Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil { - tx.Rollback() - return nil, updateErr - } - changeModel := &UserSponsorBalanceUpdateLogDBModel{ - PayUserId: input.PayUserId, - Amount: BigFloat{input.Amount}, - Source: "Withdraw", - IsTestNet: input.IsTestNet, - UpdateType: global_const.UpdateTypeWithdraw, - TxHash: input.TxHash, - } - if createErr := tx.Create(changeModel).Error; createErr != nil { - tx.Rollback() - return nil, createErr - } - if commitErr := tx.Commit().Error; commitErr != nil { - tx.Rollback() - return nil, commitErr + err = utils.DBTransactional(relayDB, func() error { + if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}). + Where("pay_user_id = ?", balanceModel.PayUserId). + Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil { + return updateErr + } + changeModel := &UserSponsorBalanceUpdateLogDBModel{ + PayUserId: input.PayUserId, + Amount: BigFloat{input.Amount}, + Source: "Withdraw", + IsTestNet: input.IsTestNet, + UpdateType: global_const.UpdateTypeWithdraw, + TxHash: input.TxHash, + } + if createErr := relayDB.Create(changeModel).Error; createErr != nil { + return createErr + } + return nil + }) + if err != nil { + return nil, err } return balanceModel, nil }