package service import ( "q5" "f5" "sync" "strings" "main/constant" "math/big" ) type vip struct { lock sync.Mutex } type vesterDepositWithdrawPo struct { idx int64 eventName string chainTimestamp int32 accountAddress string depositAmount string withdrawClamiedAmount string withdrawBalance string } func (this *vip) init() () { } func (this *vip) Add(accountAddress string, val string, idx int64, valField string, idxField string) bool { this.lock.Lock() defer this.lock.Unlock() extKv := [][]string{} accountAddress = strings.ToLower(accountAddress) err, ds := f5.GetGoStyleDb().NewOrmSelect( constant.BCNFT_DB, "t_vip_user", [][]string { {"account_address", accountAddress}, }) if err != nil { return false } nowTime := f5.GetApp().GetRealSeconds() updateKv := [][]string { {idxField, q5.ToString(idx)}, {"modifytime", q5.ToString(nowTime)}, } insertKv := [][]string { {"account_address", accountAddress}, {valField, val}, {idxField, q5.ToString(idx)}, {"createtime", q5.ToString(nowTime)}, {"modifytime", q5.ToString(nowTime)}, } updateKv = append(updateKv, extKv...) insertKv = append(insertKv, extKv...) if ds.Next() { if q5.ToInt64(ds.GetByName(idxField)) >= idx { return true } bnOldVal, _ := new(big.Int).SetString(ds.GetByName(valField), 10) bnVal, _ := new(big.Int).SetString(val, 10) bnNewVal := bnOldVal.Add(bnOldVal, bnVal) updateKv = append(updateKv, [][]string{{valField, bnNewVal.String()}}...) err1, _, _ := f5.GetGoStyleDb().NewUpdate( constant.BCNFT_DB, "t_vip_user", [][]string { {"account_address", accountAddress}, }, updateKv) if err1 != nil { return false } } else { err1, _, _ := f5.GetGoStyleDb().NewInsert( constant.BCNFT_DB, "t_vip_user", insertKv) if err1 != nil { return false } } return true } func (this *vip) Replace(accountAddress string, val string, idx int64, valField string, idxField string, extKv [][]string) bool { this.lock.Lock() defer this.lock.Unlock() accountAddress = strings.ToLower(accountAddress) err, ds := f5.GetGoStyleDb().NewOrmSelect( constant.BCNFT_DB, "t_vip_user", [][]string { {"account_address", accountAddress}, }) if err != nil { return false } nowTime := f5.GetApp().GetRealSeconds() updateKv := [][]string { {valField, val}, {idxField, q5.ToString(idx)}, {"modifytime", q5.ToString(nowTime)}, } insertKv := [][]string { {"account_address", accountAddress}, {valField, val}, {idxField, q5.ToString(idx)}, {"createtime", q5.ToString(nowTime)}, {"modifytime", q5.ToString(nowTime)}, } updateKv = append(updateKv, extKv...) insertKv = append(insertKv, extKv...) if ds.Next() { if q5.ToInt64(ds.GetByName(idxField)) >= idx { return true } err1, _, _ := f5.GetGoStyleDb().NewUpdate( constant.BCNFT_DB, "t_vip_user", [][]string { {"account_address", accountAddress}, }, updateKv) if err1 != nil { return false } } else { err1, _, _ := f5.GetGoStyleDb().NewInsert( constant.BCNFT_DB, "t_vip_user", insertKv) if err1 != nil { return false } } return true } /* Deposit amount his_amount 衰减,最后的存覆盖之前的 Withdraw 所有 按时间排序处理事件的先后顺序 通过Vester.sol的remainingEsToken方法获取, 如果要本地计算的话, 那就取每次Deposit事件的时间和amount, 加上先前的转换的余额, 再按total * (now - deposit_time) / (365 * 24 * 2600) */ func (this *vip) RecalcEsCecConvert(accountAddress string) error { accountAddress = strings.ToLower(accountAddress) err , ds := f5.GetGoStyleDb().NewOrmSelect( constant.BCEVENT_DB, "t_vester_deposit_withdraw", [][]string { {"account_address", accountAddress}, }) if err != nil { return err } matchDeposits := []*vesterDepositWithdrawPo{} var lastWithdraw *vesterDepositWithdrawPo { allDeposits := []*vesterDepositWithdrawPo{} for ds.Next() { p := new(vesterDepositWithdrawPo) p.idx = q5.ToInt64(ds.GetByName("idx")) p.eventName = ds.GetByName("event_name") p.chainTimestamp = q5.ToInt32(ds.GetByName("chain_timestamp")) p.accountAddress = ds.GetByName("account_address") p.depositAmount = ds.GetByName("deposit_amount") p.withdrawClamiedAmount = ds.GetByName("withdraw_clamied_amount") p.withdrawBalance = ds.GetByName("withdraw_balance") if p.eventName == constant.VESTER_DEPOSIT_EVENT_NAME { q5.AppendSlice(&allDeposits, p) } else if p.eventName == constant.VESTER_WITHDRAW_EVENT_NAME { if lastWithdraw == nil || lastWithdraw.chainTimestamp < p.chainTimestamp { lastWithdraw = p } } } for _, val := range allDeposits { if lastWithdraw == nil || val.chainTimestamp > lastWithdraw.chainTimestamp { q5.AppendSlice(&matchDeposits, val) } } } q5.Sort(matchDeposits, func (a *vesterDepositWithdrawPo, b *vesterDepositWithdrawPo) bool { return a.chainTimestamp < b.chainTimestamp }) var lastDeposit *vesterDepositWithdrawPo nowTime := q5.ToInt32(f5.GetApp().GetRealSeconds()) bnTotal := new(big.Int) for _, val := range matchDeposits { if lastDeposit != nil { if nowTime > lastDeposit.chainTimestamp { bnPassTime := new(big.Int).SetInt64(int64(nowTime - lastDeposit.chainTimestamp)) bnTotalTime := new(big.Int).SetInt64(int64(365 * 24 * 2600)) bnTmp := bnTotal.Mul(bnTotal, bnPassTime) bnInterest := bnTmp.Div(bnTmp, bnTotalTime) bnTotal = bnTotal.Sub(bnTotal, bnInterest) } } bnAmount, _ := new(big.Int).SetString(val.depositAmount, 10) bnTotal = bnAmount.Add(bnAmount, bnTotal) lastDeposit = val } var maxIdx int64 if lastDeposit != nil && lastDeposit.idx > maxIdx { maxIdx = lastDeposit.idx } if lastWithdraw != nil && lastWithdraw.idx > maxIdx { maxIdx = lastWithdraw.idx } if lastDeposit != nil { this.Replace(accountAddress, bnTotal.String(), maxIdx, "escec_convert", "deposit_withdraw_last_src_idx", [][]string { {"last_convert_time", q5.ToString(lastDeposit.chainTimestamp)}, }) } else if lastWithdraw != nil { this.Replace(accountAddress, "0", maxIdx, "escec_convert", "deposit_withdraw_last_src_idx", [][]string { {"last_convert_time", q5.ToString(lastWithdraw.chainTimestamp)}, }) } return nil }