@@ -101,6 +101,73 @@ func isSupportedSubjectAsset(subjectAsset *oraclerpc.AssetSpecifier) bool {
101
101
return false
102
102
}
103
103
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
+
104
171
// getAssetRates returns the asset rates for a given transaction type and
105
172
// subject asset max amount.
106
173
func getAssetRates (transactionType oraclerpc.TransactionType ,
@@ -109,21 +176,9 @@ func getAssetRates(transactionType oraclerpc.TransactionType,
109
176
// Determine the rate based on the transaction type.
110
177
var subjectAssetRate rfqmath.BigIntFixedPoint
111
178
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 ()
119
180
} 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 ()
127
182
}
128
183
129
184
// Set the rate expiry to 5 minutes by default.
0 commit comments