@@ -6,13 +6,10 @@ import ( | |||
"net/http" | |||
"strings" | |||
"github.com/imosed/signet/client" | |||
. "github.com/imosed/signet/data" | |||
"github.com/imosed/signet/utils" | |||
"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" | |||
) | |||
@@ -42,56 +39,21 @@ func Contribute(resp http.ResponseWriter, req *http.Request) { | |||
return | |||
} | |||
var result SuccessResponse | |||
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 { | |||
log.Error().Err(err).Msg("Could not submit contribution transaction") | |||
log.Error().Err(err).Msg("Could not send asset in contribution") | |||
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) | |||
if err != nil { | |||
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 | |||
} |