func (s *Service) circuitBreakCheck(
	tok string, supply interface{},
	totalSupplies map[string]interface{},
	pool config.Pool,
	contract utils.Breaker,
) error {

	oldSupplyStr, ok := supply.(string)
	if !ok {
		return errors.New("old supply is not of type string")
	}

	oldSupplyBig, ok := new(big.Int).SetString(oldSupplyStr, 10)
	if !ok {
		return errors.New("failed to convert old supply from string to big.Int")
	}

	newSupplyStr, ok := totalSupplies[tok].(string)
	if !ok {
		return errors.New("new supply is not of type string")
	}

	newSupplyBig, ok := new(big.Int).SetString(newSupplyStr, 10)
	if !ok {
		return errors.New("failed to convert new supply from string to big.Int")
	}

	var (
		direction string
		change    = (utils.GetChangePercentageBig(newSupplyBig, oldSupplyBig)) * 100
	)

	if change < 0 {
		direction = "decreased"
	} else if change > 0 {
		direction = "increased"
	}

	s.logger.Debug(
		"token total supply changed",
		zap.String("direction", direction),
		zap.Float64("change.percent", change),
		zap.String("pool", pool.Name),
		zap.String("token", tok),
		zap.String("supply.old", oldSupplyStr),
		zap.String("supply.new", newSupplyStr),
	)

	// we take the absolute to see if the change is greater than the break percentage
	// as we want to handle circuit breaks whether the total supply increased or decreases
	if math.Abs(change) > pool.SupplyBreakPercentage {
		circuitBreakAddr, err := contract.CircuitBreaker(nil)
		if err != nil {
			s.logger.Error("failed to get circuit breaker contract address", zap.Error(err))
			return err
		}
		breaker, err := controller.NewController(circuitBreakAddr, s.ew.BC())
		if err != nil {
			s.logger.Error("failed to get circuit breaker contract binding", zap.Error(err))
			return err
		}
		s.logger.Warn(
			"token supply fluctuation is greater than minimum break percentage, breaking circuits!",
			zap.String("pool", pool.Name), zap.String("token", tok),
			zap.Float64("break_at", pool.SupplyBreakPercentage), zap.Float64("change", change), zap.Float64("change_abs", math.Abs(change)),
			zap.String("supply.old", oldSupplyBig.String()), zap.String("supply.new", newSupplyBig.String()),
		)
		s.wg.Add(1)
		go func() {
			defer s.wg.Done()
			if err := circuit.BreakCircuit(circuit.BreakConfig{
				Ctx:           s.ctx,
				BC:            s.ew.BC(),
				MinimumGwei:   s.minimumGwei,
				GasMultiplier: s.gasMultiplier,
				Auth:          s.auther,
				PoolAddress:   common.HexToAddress(pool.ContractAddress),
				PoolName:      pool.Name,
				Logger:        s.logger,
				Breaker:       breaker,
			}); err != nil {
				s.logger.Error(
					"circuit break failed to execute properly",
					zap.Error(err),
					zap.String("pool", pool.Name),
				)
			}
		}()
		if err := s.at.NotifyCircuitBreak(
			fmt.Sprintf(
				"a circuit break is in progress. pool: %s, token: %s, reason: token supply %s",
				pool.Name, tok, direction,
			),
		); err != nil {
			s.logger.Error("circuit break notification failed")
		}

	}
	return nil
}
// circuitBreakCheck performs a check to see if a circuit needs to be broken
// and if so handles breaking of the circuit
circuitBreakCheck performs a check to see if a circuit needs to be broken
and if so handles breaking of the circuit
// circuitBreakCheck performs a check to see if a circuit needs to be broken // and if so handles breaking of the circuit
func (s *Service) circuitBreakCheck(
	tok string, supply interface{},
	totalSupplies map[string]interface{},
	pool config.Pool,
	contract utils.Breaker,
) error {
	oldSupplyStr, ok := supply.(string)
	if !ok {
		return errors.New("old supply is not of type string")
	}
	oldSupplyBig, ok := new(big.Int).SetString(oldSupplyStr, 10)
	if !ok {
		return errors.New("failed to convert old supply from string to big.Int")
	}
	newSupplyStr, ok := totalSupplies[tok].(string)
	if !ok {
		return errors.New("new supply is not of type string")
	}
	newSupplyBig, ok := new(big.Int).SetString(newSupplyStr, 10)
	if !ok {
		return errors.New("failed to convert new supply from string to big.Int")
	}
	var (
		direction string
		change    = (utils.GetChangePercentageBig(newSupplyBig, oldSupplyBig)) * 100
	)
	if change < 0 {
		direction = "decreased"
	} else if change > 0 {
		direction = "increased"
	}
	s.logger.Debug(
		"token total supply changed",
		zap.String("direction", direction),
		zap.Float64("change.percent", change),
		zap.String("pool", pool.Name),
		zap.String("token", tok),
		zap.String("supply.old", oldSupplyStr),
		zap.String("supply.new", newSupplyStr),
	)
	if math.Abs(change) > pool.SupplyBreakPercentage {
		circuitBreakAddr, err := contract.CircuitBreaker(nil)
		if err != nil {
			s.logger.Error("failed to get circuit breaker contract address", zap.Error(err))
			return err
		}
		breaker, err := controller.NewController(circuitBreakAddr, s.ew.BC())
		if err != nil {
			s.logger.Error("failed to get circuit breaker contract binding", zap.Error(err))
			return err
		}
		s.logger.Warn(
			"token supply fluctuation is greater than minimum break percentage, breaking circuits!",
			zap.String("pool", pool.Name), zap.String("token", tok),
			zap.Float64("break_at", pool.SupplyBreakPercentage), zap.Float64("change", change), zap.Float64("change_abs", math.Abs(change)),
			zap.String("supply.old", oldSupplyBig.String()), zap.String("supply.new", newSupplyBig.String()),
		)
		s.wg.Add(1)
		go func() {
			defer s.wg.Done()
			if err := circuit.BreakCircuit(circuit.BreakConfig{
				Ctx:           s.ctx,
				BC:            s.ew.BC(),
				MinimumGwei:   s.minimumGwei,
				GasMultiplier: s.gasMultiplier,
				Auth:          s.auther,
				PoolAddress:   common.HexToAddress(pool.ContractAddress),
				PoolName:      pool.Name,
				Logger:        s.logger,
				Breaker:       breaker,
			}); err != nil {
				s.logger.Error(
					"circuit break failed to execute properly",
					zap.Error(err),
					zap.String("pool", pool.Name),
				)
			}
		}()
		if err := s.at.NotifyCircuitBreak(
			fmt.Sprintf(
				"a circuit break is in progress. pool: %s, token: %s, reason: token supply %s",
				pool.Name, tok, direction,
			),
		); err != nil {
			s.logger.Error("circuit break notification failed")
		}
	}
	return nil
}
func ( s * Service ) circuitBreakCheck ( tok string , supply interface { } , totalSupplies map [ string ] interface { } , pool config . Pool , contract utils . Breaker , ) error { oldSupplyStr , ok := supply . ( string ) if ! ok { return errors . New ( " " ) } oldSupplyBig , ok := new ( big . Int ) . SetString ( oldSupplyStr , 10 ) if ! ok { return errors . New ( " " ) } newSupplyStr , ok := totalSupplies [ tok ] . ( string ) if ! ok { return errors . New ( " " ) } newSupplyBig , ok := new ( big . Int ) . SetString ( newSupplyStr , 10 ) if ! ok { return errors . New ( " " ) } var ( direction string change = ( utils . GetChangePercentageBig ( newSupplyBig , oldSupplyBig ) ) * 100 ) if change < 0 { direction = " " } else if change > 0 { direction = " " } s . logger . Debug ( " " , zap . String ( " " , direction ) , zap . Float64 ( " " , change ) , zap . String ( " " , pool . Name ) , zap . String ( " " , tok ) , zap . String ( " " , oldSupplyStr ) , zap . String ( " " , newSupplyStr ) , ) if math . Abs ( change ) > pool . SupplyBreakPercentage { circuitBreakAddr , err := contract . CircuitBreaker ( nil ) if err != nil { s . logger . Error ( " " , zap . Error ( err ) ) return err } breaker , err := controller . NewController ( circuitBreakAddr , s . ew . BC ( ) ) if err != nil { s . logger . Error ( " " , zap . Error ( err ) ) return err } s . logger . Warn ( " " , zap . String ( " " , pool . Name ) , zap . String ( " " , tok ) , zap . Float64 ( " " , pool . SupplyBreakPercentage ) , zap . Float64 ( " " , change ) , zap . Float64 ( " " , math . Abs ( change ) ) , zap . String ( " " , oldSupplyBig . String ( ) ) , zap . String ( " " , newSupplyBig . String ( ) ) , ) s . wg . Add ( 1 ) go func ( ) { defer s . wg . Done ( ) if err := circuit . BreakCircuit ( circuit . BreakConfig { Ctx : s . ctx , BC : s . ew . BC ( ) , MinimumGwei : s . minimumGwei , GasMultiplier : s . gasMultiplier , Auth : s . auther , PoolAddress : common . HexToAddress ( pool . ContractAddress ) , PoolName : pool . Name , Logger : s . logger , Breaker : breaker , } ) ; err != nil { s . logger . Error ( " " , zap . Error ( err ) , zap . String ( " " , pool . Name ) , ) } } ( ) if err := s . at . NotifyCircuitBreak ( fmt . Sprintf ( " " , pool . Name , tok , direction , ) , ) ; err != nil { s . logger . Error ( " " ) } } return nil }
circuitBreakCheck performs a check to see if a circuit needs to be broken
and if so handles breaking of the circuit
circuitBreakCheck performs a check to see if a circuit needs to be broken and if so handles breaking of the circuit
// we take the absolute to see if the change is greater than the break percentage // as we want to handle circuit breaks whether the total supply increased or decreases