diff --git a/lib/core/src/Cardano/Wallet.hs b/lib/core/src/Cardano/Wallet.hs index 5036e3d7531..ab4e139440d 100644 --- a/lib/core/src/Cardano/Wallet.hs +++ b/lib/core/src/Cardano/Wallet.hs @@ -158,6 +158,7 @@ module Cardano.Wallet -- ** Transaction , forgetTx , listTransactions + , listAssets , getTransaction , submitExternalTx , submitTx @@ -508,7 +509,7 @@ import Data.List.NonEmpty import Data.Map.Strict ( Map ) import Data.Maybe - ( fromMaybe, mapMaybe ) + ( fromMaybe, isJust, mapMaybe ) import Data.Proxy ( Proxy ) import Data.Quantity @@ -2489,6 +2490,28 @@ listTransactions ctx wid mMinWithdrawal mStart mEnd order = db & \DBLayer{..} -> $ slotRangeFromTimeRange $ Range mStart mEnd +-- | Extract assets associated with a given wallet from its transaction history. +listAssets + :: forall s k ctx. (HasDBLayer IO s k ctx, IsOurs s Address) + => ctx + -> WalletId + -> ExceptT ErrNoSuchWallet IO (Set TokenMap.AssetId) +listAssets ctx wid = db & \DBLayer{..} -> do + cp <- mapExceptT atomically $ withNoSuchWallet wid $ readCheckpoint wid + txs <- lift . atomically $ + let noMinWithdrawal = Nothing + allTxStatuses = Nothing + in readTxHistory wid noMinWithdrawal Ascending wholeRange allTxStatuses + let txAssets :: TransactionInfo -> Set TokenMap.AssetId + txAssets = Set.unions + . map (TokenBundle.getAssets . view #tokens) + . filter ourOut + . txInfoOutputs + ourOut TxOut{address} = ourAddress address + ourAddress addr = isJust . fst . isOurs addr $ getState cp + pure $ Set.unions $ map txAssets txs + where + db = ctx ^. dbLayer @IO @s @k -- | Get transaction and metadata from history for a given wallet. getTransaction diff --git a/lib/core/src/Cardano/Wallet/Api/Server.hs b/lib/core/src/Cardano/Wallet/Api/Server.hs index 786ce638197..8535fb6b14f 100644 --- a/lib/core/src/Cardano/Wallet/Api/Server.hs +++ b/lib/core/src/Cardano/Wallet/Api/Server.hs @@ -1731,6 +1731,7 @@ newtype ErrListAssets = ErrListAssetsNoSuchWallet ErrNoSuchWallet listAssets :: forall ctx s k. ( ctx ~ ApiLayer s k + , IsOurs s Address , HasTokenMetadataClient ctx ) => ctx @@ -1738,27 +1739,18 @@ listAssets -> Handler [ApiAsset] listAssets ctx wid = do assets <- listAssetsBase ctx wid - liftIO $ fillMetadata client assets toApiAsset + liftIO $ fillMetadata client (Set.toList assets) toApiAsset where client = ctx ^. tokenMetadataClient -- | Return a list of all AssetIds involved in the transaction history of this -- wallet. listAssetsBase - :: forall ctx s k. - ( ctx ~ ApiLayer s k - ) - => ctx - -> ApiT WalletId - -> Handler [AssetId] -listAssetsBase ctx (ApiT wid) = withWorkerCtx ctx wid liftE liftE $ \wrk -> - liftHandler $ allTxAssets <$> - W.listTransactions @_ @_ @_ wrk wid Nothing Nothing Nothing Descending - where - allTxAssets = Set.toList . Set.unions . map txAssets - txAssets = Set.unions - . map (TokenBundle.getAssets . view #tokens) - . W.txInfoOutputs + :: forall s k. IsOurs s Address => + ApiLayer s k -> ApiT WalletId -> Handler (Set AssetId) +listAssetsBase ctx (ApiT wallet) = + withWorkerCtx ctx wallet liftE liftE $ \wctx -> + liftHandler $ W.listAssets wctx wallet -- | Look up a single asset and its metadata. -- @@ -1767,6 +1759,7 @@ listAssetsBase ctx (ApiT wid) = withWorkerCtx ctx wid liftE liftE $ \wrk -> getAsset :: forall ctx s k. ( ctx ~ ApiLayer s k + , IsOurs s Address , HasTokenMetadataClient ctx ) => ctx @@ -1786,6 +1779,7 @@ getAsset ctx wid (ApiT policyId) (ApiT assetName) = do getAssetDefault :: forall ctx s k. ( ctx ~ ApiLayer s k + , IsOurs s Address , HasTokenMetadataClient ctx ) => ctx diff --git a/lib/core/src/Cardano/Wallet/Primitive/Model.hs b/lib/core/src/Cardano/Wallet/Primitive/Model.hs index ef16862d4de..38a44e249bc 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Model.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Model.hs @@ -271,11 +271,11 @@ applyBlock !block (Wallet !u0 _ s0) = -- applyBlocks :: (IsOurs s Address, IsOurs s RewardAccount) - => NonEmpty (Block) + => NonEmpty Block -> Wallet s -> NonEmpty (FilteredBlock, Wallet s) -applyBlocks (block0 :| blocks) cp = - NE.scanl (flip applyBlock . snd) (applyBlock block0 cp) blocks +applyBlocks (block0 :| blocks) walletState = + NE.scanl (flip applyBlock . snd) (applyBlock block0 walletState) blocks {------------------------------------------------------------------------------- Accessors @@ -379,7 +379,7 @@ changeUTxO pending = evalState $ UTxO operations -------------------------------------------------------------------------------} --- | Applies a transaction to a UTxO, moving it from one state from another. +-- | Applies a transaction to a UTxO, moving it from one state to another. -- -- When applying a transaction to a UTxO: -- 1. We need to remove any unspents that have been spent in the transaction. @@ -426,7 +426,7 @@ spendTx tx !u = -- | Construct a 'UTxO' corresponding to a given transaction. -- -- It is important for the transaction outputs to be ordered correctly, --- as their index within this ordering determines how +-- as their index within this ordering determines how -- they are referenced as transaction inputs in subsequent blocks. -- -- > balance (utxoFromTx tx) = foldMap tokens (outputs tx) @@ -463,7 +463,7 @@ discoverAddresses block s0 = s2 -- NOTE: Only outputs and withdrawals can potentially -- result in the extension of the address pool and -- the learning of new addresses. - -- + -- -- Inputs and collateral are forced to use existing addresses. discoverTx s tx = discoverWithdrawals (discoverOutputs s tx) tx discoverOutputs s tx = @@ -529,10 +529,7 @@ applyBlockToUTxO Block{header,transactions,delegations} s u0 = (fblock, u1) } (txs1, u1) = L.foldl' applyOurTx (mempty, u0) transactions - applyOurTx - :: ([(Tx, TxMeta)], UTxO) - -> Tx - -> ([(Tx, TxMeta)], UTxO) + applyOurTx :: ([(Tx, TxMeta)], UTxO) -> Tx -> ([(Tx, TxMeta)], UTxO) applyOurTx (!txs, !u) !tx = case applyOurTxToUTxO slotNo blockHeight s tx u of Nothing -> (txs, u) @@ -557,59 +554,59 @@ applyOurTxToUTxO -> UTxO -> Maybe ((Tx, TxMeta), UTxO) applyOurTxToUTxO !slotNo !blockHeight !s !tx !prevUTxO = - let - -- The next UTxO state (apply a state transition) (e.g. remove - -- transaction outputs we've spent) - ourNextUTxO = - spendTx tx prevUTxO - <> UTxO.filterByAddress (ours s) (utxoFromTx tx) - ourWithdrawalSum = ourWithdrawalSumFromTx s tx - - -- Balance of the UTxO that we received and that we spent - received = balance (ourNextUTxO `excluding` dom prevUTxO) - spent = - balance (prevUTxO `excluding` dom ourNextUTxO) - `TB.add` TB.fromCoin ourWithdrawalSum - - adaSpent = TB.getCoin spent - adaReceived = TB.getCoin received - dir = if adaSpent > adaReceived then Outgoing else Incoming - amount = distance adaSpent adaReceived - - -- Transaction metadata computed from the above information - txmeta = TxMeta - { status = InLedger - , direction = dir - , slotNo - , blockHeight - , amount = amount - , expiry = Nothing - } - - hasKnownWithdrawal = ourWithdrawalSum /= mempty - - -- NOTE 1: The only case where fees can be 'Nothing' is when dealing with - -- a Byron transaction. In which case fees can actually be calculated as - -- the delta between inputs and outputs. - -- - -- NOTE 2: We do not have in practice the actual input amounts, yet we - -- do make the assumption that if one input is ours, then all inputs are - -- necessarily ours and therefore, known as part of our current UTxO. - actualFee direction = case (tx ^. #fee, direction) of - (Just x, Outgoing) -> - -- Shelley and beyond: - Just x - (Nothing, Outgoing) -> - -- Byron: - let totalOut = F.fold (txOutCoin <$> outputs tx) - totalIn = TB.getCoin spent - in - Just $ distance totalIn totalOut - (_, Incoming) -> - Nothing - in if hasKnownWithdrawal || prevUTxO /= ourNextUTxO - then Just ((tx {fee = actualFee dir}, txmeta), ourNextUTxO) + if ourWithdrawalSum /= mempty || prevUTxO /= ourNextUTxO + then + let updatedTx = tx { fee = actualFee dir } + in Just ((updatedTx, txmeta), ourNextUTxO) else Nothing + where + -- The next UTxO state (apply a state transition) (e.g. remove + -- transaction outputs we've spent) + ourNextUTxO = + spendTx tx prevUTxO + <> UTxO.filterByAddress (ours s) (utxoFromTx tx) + ourWithdrawalSum = ourWithdrawalSumFromTx s tx + + -- Balance of the UTxO that we received and that we spent + received = balance (ourNextUTxO `excluding` dom prevUTxO) + spent = + balance (prevUTxO `excluding` dom ourNextUTxO) + `TB.add` TB.fromCoin ourWithdrawalSum + + adaSpent = TB.getCoin spent + adaReceived = TB.getCoin received + dir = if adaSpent > adaReceived then Outgoing else Incoming + amount = distance adaSpent adaReceived + + -- Transaction metadata computed from the above information + txmeta = TxMeta + { status = InLedger + , direction = dir + , slotNo + , blockHeight + , amount = amount + , expiry = Nothing + } + + -- NOTE 1: The only case where fees can be 'Nothing' is when dealing with + -- a Byron transaction. In which case fees can actually be calculated as + -- the delta between inputs and outputs. + -- + -- NOTE 2: We do not have in practice the actual input amounts, yet we + -- do make the assumption that if one input is ours, then all inputs are + -- necessarily ours and therefore, known as part of our current UTxO. + actualFee direction = case (tx ^. #fee, direction) of + (Just x, Outgoing) -> + -- Shelley and beyond: + Just x + (Nothing, Outgoing) -> + -- Byron: + let totalOut = F.fold (txOutCoin <$> outputs tx) + totalIn = TB.getCoin spent + in + Just $ distance totalIn totalOut + (_, Incoming) -> + Nothing ourWithdrawalSumFromTx :: IsOurs s RewardAccount diff --git a/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs b/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs index 4c0ee777cd0..043f4dc1645 100644 --- a/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs @@ -10,6 +10,7 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} +{-# LANGUAGE TupleSections #-} module Cardano.Wallet.Primitive.ModelSpec ( spec @@ -563,7 +564,7 @@ prop_changeUTxO_inner pendingTxs = data AllOurs = AllOurs instance IsOurs AllOurs a where - isOurs _ s = (Just shouldNotEvaluate, s) + isOurs _ = (Just shouldNotEvaluate,) where shouldNotEvaluate = error "AllOurs: unexpected evaluation" @@ -732,34 +733,20 @@ prop_applyOurTxToUTxO_allOurs -> Property prop_applyOurTxToUTxO_allOurs slotNo blockHeight tx utxo = checkCoverage $ - cover 50 ( haveResult) "have result" $ + cover 50 haveResult "have result" $ cover 0.1 (not haveResult) "do not have result" $ - report - (utxo) - "utxo" $ - report - (utxoFromTx tx) - "utxoFromTx tx" $ - report - (haveResult) - "haveResult" $ - report - (shouldHaveResult) - "shouldHaveResult" $ + report utxo "utxo" $ + report (utxoFromTx tx) "utxoFromTx tx" $ + report haveResult "haveResult" $ + report shouldHaveResult "shouldHaveResult" $ case maybeResult of Nothing -> - verify - (not shouldHaveResult) - "not shouldHaveResult" $ + verify (not shouldHaveResult) "not shouldHaveResult" $ property True Just utxo' -> - cover 10 (utxo /= utxo') - "utxo /= utxo'" $ - verify - (shouldHaveResult) - "shouldHaveResult" $ - verify - (utxo' == applyTxToUTxO tx utxo) + cover 10 (utxo /= utxo') "utxo /= utxo'" $ + verify shouldHaveResult "shouldHaveResult" $ + verify (utxo' == applyTxToUTxO tx utxo) "utxo' == applyTxToUTxO tx utxo" $ property True where @@ -785,32 +772,19 @@ prop_applyOurTxToUTxO_someOurs -> Property prop_applyOurTxToUTxO_someOurs ourState slotNo blockHeight tx utxo = checkCoverage $ - cover 50 ( haveResult) "have result" $ + cover 50 haveResult "have result" $ cover 0.1 (not haveResult) "do not have result" $ - report - (utxo) - "utxo" $ - report - (utxoFromTx tx) - "utxoFromTx tx" $ - report - (haveResult) - "haveResult" $ - report - (shouldHaveResult) - "shouldHaveResult" $ + report utxo "utxo" $ + report (utxoFromTx tx) "utxoFromTx tx" $ + report haveResult "haveResult" $ + report shouldHaveResult "shouldHaveResult" $ case maybeResult of Nothing -> - verify - (not shouldHaveResult) - "not shouldHaveResult" $ + verify (not shouldHaveResult) "not shouldHaveResult" $ property True Just utxo' -> - cover 10 (utxo /= utxo') - "utxo /= utxo'" $ - verify - (shouldHaveResult) - "shouldHaveResult" $ + cover 10 (utxo /= utxo') "utxo /= utxo'" $ + verify shouldHaveResult "shouldHaveResult" $ property True where haveResult :: Bool diff --git a/lib/core/test/unit/Cardano/WalletSpec.hs b/lib/core/test/unit/Cardano/WalletSpec.hs index 8c39b86c2e2..3866cb3abde 100644 --- a/lib/core/test/unit/Cardano/WalletSpec.hs +++ b/lib/core/test/unit/Cardano/WalletSpec.hs @@ -1,9 +1,12 @@ +{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -115,7 +118,7 @@ import Cardano.Wallet.Primitive.Types.Hash import Cardano.Wallet.Primitive.Types.RewardAccount ( RewardAccount (..) ) import Cardano.Wallet.Primitive.Types.TokenBundle - ( TokenBundle ) + ( TokenBundle (TokenBundle), getAssets ) import Cardano.Wallet.Primitive.Types.Tx ( Direction (..) , LocalTxSubmissionStatus (..) @@ -224,6 +227,7 @@ import Test.QuickCheck , counterexample , cover , elements + , forAll , forAllBlind , label , liftArbitrary @@ -273,6 +277,11 @@ import qualified Cardano.Wallet.DB.Sqlite.AddressBook as Sqlite import qualified Cardano.Wallet.Primitive.Migration as Migration import qualified Cardano.Wallet.Primitive.Types.Coin as Coin import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TokenBundle +import qualified Cardano.Wallet.Primitive.Types.TokenMap as TokenMap +import Cardano.Wallet.Primitive.Types.TokenMap.Gen + ( genAssetIdLargeRange ) +import Cardano.Wallet.Primitive.Types.TokenQuantity.Gen + ( genTokenQuantityPositive ) import qualified Data.ByteArray as BA import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as B8 @@ -322,6 +331,8 @@ spec = parallel $ describe "Cardano.WalletSpec" $ do (withMaxSuccess 10 $ property walletKeyIsReencrypted) it "Wallet can list transactions" (property walletListTransactionsSorted) + it "Wallet won't list unrelated assets used in related transactions" + (property walletListsOnlyRelatedAssets) describe "Tx fee estimation" $ it "Fee estimates are sound" @@ -628,7 +639,7 @@ walletListTransactionsSorted -> Property walletListTransactionsSorted wallet@(wid, _, _) _order (_mstart, _mend) history = monadicIO $ liftIO $ do - WalletLayerFixture DBLayer{..} wl _ slotNoTime <- liftIO $ setupFixture wallet + WalletLayerFixture DBLayer{..} wl _ slotNoTime <- setupFixture wallet atomically $ unsafeRunExceptT $ putTxHistory wid history txs <- unsafeRunExceptT $ W.listTransactions @_ @_ @_ wl wid Nothing Nothing Nothing Descending @@ -642,6 +653,57 @@ walletListTransactionsSorted wallet@(wid, _, _) _order (_mstart, _mend) history | (tx, meta) <- history ] times `shouldBe` expTimes +newtype DummyStateWithAddresses = DummyStateWithAddresses [Address] + deriving stock (Show) + +instance IsOurs DummyStateWithAddresses Address where + isOurs a s@(DummyStateWithAddresses addr) = + if a `elem` addr + then (Just (DerivationIndex 0 :| []), s) + else (Nothing, s) + +instance IsOurs DummyStateWithAddresses RewardAccount where + isOurs _ s = (Nothing, s) + +walletListsOnlyRelatedAssets :: Hash "Tx" -> TxMeta -> Property +walletListsOnlyRelatedAssets txId txMeta = + forAll genOuts $ \(out1, out2, wallet@(wid, _, _)) -> monadicIO $ do + WalletLayerFixture DBLayer{..} wl _ _ <- liftIO $ setupFixture wallet + let listHistoricalAssets hry = do + liftIO . atomically . unsafeRunExceptT $ putTxHistory wid hry + liftIO . unsafeRunExceptT $ W.listAssets wl wid + let tx = Tx { txId + , fee = Nothing + , resolvedCollateral = mempty + , resolvedInputs = mempty + , outputs = [out1, out2] + , metadata = mempty + , withdrawals = mempty + , scriptValidity = Nothing + } + assets <- listHistoricalAssets [ (tx, txMeta) ] + monitor $ report out1 "Output with related address" + monitor $ report out2 "Output with unrelated address" + monitor $ report assets "Discovered assets" + assert $ assets == getAssets (out1 ^. #tokens) + where + genOuts :: + Gen (TxOut, TxOut, (WalletId, WalletName, DummyStateWithAddresses)) + genOuts = do + relatedAddress <- genAddress + unrelatedAddress <- genAddress `suchThat` (/= relatedAddress) + coin <- genCoinPositive + let bundle aid = TokenBundle coin . TokenMap.singleton aid <$> + genTokenQuantityPositive + tokenBundle1 <- genAssetIdLargeRange >>= bundle + tokenBundle2 <- genAssetIdLargeRange >>= bundle + wId <- arbitrary + wName <- arbitrary + pure ( TxOut { tokens = tokenBundle1, address = relatedAddress } + , TxOut { tokens = tokenBundle2, address = unrelatedAddress } + , (wId, wName, DummyStateWithAddresses [relatedAddress]) + ) + {------------------------------------------------------------------------------- Properties of tx fee estimation -------------------------------------------------------------------------------} @@ -1048,15 +1110,10 @@ genMigrationUTxO mockTxConstraints = do UTxO . Map.fromList <$> replicateM entryCount genUTxOEntry where genUTxOEntry :: Gen (TxIn, TxOut) - genUTxOEntry = (,) <$> genTxIn <*> genTxOut - where - genTxIn :: Gen TxIn - genTxIn = genTxInLargeRange - - genTxOut :: Gen TxOut - genTxOut = TxOut - <$> genAddress - <*> genTokenBundleMixed mockTxConstraints + genUTxOEntry = + (,) + <$> genTxInLargeRange + <*> (TxOut <$> genAddress <*> genTokenBundleMixed mockTxConstraints) -- Tests that user-specified target addresses are assigned to generated outputs -- in the correct cyclical order. @@ -1226,17 +1283,23 @@ instance Arbitrary UTxO where <*> vector n return $ UTxO $ Map.fromList utxo -data WalletLayerFixture m = WalletLayerFixture - { _fixtureDBLayer :: DBLayer m DummyState ShelleyKey - , _fixtureWalletLayer :: WalletLayer m DummyState ShelleyKey +data WalletLayerFixture s m = WalletLayerFixture + { _fixtureDBLayer :: DBLayer m s ShelleyKey + , _fixtureWalletLayer :: WalletLayer m s ShelleyKey , _fixtureWallet :: [WalletId] , _fixtureSlotNoTime :: SlotNo -> UTCTime } setupFixture - :: (MonadUnliftIO m, MonadFail m, MonadTime m) - => (WalletId, WalletName, DummyState) - -> m (WalletLayerFixture m) + :: forall s m + . ( MonadUnliftIO m + , MonadFail m + , MonadTime m + , IsOurs s Address + , IsOurs s RewardAccount + ) + => (WalletId, WalletName, s) + -> m (WalletLayerFixture s m) setupFixture (wid, wname, wstate) = do let nl = mockNetworkLayer let tl = dummyTransactionLayer @@ -1353,7 +1416,7 @@ instance Sqlite.AddressBookIso DummyState where instance Eq (Sqlite.Prologue DummyState) where _ == _ = True instance Eq (Sqlite.Discoveries DummyState) where DummyDiscoveries a == DummyDiscoveries b = a == b - + instance Sqlite.PersistAddressBook DummyState where insertPrologue _ _ = error "DummyState.insertPrologue: not implemented" insertDiscoveries _ _ _ = error "DummyState.insertDiscoveries: not implemented" @@ -1407,7 +1470,6 @@ instance Arbitrary (Passphrase purpose) where arbitrary = Passphrase . BA.convert . BS.pack <$> replicateM 16 arbitrary - instance Arbitrary SomeMnemonic where arbitrary = SomeMnemonic <$> genMnemonic @12 diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index c253d389488..9062824b735 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -5633,8 +5633,8 @@ paths: List all assets associated with the wallet, and their metadata if known. - An asset is _associated_ with a wallet if it is involved in a - transaction of the wallet. + An asset is _associated_ with a wallet if, at one point in history, + it was spendable by the wallet. parameters: - *parametersWalletId responses: *responsesListAssets diff --git a/test/e2e/spec/e2e_spec.rb b/test/e2e/spec/e2e_spec.rb index 3092ec44bdc..287e111daa2 100644 --- a/test/e2e/spec/e2e_spec.rb +++ b/test/e2e/spec/e2e_spec.rb @@ -19,11 +19,11 @@ wait_for_all_shared_wallets(@nightly_shared_wallets) wait_for_all_byron_wallets(@nighly_byron_wallets) - # @wid_sha = "d20b7f812fb571e7a3b14fb8a13c595d32cad5e6" + # @wid_sha = "f7b49bb7d58f7986e2394fefdc459a0ce67f42fa" # @wid_rnd = "12cbebfdc4521766e63a7e07c4825b24deb4176c" # @wid_ic = "f5da82c1eb3e391a535dd5ba2867fe9bdaf2f313" # @wid = "a042bafdaf98844cfa8f6d4b1dc47519b21a4d95" - # @target_id = "daf9043925bfe12cd891c6c4495c108cdb120632" + # @target_id = "d11ceb4d63f69fa0e8a02927d3f866f5fb5f6112" # 1f82e83772b7579fc0854bd13db6a9cce21ccd95 # 2269611a3c10b219b0d38d74b004c298b76d16a9 # a042bafdaf98844cfa8f6d4b1dc47519b21a4d95 @@ -409,6 +409,17 @@ def run_contract(contract_setup, scripts) verify_asset_balance(src_after, src_before, target_after, target_before, amt) + + # Target wallet only lists my associated assets + assets = SHELLEY.assets.get(@target_id) + expect(assets).to be_correct_and_respond 200 + expect(assets.size).to eq 2 + expect(assets.to_s).to include ASSETS[0]["policy_id"] + expect(assets.to_s).to include ASSETS[0]["asset_name"] + expect(assets.to_s).to include ASSETS[0]["metadata"]["name"] + expect(assets.to_s).to include ASSETS[1]["policy_id"] + expect(assets.to_s).to include ASSETS[1]["asset_name"] + expect(assets.to_s).to include ASSETS[1]["metadata"]["name"] end it "Only withdrawal" do @@ -633,10 +644,6 @@ def run_contract(contract_setup, scripts) describe "E2E Shelley" do describe "Native Assets" do it "I can list native assets" do - skip %(Underlying query is too large for token-metadata-server - which causes this test to fail as token-metadata-server returns 502. - ADP-710 should improve things a bit.) - assets = SHELLEY.assets.get @wid expect(assets).to be_correct_and_respond 200 expect(assets.to_s).to include ASSETS[0]["policy_id"] @@ -1124,6 +1131,17 @@ def test_byron_assets_tx(source_id, target_id) verify_asset_balance(src_after, src_before, target_after, target_before, amt) + + # Target wallet only lists my associated assets + assets = SHELLEY.assets.get(target_id) + expect(assets).to be_correct_and_respond 200 + expect(assets.size).to eq 2 + expect(assets.to_s).to include ASSETS[0]["policy_id"] + expect(assets.to_s).to include ASSETS[0]["asset_name"] + expect(assets.to_s).to include ASSETS[0]["metadata"]["name"] + expect(assets.to_s).to include ASSETS[1]["policy_id"] + expect(assets.to_s).to include ASSETS[1]["asset_name"] + expect(assets.to_s).to include ASSETS[1]["metadata"]["name"] end describe "Byron Transactions" do