func (c *Controller) EData() (string, error) { c.w.Header().Set("Access-Control-Allow-Origin", "*") // сколько всего продается DC eOrders, err := c.GetAll(`SELECT sell_currency_id, sum(amount) as amount FROM e_orders WHERE sell_currency_id < 1000 AND empty_time = 0 GROUP BY sell_currency_id`, 100) if err != nil { return "", utils.ErrInfo(err) } values := "" for _, data := range eOrders { values += utils.ClearNull(data["amount"], 0) + ` d` + c.CurrencyList[utils.StrToInt64(data["sell_currency_id"])] + `, ` } if len(values) > 0 { values = values[:len(values)-2] } ps, err := c.Single(`SELECT value FROM e_config WHERE name = 'ps'`).String() if err != nil { return "", utils.ErrInfo(err) } jsonData, err := json.Marshal(map[string]string{"values": values, "ps": ps}) if err != nil { return "", utils.ErrInfo(err) } return string(jsonData), nil }
func (c *Controller) EWithdraw() (string, error) { if c.SessUserId == 0 { return "", errors.New(c.Lang["sign_up_please"]) } c.r.ParseForm() currencyId := utils.StrToInt64(c.r.FormValue("currency_id")) if !utils.CheckInputData(c.r.FormValue("amount"), "amount") { return "", fmt.Errorf("incorrect amount") } method := c.r.FormValue("method") if !utils.CheckInputData(method, "method") { return "", fmt.Errorf("incorrect method") } account := c.r.FormValue("account") if !utils.CheckInputData(account, "account") { return "", fmt.Errorf("incorrect account") } amount := utils.StrToFloat64(c.r.FormValue("amount")) curTime := utils.Time() // нужно проверить, есть ли нужная сумма на счету юзера userAmount := utils.EUserAmountAndProfit(c.SessUserId, currencyId) if userAmount < amount { return "", fmt.Errorf("%s (%f<%f)", c.Lang["not_enough_money"], userAmount, amount) } if method != "Dcoin" && currencyId < 1000 { return "", fmt.Errorf("incorrect method") } err := userLock(c.SessUserId) if err != nil { return "", utils.ErrInfo(err) } err = c.ExecSql(`UPDATE e_wallets SET amount = ?, last_update = ? WHERE user_id = ? AND currency_id = ?`, userAmount-amount, curTime, c.SessUserId, currencyId) if err != nil { return "", utils.ErrInfo(err) } var commission float64 if method == "Dcoin" { commission = utils.StrToFloat64(c.EConfig["dc_commission"]) } else if method == "Perfect-money" { commission = utils.StrToFloat64(c.EConfig["pm_commission"]) } wdAmount := utils.ClearNull(utils.Float64ToStr(amount*(1-commission/100)), 2) err = c.ExecSql(`INSERT INTO e_withdraw (open_time, user_id, currency_id, account, amount, wd_amount, method) VALUES (?, ?, ?, ?, ?, ?, ?)`, curTime, c.SessUserId, currencyId, account, amount, wdAmount, method) if err != nil { return "", utils.ErrInfo(err) } userUnlock(c.SessUserId) return utils.JsonAnswer(c.Lang["request_is_created"], "success").String(), nil }
func (c *Controller) getMyWallets() ([]map[string]string, error) { var myWallets []map[string]string eCurrency, err := c.GetAll(`SELECT name as currency_name, id FROM e_currency ORDER BY sort_id ASC`, -1) if err != nil { return myWallets, utils.ErrInfo(err) } for _, data := range eCurrency { wallet, err := c.OneRow("SELECT * FROM e_wallets WHERE user_id = ? AND currency_id = ?", c.SessUserId, data["id"]).String() if err != nil { return myWallets, utils.ErrInfo(err) } if len(wallet) > 0 { amount := utils.StrToFloat64(wallet["amount"]) profit, err := utils.DB.CalcProfitGen(utils.StrToInt64(wallet["currency_id"]), amount, 0, utils.StrToInt64(wallet["last_update"]), utils.Time(), "wallet") if err != nil { return myWallets, utils.ErrInfo(err) } myWallets = append(myWallets, map[string]string{"amount": utils.ClearNull(utils.Float64ToStr(amount+profit), 2), "currency_name": data["currency_name"], "last_update": wallet["last_update"]}) } } return myWallets, nil }
func (c *Controller) EMain() (string, error) { var err error dcCurrencyId := utils.StrToInt64(c.Parameters["dc_currency_id"]) currencyId := utils.StrToInt64(c.Parameters["currency_id"]) if dcCurrencyId == 0 { dcCurrencyId = 72 } if currencyId == 0 { currencyId = 1001 } // все валюты, с которыми работаем currencyList, err := utils.EGetCurrencyList() if err != nil { return "", utils.ErrInfo(err) } log.Debug("%v", currencyList) // работаем только с теми валютами, которые есть у нас в списке if len(currencyList[dcCurrencyId]) == 0 || len(currencyList[currencyId]) == 0 { return "", utils.ErrInfo("incorrect currency") } // пары валют для меню currencyListPair, err := eGetCurrencyPair() if err != nil { return "", utils.ErrInfo(err) } dcCurrency := currencyList[dcCurrencyId] currency := currencyList[currencyId] // история сделок var tradeHistory []map[string]string rows, err := c.Query(c.FormatQuery(` SELECT sell_currency_id, sell_rate, amount, time FROM e_trade WHERE ((sell_currency_id = ? AND buy_currency_id = ?) OR (sell_currency_id = ? AND buy_currency_id = ?)) AND main = 1 ORDER BY time DESC LIMIT 40 `), dcCurrencyId, currencyId, currencyId, dcCurrencyId) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() for rows.Next() { var sellCurrencyId, eTime int64 var sellRate, amount float64 err = rows.Scan(&sellCurrencyId, &sellRate, &amount, &eTime) if err != nil { return "", utils.ErrInfo(err) } var eType string var eAmount float64 var eTotal float64 if sellCurrencyId == dcCurrencyId { eType = "sell" sellRate = 1 / sellRate eAmount = amount eTotal = amount * sellRate } else { eType = "buy" eAmount = amount * (1 / sellRate) eTotal = amount } t := time.Unix(eTime, 0) tradeHistory = append(tradeHistory, map[string]string{"Time": t.Format(c.TimeFormat), "Type": eType, "SellRate": utils.ClearNull(utils.Float64ToStr(sellRate), 4), "Amount": utils.ClearNull(utils.Float64ToStr(eAmount), 4), "Total": utils.ClearNull(utils.Float64ToStr(eTotal), 4)}) } // активные ордеры на продажу var orders eOrders rows, err = c.Query(c.FormatQuery(` SELECT sell_rate, amount FROM e_orders WHERE (sell_currency_id = ? AND buy_currency_id = ?) AND empty_time = 0 AND del_time = 0 AND amount > 0 ORDER BY sell_rate DESC LIMIT 100 `), dcCurrencyId, currencyId) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() // мин. цена покупки var buyMin float64 for rows.Next() { var sellRate, amount float64 err = rows.Scan(&sellRate, &amount) if err != nil { return "", utils.ErrInfo(err) } if orders.Sell == nil { orders.Sell = make(map[float64]float64) } sellRate = utils.ClearNullFloat64(1/sellRate, 6) orders.Sell[sellRate] = utils.ClearNullFloat64(orders.Sell[sellRate]+amount, 6) if buyMin == 0 { buyMin = sellRate } else if sellRate < buyMin { buyMin = sellRate } } keys := []float64{} for k := range orders.Sell { keys = append(keys, k) } sort.Float64s(keys) var eOrdersSell []map[string]float64 for _, k := range keys { eOrdersSell = append(eOrdersSell, map[string]float64{"sell_rate": k, "amount": orders.Sell[k]}) } // активные ордеры на покупку rows, err = c.Query(c.FormatQuery(` SELECT sell_rate, amount FROM e_orders WHERE (sell_currency_id = ? AND buy_currency_id = ?) AND empty_time = 0 AND del_time = 0 AND amount > 0 ORDER BY sell_rate ASC LIMIT 100 `), currencyId, dcCurrencyId) if err != nil { return "", utils.ErrInfo(err) } defer rows.Close() // мин. цена продажи var sellMax float64 for rows.Next() { var sellRate, amount float64 err = rows.Scan(&sellRate, &amount) if err != nil { return "", utils.ErrInfo(err) } if orders.Buy == nil { orders.Buy = make(map[float64]float64) } sellRate = utils.ClearNullFloat64(sellRate, 6) orders.Buy[sellRate] = utils.ClearNullFloat64(orders.Buy[sellRate]+amount*(1/sellRate), 6) if sellMax == 0 { sellMax = sellRate } else if sellRate < sellMax { sellMax = sellRate } } var keysR sort.Float64Slice for k := range orders.Buy { keysR = append(keysR, k) } sort.Sort(sort.Reverse(keysR)) var eOrdersBuy []map[string]float64 for _, k := range keysR { eOrdersBuy = append(eOrdersBuy, map[string]float64{"sell_rate": k, "amount": orders.Buy[k]}) } // комиссия commission := c.EConfig["commission"] commissionText := strings.Replace(c.Lang["commission_text"], "[commission]", commission, -1) // кол-во юзеров members, err := c.Single(`SELECT count(*) FROM e_users`).Int64() if err != nil { return "", utils.ErrInfo(err) } TemplateStr, err := makeTemplate("e_main", "eMain", &eMainPage{ Lang: c.Lang, Commission: commission, Members: members, SellMax: sellMax, BuyMin: buyMin, EOrdersSell: eOrdersSell, EOrdersBuy: eOrdersBuy, DcCurrency: dcCurrency, Currency: currency, DcCurrencyId: dcCurrencyId, UserId: c.SessUserId, TradeHistory: tradeHistory, CurrencyId: currencyId, CommissionText: commissionText, CurrencyListPair: currencyListPair, CurrencyList: currencyList}) if err != nil { return "", utils.ErrInfo(err) } return TemplateStr, nil }
func NewForexOrder(userId int64, amount, sellRate float64, sellCurrencyId, buyCurrencyId int64, orderType string, eCommission float64) error { log.Debug("userId: %v / amount: %v / sellRate: %v / sellCurrencyId: %v / buyCurrencyId: %v / orderType: %v ", userId, amount, sellRate, sellCurrencyId, buyCurrencyId, orderType) curTime := utils.Time() err := userLock(userId) if err != nil { return utils.ErrInfo(err) } commission := utils.StrToFloat64(utils.ClearNull(utils.Float64ToStr(amount*(eCommission/100)), 6)) newAmount := utils.StrToFloat64(utils.ClearNull(utils.Float64ToStr(amount-commission), 6)) if newAmount < commission { commission = 0 newAmount = amount } log.Debug("newAmount: %v / commission: %v ", newAmount, commission) if commission > 0 { userAmount := utils.EUserAmountAndProfit(1, sellCurrencyId) newAmount_ := userAmount + commission // наисляем комиссию системе err = utils.UpdEWallet(1, sellCurrencyId, utils.Time(), newAmount_, true) if err != nil { return utils.ErrInfo(err) } // и сразу вычитаем комиссию с кошелька юзера userAmount = utils.EUserAmountAndProfit(userId, sellCurrencyId) err = utils.DB.ExecSql("UPDATE e_wallets SET amount = ?, last_update = ? WHERE user_id = ? AND currency_id = ?", userAmount-commission, utils.Time(), userId, sellCurrencyId) if err != nil { return utils.ErrInfo(err) } } // обратный курс. нужен для поиска по ордерам reverseRate := utils.StrToFloat64(utils.ClearNull(utils.Float64ToStr(1/sellRate), 6)) log.Debug("sellRate %v", sellRate) log.Debug("reverseRate %v", reverseRate) var totalBuyAmount, totalSellAmount float64 if orderType == "buy" { totalBuyAmount = newAmount * reverseRate } else { totalSellAmount = newAmount } var debit float64 var prevUserId int64 // берем из БД только те ордеры, которые удовлетворяют нашим требованиям rows, err := utils.DB.Query(utils.DB.FormatQuery(` SELECT id, user_id, amount, sell_rate, buy_currency_id, sell_currency_id FROM e_orders WHERE buy_currency_id = ? AND sell_rate >= ? AND sell_currency_id = ? AND del_time = 0 AND empty_time = 0 ORDER BY sell_rate DESC `), sellCurrencyId, reverseRate, buyCurrencyId) if err != nil { return utils.ErrInfo(err) } defer rows.Close() for rows.Next() { var rowId, rowUserId, rowBuyCurrencyId, rowSellCurrencyId int64 var rowAmount, rowSellRate float64 err = rows.Scan(&rowId, &rowUserId, &rowAmount, &rowSellRate, &rowBuyCurrencyId, &rowSellCurrencyId) if err != nil { return utils.ErrInfo(err) } log.Debug("rowId: %v / rowUserId: %v / rowAmount: %v / rowSellRate: %v / rowBuyCurrencyId: %v / rowSellCurrencyId: %v", rowId, rowUserId, rowAmount, rowSellRate, rowBuyCurrencyId, rowSellCurrencyId) // чтобы ордеры одного и тоже юзера не вызывали стопор, пропускаем все его оредера if rowUserId == prevUserId { continue } // блокируем юзера, чей ордер взяли, кроме самого себя if rowUserId != userId { lockErr := userLock(rowUserId) if lockErr != nil { log.Error("%v", utils.ErrInfo(err)) prevUserId = rowUserId continue } } if orderType == "buy" { // удовлетворит ли данный ордер наш запрос целиком if rowAmount >= totalBuyAmount { debit = totalBuyAmount log.Debug("order ENDED") } else { debit = rowAmount } } else { // удовлетворит ли данный ордер наш запрос целиком if rowAmount/rowSellRate >= totalSellAmount { debit = totalSellAmount * rowSellRate } else { debit = rowAmount } } log.Debug("totalBuyAmount: %v / debit: %v", totalBuyAmount, debit) if rowAmount-debit < 0.01 { // ордер опустошили err = utils.DB.ExecSql("UPDATE e_orders SET amount = 0, empty_time = ? WHERE id = ?", curTime, rowId) if err != nil { return utils.ErrInfo(err) } } else { // вычитаем забранную сумму из ордера err = utils.DB.ExecSql("UPDATE e_orders SET amount = amount - ? WHERE id = ?", debit, rowId) if err != nil { return utils.ErrInfo(err) } } mySellRate := utils.ClearNull(utils.Float64ToStr(1/rowSellRate), 6) myAmount := debit * utils.StrToFloat64(mySellRate) eTradeSellCurrencyId := sellCurrencyId eTradeBuyCurrencyId := buyCurrencyId // для истории сделок err = utils.DB.ExecSql("INSERT INTO e_trade ( user_id, sell_currency_id, sell_rate, amount, buy_currency_id, time, main ) VALUES ( ?, ?, ?, ?, ?, ?, 1 )", userId, eTradeSellCurrencyId, mySellRate, myAmount, eTradeBuyCurrencyId, curTime) if err != nil { return utils.ErrInfo(err) } // тот, чей ордер обрабатываем err = utils.DB.ExecSql("INSERT INTO e_trade ( user_id, sell_currency_id, sell_rate, amount, buy_currency_id, time ) VALUES ( ?, ?, ?, ?, ?, ? )", rowUserId, eTradeBuyCurrencyId, rowSellRate, debit, eTradeSellCurrencyId, curTime) if err != nil { return utils.ErrInfo(err) } // ==== Продавец валюты (тот, чей ордер обработали) ==== // сколько продавец данного ордера продал валюты sellerSellAmount := debit // сколько продавец получил buy_currency_id с продажи суммы $seller_sell_amount по его курсу sellerBuyAmount := sellerSellAmount * (1 / rowSellRate) // начисляем валюту, которую продавец получил (R) userAmount := utils.EUserAmountAndProfit(rowUserId, rowBuyCurrencyId) newAmount_ := userAmount + sellerBuyAmount err = utils.UpdEWallet(rowUserId, rowBuyCurrencyId, utils.Time(), newAmount_, true) if err != nil { return utils.ErrInfo(err) } // ====== Покупатель валюты (наш юзер) ====== // списываем валюту, которую мы продали (R) userAmount = utils.EUserAmountAndProfit(userId, rowBuyCurrencyId) newAmount_ = userAmount - sellerBuyAmount err = utils.UpdEWallet(userId, rowBuyCurrencyId, utils.Time(), newAmount_, true) if err != nil { return utils.ErrInfo(err) } // начисляем валюту, которую мы получили (U) userAmount = utils.EUserAmountAndProfit(userId, rowSellCurrencyId) newAmount_ = userAmount + sellerSellAmount err = utils.UpdEWallet(userId, rowSellCurrencyId, utils.Time(), newAmount_, true) if err != nil { return utils.ErrInfo(err) } if orderType == "buy" { totalBuyAmount -= rowAmount if totalBuyAmount <= 0 { userUnlock(rowUserId) log.Debug("total_buy_amount == 0 break") break // проход по ордерам прекращаем, т.к. наш запрос удовлетворен } } else { totalSellAmount -= rowAmount / rowSellRate if totalSellAmount <= 0 { userUnlock(rowUserId) log.Debug("total_sell_amount == 0 break") break // проход по ордерам прекращаем, т.к. наш запрос удовлетворен } } if rowUserId != userId { userUnlock(rowUserId) } } log.Debug("totalBuyAmount: %v / orderType: %v / sellRate: %v / reverseRate: %v", totalBuyAmount, orderType, sellRate, reverseRate) // если после прохода по всем имеющимся ордерам мы не набрали нужную сумму, то создаем свой ордер if totalBuyAmount > 0 || totalSellAmount > 0 { var newOrderAmount float64 if orderType == "buy" { newOrderAmount = totalBuyAmount * sellRate } else { newOrderAmount = totalSellAmount } log.Debug("newOrderAmount: %v", newOrderAmount) if newOrderAmount >= 0.000001 { err = utils.DB.ExecSql("INSERT INTO e_orders ( time, user_id, sell_currency_id, sell_rate, begin_amount, amount, buy_currency_id ) VALUES ( ?, ?, ?, ?, ?, ?, ? )", curTime, userId, sellCurrencyId, sellRate, newOrderAmount, newOrderAmount, buyCurrencyId) if err != nil { return utils.ErrInfo(err) } // вычитаем с баланса сумму созданного ордера userAmount := utils.EUserAmountAndProfit(userId, sellCurrencyId) err = utils.DB.ExecSql("UPDATE e_wallets SET amount = ?, last_update = ? WHERE user_id = ? AND currency_id = ?", userAmount-newOrderAmount, utils.Time(), userId, sellCurrencyId) if err != nil { return utils.ErrInfo(err) } } } userUnlock(userId) return nil }