diff --git a/api.go b/api.go index 39db4aa..d2cf1c6 100644 --- a/api.go +++ b/api.go @@ -3,12 +3,12 @@ package arseeding import ( "encoding/json" "fmt" - "github.com/everFinance/arseeding/common" "github.com/everFinance/arseeding/schema" "github.com/everFinance/everpay-go/account" "github.com/everFinance/goar/types" "github.com/everFinance/goar/utils" "github.com/gin-gonic/gin" + "gorm.io/gorm" "io" "io/ioutil" "net/http" @@ -19,13 +19,13 @@ import ( func (s *Arseeding) runAPI(port string) { r := s.engine - r.Use(common.CORSMiddleware()) + r.Use(CORSMiddleware()) if s.EnableManifest { - r.Use(common.SandboxMiddleware()) + r.Use(ManifestMiddleware(s.wdb, s.store)) } if !s.NoFee { - r.Use(common.LimiterMiddleware(3000, "M", s.config.GetIPWhiteList())) + r.Use(LimiterMiddleware(3000, "M", s.config.GetIPWhiteList())) } v1 := r.Group("/") { @@ -77,8 +77,7 @@ func (s *Arseeding) runAPI(port string) { v1.GET("/bundle/fees", s.bundleFees) v1.GET("/bundle/fee/:size/:currency", s.bundleFee) v1.GET("/bundle/orders/:signer", s.getOrders) - v1.GET("/:id", s.dataResponse) // get arTx data or bundleItem data - v1.GET("/:id/*path", s.dataResponse) // get pathData from manifest data + v1.GET("/:id", s.dataRoute) // get arTx data or bundleItem data // submit native data with X-API-KEY v1.POST("/bundle/data", s.submitNativeData) @@ -93,8 +92,8 @@ func (s *Arseeding) runAPI(port string) { func (s *Arseeding) arseedInfo(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "Name": "Arseeding", - "Version": "v1.0.12", - "Documentation": "https://web3infura.io", + "Version": "v1.0.13", + "Documentation": "https://web3infra.dev", }) } @@ -739,26 +738,35 @@ func (s *Arseeding) bundleFees(c *gin.Context) { c.JSON(http.StatusOK, s.bundlePerFeeMap) } -func (s *Arseeding) dataResponse(c *gin.Context) { - tags, data, err := getArTxOrItemData(c.Param("id"), s.store) +func (s *Arseeding) dataRoute(c *gin.Context) { + txId := c.Param("id") + tags, data, err := getArTxOrItemData(txId, s.store) switch err { case nil: // process manifest if s.EnableManifest && getTagValue(tags, schema.ContentType) == schema.ManifestType { - tags, data, err = handleManifest(data, c.Param("path"), s.store) - if err != nil { - if err == schema.ErrLocalNotExist { - proxyArweaveGateway(c) - } else if err == schema.ErrPageNotFound { - notFoundResponse(c, err.Error()) - } else { + mfUrl := expectedTxSandbox(txId) + if _, err = s.wdb.GetManifestId(mfUrl); err == gorm.ErrRecordNotFound { + // insert new record + if err = s.wdb.InsertManifest(schema.Manifest{ + ManifestUrl: mfUrl, + ManifestId: txId, + }); err != nil { internalErrorResponse(c, err.Error()) + return } - return } - } - c.Data(200, fmt.Sprintf("%s; charset=utf-8", getTagValue(tags, schema.ContentType)), data) + protocol := "https" + if c.Request.TLS == nil { + protocol = "http" + } + redirectUrl := fmt.Sprintf("%s://%s.%s", protocol, mfUrl, c.Request.Host) + + c.Redirect(302, redirectUrl) + } else { + c.Data(200, fmt.Sprintf("%s; charset=utf-8", getTagValue(tags, schema.ContentType)), data) + } case schema.ErrLocalNotExist: proxyArweaveGateway(c) diff --git a/arseeding.go b/arseeding.go index 4ff1bfb..a84a968 100644 --- a/arseeding.go +++ b/arseeding.go @@ -64,7 +64,7 @@ func New( } wdb := NewWdb(dsn) - if err = wdb.Migrate(noFee); err != nil { + if err = wdb.Migrate(noFee, enableManifest); err != nil { panic(err) } bundler, err := goar.NewWalletFromPath(arWalletKeyPath, arNode) diff --git a/go.mod b/go.mod index fa5bfa6..7e32450 100644 --- a/go.mod +++ b/go.mod @@ -9,10 +9,10 @@ require ( github.com/everFinance/goether v1.1.7 github.com/gin-gonic/gin v1.7.7 github.com/go-co-op/gocron v1.11.0 - github.com/panjf2000/ants/v2 v2.4.7 + github.com/panjf2000/ants/v2 v2.5.0 github.com/prometheus/client_golang v1.12.2 github.com/shopspring/decimal v1.2.0 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 github.com/tidwall/gjson v1.14.1 github.com/ulule/limiter/v3 v3.10.0 github.com/urfave/cli/v2 v2.3.0 diff --git a/jobs.go b/jobs.go index f294462..21b6bd1 100644 --- a/jobs.go +++ b/jobs.go @@ -207,47 +207,56 @@ func (s *Arseeding) mergeReceiptAndOrder() { } for _, urtx := range unspentRpts { - paymentItemId := gjson.Parse(urtx.Data).Get("itemId").String() - ord, err := s.wdb.GetUnPaidOrder(paymentItemId) + itemIds, err := parseItemIds(urtx.Data) if err != nil { - log.Error("s.wdb.GetUnPaidOrder", "err", err, "itemId", paymentItemId) + log.Error("parseItemIds(urtx.Data)", "err", err, "urtx", urtx.EverHash) + if err = s.wdb.UpdateReceiptStatus(urtx.RawId, schema.UnRefund, nil); err != nil { + log.Error("s.wdb.UpdateReceiptStatus1", "err", err, "id", urtx.RawId) + } + continue + } + // get orders by itemIds + ordArr, err := s.getUnPaidOrdersByItemIds(itemIds) + if err != nil { + log.Error("s.wdb.GetUnPaidOrder", "err", err, "id", urtx.RawId) if err == gorm.ErrRecordNotFound { - log.Warn("need refund about not find order", "itemId", paymentItemId) + log.Warn("need refund about not find order", "id", urtx.RawId) // update receipt status is unrefund and waiting refund if err = s.wdb.UpdateReceiptStatus(urtx.RawId, schema.UnRefund, nil); err != nil { - log.Error("s.wdb.UpdateReceiptStatus", "err", err, "id", urtx.RawId) + log.Error("s.wdb.UpdateReceiptStatus2", "err", err, "id", urtx.RawId) } } continue } - // verify payment token and amount - amt, ok := new(big.Int).SetString(urtx.Amount, 10) - if !ok { - log.Error("SetString(urtx.Amount,10)", "amount", urtx.Amount) - continue - } - fee, ok := new(big.Int).SetString(ord.Fee, 10) - if !ok { - log.Error("SetString(ord.Fee,10)", "fee", ord.Fee) + // check currency, orders currency must == paymentTxSymbol + if err = checkOrdersCurrency(ordArr, urtx.Symbol); err != nil { + log.Error("checkOrdersCurrency(ordArr, urtx.Symbol)", "err", err, "urtx", urtx.EverHash) + if err = s.wdb.UpdateReceiptStatus(urtx.RawId, schema.UnRefund, nil); err != nil { + log.Error("s.wdb.UpdateReceiptStatus3", "err", err, "id", urtx.RawId) + } continue } - if strings.ToLower(ord.Currency) != strings.ToLower(urtx.Symbol) || amt.Cmp(fee) < 0 { - log.Warn("need refund about currency or amount", "itemId", paymentItemId, "paySymble", urtx.Symbol, "payAmount", amt.String()) - // update receipt status is unrefund and waiting refund + + // check amount + if err = checkOrdersAmount(ordArr, urtx.Amount); err != nil { + log.Error("checkOrdersAmount(ordArr, urtx.Amount)", "err", err, "urtx", urtx.EverHash) if err = s.wdb.UpdateReceiptStatus(urtx.RawId, schema.UnRefund, nil); err != nil { - log.Error("s.wdb.UpdateReceiptStatus", "err", err, "id", urtx.RawId) + log.Error("s.wdb.UpdateReceiptStatus4", "err", err, "id", urtx.RawId) } continue } // update order payment status dbTx := s.wdb.Db.Begin() - if err = s.wdb.UpdateOrderPay(ord.ID, urtx.EverHash, schema.SuccPayment, dbTx); err != nil { - log.Error("s.wdb.UpdateOrderPay(ord.ID,schema.SuccPayment,dbTx)", "err", err) - dbTx.Rollback() - continue + for _, ord := range ordArr { + if err = s.wdb.UpdateOrderPay(ord.ID, urtx.EverHash, schema.SuccPayment, dbTx); err != nil { + log.Error("s.wdb.UpdateOrderPay(ord.ID,schema.SuccPayment,dbTx)", "err", err) + dbTx.Rollback() + break + } } + if err = s.wdb.UpdateReceiptStatus(urtx.RawId, schema.Spent, dbTx); err != nil { log.Error("s.wdb.UpdateReceiptStatus(urtx.ID,schema.Spent,dbTx)", "err", err) dbTx.Rollback() @@ -257,6 +266,63 @@ func (s *Arseeding) mergeReceiptAndOrder() { } } +func checkOrdersAmount(ordArr []schema.Order, txAmount string) error { + txAmountInt, ok := new(big.Int).SetString(txAmount, 10) + if !ok { + return errors.New("txAmount incorrect") + } + totalFee := big.NewInt(0) + for _, ord := range ordArr { + fee, ok := new(big.Int).SetString(ord.Fee, 10) + if !ok { + return errors.New("order fee incorrect") + } + totalFee = new(big.Int).Add(totalFee, fee) + } + if txAmountInt.Cmp(totalFee) < 0 { + return errors.New("payAmount fee not enough") + } + return nil +} + +func checkOrdersCurrency(ordArr []schema.Order, txSymbol string) error { + for _, ord := range ordArr { + if strings.ToUpper(ord.Currency) != strings.ToUpper(txSymbol) { + return errors.New("currency incorrect") + } + } + return nil +} + +func parseItemIds(txData string) ([]string, error) { + itemIds := make([]string, 0) + res := gjson.Parse(txData) + // appName must be arseeding + if res.Get("appName").String() != "arseeding" { + return nil, errors.New("txData.appName not be arseeding") + } + for _, it := range res.Get("itemIds").Array() { + itemIds = append(itemIds, it.String()) + } + if len(itemIds) == 0 { + return nil, errors.New("itemIds is empty") + } + return itemIds, nil +} + +func (s *Arseeding) getUnPaidOrdersByItemIds(itemIds []string) ([]schema.Order, error) { + ordArr := make([]schema.Order, 0, len(itemIds)) + for _, itemId := range itemIds { + ord, err := s.wdb.GetUnPaidOrder(itemId) + if err != nil { + log.Error("s.wdb.GetUnPaidOrder(itemId)", "err", err, "itemId", itemId) + return nil, err + } + ordArr = append(ordArr, ord) + } + return ordArr, nil +} + func (s *Arseeding) refundReceipt() { recpts, err := s.wdb.GetReceiptsByStatus(schema.UnRefund) if err != nil { @@ -278,8 +344,9 @@ func (s *Arseeding) refundReceipt() { } // everTx data mmap := map[string]string{ - "App-Name": "arseeding", - "Refund-EverHash": rpt.EverHash, + "appName": "arseeding", + "action": "refund", + "refundEverHash": rpt.EverHash, } data, _ := json.Marshal(mmap) everTx, err := s.everpaySdk.Transfer(rpt.Symbol, amount, rpt.From, string(data)) diff --git a/manifest.go b/manifest.go index da42ec1..5a2a539 100644 --- a/manifest.go +++ b/manifest.go @@ -15,8 +15,6 @@ func handleManifest(maniData []byte, path string, db *Store) ([]types.Tag, []byt return nil, nil, err } - originalPath := path - path = strings.TrimPrefix(path, "/") path = strings.TrimSuffix(path, "/") if path == "" { @@ -27,14 +25,11 @@ func handleManifest(maniData []byte, path string, db *Store) ([]types.Tag, []byt } txId, ok := mani.Paths[path] if !ok { - if originalPath[len(originalPath)-1] == '/' { - txId, ok = mani.Paths[path+"/"+"index.html"] - if !ok { - return nil, nil, schema.ErrPageNotFound - } - } else { - return nil, nil, schema.ErrPageNotFound - } + // could ignore index.html, so add index.html and try again + txId, ok = mani.Paths[path+"/"+"index.html"] + } + if !ok { + return nil, nil, schema.ErrPageNotFound } tags, data, err := getArTxOrItemData(txId.TxId, db) diff --git a/common/middleware.go b/middleware.go similarity index 68% rename from common/middleware.go rename to middleware.go index 5422253..4460f73 100644 --- a/common/middleware.go +++ b/middleware.go @@ -1,9 +1,10 @@ -package common +package arseeding import ( "encoding/base32" "errors" "fmt" + "github.com/everFinance/arseeding/schema" "github.com/everFinance/goar/utils" "github.com/gin-gonic/gin" "github.com/ulule/limiter/v3" @@ -67,31 +68,46 @@ func CORSMiddleware() gin.HandlerFunc { } } -func SandboxMiddleware() gin.HandlerFunc { +func ManifestMiddleware(wdb *Wdb, store *Store) gin.HandlerFunc { return func(c *gin.Context) { - txId := getTxIdFromPath(c.Request.RequestURI) - isBrowser := false - if strings.Contains(c.GetHeader("User-Agent"), "Mozilla") { - isBrowser = true - } - if isBrowser && txId != "" { - currentSandbox := getRequestSandbox(c.Request) - expectedSandbox := expectedTxSandbox(txId) - if currentSandbox != expectedSandbox { + prefixUri := getRequestSandbox(c.Request.Host) + if len(prefixUri) > 0 && c.Request.Method == "GET" { + // compatible url https://xxxxxxx.arseed.web3infra.dev/{{arId}} + txId := getTxIdFromPath(c.Request.RequestURI) + if txId != "" && prefixUri == expectedTxSandbox(txId) { protocol := "https" if c.Request.TLS == nil { protocol = "http" } - redirectUrl := fmt.Sprintf("%s://%s.%s%s", protocol, expectedSandbox, c.Request.Host, c.Request.RequestURI) - // add "/" fix double slash - redirectUrl = strings.TrimSuffix(redirectUrl, "/") - if c.Param("path") == "" { - redirectUrl = redirectUrl + "/" - } - + // redirect url: https://arseed.web3infra.dev/{{arId}} + rootHost := strings.SplitN(c.Request.Host, ".", 2)[1] + redirectUrl := fmt.Sprintf("%s://%s/%s", protocol, rootHost, txId) c.Redirect(302, redirectUrl) + + c.Abort() + return + } + + mfId, err := wdb.GetManifestId(prefixUri) + if err != nil { + c.Next() + return + } + _, mfData, err := getArTxOrItemData(mfId, store) + if err != nil { + c.Abort() + internalErrorResponse(c, err.Error()) return } + tags, data, err := handleManifest(mfData, c.Request.URL.Path, store) + if err != nil { + c.Abort() + internalErrorResponse(c, err.Error()) + return + } + c.Abort() + c.Data(http.StatusOK, fmt.Sprintf("%s; charset=utf-8", getTagValue(tags, schema.ContentType)), data) + return } c.Next() } @@ -106,10 +122,10 @@ func getTxIdFromPath(path string) string { return "" } -func getRequestSandbox(req *http.Request) string { - hostStr := strings.Split(req.Host, ".") - if len(hostStr) > 0 { - return strings.ToLower(hostStr[0]) +func getRequestSandbox(host string) string { + prefix := strings.Split(host, ".")[0] + if len(prefix) > 40 { // todo 40 + return prefix } return "" } diff --git a/middleware_test.go b/middleware_test.go new file mode 100644 index 0000000..cd01617 --- /dev/null +++ b/middleware_test.go @@ -0,0 +1,10 @@ +package arseeding + +import "testing" + +func TestSandboxMiddleware(t *testing.T) { + host := "p6qmubetdqoqlsoktncg3hiec2nbyjmgqgmhboopftn67xfk.arseed.web3infura.io" + + res := getRequestSandbox(host) + t.Log(res) +} diff --git a/schema/manifest.go b/schema/manifest.go index 92c9e7a..90bfe2d 100644 --- a/schema/manifest.go +++ b/schema/manifest.go @@ -33,8 +33,10 @@ const ( ) type ManifestData struct { - Index IndexPath `json:"index"` - Paths map[string]Resource `json:"paths"` + Manifest string `json:"manifest"` // must be "arweave/paths" + Version string `json:"version"` // currently "0.1.0" + Index IndexPath `json:"index"` + Paths map[string]Resource `json:"paths"` } type IndexPath struct { @@ -44,3 +46,9 @@ type IndexPath struct { type Resource struct { TxId string `json:"id"` } + +type Manifest struct { + ID uint `gorm:"primarykey"` + ManifestUrl string `gorm:"index:idx1"` + ManifestId string // arId +} diff --git a/sdk/manifest.go b/sdk/manifest.go new file mode 100644 index 0000000..84697fe --- /dev/null +++ b/sdk/manifest.go @@ -0,0 +1,126 @@ +package sdk + +import ( + "encoding/json" + seedSchema "github.com/everFinance/arseeding/schema" + "github.com/everFinance/arseeding/sdk/schema" + "github.com/everFinance/goar/types" + "github.com/panjf2000/ants/v2" + "io/ioutil" + "os" + "path" + "path/filepath" + "strings" + "sync" +) + +func (s *SDK) UploadFolder(rootPath string, batchSize int, indexFile string, currency string) ([]*seedSchema.RespOrder, error) { + if indexFile == "" { + indexFile = "index.html" + } + + // create manifest data + manifestFile := &seedSchema.ManifestData{ + Manifest: "arweave/paths", + Version: "0.1.0", + Index: seedSchema.IndexPath{ + Path: indexFile, + }, + Paths: make(map[string]seedSchema.Resource), + } + + pathFiles, err := getPathFiles(rootPath) + if err != nil { + return nil, err + } + + orders := make([]*seedSchema.RespOrder, 0, len(pathFiles)) + + var ( + lock sync.Mutex + wg sync.WaitGroup + ) + + if batchSize == 0 { + batchSize = 10 + } + p, _ := ants.NewPoolWithFunc(batchSize, func(i interface{}) { + fp := i.(string) + data, err := readFileData(rootPath, fp) + if err != nil { + panic(err) + } + // bundle item and send to arseeding + order, err := s.SendData(data, currency, nil) + if err != nil { + panic(err) + } + lock.Lock() + orders = append(orders, order) + // add manifest file + manifestFile.Paths[fp] = seedSchema.Resource{ + TxId: order.ItemId, + } + lock.Unlock() + wg.Done() + }, ants.WithPanicHandler(func(err interface{}) { + panic(err) + })) + + defer p.Release() + + for _, fp := range pathFiles { + wg.Add(1) + _ = p.Invoke(fp) + } + wg.Wait() + + // submit manifest file + manifestFileBy, err := json.Marshal(manifestFile) + if err != nil { + return nil, err + } + order, err := s.SendData(manifestFileBy, currency, &schema.OptionItem{ + Tags: []types.Tag{{Name: "Type", Value: "manifest"}, {Name: "Content-Type", Value: "application/x.arweave-manifest+json"}}, + }) + if err != nil { + return nil, err + } + orders = append(orders, order) + return orders, nil +} + +func readFileData(rootPath, filePath string) ([]byte, error) { + allPath := path.Join(rootPath, filePath) + data, err := ioutil.ReadFile(allPath) + return data, err +} + +func getPathFiles(rootPath string) ([]string, error) { + var files []string + err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + rootAbs, err := filepath.Abs(rootPath) + if err != nil { + return err + } + + fileAbs, err := filepath.Abs(path) + if err != nil { + return err + } + pp := strings.TrimPrefix(fileAbs, rootAbs+"/") + files = append(files, pp) + return nil + }) + if err != nil { + return nil, err + } + + return files, nil +} diff --git a/sdk/manifest_test.go b/sdk/manifest_test.go new file mode 100644 index 0000000..6aaad78 --- /dev/null +++ b/sdk/manifest_test.go @@ -0,0 +1,35 @@ +package sdk + +import ( + "github.com/everFinance/goether" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSDK_UploadFolder(t *testing.T) { + priKey := "1d8bdd0d2f1e73dffe1111111118325b7e195669541f76559760ef615a588be3" + eccSigner, err := goether.NewSigner(priKey) + if err != nil { + panic(err) + } + seedUrl := "http://127.0.0.1:8080" + payUrl := "https://api-dev.everpay.io" + sdk, err := NewSDK(seedUrl, payUrl, eccSigner) + if err != nil { + panic(err) + } + + rootPath := "./dist" + orders, err := sdk.UploadFolder(rootPath, 20, "", "usdt") + if err != nil { + panic(err) + } + t.Log(orders[len(orders)-1].ItemId) + t.Log(len(orders)) + + // pay orders + everTxs, err := sdk.BatchPayOrders(orders) + assert.NoError(t, err) + t.Log(len(everTxs)) + t.Log(everTxs[0].HexHash()) +} diff --git a/sdk/sdk.go b/sdk/sdk.go index aa72c96..7cc79ff 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -3,7 +3,6 @@ package sdk import ( "encoding/json" "errors" - "fmt" arseedSchema "github.com/everFinance/arseeding/schema" "github.com/everFinance/arseeding/sdk/schema" paySchema "github.com/everFinance/everpay-go/pay/schema" @@ -42,7 +41,7 @@ func (s *SDK) SendDataAndPay(data []byte, currency string, option *schema.Option return } itemId = order.ItemId - everTx, err = s.PayOrder(order) + everTx, err = s.PayOrders([]*arseedSchema.RespOrder{order}) return } @@ -60,22 +59,85 @@ func (s *SDK) SendData(data []byte, currency string, option *schema.OptionItem) return } -func (s *SDK) PayOrder(order *arseedSchema.RespOrder) (everTx *paySchema.Transaction, err error) { - if order == nil { +func (s *SDK) BatchPayOrders(orders []*arseedSchema.RespOrder) (everTxs []*paySchema.Transaction, err error) { + if len(orders) <= 500 { + everTx, err := s.PayOrders(orders) + if err != nil { + return nil, err + } + return []*paySchema.Transaction{everTx}, nil + } + + // more than 500 + start := 0 + end := 500 + for { + subOrders := orders[start:end] + everTx, err := s.PayOrders(subOrders) + if err != nil { + return nil, err + } + everTxs = append(everTxs, everTx) + + start = end + end += 500 + if end > len(orders) { + end = len(orders) + } + if start == end { + break + } + } + return +} + +func (s *SDK) PayOrders(orders []*arseedSchema.RespOrder) (everTx *paySchema.Transaction, err error) { + if len(orders) == 0 { return nil, errors.New("order is null") } - if order.Fee == "" { // arseeding NO_FEE module + if orders[0].Fee == "" { // arseeding NO_FEE module return } - amount, ok := new(big.Int).SetString(order.Fee, 10) - if !ok { - err = errors.New(fmt.Sprintf("new(big.Int).SetString(order.Fee, 10); fee=%s", order.Fee)) - return + + // orders can not more than 500 + if len(orders) > 500 { + return nil, errors.New("please use BatchPayOrders function") + } + + // check orders + if len(orders) > 1 { + bundler := orders[0].Bundler + currency := orders[0].Currency + for _, ord := range orders[1:] { + if ord.Bundler != bundler || ord.Currency != currency { + return nil, errors.New("orders bundler and currency must be equal") + } + } + } + totalFee := big.NewInt(0) + itemIds := make([]string, 0, len(orders)) + for _, ord := range orders { + feeInt, ok := new(big.Int).SetString(ord.Fee, 10) + if !ok { + return nil, errors.New("order fee incorrect") + } + totalFee = new(big.Int).Add(totalFee, feeInt) + itemIds = append(itemIds, ord.ItemId) + } + + payTxData := struct { + AppName string `json:"appName"` + Action string `json:"action"` + ItemIds []string `json:"itemIds"` + }{ + AppName: "arseeding", + Action: "payment", + ItemIds: itemIds, } - dataJs, err := json.Marshal(&order) + dataJs, err := json.Marshal(&payTxData) if err != nil { return } - everTx, err = s.Pay.Transfer(order.Currency, amount, order.Bundler, string(dataJs)) + everTx, err = s.Pay.Transfer(orders[0].Currency, totalFee, orders[0].Bundler, string(dataJs)) return } diff --git a/wdb.go b/wdb.go index 7e3502d..116ac02 100644 --- a/wdb.go +++ b/wdb.go @@ -27,7 +27,7 @@ func NewWdb(dsn string) *Wdb { return &Wdb{Db: db} } -func (w *Wdb) Migrate(noFee bool) error { +func (w *Wdb) Migrate(noFee, enableManifest bool) error { err := w.Db.AutoMigrate(&schema.Order{}, &schema.OnChainTx{}) if err != nil { return err @@ -35,6 +35,12 @@ func (w *Wdb) Migrate(noFee bool) error { if !noFee { err = w.Db.AutoMigrate(&schema.TokenPrice{}, &schema.ReceiptEverTx{}) } + if err != nil { + return err + } + if enableManifest { + err = w.Db.AutoMigrate(&schema.Manifest{}) + } return err } @@ -44,7 +50,7 @@ func (w *Wdb) InsertOrder(order schema.Order) error { func (w *Wdb) GetUnPaidOrder(itemId string) (schema.Order, error) { res := schema.Order{} - err := w.Db.Model(&schema.Order{}).Where("item_id = ? and payment_status = ?", itemId, schema.UnPayment).First(&res).Error + err := w.Db.Model(&schema.Order{}).Where("item_id = ? and payment_status = ?", itemId, schema.UnPayment).Last(&res).Error return res, err } @@ -75,7 +81,7 @@ func (w *Wdb) UpdateOrderPay(id uint, everHash string, paymentStatus string, tx func (w *Wdb) GetNeedOnChainOrders() ([]schema.Order, error) { res := make([]schema.Order, 0) - err := w.Db.Where("payment_status = ? and on_chain_status = ?", schema.SuccPayment, schema.WaitOnChain).Find(&res).Error + err := w.Db.Model(&schema.Order{}).Where("payment_status = ? and on_chain_status = ?", schema.SuccPayment, schema.WaitOnChain).Find(&res).Error return res, err } @@ -92,7 +98,7 @@ func (w *Wdb) GetOrdersBySigner(signer string, cursorId int64, num int) ([]schem cursorId = math.MaxInt64 } records := make([]schema.Order, 0, num) - err := w.Db.Where("signer = ? and id < ?", signer, cursorId).Order("id DESC").Limit(num).Find(&records).Error + err := w.Db.Model(&schema.Order{}).Where("signer = ? and id < ?", signer, cursorId).Order("id DESC").Limit(num).Find(&records).Error return records, err } @@ -103,18 +109,18 @@ func (w *Wdb) GetOrdersByApiKey(apiKey string, cursorId int64, pageSize int, sor if cursorId <= 0 { cursorId = 0 } - err = w.Db.Where("api_key = ? and id > ?", apiKey, cursorId).Order("id ASC").Limit(pageSize).Find(&records).Error + err = w.Db.Model(&schema.Order{}).Where("api_key = ? and id > ?", apiKey, cursorId).Order("id ASC").Limit(pageSize).Find(&records).Error } else { if cursorId <= 0 { cursorId = math.MaxInt64 } - err = w.Db.Where("api_key = ? and id < ?", apiKey, cursorId).Order("id DESC").Limit(pageSize).Find(&records).Error + err = w.Db.Model(&schema.Order{}).Where("api_key = ? and id < ?", apiKey, cursorId).Order("id DESC").Limit(pageSize).Find(&records).Error } return records, err } func (w *Wdb) ExistProcessedOrderItem(itemId string) (res schema.Order, exist bool) { - err := w.Db.Where("item_id = ? and (on_chain_status = ? or on_chain_status = ?)", itemId, schema.PendingOnChain, schema.SuccOnChain).First(&res).Error + err := w.Db.Model(&schema.Order{}).Where("item_id = ? and (on_chain_status = ? or on_chain_status = ?)", itemId, schema.PendingOnChain, schema.SuccOnChain).First(&res).Error if err == nil { exist = true } @@ -202,3 +208,13 @@ func (w *Wdb) UpdateArTx(id uint, arId string, curHeight int64, dataSize, reward data["status"] = status return w.Db.Model(&schema.OnChainTx{}).Where("id = ?", id).Updates(data).Error } + +func (w *Wdb) InsertManifest(mf schema.Manifest) error { + return w.Db.Create(&mf).Error +} + +func (w *Wdb) GetManifestId(mfUrl string) (string, error) { + res := schema.Manifest{} + err := w.Db.Model(&schema.Manifest{}).Where("manifest_url = ?", mfUrl).Last(&res).Error + return res.ManifestId, err +}