@@ -21,6 +21,7 @@ import (
2121 "github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
2222 oraclerpc "github.com/lightninglabs/taproot-assets/taprpc/priceoraclerpc"
2323 "github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
24+ "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
2425 tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
2526 "github.com/lightninglabs/taproot-assets/taprpc/universerpc"
2627 "github.com/lightninglabs/taproot-assets/tapscript"
@@ -3678,3 +3679,129 @@ func testCustomChannelsForwardBandwidth(ctxb context.Context,
36783679 universeTap , noOpCoOpCloseBalanceCheck ,
36793680 )
36803681}
3682+
3683+ // testCustomChannelsDecodeAssetInvoice tests that we're able to properly
3684+ // decode and display asset invoice related information.
3685+ //
3686+ // TODO(roasbeef): just move to tapd repo due to new version that doesn't req a
3687+ // chan?
3688+ func testCustomChannelsDecodeAssetInvoice (ctx context.Context ,
3689+ net * NetworkHarness , t * harnessTest ) {
3690+
3691+ // First, we'll set up some information for our custom oracle that we'll use
3692+ // to feed in price information.
3693+ oracleAddr := fmt .Sprintf ("localhost:%d" , port .NextAvailablePort ())
3694+ oracle := newOracleHarness (oracleAddr )
3695+ oracle .start (t .t )
3696+ t .t .Cleanup (oracle .stop )
3697+
3698+ ctxb := context .Background ()
3699+ lndArgs := slices .Clone (lndArgsTemplate )
3700+ litdArgs := slices .Clone (litdArgsTemplateNoOracle )
3701+ litdArgs = append (litdArgs , fmt .Sprintf (
3702+ "--taproot-assets.experimental.rfq.priceoracleaddress=" +
3703+ "rfqrpc://%s" , oracleAddr ,
3704+ ))
3705+
3706+ // For this test, Zane will be our dedicated Universe server for all parties.
3707+ zane , err := net .NewNode (
3708+ t .t , "Zane" , lndArgs , false , true , litdArgs ... ,
3709+ )
3710+ require .NoError (t .t , err )
3711+
3712+ litdArgs = append (litdArgs , fmt .Sprintf (
3713+ "--taproot-assets.proofcourieraddr=%s://%s" ,
3714+ proof .UniverseRpcCourierType , zane .Cfg .LitAddr (),
3715+ ))
3716+
3717+ // We'll just make a single node here, as this doesn't actually rely on a set
3718+ // of active channels.
3719+ alice , err := net .NewNode (t .t , "Alice" , lndArgs , false , true , litdArgs ... )
3720+ require .NoError (t .t , err )
3721+ aliceTap := newTapClient (t .t , alice )
3722+
3723+ // Fund Alice so she'll have enough funds to mint the asset.
3724+ fundAllNodes (t .t , net , []* HarnessNode {alice })
3725+
3726+ // Next, we'll make a new asset with a specified decimal display. We'll also
3727+ // make grouped asset as well.
3728+ usdMetaData := & taprpc.AssetMeta {
3729+ Data : []byte (`{
3730+ "description":"this is a USD stablecoin with decimal display of 6"
3731+ }` ),
3732+ Type : taprpc .AssetMetaType_META_TYPE_JSON ,
3733+ }
3734+
3735+ const decimalDisplay = 6
3736+ itestAsset = & mintrpc.MintAsset {
3737+ AssetType : taprpc .AssetType_NORMAL ,
3738+ Name : "USD" ,
3739+ AssetMeta : usdMetaData ,
3740+ // We mint 1 million USD with a decimal display of 6, which
3741+ // results in 1 trillion asset units.
3742+ Amount : 1_000_000_000_000 ,
3743+ DecimalDisplay : decimalDisplay ,
3744+ NewGroupedAsset : true ,
3745+ }
3746+
3747+ // Mint an asset on Charlie and sync Dave to Charlie as the universe.
3748+ mintedAssets := itest .MintAssetsConfirmBatch (
3749+ t .t , t .lndHarness .Miner .Client , aliceTap ,
3750+ []* mintrpc.MintAssetRequest {
3751+ {
3752+ Asset : itestAsset ,
3753+ },
3754+ },
3755+ )
3756+ usdAsset := mintedAssets [0 ]
3757+ assetID := usdAsset .AssetGenesis .AssetId
3758+
3759+ // Now that we've minted the asset, we can set the price in the oracle.
3760+ var id asset.ID
3761+ copy (id [:], assetID )
3762+
3763+ // We'll assume a price of $100,000.00 USD for a single BTC. This is just the
3764+ // current subjective price our oracle will use. From this BTC price, we'll
3765+ // scale things up to be in the precision of the asset we minted above.
3766+ btcPrice := rfqmath .NewBigIntFixedPoint (
3767+ 100_000_00 , 2 ,
3768+ )
3769+ factor := rfqmath .NewBigInt (
3770+ big .NewInt (int64 (math .Pow10 (decimalDisplay ))),
3771+ )
3772+ btcPrice .Coefficient = btcPrice .Coefficient .Mul (factor )
3773+ oracle .setPrice (id , btcPrice , btcPrice )
3774+
3775+ // Now we'll make a normal invoice for 1 BTC using Alice.
3776+ expirySeconds := 10
3777+ amountSat := 100_000_000
3778+ invoiceResp , err := alice .AddInvoice (ctxb , & lnrpc.Invoice {
3779+ Value : int64 (amountSat ),
3780+ Memo : "normal invoice" ,
3781+ Expiry : int64 (expirySeconds ),
3782+ })
3783+ require .NoError (t .t , err )
3784+
3785+ payReq := invoiceResp .PaymentRequest
3786+
3787+ // Now that we have our payment request, we'll call into the new decode asset
3788+ // pay req call.
3789+ decodeResp , err := aliceTap .DecodeAssetPayReq (ctxb , & tapchannelrpc.AssetPayReq {
3790+ AssetId : assetID ,
3791+ PayReqString : payReq ,
3792+ })
3793+ require .NoError (t .t , err )
3794+
3795+ // The decimal display information, genesis, and asset group information
3796+ // should all match.
3797+ require .Equal (
3798+ t .t , int64 (decimalDisplay ), int64 (decodeResp .DecimalDisplay .DecimalDisplay ),
3799+ )
3800+ require .Equal (t .t , usdAsset .AssetGenesis , decodeResp .GenesisInfo )
3801+ require .Equal (t .t , usdAsset .AssetGroup , decodeResp .AssetGroup )
3802+
3803+ // The 1 BTC invoice should map to 100k asset units, with decimal display 6
3804+ // that's 100 billion asset units.
3805+ const expectedUnits = 100_000_000_000
3806+ require .Equal (t .t , int64 (expectedUnits ), int64 (decodeResp .AssetAmount ))
3807+ }
0 commit comments