Fix transaction hash search for Sui (#448)
### Description Tracking issue: https://github.com/wormhole-foundation/wormhole-explorer/issues/447 For Sui transaction hashes, calling `GET /api/v1/vaas?txHash={hash}` returned an HTTP status code of 400 and a message of `"MALFORMED TX HASH"`. This pull request fixes the problem.
This commit is contained in:
parent
317e411900
commit
8b58196181
|
@ -10,6 +10,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
suiMinTxHashLen = 43
|
||||
suiMaxTxHashLen = 44
|
||||
algorandTxHashLen = 52
|
||||
wormholeMinTxHashLen = 64
|
||||
wormholeMaxTxHashLen = 66
|
||||
|
@ -39,11 +41,16 @@ func ParseTxHash(value string) (*TxHash, error) {
|
|||
return parseSolanaTxHash(value)
|
||||
}
|
||||
|
||||
// Algorand txHashes are 52 bytes long, encoded as base32.
|
||||
// Algorand txHashes are 32 bytes long, encoded as base32.
|
||||
if len(value) == algorandTxHashLen {
|
||||
return parseAlgorandTxHash(value)
|
||||
}
|
||||
|
||||
// Sui txHashes are 32 bytes long, encoded as base32.
|
||||
if len(value) >= suiMinTxHashLen && len(value) <= suiMaxTxHashLen {
|
||||
return parseSuiTxHash(value)
|
||||
}
|
||||
|
||||
// Wormhole txHashes are 32 bytes long, encoded as hex.
|
||||
// Optionally, they can be prefixed with "0x" or "0X".
|
||||
if len(value) >= wormholeMinTxHashLen && len(value) <= wormholeMaxTxHashLen {
|
||||
|
@ -58,7 +65,7 @@ func parseSolanaTxHash(value string) (*TxHash, error) {
|
|||
// Decode the string from base58 to binary
|
||||
bytes, err := base58.Decode(value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode txHash from base58: %w", err)
|
||||
return nil, fmt.Errorf("failed to decode solana txHash from base58: %w", err)
|
||||
}
|
||||
|
||||
// Make sure we have the expected amount of bytes
|
||||
|
@ -78,7 +85,7 @@ func parseAlgorandTxHash(value string) (*TxHash, error) {
|
|||
// Decode the string from base32 to binary
|
||||
bytes, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode txHash from base32: %w", err)
|
||||
return nil, fmt.Errorf("failed to decode algorand txHash from base32: %w", err)
|
||||
}
|
||||
|
||||
// Make sure we have the expected amount of bytes
|
||||
|
@ -94,6 +101,27 @@ func parseAlgorandTxHash(value string) (*TxHash, error) {
|
|||
return &result, nil
|
||||
}
|
||||
|
||||
func parseSuiTxHash(value string) (*TxHash, error) {
|
||||
|
||||
// Decode the string from base58 to binary
|
||||
bytes, err := base58.Decode(value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode sui txHash from base58: %w", err)
|
||||
}
|
||||
|
||||
// Make sure we have the expected amount of bytes
|
||||
if len(bytes) != 32 {
|
||||
return nil, fmt.Errorf("sui txHash must be exactly 32 bytes, but got %d bytes", len(bytes))
|
||||
}
|
||||
|
||||
// Populate the result struct and return
|
||||
result := TxHash{
|
||||
hash: base58.Encode(bytes),
|
||||
isWormhole: true,
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func parseWormholeTxHash(value string) (*TxHash, error) {
|
||||
|
||||
// Trim any preceding "0x" to the address
|
||||
|
|
|
@ -13,24 +13,48 @@ func TestParseTxHash(t *testing.T) {
|
|||
isWormholeTxHash bool
|
||||
}{
|
||||
{
|
||||
// Solana hash - 88 characters
|
||||
// Invalid Solana hash - 86 characters (too short)
|
||||
input: "VKrJx5ak3amnpY5EXiqfu6pnrzxHTLU95m9vfbYnGSSLQrkRzb4tm4NztCGeLcJxieXQYnqddUwoaEsDRTRh57",
|
||||
},
|
||||
{
|
||||
// Valid Solana hash - 88 characters
|
||||
input: "2maR6uDZzroV7JFF76rp5QR4CFP1PFUe76VRE8gF8QtWRifpGAKJQo4SQDBNs3TAM9RrchJhnJ644jUL2yfagZco",
|
||||
output: "2maR6uDZzroV7JFF76rp5QR4CFP1PFUe76VRE8gF8QtWRifpGAKJQo4SQDBNs3TAM9RrchJhnJ644jUL2yfagZco",
|
||||
isSolanaTxHash: true,
|
||||
},
|
||||
{
|
||||
// Solana hash - 87 characters
|
||||
// Valid Solana hash - 87 characters
|
||||
input: "VKrJx5ak3amnpY5EXiqfu6pnrzxHTLU95m9vfbYnGSSLQrkRzb4tm4NztCGeLcJxieXQYnqddUwoaEsDRTRh57R",
|
||||
output: "VKrJx5ak3amnpY5EXiqfu6pnrzxHTLU95m9vfbYnGSSLQrkRzb4tm4NztCGeLcJxieXQYnqddUwoaEsDRTRh57R",
|
||||
isSolanaTxHash: true,
|
||||
},
|
||||
{
|
||||
// Solana hash w/ invalid length (86 characters)
|
||||
input: "VKrJx5ak3amnpY5EXiqfu6pnrzxHTLU95m9vfbYnGSSLQrkRzb4tm4NztCGeLcJxieXQYnqddUwoaEsDRTRh57",
|
||||
// Invalid Solana hash - 89 characters (too long)
|
||||
input: "2maR6uDZzroV7JFF76rp5QR4CFP1PFUe76VRE8gF8QtWRifpGAKJQo4SQDBNs3TAM9RrchJhnJ644jUL2yfagZco2",
|
||||
},
|
||||
{
|
||||
// Solana hash w/ invalid length (89 characters)
|
||||
input: "2maR6uDZzroV7JFF76rp5QR4CFP1PFUe76VRE8gF8QtWRifpGAKJQo4SQDBNs3TAM9RrchJhnJ644jUL2yfagZco2",
|
||||
// Invalid Sui hash - 42 characters (too short)
|
||||
input: "cVWa8xZtWbTxXQGLQaYquwmChE2sQYxFNGnHmp6oXX",
|
||||
},
|
||||
{
|
||||
// Valid Sui hash - 43 characters
|
||||
input: "cVWa8xZtWbTxXQGLQaYquwmChE2sQYxFNGnHmp6oXXL",
|
||||
output: "cVWa8xZtWbTxXQGLQaYquwmChE2sQYxFNGnHmp6oXXL",
|
||||
isWormholeTxHash: true,
|
||||
},
|
||||
{
|
||||
// Valid Sui hash - 44 characters
|
||||
input: "9yQWLTNmFkwZ6CdK3QXhk8utKr42n3Eh1CFFBWcdCeJC",
|
||||
output: "9yQWLTNmFkwZ6CdK3QXhk8utKr42n3Eh1CFFBWcdCeJC",
|
||||
isWormholeTxHash: true,
|
||||
},
|
||||
{
|
||||
// Invalid Sui hash - 45 characters (too long)
|
||||
input: "9yQWLTNmFkwZ6CdK3QXhk8utKr42n3Eh1CFFBWcdCeJC9",
|
||||
},
|
||||
{
|
||||
// Invalid Wormhole hash - 63 characters (too short)
|
||||
input: "f77f8b44f35ff047a74ee8235ce007afbab357d4e30010d51b6f6990f921637",
|
||||
},
|
||||
{
|
||||
// Wormhole hash with 0x prefix
|
||||
|
@ -51,14 +75,12 @@ func TestParseTxHash(t *testing.T) {
|
|||
isWormholeTxHash: true,
|
||||
},
|
||||
{
|
||||
// Wormhole hash w/ indalid length
|
||||
input: "33f77f8b44f35ff047a74ee8235ce007afbab357d4e30010d51b6f6990f921637",
|
||||
output: "",
|
||||
// Invalid Wormhole hash - 65 characters (too long)
|
||||
input: "33f77f8b44f35ff047a74ee8235ce007afbab357d4e30010d51b6f6990f921637",
|
||||
},
|
||||
{
|
||||
// A bunch of random characters
|
||||
input: "434234i32042oiu08d8sauf0suif",
|
||||
output: "",
|
||||
input: "434234i32042oiu08d8sauf0suif",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue