[feature]: `DecodeAssetPayReq`: add option to determine asset amount based on RFQ and the edge node's buy rate
DecodeAssetPayReq seems to decode the invoice, determines the sats amount, and then queries a nodes price oracle for their sell price to determine an asset amount that the invoice is representative of.
I'd like to see an option to also perform an RFQ with a peer to get the actual amount that would need to be sent to pay the invoice given the peer's buy price. This seems more representative of what the sender is going to actually need to send (less normal LN routing fees for sats channels).
I'd like to see the existing asset_amount that is returned kept but add this new information in another property such as asset_amount_RFQ. With this information, we can then compute the "implied fee" explained in https://github.com/lightninglabs/taproot-assets/issues/1367 in advance before attempting to make a payment.
Note that there's no "true" RFQ amount. Let's say there's 20 peers we're connected to, and we do RFQ with each of them, which response do we show for decode pay req?
It's also important to note that as is, DecodePayReq is effectively a pure RPC, there's no state mutated, we just decode then query a price. Your suggested change would actually place a standing order, that may never actually be consumed. If a service is just doing decoding, these records (though they expire) start to build up.
What are the drawbacks of having open RFQ records start to build? What is the drawback of a standing order that may never be consumed? I feel like https://github.com/lightninglabs/taproot-assets/issues/1358 and https://github.com/lightninglabs/taproot-assets/issues/1359 are going to produce the same kind of bloat.
What are the drawbacks of having open RFQ records start to build? What is the drawback of a standing order that may never be consumed?
Consider that once the edge node starts properly managing their orders, you'll start to receive rejects of flows that they don't have the liquidity or appetite to serve.
Let's say you have an invoice, that requests 10 BTC, you don't want to pay it, just decode. Your node is using a version that has DecodeAssetPayReq actually attempts to negotiate via the RFQ process. Your edge node only has a standing order for 1 BTC, so they'll reject any attempts to negotiate a 10 BTC flow. As a result, just trying to decode the invoice fails.
Consider that once the edge node starts properly managing their orders, you'll start to receive rejects of flows that they don't have the liquidity or appetite to serve.
You mean like fixing https://github.com/lightninglabs/taproot-assets/issues/1425 ?
Let's say you have an invoice, that requests 10 BTC, you don't want to pay it, just decode. Your node is using a version that has
DecodeAssetPayReqactually attempts to negotiate via the RFQ process. Your edge node only has a standing order for 1 BTC, so they'll reject any attempts to negotiate a 10 BTC flow. As a result, just trying to decode the invoice fails.
Could it be okay if this scenario fails but still allow it to work for cases where it won't fail? Like if we don't have the liquidity to make the payment, would it even be useful to return anything and maybe it makes sense to just error out?
Also, why would I have a standing order for 1 BTC? Are you talking about from a previous call to DecodeAssetPayReq for a different invoice?
, these records (though they expire) start to build up.
Could we just request a really short expiry to mitigate this and assume it could be pretty close? Maybe this is starting to reduce the usefulness of what I'm requesting though.
Also, why would I have a standing order for 1 BTC?
Ah my mistake, I meant that the remote node (your channel peer) has that standing order.
What I'm getting at here is that: as is, DecodeAssetPayReq is a pure function (it has no side effects). lnd's RPC call is also the same (it doesn't mutate any data on risk, insert db records, etc). The tapd version is more or less deterministic if we assume for a second that the price oracle always returns the same price.
Your suggestion here would mean that the function is no longer pure. It'll modify state, and not also has the remote peer in the loop. The remote peer (say it's buggy) can just send an error and not respond to the quote for w/e reason. If that happens, then just the act of decoding an invoice would fail.
As a pure function, the decoding will always succeed (assuming oracle uptime).
Could we just request a really short expiry to mitigate this and assume it could be pretty close
That would work, but still fail if the invoice is much larger than the standing order from the remote edge node.
I agree with what you are saying about how this modifies state and is not ideal. I think we should just leave this issue open and see if market demands it once people start using taproot assets channels and we get an idea on how much price spread is typically across the marketplace.