diff --git a/packages/core-go/address/detect.go b/packages/core-go/address/detect.go index ffd5b4e..b8aadab 100644 --- a/packages/core-go/address/detect.go +++ b/packages/core-go/address/detect.go @@ -1,20 +1,20 @@ package address +// Detect identifies the AddressKind of a Stellar address string. func Detect(addr string) (AddressKind, error) { versionByte, _, err := DecodeStrKey(addr) if err != nil { return "", err } -func Detect(address string) string { - if strkey.IsValidEd25519PublicKey(address) { - return "G" + switch versionByte { + case VersionByteG: + return KindG, nil + case VersionByteM: + return KindM, nil + case VersionByteC: + return KindC, nil + default: + return "", ErrUnknownVersionByteError } - if strkey.IsValidMuxedAccountEd25519PublicKey(address) { - return "M" - } - if _, err := strkey.Decode(strkey.VersionByteContract, address); err == nil { - return "C" - } - return "invalid" } diff --git a/packages/core-go/address/result.go b/packages/core-go/address/result.go deleted file mode 100644 index 2c035a8..0000000 --- a/packages/core-go/address/result.go +++ /dev/null @@ -1,14 +0,0 @@ -package address - -type ParseResult struct { - Kind string - Address string - Warnings []Warning - Err *AddressError -} - -type AddressError struct { - Code ErrorCode - Input string - Message string -} diff --git a/packages/core-go/address/types.go b/packages/core-go/address/types.go index b9633d4..d3877c4 100644 --- a/packages/core-go/address/types.go +++ b/packages/core-go/address/types.go @@ -16,9 +16,10 @@ const ( // - For muxed addresses (KindM), BaseG is the underlying G-address and // MuxedID is the 64-bit ID carried by the muxed account. type Address struct { - Kind AddressKind - Raw string - BaseG string - MuxedID uint64 + Kind AddressKind + Raw string + BaseG string + MuxedID uint64 + Warnings []Warning } diff --git a/packages/core-go/routing/extract.go b/packages/core-go/routing/extract.go index c1a1a4a..e6b1125 100644 --- a/packages/core-go/routing/extract.go +++ b/packages/core-go/routing/extract.go @@ -77,8 +77,8 @@ func ExtractRouting(input RoutingInput) RoutingResult { } } - if parsed.Kind == "M" { - baseG, id, err := muxed.DecodeMuxed(parsed.Address) + if parsed.Kind == address.KindM { + baseG, id, err := muxed.DecodeMuxed(parsed.Raw) if err != nil { return RoutingResult{ RoutingSource: "none", @@ -109,7 +109,7 @@ func ExtractRouting(input RoutingInput) RoutingResult { return RoutingResult{ DestinationBaseAccount: baseG, - RoutingID: NewRoutingID(id), + RoutingID: NewRoutingID(strconv.FormatUint(id, 10)), RoutingSource: "muxed", Warnings: warnings, } @@ -134,21 +134,6 @@ func ExtractRouting(input RoutingInput) RoutingResult { Severity: "warn", Message: "MEMO_ID was empty, non-numeric, or exceeded uint64 max.", }) - } else { - normalized := strconv.FormatUint(val, 10) - if normalized != input.MemoValue { - warnings = append(warnings, address.Warning{ - Code: address.WarnNonCanonicalRoutingID, - Severity: "warn", - Message: "Memo routing ID had leading zeros. Normalized to canonical decimal.", - Normalization: &address.Normalization{ - Original: input.MemoValue, - Normalized: normalized, - }, - }) - } - routingID = &val - routingSource = "memo" } } else if input.MemoType == "text" && memoValue != "" { norm := NormalizeMemoTextID(memoValue) @@ -191,10 +176,6 @@ func ExtractRouting(input RoutingInput) RoutingResult { } } -func stringValue(s *string) string { - if s == nil { - return "" - } - - return *s +func stringValue(s string) string { + return s } diff --git a/packages/core-go/routing/extract_test.go b/packages/core-go/routing/extract_test.go index 241c103..2527d71 100644 --- a/packages/core-go/routing/extract_test.go +++ b/packages/core-go/routing/extract_test.go @@ -40,7 +40,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(100), + RoutingID: NewRoutingID("100"), RoutingSource: "memo", Warnings: []address.Warning{}, }, @@ -54,7 +54,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(0), + RoutingID: NewRoutingID("0"), RoutingSource: "memo", Warnings: []address.Warning{}, }, @@ -68,7 +68,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(18446744073709551615), + RoutingID: NewRoutingID("18446744073709551615"), RoutingSource: "memo", Warnings: []address.Warning{}, }, @@ -142,7 +142,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(7), + RoutingID: NewRoutingID("7"), RoutingSource: "memo", Warnings: []address.Warning{ { @@ -166,7 +166,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(200), + RoutingID: NewRoutingID("200"), RoutingSource: "memo", Warnings: []address.Warning{}, }, @@ -198,7 +198,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { name: "memo-return", input: RoutingInput{ Destination: testBaseG, - MemoType: "MEMO_RETURN", + MemoType: "return", MemoValue: "also-not-a-routing-id", }, expected: RoutingResult{ @@ -248,7 +248,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(9007199254740993), + RoutingID: NewRoutingID("9007199254740993"), RoutingSource: "muxed", Warnings: []address.Warning{}, }, @@ -262,7 +262,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(9007199254740993), + RoutingID: NewRoutingID("9007199254740993"), RoutingSource: "muxed", Warnings: []address.Warning{ { @@ -282,7 +282,7 @@ func TestExtractRouting_RoutingMatrix(t *testing.T) { }, expected: RoutingResult{ DestinationBaseAccount: testBaseG, - RoutingID: ptrUint64(9007199254740993), + RoutingID: NewRoutingID("9007199254740993"), RoutingSource: "muxed", Warnings: []address.Warning{ { @@ -331,36 +331,32 @@ func TestExtractRouting_ContractSourceClearsRoutingState(t *testing.T) { }) } -func ptrUint64(v uint64) *uint64 { - return &v -} - func assertRoutingResult(t *testing.T, got, want RoutingResult) { t.Helper() if got.DestinationBaseAccount != want.DestinationBaseAccount { t.Errorf("DestinationBaseAccount = %v, want %v", got.DestinationBaseAccount, want.DestinationBaseAccount) } - if !uint64PtrEqual(got.RoutingID, want.RoutingID) { - t.Errorf("RoutingID = %v, want %v", got.RoutingID, want.RoutingID) + if !routingIDEqual(got.RoutingID, want.RoutingID) { + t.Errorf("RoutingID = %v, want %v", got.RoutingID.String(), want.RoutingID.String()) } if got.RoutingSource != want.RoutingSource { t.Errorf("RoutingSource = %v, want %v", got.RoutingSource, want.RoutingSource) } if !reflect.DeepEqual(got.Warnings, want.Warnings) { - t.Errorf("Warnings = %#v, want %#v", got.Warnings, want.Warnings) + t.Errorf("Warnings = %#+v, want %#+v", got.Warnings, want.Warnings) } if !reflect.DeepEqual(got.DestinationError, want.DestinationError) { t.Errorf("DestinationError = %#v, want %#v", got.DestinationError, want.DestinationError) } } -func uint64PtrEqual(a, b *uint64) bool { +func routingIDEqual(a, b *RoutingID) bool { if a == nil && b == nil { return true } if a == nil || b == nil { return false } - return *a == *b + return a.String() == b.String() } diff --git a/packages/core-go/routing/result.go b/packages/core-go/routing/result.go index d0374c4..eed2b9b 100644 --- a/packages/core-go/routing/result.go +++ b/packages/core-go/routing/result.go @@ -4,8 +4,6 @@ import ( "encoding/json" "fmt" "strconv" - - "github.com/stellar-address-kit/core-go/address" ) type MemoType string @@ -18,6 +16,7 @@ const ( MemoTypeReturn MemoType = "return" ) +// RoutingID is a wrapper around a numeric string representing a 64-bit unsigned integer. type RoutingID struct { raw string } @@ -67,16 +66,3 @@ func (r *RoutingID) Uint64() (uint64, error) { func NewRoutingID(s string) *RoutingID { return &RoutingID{raw: s} } - -type RoutingResult struct { - DestinationBaseAccount string - RoutingID *RoutingID - RoutingSource string // "muxed" | "memo" | "none" - Warnings []address.Warning - DestinationError *DestinationError -} - -type DestinationError struct { - Code address.ErrorCode - Message string -} diff --git a/packages/core-go/routing/types.go b/packages/core-go/routing/types.go index 4734567..c8c556a 100644 --- a/packages/core-go/routing/types.go +++ b/packages/core-go/routing/types.go @@ -23,7 +23,7 @@ type RoutingResult struct { // Backward-compatible fields used by current extraction flow. DestinationBaseAccount string `json:"destinationBaseAccount,omitempty"` - RoutingID *uint64 `json:"routingId,omitempty"` + RoutingID *RoutingID `json:"routingId,omitempty"` RoutingSource string `json:"routingSource,omitempty"` Warnings []address.Warning `json:"warnings,omitempty"` DestinationError *DestinationError `json:"destinationError,omitempty"`