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.

101 lines
2.8 KiB

  1. package endpoints
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. . "github.com/imosed/signet/data"
  8. "github.com/rs/zerolog/log"
  9. "github.com/stellar/go/clients/horizonclient"
  10. "github.com/stellar/go/keypair"
  11. "github.com/stellar/go/network"
  12. "github.com/stellar/go/protocols/horizon"
  13. "github.com/stellar/go/txnbuild"
  14. )
  15. type ContributeRequest struct {
  16. PrivateKey string `json:"privateKey"`
  17. Amount float64 `json:"amount"`
  18. RewardFund uint `json:"rewardFund"`
  19. }
  20. func Contribute(resp http.ResponseWriter, req *http.Request) {
  21. var cont ContributeRequest
  22. err := json.NewDecoder(req.Body).Decode(&cont)
  23. if err != nil {
  24. log.Error().Err(err).Msg("Could not read in contribution")
  25. return
  26. }
  27. var fund RewardFund
  28. Db.Table("reward_funds").Select("id", "deleted_at", "fund_wallet", "memo", "min_contribution").First(&fund, cont.RewardFund)
  29. if cont.Amount < fund.MinContribution || !strings.HasPrefix(cont.PrivateKey, "S") || !fund.DeletedAt.Time.IsZero() {
  30. err = json.NewEncoder(resp).Encode(&SuccessResponse{Success: false})
  31. if err != nil {
  32. log.Error().Err(err).Msg("Could not deliver unsuccessful contribution response")
  33. }
  34. return
  35. }
  36. source := keypair.MustParseFull(cont.PrivateKey)
  37. sourceReq := horizonclient.AccountRequest{AccountID: source.Address()}
  38. var sourceAcct horizon.Account
  39. sourceAcct, err = client.AccountDetail(sourceReq)
  40. if err != nil {
  41. log.Error().Err(err).Msg("Could not get account details from Horizon client")
  42. return
  43. }
  44. tx, err := txnbuild.NewTransaction(
  45. txnbuild.TransactionParams{
  46. SourceAccount: &sourceAcct,
  47. IncrementSequenceNum: true,
  48. Operations: []txnbuild.Operation{
  49. &txnbuild.Payment{
  50. Destination: fund.FundWallet,
  51. Amount: fmt.Sprintf("%f", cont.Amount),
  52. Asset: txnbuild.NativeAsset{},
  53. SourceAccount: source.Address(),
  54. },
  55. },
  56. BaseFee: txnbuild.MinBaseFee,
  57. Memo: txnbuild.Memo(txnbuild.MemoText(fund.Memo)),
  58. Preconditions: txnbuild.Preconditions{
  59. TimeBounds: txnbuild.NewTimeout(15),
  60. },
  61. })
  62. if err != nil {
  63. log.Error().Err(err).Msg("Could not create contribution transaction")
  64. return
  65. }
  66. tx, err = tx.Sign(network.TestNetworkPassphrase, source)
  67. if err != nil {
  68. log.Error().Err(err).Msg("Could not sign contribution transaction")
  69. return
  70. }
  71. var response horizon.Transaction
  72. response, err = client.SubmitTransaction(tx)
  73. if err != nil {
  74. log.Error().Err(err).Msg("Could not submit contribution transaction")
  75. return
  76. }
  77. fmt.Println("Successful Transaction:")
  78. fmt.Println("Ledger:", response.Ledger)
  79. fmt.Println("Hash:", response.Hash)
  80. var result SuccessResponse
  81. result.Success = response.Successful && err == nil
  82. err = json.NewEncoder(resp).Encode(&result)
  83. if err != nil {
  84. log.Error().Err(err).Msg("Could not create response for new contribution")
  85. }
  86. }