github.com/diadata-org/diadata@v1.4.593/pkg/dia/helpers/velarhelper/mapper.go (about)

     1  package velarhelper
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"strings"
     7  
     8  	stacks "github.com/diadata-org/diadata/pkg/dia/helpers/stackshelper"
     9  )
    10  
    11  func DecodeSwapEvents(tx stacks.Transaction) ([]SwapEvent, error) {
    12  	result := make([]SwapEvent, 0, len(tx.Events))
    13  	lastEventIndex := -1
    14  
    15  	for i, e := range tx.Events {
    16  		if !isSwapEvent(e) {
    17  			continue
    18  		}
    19  		bytes, err := hex.DecodeString(e.ContractLog.Value.Hex[2:])
    20  		if err != nil {
    21  			return nil, err
    22  		}
    23  		event, err := stacks.DeserializeCVTuple(bytes)
    24  		if err != nil {
    25  			return nil, err
    26  		}
    27  
    28  		info := SwapEvent{TxID: tx.TxID, Timestamp: tx.BlockTime}
    29  		info.AmountIn, err = stacks.DeserializeCVUint(event["amt-in"])
    30  		if err != nil {
    31  			return nil, err
    32  		}
    33  		info.AmountOut, err = stacks.DeserializeCVUint(event["amt-out"])
    34  		if err != nil {
    35  			return nil, err
    36  		}
    37  
    38  		poolAssets, err := decodePoolAssets(event["pool"])
    39  		if err != nil {
    40  			return nil, err
    41  		}
    42  		info.TickerID = poolAssets[0] + "_" + poolAssets[1]
    43  
    44  		if val, ok := event["token-in"]; ok {
    45  			info.TokenIn, err = stacks.DeserializeCVPrincipal(val)
    46  			if err != nil {
    47  				return nil, err
    48  			}
    49  		} else {
    50  			sender, err := stacks.DeserializeCVPrincipal(event["user"])
    51  			if err != nil {
    52  				return nil, err
    53  			}
    54  		outer:
    55  			for j := lastEventIndex + 1; j < i; j++ {
    56  				ev := &tx.Events[j]
    57  				if ev.Asset.EventType != "transfer" ||
    58  					ev.Asset.Sender != sender ||
    59  					ev.Asset.Recipient != e.ContractLog.ContractID {
    60  					continue
    61  				}
    62  
    63  				switch ev.Type {
    64  				case "fungible_token_asset":
    65  					info.TokenIn = strings.Split(ev.Asset.ID, "::")[0]
    66  					break outer
    67  				case "stx_asset":
    68  					for _, a := range poolAssets {
    69  						if a == DeployerAddress+".wstx" {
    70  							info.TokenIn = a
    71  							break outer
    72  						}
    73  					}
    74  				}
    75  			}
    76  		}
    77  
    78  		switch info.TokenIn {
    79  		case poolAssets[0]:
    80  			info.TokenOut = poolAssets[1]
    81  		case poolAssets[1]:
    82  			info.TokenOut = poolAssets[0]
    83  		default:
    84  			err = fmt.Errorf("unable to decode input token address: no matches for %s", info.TokenIn)
    85  			return nil, err
    86  		}
    87  
    88  		result = append(result, info)
    89  		lastEventIndex = i
    90  	}
    91  
    92  	return result, nil
    93  }
    94  
    95  func isSwapEvent(ev stacks.Event) bool {
    96  	log := ev.ContractLog
    97  	return ev.Type == "smart_contract_log" &&
    98  		log.Topic == "print" &&
    99  		(strings.HasPrefix(log.ContractID, DeployerAddress) || strings.HasPrefix(log.ContractID, DeployerAddressV2)) &&
   100  		strings.Contains(log.Value.Repr, "(op \"swap\")")
   101  }
   102  
   103  func decodePoolAssets(src []byte) ([2]string, error) {
   104  	result := [2]string{}
   105  
   106  	pool, err := stacks.DeserializeCVTuple(src)
   107  	if err != nil {
   108  		return result, err
   109  	}
   110  
   111  	result[0], err = stacks.DeserializeCVPrincipal(pool["token0"])
   112  	if err != nil {
   113  		return result, err
   114  	}
   115  	result[1], err = stacks.DeserializeCVPrincipal(pool["token1"])
   116  	if err != nil {
   117  		return result, err
   118  	}
   119  
   120  	return result, nil
   121  }