github.com/NpoolPlatform/chain-middleware@v0.0.0-20240228100535-eb1bcf896eb9/pkg/mw/coin/create.go (about)

     1  package coin
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	npool "github.com/NpoolPlatform/message/npool/chain/mw/v1/coin"
     8  
     9  	chainbasecrud "github.com/NpoolPlatform/chain-middleware/pkg/crud/chain"
    10  	basecrud "github.com/NpoolPlatform/chain-middleware/pkg/crud/coin"
    11  	extracrud "github.com/NpoolPlatform/chain-middleware/pkg/crud/coin/extra"
    12  	settingcrud "github.com/NpoolPlatform/chain-middleware/pkg/crud/coin/setting"
    13  	redis2 "github.com/NpoolPlatform/go-service-framework/pkg/redis"
    14  	basetypes "github.com/NpoolPlatform/message/npool/basetypes/v1"
    15  
    16  	"github.com/NpoolPlatform/chain-middleware/pkg/db"
    17  	"github.com/NpoolPlatform/chain-middleware/pkg/db/ent"
    18  	"github.com/NpoolPlatform/libent-cruder/pkg/cruder"
    19  
    20  	"github.com/google/uuid"
    21  )
    22  
    23  type createHandler struct {
    24  	*Handler
    25  }
    26  
    27  func (h *createHandler) createChainBase(ctx context.Context, tx *ent.Tx) error {
    28  	if h.ChainType == nil {
    29  		return nil
    30  	}
    31  	conds := &chainbasecrud.Conds{
    32  		Name: &cruder.Cond{Op: cruder.EQ, Val: *h.ChainType},
    33  	}
    34  	if h.ENV != nil {
    35  		conds.ENV = &cruder.Cond{Op: cruder.EQ, Val: *h.ENV}
    36  	}
    37  	if h.ChainID != nil {
    38  		conds.ChainID = &cruder.Cond{Op: cruder.EQ, Val: *h.ChainID}
    39  	}
    40  
    41  	stm, err := chainbasecrud.SetQueryConds(tx.ChainBase.Query(), conds)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	info, err := stm.Only(ctx)
    47  	if err != nil {
    48  		if !ent.IsNotFound(err) {
    49  			return err
    50  		}
    51  	}
    52  	if info != nil {
    53  		return nil
    54  	}
    55  
    56  	if _, err := chainbasecrud.CreateSet(
    57  		tx.ChainBase.Create(),
    58  		&chainbasecrud.Req{
    59  			Name:       h.ChainType,
    60  			NativeUnit: h.ChainNativeUnit,
    61  			AtomicUnit: h.ChainAtomicUnit,
    62  			UnitExp:    h.ChainUnitExp,
    63  			ENV:        h.ENV,
    64  			ChainID:    h.ChainID,
    65  			Nickname:   h.ChainNickname,
    66  			GasType:    h.GasType,
    67  		},
    68  	).Save(ctx); err != nil {
    69  		return err
    70  	}
    71  	return nil
    72  }
    73  
    74  func (h *createHandler) createNativeCoinBase(ctx context.Context, tx *ent.Tx) error {
    75  	if h.ChainNativeCoinName == nil {
    76  		h.FeeCoinTypeID = h.EntID
    77  		return nil
    78  	}
    79  	if *h.ChainNativeUnit == *h.Unit {
    80  		h.FeeCoinTypeID = h.EntID
    81  		return nil
    82  	}
    83  
    84  	stm, err := basecrud.SetQueryConds(
    85  		tx.CoinBase.Query(),
    86  		&basecrud.Conds{
    87  			Name: &cruder.Cond{Op: cruder.EQ, Val: *h.ChainNativeCoinName},
    88  			ENV:  &cruder.Cond{Op: cruder.EQ, Val: *h.ENV},
    89  		},
    90  	)
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	info, err := stm.Only(ctx)
    96  	if err != nil {
    97  		if !ent.IsNotFound(err) {
    98  			return err
    99  		}
   100  	}
   101  
   102  	if info == nil {
   103  		info, err = basecrud.CreateSet(
   104  			tx.CoinBase.Create(),
   105  			&basecrud.Req{
   106  				Name: h.ChainNativeCoinName,
   107  				Unit: h.ChainNativeUnit,
   108  				ENV:  h.ENV,
   109  			},
   110  		).Save(ctx)
   111  		if err != nil {
   112  			return err
   113  		}
   114  	}
   115  
   116  	h.FeeCoinTypeID = &info.EntID
   117  
   118  	return nil
   119  }
   120  func (h *createHandler) createCoinBase(ctx context.Context, tx *ent.Tx) error {
   121  	stm, err := basecrud.SetQueryConds(
   122  		tx.CoinBase.Query(),
   123  		&basecrud.Conds{
   124  			Name: &cruder.Cond{Op: cruder.EQ, Val: *h.Name},
   125  			ENV:  &cruder.Cond{Op: cruder.EQ, Val: *h.ENV},
   126  		},
   127  	)
   128  	if err != nil {
   129  		return err
   130  	}
   131  
   132  	info, err := stm.Only(ctx)
   133  	if err != nil {
   134  		if !ent.IsNotFound(err) {
   135  			return err
   136  		}
   137  	}
   138  	if info != nil {
   139  		h.EntID = &info.EntID
   140  		return nil
   141  	}
   142  
   143  	if _, err := basecrud.CreateSet(
   144  		tx.CoinBase.Create(),
   145  		&basecrud.Req{
   146  			EntID:          h.EntID,
   147  			Name:           h.Name,
   148  			Logo:           h.Logo,
   149  			Presale:        h.Presale,
   150  			Unit:           h.Unit,
   151  			ENV:            h.ENV,
   152  			ReservedAmount: h.ReservedAmount,
   153  			ForPay:         h.ForPay,
   154  		},
   155  	).Save(ctx); err != nil {
   156  		return err
   157  	}
   158  	return nil
   159  }
   160  
   161  func (h *createHandler) createNativeCoinExtra(ctx context.Context, tx *ent.Tx) error {
   162  	if h.FeeCoinTypeID == nil {
   163  		return nil
   164  	}
   165  
   166  	stm, err := extracrud.SetQueryConds(
   167  		tx.CoinExtra.Query(),
   168  		&extracrud.Conds{
   169  			CoinTypeID: &cruder.Cond{Op: cruder.EQ, Val: *h.FeeCoinTypeID},
   170  		},
   171  	)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	info, err := stm.Only(ctx)
   177  	if err != nil {
   178  		if !ent.IsNotFound(err) {
   179  			return err
   180  		}
   181  	}
   182  	if info != nil {
   183  		return nil
   184  	}
   185  
   186  	if _, err := extracrud.CreateSet(
   187  		tx.CoinExtra.Create(),
   188  		&extracrud.Req{
   189  			CoinTypeID: h.FeeCoinTypeID,
   190  		},
   191  	).Save(ctx); err != nil {
   192  		return err
   193  	}
   194  	return nil
   195  }
   196  
   197  func (h *createHandler) createCoinExtra(ctx context.Context, tx *ent.Tx) error {
   198  	stm, err := extracrud.SetQueryConds(
   199  		tx.CoinExtra.Query(),
   200  		&extracrud.Conds{
   201  			CoinTypeID: &cruder.Cond{Op: cruder.EQ, Val: *h.EntID},
   202  		},
   203  	)
   204  	if err != nil {
   205  		return err
   206  	}
   207  
   208  	info, err := stm.Only(ctx)
   209  	if err != nil {
   210  		if !ent.IsNotFound(err) {
   211  			return err
   212  		}
   213  	}
   214  	if info != nil {
   215  		return nil
   216  	}
   217  
   218  	if _, err := extracrud.CreateSet(
   219  		tx.CoinExtra.Create(),
   220  		&extracrud.Req{
   221  			CoinTypeID: h.EntID,
   222  			HomePage:   h.HomePage,
   223  			Specs:      h.Specs,
   224  		},
   225  	).Save(ctx); err != nil {
   226  		return err
   227  	}
   228  	return nil
   229  }
   230  
   231  func (h *createHandler) createNativeCoinSetting(ctx context.Context, tx *ent.Tx) error {
   232  	if h.FeeCoinTypeID == nil {
   233  		return nil
   234  	}
   235  
   236  	stm, err := settingcrud.SetQueryConds(
   237  		tx.Setting.Query(),
   238  		&settingcrud.Conds{
   239  			CoinTypeID: &cruder.Cond{Op: cruder.EQ, Val: *h.FeeCoinTypeID},
   240  		},
   241  	)
   242  	if err != nil {
   243  		return err
   244  	}
   245  
   246  	info, err := stm.Only(ctx)
   247  	if err != nil {
   248  		if !ent.IsNotFound(err) {
   249  			return err
   250  		}
   251  	}
   252  	if info != nil {
   253  		return nil
   254  	}
   255  
   256  	if _, err := settingcrud.CreateSet(
   257  		tx.Setting.Create(),
   258  		&settingcrud.Req{
   259  			CoinTypeID:    h.FeeCoinTypeID,
   260  			FeeCoinTypeID: h.FeeCoinTypeID,
   261  		},
   262  	).Save(ctx); err != nil {
   263  		return err
   264  	}
   265  	return nil
   266  }
   267  
   268  func (h *createHandler) createCoinSetting(ctx context.Context, tx *ent.Tx) error {
   269  	stm, err := settingcrud.SetQueryConds(
   270  		tx.Setting.Query(),
   271  		&settingcrud.Conds{
   272  			CoinTypeID: &cruder.Cond{Op: cruder.EQ, Val: *h.EntID},
   273  		},
   274  	)
   275  	if err != nil {
   276  		return err
   277  	}
   278  
   279  	info, err := stm.Only(ctx)
   280  	if err != nil {
   281  		if !ent.IsNotFound(err) {
   282  			return err
   283  		}
   284  	}
   285  	if info != nil {
   286  		return nil
   287  	}
   288  
   289  	if _, err := settingcrud.CreateSet(
   290  		tx.Setting.Create(),
   291  		&settingcrud.Req{
   292  			CoinTypeID:                  h.EntID,
   293  			FeeCoinTypeID:               h.FeeCoinTypeID,
   294  			WithdrawFeeByStableUSD:      h.WithdrawFeeByStableUSD,
   295  			WithdrawFeeAmount:           h.WithdrawFeeAmount,
   296  			CollectFeeAmount:            h.CollectFeeAmount,
   297  			HotWalletFeeAmount:          h.HotWalletFeeAmount,
   298  			LowFeeAmount:                h.LowFeeAmount,
   299  			HotLowFeeAmount:             h.HotLowFeeAmount,
   300  			HotWalletAccountAmount:      h.HotWalletAccountAmount,
   301  			PaymentAccountCollectAmount: h.PaymentAccountCollectAmount,
   302  			LeastTransferAmount:         h.LeastTransferAmount,
   303  			NeedMemo:                    h.NeedMemo,
   304  			RefreshCurrency:             h.RefreshCurrency,
   305  			CheckNewAddressBalance:      h.CheckNewAddressBalance,
   306  		},
   307  	).Save(ctx); err != nil {
   308  		return err
   309  	}
   310  	return nil
   311  }
   312  
   313  func (h *Handler) CreateCoin(ctx context.Context) (*npool.Coin, error) {
   314  	if h.Name == nil {
   315  		return nil, fmt.Errorf("invalid coinname")
   316  	}
   317  	if h.Unit == nil {
   318  		return nil, fmt.Errorf("invalid coinunit")
   319  	}
   320  	if h.ENV == nil {
   321  		return nil, fmt.Errorf("invalid coinenv")
   322  	}
   323  
   324  	lockKey := fmt.Sprintf(
   325  		"%v:%v:%v",
   326  		basetypes.Prefix_PrefixCreateCoin,
   327  		*h.Name,
   328  		*h.ENV,
   329  	)
   330  	if err := redis2.TryLock(lockKey, 0); err != nil {
   331  		return nil, err
   332  	}
   333  	defer func() {
   334  		_ = redis2.Unlock(lockKey)
   335  	}()
   336  
   337  	id := uuid.New()
   338  	if h.EntID == nil {
   339  		h.EntID = &id
   340  	}
   341  
   342  	handler := &createHandler{
   343  		Handler: h,
   344  	}
   345  
   346  	err := db.WithTx(ctx, func(_ctx context.Context, tx *ent.Tx) error {
   347  		if err := handler.createChainBase(_ctx, tx); err != nil {
   348  			return err
   349  		}
   350  		if err := handler.createNativeCoinBase(_ctx, tx); err != nil {
   351  			return err
   352  		}
   353  		if err := handler.createNativeCoinExtra(_ctx, tx); err != nil {
   354  			return err
   355  		}
   356  		if err := handler.createNativeCoinSetting(_ctx, tx); err != nil {
   357  			return err
   358  		}
   359  		if err := handler.createCoinBase(_ctx, tx); err != nil {
   360  			return err
   361  		}
   362  		if err := handler.createCoinExtra(_ctx, tx); err != nil {
   363  			return err
   364  		}
   365  		if err := handler.createCoinSetting(_ctx, tx); err != nil {
   366  			return err
   367  		}
   368  		return nil
   369  	})
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  
   374  	return h.GetCoin(ctx)
   375  }