From 64ef8ccc56301a1fd4c0a13f08cb924ac252ed53 Mon Sep 17 00:00:00 2001 From: Kevin Pita Date: Tue, 28 Jul 2026 13:34:10 +0200 Subject: [PATCH 1/3] fix(binary-codec): align confidential MPT wire fields --- .../confidential_mpt_wire_fields_test.go | 144 ++++++++++++++++++ .../definitions/confidential_mpt_test.go | 107 +++++++++++++ binary-codec/definitions/definitions.go | 2 + binary-codec/definitions/definitions.json | 15 +- binary-codec/definitions/field_instance.go | 1 + .../confidential-mpt-wire-fields.json | 31 ++++ binary-codec/types/st_object.go | 13 +- binary-codec/types/uint32_test.go | 31 ++++ binary-codec/types/uint64.go | 30 +++- binary-codec/types/uint64_test.go | 50 +++++- 10 files changed, 408 insertions(+), 16 deletions(-) create mode 100644 binary-codec/confidential_mpt_wire_fields_test.go create mode 100644 binary-codec/definitions/confidential_mpt_test.go create mode 100644 binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json diff --git a/binary-codec/confidential_mpt_wire_fields_test.go b/binary-codec/confidential_mpt_wire_fields_test.go new file mode 100644 index 000000000..c9902f88d --- /dev/null +++ b/binary-codec/confidential_mpt_wire_fields_test.go @@ -0,0 +1,144 @@ +package binarycodec + +import ( + "encoding/hex" + "encoding/json" + "maps" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +type confidentialMPTWireFixtures struct { + Source string `json:"source"` + Cases []confidentialMPTWireFixture `json:"cases"` +} + +type confidentialMPTWireFixture struct { + Name string `json:"name"` + JSON map[string]any `json:"json"` + Binary string `json:"binary"` +} + +func loadConfidentialMPTWireFixtures(t *testing.T) confidentialMPTWireFixtures { + t.Helper() + + data, err := os.ReadFile("testdata/fixtures/confidential-mpt-wire-fields.json") + require.NoError(t, err) + + var fixtures confidentialMPTWireFixtures + require.NoError(t, json.Unmarshal(data, &fixtures)) + require.NotEmpty(t, fixtures.Source) + require.Len(t, fixtures.Cases, 3) + + return fixtures +} + +func TestConfidentialMPTWireFieldGoldenFixtures(t *testing.T) { + fixtures := loadConfidentialMPTWireFixtures(t) + + for _, fixture := range fixtures.Cases { + t.Run(fixture.Name, func(t *testing.T) { + expected := maps.Clone(fixture.JSON) + encoded, err := Encode(maps.Clone(expected)) + require.NoError(t, err) + require.Equal(t, fixture.Binary, encoded) + + decoded, err := Decode(fixture.Binary) + require.NoError(t, err) + require.Equal(t, expected, decoded) + + reencoded, err := Encode(decoded) + require.NoError(t, err) + require.Equal(t, fixture.Binary, reencoded) + }) + } +} + +func TestLiveRPCNumberTypesRoundTrip(t *testing.T) { + input := map[string]any{ + "TransactionType": "MPTokenIssuanceCreate", + "Flags": json.Number("160"), + "Sequence": json.Number("1"), + "LastLedgerSequence": json.Number("10"), + "MaximumAmount": "1000", + } + + encoded, err := Encode(maps.Clone(input)) + require.NoError(t, err) + + decoded, err := Decode(encoded) + require.NoError(t, err) + require.Equal(t, "MPTokenIssuanceCreate", decoded["TransactionType"]) + require.Equal(t, uint32(160), decoded["Flags"]) + require.Equal(t, uint32(1), decoded["Sequence"]) + require.Equal(t, uint32(10), decoded["LastLedgerSequence"]) + require.Equal(t, "1000", decoded["MaximumAmount"]) + + reencoded, err := Encode(decoded) + require.NoError(t, err) + require.Equal(t, encoded, reencoded) +} + +func TestMPTBaseTenUInt64GoldenWireValues(t *testing.T) { + tests := []struct { + field string + header string + }{ + {field: "MaximumAmount", header: "3018"}, + {field: "OutstandingAmount", header: "3019"}, + {field: "MPTAmount", header: "301A"}, + {field: "LockedAmount", header: "301D"}, + {field: "ConfidentialOutstandingAmount", header: "3020"}, + } + + for _, tt := range tests { + t.Run(tt.field, func(t *testing.T) { + expected := tt.header + "00000000000003E8" + encoded, err := Encode(map[string]any{tt.field: "1000"}) + require.NoError(t, err) + require.Equal(t, expected, encoded) + + decoded, err := Decode(expected) + require.NoError(t, err) + require.Equal(t, map[string]any{tt.field: "1000"}, decoded) + + reencoded, err := Encode(decoded) + require.NoError(t, err) + require.Equal(t, expected, reencoded) + }) + } +} + +func TestConfidentialMPTGoldenWireLayout(t *testing.T) { + fixtures := loadConfidentialMPTWireFixtures(t) + byName := make(map[string]confidentialMPTWireFixture, len(fixtures.Cases)) + for _, fixture := range fixtures.Cases { + byName[fixture.Name] = fixture + } + + convert, err := hex.DecodeString(byName["convert_blinding_factor"].Binary) + require.NoError(t, err) + require.Len(t, convert, 37) + require.Equal(t, []byte{0x12, 0x00, 0x55}, convert[:3]) + require.Equal(t, []byte{0x50, 0x28}, convert[3:5]) + blindingFactor, err := hex.DecodeString(byName["convert_blinding_factor"].JSON["BlindingFactor"].(string)) + require.NoError(t, err) + require.Equal(t, blindingFactor, convert[5:37]) + + convertBack, err := hex.DecodeString(byName["convert_back_blinding_and_balance_commitment"].Binary) + require.NoError(t, err) + require.Len(t, convertBack, 73) + require.Equal(t, []byte{0x12, 0x00, 0x57}, convertBack[:3]) + require.Equal(t, []byte{0x50, 0x28}, convertBack[3:5]) + require.Equal(t, blindingFactor, convertBack[5:37]) + require.Equal(t, []byte{0x70, 0x2E, 0x21}, convertBack[37:40]) + + send, err := hex.DecodeString(byName["send_amount_and_balance_commitments"].Binary) + require.NoError(t, err) + require.Len(t, send, 75) + require.Equal(t, []byte{0x12, 0x00, 0x58}, send[:3]) + require.Equal(t, []byte{0x70, 0x2D, 0x21}, send[3:6]) + require.Equal(t, []byte{0x70, 0x2E, 0x21}, send[39:42]) +} diff --git a/binary-codec/definitions/confidential_mpt_test.go b/binary-codec/definitions/confidential_mpt_test.go new file mode 100644 index 000000000..0bcfe8113 --- /dev/null +++ b/binary-codec/definitions/confidential_mpt_test.go @@ -0,0 +1,107 @@ +package definitions + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestConfidentialMPTWireFieldDefinitions(t *testing.T) { + tests := []struct { + name string + info FieldInfo + header FieldHeader + ordinal int32 + }{ + { + name: "BlindingFactor", + info: FieldInfo{ + Nth: 40, + IsVLEncoded: false, + IsSerialized: true, + IsSigningField: true, + Type: "Hash256", + }, + header: FieldHeader{TypeCode: 5, FieldCode: 40}, + ordinal: 327720, + }, + { + name: "AmountCommitment", + info: FieldInfo{ + Nth: 45, + IsVLEncoded: true, + IsSerialized: true, + IsSigningField: true, + Type: "Blob", + }, + header: FieldHeader{TypeCode: 7, FieldCode: 45}, + ordinal: 458797, + }, + { + name: "BalanceCommitment", + info: FieldInfo{ + Nth: 46, + IsVLEncoded: true, + IsSerialized: true, + IsSigningField: true, + Type: "Blob", + }, + header: FieldHeader{TypeCode: 7, FieldCode: 46}, + ordinal: 458798, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + field, err := Get().GetFieldInstanceByFieldName(tc.name) + require.NoError(t, err) + require.Equal(t, tc.info, *field.FieldInfo) + require.Equal(t, tc.header, *field.FieldHeader) + require.Equal(t, tc.ordinal, field.Ordinal) + }) + } +} + +func TestMPTUInt64BaseTenDefinitions(t *testing.T) { + baseTenFields := []string{ + "MaximumAmount", + "OutstandingAmount", + "MPTAmount", + "LockedAmount", + "ConfidentialOutstandingAmount", + } + + for _, name := range baseTenFields { + t.Run(name, func(t *testing.T) { + field, err := Get().GetFieldInstanceByFieldName(name) + require.NoError(t, err) + require.Equal(t, "UInt64", field.Type) + require.True(t, field.IsBaseTen) + }) + } + + field, err := Get().GetFieldInstanceByFieldName("IssuerNode") + require.NoError(t, err) + require.False(t, field.IsBaseTen) +} + +func TestConfidentialMPTTransactionTypeCodes(t *testing.T) { + tests := []struct { + name string + code int32 + }{ + {name: "ConfidentialMPTConvert", code: 85}, + {name: "ConfidentialMPTMergeInbox", code: 86}, + {name: "ConfidentialMPTConvertBack", code: 87}, + {name: "ConfidentialMPTSend", code: 88}, + {name: "ConfidentialMPTClawback", code: 89}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + code, err := Get().GetTransactionTypeCodeByTransactionTypeName(tc.name) + require.NoError(t, err) + require.Equal(t, tc.code, code) + }) + } +} diff --git a/binary-codec/definitions/definitions.go b/binary-codec/definitions/definitions.go index 52aca93ff..25d611786 100644 --- a/binary-codec/definitions/definitions.go +++ b/binary-codec/definitions/definitions.go @@ -85,6 +85,7 @@ func convertToFieldInstanceMap(m [][]any) map[string]*FieldInstance { func castFieldInfo(v any) (FieldInfo, error) { if fi, ok := v.(map[string]any); ok { + isBaseTen, _ := fi["isBaseTen"].(bool) return FieldInfo{ // TODO: Check if this is still needed //nolint:gosec // G115: integer overflow conversion int64 -> int32, nth is a small field ordinal @@ -92,6 +93,7 @@ func castFieldInfo(v any) (FieldInfo, error) { IsVLEncoded: fi["isVLEncoded"].(bool), IsSerialized: fi["isSerialized"].(bool), IsSigningField: fi["isSigningField"].(bool), + IsBaseTen: isBaseTen, Type: fi["type"].(string), }, nil } diff --git a/binary-codec/definitions/definitions.json b/binary-codec/definitions/definitions.json index 9d421d489..95db2ff81 100644 --- a/binary-codec/definitions/definitions.json +++ b/binary-codec/definitions/definitions.json @@ -1073,6 +1073,7 @@ [ "MaximumAmount", { + "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1083,6 +1084,7 @@ [ "OutstandingAmount", { + "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1093,6 +1095,7 @@ [ "MPTAmount", { + "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1123,6 +1126,7 @@ [ "LockedAmount", { + "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1153,6 +1157,7 @@ [ "ConfidentialOutstandingAmount", { + "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -2255,9 +2260,9 @@ { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 45, - "type": "Blob" + "isVLEncoded": false, + "nth": 40, + "type": "Hash256" } ], [ @@ -2266,7 +2271,7 @@ "isSerialized": true, "isSigningField": true, "isVLEncoded": true, - "nth": 46, + "nth": 45, "type": "Blob" } ], @@ -2276,7 +2281,7 @@ "isSerialized": true, "isSigningField": true, "isVLEncoded": true, - "nth": 47, + "nth": 46, "type": "Blob" } ], diff --git a/binary-codec/definitions/field_instance.go b/binary-codec/definitions/field_instance.go index 915590870..762fb299e 100644 --- a/binary-codec/definitions/field_instance.go +++ b/binary-codec/definitions/field_instance.go @@ -16,6 +16,7 @@ type FieldInfo struct { IsVLEncoded bool IsSerialized bool IsSigningField bool + IsBaseTen bool Type string } diff --git a/binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json b/binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json new file mode 100644 index 000000000..957aa7511 --- /dev/null +++ b/binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json @@ -0,0 +1,31 @@ +{ + "source": "Manually assembled from rippled ba01b05f33d4b28c30ce347d0cd68c4d83005359 SField type/ordinal headers and XRPL canonical VL rules; not generated by xrpl-go.", + "cases": [ + { + "name": "convert_blinding_factor", + "json": { + "TransactionType": "ConfidentialMPTConvert", + "BlindingFactor": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" + }, + "binary": "1200555028000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" + }, + { + "name": "convert_back_blinding_and_balance_commitment", + "json": { + "TransactionType": "ConfidentialMPTConvertBack", + "BlindingFactor": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "BalanceCommitment": "032222222222222222222222222222222222222222222222222222222222222222" + }, + "binary": "1200575028000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F702E21032222222222222222222222222222222222222222222222222222222222222222" + }, + { + "name": "send_amount_and_balance_commitments", + "json": { + "TransactionType": "ConfidentialMPTSend", + "AmountCommitment": "021111111111111111111111111111111111111111111111111111111111111111", + "BalanceCommitment": "032222222222222222222222222222222222222222222222222222222222222222" + }, + "binary": "120058702D21021111111111111111111111111111111111111111111111111111111111111111702E21032222222222222222222222222222222222222222222222222222222222222222" + } + ] +} diff --git a/binary-codec/types/st_object.go b/binary-codec/types/st_object.go index 7b10abbfb..cb4fb97e4 100644 --- a/binary-codec/types/st_object.go +++ b/binary-codec/types/st_object.go @@ -43,7 +43,12 @@ func (t *STObject) FromJSON(json any) ([]byte, error) { } st := GetSerializedType(v.Type) - b, err := st.FromJSON(fimap[v]) + var b []byte + if v.Type == "UInt64" && v.IsBaseTen { + b, err = (&UInt64{}).fromJSON(fimap[v], uint64BaseTen) + } else { + b, err = st.FromJSON(fimap[v]) + } if err != nil { return nil, err } @@ -89,7 +94,11 @@ func (t *STObject) ToJSON(p interfaces.BinaryParser, _ ...int) (any, error) { } } else { - res, err = st.ToJSON(p) + if fi.Type == "UInt64" && fi.IsBaseTen { + res, err = st.ToJSON(p, uint64BaseTen) + } else { + res, err = st.ToJSON(p) + } if err != nil { return nil, fmt.Errorf("ToJSON error for field %q (type=%s): %w", fi.FieldName, fi.Type, err) } diff --git a/binary-codec/types/uint32_test.go b/binary-codec/types/uint32_test.go index c87e5384d..f2a737a1e 100644 --- a/binary-codec/types/uint32_test.go +++ b/binary-codec/types/uint32_test.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "encoding/json" "errors" "fmt" "testing" @@ -69,6 +70,18 @@ func TestUint32_FromJson(t *testing.T) { expected: []byte{0, 0, 1, 244}, expectedErr: nil, }, + { + name: "Valid uint32 - from json number", + input: json.Number("500"), + expected: []byte{0, 0, 1, 244}, + expectedErr: nil, + }, + { + name: "Valid uint32 max - from json number", + input: json.Number("4294967295"), + expected: []byte{0xFF, 0xFF, 0xFF, 0xFF}, + expectedErr: nil, + }, { name: "Error - negative int", input: int(-1), @@ -111,6 +124,24 @@ func TestUint32_FromJson(t *testing.T) { expected: nil, expectedErr: ErrUInt32OutOfRange, }, + { + name: "Error - negative json number", + input: json.Number("-1"), + expected: nil, + expectedErr: ErrUInt32OutOfRange, + }, + { + name: "Error - json number overflow", + input: json.Number("4294967296"), + expected: nil, + expectedErr: ErrUInt32OutOfRange, + }, + { + name: "Error - fractional json number", + input: json.Number("1.5"), + expected: nil, + expectedErr: ErrUInt32OutOfRange, + }, { name: "Error - invalid type (string)", input: "not a number", diff --git a/binary-codec/types/uint64.go b/binary-codec/types/uint64.go index 84aaa24c4..68fec04eb 100644 --- a/binary-codec/types/uint64.go +++ b/binary-codec/types/uint64.go @@ -2,15 +2,17 @@ package types import ( - "encoding/hex" + "encoding/binary" "errors" - "strings" + "strconv" "github.com/Peersyst/xrpl-go/binary-codec/types/interfaces" "github.com/Peersyst/xrpl-go/pkg/hexutil" "github.com/Peersyst/xrpl-go/pkg/typecheck" ) +const uint64BaseTen = 10 + // UInt64 represents a 64-bit unsigned integer serialized from a hex JSON string. type UInt64 struct{} @@ -26,31 +28,43 @@ var ErrInvalidUInt64String = errors.New("invalid UInt64 string, value should be // Returns ErrInvalidUInt64String when the input is not a string, contains non-hex // characters, or exceeds 16 characters. func (u *UInt64) FromJSON(value any) ([]byte, error) { + return u.fromJSON(value, 16) +} + +func (u *UInt64) fromJSON(value any, base int) ([]byte, error) { strValue, ok := value.(string) if !ok { return nil, ErrInvalidUInt64String } - if len(strValue) > 16 || !typecheck.IsHex(strValue) { + if base == 16 && (len(strValue) > 16 || !typecheck.IsHex(strValue)) { return nil, ErrInvalidUInt64String } - // Right justify the string to 16 hex characters (8 bytes) - strValue = strings.Repeat("0", 16-len(strValue)) + strValue - decoded, err := hex.DecodeString(strValue) + parsed, err := strconv.ParseUint(strValue, base, 64) if err != nil { + var numErr *strconv.NumError + if errors.As(err, &numErr) && errors.Is(numErr.Err, strconv.ErrRange) { + return nil, ErrInvalidUInt64String + } return nil, err } - return decoded, nil + + serialized := make([]byte, 8) + binary.BigEndian.PutUint64(serialized, parsed) + return serialized, nil } // ToJSON takes a BinaryParser and optional parameters, and converts the serialized byte data // back into a JSON string value. This method assumes the parser contains data representing // a 64-bit unsigned integer. If the parsing fails, an error is returned. -func (u *UInt64) ToJSON(p interfaces.BinaryParser, _ ...int) (any, error) { +func (u *UInt64) ToJSON(p interfaces.BinaryParser, opts ...int) (any, error) { b, err := p.ReadBytes(8) if err != nil { return nil, err } + if len(opts) > 0 && opts[0] == uint64BaseTen { + return strconv.FormatUint(binary.BigEndian.Uint64(b), uint64BaseTen), nil + } return hexutil.EncodeToUpperHex(b), nil } diff --git a/binary-codec/types/uint64_test.go b/binary-codec/types/uint64_test.go index 0e4e68679..851b40445 100644 --- a/binary-codec/types/uint64_test.go +++ b/binary-codec/types/uint64_test.go @@ -118,6 +118,43 @@ func TestUint64_FromJson(t *testing.T) { } } +func TestUInt64FromBaseTenJSON(t *testing.T) { + tests := []struct { + name string + input any + expected []byte + expectedErr error + }{ + { + name: "decimal one thousand", + input: "1000", + expected: []byte{0, 0, 0, 0, 0, 0, 3, 232}, + }, + { + name: "maximum uint64", + input: "18446744073709551615", + expected: []byte{255, 255, 255, 255, 255, 255, 255, 255}, + }, + { + name: "decimal overflow", + input: "18446744073709551616", + expectedErr: ErrInvalidUInt64String, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual, err := (&UInt64{}).fromJSON(tt.input, uint64BaseTen) + if tt.expectedErr != nil { + require.ErrorIs(t, err, tt.expectedErr) + return + } + require.NoError(t, err) + require.Equal(t, tt.expected, actual) + }) + } +} + func TestUint64_ToJson(t *testing.T) { defs := definitions.Get() @@ -127,6 +164,7 @@ func TestUint64_ToJson(t *testing.T) { malleate func(t *testing.T) interfaces.BinaryParser expected string expectedErr error + opts []int }{ { name: "fail - binary parser has no data", @@ -175,13 +213,23 @@ func TestUint64_ToJson(t *testing.T) { return serdes.NewBinaryParser([]byte{255, 255, 255, 255, 255, 255, 255, 255}, defs) }, }, + { + name: "pass - base ten field", + input: []byte{0, 0, 0, 0, 0, 0, 3, 232}, + expected: "1000", + expectedErr: nil, + opts: []int{uint64BaseTen}, + malleate: func(t *testing.T) interfaces.BinaryParser { + return serdes.NewBinaryParser([]byte{0, 0, 0, 0, 0, 0, 3, 232}, defs) + }, + }, } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { class := &UInt64{} parser := tc.malleate(t) - actual, err := class.ToJSON(parser) + actual, err := class.ToJSON(parser, tc.opts...) if tc.expectedErr != nil { require.EqualError(t, err, tc.expectedErr.Error()) } else { From b6cd47ee911d8d8a7eec7f1e6d83d820a66f31ee Mon Sep 17 00:00:00 2001 From: Kevin Pita Date: Wed, 29 Jul 2026 14:02:38 +0200 Subject: [PATCH 2/3] fix(binary-codec): sync definitions.json --- .../definitions/confidential_mpt_test.go | 27 +- binary-codec/definitions/definitions.go | 2 - binary-codec/definitions/definitions.json | 3385 +++++++++++++++-- binary-codec/definitions/definitions_test.go | 2 +- binary-codec/definitions/field_instance.go | 1 - binary-codec/types/st_object.go | 8 +- binary-codec/types/uint64.go | 24 +- binary-codec/types/uint64_test.go | 4 +- binary-codec/types/uint8.go | 6 +- binary-codec/types/uint8_test.go | 14 +- 10 files changed, 3212 insertions(+), 261 deletions(-) diff --git a/binary-codec/definitions/confidential_mpt_test.go b/binary-codec/definitions/confidential_mpt_test.go index 0bcfe8113..f08f13120 100644 --- a/binary-codec/definitions/confidential_mpt_test.go +++ b/binary-codec/definitions/confidential_mpt_test.go @@ -62,27 +62,22 @@ func TestConfidentialMPTWireFieldDefinitions(t *testing.T) { } } -func TestMPTUInt64BaseTenDefinitions(t *testing.T) { - baseTenFields := []string{ - "MaximumAmount", - "OutstandingAmount", - "MPTAmount", - "LockedAmount", - "ConfidentialOutstandingAmount", +func TestConfidentialMPTTransactionResultCodes(t *testing.T) { + tests := []struct { + name string + code int32 + }{ + {name: "tecBAD_PROOF", code: 199}, + {name: "temBAD_CIPHERTEXT", code: -248}, } - for _, name := range baseTenFields { - t.Run(name, func(t *testing.T) { - field, err := Get().GetFieldInstanceByFieldName(name) + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + code, err := Get().GetTransactionResultTypeCodeByTransactionResultName(tc.name) require.NoError(t, err) - require.Equal(t, "UInt64", field.Type) - require.True(t, field.IsBaseTen) + require.Equal(t, tc.code, code) }) } - - field, err := Get().GetFieldInstanceByFieldName("IssuerNode") - require.NoError(t, err) - require.False(t, field.IsBaseTen) } func TestConfidentialMPTTransactionTypeCodes(t *testing.T) { diff --git a/binary-codec/definitions/definitions.go b/binary-codec/definitions/definitions.go index 25d611786..52aca93ff 100644 --- a/binary-codec/definitions/definitions.go +++ b/binary-codec/definitions/definitions.go @@ -85,7 +85,6 @@ func convertToFieldInstanceMap(m [][]any) map[string]*FieldInstance { func castFieldInfo(v any) (FieldInfo, error) { if fi, ok := v.(map[string]any); ok { - isBaseTen, _ := fi["isBaseTen"].(bool) return FieldInfo{ // TODO: Check if this is still needed //nolint:gosec // G115: integer overflow conversion int64 -> int32, nth is a small field ordinal @@ -93,7 +92,6 @@ func castFieldInfo(v any) (FieldInfo, error) { IsVLEncoded: fi["isVLEncoded"].(bool), IsSerialized: fi["isSerialized"].(bool), IsSigningField: fi["isSigningField"].(bool), - IsBaseTen: isBaseTen, Type: fi["type"].(string), }, nil } diff --git a/binary-codec/definitions/definitions.json b/binary-codec/definitions/definitions.json index 95db2ff81..a261e322f 100644 --- a/binary-codec/definitions/definitions.json +++ b/binary-codec/definitions/definitions.json @@ -1,15 +1,23 @@ { + "ACCOUNT_SET_FLAGS": { + "asfAccountTxnID": 5, + "asfAllowTrustLineClawback": 16, + "asfAllowTrustLineLocking": 17, + "asfAuthorizedNFTokenMinter": 10, + "asfDefaultRipple": 8, + "asfDepositAuth": 9, + "asfDisableMaster": 4, + "asfDisallowIncomingCheck": 13, + "asfDisallowIncomingNFTokenOffer": 12, + "asfDisallowIncomingPayChan": 14, + "asfDisallowIncomingTrustline": 15, + "asfDisallowXRP": 3, + "asfGlobalFreeze": 7, + "asfNoFreeze": 6, + "asfRequireAuth": 2, + "asfRequireDest": 1 + }, "FIELDS": [ - [ - "Generic", - { - "isSerialized": false, - "isSigningField": false, - "isVLEncoded": false, - "nth": 0, - "type": "Unknown" - } - ], [ "Invalid", { @@ -60,6 +68,16 @@ "type": "Amount" } ], + [ + "Generic", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 0, + "type": "Unknown" + } + ], [ "LedgerEntryType", { @@ -850,16 +868,6 @@ "type": "UInt32" } ], - [ - "ConfidentialBalanceVersion", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": false, - "nth": 69, - "type": "UInt32" - } - ], [ "IndexNext", { @@ -1073,7 +1081,6 @@ [ "MaximumAmount", { - "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1084,7 +1091,6 @@ [ "OutstandingAmount", { - "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1095,7 +1101,6 @@ [ "MPTAmount", { - "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1126,7 +1131,6 @@ [ "LockedAmount", { - "isBaseTen": true, "isSerialized": true, "isSigningField": true, "isVLEncoded": false, @@ -1154,17 +1158,6 @@ "type": "UInt64" } ], - [ - "ConfidentialOutstandingAmount", - { - "isBaseTen": true, - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": false, - "nth": 32, - "type": "UInt64" - } - ], [ "EmailHash", { @@ -1535,6 +1528,16 @@ "type": "Hash256" } ], + [ + "ReferenceHolding", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 39, + "type": "Hash256" + } + ], [ "hash", { @@ -2125,166 +2128,6 @@ "type": "Blob" } ], - [ - "ConfidentialBalanceInbox", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 32, - "type": "Blob" - } - ], - [ - "ConfidentialBalanceSpending", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 33, - "type": "Blob" - } - ], - [ - "IssuerEncryptedBalance", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 34, - "type": "Blob" - } - ], - [ - "IssuerEncryptionKey", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 35, - "type": "Blob" - } - ], - [ - "HolderEncryptionKey", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 36, - "type": "Blob" - } - ], - [ - "ZKProof", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 37, - "type": "Blob" - } - ], - [ - "HolderEncryptedAmount", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 38, - "type": "Blob" - } - ], - [ - "IssuerEncryptedAmount", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 39, - "type": "Blob" - } - ], - [ - "SenderEncryptedAmount", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 40, - "type": "Blob" - } - ], - [ - "DestinationEncryptedAmount", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 41, - "type": "Blob" - } - ], - [ - "AuditorEncryptedBalance", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 42, - "type": "Blob" - } - ], - [ - "AuditorEncryptedAmount", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 43, - "type": "Blob" - } - ], - [ - "AuditorEncryptionKey", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 44, - "type": "Blob" - } - ], - [ - "BlindingFactor", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": false, - "nth": 40, - "type": "Hash256" - } - ], - [ - "AmountCommitment", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 45, - "type": "Blob" - } - ], - [ - "BalanceCommitment", - { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 46, - "type": "Blob" - } - ], [ "Account", { @@ -3505,6 +3348,26 @@ "type": "Hash192" } ], + [ + "TakerPaysMPT", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 3, + "type": "Hash192" + } + ], + [ + "TakerGetsMPT", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 4, + "type": "Hash192" + } + ], [ "LockingChainIssue", { @@ -3606,32 +3469,1618 @@ } ], [ - "Metadata", + "ConfidentialOutstandingAmount", { - "isSerialized": false, - "isSigningField": false, + "isSerialized": true, + "isSigningField": true, "isVLEncoded": false, - "nth": 257, - "type": "Metadata" + "nth": 32, + "type": "UInt64" } - ] - ], - "LEDGER_ENTRY_TYPES": { - "AMM": 121, - "AccountRoot": 97, - "Amendments": 102, - "Bridge": 105, - "Check": 67, - "Credential": 129, - "DID": 73, - "Delegate": 131, - "DepositPreauth": 112, - "DirectoryNode": 100, - "Escrow": 117, - "FeeSettings": 115, - "Invalid": -1, - "LedgerHashes": 104, - "Loan": 137, + ], + [ + "ConfidentialBalanceVersion", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 69, + "type": "UInt32" + } + ], + [ + "BlindingFactor", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": false, + "nth": 40, + "type": "Hash256" + } + ], + [ + "ConfidentialBalanceInbox", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 32, + "type": "Blob" + } + ], + [ + "ConfidentialBalanceSpending", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 33, + "type": "Blob" + } + ], + [ + "IssuerEncryptedBalance", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 34, + "type": "Blob" + } + ], + [ + "IssuerEncryptionKey", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 35, + "type": "Blob" + } + ], + [ + "HolderEncryptionKey", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 36, + "type": "Blob" + } + ], + [ + "ZKProof", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 37, + "type": "Blob" + } + ], + [ + "HolderEncryptedAmount", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 38, + "type": "Blob" + } + ], + [ + "IssuerEncryptedAmount", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 39, + "type": "Blob" + } + ], + [ + "SenderEncryptedAmount", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 40, + "type": "Blob" + } + ], + [ + "DestinationEncryptedAmount", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 41, + "type": "Blob" + } + ], + [ + "AuditorEncryptedBalance", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 42, + "type": "Blob" + } + ], + [ + "AuditorEncryptedAmount", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 43, + "type": "Blob" + } + ], + [ + "AuditorEncryptionKey", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 44, + "type": "Blob" + } + ], + [ + "AmountCommitment", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 45, + "type": "Blob" + } + ], + [ + "BalanceCommitment", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 46, + "type": "Blob" + } + ], + [ + "Metadata", + { + "isSerialized": false, + "isSigningField": false, + "isVLEncoded": false, + "nth": 257, + "type": "Metadata" + } + ] + ], + "LEDGER_ENTRY_FLAGS": { + "AccountRoot": { + "lsfAllowTrustLineClawback": 2147483648, + "lsfAllowTrustLineLocking": 1073741824, + "lsfDefaultRipple": 8388608, + "lsfDepositAuth": 16777216, + "lsfDisableMaster": 1048576, + "lsfDisallowIncomingCheck": 134217728, + "lsfDisallowIncomingNFTokenOffer": 67108864, + "lsfDisallowIncomingPayChan": 268435456, + "lsfDisallowIncomingTrustline": 536870912, + "lsfDisallowXRP": 524288, + "lsfGlobalFreeze": 4194304, + "lsfNoFreeze": 2097152, + "lsfPasswordSpent": 65536, + "lsfRequireAuth": 262144, + "lsfRequireDestTag": 131072 + }, + "Credential": { + "lsfAccepted": 65536 + }, + "DirNode": { + "lsfNFTokenBuyOffers": 1, + "lsfNFTokenSellOffers": 2 + }, + "Loan": { + "lsfLoanDefault": 65536, + "lsfLoanImpaired": 131072, + "lsfLoanOverpayment": 262144 + }, + "MPToken": { + "lsfMPTAMM": 4, + "lsfMPTAuthorized": 2, + "lsfMPTLocked": 1 + }, + "MPTokenIssuance": { + "lsfMPTCanClawback": 64, + "lsfMPTCanEscrow": 8, + "lsfMPTCanLock": 2, + "lsfMPTCanTrade": 16, + "lsfMPTCanTransfer": 32, + "lsfMPTLocked": 1, + "lsfMPTRequireAuth": 4 + }, + "MPTokenIssuanceMutable": { + "lsmfMPTCanEnableCanClawback": 64, + "lsmfMPTCanEnableCanEscrow": 8, + "lsmfMPTCanEnableCanLock": 2, + "lsmfMPTCanEnableCanTrade": 16, + "lsmfMPTCanEnableCanTransfer": 32, + "lsmfMPTCanEnableRequireAuth": 4, + "lsmfMPTCanMutateMetadata": 65536, + "lsmfMPTCanMutateTransferFee": 131072 + }, + "NFTokenOffer": { + "lsfSellNFToken": 1 + }, + "Offer": { + "lsfHybrid": 262144, + "lsfPassive": 65536, + "lsfSell": 131072 + }, + "RippleState": { + "lsfAMMNode": 16777216, + "lsfHighAuth": 524288, + "lsfHighDeepFreeze": 67108864, + "lsfHighFreeze": 8388608, + "lsfHighNoRipple": 2097152, + "lsfHighReserve": 131072, + "lsfLowAuth": 262144, + "lsfLowDeepFreeze": 33554432, + "lsfLowFreeze": 4194304, + "lsfLowNoRipple": 1048576, + "lsfLowReserve": 65536 + }, + "SignerList": { + "lsfOneOwnerCount": 65536 + }, + "Vault": { + "lsfVaultPrivate": 65536 + } + }, + "LEDGER_ENTRY_FORMATS": { + "AMM": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "TradingFee", + "optionality": 2 + }, + { + "name": "VoteSlots", + "optionality": 1 + }, + { + "name": "AuctionSlot", + "optionality": 1 + }, + { + "name": "LPTokenBalance", + "optionality": 0 + }, + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "Asset2", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 1 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 1 + } + ], + "AccountRoot": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "Balance", + "optionality": 0 + }, + { + "name": "OwnerCount", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "AccountTxnID", + "optionality": 1 + }, + { + "name": "RegularKey", + "optionality": 1 + }, + { + "name": "EmailHash", + "optionality": 1 + }, + { + "name": "WalletLocator", + "optionality": 1 + }, + { + "name": "WalletSize", + "optionality": 1 + }, + { + "name": "MessageKey", + "optionality": 1 + }, + { + "name": "TransferRate", + "optionality": 1 + }, + { + "name": "Domain", + "optionality": 1 + }, + { + "name": "TickSize", + "optionality": 1 + }, + { + "name": "TicketCount", + "optionality": 1 + }, + { + "name": "NFTokenMinter", + "optionality": 1 + }, + { + "name": "MintedNFTokens", + "optionality": 2 + }, + { + "name": "BurnedNFTokens", + "optionality": 2 + }, + { + "name": "FirstNFTokenSequence", + "optionality": 1 + }, + { + "name": "AMMID", + "optionality": 1 + }, + { + "name": "VaultID", + "optionality": 1 + }, + { + "name": "LoanBrokerID", + "optionality": 1 + } + ], + "Amendments": [ + { + "name": "Amendments", + "optionality": 1 + }, + { + "name": "Majorities", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 1 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 1 + } + ], + "Bridge": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "SignatureReward", + "optionality": 0 + }, + { + "name": "MinAccountCreateAmount", + "optionality": 1 + }, + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "XChainClaimID", + "optionality": 0 + }, + { + "name": "XChainAccountCreateCount", + "optionality": 0 + }, + { + "name": "XChainAccountClaimCount", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "Check": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "SendMax", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "DestinationNode", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "InvoiceID", + "optionality": 1 + }, + { + "name": "SourceTag", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "Credential": [ + { + "name": "Subject", + "optionality": 0 + }, + { + "name": "Issuer", + "optionality": 0 + }, + { + "name": "CredentialType", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "URI", + "optionality": 1 + }, + { + "name": "IssuerNode", + "optionality": 0 + }, + { + "name": "SubjectNode", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "DID": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "DIDDocument", + "optionality": 1 + }, + { + "name": "URI", + "optionality": 1 + }, + { + "name": "Data", + "optionality": 1 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "Delegate": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Authorize", + "optionality": 0 + }, + { + "name": "Permissions", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "DestinationNode", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "DepositPreauth": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Authorize", + "optionality": 1 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "AuthorizeCredentials", + "optionality": 1 + } + ], + "DirectoryNode": [ + { + "name": "Owner", + "optionality": 1 + }, + { + "name": "TakerPaysCurrency", + "optionality": 1 + }, + { + "name": "TakerPaysIssuer", + "optionality": 1 + }, + { + "name": "TakerPaysMPT", + "optionality": 1 + }, + { + "name": "TakerGetsCurrency", + "optionality": 1 + }, + { + "name": "TakerGetsIssuer", + "optionality": 1 + }, + { + "name": "TakerGetsMPT", + "optionality": 1 + }, + { + "name": "ExchangeRate", + "optionality": 1 + }, + { + "name": "Indexes", + "optionality": 0 + }, + { + "name": "RootIndex", + "optionality": 0 + }, + { + "name": "IndexNext", + "optionality": 1 + }, + { + "name": "IndexPrevious", + "optionality": 1 + }, + { + "name": "NFTokenID", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 1 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + } + ], + "Escrow": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 1 + }, + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Condition", + "optionality": 1 + }, + { + "name": "CancelAfter", + "optionality": 1 + }, + { + "name": "FinishAfter", + "optionality": 1 + }, + { + "name": "SourceTag", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "DestinationNode", + "optionality": 1 + }, + { + "name": "TransferRate", + "optionality": 1 + }, + { + "name": "IssuerNode", + "optionality": 1 + } + ], + "FeeSettings": [ + { + "name": "BaseFee", + "optionality": 1 + }, + { + "name": "ReferenceFeeUnits", + "optionality": 1 + }, + { + "name": "ReserveBase", + "optionality": 1 + }, + { + "name": "ReserveIncrement", + "optionality": 1 + }, + { + "name": "BaseFeeDrops", + "optionality": 1 + }, + { + "name": "ReserveBaseDrops", + "optionality": 1 + }, + { + "name": "ReserveIncrementDrops", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 1 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 1 + } + ], + "LedgerHashes": [ + { + "name": "FirstLedgerSequence", + "optionality": 1 + }, + { + "name": "LastLedgerSequence", + "optionality": 1 + }, + { + "name": "Hashes", + "optionality": 0 + } + ], + "Loan": [ + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "LoanBrokerNode", + "optionality": 0 + }, + { + "name": "LoanBrokerID", + "optionality": 0 + }, + { + "name": "LoanSequence", + "optionality": 0 + }, + { + "name": "Borrower", + "optionality": 0 + }, + { + "name": "LoanOriginationFee", + "optionality": 2 + }, + { + "name": "LoanServiceFee", + "optionality": 2 + }, + { + "name": "LatePaymentFee", + "optionality": 2 + }, + { + "name": "ClosePaymentFee", + "optionality": 2 + }, + { + "name": "OverpaymentFee", + "optionality": 2 + }, + { + "name": "InterestRate", + "optionality": 2 + }, + { + "name": "LateInterestRate", + "optionality": 2 + }, + { + "name": "CloseInterestRate", + "optionality": 2 + }, + { + "name": "OverpaymentInterestRate", + "optionality": 2 + }, + { + "name": "StartDate", + "optionality": 0 + }, + { + "name": "PaymentInterval", + "optionality": 0 + }, + { + "name": "GracePeriod", + "optionality": 2 + }, + { + "name": "PreviousPaymentDueDate", + "optionality": 2 + }, + { + "name": "NextPaymentDueDate", + "optionality": 2 + }, + { + "name": "PaymentRemaining", + "optionality": 2 + }, + { + "name": "PeriodicPayment", + "optionality": 0 + }, + { + "name": "PrincipalOutstanding", + "optionality": 2 + }, + { + "name": "TotalValueOutstanding", + "optionality": 2 + }, + { + "name": "ManagementFeeOutstanding", + "optionality": 2 + }, + { + "name": "LoanScale", + "optionality": 2 + } + ], + "LoanBroker": [ + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "VaultNode", + "optionality": 0 + }, + { + "name": "VaultID", + "optionality": 0 + }, + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Owner", + "optionality": 0 + }, + { + "name": "LoanSequence", + "optionality": 0 + }, + { + "name": "Data", + "optionality": 2 + }, + { + "name": "ManagementFeeRate", + "optionality": 2 + }, + { + "name": "OwnerCount", + "optionality": 2 + }, + { + "name": "DebtTotal", + "optionality": 2 + }, + { + "name": "DebtMaximum", + "optionality": 2 + }, + { + "name": "CoverAvailable", + "optionality": 2 + }, + { + "name": "CoverRateMinimum", + "optionality": 2 + }, + { + "name": "CoverRateLiquidation", + "optionality": 2 + } + ], + "MPToken": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "MPTokenIssuanceID", + "optionality": 0 + }, + { + "name": "MPTAmount", + "optionality": 2 + }, + { + "name": "LockedAmount", + "optionality": 1 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "MPTokenIssuance": [ + { + "name": "Issuer", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "TransferFee", + "optionality": 2 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "AssetScale", + "optionality": 2 + }, + { + "name": "MaximumAmount", + "optionality": 1 + }, + { + "name": "OutstandingAmount", + "optionality": 0 + }, + { + "name": "LockedAmount", + "optionality": 1 + }, + { + "name": "MPTokenMetadata", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "DomainID", + "optionality": 1 + }, + { + "name": "MutableFlags", + "optionality": 2 + }, + { + "name": "ReferenceHolding", + "optionality": 1 + } + ], + "NFTokenOffer": [ + { + "name": "Owner", + "optionality": 0 + }, + { + "name": "NFTokenID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "NFTokenOfferNode", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 1 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "NFTokenPage": [ + { + "name": "PreviousPageMin", + "optionality": 1 + }, + { + "name": "NextPageMin", + "optionality": 1 + }, + { + "name": "NFTokens", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "NegativeUNL": [ + { + "name": "DisabledValidators", + "optionality": 1 + }, + { + "name": "ValidatorToDisable", + "optionality": 1 + }, + { + "name": "ValidatorToReEnable", + "optionality": 1 + }, + { + "name": "PreviousTxnID", + "optionality": 1 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 1 + } + ], + "Offer": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "TakerPays", + "optionality": 0 + }, + { + "name": "TakerGets", + "optionality": 0 + }, + { + "name": "BookDirectory", + "optionality": 0 + }, + { + "name": "BookNode", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + }, + { + "name": "AdditionalBooks", + "optionality": 1 + } + ], + "Oracle": [ + { + "name": "Owner", + "optionality": 0 + }, + { + "name": "OracleDocumentID", + "optionality": 1 + }, + { + "name": "Provider", + "optionality": 0 + }, + { + "name": "PriceDataSeries", + "optionality": 0 + }, + { + "name": "AssetClass", + "optionality": 0 + }, + { + "name": "LastUpdateTime", + "optionality": 0 + }, + { + "name": "URI", + "optionality": 1 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "PayChannel": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 1 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Balance", + "optionality": 0 + }, + { + "name": "PublicKey", + "optionality": 0 + }, + { + "name": "SettleDelay", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "CancelAfter", + "optionality": 1 + }, + { + "name": "SourceTag", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "DestinationNode", + "optionality": 1 + } + ], + "PermissionedDomain": [ + { + "name": "Owner", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "AcceptedCredentials", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "RippleState": [ + { + "name": "Balance", + "optionality": 0 + }, + { + "name": "LowLimit", + "optionality": 0 + }, + { + "name": "HighLimit", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "LowNode", + "optionality": 1 + }, + { + "name": "LowQualityIn", + "optionality": 1 + }, + { + "name": "LowQualityOut", + "optionality": 1 + }, + { + "name": "HighNode", + "optionality": 1 + }, + { + "name": "HighQualityIn", + "optionality": 1 + }, + { + "name": "HighQualityOut", + "optionality": 1 + } + ], + "SignerList": [ + { + "name": "Owner", + "optionality": 1 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "SignerQuorum", + "optionality": 0 + }, + { + "name": "SignerEntries", + "optionality": 0 + }, + { + "name": "SignerListID", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "Ticket": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "TicketSequence", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "Vault": [ + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "Owner", + "optionality": 0 + }, + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Data", + "optionality": 1 + }, + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "AssetsTotal", + "optionality": 2 + }, + { + "name": "AssetsAvailable", + "optionality": 2 + }, + { + "name": "AssetsMaximum", + "optionality": 2 + }, + { + "name": "LossUnrealized", + "optionality": 2 + }, + { + "name": "ShareMPTID", + "optionality": 0 + }, + { + "name": "WithdrawalPolicy", + "optionality": 0 + }, + { + "name": "Scale", + "optionality": 2 + } + ], + "XChainOwnedClaimID": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "XChainClaimID", + "optionality": 0 + }, + { + "name": "OtherChainSource", + "optionality": 0 + }, + { + "name": "XChainClaimAttestations", + "optionality": 0 + }, + { + "name": "SignatureReward", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "XChainOwnedCreateAccountClaimID": [ + { + "name": "Account", + "optionality": 0 + }, + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "XChainAccountCreateCount", + "optionality": 0 + }, + { + "name": "XChainCreateAccountAttestations", + "optionality": 0 + }, + { + "name": "OwnerNode", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 0 + }, + { + "name": "PreviousTxnLgrSeq", + "optionality": 0 + } + ], + "common": [ + { + "name": "LedgerIndex", + "optionality": 1 + }, + { + "name": "LedgerEntryType", + "optionality": 0 + }, + { + "name": "Flags", + "optionality": 0 + } + ] + }, + "LEDGER_ENTRY_TYPES": { + "AMM": 121, + "AccountRoot": 97, + "Amendments": 102, + "Bridge": 105, + "Check": 67, + "Credential": 129, + "DID": 73, + "Delegate": 131, + "DepositPreauth": 112, + "DirectoryNode": 100, + "Escrow": 117, + "FeeSettings": 115, + "Invalid": -1, + "LedgerHashes": 104, + "Loan": 137, "LoanBroker": 136, "MPToken": 127, "MPTokenIssuance": 126, @@ -3649,6 +5098,1488 @@ "XChainOwnedClaimID": 113, "XChainOwnedCreateAccountClaimID": 116 }, + "TRANSACTION_FLAGS": { + "AMMClawback": { + "tfClawTwoAssets": 1 + }, + "AMMDeposit": { + "tfLPToken": 65536, + "tfLimitLPToken": 4194304, + "tfOneAssetLPToken": 2097152, + "tfSingleAsset": 524288, + "tfTwoAsset": 1048576, + "tfTwoAssetIfEmpty": 8388608 + }, + "AMMWithdraw": { + "tfLPToken": 65536, + "tfLimitLPToken": 4194304, + "tfOneAssetLPToken": 2097152, + "tfOneAssetWithdrawAll": 262144, + "tfSingleAsset": 524288, + "tfTwoAsset": 1048576, + "tfWithdrawAll": 131072 + }, + "AccountSet": { + "tfAllowXRP": 2097152, + "tfDisallowXRP": 1048576, + "tfOptionalAuth": 524288, + "tfOptionalDestTag": 131072, + "tfRequireAuth": 262144, + "tfRequireDestTag": 65536 + }, + "Batch": { + "tfAllOrNothing": 65536, + "tfIndependent": 524288, + "tfOnlyOne": 131072, + "tfUntilFailure": 262144 + }, + "EnableAmendment": { + "tfGotMajority": 65536, + "tfLostMajority": 131072 + }, + "LoanManage": { + "tfLoanDefault": 65536, + "tfLoanImpair": 131072, + "tfLoanUnimpair": 262144 + }, + "LoanPay": { + "tfLoanFullPayment": 131072, + "tfLoanLatePayment": 262144, + "tfLoanOverpayment": 65536 + }, + "LoanSet": { + "tfLoanOverpayment": 65536 + }, + "MPTokenAuthorize": { + "tfMPTUnauthorize": 1 + }, + "MPTokenIssuanceCreate": { + "tfMPTCanClawback": 64, + "tfMPTCanEscrow": 8, + "tfMPTCanLock": 2, + "tfMPTCanTrade": 16, + "tfMPTCanTransfer": 32, + "tfMPTRequireAuth": 4 + }, + "MPTokenIssuanceSet": { + "tfMPTLock": 1, + "tfMPTUnlock": 2 + }, + "NFTokenCreateOffer": { + "tfSellNFToken": 1 + }, + "NFTokenMint": { + "tfBurnable": 1, + "tfMutable": 16, + "tfOnlyXRP": 2, + "tfTransferable": 8 + }, + "OfferCreate": { + "tfFillOrKill": 262144, + "tfHybrid": 1048576, + "tfImmediateOrCancel": 131072, + "tfPassive": 65536, + "tfSell": 524288 + }, + "Payment": { + "tfLimitQuality": 262144, + "tfNoRippleDirect": 65536, + "tfPartialPayment": 131072 + }, + "PaymentChannelClaim": { + "tfClose": 131072, + "tfRenew": 65536 + }, + "TrustSet": { + "tfClearDeepFreeze": 8388608, + "tfClearFreeze": 2097152, + "tfClearNoRipple": 262144, + "tfSetDeepFreeze": 4194304, + "tfSetFreeze": 1048576, + "tfSetNoRipple": 131072, + "tfSetfAuth": 65536 + }, + "VaultCreate": { + "tfVaultPrivate": 65536, + "tfVaultShareNonTransferable": 131072 + }, + "XChainModifyBridge": { + "tfClearAccountCreateAmount": 65536 + }, + "universal": { + "tfFullyCanonicalSig": 2147483648, + "tfInnerBatchTxn": 1073741824 + } + }, + "TRANSACTION_FORMATS": { + "AMMBid": [ + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "Asset2", + "optionality": 0 + }, + { + "name": "BidMin", + "optionality": 1 + }, + { + "name": "BidMax", + "optionality": 1 + }, + { + "name": "AuthAccounts", + "optionality": 1 + } + ], + "AMMClawback": [ + { + "name": "Holder", + "optionality": 0 + }, + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "Asset2", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 1 + } + ], + "AMMCreate": [ + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Amount2", + "optionality": 0 + }, + { + "name": "TradingFee", + "optionality": 0 + } + ], + "AMMDelete": [ + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "Asset2", + "optionality": 0 + } + ], + "AMMDeposit": [ + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "Asset2", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 1 + }, + { + "name": "Amount2", + "optionality": 1 + }, + { + "name": "EPrice", + "optionality": 1 + }, + { + "name": "LPTokenOut", + "optionality": 1 + }, + { + "name": "TradingFee", + "optionality": 1 + } + ], + "AMMVote": [ + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "Asset2", + "optionality": 0 + }, + { + "name": "TradingFee", + "optionality": 0 + } + ], + "AMMWithdraw": [ + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "Asset2", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 1 + }, + { + "name": "Amount2", + "optionality": 1 + }, + { + "name": "EPrice", + "optionality": 1 + }, + { + "name": "LPTokenIn", + "optionality": 1 + } + ], + "AccountDelete": [ + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "DestinationTag", + "optionality": 1 + }, + { + "name": "CredentialIDs", + "optionality": 1 + } + ], + "AccountSet": [ + { + "name": "EmailHash", + "optionality": 1 + }, + { + "name": "WalletLocator", + "optionality": 1 + }, + { + "name": "WalletSize", + "optionality": 1 + }, + { + "name": "MessageKey", + "optionality": 1 + }, + { + "name": "Domain", + "optionality": 1 + }, + { + "name": "TransferRate", + "optionality": 1 + }, + { + "name": "SetFlag", + "optionality": 1 + }, + { + "name": "ClearFlag", + "optionality": 1 + }, + { + "name": "TickSize", + "optionality": 1 + }, + { + "name": "NFTokenMinter", + "optionality": 1 + } + ], + "Batch": [ + { + "name": "RawTransactions", + "optionality": 0 + }, + { + "name": "BatchSigners", + "optionality": 1 + } + ], + "CheckCancel": [ + { + "name": "CheckID", + "optionality": 0 + } + ], + "CheckCash": [ + { + "name": "CheckID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 1 + }, + { + "name": "DeliverMin", + "optionality": 1 + } + ], + "CheckCreate": [ + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "SendMax", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + }, + { + "name": "InvoiceID", + "optionality": 1 + } + ], + "Clawback": [ + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Holder", + "optionality": 1 + } + ], + "CredentialAccept": [ + { + "name": "Issuer", + "optionality": 0 + }, + { + "name": "CredentialType", + "optionality": 0 + } + ], + "CredentialCreate": [ + { + "name": "Subject", + "optionality": 0 + }, + { + "name": "CredentialType", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "URI", + "optionality": 1 + } + ], + "CredentialDelete": [ + { + "name": "Subject", + "optionality": 1 + }, + { + "name": "Issuer", + "optionality": 1 + }, + { + "name": "CredentialType", + "optionality": 0 + } + ], + "DIDDelete": [], + "DIDSet": [ + { + "name": "DIDDocument", + "optionality": 1 + }, + { + "name": "URI", + "optionality": 1 + }, + { + "name": "Data", + "optionality": 1 + } + ], + "DelegateSet": [ + { + "name": "Authorize", + "optionality": 0 + }, + { + "name": "Permissions", + "optionality": 0 + } + ], + "DepositPreauth": [ + { + "name": "Authorize", + "optionality": 1 + }, + { + "name": "Unauthorize", + "optionality": 1 + }, + { + "name": "AuthorizeCredentials", + "optionality": 1 + }, + { + "name": "UnauthorizeCredentials", + "optionality": 1 + } + ], + "EnableAmendment": [ + { + "name": "LedgerSequence", + "optionality": 0 + }, + { + "name": "Amendment", + "optionality": 0 + } + ], + "EscrowCancel": [ + { + "name": "Owner", + "optionality": 0 + }, + { + "name": "OfferSequence", + "optionality": 0 + } + ], + "EscrowCreate": [ + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Condition", + "optionality": 1 + }, + { + "name": "CancelAfter", + "optionality": 1 + }, + { + "name": "FinishAfter", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + } + ], + "EscrowFinish": [ + { + "name": "Owner", + "optionality": 0 + }, + { + "name": "OfferSequence", + "optionality": 0 + }, + { + "name": "Fulfillment", + "optionality": 1 + }, + { + "name": "Condition", + "optionality": 1 + }, + { + "name": "CredentialIDs", + "optionality": 1 + } + ], + "LedgerStateFix": [ + { + "name": "LedgerFixType", + "optionality": 0 + }, + { + "name": "Owner", + "optionality": 1 + }, + { + "name": "BookDirectory", + "optionality": 1 + } + ], + "LoanBrokerCoverClawback": [ + { + "name": "LoanBrokerID", + "optionality": 1 + }, + { + "name": "Amount", + "optionality": 1 + } + ], + "LoanBrokerCoverDeposit": [ + { + "name": "LoanBrokerID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + } + ], + "LoanBrokerCoverWithdraw": [ + { + "name": "LoanBrokerID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + } + ], + "LoanBrokerDelete": [ + { + "name": "LoanBrokerID", + "optionality": 0 + } + ], + "LoanBrokerSet": [ + { + "name": "VaultID", + "optionality": 0 + }, + { + "name": "LoanBrokerID", + "optionality": 1 + }, + { + "name": "Data", + "optionality": 1 + }, + { + "name": "ManagementFeeRate", + "optionality": 1 + }, + { + "name": "DebtMaximum", + "optionality": 1 + }, + { + "name": "CoverRateMinimum", + "optionality": 1 + }, + { + "name": "CoverRateLiquidation", + "optionality": 1 + } + ], + "LoanDelete": [ + { + "name": "LoanID", + "optionality": 0 + } + ], + "LoanManage": [ + { + "name": "LoanID", + "optionality": 0 + } + ], + "LoanPay": [ + { + "name": "LoanID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + } + ], + "LoanSet": [ + { + "name": "LoanBrokerID", + "optionality": 0 + }, + { + "name": "Data", + "optionality": 1 + }, + { + "name": "Counterparty", + "optionality": 1 + }, + { + "name": "CounterpartySignature", + "optionality": 1 + }, + { + "name": "LoanOriginationFee", + "optionality": 1 + }, + { + "name": "LoanServiceFee", + "optionality": 1 + }, + { + "name": "LatePaymentFee", + "optionality": 1 + }, + { + "name": "ClosePaymentFee", + "optionality": 1 + }, + { + "name": "OverpaymentFee", + "optionality": 1 + }, + { + "name": "InterestRate", + "optionality": 1 + }, + { + "name": "LateInterestRate", + "optionality": 1 + }, + { + "name": "CloseInterestRate", + "optionality": 1 + }, + { + "name": "OverpaymentInterestRate", + "optionality": 1 + }, + { + "name": "PrincipalRequested", + "optionality": 0 + }, + { + "name": "PaymentTotal", + "optionality": 1 + }, + { + "name": "PaymentInterval", + "optionality": 1 + }, + { + "name": "GracePeriod", + "optionality": 1 + } + ], + "MPTokenAuthorize": [ + { + "name": "MPTokenIssuanceID", + "optionality": 0 + }, + { + "name": "Holder", + "optionality": 1 + } + ], + "MPTokenIssuanceCreate": [ + { + "name": "AssetScale", + "optionality": 1 + }, + { + "name": "TransferFee", + "optionality": 1 + }, + { + "name": "MaximumAmount", + "optionality": 1 + }, + { + "name": "MPTokenMetadata", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + }, + { + "name": "MutableFlags", + "optionality": 1 + } + ], + "MPTokenIssuanceDestroy": [ + { + "name": "MPTokenIssuanceID", + "optionality": 0 + } + ], + "MPTokenIssuanceSet": [ + { + "name": "MPTokenIssuanceID", + "optionality": 0 + }, + { + "name": "Holder", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + }, + { + "name": "MPTokenMetadata", + "optionality": 1 + }, + { + "name": "TransferFee", + "optionality": 1 + }, + { + "name": "MutableFlags", + "optionality": 1 + } + ], + "NFTokenAcceptOffer": [ + { + "name": "NFTokenBuyOffer", + "optionality": 1 + }, + { + "name": "NFTokenSellOffer", + "optionality": 1 + }, + { + "name": "NFTokenBrokerFee", + "optionality": 1 + } + ], + "NFTokenBurn": [ + { + "name": "NFTokenID", + "optionality": 0 + }, + { + "name": "Owner", + "optionality": 1 + } + ], + "NFTokenCancelOffer": [ + { + "name": "NFTokenOffers", + "optionality": 0 + } + ], + "NFTokenCreateOffer": [ + { + "name": "NFTokenID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 1 + }, + { + "name": "Owner", + "optionality": 1 + }, + { + "name": "Expiration", + "optionality": 1 + } + ], + "NFTokenMint": [ + { + "name": "NFTokenTaxon", + "optionality": 0 + }, + { + "name": "TransferFee", + "optionality": 1 + }, + { + "name": "Issuer", + "optionality": 1 + }, + { + "name": "URI", + "optionality": 1 + }, + { + "name": "Amount", + "optionality": 1 + }, + { + "name": "Destination", + "optionality": 1 + }, + { + "name": "Expiration", + "optionality": 1 + } + ], + "NFTokenModify": [ + { + "name": "NFTokenID", + "optionality": 0 + }, + { + "name": "Owner", + "optionality": 1 + }, + { + "name": "URI", + "optionality": 1 + } + ], + "OfferCancel": [ + { + "name": "OfferSequence", + "optionality": 0 + } + ], + "OfferCreate": [ + { + "name": "TakerPays", + "optionality": 0 + }, + { + "name": "TakerGets", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + }, + { + "name": "OfferSequence", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + } + ], + "OracleDelete": [ + { + "name": "OracleDocumentID", + "optionality": 0 + } + ], + "OracleSet": [ + { + "name": "OracleDocumentID", + "optionality": 0 + }, + { + "name": "Provider", + "optionality": 1 + }, + { + "name": "URI", + "optionality": 1 + }, + { + "name": "AssetClass", + "optionality": 1 + }, + { + "name": "LastUpdateTime", + "optionality": 0 + }, + { + "name": "PriceDataSeries", + "optionality": 0 + } + ], + "Payment": [ + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "SendMax", + "optionality": 1 + }, + { + "name": "Paths", + "optionality": 2 + }, + { + "name": "InvoiceID", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + }, + { + "name": "DeliverMin", + "optionality": 1 + }, + { + "name": "CredentialIDs", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + } + ], + "PaymentChannelClaim": [ + { + "name": "Channel", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 1 + }, + { + "name": "Balance", + "optionality": 1 + }, + { + "name": "Signature", + "optionality": 1 + }, + { + "name": "PublicKey", + "optionality": 1 + }, + { + "name": "CredentialIDs", + "optionality": 1 + } + ], + "PaymentChannelCreate": [ + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "SettleDelay", + "optionality": 0 + }, + { + "name": "PublicKey", + "optionality": 0 + }, + { + "name": "CancelAfter", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + } + ], + "PaymentChannelFund": [ + { + "name": "Channel", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Expiration", + "optionality": 1 + } + ], + "PermissionedDomainDelete": [ + { + "name": "DomainID", + "optionality": 0 + } + ], + "PermissionedDomainSet": [ + { + "name": "DomainID", + "optionality": 1 + }, + { + "name": "AcceptedCredentials", + "optionality": 0 + } + ], + "SetFee": [ + { + "name": "LedgerSequence", + "optionality": 1 + }, + { + "name": "BaseFee", + "optionality": 1 + }, + { + "name": "ReferenceFeeUnits", + "optionality": 1 + }, + { + "name": "ReserveBase", + "optionality": 1 + }, + { + "name": "ReserveIncrement", + "optionality": 1 + }, + { + "name": "BaseFeeDrops", + "optionality": 1 + }, + { + "name": "ReserveBaseDrops", + "optionality": 1 + }, + { + "name": "ReserveIncrementDrops", + "optionality": 1 + } + ], + "SetRegularKey": [ + { + "name": "RegularKey", + "optionality": 1 + } + ], + "SignerListSet": [ + { + "name": "SignerQuorum", + "optionality": 0 + }, + { + "name": "SignerEntries", + "optionality": 1 + } + ], + "TicketCreate": [ + { + "name": "TicketCount", + "optionality": 0 + } + ], + "TrustSet": [ + { + "name": "LimitAmount", + "optionality": 1 + }, + { + "name": "QualityIn", + "optionality": 1 + }, + { + "name": "QualityOut", + "optionality": 1 + } + ], + "UNLModify": [ + { + "name": "UNLModifyDisabling", + "optionality": 0 + }, + { + "name": "LedgerSequence", + "optionality": 0 + }, + { + "name": "UNLModifyValidator", + "optionality": 0 + } + ], + "VaultClawback": [ + { + "name": "VaultID", + "optionality": 0 + }, + { + "name": "Holder", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 1 + } + ], + "VaultCreate": [ + { + "name": "Asset", + "optionality": 0 + }, + { + "name": "AssetsMaximum", + "optionality": 1 + }, + { + "name": "MPTokenMetadata", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + }, + { + "name": "WithdrawalPolicy", + "optionality": 1 + }, + { + "name": "Data", + "optionality": 1 + }, + { + "name": "Scale", + "optionality": 1 + } + ], + "VaultDelete": [ + { + "name": "VaultID", + "optionality": 0 + } + ], + "VaultDeposit": [ + { + "name": "VaultID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + } + ], + "VaultSet": [ + { + "name": "VaultID", + "optionality": 0 + }, + { + "name": "AssetsMaximum", + "optionality": 1 + }, + { + "name": "DomainID", + "optionality": 1 + }, + { + "name": "Data", + "optionality": 1 + } + ], + "VaultWithdraw": [ + { + "name": "VaultID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 1 + }, + { + "name": "DestinationTag", + "optionality": 1 + } + ], + "XChainAccountCreateCommit": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "SignatureReward", + "optionality": 0 + } + ], + "XChainAddAccountCreateAttestation": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "AttestationSignerAccount", + "optionality": 0 + }, + { + "name": "PublicKey", + "optionality": 0 + }, + { + "name": "Signature", + "optionality": 0 + }, + { + "name": "OtherChainSource", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "AttestationRewardAccount", + "optionality": 0 + }, + { + "name": "WasLockingChainSend", + "optionality": 0 + }, + { + "name": "XChainAccountCreateCount", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "SignatureReward", + "optionality": 0 + } + ], + "XChainAddClaimAttestation": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "AttestationSignerAccount", + "optionality": 0 + }, + { + "name": "PublicKey", + "optionality": 0 + }, + { + "name": "Signature", + "optionality": 0 + }, + { + "name": "OtherChainSource", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "AttestationRewardAccount", + "optionality": 0 + }, + { + "name": "WasLockingChainSend", + "optionality": 0 + }, + { + "name": "XChainClaimID", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 1 + } + ], + "XChainClaim": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "XChainClaimID", + "optionality": 0 + }, + { + "name": "Destination", + "optionality": 0 + }, + { + "name": "DestinationTag", + "optionality": 1 + }, + { + "name": "Amount", + "optionality": 0 + } + ], + "XChainCommit": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "XChainClaimID", + "optionality": 0 + }, + { + "name": "Amount", + "optionality": 0 + }, + { + "name": "OtherChainDestination", + "optionality": 1 + } + ], + "XChainCreateBridge": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "SignatureReward", + "optionality": 0 + }, + { + "name": "MinAccountCreateAmount", + "optionality": 1 + } + ], + "XChainCreateClaimID": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "SignatureReward", + "optionality": 0 + }, + { + "name": "OtherChainSource", + "optionality": 0 + } + ], + "XChainModifyBridge": [ + { + "name": "XChainBridge", + "optionality": 0 + }, + { + "name": "SignatureReward", + "optionality": 1 + }, + { + "name": "MinAccountCreateAmount", + "optionality": 1 + } + ], + "common": [ + { + "name": "TransactionType", + "optionality": 0 + }, + { + "name": "Flags", + "optionality": 1 + }, + { + "name": "SourceTag", + "optionality": 1 + }, + { + "name": "Account", + "optionality": 0 + }, + { + "name": "Sequence", + "optionality": 0 + }, + { + "name": "PreviousTxnID", + "optionality": 1 + }, + { + "name": "LastLedgerSequence", + "optionality": 1 + }, + { + "name": "AccountTxnID", + "optionality": 1 + }, + { + "name": "Fee", + "optionality": 0 + }, + { + "name": "OperationLimit", + "optionality": 1 + }, + { + "name": "Memos", + "optionality": 1 + }, + { + "name": "SigningPubKey", + "optionality": 0 + }, + { + "name": "TicketSequence", + "optionality": 1 + }, + { + "name": "TxnSignature", + "optionality": 1 + }, + { + "name": "Signers", + "optionality": 1 + }, + { + "name": "NetworkID", + "optionality": 1 + }, + { + "name": "Delegate", + "optionality": 1 + } + ] + }, "TRANSACTION_RESULTS": { "tecAMM_ACCOUNT": 168, "tecAMM_BALANCE": 163, @@ -3659,6 +6590,7 @@ "tecARRAY_EMPTY": 190, "tecARRAY_TOO_LARGE": 191, "tecBAD_CREDENTIALS": 193, + "tecBAD_PROOF": 199, "tecCANT_ACCEPT_OWN_NFTOKEN_OFFER": 158, "tecCLAIM": 100, "tecCRYPTOCONDITION_ERROR": 146, @@ -3670,7 +6602,6 @@ "tecFAILED_PROCESSING": 105, "tecFROZEN": 137, "tecHAS_OBLIGATIONS": 151, - "tecHOOK_REJECTED": 153, "tecINCOMPLETE": 169, "tecINSUFFICIENT_FUNDS": 159, "tecINSUFFICIENT_PAYMENT": 161, @@ -3690,7 +6621,6 @@ "tecNFTOKEN_OFFER_TYPE_MISMATCH": 157, "tecNO_ALTERNATIVE_KEY": 130, "tecNO_AUTH": 134, - "tecNO_DELEGATE_PERMISSION": 198, "tecNO_DST": 124, "tecNO_DST_INSUF_XRP": 125, "tecNO_ENTRY": 140, @@ -3734,7 +6664,6 @@ "tecXCHAIN_SELF_COMMIT": 184, "tecXCHAIN_SENDING_ACCOUNT_MISMATCH": 179, "tecXCHAIN_WRONG_CHAIN": 176, - "tefALREADY": -198, "tefBAD_ADD_AUTH": -197, "tefBAD_AUTH": -196, @@ -3757,7 +6686,6 @@ "tefPAST_SEQ": -190, "tefTOO_BIG": -181, "tefWRONG_PRIOR": -189, - "telBAD_DOMAIN": -398, "telBAD_PATH_COUNT": -397, "telBAD_PUBLIC_KEY": -396, @@ -3775,16 +6703,17 @@ "telNO_DST_PARTIAL": -393, "telREQUIRES_NETWORK_ID": -385, "telWRONG_NETWORK": -386, - "temARRAY_EMPTY": -253, "temARRAY_TOO_LARGE": -252, "temBAD_AMM_TOKENS": -261, "temBAD_AMOUNT": -298, + "temBAD_CIPHERTEXT": -248, "temBAD_CURRENCY": -297, "temBAD_EXPIRATION": -296, "temBAD_FEE": -295, "temBAD_ISSUER": -294, "temBAD_LIMIT": -293, + "temBAD_MPT": -249, "temBAD_NFTOKEN_TRANSFER_FEE": -262, "temBAD_OFFER": -292, "temBAD_PATH": -291, @@ -3826,11 +6755,11 @@ "temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT": -255, "temXCHAIN_BRIDGE_NONDOOR_OWNER": -257, "temXCHAIN_EQUAL_DOOR_ACCOUNTS": -260, - "terADDRESS_COLLISION": -86, "terFUNDS_SPENT": -98, "terINSUF_FEE_B": -97, "terLAST": -91, + "terLOCKED": -84, "terNO_ACCOUNT": -96, "terNO_AMM": -87, "terNO_AUTH": -95, @@ -3842,7 +6771,6 @@ "terPRE_TICKET": -88, "terQUEUED": -89, "terRETRY": -99, - "tesSUCCESS": 0 }, "TRANSACTION_TYPES": { @@ -3938,6 +6866,8 @@ "Hash160": 17, "Hash192": 21, "Hash256": 5, + "Hash384": 22, + "Hash512": 23, "Int32": 10, "Int64": 11, "Issue": 24, @@ -3951,8 +6881,6 @@ "Transaction": 10001, "UInt16": 1, "UInt32": 2, - "UInt384": 22, - "UInt512": 23, "UInt64": 3, "UInt8": 16, "UInt96": 20, @@ -3960,5 +6888,6 @@ "Validation": 10003, "Vector256": 19, "XChainBridge": 25 - } + }, + "hash": "C685734F5FEB756693B4BB978BBB3A158A65652E71EEB2977068B0D680689213" } diff --git a/binary-codec/definitions/definitions_test.go b/binary-codec/definitions/definitions_test.go index aaf3dcf45..86f0a3177 100644 --- a/binary-codec/definitions/definitions_test.go +++ b/binary-codec/definitions/definitions_test.go @@ -13,7 +13,7 @@ func TestLoadDefinitions(t *testing.T) { require.Equal(t, int32(97), definitions.LedgerEntryTypes["AccountRoot"]) require.Equal(t, int32(-399), definitions.TransactionResults["telLOCAL_ERROR"]) require.Equal(t, int32(1), definitions.TransactionTypes["EscrowCreate"]) - require.Equal(t, &FieldInfo{Nth: 0, IsVLEncoded: false, IsSerialized: false, IsSigningField: false, Type: "Unknown"}, definitions.Fields["Generic"].FieldInfo) + require.Equal(t, &FieldInfo{Nth: 0, IsVLEncoded: false, IsSerialized: true, IsSigningField: true, Type: "Unknown"}, definitions.Fields["Generic"].FieldInfo) require.Equal(t, &FieldInfo{Nth: 28, IsVLEncoded: false, IsSerialized: true, IsSigningField: true, Type: "Hash256"}, definitions.Fields["NFTokenBuyOffer"].FieldInfo) require.Equal(t, &FieldInfo{Nth: 16, IsVLEncoded: false, IsSerialized: true, IsSigningField: true, Type: "UInt8"}, definitions.Fields["TickSize"].FieldInfo) require.Equal(t, &FieldHeader{TypeCode: 2, FieldCode: 4}, definitions.Fields["Sequence"].FieldHeader) diff --git a/binary-codec/definitions/field_instance.go b/binary-codec/definitions/field_instance.go index 762fb299e..915590870 100644 --- a/binary-codec/definitions/field_instance.go +++ b/binary-codec/definitions/field_instance.go @@ -16,7 +16,6 @@ type FieldInfo struct { IsVLEncoded bool IsSerialized bool IsSigningField bool - IsBaseTen bool Type string } diff --git a/binary-codec/types/st_object.go b/binary-codec/types/st_object.go index cb4fb97e4..ed99f8fdb 100644 --- a/binary-codec/types/st_object.go +++ b/binary-codec/types/st_object.go @@ -44,8 +44,8 @@ func (t *STObject) FromJSON(json any) ([]byte, error) { st := GetSerializedType(v.Type) var b []byte - if v.Type == "UInt64" && v.IsBaseTen { - b, err = (&UInt64{}).fromJSON(fimap[v], uint64BaseTen) + if v.Type == "UInt64" { + b, err = (&UInt64{}).fromJSON(fimap[v], uint64JSONBaseForField(v.FieldName)) } else { b, err = st.FromJSON(fimap[v]) } @@ -94,8 +94,8 @@ func (t *STObject) ToJSON(p interfaces.BinaryParser, _ ...int) (any, error) { } } else { - if fi.Type == "UInt64" && fi.IsBaseTen { - res, err = st.ToJSON(p, uint64BaseTen) + if fi.Type == "UInt64" { + res, err = st.ToJSON(p, uint64JSONBaseForField(fi.FieldName)) } else { res, err = st.ToJSON(p) } diff --git a/binary-codec/types/uint64.go b/binary-codec/types/uint64.go index 68fec04eb..4a699ba4a 100644 --- a/binary-codec/types/uint64.go +++ b/binary-codec/types/uint64.go @@ -11,7 +11,21 @@ import ( "github.com/Peersyst/xrpl-go/pkg/typecheck" ) -const uint64BaseTen = 10 +const ( + uint64JSONBaseDecimal int = 10 + uint64JSONBaseHex int = 16 +) + +// uint64JSONBaseForField mirrors rippled's kSmdBaseTen metadata, which is not +// included in the server definitions copied from xrpl.js. +func uint64JSONBaseForField(fieldName string) int { + switch fieldName { + case "MaximumAmount", "OutstandingAmount", "MPTAmount", "LockedAmount", "ConfidentialOutstandingAmount": + return uint64JSONBaseDecimal + default: + return uint64JSONBaseHex + } +} // UInt64 represents a 64-bit unsigned integer serialized from a hex JSON string. type UInt64 struct{} @@ -28,7 +42,7 @@ var ErrInvalidUInt64String = errors.New("invalid UInt64 string, value should be // Returns ErrInvalidUInt64String when the input is not a string, contains non-hex // characters, or exceeds 16 characters. func (u *UInt64) FromJSON(value any) ([]byte, error) { - return u.fromJSON(value, 16) + return u.fromJSON(value, uint64JSONBaseHex) } func (u *UInt64) fromJSON(value any, base int) ([]byte, error) { @@ -37,7 +51,7 @@ func (u *UInt64) fromJSON(value any, base int) ([]byte, error) { return nil, ErrInvalidUInt64String } - if base == 16 && (len(strValue) > 16 || !typecheck.IsHex(strValue)) { + if base == uint64JSONBaseHex && (len(strValue) > 16 || !typecheck.IsHex(strValue)) { return nil, ErrInvalidUInt64String } @@ -63,8 +77,8 @@ func (u *UInt64) ToJSON(p interfaces.BinaryParser, opts ...int) (any, error) { if err != nil { return nil, err } - if len(opts) > 0 && opts[0] == uint64BaseTen { - return strconv.FormatUint(binary.BigEndian.Uint64(b), uint64BaseTen), nil + if len(opts) > 0 && opts[0] == uint64JSONBaseDecimal { + return strconv.FormatUint(binary.BigEndian.Uint64(b), uint64JSONBaseDecimal), nil } return hexutil.EncodeToUpperHex(b), nil } diff --git a/binary-codec/types/uint64_test.go b/binary-codec/types/uint64_test.go index 851b40445..c8a206d7c 100644 --- a/binary-codec/types/uint64_test.go +++ b/binary-codec/types/uint64_test.go @@ -144,7 +144,7 @@ func TestUInt64FromBaseTenJSON(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - actual, err := (&UInt64{}).fromJSON(tt.input, uint64BaseTen) + actual, err := (&UInt64{}).fromJSON(tt.input, uint64JSONBaseDecimal) if tt.expectedErr != nil { require.ErrorIs(t, err, tt.expectedErr) return @@ -218,7 +218,7 @@ func TestUint64_ToJson(t *testing.T) { input: []byte{0, 0, 0, 0, 0, 0, 3, 232}, expected: "1000", expectedErr: nil, - opts: []int{uint64BaseTen}, + opts: []int{uint64JSONBaseDecimal}, malleate: func(t *testing.T) interfaces.BinaryParser { return serdes.NewBinaryParser([]byte{0, 0, 0, 0, 0, 0, 3, 232}, defs) }, diff --git a/binary-codec/types/uint8.go b/binary-codec/types/uint8.go index 3427653e9..e40e60cbe 100644 --- a/binary-codec/types/uint8.go +++ b/binary-codec/types/uint8.go @@ -54,7 +54,11 @@ func (u *UInt8) FromJSON(value any) ([]byte, error) { return nil, ErrUInt8OutOfRange } - // Check range before casting + // Transaction result definitions also contain negative tel/tem/tef/ter + // engine codes. Those transactions are not applied to a ledger, so the + // codes are returned through RPC JSON and never serialized in the UInt8 + // TransactionResult metadata field. Do not wrap them modulo 256 here; + // only ledger metadata results such as tes and tec are valid UInt8 values. if err := u.checkRange(int64Value); err != nil { return nil, err } diff --git a/binary-codec/types/uint8_test.go b/binary-codec/types/uint8_test.go index 41fa60b46..9c91fa181 100644 --- a/binary-codec/types/uint8_test.go +++ b/binary-codec/types/uint8_test.go @@ -37,11 +37,23 @@ func TestUint8_FromJson(t *testing.T) { expectedErr: nil, }, { - name: "Valid uint8 from string", + name: "Valid uint8 from successful transaction result", input: "tesSUCCESS", expected: []byte{0}, expectedErr: nil, }, + { + name: "Valid uint8 from claim-cost transaction result", + input: "tecBAD_PROOF", + expected: []byte{199}, + expectedErr: nil, + }, + { + name: "Reject engine-only negative transaction result", + input: "temBAD_CIPHERTEXT", + expected: nil, + expectedErr: ErrUInt8OutOfRange, + }, { name: "Invalid uint8 from string", input: "InvalidUint8", From cdd1a0965159179ce683d13b3c22751a2f9fc8e9 Mon Sep 17 00:00:00 2001 From: Kevin Pita Date: Wed, 29 Jul 2026 14:35:46 +0200 Subject: [PATCH 3/3] test(binary-codec): remove redundant MPT wire fixtures --- binary-codec/codec_test.go | 51 +++++++ .../confidential_mpt_wire_fields_test.go | 144 ------------------ .../definitions/confidential_mpt_test.go | 102 ------------- .../confidential-mpt-wire-fields.json | 31 ---- 4 files changed, 51 insertions(+), 277 deletions(-) delete mode 100644 binary-codec/confidential_mpt_wire_fields_test.go delete mode 100644 binary-codec/definitions/confidential_mpt_test.go delete mode 100644 binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json diff --git a/binary-codec/codec_test.go b/binary-codec/codec_test.go index 5e014549a..32ec70edc 100644 --- a/binary-codec/codec_test.go +++ b/binary-codec/codec_test.go @@ -1,6 +1,7 @@ package binarycodec import ( + "encoding/json" "errors" "testing" @@ -344,6 +345,56 @@ func TestEncode(t *testing.T) { } } +func TestLiveRPCNumberTypesRoundTrip(t *testing.T) { + input := map[string]any{ + "TransactionType": "MPTokenIssuanceCreate", + "Flags": json.Number("160"), + "Sequence": json.Number("1"), + "LastLedgerSequence": json.Number("10"), + "MaximumAmount": "1000", + } + + encoded, err := Encode(input) + require.NoError(t, err) + + decoded, err := Decode(encoded) + require.NoError(t, err) + require.Equal(t, "MPTokenIssuanceCreate", decoded["TransactionType"]) + require.Equal(t, uint32(160), decoded["Flags"]) + require.Equal(t, uint32(1), decoded["Sequence"]) + require.Equal(t, uint32(10), decoded["LastLedgerSequence"]) + require.Equal(t, "1000", decoded["MaximumAmount"]) + + reencoded, err := Encode(decoded) + require.NoError(t, err) + require.Equal(t, encoded, reencoded) +} + +func TestMPTBaseTenUInt64RoundTrip(t *testing.T) { + fields := []string{ + "MaximumAmount", + "OutstandingAmount", + "MPTAmount", + "LockedAmount", + "ConfidentialOutstandingAmount", + } + + for _, field := range fields { + t.Run(field, func(t *testing.T) { + encoded, err := Encode(map[string]any{field: "1000"}) + require.NoError(t, err) + + decoded, err := Decode(encoded) + require.NoError(t, err) + require.Equal(t, map[string]any{field: "1000"}, decoded) + + reencoded, err := Encode(decoded) + require.NoError(t, err) + require.Equal(t, encoded, reencoded) + }) + } +} + func TestEncodeDoesNotMutateInput(t *testing.T) { tx := map[string]any{ "Account": "rMBzp8CgpE441cp5PVyA9rpVV7oT8hP3ys", diff --git a/binary-codec/confidential_mpt_wire_fields_test.go b/binary-codec/confidential_mpt_wire_fields_test.go deleted file mode 100644 index c9902f88d..000000000 --- a/binary-codec/confidential_mpt_wire_fields_test.go +++ /dev/null @@ -1,144 +0,0 @@ -package binarycodec - -import ( - "encoding/hex" - "encoding/json" - "maps" - "os" - "testing" - - "github.com/stretchr/testify/require" -) - -type confidentialMPTWireFixtures struct { - Source string `json:"source"` - Cases []confidentialMPTWireFixture `json:"cases"` -} - -type confidentialMPTWireFixture struct { - Name string `json:"name"` - JSON map[string]any `json:"json"` - Binary string `json:"binary"` -} - -func loadConfidentialMPTWireFixtures(t *testing.T) confidentialMPTWireFixtures { - t.Helper() - - data, err := os.ReadFile("testdata/fixtures/confidential-mpt-wire-fields.json") - require.NoError(t, err) - - var fixtures confidentialMPTWireFixtures - require.NoError(t, json.Unmarshal(data, &fixtures)) - require.NotEmpty(t, fixtures.Source) - require.Len(t, fixtures.Cases, 3) - - return fixtures -} - -func TestConfidentialMPTWireFieldGoldenFixtures(t *testing.T) { - fixtures := loadConfidentialMPTWireFixtures(t) - - for _, fixture := range fixtures.Cases { - t.Run(fixture.Name, func(t *testing.T) { - expected := maps.Clone(fixture.JSON) - encoded, err := Encode(maps.Clone(expected)) - require.NoError(t, err) - require.Equal(t, fixture.Binary, encoded) - - decoded, err := Decode(fixture.Binary) - require.NoError(t, err) - require.Equal(t, expected, decoded) - - reencoded, err := Encode(decoded) - require.NoError(t, err) - require.Equal(t, fixture.Binary, reencoded) - }) - } -} - -func TestLiveRPCNumberTypesRoundTrip(t *testing.T) { - input := map[string]any{ - "TransactionType": "MPTokenIssuanceCreate", - "Flags": json.Number("160"), - "Sequence": json.Number("1"), - "LastLedgerSequence": json.Number("10"), - "MaximumAmount": "1000", - } - - encoded, err := Encode(maps.Clone(input)) - require.NoError(t, err) - - decoded, err := Decode(encoded) - require.NoError(t, err) - require.Equal(t, "MPTokenIssuanceCreate", decoded["TransactionType"]) - require.Equal(t, uint32(160), decoded["Flags"]) - require.Equal(t, uint32(1), decoded["Sequence"]) - require.Equal(t, uint32(10), decoded["LastLedgerSequence"]) - require.Equal(t, "1000", decoded["MaximumAmount"]) - - reencoded, err := Encode(decoded) - require.NoError(t, err) - require.Equal(t, encoded, reencoded) -} - -func TestMPTBaseTenUInt64GoldenWireValues(t *testing.T) { - tests := []struct { - field string - header string - }{ - {field: "MaximumAmount", header: "3018"}, - {field: "OutstandingAmount", header: "3019"}, - {field: "MPTAmount", header: "301A"}, - {field: "LockedAmount", header: "301D"}, - {field: "ConfidentialOutstandingAmount", header: "3020"}, - } - - for _, tt := range tests { - t.Run(tt.field, func(t *testing.T) { - expected := tt.header + "00000000000003E8" - encoded, err := Encode(map[string]any{tt.field: "1000"}) - require.NoError(t, err) - require.Equal(t, expected, encoded) - - decoded, err := Decode(expected) - require.NoError(t, err) - require.Equal(t, map[string]any{tt.field: "1000"}, decoded) - - reencoded, err := Encode(decoded) - require.NoError(t, err) - require.Equal(t, expected, reencoded) - }) - } -} - -func TestConfidentialMPTGoldenWireLayout(t *testing.T) { - fixtures := loadConfidentialMPTWireFixtures(t) - byName := make(map[string]confidentialMPTWireFixture, len(fixtures.Cases)) - for _, fixture := range fixtures.Cases { - byName[fixture.Name] = fixture - } - - convert, err := hex.DecodeString(byName["convert_blinding_factor"].Binary) - require.NoError(t, err) - require.Len(t, convert, 37) - require.Equal(t, []byte{0x12, 0x00, 0x55}, convert[:3]) - require.Equal(t, []byte{0x50, 0x28}, convert[3:5]) - blindingFactor, err := hex.DecodeString(byName["convert_blinding_factor"].JSON["BlindingFactor"].(string)) - require.NoError(t, err) - require.Equal(t, blindingFactor, convert[5:37]) - - convertBack, err := hex.DecodeString(byName["convert_back_blinding_and_balance_commitment"].Binary) - require.NoError(t, err) - require.Len(t, convertBack, 73) - require.Equal(t, []byte{0x12, 0x00, 0x57}, convertBack[:3]) - require.Equal(t, []byte{0x50, 0x28}, convertBack[3:5]) - require.Equal(t, blindingFactor, convertBack[5:37]) - require.Equal(t, []byte{0x70, 0x2E, 0x21}, convertBack[37:40]) - - send, err := hex.DecodeString(byName["send_amount_and_balance_commitments"].Binary) - require.NoError(t, err) - require.Len(t, send, 75) - require.Equal(t, []byte{0x12, 0x00, 0x58}, send[:3]) - require.Equal(t, []byte{0x70, 0x2D, 0x21}, send[3:6]) - require.Equal(t, []byte{0x70, 0x2E, 0x21}, send[39:42]) -} diff --git a/binary-codec/definitions/confidential_mpt_test.go b/binary-codec/definitions/confidential_mpt_test.go deleted file mode 100644 index f08f13120..000000000 --- a/binary-codec/definitions/confidential_mpt_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package definitions - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestConfidentialMPTWireFieldDefinitions(t *testing.T) { - tests := []struct { - name string - info FieldInfo - header FieldHeader - ordinal int32 - }{ - { - name: "BlindingFactor", - info: FieldInfo{ - Nth: 40, - IsVLEncoded: false, - IsSerialized: true, - IsSigningField: true, - Type: "Hash256", - }, - header: FieldHeader{TypeCode: 5, FieldCode: 40}, - ordinal: 327720, - }, - { - name: "AmountCommitment", - info: FieldInfo{ - Nth: 45, - IsVLEncoded: true, - IsSerialized: true, - IsSigningField: true, - Type: "Blob", - }, - header: FieldHeader{TypeCode: 7, FieldCode: 45}, - ordinal: 458797, - }, - { - name: "BalanceCommitment", - info: FieldInfo{ - Nth: 46, - IsVLEncoded: true, - IsSerialized: true, - IsSigningField: true, - Type: "Blob", - }, - header: FieldHeader{TypeCode: 7, FieldCode: 46}, - ordinal: 458798, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - field, err := Get().GetFieldInstanceByFieldName(tc.name) - require.NoError(t, err) - require.Equal(t, tc.info, *field.FieldInfo) - require.Equal(t, tc.header, *field.FieldHeader) - require.Equal(t, tc.ordinal, field.Ordinal) - }) - } -} - -func TestConfidentialMPTTransactionResultCodes(t *testing.T) { - tests := []struct { - name string - code int32 - }{ - {name: "tecBAD_PROOF", code: 199}, - {name: "temBAD_CIPHERTEXT", code: -248}, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - code, err := Get().GetTransactionResultTypeCodeByTransactionResultName(tc.name) - require.NoError(t, err) - require.Equal(t, tc.code, code) - }) - } -} - -func TestConfidentialMPTTransactionTypeCodes(t *testing.T) { - tests := []struct { - name string - code int32 - }{ - {name: "ConfidentialMPTConvert", code: 85}, - {name: "ConfidentialMPTMergeInbox", code: 86}, - {name: "ConfidentialMPTConvertBack", code: 87}, - {name: "ConfidentialMPTSend", code: 88}, - {name: "ConfidentialMPTClawback", code: 89}, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - code, err := Get().GetTransactionTypeCodeByTransactionTypeName(tc.name) - require.NoError(t, err) - require.Equal(t, tc.code, code) - }) - } -} diff --git a/binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json b/binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json deleted file mode 100644 index 957aa7511..000000000 --- a/binary-codec/testdata/fixtures/confidential-mpt-wire-fields.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "source": "Manually assembled from rippled ba01b05f33d4b28c30ce347d0cd68c4d83005359 SField type/ordinal headers and XRPL canonical VL rules; not generated by xrpl-go.", - "cases": [ - { - "name": "convert_blinding_factor", - "json": { - "TransactionType": "ConfidentialMPTConvert", - "BlindingFactor": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" - }, - "binary": "1200555028000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" - }, - { - "name": "convert_back_blinding_and_balance_commitment", - "json": { - "TransactionType": "ConfidentialMPTConvertBack", - "BlindingFactor": "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", - "BalanceCommitment": "032222222222222222222222222222222222222222222222222222222222222222" - }, - "binary": "1200575028000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F702E21032222222222222222222222222222222222222222222222222222222222222222" - }, - { - "name": "send_amount_and_balance_commitments", - "json": { - "TransactionType": "ConfidentialMPTSend", - "AmountCommitment": "021111111111111111111111111111111111111111111111111111111111111111", - "BalanceCommitment": "032222222222222222222222222222222222222222222222222222222222222222" - }, - "binary": "120058702D21021111111111111111111111111111111111111111111111111111111111111111702E21032222222222222222222222222222222222222222222222222222222222222222" - } - ] -}