From 1f89bebb6c6948911938cc7549be1e65a62a6eb1 Mon Sep 17 00:00:00 2001 From: Ales Verbic Date: Mon, 14 Oct 2024 13:26:30 -0400 Subject: [PATCH] feat(address): improved NewAddress to support both bech32/base58 Signed-off-by: Ales Verbic --- ledger/common/address.go | 44 ++++++++++++++++++++++++++++------- ledger/common/address_test.go | 9 +++++++ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/ledger/common/address.go b/ledger/common/address.go index a6d9439a..1f0888cb 100644 --- a/ledger/common/address.go +++ b/ledger/common/address.go @@ -16,6 +16,7 @@ package common import ( "fmt" + "unicode" "github.com/blinklabs-io/gouroboros/base58" "github.com/blinklabs-io/gouroboros/bech32" @@ -53,15 +54,25 @@ type Address struct { extraData []byte } -// NewAddress returns an Address based on the provided bech32 address string +// NewAddress returns an Address based on the provided bech32/base58 address string +// It detects if the string has mixed case assumes it is a base58 encoded address +// otherwise, it assumes it is bech32 encoded func NewAddress(addr string) (Address, error) { - _, data, err := bech32.DecodeNoLimit(addr) - if err != nil { - return Address{}, err - } - decoded, err := bech32.ConvertBits(data, 5, 8, false) - if err != nil { - return Address{}, err + var decoded []byte + var err error + + if isMixedCase(addr) { + // Mixed case detected: Assume Base58 encoding (e.g., Byron addresses) + decoded = base58.Decode(addr) + } else { + _, data, err := bech32.DecodeNoLimit(addr) + if err != nil { + return Address{}, err + } + decoded, err = bech32.ConvertBits(data, 5, 8, false) + if err != nil { + return Address{}, err + } } a := Address{} err = a.populateFromBytes(decoded) @@ -286,3 +297,20 @@ func (a Address) String() string { func (a Address) MarshalJSON() ([]byte, error) { return []byte(`"` + a.String() + `"`), nil } + +// isMixedCase checks if the string contains both uppercase and lowercase letters +// returns true if it does, false otherwise +func isMixedCase(s string) bool { + hasUpper, hasLower := false, false + for _, r := range s { + if unicode.IsUpper(r) { + hasUpper = true + } else if unicode.IsLower(r) { + hasLower = true + } + if hasUpper && hasLower { + return true + } + } + return false +} diff --git a/ledger/common/address_test.go b/ledger/common/address_test.go index 99649038..caf54b87 100644 --- a/ledger/common/address_test.go +++ b/ledger/common/address_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/blinklabs-io/gouroboros/internal/test" + "github.com/stretchr/testify/assert" ) func TestAddressFromBytes(t *testing.T) { @@ -225,3 +226,11 @@ func TestAddressStakeAddress(t *testing.T) { } } } + +func TestAddressPaymentAddress_MixedCase(t *testing.T) { + // address with mixed case Byron address + mixedCaseAddress := "Ae2tdPwUPEYwFx4dmJheyNPPYXtvHbJLeCaA96o6Y2iiUL18cAt7AizN2zG" + addr, err := NewAddress(mixedCaseAddress) + assert.Nil(t, err, "Expected no error when decoding a mixed-case address") + assert.NotNil(t, addr, "Expected a valid address object after decoding") +}