Merge pull request #1815 from c9s/c9s/d2t/ignore-dust-deposits

IMPROVE: [deposit2transfer] ignore dust amount
This commit is contained in:
c9s 2024-11-14 16:08:46 +08:00 committed by GitHub
commit ac0dfff59d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 125 additions and 7 deletions

View File

@ -29,6 +29,8 @@ var groupIdRegExp = regexp.MustCompile(`^<!subteam\^(.+?)>$`)
var emailRegExp = regexp.MustCompile("`^(?P<name>[a-zA-Z0-9.!#$%&'*+/=?^_ \\x60{|}~-]+)@(?P<domain>[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$`gm")
var typeNamePrefixRE = regexp.MustCompile(`^\*?([a-zA-Z0-9_]+\.)?`)
type notifyTask struct {
channel string
@ -521,7 +523,7 @@ func diffsToComment(obj any, diffs []dynamic.Diff) (text string) {
return text
}
text += fmt.Sprintf("%T updated\n", obj)
text += fmt.Sprintf("_%s_ updated\n", objectName(obj))
for _, diff := range diffs {
text += fmt.Sprintf("- %s: `%s` transited to `%s`\n", diff.Field, diff.Before, diff.After)
@ -529,3 +531,17 @@ func diffsToComment(obj any, diffs []dynamic.Diff) (text string) {
return text
}
func objectName(obj any) string {
type labelInf interface {
Label() string
}
if ll, ok := obj.(labelInf); ok {
return ll.Label()
}
typeName := fmt.Sprintf("%T", obj)
typeName = typeNamePrefixRE.ReplaceAllString(typeName, "")
return typeName
}

View File

@ -0,0 +1,22 @@
package slacknotifier
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/c9s/bbgo/pkg/types"
)
func Test_objectName(t *testing.T) {
t.Run("deposit", func(t *testing.T) {
var deposit = &types.Deposit{}
assert.Equal(t, "Deposit", objectName(deposit))
})
t.Run("local type", func(t *testing.T) {
type A struct{}
var obj = &A{}
assert.Equal(t, "A", objectName(obj))
})
}

View File

@ -55,6 +55,9 @@ type Strategy struct {
Interval types.Duration `json:"interval"`
TransferDelay types.Duration `json:"transferDelay"`
IgnoreDust bool `json:"ignoreDust"`
DustAmounts map[string]fixedpoint.Value `json:"dustAmounts"`
SlackAlert *SlackAlert `json:"slackAlert"`
marginTransferService marginTransferService
@ -85,6 +88,15 @@ func (s *Strategy) Defaults() error {
s.TransferDelay = types.Duration(3 * time.Second)
}
if s.DustAmounts == nil {
s.DustAmounts = map[string]fixedpoint.Value{
"USDC": fixedpoint.NewFromFloat(1.0),
"USDT": fixedpoint.NewFromFloat(1.0),
"BTC": fixedpoint.NewFromFloat(0.00001),
"ETH": fixedpoint.NewFromFloat(0.00001),
}
}
return nil
}
@ -129,6 +141,16 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return nil
}
func (s *Strategy) isDust(asset string, amount fixedpoint.Value) bool {
if s.IgnoreDust {
if dustAmount, ok := s.DustAmounts[asset]; ok {
return amount.Compare(dustAmount) <= 0
}
}
return false
}
func (s *Strategy) tickWatcher(ctx context.Context, interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
@ -284,6 +306,10 @@ func (s *Strategy) scanDepositHistory(ctx context.Context, asset string, duratio
continue
}
if s.isDust(asset, deposit.Amount) {
continue
}
// if the deposit record is already in the watch list, update it
if _, ok := s.watchingDeposits[deposit.TransactionID]; ok {
s.addWatchingDeposit(deposit)

View File

@ -28,6 +28,7 @@ type StreamBookSetter interface {
type OrderBookBestPriceVolumeSignal struct {
RatioThreshold fixedpoint.Value `json:"ratioThreshold"`
MinVolume fixedpoint.Value `json:"minVolume"`
MinQuoteVolume fixedpoint.Value `json:"minQuoteVolume"`
symbol string
book *types.StreamOrderBook

View File

@ -28,6 +28,21 @@ const (
DepositCredited = DepositStatus("credited")
)
func (s DepositStatus) SlackEmoji() string {
switch s {
case DepositPending:
return ":hourglass_not_done:"
case DepositCredited:
return ":dollar_banknote:"
case DepositSuccess:
return ":check_mark_button:"
case DepositCancelled:
return ":stop_button:"
}
return ""
}
type Deposit struct {
GID int64 `json:"gid" db:"gid"`
Exchange ExchangeName `json:"exchange" db:"exchange"`
@ -106,7 +121,7 @@ func (d *Deposit) SlackAttachment() slack.Attachment {
if len(d.Status) > 0 {
fields = append(fields, slack.AttachmentField{
Title: "Status",
Value: string(d.Status),
Value: string(d.Status) + " " + d.Status.SlackEmoji(),
Short: false,
})
}
@ -138,21 +153,59 @@ func (d *Deposit) SlackAttachment() slack.Attachment {
})
return slack.Attachment{
Color: depositStatusSlackColor(d.Status),
Title: fmt.Sprintf("Deposit %s %s To %s (%s)", d.Amount.String(), d.Asset, d.Address, d.Exchange),
// TitleLink: "",
Pretext: "",
Text: "",
Color: depositStatusSlackColor(d.Status),
Fallback: "",
ID: 0,
Title: fmt.Sprintf("Deposit %s %s To %s (%s)", d.Amount.String(), d.Asset, d.Address, d.Exchange),
TitleLink: getExplorerURL(d.Network, d.TransactionID),
Pretext: "",
Text: "",
ImageURL: "",
ThumbURL: "",
ServiceName: "",
ServiceIcon: "",
FromURL: "",
OriginalURL: "",
// ServiceName: "",
// ServiceIcon: "",
// FromURL: "",
// OriginalURL: "",
Fields: fields,
Actions: nil,
MarkdownIn: nil,
Blocks: slack.Blocks{},
Footer: fmt.Sprintf("Apply Time: %s", d.Time.Time().Format(time.RFC3339)),
FooterIcon: ExchangeFooterIcon(d.Exchange),
Ts: "",
}
}
func getExplorerURL(network string, txID string) string {
switch strings.ToUpper(network) {
case "BTC":
return getBitcoinNetworkExplorerURL(txID)
case "BSC":
return getBscNetworkExplorerURL(txID)
case "ETH":
return getEthNetworkExplorerURL(txID)
}
return ""
}
func getEthNetworkExplorerURL(txID string) string {
return "https://etherscan.io/tx/" + txID
}
func getBitcoinNetworkExplorerURL(txID string) string {
return "https://www.blockchain.com/explorer/transactions/btc/" + txID
}
func getBscNetworkExplorerURL(txID string) string {
return "https://bscscan.com/tx/" + txID
}
func depositStatusSlackColor(status DepositStatus) string {
switch status {