@@ -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,123 @@ 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+ aliceTap := newTapClient (t .t , alice )
3721+
3722+ // Fund Alice so she'll have enough funds to mint the asset.
3723+ fundAllNodes (t .t , net , []* HarnessNode {alice })
3724+
3725+ // Next, we'll make a new asset with a specified decimal display. We'll also
3726+ // make grouped asset as well.
3727+ usdMetaData := & taprpc.AssetMeta {
3728+ Data : []byte (`{
3729+ "description":"this is a USD stablecoin with decimal display of 6"
3730+ }` ),
3731+ Type : taprpc .AssetMetaType_META_TYPE_JSON ,
3732+ }
3733+
3734+ const decimalDisplay = 6
3735+ itestAsset = & mintrpc.MintAsset {
3736+ AssetType : taprpc .AssetType_NORMAL ,
3737+ Name : "USD" ,
3738+ AssetMeta : usdMetaData ,
3739+ // We mint 1 million USD with a decimal display of 6, which
3740+ // results in 1 trillion asset units.
3741+ Amount : 1_000_000_000_000 ,
3742+ DecimalDisplay : decimalDisplay ,
3743+ NewGroupedAsset : true ,
3744+ }
3745+
3746+ // Mint an asset on Charlie and sync Dave to Charlie as the universe.
3747+ mintedAssets := itest .MintAssetsConfirmBatch (
3748+ t .t , t .lndHarness .Miner .Client , aliceTap ,
3749+ []* mintrpc.MintAssetRequest {
3750+ {
3751+ Asset : itestAsset ,
3752+ },
3753+ },
3754+ )
3755+ usdAsset := mintedAssets [0 ]
3756+ assetID := usdAsset .AssetGenesis .AssetId
3757+
3758+ // Now that we've minted the asset, we can set the price in the oracle.
3759+ var id asset.ID
3760+ copy (id [:], assetID )
3761+
3762+ // We'll assume a price of $100,000.00 USD for a single BTC. This is just the
3763+ // current subjective price our oracle will use. From this BTC price, we'll
3764+ // scale things up to be in the precision of the asset we minted above.
3765+ btcPrice := rfqmath .NewBigIntFixedPoint (
3766+ 100_000_00 , 2 ,
3767+ ).ScaleTo (decimalDisplay )
3768+ oracle .setPrice (id , btcPrice , btcPrice )
3769+
3770+ // Now we'll make a normal invoice for 1 BTC using Alice.
3771+ expirySeconds := 10
3772+ amountSat := 100_000_000
3773+ invoiceResp , err := alice .AddInvoice (ctxb , & lnrpc.Invoice {
3774+ Value : int64 (amountSat ),
3775+ Memo : "normal invoice" ,
3776+ Expiry : int64 (expirySeconds ),
3777+ })
3778+ require .NoError (t .t , err )
3779+
3780+ payReq := invoiceResp .PaymentRequest
3781+
3782+ // Now that we have our payment request, we'll call into the new decode asset
3783+ // pay req call.
3784+ decodeResp , err := aliceTap .DecodeAssetPayReq (ctxb , & tapchannelrpc.AssetPayReq {
3785+ AssetId : assetID ,
3786+ PayReqString : payReq ,
3787+ })
3788+ require .NoError (t .t , err )
3789+
3790+ // The decimal display information, genesis, and asset group information
3791+ // should all match.
3792+ require .Equal (
3793+ t .t , int64 (decimalDisplay ), int64 (decodeResp .DecimalDisplay .DecimalDisplay ),
3794+ )
3795+ require .Equal (t .t , usdAsset .AssetGenesis , decodeResp .GenesisInfo )
3796+ require .Equal (t .t , usdAsset .AssetGroup , decodeResp .AssetGroup )
3797+
3798+ // The 1 BTC invoice should map to 1 asset unit (1 million units as decimal display is 6).
3799+ const expectedUnits = 1_000_000
3800+ require .Equal (t .t , int64 (expectedUnits ), int64 (decodeResp .AssetAmount ))
3801+ }
0 commit comments