The backend for the project formerly known as signet, now known as beignet.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 line
3.7 KiB

  1. package endpoints
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "github.com/imosed/signet/client"
  7. . "github.com/imosed/signet/data"
  8. "github.com/imosed/signet/utils"
  9. "github.com/rs/zerolog/log"
  10. "github.com/stellar/go/clients/horizonclient"
  11. "github.com/stellar/go/keypair"
  12. "github.com/stellar/go/network"
  13. "github.com/stellar/go/protocols/horizon"
  14. "github.com/stellar/go/txnbuild"
  15. "github.com/stellar/go/xdr"
  16. "gorm.io/gorm/clause"
  17. )
  18. type SubmitFundRequest struct {
  19. FundID uint `json:"fundID"`
  20. Submit bool `json:"submit"`
  21. }
  22. func SubmitFund(w http.ResponseWriter, r *http.Request) {
  23. var req SubmitFundRequest
  24. err := json.NewDecoder(r.Body).Decode(&req)
  25. if err != nil {
  26. log.Error().Err(err).Msg("Could not decode body in SubmitFund call")
  27. }
  28. var fund RewardFund
  29. Db.Preload(clause.Associations).Find(&fund, req.FundID)
  30. var resp SuccessResponse
  31. if !req.Submit {
  32. json.NewEncoder(w).Encode(&SuccessResponse{Success: false})
  33. return
  34. }
  35. source := keypair.MustParseFull(fund.FundSecret)
  36. sourceReq := horizonclient.AccountRequest{AccountID: source.Address()}
  37. var sourceAcct horizon.Account
  38. sourceAcct, err = client.SignetClient.AccountDetail(sourceReq)
  39. offerReq := horizonclient.OfferRequest{
  40. Seller: fund.SellingWallet,
  41. Selling: fmt.Sprintf("%s:%s", fund.Asset, fund.IssuerWallet),
  42. Order: horizonclient.OrderDesc,
  43. }
  44. if err, ok := utils.FindOffer(offerReq, &fund); !ok {
  45. err = json.NewEncoder(w).Encode(&SuccessResponse{Success: ok})
  46. if err != nil {
  47. log.Error().Err(err).Msg("Could not deliver response after failing to find issuer offer in submission")
  48. }
  49. return
  50. }
  51. var currentContributions = fund.Contributions
  52. var submissionAmount = SumContributions(currentContributions)
  53. tr := Db.Begin()
  54. tr.Table("contributions").
  55. Where("reward_fund_id = ? and submitted is null or submitted = false", req.FundID).
  56. Updates(Contribution{Submitted: true})
  57. var tx *txnbuild.Transaction
  58. tx, err = txnbuild.NewTransaction(
  59. txnbuild.TransactionParams{
  60. SourceAccount: &sourceAcct,
  61. IncrementSequenceNum: true,
  62. Operations: []txnbuild.Operation{
  63. &txnbuild.ChangeTrust{
  64. Line: txnbuild.CreditAsset{
  65. Code: fund.Asset,
  66. Issuer: fund.IssuerWallet,
  67. }.MustToChangeTrustAsset(),
  68. SourceAccount: fund.FundWallet,
  69. },
  70. &txnbuild.ManageBuyOffer{
  71. Selling: txnbuild.NativeAsset{},
  72. Buying: txnbuild.CreditAsset{
  73. Code: fund.Asset,
  74. Issuer: fund.IssuerWallet,
  75. },
  76. Amount: fmt.Sprintf("%f", submissionAmount),
  77. Price: xdr.Price{N: 1, D: xdr.Int32(fund.Price)},
  78. OfferID: 0,
  79. SourceAccount: fund.FundWallet,
  80. },
  81. },
  82. BaseFee: txnbuild.MinBaseFee,
  83. Memo: txnbuild.Memo(nil),
  84. Preconditions: txnbuild.Preconditions{
  85. TimeBounds: txnbuild.NewInfiniteTimeout(), // TODO: change from infinite
  86. },
  87. })
  88. if err != nil {
  89. log.Error().Err(err).Msg("Could not build submission transaction")
  90. tr.Rollback()
  91. return
  92. }
  93. tx, err = tx.Sign(network.TestNetworkPassphrase, source)
  94. if err != nil {
  95. log.Error().Err(err).Msg("Could not sign submission transaction")
  96. tr.Rollback()
  97. return
  98. }
  99. var response horizon.Transaction
  100. response, err = client.SignetClient.SubmitTransaction(tx)
  101. if err != nil {
  102. log.Error().Err(err).Msg("Could not submit transaction")
  103. tr.Rollback()
  104. return
  105. }
  106. tr.Commit()
  107. resp.Success = response.Successful
  108. err = json.NewEncoder(w).Encode(resp)
  109. if err != nil {
  110. log.Error().Err(err).Msg("Could not deliver response in SubmitFund call")
  111. }
  112. }
  113. func SumContributions(contributions []Contribution) float64 {
  114. var total float64 = 0
  115. for _, contribution := range contributions {
  116. if !contribution.Submitted {
  117. total += contribution.Amount
  118. }
  119. }
  120. return total
  121. }