• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 15951470896

29 Jun 2025 04:23AM UTC coverage: 67.594% (-0.01%) from 67.606%
15951470896

Pull #9751

github

web-flow
Merge 599d9b051 into 6290edf14
Pull Request #9751: multi: update Go to 1.23.10 and update some packages

135088 of 199851 relevant lines covered (67.59%)

21909.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.47
/zpay32/amountunits.go
1
package zpay32
2

3
import (
4
        "fmt"
5
        "strconv"
6

7
        "github.com/lightningnetwork/lnd/lnwire"
8
)
9

10
var (
11
        // toMSat is a map from a unit to a function that converts an amount
12
        // of that unit to millisatoshis.
13
        toMSat = map[byte]func(uint64) (lnwire.MilliSatoshi, error){
14
                'm': mBtcToMSat,
15
                'u': uBtcToMSat,
16
                'n': nBtcToMSat,
17
                'p': pBtcToMSat,
18
        }
19

20
        // fromMSat is a map from a unit to a function that converts an amount
21
        // in millisatoshis to an amount of that unit.
22
        fromMSat = map[byte]func(lnwire.MilliSatoshi) (uint64, error){
23
                'm': mSatToMBtc,
24
                'u': mSatToUBtc,
25
                'n': mSatToNBtc,
26
                'p': mSatToPBtc,
27
        }
28
)
29

30
// mBtcToMSat converts the given amount in milliBTC to millisatoshis.
31
func mBtcToMSat(m uint64) (lnwire.MilliSatoshi, error) {
38✔
32
        return lnwire.MilliSatoshi(m) * 100000000, nil
38✔
33
}
38✔
34

35
// uBtcToMSat converts the given amount in microBTC to millisatoshis.
36
func uBtcToMSat(u uint64) (lnwire.MilliSatoshi, error) {
18✔
37
        return lnwire.MilliSatoshi(u * 100000), nil
18✔
38
}
18✔
39

40
// nBtcToMSat converts the given amount in nanoBTC to millisatoshis.
41
func nBtcToMSat(n uint64) (lnwire.MilliSatoshi, error) {
6✔
42
        return lnwire.MilliSatoshi(n * 100), nil
6✔
43
}
6✔
44

45
// pBtcToMSat converts the given amount in picoBTC to millisatoshis.
46
func pBtcToMSat(p uint64) (lnwire.MilliSatoshi, error) {
13✔
47
        if p < 10 {
15✔
48
                return 0, fmt.Errorf("minimum amount is 10p")
2✔
49
        }
2✔
50
        if p%10 != 0 {
14✔
51
                return 0, fmt.Errorf("amount %d pBTC not expressible in msat",
3✔
52
                        p)
3✔
53
        }
3✔
54
        return lnwire.MilliSatoshi(p / 10), nil
8✔
55
}
56

57
// mSatToMBtc converts the given amount in millisatoshis to milliBTC.
58
func mSatToMBtc(msat lnwire.MilliSatoshi) (uint64, error) {
138✔
59
        if msat%100000000 != 0 {
250✔
60
                return 0, fmt.Errorf("%d msat not expressible "+
112✔
61
                        "in mBTC", msat)
112✔
62
        }
112✔
63
        return uint64(msat / 100000000), nil
29✔
64
}
65

66
// mSatToUBtc converts the given amount in millisatoshis to microBTC.
67
func mSatToUBtc(msat lnwire.MilliSatoshi) (uint64, error) {
138✔
68
        if msat%100000 != 0 {
149✔
69
                return 0, fmt.Errorf("%d msat not expressible "+
11✔
70
                        "in uBTC", msat)
11✔
71
        }
11✔
72
        return uint64(msat / 100000), nil
130✔
73
}
74

75
// mSatToNBtc converts the given amount in millisatoshis to nanoBTC.
76
func mSatToNBtc(msat lnwire.MilliSatoshi) (uint64, error) {
138✔
77
        if msat%100 != 0 {
142✔
78
                return 0, fmt.Errorf("%d msat not expressible in nBTC", msat)
4✔
79
        }
4✔
80
        return uint64(msat / 100), nil
134✔
81
}
82

83
// mSatToPBtc converts the given amount in millisatoshis to picoBTC.
84
func mSatToPBtc(msat lnwire.MilliSatoshi) (uint64, error) {
273✔
85
        return uint64(msat * 10), nil
273✔
86
}
273✔
87

88
// decodeAmount returns the amount encoded by the provided string in
89
// millisatoshi.
90
func decodeAmount(amount string) (lnwire.MilliSatoshi, error) {
126✔
91
        if len(amount) < 1 {
127✔
92
                return 0, fmt.Errorf("amount must be non-empty")
1✔
93
        }
1✔
94

95
        // If last character is a digit, then the amount can just be
96
        // interpreted as BTC.
97
        char := amount[len(amount)-1]
125✔
98
        digit := char - '0'
125✔
99
        if digit >= 0 && digit <= 9 {
170✔
100
                btc, err := strconv.ParseUint(amount, 10, 64)
45✔
101
                if err != nil {
52✔
102
                        return 0, err
7✔
103
                }
7✔
104
                return lnwire.MilliSatoshi(btc) * mSatPerBtc, nil
38✔
105
        }
106

107
        // If not a digit, it must be part of the known units.
108
        conv, ok := toMSat[char]
80✔
109
        if !ok {
84✔
110
                return 0, fmt.Errorf("unknown multiplier %c", char)
4✔
111
        }
4✔
112

113
        // Known unit.
114
        num := amount[:len(amount)-1]
76✔
115
        if len(num) < 1 {
79✔
116
                return 0, fmt.Errorf("number must be non-empty")
3✔
117
        }
3✔
118

119
        am, err := strconv.ParseUint(num, 10, 64)
73✔
120
        if err != nil {
77✔
121
                return 0, err
4✔
122
        }
4✔
123

124
        return conv(am)
69✔
125
}
126

127
// encodeAmount encodes the provided millisatoshi amount using as few characters
128
// as possible.
129
func encodeAmount(msat lnwire.MilliSatoshi) (string, error) {
155✔
130
        // If possible to express in BTC, that will always be the shortest
155✔
131
        // representation.
155✔
132
        if msat%mSatPerBtc == 0 {
172✔
133
                return strconv.FormatInt(int64(msat/mSatPerBtc), 10), nil
17✔
134
        }
17✔
135

136
        // Should always be expressible in pico BTC.
137
        pico, err := fromMSat['p'](msat)
138✔
138
        if err != nil {
138✔
139
                return "", fmt.Errorf("unable to express %d msat as pBTC: %w",
×
140
                        msat, err)
×
141
        }
×
142
        shortened := strconv.FormatUint(pico, 10) + "p"
138✔
143
        for unit, conv := range fromMSat {
681✔
144
                am, err := conv(msat)
543✔
145
                if err != nil {
667✔
146
                        // Not expressible using this unit.
124✔
147
                        continue
124✔
148
                }
149

150
                // Save the shortest found representation.
151
                str := strconv.FormatUint(am, 10) + string(unit)
422✔
152
                if len(str) < len(shortened) {
575✔
153
                        shortened = str
153✔
154
                }
153✔
155
        }
156

157
        return shortened, nil
138✔
158
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc