feat: refactor payment system with multi-currency support and TRX native transfer detection

- Add multi-currency exchange rate API integration (GetRateForCoin)
 - Implement native TRX transfer detection alongside TRC20 USDT transfers
 - Replace deprecated Tronscan API with Trongrid API for better reliability
 - Add TRON Grid API key configuration support
 - Refactor order service to support multiple tokens and currencies
 - Update wallet address locking/unlocking to track token type
 - Add base58 and gjson dependencies for crypto operations
 - Optimize SQLite connection with WAL mode and busy timeout
 - Remove deprecated USDT rate job (replaced by dynamic rate API)
 - Update order data model to include currency and receive address fields
 - Enhance TRC20 callback with improved error handling and logging
This commit is contained in:
line-6000
2026-03-30 16:19:10 +08:00
parent d6e7927605
commit 938396d82b
24 changed files with 505 additions and 222 deletions
+12 -4
View File
@@ -1,12 +1,20 @@
package task
import "github.com/robfig/cron/v3"
import (
"github.com/assimon/luuu/util/log"
"github.com/robfig/cron/v3"
)
func Start() {
log.Sugar.Info("[task] Starting task scheduler...")
c := cron.New()
// 汇率监听
c.AddJob("@every 60s", UsdtRateJob{})
// trc20钱包监听
c.AddJob("@every 5s", ListenTrc20Job{})
_, err := c.AddJob("@every 5s", ListenTrc20Job{})
if err != nil {
log.Sugar.Errorf("[task] Failed to add ListenTrc20Job: %v", err)
return
}
log.Sugar.Info("[task] ListenTrc20Job scheduled successfully (@every 5s)")
c.Start()
log.Sugar.Info("[task] Task scheduler started")
}
+10 -3
View File
@@ -1,10 +1,11 @@
package task
import (
"sync"
"github.com/assimon/luuu/model/data"
"github.com/assimon/luuu/model/service"
"github.com/assimon/luuu/util/log"
"sync"
)
type ListenTrc20Job struct {
@@ -15,18 +16,24 @@ var gListenTrc20JobLock sync.Mutex
func (r ListenTrc20Job) Run() {
gListenTrc20JobLock.Lock()
defer gListenTrc20JobLock.Unlock()
log.Sugar.Debug("[ListenTrc20Job] Job triggered")
walletAddress, err := data.GetAvailableWalletAddress()
if err != nil {
log.Sugar.Error(err)
log.Sugar.Errorf("[ListenTrc20Job] Failed to get wallet addresses: %v", err)
return
}
if len(walletAddress) <= 0 {
log.Sugar.Debug("[ListenTrc20Job] No available wallet addresses")
return
}
log.Sugar.Infof("[ListenTrc20Job] Found %d wallet addresses to monitor", len(walletAddress))
var wg sync.WaitGroup
for _, address := range walletAddress {
log.Sugar.Infof("[ListenTrc20Job] Listening to address: %s", address.Address)
wg.Add(1)
go service.Trc20CallBack(address.Token, &wg)
go service.Trc20CallBack(address.Address, &wg)
}
wg.Wait()
log.Sugar.Debug("[ListenTrc20Job] Job completed")
}
-62
View File
@@ -1,62 +0,0 @@
package task
import (
"github.com/assimon/luuu/config"
"github.com/assimon/luuu/util/http_client"
"github.com/assimon/luuu/util/json"
"github.com/assimon/luuu/util/log"
"github.com/assimon/luuu/util/math"
"time"
)
const UsdtRateApiUri = "https://api.coinmarketcap.com/data-api/v3/cryptocurrency/detail/chart"
type UsdtRateJob struct {
}
type UsdtRateResp struct {
Data Data `json:"data"`
Status Status `json:"status"`
}
type Status struct {
Timestamp time.Time `json:"timestamp"`
ErrorCode string `json:"error_code"`
ErrorMessage string `json:"error_message"`
Elapsed string `json:"elapsed"`
CreditCount int `json:"credit_count"`
}
type Data struct {
Points map[string]Points `json:"points"`
}
type Points struct {
V []float64 `json:"v"`
C []float64 `json:"c"`
}
func (r UsdtRateJob) Run() {
client := http_client.GetHttpClient()
resp, err := client.R().SetQueryString("id=825&range=1H&convertId=2787").SetHeader("Accept", "application/json").Get(UsdtRateApiUri)
if err != nil {
log.Sugar.Error("usdt rate get err:", err.Error())
return
}
var usdtResp UsdtRateResp
err = json.Cjson.Unmarshal(resp.Body(), &usdtResp)
if err != nil {
log.Sugar.Error("Unmarshal usdt resp err:", err.Error())
return
}
if usdtResp.Status.ErrorCode != "0" {
log.Sugar.Error("usdt resp err:", usdtResp.Status.ErrorMessage)
return
}
for _, points := range usdtResp.Data.Points {
if len(points.C) > 0 && points.C[0] > 0 {
config.UsdtRate = math.MustParsePrecFloat64(points.C[0], 2)
return
}
}
}