diff --git a/internal/consts/consts.go b/internal/consts/consts.go index 480170f..ac7db69 100644 --- a/internal/consts/consts.go +++ b/internal/consts/consts.go @@ -14,3 +14,12 @@ const ( AdminSecret = "admin_secret" NftHolderApiConf = "nft_holder_api_conf" ) + +type AssetType string + +const ( + AssetType_Points AssetType = "points" + AssetType_Keys AssetType = "keys" + AssetType_Castile AssetType = "castile" + AssetType_Elite_Points AssetType = "elite_points" +) diff --git a/internal/model/nh_nft_holder_model.go b/internal/model/nh_nft_holder_model.go index b943563..d3ebcb5 100755 --- a/internal/model/nh_nft_holder_model.go +++ b/internal/model/nh_nft_holder_model.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/stores/sqlc" "github.com/zeromicro/go-zero/core/stores/sqlx" ) @@ -18,6 +20,7 @@ type ( FindOtherUpdateSeq(ctx context.Context, updateSeq int) ([]*NhNftHolder, error) DeleteOtherUpdateSeq(ctx context.Context, updateSeq int) error FindTokensByAddress(ctx context.Context, address string) ([]string, error) + HoldNft(ctx context.Context, uid uint) bool } customNhNftHolderModel struct { @@ -25,6 +28,19 @@ type ( } ) +func (m *customNhNftHolderModel) HoldNft(ctx context.Context, uid uint) bool { + query := fmt.Sprintf("select count(1) from %s h join nh_wallet w on h.address = w.address where w.`uid` = ?", m.table) + var count int + err := m.conn.QueryRowCtx(ctx, &count, query, uid) + if err != nil { + if !errors.Is(err, sqlc.ErrNotFound) { + logx.Errorw("HoldNft query failed", logx.Field("query", query), logx.Field("args", uid), logx.Field("err", err)) + } + return false + } + return count > 0 +} + func (m *customNhNftHolderModel) FindTokensByAddress(ctx context.Context, address string) ([]string, error) { query := fmt.Sprintf("select `token_id` from %s where `address` = ?", m.table) var tokens []string diff --git a/internal/model/nh_task_ambassador_model.go b/internal/model/nh_task_ambassador_model.go index 905a696..e078c6f 100755 --- a/internal/model/nh_task_ambassador_model.go +++ b/internal/model/nh_task_ambassador_model.go @@ -1,6 +1,11 @@ package model -import "github.com/zeromicro/go-zero/core/stores/sqlx" +import ( + "context" + "errors" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) var _ NhTaskAmbassadorModel = (*customNhTaskAmbassadorModel)(nil) @@ -10,6 +15,7 @@ type ( NhTaskAmbassadorModel interface { nhTaskAmbassadorModel withSession(session sqlx.Session) NhTaskAmbassadorModel + IsAmbassador(ctx context.Context, uid uint) bool } customNhTaskAmbassadorModel struct { @@ -17,6 +23,19 @@ type ( } ) +func (m *customNhTaskAmbassadorModel) IsAmbassador(ctx context.Context, uid uint) bool { + query := "select t.id from nh_task_ambassador t join nh_user u on t.email = u.email where u.id = ? limit 1" + var id uint + err := m.conn.QueryRowCtx(ctx, &id, query, uid) + if err != nil { + if !errors.Is(err, sqlx.ErrNotFound) { + logx.Errorw("IsAmbassador query failed", logx.Field("query", query), logx.Field("args", uid), logx.Field("err", err)) + } + return false + } + return id > 0 +} + // NewNhTaskAmbassadorModel returns a model for the database table. func NewNhTaskAmbassadorModel(conn sqlx.SqlConn) NhTaskAmbassadorModel { return &customNhTaskAmbassadorModel{ diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index d472e86..9580662 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -4,15 +4,18 @@ import ( "context" "errors" ea "github.com/earn-alliance/earnalliance-go" + "github.com/shopspring/decimal" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/rest" "nova_task/internal/config" + "nova_task/internal/consts" "nova_task/internal/middleware" "nova_task/internal/model" "nova_task/internal/pkg/errs" "nova_task/internal/types" + "time" ) type ServiceContext struct { @@ -145,3 +148,56 @@ func (s *ServiceContext) GetUidByEmail(ctx context.Context, email string) (uint, } return u.Id, nil } + +func (s *ServiceContext) AddUserAsset(ctx context.Context, uid uint, asset consts.AssetType, amount decimal.Decimal, remark string, eventId uint64, provideUid uint, referralReward bool) error { + var err error + switch asset { + case consts.AssetType_Points: + err = s.TaskAssetModel.AddPoint(ctx, uid, amount) + case consts.AssetType_Castile: + err = s.TaskAssetModel.AddCastile(ctx, uid, amount) + case consts.AssetType_Elite_Points: + err = s.TaskAssetModel.AddElitePoints(ctx, uid, amount) + case consts.AssetType_Keys: + err = s.TaskAssetModel.AddKeys(ctx, uid, int(amount.IntPart())) + default: + return errors.New("unknown asset type") + } + if err != nil { + return err + } + _, err = s.TaskAssetRecordModel.Insert(ctx, &model.NhTaskAssetRecord{ + Uid: int(uid), + EventId: eventId, + AssetField: string(asset), + Count: amount.InexactFloat64(), + Remark: remark, + ProvideUid: provideUid, + CreateTime: int(time.Now().Unix()), + }) + if err != nil { + return err + } + if !referralReward { + return nil + } + // 返利给上级 + pb, err := s.PromoteBindModel.FindOneByInvitedUid(ctx, uid) + if err != nil { + if !errors.Is(err, model.ErrNotFound) { + logx.Errorw("find promote bind error", logx.Field("err", err), logx.Field("uid", uid)) + } + return nil + } + if pb.ShareUid == 0 { + return nil + } + var rate = 5 + if s.NftHolderModel.HoldNft(ctx, pb.ShareUid) { + rate = 15 + } else if s.AmbassadorModel.IsAmbassador(ctx, pb.ShareUid) { + rate = 10 + } + rewardAmount := amount.Mul(decimal.NewFromFloat(float64(rate) / 100)) + return s.AddUserAsset(ctx, pb.ShareUid, asset, rewardAmount, "referral reward", 0, uid, false) +}