Skip to content

Commit

Permalink
feat(binary-codec): decode ledger data
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillemGarciaDev committed Nov 7, 2024
1 parent 504a451 commit 7453128
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 0 deletions.
101 changes: 101 additions & 0 deletions binary-codec/ledger_data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package binarycodec

import (
"encoding/binary"
"encoding/hex"
"strconv"
"strings"

"github.com/Peersyst/xrpl-go/binary-codec/definitions"
"github.com/Peersyst/xrpl-go/binary-codec/serdes"
)

// LedgerData represents the data of a ledger.
type LedgerData struct {
LedgerIndex uint32
TotalCoins string
ParentHash string
TransactionHash string
AccountHash string
ParentCloseTime uint32
CloseTime uint32
CloseTimeResolution uint8
CloseFlags uint8
}

// DecodeLedgerData decodes a hex string in the canonical binary format into a LedgerData object.
// The hex string should represent a ledger data object.
func DecodeLedgerData(data string) (LedgerData, error) {
decoded, err := hex.DecodeString(data)
if err != nil {
return LedgerData{}, err
}

parser := serdes.NewBinaryParser(decoded, definitions.Get())
var ledgerData LedgerData

ledgerIndex, err := parser.ReadBytes(4)
if err != nil {
return LedgerData{}, err
}

ledgerData.LedgerIndex = binary.BigEndian.Uint32(ledgerIndex)

totalCoins, err := parser.ReadBytes(8)
if err != nil {
return LedgerData{}, err
}

ledgerData.TotalCoins = strconv.FormatUint(binary.BigEndian.Uint64(totalCoins), 10)

parentHash, err := parser.ReadBytes(32)
if err != nil {
return LedgerData{}, err
}

ledgerData.ParentHash = strings.ToUpper(hex.EncodeToString(parentHash))

transactionHash, err := parser.ReadBytes(32)
if err != nil {
return LedgerData{}, err
}

ledgerData.TransactionHash = strings.ToUpper(hex.EncodeToString(transactionHash))

accountHash, err := parser.ReadBytes(32)
if err != nil {
return LedgerData{}, err
}

ledgerData.AccountHash = strings.ToUpper(hex.EncodeToString(accountHash))

parentCloseTime, err := parser.ReadBytes(4)
if err != nil {
return LedgerData{}, err
}

ledgerData.ParentCloseTime = binary.BigEndian.Uint32(parentCloseTime)

closeTime, err := parser.ReadBytes(4)
if err != nil {
return LedgerData{}, err
}

ledgerData.CloseTime = binary.BigEndian.Uint32(closeTime)

closeTimeResolution, err := parser.ReadByte()
if err != nil {
return LedgerData{}, err
}

ledgerData.CloseTimeResolution = uint8(closeTimeResolution)

closeFlags, err := parser.ReadByte()
if err != nil {
return LedgerData{}, err
}

ledgerData.CloseFlags = uint8(closeFlags)

return ledgerData, nil
}
97 changes: 97 additions & 0 deletions binary-codec/ledger_data_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package binarycodec

import (
"encoding/hex"
"testing"

"github.com/Peersyst/xrpl-go/binary-codec/serdes"
"github.com/stretchr/testify/require"
)

func TestDecodeLedgerData(t *testing.T) {
testcases := []struct {
name string
input string
expected LedgerData
expectedErr error
}{
{
name: "fail - invalid hex string",
input: "invalid",
expectedErr: hex.InvalidByteError(0x69),
},
{
name: "fail - invalid ledger index",
input: "01E914",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid total coins",
input: "01E91435016340767BF1",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid parent hash",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DE",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid transaction hash",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid account hash",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid parent close time",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276C",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid close time",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276C",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid close time resolution",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276CE6",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "fail - invalid close flags",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276CE60A",
expectedErr: serdes.ErrParserOutOfBound,
},
{
name: "pass - valid encoded ledger data",
input: "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276CE60A00",
expected: LedgerData{
AccountHash: "3B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D5",
CloseFlags: 0,
CloseTime: 556231910,
CloseTimeResolution: 10,
LedgerIndex: 32052277,
ParentCloseTime: 556231902,
ParentHash: "EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6",
TotalCoins: "99994494362043555",
TransactionHash: "DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F87",
},
},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
ledgerData, err := DecodeLedgerData(tc.input)
if tc.expectedErr != nil {
require.Error(t, err)
require.Equal(t, tc.expectedErr, err)
} else {
require.NoError(t, err)
require.Equal(t, tc.expected, ledgerData)
}
})
}
}

0 comments on commit 7453128

Please sign in to comment.