Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client-sdk/go/modules/consensusaccounts/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ type Undelegate struct {
}

// PrettyPrint writes a pretty-printed representation of the transaction to the given writer.
func (ud *Undelegate) PrettyPrint(_ context.Context, prefix string, w io.Writer) {
_, _ = fmt.Fprintf(w, "%sFrom: %s\n", prefix, ud.From)
func (ud *Undelegate) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
_, _ = fmt.Fprintf(w, "%sFrom: %s\n", prefix, types.FormatNamedAddress(ctx, ud.From))
_, _ = fmt.Fprintf(w, "%sShares: %s\n", prefix, ud.Shares)
}

Expand Down
41 changes: 41 additions & 0 deletions client-sdk/go/modules/consensusaccounts/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package consensusaccounts

import (
"bytes"
"context"
"encoding/hex"
"testing"

"github.com/stretchr/testify/require"

"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"

"github.com/oasisprotocol/oasis-core/go/common/quantity"
)

func TestUndelegatePrettyPrintFromNamedAddress(t *testing.T) {
require := require.New(t)

ethHex := "0x60a6321ea71d37102dbf923aae2e08d005c4e403"
ethBytes, err := hex.DecodeString(ethHex[2:])
require.NoError(err)

addr := types.NewAddressFromEth(ethBytes)
native := addr.String()

shares := *quantity.NewFromUint64(1234)

ctx := context.Background()
ctx = context.WithValue(ctx, types.ContextKeyAccountNames, types.AccountNames{native: "my"})
ctx = context.WithValue(ctx, types.ContextKeyAccountEthMap, map[string]string{native: ethHex})

ud := Undelegate{
From: addr,
Shares: shares,
}

var buf bytes.Buffer
ud.PrettyPrint(ctx, "", &buf)

require.Equal("From: my ("+ethHex+")\nShares: "+shares.String()+"\n", buf.String())
}
6 changes: 5 additions & 1 deletion client-sdk/go/types/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ var (

type contextKey string

// ContextKeyAccountNames is the key to retrieve the public key to account name map from context.
// ContextKeyAccountNames is the key to retrieve the native (Bech32) address string to account name map from context.
const ContextKeyAccountNames = contextKey("runtime/account-names")

// ContextKeyAccountEthMap is the key to retrieve a mapping from native (Bech32)
Comment thread
uniyalabhishek marked this conversation as resolved.
// Oasis addresses to their corresponding Ethereum hex addresses.
const ContextKeyAccountEthMap = contextKey("runtime/account-eth-map")
Comment thread
uniyalabhishek marked this conversation as resolved.

// AccountNames maps public key or address to user-defined account name for pretty printing.
type AccountNames map[string]string

Expand Down
64 changes: 57 additions & 7 deletions client-sdk/go/types/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,67 @@ func NewBaseUnits(amount quantity.Quantity, denomination Denomination) BaseUnits
}
}

// FormatNamedAddress is like FormatNamedAddressWith but reads the name and eth maps from ctx.
func FormatNamedAddress(ctx context.Context, addr Address) string {
Comment thread
uniyalabhishek marked this conversation as resolved.
Comment thread
uniyalabhishek marked this conversation as resolved.
var (
names AccountNames
ethMap map[string]string
)
if v, ok := ctx.Value(ContextKeyAccountNames).(AccountNames); ok {
names = v
}
if v, ok := ctx.Value(ContextKeyAccountEthMap).(map[string]string); ok {
ethMap = v
}

return FormatNamedAddressWith(names, ethMap, addr)
}

// FormatNamedAddressWith formats an address for display. Output cases:
// - Named + eth known: "name (0x...)"
// - Named + eth unknown: "name (oasis1...)"
// - Unnamed + eth known: "0x... (oasis1...)"
// - Unnamed + eth unknown: "oasis1..."
func FormatNamedAddressWith(names AccountNames, ethMap map[string]string, addr Address) string {
native := addr.String()

ethHex := ""
if ethMap != nil {
if hex := ethMap[native]; hex != "" {
ethHex = hex
}
}

name := ""
if names != nil {
name = names[native]
}

// Named address.
if name != "" {
preferred := native
if ethHex != "" {
preferred = ethHex
}
if name == preferred {
return preferred
}
return fmt.Sprintf("%s (%s)", name, preferred)
}

// Unnamed address.
if ethHex != "" {
return fmt.Sprintf("%s (%s)", ethHex, native)
}

return native
}

// PrettyPrintToAmount is a helper for printing To-Amount transaction bodies (e.g. transfer, deposit, withdraw).
func PrettyPrintToAmount(ctx context.Context, prefix string, w io.Writer, to *Address, amount BaseUnits) {
toStr := "Self"
if to != nil {
toStr = to.String()
an, ok := ctx.Value(ContextKeyAccountNames).(AccountNames)
if ok {
if name, ok := an[to.String()]; ok {
toStr = fmt.Sprintf("%s (%s)", name, to)
}
}
toStr = FormatNamedAddress(ctx, *to)
}
_, _ = fmt.Fprintf(w, "%sTo: %s\n", prefix, toStr)
_, _ = fmt.Fprintf(w, "%sAmount: ", prefix)
Expand Down
61 changes: 61 additions & 0 deletions client-sdk/go/types/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,70 @@ func TestPrettyPrintToAmount(t *testing.T) {
PrettyPrintToAmount(ctx, "", &buf, &to, amt)
require.Equal("To: test:dave (oasis1qrk58a6j2qn065m6p06jgjyt032f7qucy5wqeqpt)\nAmount: 50.0 TEST\n", buf.String())

// Unnamed address with eth mapping should display eth hex with native in parentheses.
buf.Reset()
ethHex := "0x60a6321eA71d37102Dbf923AAe2E08d005C4e403"
ethBytes, err2 := hex.DecodeString(ethHex[2:])
require.NoError(err2)
ethTo := NewAddressFromEth(ethBytes)
ctx2 := context.Background()
ctx2 = context.WithValue(ctx2, config.ContextKeyParaTimeCfg, ptCfg)
ctx2 = context.WithValue(ctx2, ContextKeyAccountEthMap, map[string]string{
ethTo.String(): ethHex,
})
PrettyPrintToAmount(ctx2, "", &buf, &ethTo, amt)
require.Equal("To: "+ethHex+" ("+ethTo.String()+")\nAmount: 50.0 TEST\n", buf.String())

// No ParaTime set. Amount cannot be correctly determined.
buf.Reset()
ctx = context.WithValue(ctx, config.ContextKeyParaTimeCfg, nil)
PrettyPrintToAmount(ctx, "", &buf, &to, amt)
require.Equal("To: test:dave (oasis1qrk58a6j2qn065m6p06jgjyt032f7qucy5wqeqpt)\nAmount: <error: ParaTime information not available>\n", buf.String())
}

func TestFormatNamedAddressWith(t *testing.T) {
require := require.New(t)

ethHex := "0x60a6321ea71d37102dbf923aae2e08d005c4e403"
ethBytes, err := hex.DecodeString(ethHex[2:])
require.NoError(err)

addr := NewAddressFromEth(ethBytes)
native := addr.String()

t.Run("unknown no eth returns native", func(_ *testing.T) {
require.Equal(native, FormatNamedAddressWith(nil, nil, addr))
require.Equal(native, FormatNamedAddressWith(AccountNames{}, map[string]string{}, addr))
})

t.Run("unknown with eth returns eth hex", func(_ *testing.T) {
ethMap := map[string]string{native: ethHex}
require.Equal(ethHex+" ("+native+")", FormatNamedAddressWith(nil, ethMap, addr))
require.Equal(ethHex+" ("+native+")", FormatNamedAddressWith(AccountNames{}, ethMap, addr))
})

t.Run("native fallback when eth unknown", func(_ *testing.T) {
names := AccountNames{native: "my"}
require.Equal("my ("+native+")", FormatNamedAddressWith(names, nil, addr))
require.Equal("my ("+native+")", FormatNamedAddressWith(names, map[string]string{}, addr))
require.Equal("my ("+native+")", FormatNamedAddressWith(names, map[string]string{native: ""}, addr))
})

t.Run("eth preferred when known", func(_ *testing.T) {
names := AccountNames{native: "my"}
ethMap := map[string]string{native: ethHex}
require.Equal("my ("+ethHex+")", FormatNamedAddressWith(names, ethMap, addr))
})

t.Run("name equals preferred yields preferred", func(_ *testing.T) {
names := AccountNames{native: native}
require.Equal(native, FormatNamedAddressWith(names, nil, addr))
})

t.Run("ctx wrapper reads maps", func(_ *testing.T) {
ctx := context.Background()
ctx = context.WithValue(ctx, ContextKeyAccountNames, AccountNames{native: "my"})
ctx = context.WithValue(ctx, ContextKeyAccountEthMap, map[string]string{native: ethHex})
require.Equal("my ("+ethHex+")", FormatNamedAddress(ctx, addr))
})
}
Loading