refactor(textual): Use Title/Content instead of Text (#14730)
This commit is contained in:
parent
5ec3d2b875
commit
45624191ee
@ -12,6 +12,7 @@
|
||||
* Dec 01, 2022: Link to examples in separate JSON file.
|
||||
* Dec 06, 2022: Re-ordering of envelope screens.
|
||||
* Dec 14, 2022: Mention exceptions for invertability.
|
||||
* Jan 23, 2022: Switch Screen.Text to Title+Content.
|
||||
|
||||
## Status
|
||||
|
||||
@ -126,10 +127,11 @@ in the rendering.
|
||||
|
||||
The SignDoc for `SIGN_MODE_TEXTUAL` is formed from a data structure like:
|
||||
|
||||
```
|
||||
```go
|
||||
type Screen struct {
|
||||
Text string text // possibly size limited to, e.g. 255 characters
|
||||
Indent uint8 // size limited to something small like 16 or 32
|
||||
Title string // possibly size limited to, e.g. 64 characters
|
||||
Content string // possibly size limited to, e.g. 255 characters
|
||||
Indent uint8 // size limited to something small like 16 or 32
|
||||
Expert bool
|
||||
}
|
||||
|
||||
@ -154,15 +156,17 @@ screens = [* screen]
|
||||
;; Text defaults to the empty string, indent defaults to zero,
|
||||
;; and expert defaults to false.
|
||||
screen = {
|
||||
? text_key: tstr,
|
||||
? title_key: tstr,
|
||||
? content_key: tstr,
|
||||
? indent_key: uint,
|
||||
? expert_key: bool,
|
||||
}
|
||||
|
||||
;; Keys are small integers to keep the encoding small.
|
||||
text_key = 1
|
||||
indent_key = 2
|
||||
expert_key = 3
|
||||
title_key = 1
|
||||
content_key = 2
|
||||
indent_key = 3
|
||||
expert_key = 4
|
||||
```
|
||||
|
||||
## Details
|
||||
|
||||
@ -46,7 +46,7 @@ func (ar anyValueRenderer) Format(ctx context.Context, v protoreflect.Value) ([]
|
||||
}
|
||||
|
||||
screens := make([]Screen, 1+len(subscreens))
|
||||
screens[0].Text = anymsg.GetTypeUrl()
|
||||
screens[0].Content = anymsg.GetTypeUrl()
|
||||
for i, subscreen := range subscreens {
|
||||
subscreen.Indent++
|
||||
screens[i+1] = subscreen
|
||||
@ -64,7 +64,7 @@ func (ar anyValueRenderer) Parse(ctx context.Context, screens []Screen) (protore
|
||||
return nilValue, fmt.Errorf("bad indentation: want 0, got %d", screens[0].Indent)
|
||||
}
|
||||
|
||||
msgType, err := protoregistry.GlobalTypes.FindMessageByURL(screens[0].Text)
|
||||
msgType, err := protoregistry.GlobalTypes.FindMessageByURL(screens[0].Content)
|
||||
if err != nil {
|
||||
return nilValue, err
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ func (vr bytesValueRenderer) Format(ctx context.Context, v protoreflect.Value) (
|
||||
|
||||
if len(bz) <= maxByteLen {
|
||||
text := toHex(bz)
|
||||
return []Screen{{Text: text}}, nil
|
||||
return []Screen{{Content: text}}, nil
|
||||
}
|
||||
|
||||
// For long bytes, we display the hash.
|
||||
@ -43,14 +43,14 @@ func (vr bytesValueRenderer) Format(ctx context.Context, v protoreflect.Value) (
|
||||
h := hasher.Sum(nil)
|
||||
|
||||
text := fmt.Sprintf("%s%s", hashPrefix, toHex(h))
|
||||
return []Screen{{Text: text}}, nil
|
||||
return []Screen{{Content: text}}, nil
|
||||
}
|
||||
|
||||
func (vr bytesValueRenderer) Parse(_ context.Context, screens []Screen) (protoreflect.Value, error) {
|
||||
if len(screens) != 1 {
|
||||
return nilValue, fmt.Errorf("expected single screen: %v", screens)
|
||||
}
|
||||
formatted := screens[0].Text
|
||||
formatted := screens[0].Content
|
||||
|
||||
// If the formatted string starts with `SHA-256=`, then we can't actually
|
||||
// invert to get the original bytes. In this case, we return empty bytes.
|
||||
|
||||
@ -30,7 +30,7 @@ func TestBytesJsonTestCases(t *testing.T) {
|
||||
screens, err := valrend.Format(context.Background(), protoreflect.ValueOfBytes(tc.base64))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, tc.hex, screens[0].Text)
|
||||
require.Equal(t, tc.hex, screens[0].Content)
|
||||
|
||||
// Round trip
|
||||
val, err := valrend.Parse(context.Background(), screens)
|
||||
|
||||
@ -91,7 +91,7 @@ func TestCoinJsonTestcases(t *testing.T) {
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, tc.Text, screens[0].Text)
|
||||
require.Equal(t, tc.Text, screens[0].Content)
|
||||
|
||||
// Round trip.
|
||||
value, err := vr.Parse(ctx, screens)
|
||||
|
||||
@ -49,7 +49,7 @@ func (vr coinsValueRenderer) Format(ctx context.Context, v protoreflect.Value) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []Screen{{Text: formatted}}, nil
|
||||
return []Screen{{Content: formatted}}, nil
|
||||
}
|
||||
|
||||
func (vr coinsValueRenderer) FormatRepeated(ctx context.Context, v protoreflect.Value) ([]Screen, error) {
|
||||
@ -74,7 +74,7 @@ func (vr coinsValueRenderer) FormatRepeated(ctx context.Context, v protoreflect.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []Screen{{Text: formatted}}, nil
|
||||
return []Screen{{Content: formatted}}, nil
|
||||
}
|
||||
|
||||
func (vr coinsValueRenderer) Parse(ctx context.Context, screens []Screen) (protoreflect.Value, error) {
|
||||
@ -82,11 +82,11 @@ func (vr coinsValueRenderer) Parse(ctx context.Context, screens []Screen) (proto
|
||||
return nilValue, fmt.Errorf("expected single screen: %v", screens)
|
||||
}
|
||||
|
||||
if screens[0].Text == emptyCoins {
|
||||
if screens[0].Content == emptyCoins {
|
||||
return protoreflect.ValueOfMessage((&basev1beta1.Coin{}).ProtoReflect()), nil
|
||||
}
|
||||
|
||||
parsed, err := vr.parseCoins(ctx, screens[0].Text)
|
||||
parsed, err := vr.parseCoins(ctx, screens[0].Content)
|
||||
if err != nil {
|
||||
return nilValue, err
|
||||
}
|
||||
@ -99,11 +99,11 @@ func (vr coinsValueRenderer) ParseRepeated(ctx context.Context, screens []Screen
|
||||
return fmt.Errorf("expected single screen: %v", screens)
|
||||
}
|
||||
|
||||
if screens[0].Text == emptyCoins {
|
||||
if screens[0].Content == emptyCoins {
|
||||
return nil
|
||||
}
|
||||
|
||||
parsed, err := vr.parseCoins(ctx, screens[0].Text)
|
||||
parsed, err := vr.parseCoins(ctx, screens[0].Content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ func TestCoinsJsonTestcases(t *testing.T) {
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, tc.Text, screens[0].Text)
|
||||
require.Equal(t, tc.Text, screens[0].Content)
|
||||
|
||||
// Round trip.
|
||||
parsedValue := NewGenericList([]*basev1beta1.Coin{})
|
||||
|
||||
@ -25,7 +25,7 @@ func (vr decValueRenderer) Format(_ context.Context, v protoreflect.Value) ([]Sc
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []Screen{{Text: formatted}}, nil
|
||||
return []Screen{{Content: formatted}}, nil
|
||||
}
|
||||
|
||||
func (vr decValueRenderer) Parse(_ context.Context, screens []Screen) (protoreflect.Value, error) {
|
||||
@ -33,7 +33,7 @@ func (vr decValueRenderer) Parse(_ context.Context, screens []Screen) (protorefl
|
||||
return nilValue, fmt.Errorf("expected 1 screen, got: %d", n)
|
||||
}
|
||||
|
||||
parsed, err := parseDec(screens[0].Text)
|
||||
parsed, err := parseDec(screens[0].Content)
|
||||
if err != nil {
|
||||
return nilValue, err
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ func (dr durationValueRenderer) Format(_ context.Context, v protoreflect.Value)
|
||||
s = "-" + s
|
||||
}
|
||||
|
||||
return []Screen{{Text: s}}, nil
|
||||
return []Screen{{Content: s}}, nil
|
||||
}
|
||||
|
||||
var durRegexp = regexp.MustCompile(`^(-)?(?:([0-9]+) days?)?(?:, )?(?:([0-9]+) hours?)?(?:, )?(?:([0-9]+) minutes?)?(?:, )?(?:([0-9]+)(?:\.([0-9]+))? seconds?)?$`)
|
||||
@ -125,9 +125,9 @@ func (dr durationValueRenderer) Parse(_ context.Context, screens []Screen) (prot
|
||||
return protoreflect.Value{}, fmt.Errorf("expected single screen: %v", screens)
|
||||
}
|
||||
|
||||
parts := durRegexp.FindStringSubmatch(screens[0].Text)
|
||||
parts := durRegexp.FindStringSubmatch(screens[0].Content)
|
||||
if parts == nil {
|
||||
return protoreflect.Value{}, fmt.Errorf("bad duration format: %s", screens[0].Text)
|
||||
return protoreflect.Value{}, fmt.Errorf("bad duration format: %s", screens[0].Content)
|
||||
}
|
||||
|
||||
negative := parts[1] != ""
|
||||
|
||||
@ -42,7 +42,7 @@ func TestDurationJSON(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, tc.Text, screens[0].Text)
|
||||
require.Equal(t, tc.Text, screens[0].Content)
|
||||
}
|
||||
|
||||
val, err := rend.Parse(context.Background(), screens)
|
||||
|
||||
@ -7,22 +7,25 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
textKey = cbor.NewUint(1)
|
||||
indentKey = cbor.NewUint(2)
|
||||
expertKey = cbor.NewUint(3)
|
||||
titleKey = cbor.NewUint(1)
|
||||
contentKey = cbor.NewUint(2)
|
||||
indentKey = cbor.NewUint(3)
|
||||
expertKey = cbor.NewUint(4)
|
||||
)
|
||||
|
||||
// encode encodes an array of screens according to the CDDL:
|
||||
//
|
||||
// screens = [* screen]
|
||||
// screen = {
|
||||
// ? text_key: tstr,
|
||||
// ? title_key: tstr,
|
||||
// ? content_key: tstr,
|
||||
// ? indent_key: uint,
|
||||
// ? expert_key: bool,
|
||||
// }
|
||||
// text_key = 1
|
||||
// indent_key = 2
|
||||
// expert_key = 3
|
||||
// content_key = 2
|
||||
// indent_key = 3
|
||||
// expert_key = 4
|
||||
//
|
||||
// with empty values ("", 0, false) omitted from the screen map.
|
||||
func encode(screens []Screen, w io.Writer) error {
|
||||
@ -35,8 +38,11 @@ func encode(screens []Screen, w io.Writer) error {
|
||||
|
||||
func (s Screen) Cbor() cbor.Cbor {
|
||||
m := cbor.NewMap()
|
||||
if s.Text != "" {
|
||||
m = m.Add(textKey, cbor.NewText(s.Text))
|
||||
if s.Title != "" {
|
||||
m = m.Add(titleKey, cbor.NewText(s.Title))
|
||||
}
|
||||
if s.Content != "" {
|
||||
m = m.Add(contentKey, cbor.NewText(s.Content))
|
||||
}
|
||||
if s.Indent > 0 {
|
||||
// #nosec G701
|
||||
|
||||
@ -30,7 +30,7 @@ func (er enumValueRenderer) Format(_ context.Context, v protoreflect.Value) ([]S
|
||||
return nil, fmt.Errorf("cannot get enum %s variant of number %d", er.ed.FullName(), v.Enum())
|
||||
}
|
||||
|
||||
return []Screen{{Text: string(evd.Name())}}, nil
|
||||
return []Screen{{Content: string(evd.Name())}}, nil
|
||||
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ func (er enumValueRenderer) Parse(_ context.Context, screens []Screen) (protoref
|
||||
return nilValue, fmt.Errorf("expected single screen: %v", screens)
|
||||
}
|
||||
|
||||
formatted := screens[0].Text
|
||||
formatted := screens[0].Content
|
||||
|
||||
// Loop through all enum variants until we find the one matching the
|
||||
// formatted screen's one.
|
||||
|
||||
@ -44,7 +44,7 @@ func TestEnumJsonTestcases(t *testing.T) {
|
||||
screens, err := valrend.Format(context.Background(), val)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, tc.Text, screens[0].Text)
|
||||
require.Equal(t, tc.Text, screens[0].Content)
|
||||
|
||||
// Round trip
|
||||
parsedVal, err := valrend.Parse(context.Background(), screens)
|
||||
|
||||
@ -27,7 +27,7 @@ func (vr intValueRenderer) Format(_ context.Context, v protoreflect.Value) ([]Sc
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []Screen{{Text: formatted}}, nil
|
||||
return []Screen{{Content: formatted}}, nil
|
||||
}
|
||||
|
||||
func (vr intValueRenderer) Parse(_ context.Context, screens []Screen) (protoreflect.Value, error) {
|
||||
@ -35,7 +35,7 @@ func (vr intValueRenderer) Parse(_ context.Context, screens []Screen) (protorefl
|
||||
return nilValue, fmt.Errorf("expected 1 screen, got: %d", n)
|
||||
}
|
||||
|
||||
parsedInt, err := parseInt(screens[0].Text)
|
||||
parsedInt, err := parseInt(screens[0].Content)
|
||||
if err != nil {
|
||||
return nilValue, err
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ func checkNumberTest(t *testing.T, r textual.ValueRenderer, pv protoreflect.Valu
|
||||
require.Equal(t, 0, screens[0].Indent)
|
||||
require.Equal(t, false, screens[0].Expert)
|
||||
|
||||
require.Equal(t, expected, screens[0].Text)
|
||||
require.Equal(t, expected, screens[0].Content)
|
||||
|
||||
// Round trip.
|
||||
value, err := r.Parse(context.Background(), screens)
|
||||
|
||||
38
x/tx/textual/internal/testdata/any.json
vendored
38
x/tx/textual/internal/testdata/any.json
vendored
@ -4,8 +4,8 @@
|
||||
"@type": "/Foo"
|
||||
},
|
||||
"screens": [
|
||||
{"text": "/Foo"},
|
||||
{"text": "Foo object", "indent": 1}
|
||||
{"content": "/Foo"},
|
||||
{"content": "Foo object", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -14,9 +14,9 @@
|
||||
"full_name": "testing"
|
||||
},
|
||||
"screens": [
|
||||
{"text": "/Foo"},
|
||||
{"text": "Foo object", "indent": 1},
|
||||
{"text": "Full name: testing", "indent": 2}
|
||||
{"content": "/Foo"},
|
||||
{"content": "Foo object", "indent": 1},
|
||||
{"title": "Full name", "content": "testing", "indent": 2}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -25,8 +25,8 @@
|
||||
"value": "2006-01-02T15:04:05Z"
|
||||
},
|
||||
"screens": [
|
||||
{"text": "/google.protobuf.Timestamp"},
|
||||
{"text": "2006-01-02T15:04:05Z", "indent": 1}
|
||||
{"content": "/google.protobuf.Timestamp"},
|
||||
{"content": "2006-01-02T15:04:05Z", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -37,9 +37,9 @@
|
||||
}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "/google.protobuf.Any"},
|
||||
{"text": "/Foo", "indent": 1},
|
||||
{"text": "Foo object", "indent": 2}
|
||||
{"content": "/google.protobuf.Any"},
|
||||
{"content": "/Foo", "indent": 1},
|
||||
{"content": "Foo object", "indent": 2}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -51,10 +51,10 @@
|
||||
}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "/google.protobuf.Any"},
|
||||
{"text": "/Foo", "indent": 1},
|
||||
{"text": "Foo object", "indent": 2},
|
||||
{"text": "Full name: testing", "indent": 3}
|
||||
{"content": "/google.protobuf.Any"},
|
||||
{"content": "/Foo", "indent": 1},
|
||||
{"content": "Foo object", "indent": 2},
|
||||
{"title": "Full name", "content": "testing", "indent": 3}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -66,11 +66,11 @@
|
||||
}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "/A"},
|
||||
{"text": "A object", "indent": 1},
|
||||
{"text": "ANY: /Foo", "indent": 2},
|
||||
{"text": "Foo object", "indent": 3},
|
||||
{"text": "Full name: testing", "indent": 4}
|
||||
{"content": "/A"},
|
||||
{"content": "A object", "indent": 1},
|
||||
{"title": "ANY", "content": "/Foo", "indent": 2},
|
||||
{"content": "Foo object", "indent": 3},
|
||||
{"title": "Full name", "content": "testing", "indent": 4}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
181
x/tx/textual/internal/testdata/e2e.json
vendored
181
x/tx/textual/internal/testdata/e2e.json
vendored
File diff suppressed because one or more lines are too long
27
x/tx/textual/internal/testdata/encode.json
vendored
27
x/tx/textual/internal/testdata/encode.json
vendored
@ -8,31 +8,36 @@
|
||||
"encoding": "81a0"
|
||||
},
|
||||
{
|
||||
"screens": [{"text": ""}, {"indent": 0}, {"expert": false}],
|
||||
"screens": [{"content": ""}, {"indent": 0}, {"expert": false}],
|
||||
"encoding": "83a0a0a0"
|
||||
},
|
||||
{
|
||||
"screens": [{"title": ""}, {"content": ""}, {"indent": 0}, {"expert": false}],
|
||||
"encoding": "84a0a0a0a0"
|
||||
},
|
||||
{
|
||||
"screens": [
|
||||
{"text": "a"},
|
||||
{"title": "1"},
|
||||
{"content": "a"},
|
||||
{"indent": 1},
|
||||
{"expert": true}
|
||||
],
|
||||
"encoding": "83a1016161a10201a103f5"
|
||||
"encoding": "84a1016131a1026161a10301a104f5"
|
||||
},
|
||||
{
|
||||
"screens": [
|
||||
{"text": "", "indent": 4, "expert": true},
|
||||
{"text": "a", "indent": 0, "expert": true},
|
||||
{"text": "b", "indent": 5, "expert": false}
|
||||
{"title": "1", "content": "", "indent": 4, "expert": true},
|
||||
{"title": "", "content": "a", "indent": 0, "expert": true},
|
||||
{"title": "2", "content": "b", "indent": 5, "expert": false}
|
||||
],
|
||||
"encoding": "83a2020403f5a201616103f5a20161620205"
|
||||
"encoding": "83a3016131030404f5a202616104f5a30161320261620305"
|
||||
},
|
||||
{
|
||||
"screens": [
|
||||
{"text": "start"},
|
||||
{"text": "middle", "indent": 1},
|
||||
{"text": "end"}
|
||||
{"title": "first", "content": "start"},
|
||||
{"title": "then", "content": "middle", "indent": 1},
|
||||
{"title": "last", "content": "end"}
|
||||
],
|
||||
"encoding": "83a101657374617274a201666d6964646c650201a10163656e64"
|
||||
"encoding": "83a20165666972737402657374617274a301647468656e02666d6964646c650301a201646c6173740263656e64"
|
||||
}
|
||||
]
|
||||
|
||||
90
x/tx/textual/internal/testdata/message.json
vendored
90
x/tx/textual/internal/testdata/message.json
vendored
@ -2,7 +2,7 @@
|
||||
{
|
||||
"proto": {},
|
||||
"screens": [
|
||||
{"text": "Foo object"}
|
||||
{"content": "Foo object"}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -10,8 +10,8 @@
|
||||
"full_name": "nonempty"
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Full name: nonempty", "indent": 1}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Full name", "content": "nonempty", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -20,9 +20,9 @@
|
||||
"nickname": ":thing two"
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Full name: thing one", "indent": 1},
|
||||
{"text": "Nickname: :thing two", "indent": 1}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Full name", "content": "thing one", "indent": 1},
|
||||
{"title": "Nickname", "content": ":thing two", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -33,9 +33,9 @@
|
||||
}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Full name: special child message", "indent": 1},
|
||||
{"text": "Mtime: 2006-01-02T15:04:05Z", "indent": 1}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Full name", "content": "special child message", "indent": 1},
|
||||
{"title": "Mtime", "content": "2006-01-02T15:04:05Z", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -44,9 +44,9 @@
|
||||
"left": {}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Nickname: empty child", "indent": 1},
|
||||
{"text": "Left: Foo object", "indent": 1}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Nickname", "content": "empty child", "indent": 1},
|
||||
{"title": "Left", "content": "Foo object", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -57,11 +57,11 @@
|
||||
"bar": {}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Nickname: empty children", "indent": 1},
|
||||
{"text": "Left: Foo object", "indent": 1},
|
||||
{"text": "Right: Foo object", "indent": 1},
|
||||
{"text": "Bar: Bar object", "indent": 1}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Nickname", "content": "empty children", "indent": 1},
|
||||
{"title": "Left", "content": "Foo object", "indent": 1},
|
||||
{"title": "Right", "content": "Foo object", "indent": 1},
|
||||
{"title": "Bar", "content": "Bar object", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -74,12 +74,12 @@
|
||||
"bar": {}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Full name: subfield", "indent": 1},
|
||||
{"text": "Left: Foo object", "indent": 1},
|
||||
{"text": "Right: Foo object", "indent": 1},
|
||||
{"text": "Nickname: junior", "indent": 2},
|
||||
{"text": "Bar: Bar object", "indent": 1}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Full name", "content": "subfield", "indent": 1},
|
||||
{"title": "Left", "content": "Foo object", "indent": 1},
|
||||
{"title": "Right", "content": "Foo object", "indent": 1},
|
||||
{"title": "Nickname", "content": "junior", "indent": 2},
|
||||
{"title": "Bar", "content": "Bar object", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -95,18 +95,18 @@
|
||||
}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Full name: deep", "indent": 1},
|
||||
{"text": "Left: Foo object", "indent": 1},
|
||||
{"text": "Left: Foo object", "indent": 2},
|
||||
{"text": "Nickname: LL", "indent": 3},
|
||||
{"text": "Right: Foo object", "indent": 2},
|
||||
{"text": "Nickname: LR", "indent": 3},
|
||||
{"text": "Right: Foo object", "indent": 1},
|
||||
{"text": "Left: Foo object", "indent": 2},
|
||||
{"text": "Nickname: RL", "indent": 3},
|
||||
{"text": "Right: Foo object", "indent": 2},
|
||||
{"text": "Nickname: RR", "indent": 3}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Full name", "content": "deep", "indent": 1},
|
||||
{"title": "Left", "content": "Foo object", "indent": 1},
|
||||
{"title": "Left", "content": "Foo object", "indent": 2},
|
||||
{"title": "Nickname", "content": "LL", "indent": 3},
|
||||
{"title": "Right", "content": "Foo object", "indent": 2},
|
||||
{"title": "Nickname", "content": "LR", "indent": 3},
|
||||
{"title": "Right", "content": "Foo object", "indent": 1},
|
||||
{"title": "Left", "content": "Foo object", "indent": 2},
|
||||
{"title": "Nickname", "content": "RL", "indent": 3},
|
||||
{"title": "Right", "content": "Foo object", "indent": 2},
|
||||
{"title": "Nickname", "content": "RR", "indent": 3}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -124,16 +124,16 @@
|
||||
}
|
||||
},
|
||||
"screens": [
|
||||
{"text": "Foo object"},
|
||||
{"text": "Full name: the kitchen sink ", "indent": 1},
|
||||
{"text": "Mtime: 1970-01-01T00:00:00Z", "indent": 1},
|
||||
{"text": "Left: Foo object", "indent": 1},
|
||||
{"text": "Right: Foo object", "indent": 1},
|
||||
{"text": "Nickname: blub", "indent": 2},
|
||||
{"text": "Right: Foo object", "indent": 2},
|
||||
{"text": "Bar: Bar object", "indent": 2},
|
||||
{"text": "Bar id: quux", "indent": 3},
|
||||
{"text": "Data: FFFE", "indent": 3}
|
||||
{"content": "Foo object"},
|
||||
{"title": "Full name", "content": " the kitchen sink ", "indent": 1},
|
||||
{"title": "Mtime", "content": "1970-01-01T00:00:00Z", "indent": 1},
|
||||
{"title": "Left", "content": "Foo object", "indent": 1},
|
||||
{"title": "Right", "content": "Foo object", "indent": 1},
|
||||
{"title": "Nickname", "content": "blub", "indent": 2},
|
||||
{"title": "Right", "content": "Foo object", "indent": 2},
|
||||
{"title": "Bar", "content": "Bar object", "indent": 2},
|
||||
{"title": "Bar id", "content": "quux", "indent": 3},
|
||||
{"title": "Data", "content": "FFFE", "indent": 3}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
112
x/tx/textual/internal/testdata/repeated.json
vendored
112
x/tx/textual/internal/testdata/repeated.json
vendored
@ -1,9 +1,8 @@
|
||||
[
|
||||
{
|
||||
"proto": {},
|
||||
"parses": true,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0}
|
||||
{"content": "Qux object", "indent": 0}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -15,14 +14,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"parses": true,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0},
|
||||
{"text": "Messages: 1 Foo", "indent": 1},
|
||||
{"text": "Messages (1/1): Foo object", "indent": 2},
|
||||
{"text": "Full name: thing one", "indent": 3},
|
||||
{"text": "Nickname: :thing two", "indent": 3},
|
||||
{"text": "End of Messages", "indent": 1}
|
||||
{"content": "Qux object", "indent": 0},
|
||||
{"title": "Messages", "content": "1 Foo", "indent": 1},
|
||||
{"title": "Messages (1/1)", "content": "Foo object", "indent": 2},
|
||||
{"title": "Full name", "content": "thing one", "indent": 3},
|
||||
{"title": "Nickname", "content": ":thing two", "indent": 3},
|
||||
{"content": "End of Messages", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -38,17 +36,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"parses": true,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0},
|
||||
{"text": "Messages: 2 Foo", "indent": 1},
|
||||
{"text": "Messages (1/2): Foo object", "indent": 2},
|
||||
{"text": "Full name: thing one", "indent": 3},
|
||||
{"text": "Nickname: thing two", "indent": 3},
|
||||
{"text": "Messages (2/2): Foo object", "indent": 2},
|
||||
{"text": "Full name: thing three", "indent": 3},
|
||||
{"text": "Nickname: thing four", "indent": 3},
|
||||
{"text": "End of Messages", "indent": 1}
|
||||
{"content": "Qux object", "indent": 0},
|
||||
{"title": "Messages", "content": "2 Foo", "indent": 1},
|
||||
{"title": "Messages (1/2)", "content": "Foo object", "indent": 2},
|
||||
{"title": "Full name", "content": "thing one", "indent": 3},
|
||||
{"title": "Nickname", "content": "thing two", "indent": 3},
|
||||
{"title": "Messages (2/2)", "content": "Foo object", "indent": 2},
|
||||
{"title": "Full name", "content": "thing three", "indent": 3},
|
||||
{"title": "Nickname", "content": "thing four", "indent": 3},
|
||||
{"content": "End of Messages", "indent": 1}
|
||||
|
||||
]
|
||||
},
|
||||
@ -58,12 +55,11 @@
|
||||
"/OmniFlix.onft.v1beta1.MsgTransferONFT"
|
||||
]
|
||||
},
|
||||
"parses": true,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0},
|
||||
{"text": "String messages: 1 String", "indent": 1},
|
||||
{"text": "String messages (1/1): /OmniFlix.onft.v1beta1.MsgTransferONFT", "indent": 2},
|
||||
{"text": "End of String messages", "indent": 1}
|
||||
{"content": "Qux object", "indent": 0},
|
||||
{"title": "String messages", "content": "1 String", "indent": 1},
|
||||
{"title": "String messages (1/1)", "content": "/OmniFlix.onft.v1beta1.MsgTransferONFT", "indent": 2},
|
||||
{"content": "End of String messages", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -74,14 +70,13 @@
|
||||
"/OmniFlix.marketplace.v1beta1.MsgListNFT"
|
||||
]
|
||||
},
|
||||
"parses": true,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0},
|
||||
{"text": "String messages: 3 String", "indent": 1},
|
||||
{"text": "String messages (1/3): /OmniFlix.onft.v1beta1.MsgTransferONFT", "indent": 2},
|
||||
{"text": "String messages (2/3): /OmniFlix.onft.v1beta1.MsgBurnONFT", "indent": 2},
|
||||
{"text": "String messages (3/3): /OmniFlix.marketplace.v1beta1.MsgListNFT", "indent": 2},
|
||||
{"text": "End of String messages", "indent": 1}
|
||||
{"content": "Qux object", "indent": 0},
|
||||
{"title": "String messages", "content": "3 String", "indent": 1},
|
||||
{"title": "String messages (1/3)", "content": "/OmniFlix.onft.v1beta1.MsgTransferONFT", "indent": 2},
|
||||
{"title": "String messages (2/3)", "content": "/OmniFlix.onft.v1beta1.MsgBurnONFT", "indent": 2},
|
||||
{"title": "String messages (3/3)", "content": "/OmniFlix.marketplace.v1beta1.MsgListNFT", "indent": 2},
|
||||
{"content": "End of String messages", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -101,20 +96,19 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"parses": false,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0},
|
||||
{"text": "Vote: Ballot object", "indent": 1},
|
||||
{"text": "Proposal id: 4", "indent": 2},
|
||||
{"text": "Voter: cosmos1abc...def", "indent": 2},
|
||||
{"text": "Options: 2 WeightedBallotOption", "indent": 2},
|
||||
{"text": "Options (1/2): WeightedBallotOption object", "indent": 3},
|
||||
{"text": "Option: Yes", "indent": 4},
|
||||
{"text": "Weight: 0.7", "indent": 4},
|
||||
{"text": "Options (2/2): WeightedBallotOption object", "indent": 3},
|
||||
{"text": "Option: No", "indent": 4},
|
||||
{"text": "Weight: 0.3", "indent": 4},
|
||||
{"text": "End of Options", "indent": 2}
|
||||
{"content": "Qux object", "indent": 0},
|
||||
{"title": "Vote", "content": "Ballot object", "indent": 1},
|
||||
{"title": "Proposal id", "content": "4", "indent": 2},
|
||||
{"title": "Voter", "content": "cosmos1abc...def", "indent": 2},
|
||||
{"title": "Options", "content": "2 WeightedBallotOption", "indent": 2},
|
||||
{"title": "Options (1/2)", "content": "WeightedBallotOption object", "indent": 3},
|
||||
{"title": "Option", "content": "Yes", "indent": 4},
|
||||
{"title": "Weight", "content": "0.7", "indent": 4},
|
||||
{"title": "Options (2/2)", "content": "WeightedBallotOption object", "indent": 3},
|
||||
{"title": "Option", "content": "No", "indent": 4},
|
||||
{"title": "Weight", "content": "0.3", "indent": 4},
|
||||
{"content": "End of Options", "indent": 2}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -124,10 +118,9 @@
|
||||
{ "amount": "3", "denom": "ustake" }
|
||||
]
|
||||
},
|
||||
"parses": false,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0},
|
||||
{"text": "Price: 1 ucosm, 3 ustake", "indent": 1}
|
||||
{"content": "Qux object", "indent": 0},
|
||||
{"title": "Price", "content": "1 ucosm, 3 ustake", "indent": 1}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -143,19 +136,18 @@
|
||||
{"seconds": 0, "nanos": 10000000}
|
||||
]
|
||||
},
|
||||
"parses": true,
|
||||
"screens": [
|
||||
{"text": "Qux object", "indent": 0},
|
||||
{"text": "Expirations: 8 Timestamp", "indent": 1},
|
||||
{"text": "Expirations (1/8): 1970-01-01T00:00:00.000000001Z", "indent": 2},
|
||||
{"text": "Expirations (2/8): 1970-01-01T00:00:00.00000001Z", "indent": 2},
|
||||
{"text": "Expirations (3/8): 1970-01-01T00:00:00.0000001Z", "indent": 2},
|
||||
{"text": "Expirations (4/8): 1970-01-01T00:00:00.000001Z", "indent": 2},
|
||||
{"text": "Expirations (5/8): 1970-01-01T00:00:00.00001Z", "indent": 2},
|
||||
{"text": "Expirations (6/8): 1970-01-01T00:00:00.0001Z", "indent": 2},
|
||||
{"text": "Expirations (7/8): 1970-01-01T00:00:00.001Z", "indent": 2},
|
||||
{"text": "Expirations (8/8): 1970-01-01T00:00:00.01Z", "indent": 2},
|
||||
{"text": "End of Expirations", "indent": 1}
|
||||
{"content": "Qux object", "indent": 0},
|
||||
{"title": "Expirations", "content": "8 Timestamp", "indent": 1},
|
||||
{"title": "Expirations (1/8)", "content": "1970-01-01T00:00:00.000000001Z", "indent": 2},
|
||||
{"title": "Expirations (2/8)", "content": "1970-01-01T00:00:00.00000001Z", "indent": 2},
|
||||
{"title": "Expirations (3/8)", "content": "1970-01-01T00:00:00.0000001Z", "indent": 2},
|
||||
{"title": "Expirations (4/8)", "content": "1970-01-01T00:00:00.000001Z", "indent": 2},
|
||||
{"title": "Expirations (5/8)", "content": "1970-01-01T00:00:00.00001Z", "indent": 2},
|
||||
{"title": "Expirations (6/8)", "content": "1970-01-01T00:00:00.0001Z", "indent": 2},
|
||||
{"title": "Expirations (7/8)", "content": "1970-01-01T00:00:00.001Z", "indent": 2},
|
||||
{"title": "Expirations (8/8)", "content": "1970-01-01T00:00:00.01Z", "indent": 2},
|
||||
{"content": "End of Expirations", "indent": 1}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
259
x/tx/textual/internal/testdata/tx.json
vendored
259
x/tx/textual/internal/testdata/tx.json
vendored
@ -48,37 +48,30 @@
|
||||
]
|
||||
},
|
||||
"screens": [
|
||||
{ "text": "Chain id: my-chain" },
|
||||
{ "text": "Account number: 1" },
|
||||
{ "text": "Sequence: 2" },
|
||||
{ "text": "Address: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "text": "Public key: /cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "text": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "text": "Key: 02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "text": "This transaction has 1 Message" },
|
||||
{ "text": "Message (1/1): /cosmos.bank.v1beta1.MsgSend", "indent": 1 },
|
||||
{ "text": "MsgSend object", "indent": 2 },
|
||||
{ "text": "From address: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "text": "To address: cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "indent": 3 },
|
||||
{ "text": "Amount: 10 ATOM", "indent": 3 },
|
||||
{ "text": "End of Message" },
|
||||
{ "text": "Fees: 0.002 ATOM" },
|
||||
{ "text": "Gas limit: 100'000", "expert": true },
|
||||
{ "text": "Hash of raw bytes: 785bd306ea8962cdb9600089bdd65f3dc029e1aea112dee69e19546c9adad86e", "expert": true }
|
||||
{ "title": "Chain id", "content": "my-chain" },
|
||||
{ "title": "Account number", "content": "1" },
|
||||
{ "title": "Sequence", "content": "2" },
|
||||
{ "title": "Address", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "title": "Public key", "content": "/cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "content": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "title": "Key", "content": "02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "content": "This transaction has 1 Message" },
|
||||
{ "title": "Message (1/1)", "content": "/cosmos.bank.v1beta1.MsgSend", "indent": 1 },
|
||||
{ "content": "MsgSend object", "indent": 2 },
|
||||
{ "title": "From address", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "title": "To address", "content": "cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "indent": 3 },
|
||||
{ "title": "Amount", "content": "10 ATOM", "indent": 3 },
|
||||
{ "content": "End of Message" },
|
||||
{ "title": "Fees", "content": "0.002 ATOM" },
|
||||
{ "title": "Gas limit", "content": "100'000", "expert": true },
|
||||
{ "title": "Hash of raw bytes", "content": "785bd306ea8962cdb9600089bdd65f3dc029e1aea112dee69e19546c9adad86e", "expert": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tricky memo (starts with >, utf-8, trailing whitespaces)",
|
||||
"proto": {
|
||||
"body": {
|
||||
"messages": [
|
||||
{
|
||||
"@type": "/cosmos.bank.v1beta1.MsgSend",
|
||||
"from_address": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs",
|
||||
"to_address": "cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t",
|
||||
"amount": [{ "denom": "uatom", "amount": "10000000" }]
|
||||
}
|
||||
],
|
||||
"messages": [{ "@type": "/cosmos.bank.v1beta1.MsgSend", "from_address": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "to_address": "cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "amount": [{ "denom": "uatom", "amount": "10000000" }] }],
|
||||
"memo": "> ⚛️\\u269B⚛️ "
|
||||
},
|
||||
"auth_info": {
|
||||
@ -117,24 +110,24 @@
|
||||
]
|
||||
},
|
||||
"screens": [
|
||||
{ "text": "Chain id: my-chain" },
|
||||
{ "text": "Account number: 1" },
|
||||
{ "text": "Sequence: 2" },
|
||||
{ "text": "Address: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "text": "Public key: /cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "text": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "text": "Key: 02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "text": "This transaction has 1 Message" },
|
||||
{ "text": "Message (1/1): /cosmos.bank.v1beta1.MsgSend", "indent": 1 },
|
||||
{ "text": "MsgSend object", "indent": 2 },
|
||||
{ "text": "From address: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "text": "To address: cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "indent": 3 },
|
||||
{ "text": "Amount: 10 ATOM", "indent": 3 },
|
||||
{ "text": "End of Message" },
|
||||
{ "text": "Memo: > ⚛️\\u269B⚛️ " },
|
||||
{ "text": "Fees: 0.002 ATOM" },
|
||||
{ "text": "Gas limit: 100'000", "expert": true },
|
||||
{ "text": "Hash of raw bytes: 9c043290109c270b2ffa9f3c0fa55a090c0125ebef881f7da53978dbf93f7385", "expert": true }
|
||||
{ "title": "Chain id", "content": "my-chain" },
|
||||
{ "title": "Account number", "content": "1" },
|
||||
{ "title": "Sequence", "content": "2" },
|
||||
{ "title": "Address", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "title": "Public key", "content": "/cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "content": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "title": "Key", "content": "02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "content": "This transaction has 1 Message" },
|
||||
{ "title": "Message (1/1)", "content": "/cosmos.bank.v1beta1.MsgSend", "indent": 1 },
|
||||
{ "content": "MsgSend object", "indent": 2 },
|
||||
{ "title": "From address", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "title": "To address", "content": "cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "indent": 3 },
|
||||
{ "title": "Amount", "content": "10 ATOM", "indent": 3 },
|
||||
{ "content": "End of Message" },
|
||||
{ "title": "Memo", "content": "> ⚛️\\u269B⚛️ " },
|
||||
{ "title": "Fees", "content": "0.002 ATOM" },
|
||||
{ "title": "Gas limit", "content": "100'000", "expert": true },
|
||||
{ "title": "Hash of raw bytes", "content": "9c043290109c270b2ffa9f3c0fa55a090c0125ebef881f7da53978dbf93f7385", "expert": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -187,27 +180,28 @@
|
||||
]
|
||||
},
|
||||
"screens": [
|
||||
{ "text": "Chain id: my-chain" },
|
||||
{ "text": "Account number: 1" },
|
||||
{ "text": "Sequence: 2" },
|
||||
{ "text": "Address: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "text": "Public key: /cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "text": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "text": "Key: 02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "text": "This transaction has 1 Message" },
|
||||
{ "text": "Message (1/1): /cosmos.gov.v1.MsgVote", "indent": 1 },
|
||||
{ "text": "MsgVote object", "indent": 2 },
|
||||
{ "text": "Proposal id: 1", "indent": 3 },
|
||||
{ "text": "Voter: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "text": "Option: VOTE_OPTION_YES", "indent": 3 },
|
||||
{ "title": "Chain id", "content": "my-chain" },
|
||||
{ "title": "Account number", "content": "1" },
|
||||
{ "title": "Sequence", "content": "2" },
|
||||
{ "title": "Address", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "title": "Public key", "content": "/cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "content": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "title": "Key", "content": "02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "content": "This transaction has 1 Message" },
|
||||
{ "title": "Message (1/1)", "content": "/cosmos.gov.v1.MsgVote", "indent": 1 },
|
||||
{ "content": "MsgVote object", "indent": 2 },
|
||||
{ "title": "Proposal id", "content": "1", "indent": 3 },
|
||||
{ "title": "Voter", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "title": "Option", "content": "VOTE_OPTION_YES", "indent": 3 },
|
||||
{
|
||||
"text": "Metadata: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Also it ends in a single ampersand @",
|
||||
"title": "Metadata",
|
||||
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Also it ends in a single ampersand @",
|
||||
"indent": 3
|
||||
},
|
||||
{ "text": "End of Message" },
|
||||
{ "text": "Fees: 0.002 ATOM" },
|
||||
{ "text": "Gas limit: 100'000", "expert": true },
|
||||
{ "text": "Hash of raw bytes: 0397a88038a9d5f4cc60e3e06bb02bb9f093209fd72057008fddaeab6f039d74", "expert": true }
|
||||
{ "content": "End of Message" },
|
||||
{ "title": "Fees", "content": "0.002 ATOM" },
|
||||
{ "title": "Gas limit", "content": "100'000", "expert": true },
|
||||
{ "title": "Hash of raw bytes", "content": "0397a88038a9d5f4cc60e3e06bb02bb9f093209fd72057008fddaeab6f039d74", "expert": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -333,80 +327,81 @@
|
||||
]
|
||||
},
|
||||
"screens": [
|
||||
{ "text": "Chain id: my-chain" },
|
||||
{ "text": "Account number: 1" },
|
||||
{ "text": "Sequence: 2" },
|
||||
{ "text": "Address: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "text": "Public key: /cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "text": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "text": "Key: 02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "text": "This transaction has 2 Messages" },
|
||||
{ "text": "Message (1/2): /cosmos.authz.v1beta1.MsgExec", "indent": 1 },
|
||||
{ "text": "MsgExec object", "indent": 2 },
|
||||
{ "text": "Grantee: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "text": "Msgs: 1 Any", "indent": 3 },
|
||||
{ "text": "Msgs (1/1): /cosmos.bank.v1beta1.MsgSend", "indent": 4 },
|
||||
{ "text": "MsgSend object", "indent": 5 },
|
||||
{ "text": "From address: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 6 },
|
||||
{ "text": "To address: cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "indent": 6 },
|
||||
{ "text": "Amount: 10 ATOM", "indent": 6 },
|
||||
{ "text": "End of Msgs", "indent": 3 },
|
||||
{ "text": "Message (2/2): /cosmos.gov.v1.MsgVote", "indent": 1 },
|
||||
{ "text": "MsgVote object", "indent": 2 },
|
||||
{ "text": "Proposal id: 1", "indent": 3 },
|
||||
{ "text": "Voter: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "text": "Option: VOTE_OPTION_YES", "indent": 3 },
|
||||
{ "title": "Chain id", "content": "my-chain" },
|
||||
{ "title": "Account number", "content": "1" },
|
||||
{ "title": "Sequence", "content": "2" },
|
||||
{ "title": "Address", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "title": "Public key", "content": "/cosmos.crypto.secp256k1.PubKey", "expert": true },
|
||||
{ "content": "PubKey object", "indent": 1, "expert": true },
|
||||
{ "title": "Key", "content": "02EB DD7F E4FD EB76 DC8A 205E F65D 790C D30E 8A37 5A5C 2528 EB3A 923A F1FB 4D79 4D", "indent": 2, "expert": true },
|
||||
{ "content": "This transaction has 2 Messages" },
|
||||
{ "title": "Message (1/2)", "content": "/cosmos.authz.v1beta1.MsgExec", "indent": 1 },
|
||||
{ "content": "MsgExec object", "indent": 2 },
|
||||
{ "title": "Grantee", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "title": "Msgs", "content": "1 Any", "indent": 3 },
|
||||
{ "title": "Msgs (1/1)", "content": "/cosmos.bank.v1beta1.MsgSend", "indent": 4 },
|
||||
{ "content": "MsgSend object", "indent": 5 },
|
||||
{ "title": "From address", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 6 },
|
||||
{ "title": "To address", "content": "cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "indent": 6 },
|
||||
{ "title": "Amount", "content": "10 ATOM", "indent": 6 },
|
||||
{ "content": "End of Msgs", "indent": 3 },
|
||||
{ "title": "Message (2/2)", "content": "/cosmos.gov.v1.MsgVote", "indent": 1 },
|
||||
{ "content": "MsgVote object", "indent": 2 },
|
||||
{ "title": "Proposal id", "content": "1", "indent": 3 },
|
||||
{ "title": "Voter", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "indent": 3 },
|
||||
{ "title": "Option", "content": "VOTE_OPTION_YES", "indent": 3 },
|
||||
{
|
||||
"text": "Metadata: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Also it ends in a single ampersand @",
|
||||
"title": "Metadata",
|
||||
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Also it ends in a single ampersand @",
|
||||
"indent": 3
|
||||
},
|
||||
{ "text": "End of Message" },
|
||||
{ "text": "Memo: > ⚛️\\u269B⚛️ " },
|
||||
{ "text": "Fees: 0.002 ATOM" },
|
||||
{ "text": "Fee payer: cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "expert": true },
|
||||
{ "text": "Fee granter: cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "text": "Tip: 0.02 ATOM, 30'000 uosmo" },
|
||||
{ "text": "Tipper: cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t" },
|
||||
{ "text": "Gas limit: 100'000", "expert": true },
|
||||
{ "text": "Timeout height: 20", "expert": true },
|
||||
{ "text": "Other signer: 1 SignerInfo", "expert": true },
|
||||
{ "text": "Other signer (1/1): SignerInfo object", "indent": 1, "expert": true },
|
||||
{ "text": "Public key: /cosmos.crypto.multisig.LegacyAminoPubKey", "indent": 2, "expert": true },
|
||||
{ "text": "LegacyAminoPubKey object", "indent": 3, "expert": true },
|
||||
{ "text": "Threshold: 2", "indent": 4, "expert": true },
|
||||
{ "text": "Public keys: 2 Any", "indent": 4, "expert": true },
|
||||
{ "text": "Public keys (1/2): /cosmos.crypto.secp256k1.PubKey", "indent": 5, "expert": true },
|
||||
{ "text": "PubKey object", "indent": 6, "expert": true },
|
||||
{ "text": "Key: 0257 4EBE 0BFC 754F 5967 3BA1 1B27 500F 9158 ADE2 E17E 1A01 82B0 CA8B C652 4DB0 93", "indent": 7, "expert": true },
|
||||
{ "text": "Public keys (2/2): /cosmos.crypto.ed25519.PubKey", "indent": 5, "expert": true },
|
||||
{ "text": "PubKey object", "indent": 6, "expert": true },
|
||||
{ "text": "Key: 0315 0C47 F18A A327 16A6 547E DA8B 7369 067D CE11 D141 6245 B778 756C F835 9678 77", "indent": 7, "expert": true },
|
||||
{ "text": "End of Public keys", "indent": 4, "expert": true },
|
||||
{ "text": "Mode info: ModeInfo object", "indent": 2, "expert": true },
|
||||
{ "text": "Multi: Multi object", "indent": 3, "expert": true },
|
||||
{ "text": "Bitarray: CompactBitArray object", "indent": 4, "expert": true },
|
||||
{ "text": "Extra bits stored: 5", "indent": 5, "expert": true },
|
||||
{ "text": "Elems: 48", "indent": 5, "expert": true },
|
||||
{ "text": "Mode infos: 2 ModeInfo", "indent": 4, "expert": true },
|
||||
{ "text": "Mode infos (1/2): ModeInfo object", "indent": 5, "expert": true },
|
||||
{ "text": "Single: Single object", "indent": 6, "expert": true },
|
||||
{ "text": "Mode: SIGN_MODE_LEGACY_AMINO_JSON", "indent": 7, "expert": true },
|
||||
{ "text": "Mode infos (2/2): ModeInfo object", "indent": 5, "expert": true },
|
||||
{ "text": "Single: Single object", "indent": 6, "expert": true },
|
||||
{ "text": "Mode: SIGN_MODE_LEGACY_AMINO_JSON", "indent": 7, "expert": true },
|
||||
{ "text": "End of Mode infos", "indent": 4, "expert": true },
|
||||
{ "text": "Sequence: 5", "indent": 2, "expert": true },
|
||||
{ "text": "End of Other signer", "expert": true },
|
||||
{ "text": "Extension options: 1 Any", "expert": true },
|
||||
{ "text": "Extension options (1/1): /cosmos.base.v1beta1.Coin", "indent": 1, "expert": true },
|
||||
{ "text": "5 ATOM", "indent": 2, "expert": true },
|
||||
{ "text": "End of Extension options", "expert": true },
|
||||
{ "text": "Non critical extension options: 1 Any", "expert": true },
|
||||
{ "text": "Non critical extension options (1/1): /cosmos.auth.v1beta1.Params", "indent": 1, "expert": true },
|
||||
{ "text": "Params object", "indent": 2, "expert": true },
|
||||
{ "text": "Max memo characters: 10", "indent": 3, "expert": true },
|
||||
{ "text": "End of Non critical extension options", "expert": true },
|
||||
{ "text": "Hash of raw bytes: 7ea02e8f0baed2db969e2d9ae4dc51fa31116259bd42897588072faf0ebb4d2e", "expert": true }
|
||||
{ "content": "End of Message" },
|
||||
{ "title": "Memo", "content": "> ⚛️\\u269B⚛️ " },
|
||||
{ "title": "Fees", "content": "0.002 ATOM" },
|
||||
{ "title": "Fee payer", "content": "cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t", "expert": true },
|
||||
{ "title": "Fee granter", "content": "cosmos1ulav3hsenupswqfkw2y3sup5kgtqwnvqa8eyhs", "expert": true },
|
||||
{ "title": "Tip", "content": "0.02 ATOM, 30'000 uosmo" },
|
||||
{ "title": "Tipper", "content": "cosmos1ejrf4cur2wy6kfurg9f2jppp2h3afe5h6pkh5t" },
|
||||
{ "title": "Gas limit", "content": "100'000", "expert": true },
|
||||
{ "title": "Timeout height", "content": "20", "expert": true },
|
||||
{ "title": "Other signer", "content": "1 SignerInfo", "expert": true },
|
||||
{ "title": "Other signer (1/1)", "content": "SignerInfo object", "indent": 1, "expert": true },
|
||||
{ "title": "Public key", "content": "/cosmos.crypto.multisig.LegacyAminoPubKey", "indent": 2, "expert": true },
|
||||
{ "content": "LegacyAminoPubKey object", "indent": 3, "expert": true },
|
||||
{ "title": "Threshold", "content": "2", "indent": 4, "expert": true },
|
||||
{ "title": "Public keys", "content": "2 Any", "indent": 4, "expert": true },
|
||||
{ "title": "Public keys (1/2)", "content": "/cosmos.crypto.secp256k1.PubKey", "indent": 5, "expert": true },
|
||||
{ "content": "PubKey object", "indent": 6, "expert": true },
|
||||
{ "title": "Key", "content": "0257 4EBE 0BFC 754F 5967 3BA1 1B27 500F 9158 ADE2 E17E 1A01 82B0 CA8B C652 4DB0 93", "indent": 7, "expert": true },
|
||||
{ "title": "Public keys (2/2)", "content": "/cosmos.crypto.ed25519.PubKey", "indent": 5, "expert": true },
|
||||
{ "content": "PubKey object", "indent": 6, "expert": true },
|
||||
{ "title": "Key", "content": "0315 0C47 F18A A327 16A6 547E DA8B 7369 067D CE11 D141 6245 B778 756C F835 9678 77", "indent": 7, "expert": true },
|
||||
{ "content": "End of Public keys", "indent": 4, "expert": true },
|
||||
{ "title": "Mode info", "content": "ModeInfo object", "indent": 2, "expert": true },
|
||||
{ "title": "Multi", "content": "Multi object", "indent": 3, "expert": true },
|
||||
{ "title": "Bitarray", "content": "CompactBitArray object", "indent": 4, "expert": true },
|
||||
{ "title": "Extra bits stored", "content": "5", "indent": 5, "expert": true },
|
||||
{ "title": "Elems", "content": "48", "indent": 5, "expert": true },
|
||||
{ "title": "Mode infos", "content": "2 ModeInfo", "indent": 4, "expert": true },
|
||||
{ "title": "Mode infos (1/2)", "content": "ModeInfo object", "indent": 5, "expert": true },
|
||||
{ "title": "Single", "content": "Single object", "indent": 6, "expert": true },
|
||||
{ "title": "Mode", "content": "SIGN_MODE_LEGACY_AMINO_JSON", "indent": 7, "expert": true },
|
||||
{ "title": "Mode infos (2/2)", "content": "ModeInfo object", "indent": 5, "expert": true },
|
||||
{ "title": "Single", "content": "Single object", "indent": 6, "expert": true },
|
||||
{ "title": "Mode", "content": "SIGN_MODE_LEGACY_AMINO_JSON", "indent": 7, "expert": true },
|
||||
{ "content": "End of Mode infos", "indent": 4, "expert": true },
|
||||
{ "title": "Sequence", "content": "5", "indent": 2, "expert": true },
|
||||
{ "content": "End of Other signer", "expert": true },
|
||||
{ "title": "Extension options", "content": "1 Any", "expert": true },
|
||||
{ "title": "Extension options (1/1)", "content": "/cosmos.base.v1beta1.Coin", "indent": 1, "expert": true },
|
||||
{ "content": "5 ATOM", "indent": 2, "expert": true },
|
||||
{ "content": "End of Extension options", "expert": true },
|
||||
{ "title": "Non critical extension options", "content": "1 Any", "expert": true },
|
||||
{ "title": "Non critical extension options (1/1)", "content": "/cosmos.auth.v1beta1.Params", "indent": 1, "expert": true },
|
||||
{ "content": "Params object", "indent": 2, "expert": true },
|
||||
{ "title": "Max memo characters", "content": "10", "indent": 3, "expert": true },
|
||||
{ "content": "End of Non critical extension options", "expert": true },
|
||||
{ "title": "Hash of raw bytes", "content": "7ea02e8f0baed2db969e2d9ae4dc51fa31116259bd42897588072faf0ebb4d2e", "expert": true }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -42,7 +42,7 @@ func (mr *messageValueRenderer) Format(ctx context.Context, v protoreflect.Value
|
||||
}
|
||||
|
||||
screens := make([]Screen, 1)
|
||||
screens[0].Text = mr.header()
|
||||
screens[0].Content = mr.header()
|
||||
|
||||
for _, fd := range mr.fds {
|
||||
if !v.Message().Has(fd) {
|
||||
@ -76,17 +76,19 @@ func (mr *messageValueRenderer) Format(ctx context.Context, v protoreflect.Value
|
||||
}
|
||||
|
||||
headerScreen := Screen{
|
||||
Text: fmt.Sprintf("%s: %s", toSentenceCase(string(fd.Name())), subscreens[0].Text),
|
||||
Indent: subscreens[0].Indent + 1,
|
||||
Expert: subscreens[0].Expert,
|
||||
Title: toSentenceCase(string(fd.Name())),
|
||||
Content: subscreens[0].Content,
|
||||
Indent: subscreens[0].Indent + 1,
|
||||
Expert: subscreens[0].Expert,
|
||||
}
|
||||
screens = append(screens, headerScreen)
|
||||
|
||||
for i := 1; i < len(subscreens); i++ {
|
||||
extraScreen := Screen{
|
||||
Text: subscreens[i].Text,
|
||||
Indent: subscreens[i].Indent + 1,
|
||||
Expert: subscreens[i].Expert,
|
||||
Title: subscreens[i].Title,
|
||||
Content: subscreens[i].Content,
|
||||
Indent: subscreens[i].Indent + 1,
|
||||
Expert: subscreens[i].Expert,
|
||||
}
|
||||
screens = append(screens, extraScreen)
|
||||
}
|
||||
@ -108,7 +110,7 @@ func (mr *messageValueRenderer) formatRepeated(ctx context.Context, v protorefle
|
||||
|
||||
screens := make([]Screen, 1)
|
||||
// <field_name>: <int> <field_kind>
|
||||
screens[0].Text = fmt.Sprintf("%d %s", l.Len(), toSentenceCase(getKind(fd)))
|
||||
screens[0].Content = fmt.Sprintf("%d %s", l.Len(), toSentenceCase(getKind(fd)))
|
||||
|
||||
for i := 0; i < l.Len(); i++ {
|
||||
subscreens, err := vr.Format(ctx, l.Get(i))
|
||||
@ -121,19 +123,22 @@ func (mr *messageValueRenderer) formatRepeated(ctx context.Context, v protorefle
|
||||
}
|
||||
|
||||
headerScreen := Screen{
|
||||
// <field_name> (<int>/<int>): <value rendered 1st line>
|
||||
Text: fmt.Sprintf("%s (%d/%d): %s", toSentenceCase(string(fd.Name())), i+1, l.Len(), subscreens[0].Text),
|
||||
Indent: subscreens[0].Indent + 1,
|
||||
Expert: subscreens[0].Expert,
|
||||
// <field_name> (<int>/<int>)
|
||||
Title: fmt.Sprintf("%s (%d/%d)", toSentenceCase(string(fd.Name())), i+1, l.Len()),
|
||||
// <value rendered 1st line>
|
||||
Content: subscreens[0].Content,
|
||||
Indent: subscreens[0].Indent + 1,
|
||||
Expert: subscreens[0].Expert,
|
||||
}
|
||||
screens = append(screens, headerScreen)
|
||||
|
||||
// <optional value rendered in the next lines>
|
||||
for i := 1; i < len(subscreens); i++ {
|
||||
extraScreen := Screen{
|
||||
Text: subscreens[i].Text,
|
||||
Indent: subscreens[i].Indent + 1,
|
||||
Expert: subscreens[i].Expert,
|
||||
Title: subscreens[i].Title,
|
||||
Content: subscreens[i].Content,
|
||||
Indent: subscreens[i].Indent + 1,
|
||||
Expert: subscreens[i].Expert,
|
||||
}
|
||||
screens = append(screens, extraScreen)
|
||||
}
|
||||
@ -141,7 +146,7 @@ func (mr *messageValueRenderer) formatRepeated(ctx context.Context, v protorefle
|
||||
|
||||
// End of <field_name>
|
||||
terminalScreen := Screen{
|
||||
Text: fmt.Sprintf("End of %s", toSentenceCase(string(fd.Name()))),
|
||||
Content: fmt.Sprintf("End of %s", toSentenceCase(string(fd.Name()))),
|
||||
}
|
||||
screens = append(screens, terminalScreen)
|
||||
return screens, nil
|
||||
@ -177,8 +182,8 @@ func (mr *messageValueRenderer) Parse(ctx context.Context, screens []Screen) (pr
|
||||
}
|
||||
|
||||
wantHeader := fmt.Sprintf("%s object", mr.msgDesc.Name())
|
||||
if screens[0].Text != wantHeader {
|
||||
return nilValue, fmt.Errorf(`bad header: want "%s", got "%s"`, wantHeader, screens[0].Text)
|
||||
if screens[0].Content != wantHeader {
|
||||
return nilValue, fmt.Errorf(`bad header: want "%s", got "%s"`, wantHeader, screens[0].Title)
|
||||
}
|
||||
if screens[0].Indent != 0 {
|
||||
return nilValue, fmt.Errorf("bad message indentation: want 0, got %d", screens[0].Indent)
|
||||
@ -206,8 +211,8 @@ func (mr *messageValueRenderer) Parse(ctx context.Context, screens []Screen) (pr
|
||||
return nilValue, fmt.Errorf("bad message indentation: want 1, got %d", screens[idx].Indent)
|
||||
}
|
||||
|
||||
prefix := toSentenceCase(string(fd.Name())) + ": "
|
||||
if !strings.HasPrefix(screens[idx].Text, prefix) {
|
||||
expectedTitle := toSentenceCase(string(fd.Name()))
|
||||
if screens[idx].Title != expectedTitle {
|
||||
// we must have skipped this fd because of a default value
|
||||
continue
|
||||
}
|
||||
@ -215,7 +220,8 @@ func (mr *messageValueRenderer) Parse(ctx context.Context, screens []Screen) (pr
|
||||
// Make a new screen without the prefix
|
||||
subscreens := make([]Screen, 1)
|
||||
subscreens[0] = screens[idx]
|
||||
subscreens[0].Text = strings.TrimPrefix(screens[idx].Text, prefix)
|
||||
subscreens[0].Title = screens[idx].Title
|
||||
subscreens[0].Content = screens[idx].Content
|
||||
subscreens[0].Indent--
|
||||
idx++
|
||||
|
||||
@ -256,10 +262,9 @@ func (mr *messageValueRenderer) Parse(ctx context.Context, screens []Screen) (pr
|
||||
}
|
||||
|
||||
func (mr *messageValueRenderer) parseRepeated(ctx context.Context, screens []Screen, l protoreflect.List, vr ValueRenderer) error {
|
||||
|
||||
// <int> <field_kind>
|
||||
headerRegex := *regexp.MustCompile(`(\d+) .+`)
|
||||
res := headerRegex.FindAllStringSubmatch(screens[0].Text, -1)
|
||||
res := headerRegex.FindAllStringSubmatch(screens[0].Content, -1)
|
||||
|
||||
if res == nil {
|
||||
return errors.New("failed to match <int> <field_kind>")
|
||||
@ -276,8 +281,8 @@ func (mr *messageValueRenderer) parseRepeated(ctx context.Context, screens []Scr
|
||||
elementIndex := 1
|
||||
|
||||
// <field_name> (<int>/<int>): <value rendered 1st line>
|
||||
elementRegex := regexp.MustCompile(`(.+) \(\d+\/\d+\): (.+)`)
|
||||
elementRes := elementRegex.FindAllStringSubmatch(screens[idx].Text, -1)
|
||||
elementRegex := regexp.MustCompile(`(.+) \(\d+\/\d+\)`)
|
||||
elementRes := elementRegex.FindAllStringSubmatch(screens[idx].Title, -1)
|
||||
if elementRes == nil {
|
||||
return errors.New("element malformed")
|
||||
}
|
||||
@ -288,7 +293,7 @@ func (mr *messageValueRenderer) parseRepeated(ctx context.Context, screens []Scr
|
||||
// Make a new screen without the prefix
|
||||
subscreens := make([]Screen, 1)
|
||||
subscreens[0] = screens[idx]
|
||||
subscreens[0].Text = strings.TrimPrefix(screens[idx].Text, prefix)
|
||||
subscreens[0].Content = strings.TrimPrefix(screens[idx].Content, prefix)
|
||||
subscreens[0].Indent--
|
||||
idx++
|
||||
|
||||
|
||||
@ -7,13 +7,14 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
|
||||
"cosmossdk.io/x/tx/textual"
|
||||
"cosmossdk.io/x/tx/textual/internal/testpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
)
|
||||
|
||||
func EmptyCoinMetadataQuerier(ctx context.Context, denom string) (*bankv1beta1.Metadata, error) {
|
||||
@ -47,7 +48,8 @@ func TestMessageJsonTestcases(t *testing.T) {
|
||||
msg := val.Message().Interface()
|
||||
require.IsType(t, &testpb.Foo{}, msg)
|
||||
foo := msg.(*testpb.Foo)
|
||||
require.True(t, proto.Equal(foo, tc.Proto))
|
||||
diff := cmp.Diff(foo, tc.Proto, protocmp.Transform())
|
||||
require.Empty(t, diff)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,10 +18,6 @@ import (
|
||||
type repeatedJsonTest struct {
|
||||
Proto *testpb.Qux
|
||||
Screens []textual.Screen
|
||||
// TODO Remove once we finished all primitive value renderers parsing
|
||||
// https://github.com/cosmos/cosmos-sdk/pull/13696
|
||||
// https://github.com/cosmos/cosmos-sdk/pull/13853
|
||||
Parses bool
|
||||
}
|
||||
|
||||
func TestRepeatedJsonTestcases(t *testing.T) {
|
||||
@ -45,14 +41,12 @@ func TestRepeatedJsonTestcases(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.Screens, screens)
|
||||
|
||||
if tc.Parses {
|
||||
val, err := rend.Parse(context.Background(), screens)
|
||||
require.NoError(t, err)
|
||||
msg := val.Message().Interface()
|
||||
require.IsType(t, &testpb.Qux{}, msg)
|
||||
baz := msg.(*testpb.Qux)
|
||||
require.True(t, proto.Equal(baz, tc.Proto))
|
||||
}
|
||||
val, err := rend.Parse(context.Background(), screens)
|
||||
require.NoError(t, err)
|
||||
msg := val.Message().Interface()
|
||||
require.IsType(t, &testpb.Qux{}, msg)
|
||||
baz := msg.(*testpb.Qux)
|
||||
require.True(t, proto.Equal(baz, tc.Proto))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,12 +16,12 @@ func NewStringValueRenderer() ValueRenderer {
|
||||
}
|
||||
|
||||
func (sr stringValueRenderer) Format(_ context.Context, v protoreflect.Value) ([]Screen, error) {
|
||||
return []Screen{{Text: v.String()}}, nil
|
||||
return []Screen{{Content: v.String()}}, nil
|
||||
}
|
||||
|
||||
func (sr stringValueRenderer) Parse(_ context.Context, screens []Screen) (protoreflect.Value, error) {
|
||||
if len(screens) != 1 {
|
||||
return protoreflect.Value{}, fmt.Errorf("expected single screen: %v", screens)
|
||||
}
|
||||
return protoreflect.ValueOfString(screens[0].Text), nil
|
||||
return protoreflect.ValueOfString(screens[0].Content), nil
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ func TestStringJsonTestcases(t *testing.T) {
|
||||
screens, err := rend.Format(context.Background(), protoreflect.ValueOfString(tc.Text))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, tc.Text, screens[0].Text)
|
||||
require.Equal(t, tc.Text, screens[0].Content)
|
||||
|
||||
val, err := rend.Parse(context.Background(), screens)
|
||||
require.NoError(t, err)
|
||||
@ -48,7 +48,7 @@ func TestStringHighUnicode(t *testing.T) {
|
||||
screens, err := rend.Format(context.Background(), protoreflect.ValueOfString(s))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, s, screens[0].Text)
|
||||
require.Equal(t, s, screens[0].Content)
|
||||
val, err := rend.Parse(context.Background(), screens)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, s, val.String())
|
||||
|
||||
@ -32,7 +32,7 @@ func (vr timestampValueRenderer) Format(_ context.Context, v protoreflect.Value)
|
||||
|
||||
// Format the Go Time as RFC 3339.
|
||||
s := t.Format(time.RFC3339Nano)
|
||||
return []Screen{{Text: s}}, nil
|
||||
return []Screen{{Content: s}}, nil
|
||||
}
|
||||
|
||||
// Parse implements the ValueRenderer interface.
|
||||
@ -41,7 +41,7 @@ func (vr timestampValueRenderer) Parse(_ context.Context, screens []Screen) (pro
|
||||
if len(screens) != 1 {
|
||||
return protoreflect.Value{}, fmt.Errorf("expected single screen: %v", screens)
|
||||
}
|
||||
t, err := time.Parse(time.RFC3339Nano, screens[0].Text)
|
||||
t, err := time.Parse(time.RFC3339Nano, screens[0].Content)
|
||||
if err != nil {
|
||||
return protoreflect.Value{}, err
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ func TestTimestampJsonTestcases(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(screens))
|
||||
require.Equal(t, tc.Text, screens[0].Text)
|
||||
require.Equal(t, tc.Text, screens[0].Content)
|
||||
}
|
||||
|
||||
val, err := rend.Parse(context.Background(), screens)
|
||||
|
||||
@ -8,7 +8,6 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
@ -22,7 +21,7 @@ import (
|
||||
|
||||
var (
|
||||
// msgRe is a regex matching the beginning of the TxBody msgs in the envelope.
|
||||
msgRe = regexp.MustCompile("Message: ([0-9]+) Any")
|
||||
msgRe = regexp.MustCompile("([0-9]+) Any")
|
||||
// inverseMsgRe is a regex matching the textual output of the TxBody msgs
|
||||
// header.
|
||||
inverseMsgRe = regexp.MustCompile("This transaction has ([0-9]+) Messages?")
|
||||
@ -138,23 +137,26 @@ func (vr txValueRenderer) Format(ctx context.Context, v protoreflect.Value) ([]S
|
||||
for i := range screens {
|
||||
if screens[i].Indent == 0 {
|
||||
// Do expert fields.
|
||||
screenKV := strings.Split(screens[i].Text, ": ")
|
||||
_, ok := expert[screenKV[0]]
|
||||
_, ok := expert[screens[i].Title]
|
||||
if ok {
|
||||
expertify(screens, i, screenKV[0])
|
||||
expertify(screens, i, screens[i].Title)
|
||||
}
|
||||
|
||||
// Replace:
|
||||
// "Message: <N> Any"
|
||||
// with:
|
||||
// "This transaction has <N> Message"
|
||||
matches := msgRe.FindStringSubmatch(screens[i].Text)
|
||||
if len(matches) > 0 {
|
||||
screens[i].Text = fmt.Sprintf("This transaction has %s Message", matches[1])
|
||||
if matches[1] != "1" {
|
||||
screens[i].Text += "s"
|
||||
if screens[i].Title == "Message" {
|
||||
matches := msgRe.FindStringSubmatch(screens[i].Content)
|
||||
if len(matches) > 0 {
|
||||
screens[i].Title = ""
|
||||
screens[i].Content = fmt.Sprintf("This transaction has %s Message", matches[1])
|
||||
if matches[1] != "1" {
|
||||
screens[i].Content += "s"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,7 +170,7 @@ func expertify(screens []Screen, fromIdx int, fieldName string) {
|
||||
for i := fromIdx; i < len(screens); i++ {
|
||||
if i > fromIdx &&
|
||||
screens[i].Indent == 0 &&
|
||||
screens[i].Text != fmt.Sprintf("End of %s", fieldName) {
|
||||
screens[i].Content != fmt.Sprintf("End of %s", fieldName) {
|
||||
break
|
||||
}
|
||||
|
||||
@ -198,7 +200,7 @@ func getHash(bodyBz, authInfoBz []byte) string {
|
||||
func (vr txValueRenderer) Parse(ctx context.Context, screens []Screen) (protoreflect.Value, error) {
|
||||
// Process the screens to be parsable by a envelope message value renderer
|
||||
parsable := make([]Screen, len(screens)+1)
|
||||
parsable[0] = Screen{Text: "Envelope object"}
|
||||
parsable[0] = Screen{Content: "Envelope object"}
|
||||
for i := range screens {
|
||||
parsable[i+1].Indent = screens[i].Indent + 1
|
||||
|
||||
@ -206,11 +208,13 @@ func (vr txValueRenderer) Parse(ctx context.Context, screens []Screen) (protoref
|
||||
// "This transaction has <N> Message"
|
||||
// with:
|
||||
// "Message: <N> Any"
|
||||
matches := inverseMsgRe.FindStringSubmatch(screens[i].Text)
|
||||
matches := inverseMsgRe.FindStringSubmatch(screens[i].Content)
|
||||
if len(matches) > 0 {
|
||||
parsable[i+1].Text = fmt.Sprintf("Message: %s Any", matches[1])
|
||||
parsable[i+1].Title = "Message"
|
||||
parsable[i+1].Content = fmt.Sprintf("%s Any", matches[1])
|
||||
} else {
|
||||
parsable[i+1].Text = screens[i].Text
|
||||
parsable[i+1].Title = screens[i].Title
|
||||
parsable[i+1].Content = screens[i].Content
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,14 @@ import (
|
||||
|
||||
// Screen is the abstract unit of Textual rendering.
|
||||
type Screen struct {
|
||||
// Text is the text to display - a sequence of Unicode code points.
|
||||
Text string
|
||||
// Title is the text (sequence of Unicode code points) to display first,
|
||||
// generally on the device's title section. It can be empty.
|
||||
Title string
|
||||
|
||||
// Content is the text (sequence of Unicode code points) to display after
|
||||
// the Title, generally on the device's content section. It must be
|
||||
// non-empty.
|
||||
Content string
|
||||
|
||||
// Indent is the indentation level of the screen.
|
||||
// Zero indicates top-level. Should be less than 16.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user