Add support for Sui in the `tx-tracker` service (#416)

### Description

This pull request modifies the `tx-tracker` service to support the Sui blockchain.

In particular, this will make the Sui sender addresses available for the Wormhole Scan UI.
This commit is contained in:
agodnic 2023-06-15 21:42:46 -03:00 committed by GitHub
parent 97946d5a56
commit bf3be056b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 0 deletions

View File

@ -67,6 +67,10 @@ spec:
value: {{ .SOLANA_BASE_URL }}
- name: SOLANA_REQUESTS_PER_MINUTE
value: "{{ .SOLANA_REQUESTS_PER_MINUTE }}"
- name: SUI_BASE_URL
value: {{ .SUI_BASE_URL }}
- name: SUI_REQUESTS_PER_MINUTE
value: "{{ .SUI_REQUESTS_PER_MINUTE }}"
- name: NUM_WORKERS
value: "100"
- name: BULK_SIZE

View File

@ -93,6 +93,10 @@ spec:
value: {{ .SOLANA_BASE_URL }}
- name: SOLANA_REQUESTS_PER_MINUTE
value: "{{ .SOLANA_REQUESTS_PER_MINUTE }}"
- name: SUI_BASE_URL
value: {{ .SUI_BASE_URL }}
- name: SUI_REQUESTS_PER_MINUTE
value: "{{ .SUI_REQUESTS_PER_MINUTE }}"
resources:
limits:
memory: {{ .RESOURCES_LIMITS_MEMORY }}

59
tx-tracker/chains/sui.go Normal file
View File

@ -0,0 +1,59 @@
package chains
import (
"context"
"fmt"
"time"
"github.com/ethereum/go-ethereum/rpc"
"github.com/wormhole-foundation/wormhole-explorer/txtracker/config"
)
type suiGetTransactionBlockResponse struct {
Digest string `json:"digest"`
TimestampMs int64 `json:"timestampMs,string"`
Transaction struct {
Data struct {
Sender string `json:"sender"`
} `json:"data"`
} `json:"transaction"`
}
type suiGetTransactionBlockOpts struct {
ShowInput bool `json:"showInput"`
ShowRawInput bool `json:"showRawInput"`
ShowEffects bool `json:"showEffects"`
ShowEvents bool `json:"showEvents"`
ShowObjectChanges bool `json:"showObjectChanges"`
ShowBalanceChanges bool `json:"showBalanceChanges"`
}
func fetchSuiTx(
ctx context.Context,
cfg *config.RpcProviderSettings,
txHash string,
) (*TxDetail, error) {
// Initialize RPC client
client, err := rpc.DialContext(ctx, cfg.SuiBaseUrl)
if err != nil {
return nil, fmt.Errorf("failed to initialize RPC client: %w", err)
}
defer client.Close()
// Query transaction data
var reply suiGetTransactionBlockResponse
opts := suiGetTransactionBlockOpts{ShowInput: true}
err = client.CallContext(ctx, &reply, "sui_getTransactionBlock", txHash, opts)
if err != nil {
return nil, fmt.Errorf("failed to get tx by hash: %w", err)
}
// Populate the response struct and return
txDetail := TxDetail{
NativeTxHash: reply.Digest,
From: reply.Transaction.Data.Sender,
Timestamp: time.UnixMilli(reply.TimestampMs),
}
return &txDetail, nil
}

View File

@ -39,6 +39,7 @@ var tickers = struct {
optimism *time.Ticker
polygon *time.Ticker
solana *time.Ticker
sui *time.Ticker
}{}
func Initialize(cfg *config.RpcProviderSettings) {
@ -52,6 +53,9 @@ func Initialize(cfg *config.RpcProviderSettings) {
return time.Duration(roundedUp)
}
// this adapter sends 1 request per txHash
tickers.sui = time.NewTicker(f(cfg.SuiRequestsPerMinute))
// these adapters send 2 requests per txHash
tickers.arbitrum = time.NewTicker(f(cfg.ArbitrumRequestsPerMinute / 2))
tickers.avalanche = time.NewTicker(f(cfg.AvalancheRequestsPerMinute / 2))
@ -119,6 +123,9 @@ func FetchTx(
return fetchEthTx(ctx, txHash, cfg.AvalancheBaseUrl)
}
rateLimiter = *tickers.avalanche
case vaa.ChainIDSui:
fetchFunc = fetchSuiTx
rateLimiter = *tickers.sui
default:
return nil, ErrChainNotSupported
}

View File

@ -77,6 +77,8 @@ type RpcProviderSettings struct {
PolygonRequestsPerMinute uint16 `split_words:"true" required:"true"`
SolanaBaseUrl string `split_words:"true" required:"true"`
SolanaRequestsPerMinute uint16 `split_words:"true" required:"true"`
SuiBaseUrl string `split_words:"true" required:"true"`
SuiRequestsPerMinute uint16 `split_words:"true" required:"true"`
}
func LoadFromEnv[T any]() (*T, error) {