Skip to content

Commit 7496ab3

Browse files
author
ffranr
authored
Merge pull request #1059 from guggero/rfq-doc
README+docs: create document explaining decimal display and RFQ, add reference implementation
2 parents 2f0947d + b4208ac commit 7496ab3

File tree

60 files changed

+2808
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2808
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ updates the daemon's funds-custody material. Merely having the `lnd` seed phrase
139139
is **NOT** enough to restore assets minted or received.
140140
**WITHOUT BACKUP BEFORE DELETION, FUNDS ARE DESTROYED**.
141141

142+
## RFQ, asset decimal display, unit precision and price oracle
143+
144+
[Everything related to the RFQ (Request For Quote) system, the asset's currency
145+
precision (decimal display) and the RFQ price oracle can be found in this
146+
document](./docs/rfq-and-decimal-display.md).
147+
142148
## Submit feature requests
143149

144150
The [GitHub issue tracker](https://github.com/lightninglabs/taproot-assets/issues) can be used to request specific improvements or report bugs.

docs/rfq-and-decimal-display.md

Lines changed: 404 additions & 0 deletions
Large diffs are not rendered by default.

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ require (
5050
gopkg.in/macaroon-bakery.v2 v2.1.0
5151
gopkg.in/macaroon.v2 v2.1.0
5252
modernc.org/sqlite v1.30.0
53+
pgregory.net/rapid v1.1.0
5354
)
5455

5556
require (

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,8 @@ modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
11691169
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
11701170
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
11711171
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
1172+
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
1173+
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
11721174
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
11731175
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
11741176
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

rfq/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# RFQ
2+
3+
This package contains most code related to the business logic of the Request
4+
For Quotes subsystem.
5+
6+
The high-level/conceptual explanation of [how RFQ (and related concepts such
7+
as the decimal display value and price oracles) works, can be found
8+
in this separate document](../docs/rfq-and-decimal-display.md).
9+
10+
The implementation of the [RFQ fixed point arithmetic can be found in the
11+
`rfqmath` package](../rfqmath).
12+
13+
The actual [wire messages are located in the `rfqmsg`](../rfqmsg) package.
14+
15+
The [gRPC definitions of the RFQ methods can be found in the `taprpc/rfqrpc`
16+
package](../taprpc/rfqrpc).
17+
18+
The [gRPC definitions of the price oracle methods can be found in the
19+
`taprpc/priceoraclerpc` package](../taprpc/priceoraclerpc).
20+
21+
[An example implementation of a price oracle server implementing that RPC
22+
interface with Golang can be found in
23+
`docs/examples/basic-price-oracle`](../docs/examples/basic-price-oracle).

rfqmath/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# RFQ math
2+
3+
This package contains code related to fixed point arithmetics used in RFQ
4+
exchange rate calculations.
5+
6+
The high-level/conceptual explanation of [how RFQ (and related concepts such
7+
as the decimal display value and price oracles) works, can be found
8+
in this separate document](../docs/rfq-and-decimal-display.md).

rfqmath/arithmetic.go

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
package rfqmath
2+
3+
import (
4+
"math/big"
5+
6+
"golang.org/x/exp/constraints"
7+
)
8+
9+
// Arithmetic defines the basic arithmetic operations. The structure of the
10+
// interfaces allows for chaining the arithmetic operations.
11+
type Arithmetic[N any] interface {
12+
// Add returns the sum of the two numbers.
13+
Add(N) N
14+
15+
// Mul returns the product of the two numbers.
16+
Mul(N) N
17+
18+
// Sub returns the difference of the two numbers.
19+
Sub(N) N
20+
21+
// Div returns the division of the two numbers.
22+
Div(N) N
23+
}
24+
25+
// Int is an interface that represents an integer types and the operations we
26+
// care about w.r.t that type.
27+
type Int[N any] interface {
28+
// Arithmetic asserts that the target type of this interface satisfies
29+
// the Arithmetic interface. This lets us get around limitations
30+
// regarding recursive types in Go.
31+
Arithmetic[N]
32+
33+
// Equals returns true if the two integers are equal.
34+
Equals(other N) bool
35+
36+
// ToFloat converts the integer to a float.
37+
ToFloat() float64
38+
39+
// FromFloat converts a float to the integer type.
40+
FromFloat(float64) N
41+
42+
// ToUint64 converts the integer to a uint64.
43+
ToUint64() uint64
44+
45+
// FromUint64 converts a uint64 to the integer type.
46+
FromUint64(uint64) N
47+
}
48+
49+
// NewInt creates a new integer of the target type.
50+
func NewInt[N Int[N]]() N {
51+
var n N
52+
return n
53+
}
54+
55+
// GoInt is a concrete implementation of the Int interface for the set of
56+
// built-in integer types. It ends up mapping the integers to a uint64
57+
// internally for operations.
58+
type GoInt[T constraints.Unsigned] struct {
59+
value T
60+
}
61+
62+
// NewGoInt creates a new GoInt from the given integer.
63+
func NewGoInt[T constraints.Unsigned](value T) GoInt[T] {
64+
return GoInt[T]{
65+
value: value,
66+
}
67+
}
68+
69+
// Add returns the sum of the two integers.
70+
func (b GoInt[T]) Add(other GoInt[T]) GoInt[T] {
71+
return GoInt[T]{
72+
value: b.value + other.value,
73+
}
74+
}
75+
76+
// Mul returns the product of the two integers.
77+
func (b GoInt[T]) Mul(other GoInt[T]) GoInt[T] {
78+
return GoInt[T]{
79+
value: b.value * other.value,
80+
}
81+
}
82+
83+
// Sub returns the difference of the two integers.
84+
func (b GoInt[T]) Sub(other GoInt[T]) GoInt[T] {
85+
return GoInt[T]{
86+
value: b.value - other.value,
87+
}
88+
}
89+
90+
// Div returns the division of the two integers.
91+
func (b GoInt[T]) Div(other GoInt[T]) GoInt[T] {
92+
return GoInt[T]{
93+
value: b.value / other.value,
94+
}
95+
}
96+
97+
// ToFloat converts the integer to a float.
98+
func (b GoInt[T]) ToFloat() float64 {
99+
return float64(b.value)
100+
}
101+
102+
// FromFloat converts a float to the integer type.
103+
func (b GoInt[T]) FromFloat(f float64) GoInt[T] {
104+
b.value = T(f)
105+
return b
106+
}
107+
108+
// ToUint64 converts the integer to a uint64.
109+
func (b GoInt[T]) ToUint64() uint64 {
110+
return uint64(b.value)
111+
}
112+
113+
// FromUint64 converts a uint64 to the integer type.
114+
func (b GoInt[T]) FromUint64(u uint64) GoInt[T] {
115+
b.value = T(u)
116+
return b
117+
}
118+
119+
// Equals returns true if the two integers are equal.
120+
func (b GoInt[T]) Equals(other GoInt[T]) bool {
121+
return b.value == other.value
122+
}
123+
124+
// A compile-time constraint to ensure that the GoInt type implements the Int
125+
// interface.
126+
var _ Int[GoInt[uint]] = GoInt[uint]{}
127+
128+
// BigInt is a concrete implementation of the Int interface using Go's big
129+
// integer type.
130+
type BigInt struct {
131+
value *big.Int
132+
}
133+
134+
// NewBigInt creates a new BigInt from the given integer.
135+
func NewBigInt(value *big.Int) BigInt {
136+
return BigInt{
137+
value: value,
138+
}
139+
}
140+
141+
// copyInt returns a copy of the internal big.Int. This is used to ensure we
142+
// don't mutate the underlying bit.Int during arithmetic operations.
143+
func (b BigInt) copyInt() *big.Int {
144+
return new(big.Int).Set(b.value)
145+
}
146+
147+
// Add returns the sum of the two integers.
148+
func (b BigInt) Add(other BigInt) BigInt {
149+
return BigInt{
150+
value: b.copyInt().Add(b.value, other.value),
151+
}
152+
}
153+
154+
// Mul returns the product of the two integers.
155+
func (b BigInt) Mul(other BigInt) BigInt {
156+
return BigInt{
157+
value: b.copyInt().Mul(b.value, other.value),
158+
}
159+
}
160+
161+
// Sub returns the difference of the two integers.
162+
func (b BigInt) Sub(other BigInt) BigInt {
163+
return BigInt{
164+
value: b.copyInt().Sub(b.value, other.value),
165+
}
166+
}
167+
168+
// Div returns the division of the two integers.
169+
func (b BigInt) Div(other BigInt) BigInt {
170+
return BigInt{
171+
value: b.copyInt().Div(b.value, other.value),
172+
}
173+
}
174+
175+
// ToFloat converts the integer to a float.
176+
func (b BigInt) ToFloat() float64 {
177+
floatVal, _ := b.value.Float64()
178+
return floatVal
179+
}
180+
181+
// FromFloat converts a float to the integer type.
182+
func (b BigInt) FromFloat(f float64) BigInt {
183+
if b.value == nil {
184+
b.value = new(big.Int)
185+
}
186+
187+
b.value.SetInt64(int64(f))
188+
return b
189+
}
190+
191+
// FromUint64 converts a uint64 to the integer type.
192+
func (b BigInt) FromUint64(u uint64) BigInt {
193+
if b.value == nil {
194+
b.value = new(big.Int)
195+
}
196+
197+
b.value.SetUint64(u)
198+
return b
199+
}
200+
201+
// ToUint64 converts the integer to a uint64.
202+
func (b BigInt) ToUint64() uint64 {
203+
return b.value.Uint64()
204+
}
205+
206+
// Equals returns true if the two integers are equal.
207+
func (b BigInt) Equals(other BigInt) bool {
208+
return b.value.Cmp(other.value) == 0
209+
}
210+
211+
// A compile-time constraint to ensure that the BigInt type implements the Int
212+
// interface.
213+
var _ Int[BigInt] = BigInt{}

0 commit comments

Comments
 (0)