跨链资产转移后端服务,支持多链路由选择、费用估算与交易状态追踪
┌─────────────────────────────────────────────────────────────┐ │ API Gateway (REST + WebSocket) │ ├─────────────────────────────────────────────────────────────┤ │ Route │ Quote │ Transaction │ Status │ │ Finder │ Service │ Builder │ Tracker │ ├─────────────────────────────────────────────────────────────┤ │ Bridge Protocol Adapters │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │Wormhole│ │LayerZero│ │ Axelar │ │Stargate│ │ Across │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ Chain Connectors (ETH, BSC, Polygon, Arbitrum, Optimism) │ ├─────────────────────────────────────────────────────────────┤ │ PostgreSQL (Transactions) │ Redis (Cache + Pub/Sub) │ └─────────────────────────────────────────────────────────────┘
1// BridgeRouter 跨链路由选择器2type BridgeRouter struct {3 adapters map[string]BridgeAdapter4 cache *redis.Client5}6 7// RouteQuote 跨链报价8type RouteQuote struct {9 Bridge string10 SourceChain string11 DestChain string12 TokenIn common.Address13 TokenOut common.Address14 AmountIn *big.Int15 AmountOut *big.Int16 Fee *big.Int17 EstimatedTime time.Duration18 Route []string19}20 21// FindBestRoute 查找最优跨链路由22func (r *BridgeRouter) FindBestRoute(23 ctx context.Context,24 req *RouteRequest,25) ([]*RouteQuote, error) {26 // 1. 获取所有支持此路径的桥接协议27 supportedBridges := r.getSupportedBridges(28 req.SourceChain,29 req.DestChain,30 req.Token,31 )32 33 // 2. 并发获取各桥报价34 quotes := make([]*RouteQuote, 0)35 var wg sync.WaitGroup36 var mu sync.Mutex37 38 for _, bridge := range supportedBridges {39 wg.Add(1)40 go func(adapter BridgeAdapter) {41 defer wg.Done()42 43 quote, err := adapter.GetQuote(ctx, req)44 if err != nil {45 log.Warn("Bridge quote failed", 46 "bridge", adapter.Name(), "err", err)47 return48 }49 50 mu.Lock()51 quotes = append(quotes, quote)52 mu.Unlock()53 }(r.adapters[bridge])54 }55 wg.Wait()56 57 // 3. 按净收益排序 (到账金额 - 费用)58 sort.Slice(quotes, func(i, j int) bool {59 netI := new(big.Int).Sub(quotes[i].AmountOut, quotes[i].Fee)60 netJ := new(big.Int).Sub(quotes[j].AmountOut, quotes[j].Fee)61 return netI.Cmp(netJ) > 062 })63 64 return quotes, nil65}1// BridgeTransaction 跨链交易状态2type BridgeTransaction struct {3 ID string4 SourceChain string5 DestChain string6 SourceTxHash common.Hash7 DestTxHash common.Hash8 Status TxStatus9 CreatedAt time.Time10 UpdatedAt time.Time11}12 13type TxStatus string14 15const (16 StatusPending TxStatus = "pending"17 StatusSourceConf TxStatus = "source_confirmed"18 StatusBridging TxStatus = "bridging"19 StatusDestConf TxStatus = "dest_confirmed"20 StatusCompleted TxStatus = "completed"21 StatusFailed TxStatus = "failed"22)23 24// TrackTransaction 追踪跨链交易状态25func (t *TransactionTracker) TrackTransaction(26 ctx context.Context,27 txID string,28) error {29 tx, err := t.db.GetTransaction(ctx, txID)30 if err != nil {31 return err32 }33 34 for {35 select {36 case <-ctx.Done():37 return ctx.Err()38 case <-time.After(5 * time.Second):39 newStatus, err := t.checkStatus(ctx, tx)40 if err != nil {41 continue42 }43 44 if newStatus != tx.Status {45 tx.Status = newStatus46 tx.UpdatedAt = time.Now()47 48 // 更新数据库49 t.db.UpdateTransaction(ctx, tx)50 51 // 推送状态更新52 t.pubsub.Publish(ctx, 53 fmt.Sprintf("tx:%s", txID),54 newStatus,55 )56 57 // 完成或失败时退出58 if newStatus == StatusCompleted || 59 newStatus == StatusFailed {60 return nil61 }62 }63 }64 }65}