mirror of
https://github.com/grassrootseconomics/cic-custodial.git
synced 2024-11-21 22:06:47 +01:00
feat: add otx tracking API, add enums, minor fixes
* otx can nw be tracked at /api/track/:trackingId * moved queries to queries folder * fixed validation error check in ErrorHandler * added enum package with enum types * updated migrations: added enum tables
This commit is contained in:
parent
140c887341
commit
40cb86f522
@ -30,7 +30,7 @@ func initApiServer(custodialContainer *custodial.Custodial) *echo.Echo {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err.(validator.ValidationErrors) != nil {
|
if _, ok := err.(validator.ValidationErrors); ok {
|
||||||
c.JSON(http.StatusForbidden, api.ErrResp{
|
c.JSON(http.StatusForbidden, api.ErrResp{
|
||||||
Ok: false,
|
Ok: false,
|
||||||
Code: api.VALIDATION_ERROR,
|
Code: api.VALIDATION_ERROR,
|
||||||
@ -66,6 +66,7 @@ func initApiServer(custodialContainer *custodial.Custodial) *echo.Echo {
|
|||||||
apiRoute := server.Group("/api")
|
apiRoute := server.Group("/api")
|
||||||
apiRoute.POST("/account/create", api.CreateAccountHandler(custodialContainer))
|
apiRoute.POST("/account/create", api.CreateAccountHandler(custodialContainer))
|
||||||
apiRoute.POST("/sign/transfer", api.SignTransferHandler(custodialContainer))
|
apiRoute.POST("/sign/transfer", api.SignTransferHandler(custodialContainer))
|
||||||
|
apiRoute.GET("/track/:trackingId", api.TxStatus(custodialContainer.PgStore))
|
||||||
|
|
||||||
return server
|
return server
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ var (
|
|||||||
func init() {
|
func init() {
|
||||||
flag.StringVar(&confFlag, "config", "config.toml", "Config file location")
|
flag.StringVar(&confFlag, "config", "config.toml", "Config file location")
|
||||||
flag.BoolVar(&debugFlag, "log", false, "Enable debug logging")
|
flag.BoolVar(&debugFlag, "log", false, "Enable debug logging")
|
||||||
flag.StringVar(&queriesFlag, "queries", "queries.sql", "Queries file location")
|
flag.StringVar(&queriesFlag, "queries", "queries/queries.sql", "Queries file location")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
lo = initLogger(debugFlag)
|
lo = initLogger(debugFlag)
|
||||||
|
2
go.mod
2
go.mod
@ -6,6 +6,7 @@ require (
|
|||||||
github.com/VictoriaMetrics/metrics v1.23.1
|
github.com/VictoriaMetrics/metrics v1.23.1
|
||||||
github.com/bsm/redislock v0.7.2
|
github.com/bsm/redislock v0.7.2
|
||||||
github.com/celo-org/celo-blockchain v1.7.2
|
github.com/celo-org/celo-blockchain v1.7.2
|
||||||
|
github.com/georgysavva/scany/v2 v2.0.0
|
||||||
github.com/go-playground/validator/v10 v10.11.2
|
github.com/go-playground/validator/v10 v10.11.2
|
||||||
github.com/go-redis/redis/v8 v8.11.5
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
@ -70,7 +71,6 @@ require (
|
|||||||
github.com/prometheus/tsdb v0.10.0 // indirect
|
github.com/prometheus/tsdb v0.10.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.3 // indirect
|
github.com/rivo/uniseg v0.4.3 // indirect
|
||||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
||||||
github.com/spf13/cast v1.3.1 // indirect
|
github.com/spf13/cast v1.3.1 // indirect
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
||||||
|
7
go.sum
7
go.sum
@ -136,6 +136,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||||||
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
|
github.com/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs=
|
||||||
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
|
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
|
||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
|
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
@ -175,6 +176,8 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/
|
|||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/georgysavva/scany/v2 v2.0.0 h1:RGXqxDv4row7/FYoK8MRXAZXqoWF/NM+NP0q50k3DKU=
|
||||||
|
github.com/georgysavva/scany/v2 v2.0.0/go.mod h1:sigOdh+0qb/+aOs3TVhehVT10p8qJL7K/Zhyz8vWo38=
|
||||||
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||||
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
@ -218,6 +221,7 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP
|
|||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||||
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
@ -424,6 +428,7 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2
|
|||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
@ -572,7 +577,6 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
|
|||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
|
||||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
@ -602,6 +606,7 @@ 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/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||||
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
@ -29,7 +29,7 @@ func SignTransferHandler(cu *custodial.Custodial) func(echo.Context) error {
|
|||||||
From string `json:"from" validate:"required,eth_checksum"`
|
From string `json:"from" validate:"required,eth_checksum"`
|
||||||
To string `json:"to" validate:"required,eth_checksum"`
|
To string `json:"to" validate:"required,eth_checksum"`
|
||||||
VoucherAddress string `json:"voucherAddress" validate:"required,eth_checksum"`
|
VoucherAddress string `json:"voucherAddress" validate:"required,eth_checksum"`
|
||||||
Amount int64 `json:"amount" validate:"required,numeric"`
|
Amount uint64 `json:"amount" validate:"required,numeric"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Bind(&transferRequest); err != nil {
|
if err := c.Bind(&transferRequest); err != nil {
|
||||||
|
37
internal/api/track.go
Normal file
37
internal/api/track.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TxStatus(store store.Store) func(echo.Context) error {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
var txStatusRequest struct {
|
||||||
|
TrackingId string `param:"trackingId" validate:"required,uuid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Bind(&txStatusRequest); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Validate(txStatusRequest); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle potential timeouts
|
||||||
|
txs, err := store.GetTxStatusByTrackingId(c.Request().Context(), txStatusRequest.TrackingId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, OkResp{
|
||||||
|
Ok: true,
|
||||||
|
Result: H{
|
||||||
|
"transactions": txs,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -5,10 +5,8 @@ type EventEmitter interface {
|
|||||||
Publish(subject string, dedupId string, eventPayload interface{}) error
|
Publish(subject string, dedupId string, eventPayload interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type EventPayload struct {
|
||||||
EventPayload struct {
|
|
||||||
OtxId uint `json:"otxId"`
|
OtxId uint `json:"otxId"`
|
||||||
TrackingId string `json:"trackingId"`
|
TrackingId string `json:"trackingId"`
|
||||||
TxHash string `json:"txHash"`
|
TxHash string `json:"txHash"`
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
@ -10,10 +10,11 @@ type Queries struct {
|
|||||||
// Keystore
|
// Keystore
|
||||||
WriteKeyPair string `query:"write-key-pair"`
|
WriteKeyPair string `query:"write-key-pair"`
|
||||||
LoadKeyPair string `query:"load-key-pair"`
|
LoadKeyPair string `query:"load-key-pair"`
|
||||||
// OTX
|
// Store
|
||||||
CreateOTX string `query:"create-otx"`
|
CreateOTX string `query:"create-otx"`
|
||||||
// Dispatch
|
|
||||||
CreateDispatchStatus string `query:"create-dispatch-status"`
|
CreateDispatchStatus string `query:"create-dispatch-status"`
|
||||||
|
UpdateChainStatus string `query:"update-chain-status"`
|
||||||
|
GetTxStatusByTrackingId string `query:"get-tx-status-by-tracking-id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadQueries(q goyesql.Queries) (*Queries, error) {
|
func LoadQueries(q goyesql.Queries) (*Queries, error) {
|
||||||
|
@ -2,9 +2,9 @@ package store
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
)
|
|
||||||
|
|
||||||
type Status string
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
|
)
|
||||||
|
|
||||||
func (s *PostgresStore) CreateDispatchStatus(ctx context.Context, dispatch DispatchStatus) error {
|
func (s *PostgresStore) CreateDispatchStatus(ctx context.Context, dispatch DispatchStatus) error {
|
||||||
if _, err := s.db.Exec(
|
if _, err := s.db.Exec(
|
||||||
@ -18,3 +18,17 @@ func (s *PostgresStore) CreateDispatchStatus(ctx context.Context, dispatch Dispa
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PostgresStore) UpdateChainStatus(ctx context.Context, txHash string, status enum.OtxStatus, block uint64) error {
|
||||||
|
if _, err := s.db.Exec(
|
||||||
|
ctx,
|
||||||
|
s.queries.UpdateChainStatus,
|
||||||
|
txHash,
|
||||||
|
status,
|
||||||
|
block,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
package store
|
package store
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
func (s *PostgresStore) CreateOTX(ctx context.Context, otx OTX) (uint, error) {
|
"github.com/georgysavva/scany/v2/pgxscan"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TxStatus struct {
|
||||||
|
Type string `db:"type" json:"txType"`
|
||||||
|
TxHash string `db:"tx_hash" json:"txHash"`
|
||||||
|
TransferValue uint64 `db:"transfer_value" json:"transferValue"`
|
||||||
|
CreatedAt time.Time `db:"created_at" json:"createdAt"`
|
||||||
|
Status string `db:"status" json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PostgresStore) CreateOtx(ctx context.Context, otx OTX) (uint, error) {
|
||||||
var (
|
var (
|
||||||
id uint
|
id uint
|
||||||
)
|
)
|
||||||
@ -17,6 +30,8 @@ func (s *PostgresStore) CreateOTX(ctx context.Context, otx OTX) (uint, error) {
|
|||||||
otx.From,
|
otx.From,
|
||||||
otx.Data,
|
otx.Data,
|
||||||
otx.GasPrice,
|
otx.GasPrice,
|
||||||
|
otx.GasLimit,
|
||||||
|
otx.TransferValue,
|
||||||
otx.Nonce,
|
otx.Nonce,
|
||||||
).Scan(&id); err != nil {
|
).Scan(&id); err != nil {
|
||||||
return id, err
|
return id, err
|
||||||
@ -24,3 +39,21 @@ func (s *PostgresStore) CreateOTX(ctx context.Context, otx OTX) (uint, error) {
|
|||||||
|
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PostgresStore) GetTxStatusByTrackingId(ctx context.Context, trackingId string) ([]*TxStatus, error) {
|
||||||
|
var (
|
||||||
|
txs []*TxStatus
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := pgxscan.Select(
|
||||||
|
ctx,
|
||||||
|
s.db,
|
||||||
|
&txs,
|
||||||
|
s.queries.GetTxStatusByTrackingId,
|
||||||
|
trackingId,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return txs, nil
|
||||||
|
}
|
||||||
|
@ -3,30 +3,32 @@ package store
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/grassrootseconomics/cic-custodial/pkg/status"
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
OTX struct {
|
OTX struct {
|
||||||
TrackingId string
|
TrackingId string
|
||||||
Type string
|
Type enum.OtxType
|
||||||
RawTx string
|
RawTx string
|
||||||
TxHash string
|
TxHash string
|
||||||
From string
|
From string
|
||||||
Data string
|
Data string
|
||||||
|
GasLimit uint64
|
||||||
|
TransferValue uint64
|
||||||
GasPrice uint64
|
GasPrice uint64
|
||||||
Nonce uint64
|
Nonce uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchStatus struct {
|
DispatchStatus struct {
|
||||||
OtxId uint
|
OtxId uint
|
||||||
Status status.Status
|
Status enum.OtxStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
Store interface {
|
Store interface {
|
||||||
// OTX (Custodial originating transactions).
|
CreateOtx(ctx context.Context, otx OTX) (id uint, err error)
|
||||||
CreateOTX(ctx context.Context, otx OTX) (id uint, err error)
|
|
||||||
// Dispatch status.
|
|
||||||
CreateDispatchStatus(ctx context.Context, dispatch DispatchStatus) error
|
CreateDispatchStatus(ctx context.Context, dispatch DispatchStatus) error
|
||||||
|
GetTxStatusByTrackingId(ctx context.Context, trackingId string) ([]*TxStatus, error)
|
||||||
|
UpdateChainStatus(ctx context.Context, txHash string, status enum.OtxStatus, block uint64) error
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
"github.com/grassrootseconomics/w3-celo-patch"
|
"github.com/grassrootseconomics/w3-celo-patch"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
)
|
)
|
||||||
@ -67,14 +68,16 @@ func AccountGiftGasProcessor(cu *custodial.Custodial) func(context.Context, *asy
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cu.PgStore.CreateOTX(ctx, store.OTX{
|
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||||
TrackingId: payload.TrackingId,
|
TrackingId: payload.TrackingId,
|
||||||
Type: "GIFT_GAS",
|
Type: enum.GIFT_GAS,
|
||||||
RawTx: hexutil.Encode(rawTx),
|
RawTx: hexutil.Encode(rawTx),
|
||||||
TxHash: builtTx.Hash().Hex(),
|
TxHash: builtTx.Hash().Hex(),
|
||||||
From: cu.SystemContainer.PublicKey,
|
From: cu.SystemContainer.PublicKey,
|
||||||
Data: hexutil.Encode(builtTx.Data()),
|
Data: hexutil.Encode(builtTx.Data()),
|
||||||
GasPrice: builtTx.GasPrice().Uint64(),
|
GasPrice: builtTx.GasPrice().Uint64(),
|
||||||
|
GasLimit: builtTx.Gas(),
|
||||||
|
TransferValue: cu.SystemContainer.GiftableGasValue.Uint64(),
|
||||||
Nonce: builtTx.Nonce(),
|
Nonce: builtTx.Nonce(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
"github.com/grassrootseconomics/w3-celo-patch"
|
"github.com/grassrootseconomics/w3-celo-patch"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
)
|
)
|
||||||
@ -75,14 +76,16 @@ func GiftVoucherProcessor(cu *custodial.Custodial) func(context.Context, *asynq.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cu.PgStore.CreateOTX(ctx, store.OTX{
|
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||||
TrackingId: payload.TrackingId,
|
TrackingId: payload.TrackingId,
|
||||||
Type: "GIFT_VOUCHER",
|
Type: enum.ACCOUNT_REGISTER,
|
||||||
RawTx: hexutil.Encode(rawTx),
|
RawTx: hexutil.Encode(rawTx),
|
||||||
TxHash: builtTx.Hash().Hex(),
|
TxHash: builtTx.Hash().Hex(),
|
||||||
From: cu.SystemContainer.PublicKey,
|
From: cu.SystemContainer.PublicKey,
|
||||||
Data: hexutil.Encode(builtTx.Data()),
|
Data: hexutil.Encode(builtTx.Data()),
|
||||||
GasPrice: builtTx.GasPrice().Uint64(),
|
GasPrice: builtTx.GasPrice().Uint64(),
|
||||||
|
GasLimit: builtTx.Gas(),
|
||||||
|
TransferValue: cu.SystemContainer.GiftableTokenValue.Uint64(),
|
||||||
Nonce: builtTx.Nonce(),
|
Nonce: builtTx.Nonce(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
"github.com/grassrootseconomics/w3-celo-patch"
|
"github.com/grassrootseconomics/w3-celo-patch"
|
||||||
"github.com/grassrootseconomics/w3-celo-patch/module/eth"
|
"github.com/grassrootseconomics/w3-celo-patch/module/eth"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
@ -82,14 +83,16 @@ func AccountRefillGasProcessor(cu *custodial.Custodial) func(context.Context, *a
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cu.PgStore.CreateOTX(ctx, store.OTX{
|
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||||
TrackingId: payload.TrackingId,
|
TrackingId: payload.TrackingId,
|
||||||
Type: "REFILL_GAS",
|
Type: enum.REFILL_GAS,
|
||||||
RawTx: hexutil.Encode(rawTx),
|
RawTx: hexutil.Encode(rawTx),
|
||||||
TxHash: builtTx.Hash().Hex(),
|
TxHash: builtTx.Hash().Hex(),
|
||||||
From: cu.SystemContainer.PublicKey,
|
From: cu.SystemContainer.PublicKey,
|
||||||
Data: hexutil.Encode(builtTx.Data()),
|
Data: hexutil.Encode(builtTx.Data()),
|
||||||
GasPrice: builtTx.GasPrice().Uint64(),
|
GasPrice: builtTx.GasPrice().Uint64(),
|
||||||
|
GasLimit: builtTx.Gas(),
|
||||||
|
TransferValue: cu.SystemContainer.GiftableGasValue.Uint64(),
|
||||||
Nonce: builtTx.Nonce(),
|
Nonce: builtTx.Nonce(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
"github.com/grassrootseconomics/w3-celo-patch"
|
"github.com/grassrootseconomics/w3-celo-patch"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
)
|
)
|
||||||
@ -76,14 +77,15 @@ func AccountRegisterOnChainProcessor(cu *custodial.Custodial) func(context.Conte
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cu.PgStore.CreateOTX(ctx, store.OTX{
|
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||||
TrackingId: payload.TrackingId,
|
TrackingId: payload.TrackingId,
|
||||||
Type: "ACCOUNT_REGISTER",
|
Type: enum.ACCOUNT_REGISTER,
|
||||||
RawTx: hexutil.Encode(rawTx),
|
RawTx: hexutil.Encode(rawTx),
|
||||||
TxHash: builtTx.Hash().Hex(),
|
TxHash: builtTx.Hash().Hex(),
|
||||||
From: cu.SystemContainer.PublicKey,
|
From: cu.SystemContainer.PublicKey,
|
||||||
Data: hexutil.Encode(builtTx.Data()),
|
Data: hexutil.Encode(builtTx.Data()),
|
||||||
GasPrice: builtTx.GasPrice().Uint64(),
|
GasPrice: builtTx.GasPrice().Uint64(),
|
||||||
|
GasLimit: builtTx.Gas(),
|
||||||
Nonce: builtTx.Nonce(),
|
Nonce: builtTx.Nonce(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/grassrootseconomics/cic-custodial/internal/custodial"
|
"github.com/grassrootseconomics/cic-custodial/internal/custodial"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||||
"github.com/grassrootseconomics/cic-custodial/pkg/status"
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
"github.com/grassrootseconomics/w3-celo-patch/module/eth"
|
"github.com/grassrootseconomics/w3-celo-patch/module/eth"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
)
|
)
|
||||||
@ -43,15 +43,15 @@ func DispatchTx(cu *custodial.Custodial) func(context.Context, *asynq.Task) erro
|
|||||||
ctx,
|
ctx,
|
||||||
eth.SendTx(payload.Tx).Returns(&dispathchTx),
|
eth.SendTx(payload.Tx).Returns(&dispathchTx),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
dispatchStatus.Status = status.Unknown
|
|
||||||
|
|
||||||
switch err.Error() {
|
switch err.Error() {
|
||||||
case celoutils.ErrGasPriceLow:
|
case celoutils.ErrGasPriceLow:
|
||||||
dispatchStatus.Status = status.FailGasPrice
|
dispatchStatus.Status = enum.FAIL_LOW_GAS_PRICE
|
||||||
case celoutils.ErrInsufficientGas:
|
case celoutils.ErrInsufficientGas:
|
||||||
dispatchStatus.Status = status.FailInsufficientGas
|
dispatchStatus.Status = enum.FAIL_NO_GAS
|
||||||
case celoutils.ErrNonceLow:
|
case celoutils.ErrNonceLow:
|
||||||
dispatchStatus.Status = status.FailNonce
|
dispatchStatus.Status = enum.FAIL_LOW_NONCE
|
||||||
|
default:
|
||||||
|
dispatchStatus.Status = enum.FAIL_UNKNOWN_RPC_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cu.PgStore.CreateDispatchStatus(ctx, dispatchStatus); err != nil {
|
if err := cu.PgStore.CreateDispatchStatus(ctx, dispatchStatus); err != nil {
|
||||||
@ -65,7 +65,7 @@ func DispatchTx(cu *custodial.Custodial) func(context.Context, *asynq.Task) erro
|
|||||||
return fmt.Errorf("dispatch: failed %v: %w", err, asynq.SkipRetry)
|
return fmt.Errorf("dispatch: failed %v: %w", err, asynq.SkipRetry)
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchStatus.Status = status.Successful
|
dispatchStatus.Status = enum.IN_NETWORK
|
||||||
|
|
||||||
if err := cu.PgStore.CreateDispatchStatus(ctx, dispatchStatus); err != nil {
|
if err := cu.PgStore.CreateDispatchStatus(ctx, dispatchStatus); err != nil {
|
||||||
return fmt.Errorf("dispatch: failed %v: %w", err, asynq.SkipRetry)
|
return fmt.Errorf("dispatch: failed %v: %w", err, asynq.SkipRetry)
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
"github.com/grassrootseconomics/cic-custodial/internal/events"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
"github.com/grassrootseconomics/cic-custodial/internal/store"
|
||||||
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
||||||
|
"github.com/grassrootseconomics/cic-custodial/pkg/enum"
|
||||||
"github.com/grassrootseconomics/w3-celo-patch"
|
"github.com/grassrootseconomics/w3-celo-patch"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
)
|
)
|
||||||
@ -22,7 +23,7 @@ type (
|
|||||||
From string `json:"from" `
|
From string `json:"from" `
|
||||||
To string `json:"to"`
|
To string `json:"to"`
|
||||||
VoucherAddress string `json:"voucherAddress"`
|
VoucherAddress string `json:"voucherAddress"`
|
||||||
Amount int64 `json:"amount"`
|
Amount uint64 `json:"amount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
transferEventPayload struct {
|
transferEventPayload struct {
|
||||||
@ -71,7 +72,7 @@ func SignTransfer(cu *custodial.Custodial) func(context.Context, *asynq.Task) er
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
input, err := cu.SystemContainer.Abis["transfer"].EncodeArgs(w3.A(payload.To), big.NewInt(payload.Amount))
|
input, err := cu.SystemContainer.Abis["transfer"].EncodeArgs(w3.A(payload.To), new(big.Int).SetUint64(payload.Amount))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -97,14 +98,16 @@ func SignTransfer(cu *custodial.Custodial) func(context.Context, *asynq.Task) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cu.PgStore.CreateOTX(ctx, store.OTX{
|
id, err := cu.PgStore.CreateOtx(ctx, store.OTX{
|
||||||
TrackingId: payload.TrackingId,
|
TrackingId: payload.TrackingId,
|
||||||
Type: "TRANSFER",
|
Type: enum.TRANSFER_VOUCHER,
|
||||||
RawTx: hexutil.Encode(rawTx),
|
RawTx: hexutil.Encode(rawTx),
|
||||||
TxHash: builtTx.Hash().Hex(),
|
TxHash: builtTx.Hash().Hex(),
|
||||||
From: payload.From,
|
From: payload.From,
|
||||||
Data: hexutil.Encode(builtTx.Data()),
|
Data: hexutil.Encode(builtTx.Data()),
|
||||||
GasPrice: builtTx.GasPrice().Uint64(),
|
GasPrice: builtTx.GasPrice().Uint64(),
|
||||||
|
GasLimit: builtTx.Gas(),
|
||||||
|
TransferValue: payload.Amount,
|
||||||
Nonce: builtTx.Nonce(),
|
Nonce: builtTx.Nonce(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,23 +1,53 @@
|
|||||||
|
-- Otx tx type enum table
|
||||||
|
CREATE TABLE IF NOT EXISTS otx_tx_type (
|
||||||
|
value TEXT PRIMARY KEY
|
||||||
|
);
|
||||||
|
INSERT INTO otx_tx_type (value) VALUES
|
||||||
|
('GIFT_GAS'),
|
||||||
|
('ACCOUNT_REGISTER'),
|
||||||
|
('GIFT_VOUCHER'),
|
||||||
|
('REFILL_GAS'),
|
||||||
|
('TRANSFER_VOUCHER');
|
||||||
|
|
||||||
-- Origin tx table
|
-- Origin tx table
|
||||||
CREATE TABLE IF NOT EXISTS otx (
|
CREATE TABLE IF NOT EXISTS otx_sign (
|
||||||
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
tracking_id TEXT NOT NULL,
|
tracking_id TEXT NOT NULL,
|
||||||
"type" TEXT NOT NULL,
|
"type" TEXT REFERENCES otx_tx_type(value) NOT NULL,
|
||||||
raw_tx TEXT NOT NULL,
|
raw_tx TEXT NOT NULL,
|
||||||
tx_hash TEXT NOT NULL,
|
tx_hash TEXT NOT NULL,
|
||||||
"from" TEXT NOT NULL,
|
"from" TEXT NOT NULL,
|
||||||
"data" TEXT NOT NULL,
|
"data" TEXT NOT NULL,
|
||||||
gas_price bigint NOT NULL,
|
gas_price bigint NOT NULL,
|
||||||
|
gas_limit bigint NOT NULL,
|
||||||
|
transfer_value bigint NOT NULL,
|
||||||
nonce int NOT NULL,
|
nonce int NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
CREATE INDEX IF NOT EXISTS tx_hash_idx ON otx USING hash(tx_hash);
|
CREATE INDEX IF NOT EXISTS tx_hash_idx ON otx_sign USING hash(tx_hash);
|
||||||
CREATE INDEX IF NOT EXISTS from_idx ON otx USING hash("from");
|
CREATE INDEX IF NOT EXISTS from_idx ON otx_sign USING hash("from");
|
||||||
|
|
||||||
|
-- Otx dispatch status enum table
|
||||||
|
-- Enforces referential integrity on the dispatch table
|
||||||
|
CREATE TABLE IF NOT EXISTS otx_dispatch_status_type (
|
||||||
|
value TEXT PRIMARY KEY
|
||||||
|
);
|
||||||
|
INSERT INTO otx_dispatch_status_type (value) VALUES
|
||||||
|
('IN_NETWORK'),
|
||||||
|
('OBSOLETE'),
|
||||||
|
('SUCCESS'),
|
||||||
|
('FAIL_NO_GAS'),
|
||||||
|
('FAIL_LOW_NONCE'),
|
||||||
|
('FAIL_LOW_GAS_PRICE'),
|
||||||
|
('FAIL_UNKNOWN_RPC_ERROR'),
|
||||||
|
('REVERTED');
|
||||||
|
|
||||||
-- Dispatch status table
|
-- Dispatch status table
|
||||||
CREATE TABLE IF NOT EXISTS dispatch (
|
CREATE TABLE IF NOT EXISTS otx_dispatch (
|
||||||
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
otx_id INT REFERENCES otx(id),
|
otx_id INT REFERENCES otx_sign(id),
|
||||||
"status" TEXT NOT NULL,
|
"status" TEXT REFERENCES otx_dispatch_status_type(value) NOT NULL,
|
||||||
|
"block" bigint,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS status_idx ON otx_dispatch("status");
|
||||||
|
27
pkg/enum/enum.go
Normal file
27
pkg/enum/enum.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package enum
|
||||||
|
|
||||||
|
type (
|
||||||
|
// OtxStatus represents enum-like values received in the dispatcher from the RPC node or Network callback.
|
||||||
|
// It includes a subset of well-known and likely failures the dispatcher may encounter.
|
||||||
|
OtxStatus string
|
||||||
|
// OtxType reprsents the specific type of signed transaction.
|
||||||
|
OtxType string
|
||||||
|
)
|
||||||
|
|
||||||
|
// NOTE: These values must also be inserted/updated into db to enforce referential integrity.
|
||||||
|
const (
|
||||||
|
IN_NETWORK OtxStatus = "IN_NETWORK"
|
||||||
|
OBSOLETE OtxStatus = "OBSOLETE"
|
||||||
|
SUCCESS OtxStatus = "SUCCESS"
|
||||||
|
FAIL_NO_GAS OtxStatus = "FAIL_NO_GAS"
|
||||||
|
FAIL_LOW_NONCE OtxStatus = "FAIL_LOW_NONCE"
|
||||||
|
FAIL_LOW_GAS_PRICE OtxStatus = "FAIL_LOW_GAS_PRICE"
|
||||||
|
FAIL_UNKNOWN_RPC_ERROR OtxStatus = "FAIL_UNKNOWN_RPC_ERROR"
|
||||||
|
REVERTED OtxStatus = "REVERTED"
|
||||||
|
|
||||||
|
GIFT_GAS OtxType = "GIFT_GAS"
|
||||||
|
ACCOUNT_REGISTER OtxType = "ACCOUNT_REGISTER"
|
||||||
|
GIFT_VOUCHER OtxType = "GIFT_VOUCHER"
|
||||||
|
REFILL_GAS OtxType = "REFILL_GAS"
|
||||||
|
TRANSFER_VOUCHER OtxType = "TRANSFER_VOUCHER"
|
||||||
|
)
|
@ -1,13 +0,0 @@
|
|||||||
package status
|
|
||||||
|
|
||||||
// Status represents enum-like values received in the dispatcher from the RPC node.
|
|
||||||
// It includes a subset of well-known and likely failures the dispatcher may encounter.
|
|
||||||
type Status string
|
|
||||||
|
|
||||||
const (
|
|
||||||
FailGasPrice = "FAIL_LOW_GAS_PRICE"
|
|
||||||
FailInsufficientGas = "FAIL_NO_GAS"
|
|
||||||
FailNonce = "FAIL_LOW_NONCE"
|
|
||||||
Successful = "SUCCESSFUL"
|
|
||||||
Unknown = "UNKNOWN"
|
|
||||||
)
|
|
47
queries.sql
47
queries.sql
@ -1,47 +0,0 @@
|
|||||||
-- Keystore queries
|
|
||||||
|
|
||||||
--name: write-key-pair
|
|
||||||
-- Save hex encoded private key
|
|
||||||
-- $1: public_key
|
|
||||||
-- $2: private_key
|
|
||||||
INSERT INTO keystore(public_key, private_key) VALUES($1, $2) RETURNING id
|
|
||||||
|
|
||||||
--name: load-key-pair
|
|
||||||
-- Load saved key pair
|
|
||||||
-- $1: public_key
|
|
||||||
SELECT private_key FROM keystore WHERE public_key=$1
|
|
||||||
|
|
||||||
-- OTX queries
|
|
||||||
|
|
||||||
--name: create-otx
|
|
||||||
-- Create a new locally originating tx
|
|
||||||
-- $1: tracking_id
|
|
||||||
-- $2: type
|
|
||||||
-- $3: raw_tx
|
|
||||||
-- $4: tx_hash
|
|
||||||
-- $5: from
|
|
||||||
-- $6: data
|
|
||||||
-- $7: gas_price
|
|
||||||
-- $8: nonce
|
|
||||||
INSERT INTO otx(
|
|
||||||
tracking_id,
|
|
||||||
"type",
|
|
||||||
raw_tx,
|
|
||||||
tx_hash,
|
|
||||||
"from",
|
|
||||||
"data",
|
|
||||||
gas_price,
|
|
||||||
nonce
|
|
||||||
) VALUES($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id
|
|
||||||
|
|
||||||
|
|
||||||
-- Dispatch status queries
|
|
||||||
|
|
||||||
--name: create-dispatch-status
|
|
||||||
-- Create a new dispatch status
|
|
||||||
-- $1: otx_id
|
|
||||||
-- $2: status
|
|
||||||
INSERT INTO dispatch(
|
|
||||||
otx_id,
|
|
||||||
"status"
|
|
||||||
) VALUES($1, $2) RETURNING id
|
|
65
queries/queries.sql
Normal file
65
queries/queries.sql
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
--name: write-key-pair
|
||||||
|
-- Save hex encoded private key
|
||||||
|
-- $1: public_key
|
||||||
|
-- $2: private_key
|
||||||
|
INSERT INTO keystore(public_key, private_key) VALUES($1, $2) RETURNING id
|
||||||
|
|
||||||
|
--name: load-key-pair
|
||||||
|
-- Load saved key pair
|
||||||
|
-- $1: public_key
|
||||||
|
SELECT private_key FROM keystore WHERE public_key=$1
|
||||||
|
|
||||||
|
--name: create-otx
|
||||||
|
-- Create a new locally originating tx
|
||||||
|
-- $1: tracking_id
|
||||||
|
-- $2: type
|
||||||
|
-- $3: raw_tx
|
||||||
|
-- $4: tx_hash
|
||||||
|
-- $5: from
|
||||||
|
-- $6: data
|
||||||
|
-- $7: gas_price
|
||||||
|
-- $8: gas_limit
|
||||||
|
-- $9: transfer_value
|
||||||
|
-- $10: nonce
|
||||||
|
INSERT INTO otx_sign(
|
||||||
|
tracking_id,
|
||||||
|
"type",
|
||||||
|
raw_tx,
|
||||||
|
tx_hash,
|
||||||
|
"from",
|
||||||
|
"data",
|
||||||
|
gas_price,
|
||||||
|
gas_limit,
|
||||||
|
transfer_value,
|
||||||
|
nonce
|
||||||
|
) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id
|
||||||
|
|
||||||
|
--name: create-dispatch-status
|
||||||
|
-- Create a new dispatch status
|
||||||
|
-- $1: otx_id
|
||||||
|
-- $2: status
|
||||||
|
INSERT INTO otx_dispatch(
|
||||||
|
otx_id,
|
||||||
|
"status"
|
||||||
|
) VALUES($1, $2) RETURNING id
|
||||||
|
|
||||||
|
--name: update-chain-status
|
||||||
|
-- Updates the status of the dispatched tx with the chain mine status
|
||||||
|
-- $1: tx_hash
|
||||||
|
-- $2: status
|
||||||
|
-- $3: block
|
||||||
|
UPDATE otx_dispatch SET "status" = $2, "block" = $3 WHERE otx_dispatch.id = (
|
||||||
|
SELECT otx_dispatch.id FROM otx_dispatch
|
||||||
|
INNER JOIN otx_sign ON otx_dispatch.otx_id = otx_sign.id
|
||||||
|
WHERE otx_sign.tx_hash = $1
|
||||||
|
AND otx_dispatch.status = 'IN_NETWORK'
|
||||||
|
)
|
||||||
|
|
||||||
|
--name: get-tx-status-by-tracking-id
|
||||||
|
-- Gets tx status's from possible multiple txs with the same tracking_id
|
||||||
|
-- $1: tracking_id
|
||||||
|
SELECT otx_sign.type, otx_sign.tx_hash, otx_sign.transfer_value, otx_sign.created_at, otx_dispatch.status FROM otx_sign
|
||||||
|
INNER JOIN otx_dispatch ON otx_sign.id = otx_dispatch.otx_id
|
||||||
|
WHERE otx_sign.tracking_id = $1
|
||||||
|
|
||||||
|
-- TODO: Scroll by status type with cursor pagination
|
Loading…
Reference in New Issue
Block a user