mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
signer: refactor formatting and UI
This commit is contained in:
parent
2763dd41d6
commit
5f45cdc9fb
2 changed files with 103 additions and 52 deletions
|
|
@ -425,7 +425,6 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
|
||||||
buffer.Write(bytesValue)
|
buffer.Write(bytesValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.Bytes(), nil
|
return buffer.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -609,87 +608,109 @@ func (typedData *TypedData) Map() map[string]interface{} {
|
||||||
// of clef present data in their apps
|
// of clef present data in their apps
|
||||||
func (typedData *TypedData) PrettyPrint() string {
|
func (typedData *TypedData) PrettyPrint() string {
|
||||||
output := bytes.Buffer{}
|
output := bytes.Buffer{}
|
||||||
|
formatted := typedData.Format()
|
||||||
output.WriteString(fmt.Sprintf("%s {\n", "Domain"))
|
for _, item := range formatted {
|
||||||
output.WriteString(typedData.PrettyPrintData("EIP712Domain", typedData.Domain.Map(), 1))
|
output.WriteString(fmt.Sprintf("%v\n", item.Pprint(0)))
|
||||||
output.Truncate(output.Len() - 2)
|
}
|
||||||
output.WriteString(fmt.Sprintf("\n}\n"))
|
|
||||||
|
|
||||||
output.WriteString(fmt.Sprintf("%s {\n", typedData.PrimaryType))
|
|
||||||
output.WriteString(typedData.PrettyPrintData(typedData.PrimaryType, typedData.Message, 1))
|
|
||||||
output.Truncate(output.Len() - 2)
|
|
||||||
output.WriteString(fmt.Sprintf("\n}"))
|
|
||||||
|
|
||||||
return output.String()
|
return output.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrettyPrintData generates a formatted output for the
|
// Format returns a representation of d, which can be easily displayed by a user-interface
|
||||||
// given data
|
// without in-depth knowledge about 712 rules
|
||||||
func (typedData *TypedData) PrettyPrintData(primaryType string, data map[string]interface{}, depth int) string {
|
func (typedData *TypedData) Format() []*NameValueType {
|
||||||
output := bytes.Buffer{}
|
var nvts []*NameValueType
|
||||||
|
nvts = append(nvts, &NameValueType{
|
||||||
|
Name: "EIP712Domain",
|
||||||
|
Value: typedData.formatData("EIP712Domain", typedData.Domain.Map()),
|
||||||
|
Typ: "domain",
|
||||||
|
})
|
||||||
|
nvts = append(nvts, &NameValueType{
|
||||||
|
Name: typedData.PrimaryType,
|
||||||
|
Value: typedData.formatData(typedData.PrimaryType, typedData.Message),
|
||||||
|
Typ: "primary type",
|
||||||
|
})
|
||||||
|
return nvts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (typedData *TypedData) formatData(primaryType string, data map[string]interface{}) []*NameValueType {
|
||||||
|
var output []*NameValueType
|
||||||
|
|
||||||
// Add field contents. Structs and arrays have special handlers.
|
// Add field contents. Structs and arrays have special handlers.
|
||||||
for _, field := range typedData.Types[primaryType] {
|
for _, field := range typedData.Types[primaryType] {
|
||||||
encType := field["type"]
|
encType := field["type"]
|
||||||
encName := field["name"]
|
encName := field["name"]
|
||||||
encValue := data[encName]
|
encValue := data[encName]
|
||||||
|
item := &NameValueType{
|
||||||
|
Name: encName,
|
||||||
|
Typ: encType,
|
||||||
|
}
|
||||||
if encType[len(encType)-1:] == "]" {
|
if encType[len(encType)-1:] == "]" {
|
||||||
arrayValue, _ := encValue.([]interface{})
|
arrayValue, _ := encValue.([]interface{})
|
||||||
parsedType := strings.Split(encType, "[")[0]
|
parsedType := strings.Split(encType, "[")[0]
|
||||||
for _, item := range arrayValue {
|
for _, v := range arrayValue {
|
||||||
if typedData.Types[parsedType] != nil {
|
if typedData.Types[parsedType] != nil {
|
||||||
mapValue, _ := item.(map[string]interface{})
|
mapValue, _ := v.(map[string]interface{})
|
||||||
mapOutput := typedData.PrettyPrintData(parsedType, mapValue, depth+1)
|
mapOutput := typedData.formatData(parsedType, mapValue)
|
||||||
output.WriteString(mapOutput)
|
item.Value = mapOutput
|
||||||
} else {
|
} else {
|
||||||
primitiveOutput := typedData.PrettyPrintPrimitiveValue(encType, encName, encValue, depth)
|
primitiveOutput := formatPrimitiveValue(encType, encValue)
|
||||||
output.WriteString(primitiveOutput)
|
item.Value = primitiveOutput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if typedData.Types[field["type"]] != nil {
|
} else if typedData.Types[field["type"]] != nil {
|
||||||
output.WriteString(strings.Repeat("\u00a0", depth*2))
|
|
||||||
output.WriteString(fmt.Sprintf("\"%s\": { %s\n", field["name"], encType))
|
|
||||||
|
|
||||||
mapValue, _ := encValue.(map[string]interface{})
|
mapValue, _ := encValue.(map[string]interface{})
|
||||||
mapOutput := typedData.PrettyPrintData(field["type"], mapValue, depth+1)
|
mapOutput := typedData.formatData(field["type"], mapValue)
|
||||||
output.WriteString(mapOutput)
|
item.Value = mapOutput
|
||||||
|
|
||||||
output.Truncate(output.Len() - 2)
|
|
||||||
output.WriteString(fmt.Sprintf("\n%s},\n", strings.Repeat("\u00a0", depth*2)))
|
|
||||||
} else {
|
} else {
|
||||||
primitiveOutput := typedData.PrettyPrintPrimitiveValue(encType, encName, encValue, depth)
|
primitiveOutput := formatPrimitiveValue(encType, encValue)
|
||||||
output.WriteString(primitiveOutput)
|
item.Value = primitiveOutput
|
||||||
}
|
}
|
||||||
|
output = append(output, item)
|
||||||
|
}
|
||||||
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
return output.String()
|
func formatPrimitiveValue(encType string, encValue interface{}) string {
|
||||||
}
|
|
||||||
|
|
||||||
// PrettyPrintPrimitiveValue generates a formatted output for the
|
|
||||||
// given primitive value
|
|
||||||
func (typedData *TypedData) PrettyPrintPrimitiveValue(encType string, encName string, encValue interface{}, depth int) string {
|
|
||||||
output := bytes.Buffer{}
|
|
||||||
output.WriteString(strings.Repeat("\u00a0", depth*2))
|
|
||||||
output.WriteString(fmt.Sprintf("\"%s\": ", encName))
|
|
||||||
|
|
||||||
switch encType {
|
switch encType {
|
||||||
case "address":
|
case "address":
|
||||||
stringValue, _ := encValue.(string)
|
stringValue, _ := encValue.(string)
|
||||||
addressValue := common.HexToAddress(stringValue)
|
return common.HexToAddress(stringValue).String()
|
||||||
output.WriteString(fmt.Sprintf("%s,\n", addressValue.String()))
|
|
||||||
case "bool":
|
case "bool":
|
||||||
boolValue, _ := encValue.(bool)
|
boolValue, _ := encValue.(bool)
|
||||||
output.WriteString(fmt.Sprintf("%t,\n", boolValue))
|
return fmt.Sprintf("%t", boolValue)
|
||||||
case "bytes", "string":
|
case "bytes", "string":
|
||||||
output.WriteString(fmt.Sprintf("\"%s\",\n", encValue))
|
return fmt.Sprintf("%s", encValue)
|
||||||
default:
|
}
|
||||||
if strings.HasPrefix(encType, "bytes") {
|
if strings.HasPrefix(encType, "bytes") {
|
||||||
output.WriteString(fmt.Sprintf("\"%s\",\n", encValue))
|
return fmt.Sprintf("%s", encValue)
|
||||||
} else if strings.HasPrefix(encType, "uint") || strings.HasPrefix(encType, "int") {
|
} else if strings.HasPrefix(encType, "uint") || strings.HasPrefix(encType, "int") {
|
||||||
bigIntValue, _ := encValue.(*big.Int)
|
bigIntValue, _ := encValue.(*big.Int)
|
||||||
output.WriteString(fmt.Sprintf("%d,\n", bigIntValue))
|
return fmt.Sprintf("%d (0x%x)", bigIntValue, bigIntValue)
|
||||||
}
|
}
|
||||||
|
return "NA"
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameValueType is a very simple struct with Name, Value and Type. It's meant for simple
|
||||||
|
// json structures used to communicate signing-info about typed data with the UI
|
||||||
|
type NameValueType struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Value interface{} `json:"value"`
|
||||||
|
Typ string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pprint returns a pretty-printed version of nvt
|
||||||
|
func (nvt *NameValueType) Pprint(depth int) string {
|
||||||
|
output := bytes.Buffer{}
|
||||||
|
output.WriteString(strings.Repeat("\u00a0", depth*2))
|
||||||
|
output.WriteString(fmt.Sprintf("%s [%s]: ", nvt.Name, nvt.Typ))
|
||||||
|
if nvts, ok := nvt.Value.([]*NameValueType); ok {
|
||||||
|
output.WriteString("\n")
|
||||||
|
for _, next := range nvts {
|
||||||
|
sublevel := next.Pprint(depth + 1)
|
||||||
|
output.WriteString(sublevel)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.WriteString(fmt.Sprintf("%s\n", nvt.Value))
|
||||||
}
|
}
|
||||||
return output.String()
|
return output.String()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -598,3 +598,33 @@ func TestMalformedData4(t *testing.T) {
|
||||||
t.Fatalf("Expected no err, got %v", err)
|
t.Fatalf("Expected no err, got %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFormatter(t *testing.T) {
|
||||||
|
|
||||||
|
var d TypedData
|
||||||
|
err := json.Unmarshal([]byte(jsonTypedData), &d)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unmarshalling failed %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//x := PrettyPrintPrimitiveValue("address", "wallet", "0x123123123", 1)
|
||||||
|
//fmt.Printf(x)
|
||||||
|
//y := FormatPrimitiveValue("address", "wallet", "0x123123123")
|
||||||
|
//fmt.Printf("%v\n", y)
|
||||||
|
|
||||||
|
//fmt.Printf(d.PrettyPrintData(d.PrimaryType,d.Message, 1))
|
||||||
|
|
||||||
|
//formatted := d.FormatData(d.PrimaryType,d.Message)
|
||||||
|
//for _,item := range formatted{
|
||||||
|
// fmt.Printf("%v\n", item.Pprint(0))
|
||||||
|
//}
|
||||||
|
|
||||||
|
formatted := d.Format()
|
||||||
|
for _, item := range formatted {
|
||||||
|
fmt.Printf("%v\n", item.Pprint(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
j, _ := json.Marshal(formatted)
|
||||||
|
fmt.Printf("%v\n", string(j))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue