| @@ -17,11 +17,11 @@ type RewardFund struct { | |||
| gorm.Model | |||
| Asset string `json:"asset"` | |||
| FundWallet string `json:"fundWallet"` | |||
| FundSecret string `json:"fundSecret"` | |||
| SellingWallet string `json:"sellingWallet"` | |||
| IssuerWallet string `json:"issuerWallet"` | |||
| Memo string `json:"memo"` | |||
| Price float64 `json:"price"` | |||
| AmountGoal float64 `gorm:"type:decimal(19,7)" json:"amountGoal"` | |||
| AmountAvailable float64 `gorm:"type:decimal(19,7)" json:"amountAvailable"` | |||
| MinContribution float64 `gorm:"type:decimal(19,7)" json:"minContribution"` | |||
| Contributions []Contribution `json:"contributions"` | |||
| Title string `gorm:"type:varchar(50)" json:"title"` | |||
| @@ -28,9 +28,9 @@ func Contribute(resp http.ResponseWriter, req *http.Request) { | |||
| var fund RewardFund | |||
| Db.Table("reward_funds").Select("id", "fund_wallet", "memo", "min_contribution").First(&fund, cont.RewardFund) | |||
| Db.Table("reward_funds").Select("id", "deleted_at", "fund_wallet", "memo", "min_contribution").First(&fund, cont.RewardFund) | |||
| if cont.Amount < fund.MinContribution || !strings.HasPrefix(cont.PrivateKey, "S") { | |||
| if cont.Amount < fund.MinContribution || !strings.HasPrefix(cont.PrivateKey, "S") || !fund.DeletedAt.Time.IsZero() { | |||
| err = json.NewEncoder(resp).Encode(&SuccessResponse{Success: false}) | |||
| if err != nil { | |||
| panic("Could not deliver unsuccessful contribution response") | |||
| @@ -40,7 +40,9 @@ func ContributorStream(resp http.ResponseWriter, req *http.Request) { | |||
| } | |||
| } | |||
| func InitializeContributionStream() { | |||
| var cancellations []context.CancelFunc | |||
| func InitializeContributionStreams() { | |||
| var err error | |||
| var wallets []struct { | |||
| @@ -67,7 +69,9 @@ func InitializeContributionStream() { | |||
| if tx.Memo == "" { | |||
| return | |||
| } | |||
| Db.Table("reward_funds").Select("id").Where("memo = ? and fund_wallet = ?", tx.Memo, payment.To).First(&fund) | |||
| Db.Table("reward_funds").Where("memo = ? and fund_wallet = ?", tx.Memo, payment.To).First(&fund) | |||
| newAmt := fund.AmountAvailable - amt | |||
| Db.Model(&RewardFund{}).Where("id = ?", fund.ID).Update("amount_available", newAmt) | |||
| contribution := Contribution{ | |||
| Model: gorm.Model{ | |||
| @@ -97,7 +101,8 @@ func InitializeContributionStream() { | |||
| IncludeFailed: false, | |||
| } | |||
| opReq.SetOperationsEndpoint() | |||
| ctx, _ := context.WithCancel(context.Background()) // TODO: what is cancelFunc? | |||
| ctx, cancellation := context.WithCancel(context.Background()) | |||
| cancellations = append(cancellations, cancellation) | |||
| err = client.StreamOperations(ctx, opReq, contributionUpdateHandler) | |||
| if err != nil { | |||
| panic(err.Error()) | |||
| @@ -28,10 +28,11 @@ func CreateRewardFund(resp http.ResponseWriter, req *http.Request) { | |||
| rewardFund := RewardFund{ | |||
| Asset: fund.Asset, | |||
| FundWallet: fund.FundWallet, | |||
| SellingWallet: fund.SellingWallet, | |||
| IssuerWallet: fund.IssuerWallet, | |||
| Memo: fund.Memo, | |||
| Price: 0, | |||
| AmountGoal: fund.AmountGoal, | |||
| AmountAvailable: 0, | |||
| MinContribution: fund.MinContribution, | |||
| Title: fund.Title, | |||
| Description: fund.Description, | |||
| @@ -39,24 +40,33 @@ func CreateRewardFund(resp http.ResponseWriter, req *http.Request) { | |||
| } | |||
| offerReq := horizonclient.OfferRequest{ | |||
| Seller: rewardFund.IssuerWallet, | |||
| Seller: rewardFund.SellingWallet, | |||
| Selling: fmt.Sprintf("%s:%s", rewardFund.Asset, rewardFund.IssuerWallet), | |||
| Buying: fmt.Sprintf("XLM:%s", rewardFund.IssuerWallet), | |||
| Order: horizonclient.OrderDesc, | |||
| } | |||
| url, _ := offerReq.BuildURL() | |||
| fmt.Println(url) | |||
| op, err := client.Offers(offerReq) | |||
| if err != nil { | |||
| panic("Could not get offers") | |||
| } | |||
| offers := op.Embedded.Records | |||
| var price float64 | |||
| var amt float64 | |||
| if len(offers) == 1 { | |||
| price, err = strconv.ParseFloat(op.Embedded.Records[0].Price, 64) | |||
| if err != nil { | |||
| panic("Could not parse price to float") | |||
| } | |||
| amt, err = strconv.ParseFloat(op.Embedded.Records[0].Amount, 64) | |||
| if err != nil { | |||
| panic("Could not parse amount to float") | |||
| } | |||
| rewardFund.Price = price | |||
| } else { | |||
| rewardFund.AmountAvailable = amt | |||
| } else if len(offers) > 1 { | |||
| var maxOffers float64 = 0 | |||
| var correctOffer horizon.Offer | |||
| for _, o := range op.Embedded.Records { | |||
| @@ -74,6 +84,15 @@ func CreateRewardFund(resp http.ResponseWriter, req *http.Request) { | |||
| panic("Could not parse price to float") | |||
| } | |||
| rewardFund.Price = price | |||
| amt, err = strconv.ParseFloat(correctOffer.Amount, 64) | |||
| if err != nil { | |||
| panic("Could not parse amount to float") | |||
| } | |||
| rewardFund.AmountAvailable = amt | |||
| } else { | |||
| err = json.NewEncoder(resp).Encode(&SuccessResponse{Success: false}) | |||
| return | |||
| } | |||
| var claims *auth.Claims | |||
| @@ -85,6 +104,11 @@ func CreateRewardFund(resp http.ResponseWriter, req *http.Request) { | |||
| if claims.Privileges <= Admin { | |||
| Db.Create(&rewardFund) | |||
| for _, cancel := range cancellations { | |||
| cancel() | |||
| } | |||
| go InitializeContributionStreams() | |||
| for _, bonus := range fund.Bonuses { | |||
| bonus.RewardFundID = rewardFund.ID | |||
| bonuses = append(bonuses, bonus) | |||
| @@ -62,7 +62,7 @@ func GetRewardFund(resp http.ResponseWriter, req *http.Request) { | |||
| IssuerWallet: fund.IssuerWallet, | |||
| Memo: fund.Memo, | |||
| Price: fund.Price, | |||
| AmountGoal: fund.AmountGoal, | |||
| AmountAvailable: fund.AmountAvailable, | |||
| MinContribution: fund.MinContribution, | |||
| Title: fund.Title, | |||
| Description: fund.Description, | |||
| @@ -144,7 +144,7 @@ type FundInfo struct { | |||
| IssuerWallet string `json:"issuerWallet"` | |||
| Memo string `json:"memo"` | |||
| Price float64 `json:"price"` | |||
| AmountGoal float64 `json:"amountGoal"` | |||
| AmountAvailable float64 `json:"amountAvailable"` | |||
| MinContribution float64 `json:"minContribution"` | |||
| Title string `json:"title"` | |||
| Description string `json:"description"` | |||
| @@ -18,7 +18,7 @@ func GetRewardFunds(w http.ResponseWriter, r *http.Request) { | |||
| var rewardFunds []RewardFund | |||
| Db.Table("reward_funds").Count(&resp.Total) | |||
| Db.Preload(clause.Associations).Table("reward_funds"). | |||
| Select("id", "created_at", "asset", "fund_wallet", "issuer_wallet", "memo", "amount_goal", "min_contribution", "close_time", "title"). | |||
| Select("id", "created_at", "asset", "fund_wallet", "issuer_wallet", "memo", "min_contribution", "amount_available", "title"). | |||
| Order("created_at desc"). | |||
| Find(&rewardFunds) | |||
| @@ -30,7 +30,7 @@ func GetRewardFunds(w http.ResponseWriter, r *http.Request) { | |||
| FundWallet: f.FundWallet, | |||
| IssuerWallet: f.IssuerWallet, | |||
| Memo: f.Memo, | |||
| AmountGoal: f.AmountGoal, | |||
| AmountAvailable: f.AmountAvailable, | |||
| MinContribution: f.MinContribution, | |||
| Title: f.Title, | |||
| Description: f.Description, | |||
| @@ -135,7 +135,7 @@ func Register(w http.ResponseWriter, r *http.Request) { | |||
| panic("Could not determine if user is authenticated") | |||
| } | |||
| if claims.Privileges <= AdminPlus || noUsersRegistered() { | |||
| if noUsersRegistered() || claims.Privileges <= AdminPlus { | |||
| hash, err := GenerateHash(req.Password, &Params{ | |||
| Memory: uint32(viper.GetInt("hashing.memory")), | |||
| Iterations: uint32(viper.GetInt("hashing.iterations")), | |||
| @@ -0,0 +1,20 @@ | |||
| package endpoints | |||
| import ( | |||
| "encoding/json" | |||
| . "github.com/imosed/signet/data" | |||
| "net/http" | |||
| ) | |||
| func UsersExist(w http.ResponseWriter, r *http.Request) { | |||
| var numUsers int64 | |||
| Db.Table("users").Count(&numUsers) | |||
| var resp SuccessResponse | |||
| resp.Success = numUsers > 0 | |||
| err := json.NewEncoder(w).Encode(resp) | |||
| if err != nil { | |||
| panic("Could not deliver response") | |||
| } | |||
| } | |||
| @@ -25,7 +25,7 @@ func main() { | |||
| data.InitializeDatabase() | |||
| go endpoints.InitializeContributionStream() | |||
| go endpoints.InitializeContributionStreams() | |||
| router := mux.NewRouter() | |||
| router.HandleFunc("/GetRewardFunds", endpoints.GetRewardFunds) | |||
| @@ -39,6 +39,7 @@ func main() { | |||
| router.HandleFunc("/Login", endpoints.Login) | |||
| router.HandleFunc("/Register", endpoints.Register) | |||
| router.HandleFunc("/EscalatePrivileges", endpoints.EscalatePrivileges) | |||
| router.HandleFunc("/UsersExist", endpoints.UsersExist) | |||
| port := viper.GetInt("app.port") | |||
| fmt.Printf("Running on port %d...\n", port) | |||