-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
stellar_common.go
171 lines (160 loc) · 5.08 KB
/
stellar_common.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package client
import (
"fmt"
"os"
"strings"
"github.com/keybase/client/go/stellar"
"github.com/keybase/client/go/terminalescaper"
isatty "github.com/mattn/go-isatty"
"golang.org/x/net/context"
"github.com/keybase/client/go/libkb"
"github.com/keybase/client/go/protocol/stellar1"
)
func printPayment(g *libkb.GlobalContext, p stellar1.PaymentCLILocal, verbose, details bool, dui libkb.DumbOutputUI) {
lineUnescaped := func(format string, args ...interface{}) {
_, _ = dui.PrintfUnescaped(format+"\n", args...)
}
line := func(format string, args ...interface{}) {
dui.Printf(format+"\n", args...)
}
timeStr := p.Time.Time().Format("2006/01/02 15:04")
if p.Unread {
timeStr += " *"
}
lineUnescaped(ColorString(g, "bold", timeStr))
if details {
if p.PublicNote != "" {
line("Memo: %s (%s)", p.PublicNote, p.PublicNoteType)
}
line("Fee charged: %s", p.FeeChargedDescription)
}
if p.IsAdvanced {
line("Account: %s", p.FromStellar.String())
line("Transaction ID: %v", p.TxID)
line(p.SummaryAdvanced)
if verbose {
line("Operations: %d", len(p.Operations))
for _, op := range p.Operations {
line("\t%s", op)
}
}
return
}
// if path payment, show the source asset amount
if p.SourceAmountActual != "" {
sourceAmount, err := stellar.FormatAmountDescriptionAssetEx(libkb.NewMetaContext(context.Background(), g), p.SourceAmountActual, p.SourceAsset)
if err != nil {
lineUnescaped("%v %s", ColorString(g, "red", "Error while formatting amount:"), err)
} else {
lineUnescaped("%v", ColorString(g, "yellow", sourceAmount))
}
}
// destination amount, asset
amount, err := stellar.FormatAmountDescriptionAssetEx(libkb.NewMetaContext(context.Background(), g), p.Amount, p.Asset)
if err == nil {
if p.DisplayAmount != nil && p.DisplayCurrency != nil && len(*p.DisplayAmount) > 0 && len(*p.DisplayAmount) > 0 {
amount = fmt.Sprintf("%v %v (%v)", *p.DisplayAmount, *p.DisplayCurrency, amount)
}
} else {
lineUnescaped("%v %s", ColorString(g, "red", "Error while formatting amount:"), err)
}
lineUnescaped("%v", ColorString(g, "green", amount))
// Show sender and recipient. Prefer keybase form, fall back to stellar abbreviations.
var showedAbbreviation bool
var from string
switch {
case p.FromUsername != nil:
from = *p.FromUsername
default:
from = p.FromStellar.LossyAbbreviation()
showedAbbreviation = true
}
var to string
switch {
case p.ToUsername != nil && p.ToAssertion != nil && (*p.ToUsername != *p.ToAssertion):
to = fmt.Sprintf("%s (%q)", *p.ToUsername, *p.ToAssertion)
case p.ToUsername != nil:
to = *p.ToUsername
case p.ToStellar != nil:
to = p.ToStellar.LossyAbbreviation()
showedAbbreviation = true
case p.ToAssertion != nil:
to = fmt.Sprintf("%q", *p.ToAssertion)
default:
// This should never happen
lineUnescaped("%v", ColorString(g, "red", "missing recipient info"))
}
line("%v -> %v", from, to)
if showedAbbreviation || verbose {
// If an abbreviation was shown, show the full addresses. We could skip
// the "%v -> %v" line above if both `to` and `from` are address IDs,
// because we are printing full IDs anyway, but it serves an important
// purpose of telling user that that the entire transfer happened
// outside of Keybase.
line("From: %v", p.FromStellar.String())
if p.ToStellar != nil {
line("To: %v", p.ToStellar.String())
} else {
lineUnescaped("To: %v", ColorString(g, "yellow", "unclaimed"))
}
}
if g.Env.GetDisplayRawUntrustedOutput() || !isatty.IsTerminal(os.Stdout.Fd()) {
if len(p.Note) > 0 {
lineUnescaped("Note: %v", ColorString(g, "yellow", printPaymentFilterNote(p.Note)))
}
if len(p.NoteErr) > 0 {
lineUnescaped("Note Error: %v", ColorString(g, "red", p.NoteErr))
}
} else {
if len(p.Note) > 0 {
lineUnescaped("Note: %v", ColorString(g, "yellow", printPaymentFilterNote(terminalescaper.Clean(p.Note))))
}
if len(p.NoteErr) > 0 {
lineUnescaped("Note Error: %v", ColorString(g, "red", terminalescaper.Clean(p.NoteErr)))
}
}
if verbose {
line("Transaction ID: %v", p.TxID)
}
switch {
case p.Status == "":
case strings.EqualFold(p.Status, "completed"):
default:
color := "red"
if strings.EqualFold(p.Status, "claimable") {
color = "yellow"
}
lineUnescaped("Status: %v", ColorString(g, color, p.Status))
lineUnescaped(" %v", ColorString(g, color, p.StatusDetail))
}
}
// printPaymentFilterNote: Pare down the note so that it's less likely to contain tricks.
// Such as newlines and fake transactions.
// Shows only the first line.
func printPaymentFilterNote(note string) string {
lines := strings.Split(strings.TrimSpace(note), "\n")
if len(lines) < 1 {
return ""
}
return strings.TrimSpace(lines[0])
}
func transformStellarCLIError(err *error) {
if err == nil {
return
}
if *err == nil {
return
}
switch e := (*err).(type) {
case libkb.AppStatusError:
if e.Code == libkb.SCStellarNeedDisclaimer {
*err = libkb.NewAppStatusError(&libkb.AppStatus{
Code: e.Code,
Name: e.Name,
Desc: "Stellar disclaimer not yet accepted. Run 'keybase wallet get-started'",
})
}
default:
// Nothing to do for other errors.
}
}