Skip to content

Commit 7fb74e6

Browse files
Merge pull request #825 from lightninglabs/docs-taproot-assets
Update taproot-assets documentation
2 parents 8f550bb + 059f3b7 commit 7fb74e6

File tree

1 file changed

+69
-14
lines changed
  • docs/taproot-assets/examples/basic-price-oracle

1 file changed

+69
-14
lines changed

docs/taproot-assets/examples/basic-price-oracle/main.go

+69-14
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,73 @@ func isSupportedSubjectAsset(subjectAsset *oraclerpc.AssetSpecifier) bool {
101101
return false
102102
}
103103

104+
// getPurchaseRate returns the buy (purchase) rate for the asset. The unit of
105+
// the rate is the number of TAP asset units per BTC.
106+
//
107+
// Suppose our TAP asset is a USD stablecoin. To support liquidity and precision
108+
// in rate conversion, we mint 1,000,000 TAP asset units per 1.00 USD. Wallet
109+
// software must therefore display 1 USD for every 1,000,000 TAP asset units.
110+
// In effect, wallet software must divide TAP asset units by 1,000,000 (= 10^6)
111+
// to show the correct USD value. We call the exponent in this conversion factor
112+
// (in this example it's 6) the `decimalDisplay` of the asset. The
113+
// decimal display for a given asset is immutable and defined at minting.
114+
//
115+
// All rates returned by the price oracle service to tapd nodes are expressed as
116+
// TAP asset units per BTC.
117+
//
118+
// Suppose the real-world price of 1 BTC is $42,000.16. To express this as a
119+
// rate in TAP asset units per BTC, multiply by the decimal display conversion
120+
// factor (10^decimalDisplay):
121+
//
122+
// realWorldPrice = 42,000.16
123+
// decimalDisplay = 6
124+
// tapAssetUnitsPerBtc = realWorldPrice * (10^decimalDisplay)
125+
//
126+
// = 42,000.16 * 1,000,000
127+
// = 42,000,160,000
128+
//
129+
// Therefore, the price oracle should return the rate:
130+
//
131+
// rfqmath.NewBigIntFixedPoint(42_000_160_000, 0)
132+
//
133+
// ## When is the FixedPoint representation useful?
134+
//
135+
// Suppose another TAP asset is highly valuable, and the buy rate is
136+
// 0.00001 TAP asset units per BTC. Spending 1 BTC would return 0.00001 TAP
137+
// asset units of our valuable asset.
138+
//
139+
// To maintain integer-based communication, representing such small fractional
140+
// rates directly is impractical due to floating-point precision issues.
141+
// Instead, the price oracle returns a FixedPoint representation with integer
142+
// components.
143+
//
144+
// A FixedPoint number `F` consists of a coefficient `C` and scale exponent `s`:
145+
//
146+
// F = C * (10^-s)
147+
//
148+
// Another way to express this is:
149+
//
150+
// F = C / (10^s)
151+
//
152+
// Now, we know F = 0.00001, and we are free to choose any integer pair (C, s)
153+
// that satisfies this equation. One simple choice is to let C = 1 and s = 5,
154+
// since 1 * 10^-5 = 0.00001.
155+
//
156+
// So the rate can be represented as:
157+
//
158+
// rfqmath.NewBigIntFixedPoint(1, 5)
159+
func getPurchaseRate() rfqmath.BigIntFixedPoint {
160+
return rfqmath.NewBigIntFixedPoint(42_000_160_000, 0)
161+
}
162+
163+
// getSaleRate returns the sell/sale rate for the asset. The units of the
164+
// rate is the number of TAP asset units per BTC.
165+
//
166+
// NOTE: see getPurchaseRate for more information.
167+
func getSaleRate() rfqmath.BigIntFixedPoint {
168+
return rfqmath.NewBigIntFixedPoint(39_000_220_000, 0)
169+
}
170+
104171
// getAssetRates returns the asset rates for a given transaction type and
105172
// subject asset max amount.
106173
func getAssetRates(transactionType oraclerpc.TransactionType,
@@ -109,21 +176,9 @@ func getAssetRates(transactionType oraclerpc.TransactionType,
109176
// Determine the rate based on the transaction type.
110177
var subjectAssetRate rfqmath.BigIntFixedPoint
111178
if transactionType == oraclerpc.TransactionType_PURCHASE {
112-
// As an example, the purchase rate is $42,000 per BTC. To
113-
// increase precision, we represent this as 42 billion
114-
// taproot asset units per BTC. Therefore, we scale the
115-
// $42,000 per BTC rate by a factor of 10^6.
116-
subjectAssetRate = rfqmath.FixedPointFromUint64[rfqmath.BigInt](
117-
42_000, 6,
118-
)
179+
subjectAssetRate = getPurchaseRate()
119180
} else {
120-
// Our example sell rate will be lower at $40,000 per BTC. This
121-
// rate will be represented as 40 billion taproot asset units
122-
// per BTC. Therefore, we scale the $40,000 per BTC rate by a
123-
// factor of 10^6.
124-
subjectAssetRate = rfqmath.FixedPointFromUint64[rfqmath.BigInt](
125-
40_000, 6,
126-
)
181+
subjectAssetRate = getSaleRate()
127182
}
128183

129184
// Set the rate expiry to 5 minutes by default.

0 commit comments

Comments
 (0)