Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dto/apiRequests.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ type SharedApiReq struct {
type GetFeeRequest struct {
*SharedApiReq
ReceiversCount int `json:"receiversCount"`
Speed string `json:"speed,omitempty"`
}

type GetTokenFeeRequest struct {
*SharedApiReq
TokenAddress string `json:"tokenAddress"`
Speed string `json:"speed,omitempty"`
}
154 changes: 117 additions & 37 deletions services/feeCalculator/feeCalculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ type feeCalculator struct {
FeePerByte int
}

func GetBitcoinFee(address string, amount string, receiversCount int) (dto.GetFeeResponse, responses.ResponseError, error) {
type Params struct {
Address string
Amount string
ReceiversCount int
Speed string
TokenAddress string
}

func GetBitcoinFee(params *Params) (dto.GetFeeResponse, responses.ResponseError, error) {

var utxos responses.UtxoResponse
var apiUtxoErr, apiFeeErr responses.ResponseError
Expand All @@ -25,7 +33,7 @@ func GetBitcoinFee(address string, amount string, receiversCount int) (dto.GetFe
wg.Add(2)
go func() {
defer wg.Done()
utxos, apiUtxoErr = api.GetUtxo(address, "btc")
utxos, apiUtxoErr = api.GetUtxo(params.Address, "btc")
}()

go func() {
Expand All @@ -39,20 +47,30 @@ func GetBitcoinFee(address string, amount string, receiversCount int) (dto.GetFe
} else if apiUtxoErr.Error != nil || apiUtxoErr.ApiError != nil {
return dto.GetFeeResponse{}, apiUtxoErr, nil
}

fee, apiErr := calcUtxoFee(utxos.Utxo, amount, receiversCount, feeCalculator{
CalcFee: calcBitcoinFee,
MinFeePerByte: 10,
FeePerByte: feePerByte.HalfHourFee,
})

f, _ := speedControl(feePerByte, params.Speed)
// todo : complete
f.MinFeePerByte = 10

// Test
//switch params.Speed {
//case "1":
// f.FeePerByte = feePerByte.HourFee
//case "1.5":
// f.FeePerByte = feePerByte.HalfHourFee
//case "2":
// f.FeePerByte = feePerByte.FastestFee
//}

fee, apiErr := calcUtxoFee(utxos.Utxo, params.Amount, params.ReceiversCount, *f)
if apiErr.Error != nil || apiErr.ApiError != nil {
return dto.GetFeeResponse{}, apiErr, nil
}

return fee, responses.ResponseError{}, nil
}

func GetLitecoinFee(address string, amount string, receiversCount int) (dto.GetFeeResponse, responses.ResponseError, error) {
func GetLitecoinFee(params *Params) (dto.GetFeeResponse, responses.ResponseError, error) {

var utxos responses.UtxoResponse
var apiUtxoErr, apiFeeErr responses.ResponseError
Expand All @@ -63,7 +81,7 @@ func GetLitecoinFee(address string, amount string, receiversCount int) (dto.GetF
wg.Add(2)
go func() {
defer wg.Done()
utxos, apiUtxoErr = api.GetUtxo(address, "ltc")
utxos, apiUtxoErr = api.GetUtxo(params.Address, "ltc")
}()

go func() {
Expand All @@ -78,23 +96,23 @@ func GetLitecoinFee(address string, amount string, receiversCount int) (dto.GetF
return dto.GetFeeResponse{}, apiUtxoErr, nil
}

fee, apiErr := calcUtxoFee(utxos.Utxo, amount, receiversCount, feeCalculator{
CalcFee: calcLitecoinFee,
MinFeePerByte: 8,
FeePerByte: feePerByte.MediumFeePerKb / 1024,
})
f, _ := speedControl(feePerByte, params.Speed)
// todo : complete
f.MinFeePerByte = 8

fee, apiErr := calcUtxoFee(utxos.Utxo, params.Amount, params.ReceiversCount, *f)
if apiErr.Error != nil || apiErr.ApiError != nil {
return dto.GetFeeResponse{}, apiErr, nil
}
return fee, responses.ResponseError{}, nil
}

func GetBitcoinCashFee(address string, amount string, receiversCount int) (dto.GetFeeResponse, responses.ResponseError, error) {
utxos, apiErr := api.GetUtxo(address, "bch")
func GetBitcoinCashFee(params *Params) (dto.GetFeeResponse, responses.ResponseError, error) {
utxos, apiErr := api.GetUtxo(params.Address, "bch")
if apiErr.Error != nil || apiErr.ApiError != nil {
return dto.GetFeeResponse{}, apiErr, nil
}
fee, apiErr := calcUtxoFee(utxos.Utxo, amount, receiversCount, feeCalculator{
fee, apiErr := calcUtxoFee(utxos.Utxo, params.Amount, params.ReceiversCount, feeCalculator{
CalcFee: calcBitcoinCashFee,
MinFeePerByte: 1,
FeePerByte: 3,
Expand All @@ -105,7 +123,7 @@ func GetBitcoinCashFee(address string, amount string, receiversCount int) (dto.G
return fee, responses.ResponseError{}, nil
}

func GetEthereumFee(address string, amount string) (dto.GetEthFeeResponse, responses.ResponseError, error) {
func GetEthereumFee(params *Params) (dto.GetEthFeeResponse, responses.ResponseError, error) {

var fee responses.EthereumFeeResponse
var feeErr, balanceErr responses.ResponseError
Expand All @@ -121,7 +139,7 @@ func GetEthereumFee(address string, amount string) (dto.GetEthFeeResponse, respo

go func() {
defer wg.Done()
balance, balanceErr = api.GetEthereumBalance(address)
balance, balanceErr = api.GetEthereumBalance(params.Address)
}()
wg.Wait()

Expand All @@ -131,14 +149,16 @@ func GetEthereumFee(address string, amount string) (dto.GetEthFeeResponse, respo
return dto.GetEthFeeResponse{}, balanceErr, nil
}

fr, err := CalculateEthBasedFee(balance.Balance, fee.GasPrice, 21000, amount)
_, gaz := speedControl(fee, params.Speed)

fr, err := CalculateEthBasedFee(balance.Balance, gaz, 21000, params.Amount)
if err != nil {
return dto.GetEthFeeResponse{}, responses.ResponseError{}, err
}
return fr, responses.ResponseError{}, nil
}

func GetEthereumClassicFee(address string, amount string) (dto.GetEthFeeResponse, responses.ResponseError, error) {
func GetEthereumClassicFee(params *Params) (dto.GetEthFeeResponse, responses.ResponseError, error) {
var fee responses.EthereumFeeResponse
var feeErr, balanceErr responses.ResponseError
var balance responses.CurrencyBalanceResponse
Expand All @@ -153,7 +173,7 @@ func GetEthereumClassicFee(address string, amount string) (dto.GetEthFeeResponse

go func() {
defer wg.Done()
balance, balanceErr = api.GetEthereumClassicBalance(address)
balance, balanceErr = api.GetEthereumClassicBalance(params.Address)
}()
wg.Wait()

Expand All @@ -163,14 +183,16 @@ func GetEthereumClassicFee(address string, amount string) (dto.GetEthFeeResponse
return dto.GetEthFeeResponse{}, balanceErr, nil
}

fr, err := CalculateEthBasedFee(balance.Balance, fee.GasPrice, 21000, amount)
_, gaz := speedControl(fee, params.Speed)

fr, err := CalculateEthBasedFee(balance.Balance, gaz, 21000, params.Amount)
if err != nil {
return dto.GetEthFeeResponse{}, responses.ResponseError{}, err
}
return fr, responses.ResponseError{}, nil
}

func GetTokenFee(address, tokenAddress, amount string) (dto.GetTokenFeeResponse, responses.ResponseError, error) {
func GetTokenFee(params *Params) (dto.GetTokenFeeResponse, responses.ResponseError, error) {
var gasLimitErr, feeErr, balanceErr, tokenBalanceErr responses.ResponseError
var gasLimit responses.TokenFeeResponse
var fee responses.EthereumFeeResponse
Expand All @@ -182,9 +204,9 @@ func GetTokenFee(address, tokenAddress, amount string) (dto.GetTokenFeeResponse,
go func() {
defer wg.Done()
gasLimit, gasLimitErr = api.GetTokenGasLimit(requests.TokenGasLimitRequest{
TokenAddress: tokenAddress,
ToAddress: address,
Amount: amount,
TokenAddress: params.TokenAddress,
ToAddress: params.Address,
Amount: params.Amount,
})
}()

Expand All @@ -195,12 +217,12 @@ func GetTokenFee(address, tokenAddress, amount string) (dto.GetTokenFeeResponse,

go func() {
defer wg.Done()
balance, balanceErr = api.GetEthereumBalance(address)
balance, balanceErr = api.GetEthereumBalance(params.Address)
}()

go func() {
defer wg.Done()
tokenBalance, tokenBalanceErr = api.GetTokenBalance(address, tokenAddress)
tokenBalance, tokenBalanceErr = api.GetTokenBalance(params.Address, params.TokenAddress)
if tokenBalance.Balance == "" {
tokenBalance.Balance = "0"
}
Expand All @@ -220,21 +242,23 @@ func GetTokenFee(address, tokenAddress, amount string) (dto.GetTokenFeeResponse,
return dto.GetTokenFeeResponse{}, tokenBalanceErr, nil
}

fr, err := CalculateTokenFee(balance.Balance, tokenBalance.Balance, fee.GasPrice, gasLimit.GasLimit, amount)
_, gaz := speedControl(fee, params.Speed)

fr, err := CalculateTokenFee(balance.Balance, tokenBalance.Balance, gaz, gasLimit.GasLimit, params.Amount)
if err != nil {
return dto.GetTokenFeeResponse{}, responses.ResponseError{}, err
}
return fr, responses.ResponseError{}, nil
}

func GetWavesFee(address string, amount string) (dto.GetWavesAndStellarFeeResponse, responses.ResponseError, error) {
balance, apiErr := api.GetWavesBalance(address)
func GetWavesFee(params *Params) (dto.GetWavesAndStellarFeeResponse, responses.ResponseError, error) {
balance, apiErr := api.GetWavesBalance(params.Address)
if apiErr.Error != nil || apiErr.ApiError != nil {
return dto.GetWavesAndStellarFeeResponse{}, apiErr, nil
}
maxAmount := balance.Balance - 300000
isEnough := true
if stringAmountToSatoshi(amount) > maxAmount {
if stringAmountToSatoshi(params.Amount) > maxAmount {
isEnough = false
if maxAmount < 0 {
maxAmount = 0
Expand All @@ -250,12 +274,12 @@ func GetWavesFee(address string, amount string) (dto.GetWavesAndStellarFeeRespon
}}, responses.ResponseError{}, nil
}

func GetStellarFee(address string, amount string) (dto.GetWavesAndStellarFeeResponse, responses.ResponseError, error) {
balance, apiErr := api.GetStellarBalance(address)
func GetStellarFee(params *Params) (dto.GetWavesAndStellarFeeResponse, responses.ResponseError, error) {
balance, apiErr := api.GetStellarBalance(params.Address)
if apiErr.Error != nil || apiErr.ApiError != nil {
return dto.GetWavesAndStellarFeeResponse{}, apiErr, nil
}
fr := CalcStellarFee(balance.Balance, amount, 100)
fr := CalcStellarFee(balance.Balance, params.Amount, 100)
return fr, responses.ResponseError{}, nil
}

Expand All @@ -270,3 +294,59 @@ func calcLitecoinFee(inputCount, outputCount, feePerByte int) int {
func calcBitcoinCashFee(inputCount, outputCount, feePerByte int) int {
return (inputCount*148 + outputCount*34 + 10) * feePerByte
}

func speedControl(t interface{}, speed string) (*feeCalculator, int) {
var f feeCalculator
var gaz int

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gaz -> gasPrice

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


switch t.(type) {
case responses.BitcoinFeeResponse:
typed := t.(responses.BitcoinFeeResponse)
f.CalcFee = calcBitcoinFee
switch speed {
case "1":
f.FeePerByte = typed.HourFee
case "1.5":
f.FeePerByte = typed.HalfHourFee
case "2":
f.FeePerByte = typed.FastestFee
}
return &f, 0
case responses.LitecoinFeeResponse:
typed := t.(responses.LitecoinFeeResponse)
f.CalcFee = calcLitecoinFee
switch speed {
case "1":
f.FeePerByte = typed.LowFeePerKb
case "1.5":
f.FeePerByte = typed.MediumFeePerKb
case "2":
f.FeePerByte = typed.HighFeePerKb
}
f.FeePerByte = f.FeePerByte / 1024
return &f, 0
case responses.EthereumFeeResponse:
typed := t.(responses.EthereumFeeResponse)
switch speed {
case "1":

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slow / average / fast

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

gaz = typed.GasPrice * 10 / 8
case "1.5":
gaz = typed.GasPrice
case "2":
gaz = typed.GasPrice + (typed.GasPrice * 10 / 5)
}
return nil, gaz
case responses.TokenFeeResponse:
typed := t.(responses.TokenFeeResponse)
switch speed {
case "1":
gaz = typed.GasLimit * 10 / 8

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GasLimit -> GasPrice.
GasLimit it's a max amount of gas that may be used during transaction execution

case "1.5":
gaz = typed.GasLimit
case "2":
gaz = typed.GasLimit + (typed.GasLimit * 10 / 5)
}
return nil, gaz
}
return &f, gaz
}
Loading