| @@ -6,13 +6,10 @@ import ( | |||||
| "net/http" | "net/http" | ||||
| "strings" | "strings" | ||||
| "github.com/imosed/signet/client" | |||||
| . "github.com/imosed/signet/data" | . "github.com/imosed/signet/data" | ||||
| "github.com/imosed/signet/utils" | |||||
| "github.com/rs/zerolog/log" | "github.com/rs/zerolog/log" | ||||
| "github.com/stellar/go/clients/horizonclient" | |||||
| "github.com/stellar/go/keypair" | "github.com/stellar/go/keypair" | ||||
| "github.com/stellar/go/network" | |||||
| "github.com/stellar/go/protocols/horizon" | |||||
| "github.com/stellar/go/txnbuild" | "github.com/stellar/go/txnbuild" | ||||
| ) | ) | ||||
| @@ -42,56 +39,21 @@ func Contribute(resp http.ResponseWriter, req *http.Request) { | |||||
| return | return | ||||
| } | } | ||||
| var result SuccessResponse | |||||
| source := keypair.MustParseFull(cont.PrivateKey) | source := keypair.MustParseFull(cont.PrivateKey) | ||||
| sourceReq := horizonclient.AccountRequest{AccountID: source.Address()} | |||||
| var sourceAcct horizon.Account | |||||
| sourceAcct, err = client.SignetClient.AccountDetail(sourceReq) | |||||
| if err != nil { | |||||
| log.Error().Err(err).Msg("Could not get account details from Horizon SignetClient") | |||||
| return | |||||
| } | |||||
| tx, err := txnbuild.NewTransaction( | |||||
| txnbuild.TransactionParams{ | |||||
| SourceAccount: &sourceAcct, | |||||
| IncrementSequenceNum: true, | |||||
| Operations: []txnbuild.Operation{ | |||||
| &txnbuild.Payment{ | |||||
| Destination: fund.FundWallet, | |||||
| Amount: fmt.Sprintf("%f", cont.Amount), | |||||
| Asset: txnbuild.NativeAsset{}, | |||||
| SourceAccount: source.Address(), | |||||
| }, | |||||
| }, | |||||
| BaseFee: txnbuild.MinBaseFee, | |||||
| Memo: txnbuild.Memo(txnbuild.MemoText(fund.Memo)), | |||||
| Preconditions: txnbuild.Preconditions{ | |||||
| TimeBounds: txnbuild.NewTimeout(15), | |||||
| }, | |||||
| }) | |||||
| if err != nil { | |||||
| log.Error().Err(err).Msg("Could not create contribution transaction") | |||||
| return | |||||
| } | |||||
| tx, err = tx.Sign(network.TestNetworkPassphrase, source) | |||||
| if err != nil { | |||||
| log.Error().Err(err).Msg("Could not sign contribution transaction") | |||||
| return | |||||
| } | |||||
| var response horizon.Transaction | |||||
| response, err = client.SignetClient.SubmitTransaction(tx) | |||||
| result.Success, err = utils.SendAsset(source, txnbuild.Memo(txnbuild.MemoText(fund.Memo)), []txnbuild.Operation{ | |||||
| &txnbuild.Payment{ | |||||
| Destination: fund.FundWallet, | |||||
| Amount: fmt.Sprintf("%f", cont.Amount), | |||||
| Asset: txnbuild.NativeAsset{}, | |||||
| SourceAccount: source.Address(), | |||||
| }, | |||||
| }) | |||||
| if err != nil { | if err != nil { | ||||
| log.Error().Err(err).Msg("Could not submit contribution transaction") | |||||
| log.Error().Err(err).Msg("Could not send asset in contribution") | |||||
| return | return | ||||
| } | } | ||||
| log.Info().Msg(fmt.Sprintf("Successful Transaction: { Ledger: %d, Hash: %s }", response.Ledger, response.Hash)) | |||||
| var result SuccessResponse | |||||
| result.Success = response.Successful && err == nil | |||||
| err = json.NewEncoder(resp).Encode(&result) | err = json.NewEncoder(resp).Encode(&result) | ||||
| if err != nil { | if err != nil { | ||||
| log.Error().Err(err).Msg("Could not create response for new contribution") | log.Error().Err(err).Msg("Could not create response for new contribution") | ||||
| @@ -0,0 +1,70 @@ | |||||
| package endpoints | |||||
| import ( | |||||
| "encoding/json" | |||||
| "fmt" | |||||
| "net/http" | |||||
| . "github.com/imosed/signet/data" | |||||
| "github.com/imosed/signet/utils" | |||||
| "github.com/stellar/go/keypair" | |||||
| "github.com/stellar/go/txnbuild" | |||||
| ) | |||||
| type RewardDistributionInfo struct { | |||||
| Destination string `json:"destination"` | |||||
| Amount float64 `json:"amount"` | |||||
| } | |||||
| type DistributeRewardsRequest struct { | |||||
| RewardFundID uint `json:"rewardFundID"` | |||||
| Payments []RewardDistributionInfo `json:"payments"` | |||||
| Distribute bool `json:"distribute"` | |||||
| } | |||||
| func DistributeRewards(w http.ResponseWriter, r *http.Request) { | |||||
| var req DistributeRewardsRequest | |||||
| err := json.NewDecoder(r.Body).Decode(&req) | |||||
| if err != nil { | |||||
| panic("Could not decode body") | |||||
| } | |||||
| var fund RewardFund | |||||
| Db.Table("reward_funds").Where("id = ?", req.RewardFundID).Scan(&fund) | |||||
| var resp SuccessResponse | |||||
| resp.Success = false | |||||
| if req.Distribute { | |||||
| source := keypair.MustParseFull(fund.FundSecret) | |||||
| resp.Success, err = utils.SendAsset( | |||||
| source, | |||||
| nil, | |||||
| constructOperations( | |||||
| source, | |||||
| txnbuild.CreditAsset{ | |||||
| Code: fund.Asset, | |||||
| Issuer: fund.IssuerWallet, | |||||
| }, | |||||
| req.Payments), | |||||
| ) | |||||
| } | |||||
| err = json.NewEncoder(w).Encode(resp) | |||||
| if err != nil { | |||||
| panic("Could not deliver response") | |||||
| } | |||||
| } | |||||
| func constructOperations(sourceAccount *keypair.Full, asset txnbuild.CreditAsset, payments []RewardDistributionInfo) []txnbuild.Operation { | |||||
| var operations []txnbuild.Operation | |||||
| for _, payment := range payments { | |||||
| operations = append(operations, &txnbuild.Payment{ | |||||
| Destination: payment.Destination, | |||||
| Amount: fmt.Sprintf("%f", payment.Amount), | |||||
| Asset: asset, | |||||
| SourceAccount: sourceAccount.Address(), | |||||
| }) | |||||
| } | |||||
| return operations | |||||
| } | |||||
| @@ -0,0 +1,56 @@ | |||||
| package utils | |||||
| import ( | |||||
| "fmt" | |||||
| "github.com/imosed/signet/client" | |||||
| "github.com/rs/zerolog/log" | |||||
| "github.com/stellar/go/clients/horizonclient" | |||||
| "github.com/stellar/go/keypair" | |||||
| "github.com/stellar/go/network" | |||||
| "github.com/stellar/go/protocols/horizon" | |||||
| "github.com/stellar/go/txnbuild" | |||||
| ) | |||||
| func SendAsset(from *keypair.Full, memo txnbuild.Memo, operations []txnbuild.Operation) (bool, error) { | |||||
| var err error | |||||
| source := keypair.MustParseFull(from.Seed()) | |||||
| sourceReq := horizonclient.AccountRequest{AccountID: source.Address()} | |||||
| var sourceAcct horizon.Account | |||||
| sourceAcct, err = client.SignetClient.AccountDetail(sourceReq) | |||||
| if err != nil { | |||||
| return false, err | |||||
| } | |||||
| tx, err := txnbuild.NewTransaction( | |||||
| txnbuild.TransactionParams{ | |||||
| SourceAccount: &sourceAcct, | |||||
| IncrementSequenceNum: true, | |||||
| Operations: operations, | |||||
| BaseFee: txnbuild.MinBaseFee, | |||||
| Memo: memo, | |||||
| Preconditions: txnbuild.Preconditions{ | |||||
| TimeBounds: txnbuild.NewTimeout(15), | |||||
| }, | |||||
| }) | |||||
| if err != nil { | |||||
| return false, err | |||||
| } | |||||
| tx, err = tx.Sign(network.TestNetworkPassphrase, source) | |||||
| if err != nil { | |||||
| return false, err | |||||
| } | |||||
| var response horizon.Transaction | |||||
| response, err = client.SignetClient.SubmitTransaction(tx) | |||||
| if err != nil { | |||||
| return false, err | |||||
| } | |||||
| log.Info().Msg(fmt.Sprintf("Successful Transaction: { Ledger: %d, Hash: %s }", response.Ledger, response.Hash)) | |||||
| return true, nil | |||||
| } | |||||