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