diff --git a/lib/core-integration/src/Test/Integration/Framework/DSL.hs b/lib/core-integration/src/Test/Integration/Framework/DSL.hs index 69ef4ef25e0..9fbdee0a83b 100644 --- a/lib/core-integration/src/Test/Integration/Framework/DSL.hs +++ b/lib/core-integration/src/Test/Integration/Framework/DSL.hs @@ -1115,8 +1115,8 @@ rewardWallet ctx = do eventually "MIR wallet: wallet is 100% synced " $ do rg <- request @ApiWallet ctx (Link.getWallet @'Shelley w) Default Empty verify rg - [ expectField (#balance . #getApiT . #available . #getQuantity) (.> 0) - , expectField (#balance . #getApiT . #reward . #getQuantity) (.> 0) + [ expectField (#balance . #available . #getQuantity) (.> 0) + , expectField (#balance . #reward . #getQuantity) (.> 0) ] pure (getFromResponse id rg, mw) @@ -1184,7 +1184,7 @@ fixtureWalletWithMnemonics ctx = snd <$> allocate create (free . fst) checkBalance w = do r <- request @ApiWallet ctx (Link.getWallet @'Shelley w) Default Empty - if getFromResponse (#balance . #getApiT . #available) r > Quantity 0 + if getFromResponse (#balance . #available) r > Quantity 0 then return (getFromResponse id r) else threadDelay oneSecond *> checkBalance w @@ -1387,7 +1387,7 @@ fixtureWalletWith ctx coins0 = do -- ^ Coins to move -> IO () moveCoins src dest coins = do - balance <- getFromResponse (#balance . #getApiT . #available . #getQuantity) + balance <- getFromResponse (#balance . #available . #getQuantity) <$> request @ApiWallet ctx (Link.getWallet @'Shelley dest) Default Empty addrs <- fmap (view #id) . getFromResponse id @@ -1411,14 +1411,14 @@ fixtureWalletWith ctx coins0 = do rb <- request @ApiWallet ctx (Link.getWallet @'Shelley dest) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (sum (balance:coins))) rb ra <- request @ApiWallet ctx (Link.getWallet @'Shelley src) Default Empty - getFromResponse (#balance . #getApiT . #available) ra + getFromResponse (#balance . #available) ra `shouldBe` - getFromResponse (#balance . #getApiT . #total) ra + getFromResponse (#balance . #total) ra -- | Move coins from a wallet to another moveByronCoins diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Byron/CoinSelections.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Byron/CoinSelections.hs index d3d01d5fe01..7f8b0d7ff24 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Byron/CoinSelections.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Byron/CoinSelections.hs @@ -87,7 +87,7 @@ spec = describe "BYRON_COIN_SELECTION" $ do rnW <- emptyRandomWallet ctx shW <- emptyWallet ctx (addr:_) <- fmap (view #id) <$> listAddresses @n ctx shW - let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) ] + let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) mempty ] selectCoins @_ @'Byron ctx rnW payments >>= flip verify [ expectResponseCode HTTP.status403 , expectErrorMessage errMsg403NotAnIcarusWallet @@ -100,7 +100,7 @@ spec = describe "BYRON_COIN_SELECTION" $ do target <- emptyWallet ctx targetAddress : _ <- fmap (view #id) <$> listAddresses @n ctx target let amt = Quantity minUTxOValue - let payment = AddressAmount targetAddress amt + let payment = AddressAmount targetAddress amt mempty let output = ApiCoinSelectionOutput targetAddress amt let isValidDerivationPath path = ( length path == 5 ) @@ -136,6 +136,7 @@ spec = describe "BYRON_COIN_SELECTION" $ do let amounts = Quantity <$> [minUTxOValue ..] let payments = NE.fromList $ take paymentCount + $ map ($ mempty) $ zipWith AddressAmount targetAddresses amounts let outputs = take paymentCount @@ -153,7 +154,7 @@ spec = describe "BYRON_COIN_SELECTION" $ do icW <- emptyIcarusWallet ctx shW <- emptyWallet ctx (addr:_) <- fmap (view #id) <$> listAddresses @n ctx shW - let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) ] + let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) mempty ] _ <- request @ApiByronWallet ctx (Link.deleteWallet @'Byron icW) Default Empty selectCoins @_ @'Byron ctx icW payments >>= flip verify [ expectResponseCode HTTP.status404 @@ -168,7 +169,7 @@ spec = describe "BYRON_COIN_SELECTION" $ do targetAddress:_ <- fmap (view #id) <$> listAddresses @n ctx target let amt = Quantity minUTxOValue - let payment = AddressAmount targetAddress amt + let payment = AddressAmount targetAddress amt mempty let output = ApiCoinSelectionOutput targetAddress amt let isValidDerivationPath path = ( length path == 5 ) diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Byron/HWWallets.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Byron/HWWallets.hs index 02e07d89354..1a11d46cda7 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Byron/HWWallets.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Byron/HWWallets.hs @@ -330,7 +330,7 @@ spec = describe "BYRON_HW_WALLETS" $ do icarusAddresses @n mnemonics let targetAmounts = take paymentCount $ Quantity <$> [minUTxOValue ..] - let payments = NE.fromList $ + let payments = NE.fromList $ map ($ mempty) $ zipWith AddressAmount targetAddresses targetAmounts let outputs = zipWith ApiCoinSelectionOutput targetAddresses targetAmounts diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Byron/Migrations.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Byron/Migrations.hs index c44f55dc1c8..e4d400e64fb 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Byron/Migrations.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Byron/Migrations.hs @@ -293,10 +293,10 @@ spec = describe "BYRON_MIGRATIONS" $ do Default Empty >>= flip verify [ expectField - (#balance . #getApiT . #available) + (#balance . #available) (.> (Quantity expectedMinBalance)) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (.> (Quantity expectedMinBalance)) ] @@ -564,9 +564,9 @@ spec = describe "BYRON_MIGRATIONS" $ do (Link.getWallet @'Shelley targetWallet) Default Empty verify r2 [ expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity expectedBalance) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity expectedBalance) ] diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs index 1acb25765bc..fe1ecde795f 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Addresses.hs @@ -220,7 +220,7 @@ spec = describe "SHELLEY_ADDRESSES" $ do rb <- request @ApiWallet ctx (Link.getWallet @'Shelley wDest) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (10 * 1_000_000)) rb diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/CoinSelections.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/CoinSelections.hs index b83f98e1f57..435518737a9 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/CoinSelections.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/CoinSelections.hs @@ -98,7 +98,7 @@ spec = describe "SHELLEY_COIN_SELECTION" $ do target <- emptyWallet ctx targetAddress : _ <- fmap (view #id) <$> listAddresses @n ctx target let amount = Quantity minUTxOValue - let payment = AddressAmount targetAddress amount + let payment = AddressAmount targetAddress amount mempty let output = ApiCoinSelectionOutput targetAddress amount let isValidDerivationPath path = ( length path == 5 ) @@ -134,6 +134,7 @@ spec = describe "SHELLEY_COIN_SELECTION" $ do let amounts = Quantity <$> [minUTxOValue ..] let payments = NE.fromList $ take paymentCount + $ map ($ mempty) $ zipWith AddressAmount targetAddresses amounts let outputs = take paymentCount @@ -150,7 +151,7 @@ spec = describe "SHELLEY_COIN_SELECTION" $ do \Deleted wallet is not available for selection" $ \ctx -> runResourceT $ do w <- emptyWallet ctx (addr:_) <- fmap (view #id) <$> listAddresses @n ctx w - let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) ] + let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) mempty ] _ <- request @ApiWallet ctx (Link.deleteWallet @'Shelley w) Default Empty selectCoins @_ @'Shelley ctx w payments >>= flip verify [ expectResponseCode HTTP.status404 @@ -161,7 +162,7 @@ spec = describe "SHELLEY_COIN_SELECTION" $ do \Wrong selection method (not 'random')" $ \ctx -> runResourceT $ do w <- fixtureWallet ctx (addr:_) <- fmap (view #id) <$> listAddresses @n ctx w - let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) ] + let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) mempty ] let payload = Json [json| { "payments": #{payments} } |] let wid = toText $ getApiT $ w ^. #id let endpoints = ("POST",) . mconcat <$> @@ -209,7 +210,7 @@ spec = describe "SHELLEY_COIN_SELECTION" $ do forM_ matrix $ \(title, headers, expectations) -> it title $ \ctx -> runResourceT $ do w <- fixtureWallet ctx (addr:_) <- fmap (view #id) <$> listAddresses @n ctx w - let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) ] + let payments = NE.fromList [ AddressAmount addr (Quantity minUTxOValue) mempty ] let payload = Json [json| { "payments": #{payments} } |] r <- request @(ApiCoinSelection n) ctx (Link.selectCoins @'Shelley w) headers payload @@ -224,17 +225,17 @@ spec = describe "SHELLEY_COIN_SELECTION" $ do (Link.getWallet @'Shelley source) Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity (2 * minUTxOValue)) , expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (2 * minUTxOValue)) ] target <- emptyWallet ctx targetAddress:_ <- fmap (view #id) <$> listAddresses @n ctx target let amount = Quantity minUTxOValue - let payment = AddressAmount targetAddress amount + let payment = AddressAmount targetAddress amount mempty let output = ApiCoinSelectionOutput targetAddress amount let isValidDerivationPath path = ( length path == 5 ) diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/HWWallets.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/HWWallets.hs index 533583ced70..d0bc0de1916 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/HWWallets.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/HWWallets.hs @@ -103,8 +103,8 @@ spec = describe "SHELLEY_HW_WALLETS" $ do rInit <- postWallet ctx payldCrt verify rInit [ expectResponseCode HTTP.status201 - , expectField (#balance . #getApiT . #available) (`shouldBe` Quantity 0) - , expectField (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + , expectField (#balance . #available) (`shouldBe` Quantity 0) + , expectField (#balance . #total) (`shouldBe` Quantity 0) ] --send funds @@ -130,9 +130,9 @@ spec = describe "SHELLEY_HW_WALLETS" $ do (Link.getWallet @'Shelley wDest) Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity minUTxOValue) + (#balance . #total) (`shouldBe` Quantity minUTxOValue) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity minUTxOValue) + (#balance . #available) (`shouldBe` Quantity minUTxOValue) ] -- delete wallet @@ -149,9 +149,9 @@ spec = describe "SHELLEY_HW_WALLETS" $ do (Link.getWallet @'Shelley wDest') Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity minUTxOValue) + (#balance . #total) (`shouldBe` Quantity minUTxOValue) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity minUTxOValue) + (#balance . #available) (`shouldBe` Quantity minUTxOValue) ] describe "HW_WALLETS_03 - Cannot do operations requiring private key" $ do @@ -312,7 +312,7 @@ spec = describe "SHELLEY_HW_WALLETS" $ do fmap (view #id) <$> listAddresses @n ctx target let targetAmounts = take paymentCount $ Quantity <$> [minUTxOValue ..] - let payments = NE.fromList $ + let payments = NE.fromList $ map ($ mempty) $ zipWith AddressAmount targetAddresses targetAmounts let outputs = zipWith ApiCoinSelectionOutput targetAddresses targetAmounts diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Migrations.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Migrations.hs index ecefc3edf2e..428536508ad 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Migrations.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Migrations.hs @@ -186,10 +186,10 @@ spec = describe "SHELLEY_MIGRATIONS" $ do Default Empty verify r - [ expectField (#balance . #getApiT . #available) (.> Quantity 0) + [ expectField (#balance . #available) (.> Quantity 0) ] return $ getFromResponse - (#balance . #getApiT . #available . #getQuantity) r + (#balance . #available . #getQuantity) r -- Calculate the expected migration fee: rFee <- request @ApiWalletMigrationInfo ctx @@ -232,10 +232,10 @@ spec = describe "SHELLEY_MIGRATIONS" $ do Default Empty >>= flip verify [ expectField - (#balance . #getApiT . #available) + (#balance . #available) (.> (Quantity expectedMinBalance)) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (.> (Quantity expectedMinBalance)) ] @@ -290,9 +290,9 @@ spec = describe "SHELLEY_MIGRATIONS" $ do Default Empty verify rg - [ expectField (#balance . #getApiT . #available) (.> Quantity 0) + [ expectField (#balance . #available) (.> Quantity 0) ] - pure $ getFromResponse (#balance . #getApiT. #available . #getQuantity) + pure $ getFromResponse (#balance. #available . #getQuantity) rg -- Calculate the expected migration fee: @@ -325,10 +325,10 @@ spec = describe "SHELLEY_MIGRATIONS" $ do Default Empty >>= flip verify [ expectField - (#balance . #getApiT . #available) + (#balance . #available) ( `shouldBe` Quantity expectedBalance) , expectField - (#balance . #getApiT . #total) + (#balance . #total) ( `shouldBe` Quantity expectedBalance) ] @@ -485,7 +485,7 @@ spec = describe "SHELLEY_MIGRATIONS" $ do -- Restore a Shelley wallet with funds, to act as a source wallet: sourceWallet <- fixtureWallet ctx let originalBalance = - view (#balance . #getApiT. #available . #getQuantity) + view (#balance. #available . #getQuantity) sourceWallet -- Create an empty target wallet: @@ -524,10 +524,10 @@ spec = describe "SHELLEY_MIGRATIONS" $ do (Link.getWallet @'Shelley targetWallet) Default Empty verify r2 [ expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity expectedBalance) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity expectedBalance) ] @@ -536,9 +536,9 @@ spec = describe "SHELLEY_MIGRATIONS" $ do (Link.getWallet @'Shelley sourceWallet) Default Empty verify r3 [ expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity 0) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity 0) ] diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs index 67e67188bbf..f61f115efae 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/StakePools.hs @@ -258,13 +258,13 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do Default Empty verify r [ expectField - (#balance . #getApiT . #reward) + (#balance . #reward) (.> (Quantity 0)) ] let availableBalance = - getFromResponse (#balance . #getApiT . #available) r + getFromResponse (#balance . #available) r let rewardBalance = - getFromResponse (#balance . #getApiT . #reward) r + getFromResponse (#balance . #reward) r pure (availableBalance, rewardBalance) -- Try to use rewards @@ -299,7 +299,7 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do request @ApiWallet ctx (Link.getWallet @'Shelley src) Default Empty >>= flip verify [ expectField - (#balance . #getApiT . #reward) (`shouldBe` walletRewards) + (#balance . #reward) (`shouldBe` walletRewards) ] -- there's currently no withdrawals in the wallet @@ -338,10 +338,10 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do request @ApiWallet ctx (Link.getWallet @'Shelley src) Default Empty >>= flip verify [ expectField - (#balance . #getApiT . #reward) + (#balance . #reward) (`shouldBe` (Quantity 0)) , expectField - (#balance . #getApiT . #available) + (#balance . #available) (.> previousBalance) ] @@ -600,7 +600,7 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do eventually "Wallet gets rewards" $ do request @ApiWallet ctx (Link.getWallet @'Shelley w) Default Empty >>= flip verify - [ expectField (#balance . #getApiT . #reward) + [ expectField (#balance . #reward) (.> (Quantity 0)) ] @@ -902,10 +902,10 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do Default Empty >>= flip verify [ expectField #delegation (`shouldBe` notDelegating []) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldSatisfy` (== (Quantity (depositAmt ctx + change)))) , expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldSatisfy` (== (Quantity (depositAmt ctx + change)))) ] diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs index fc844ec18b1..07192ec8d88 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Transactions.hs @@ -322,13 +322,13 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do verify ra [ expectSuccess - , expectField (#balance . #getApiT . #total) $ + , expectField (#balance . #total) $ between ( Quantity (initialAmt - feeMax - amt) , Quantity (initialAmt - feeMin - amt) ) , expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity 0) ] @@ -364,13 +364,13 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do rb <- request @ApiWallet ctx (Link.getWallet @'Shelley wb) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (initialAmt + amt)) rb ra2 <- request @ApiWallet ctx (Link.getWallet @'Shelley wa) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (initialAmt - feeMax - amt)) ra2 it "TRANS_CREATE_02x - Multiple Output Tx to single wallet" $ \ctx -> runResourceT $ do @@ -418,13 +418,13 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do ] verify ra - [ expectField (#balance . #getApiT . #total) $ + [ expectField (#balance . #total) $ between ( Quantity (faucetAmt - feeMax - (2*amt)) , Quantity (faucetAmt - feeMin - (2*amt)) ) , expectField - (#balance . #getApiT . #available) + (#balance . #available) (.>= Quantity (faucetAmt - 2 * faucetUtxoAmt)) ] eventually "wDest balance is as expected" $ do @@ -432,10 +432,10 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do (Link.getWallet @'Shelley wDest) Default Empty verify rd [ expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (2*amt)) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity (2*amt)) ] @@ -470,8 +470,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do ra <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty verify ra - [ expectField (#balance . #getApiT . #total) (`shouldBe` Quantity 0) - , expectField (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + [ expectField (#balance . #total) (`shouldBe` Quantity 0) + , expectField (#balance . #available) (`shouldBe` Quantity 0) ] eventually "Wallet balance is as expected" $ do @@ -479,17 +479,17 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do (Link.getWallet @'Shelley wDest) Default Empty verify rd [ expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (2*amt)) , expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity (2*amt)) ] ra2 <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty verify ra2 - [ expectField (#balance . #getApiT . #total) (`shouldBe` Quantity 0) - , expectField (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + [ expectField (#balance . #total) (`shouldBe` Quantity 0) + , expectField (#balance . #available) (`shouldBe` Quantity 0) ] it "TRANS_CREATE_04 - Can't cover fee" $ \ctx -> runResourceT $ do @@ -644,7 +644,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do rb <- request @ApiWallet ctx (Link.getWallet @'Shelley wShelley) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (faucetAmt + amt)) rb ra2 <- request @ApiByronWallet ctx @@ -976,7 +976,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do verify r1 [ expectResponseCode HTTP.status201 , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) ] let wSrc = getFromResponse Prelude.id r1 @@ -1014,7 +1014,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do let (Hash txid) = getApiT $ getFromResponse #id r3 let txix = case getFromResponse #outputs r3 of - [(AddressAmount _ (Quantity out1)), (AddressAmount _ (Quantity out2))] + [(AddressAmount _ (Quantity out1) _), (AddressAmount _ (Quantity out2) _)] | out1 == amtSrc -> 0 | out2 == amtSrc -> 1 | otherwise -> error "this should not happen" @@ -1024,13 +1024,13 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do r' <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity amtSrc) r' r'' <- request @ApiWallet ctx (Link.getWallet @'Shelley wFaucet) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (between wFaucetBalRange) r'' -- #2238 quick fix to reduce likelihood of rollback. @@ -1053,7 +1053,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do [ expectSuccess , expectResponseCode HTTP.status201 , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) ] let wDest = getFromResponse Prelude.id r4 @@ -1115,13 +1115,13 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do r' <- request @ApiWallet ctx (Link.getWallet @'Shelley wDest) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity amtDest) r' r'' <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity outChange) r'' it "TRANS_EXTERNAL_02 - Multiple Outputs Transaction - Shelley witnesses" $ \ctx -> runResourceT $ do @@ -1144,7 +1144,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do verify r1 [ expectResponseCode HTTP.status201 , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) ] let wSrc = getFromResponse Prelude.id r1 @@ -1188,7 +1188,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do let (Hash txid) = getApiT $ getFromResponse #id r3 let (txix1, txix2) = case getFromResponse #outputs r3 of - [ (AddressAmount _ (Quantity out1)), (AddressAmount _ (Quantity out2)), (AddressAmount _ (Quantity out3)), (AddressAmount _ (Quantity out4))] -> + [ (AddressAmount _ (Quantity out1) _), (AddressAmount _ (Quantity out2) _), (AddressAmount _ (Quantity out3) _), (AddressAmount _ (Quantity out4) _)] -> let pairs = [(out1, 0), (out2, 1), (out3, 2), (out4, 3)] (Just ix1) = L.lookup amt1 pairs (Just ix2) = L.lookup amt2 pairs @@ -1199,14 +1199,14 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do r' <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity amtSrc) r' r'' <- request @ApiWallet ctx (Link.getWallet @'Shelley wFaucet) Default Empty txs <- listTransactions @n ctx wFaucet Nothing Nothing Nothing expectField - (#balance . #getApiT . #available) + (#balance . #available) (between wFaucetBalRange) r'' & counterexample ("fee response: " <> show r2) & counterexample ("faucet txs: " <> show txs) @@ -1230,7 +1230,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do verify r4 [ expectResponseCode HTTP.status201 , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) ] let wDest = getFromResponse Prelude.id r4 @@ -1300,13 +1300,13 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do r' <- request @ApiWallet ctx (Link.getWallet @'Shelley wDest) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity amtDest) r' r'' <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity outChange) r'' describe "TRANS_EXTERNAL_03 - Single Output Transaction with Byron witness" $ do @@ -1377,7 +1377,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do let (Hash txid) = getApiT $ getFromResponse #id r2 let txix = case getFromResponse #outputs r2 of - [(AddressAmount _ (Quantity out1)), (AddressAmount _ (Quantity out2))] + [(AddressAmount _ (Quantity out1) _), (AddressAmount _ (Quantity out2) _)] | out1 == amtSrc -> 0 | out2 == amtSrc -> 1 | otherwise -> error "this should not happen" @@ -1458,7 +1458,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do r' <- request @ApiWallet ctx (Link.getWallet @'Shelley wShelley) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity amtDest) r' r'' <- request @ApiByronWallet ctx @@ -1533,7 +1533,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do let (Hash txid) = getApiT $ getFromResponse #id r2 let txix = case getFromResponse #outputs r2 of - [(AddressAmount _ (Quantity out1)), (AddressAmount _ (Quantity out2))] + [(AddressAmount _ (Quantity out1) _), (AddressAmount _ (Quantity out2) _)] | out1 == amtSrc -> 0 | out2 == amtSrc -> 1 | otherwise -> error "this should not happen" @@ -1587,7 +1587,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do r' <- request @ApiWallet ctx (Link.getWallet @'Shelley wShelley) Default Empty expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity amtDest) r' r'' <- request @ApiByronWallet ctx @@ -1632,7 +1632,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do it "TRANS_ESTIMATE_03b - we see result when we can't cover fee (with withdrawal)" $ \ctx -> runResourceT $ do (wSrc, _) <- rewardWallet ctx addr:_ <- fmap (view #id) <$> listAddresses @n ctx wSrc - let totalBalance = wSrc ^. #balance . #getApiT . #total + let totalBalance = wSrc ^. #balance . #total let payload = Json [json|{ "withdrawal": "self", "payments": [{ @@ -1698,9 +1698,9 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do (Link.getWallet @'Shelley wDest) Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity amt) + (#balance . #total) (`shouldBe` Quantity amt) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity amt) + (#balance . #available) (`shouldBe` Quantity amt) ] -- Verify Tx list contains Incoming and Outgoing @@ -2130,9 +2130,9 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do (Link.getWallet @'Shelley wDest) Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity amt) + (#balance . #total) (`shouldBe` Quantity amt) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity amt) + (#balance . #available) (`shouldBe` Quantity amt) ] eventually "Transactions are available and in ledger" $ do @@ -2205,7 +2205,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do -- forget transaction (statusDelete, _) <- request @ApiTxId ctx (Link.deleteTransaction @'Shelley wSrc (ApiTxId txid)) Default Empty - rBalance <- getFromResponse (#balance . #getApiT . #total) + rBalance <- getFromResponse (#balance . #total) <$> request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty let assertSourceTx = do @@ -2424,9 +2424,9 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do rW <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default payload verify rW - [ expectField (#balance . #getApiT . #available) - (.> (wSrc ^. #balance . #getApiT . #available)) - , expectField (#balance . #getApiT . #reward) + [ expectField (#balance . #available) + (.> (wSrc ^. #balance . #available)) + , expectField (#balance . #reward) (`shouldBe` Quantity 0) ] @@ -2463,7 +2463,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do rWOther <- request @ApiWallet ctx (Link.getWallet @'Shelley wOther) Default payload verify rWOther - [ expectField (#balance . #getApiT . #reward) + [ expectField (#balance . #reward) (`shouldBe` Quantity 0) ] @@ -2485,8 +2485,8 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do rWSelf <- request @ApiWallet ctx (Link.getWallet @'Shelley wSelf) Default payload verify rWSelf - [ expectField (#balance . #getApiT . #available) - (.> (wSelf ^. #balance . #getApiT . #available)) + [ expectField (#balance . #available) + (.> (wSelf ^. #balance . #available)) ] eventually "withdrawal transaction is listed on self" $ do @@ -2526,7 +2526,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do rWOther <- request @ApiWallet ctx (Link.getWallet @'Shelley wOther) Default payload verify rWOther - [ expectField (#balance . #getApiT . #reward) + [ expectField (#balance . #reward) (`shouldBe` Quantity 0) ] @@ -2640,7 +2640,7 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do rWOther <- request @ApiWallet ctx (Link.getWallet @'Shelley wRewards) Default Empty verify rWOther - [ expectField (#balance . #getApiT . #available) + [ expectField (#balance . #available) (`shouldBe` Quantity 0) ] @@ -2772,14 +2772,18 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do -> Quantity "lovelace" Natural -> m () verifyWalletBalance ctx wallet amt = do - eventually "Wallet balance is as expected" $ do + eventually "Wallet Ada balance is as expected" $ do rGet <- request @ApiWallet ctx (Link.getWallet @'Shelley wallet) Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) (`shouldBe` amt) + (#balance . #total) (`shouldBe` amt) + , expectField + (#balance . #available) (`shouldBe` amt) + , expectField + (#assets . #total) (`shouldBe` mempty) , expectField - (#balance . #getApiT . #available) (`shouldBe` amt) + (#assets . #available) (`shouldBe` mempty) ] mkTxPayload diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Wallets.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Wallets.hs index 5cdb1d651a0..684db0a09de 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Wallets.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Wallets.hs @@ -166,10 +166,11 @@ spec = describe "SHELLEY_WALLETS" $ do (#name . #getApiT . #getWalletName) (`shouldBe` "1st Wallet") , expectField (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 30) - , expectField (#balance . #getApiT . #available) (`shouldBe` Quantity 0) - , expectField (#balance . #getApiT . #total) (`shouldBe` Quantity 0) - , expectField (#balance . #getApiT . #reward) (`shouldBe` Quantity 0) - + , expectField (#balance . #available) (`shouldBe` Quantity 0) + , expectField (#balance . #total) (`shouldBe` Quantity 0) + , expectField (#balance . #reward) (`shouldBe` Quantity 0) + , expectField (#assets . #total) (`shouldBe` mempty) + , expectField (#assets . #available) (`shouldBe` mempty) , expectField #delegation (`shouldBe` notDelegating []) , expectField #passphrase (`shouldNotBe` Nothing) ] @@ -205,11 +206,11 @@ spec = describe "SHELLEY_WALLETS" $ do , expectField (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 20) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) , expectField - (#balance . #getApiT . #reward) (`shouldBe` Quantity 0) + (#balance . #reward) (`shouldBe` Quantity 0) , expectField #delegation (`shouldBe` notDelegating []) , expectField #passphrase (`shouldNotBe` Nothing) ] @@ -228,8 +229,10 @@ spec = describe "SHELLEY_WALLETS" $ do rInit <- postWallet ctx payldCrt verify rInit [ expectResponseCode HTTP.status201 - , expectField (#balance . #getApiT . #available) (`shouldBe` Quantity 0) - , expectField (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + , expectField (#balance . #available) (`shouldBe` Quantity 0) + , expectField (#balance . #total) (`shouldBe` Quantity 0) + , expectField (#assets . #available) (`shouldBe` mempty) + , expectField (#assets . #total) (`shouldBe` mempty) ] --send funds @@ -254,10 +257,14 @@ spec = describe "SHELLEY_WALLETS" $ do rGet <- request @ApiWallet ctx (Link.getWallet @'Shelley wDest) Default Empty verify rGet - [ expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity minUTxOValue) - , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity minUTxOValue) + [ expectField (#balance . #total) + (`shouldBe` Quantity minUTxOValue) + , expectField (#balance . #available) + (`shouldBe` Quantity minUTxOValue) + , expectField (#assets . #available) + (`shouldBe` mempty) + , expectField (#assets . #total) + (`shouldBe` mempty) ] -- delete wallet @@ -272,9 +279,9 @@ spec = describe "SHELLEY_WALLETS" $ do (Link.getWallet @'Shelley wDest) Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity minUTxOValue) + (#balance . #total) (`shouldBe` Quantity minUTxOValue) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity minUTxOValue) + (#balance . #available) (`shouldBe` Quantity minUTxOValue) ] it "WALLETS_CREATE_03,09 - Cannot create wallet that exists" $ \ctx -> runResourceT $ do @@ -520,11 +527,11 @@ spec = describe "SHELLEY_WALLETS" $ do , expectField (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 20) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) , expectField - (#balance . #getApiT . #reward) (`shouldBe` Quantity 0) + (#balance . #reward) (`shouldBe` Quantity 0) , expectField (#state . #getApiT) (`shouldBe` Ready) , expectField #delegation (`shouldBe` notDelegating []) , expectField walletId (`shouldBe` w ^. walletId) @@ -563,11 +570,11 @@ spec = describe "SHELLEY_WALLETS" $ do , expectListField 0 (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 20) , expectListField 0 - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectListField 0 - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) , expectListField 0 - (#balance . #getApiT . #reward) (`shouldBe` Quantity 0) + (#balance . #reward) (`shouldBe` Quantity 0) , expectListField 0 #delegation (`shouldBe` notDelegating []) ] @@ -617,9 +624,9 @@ spec = describe "SHELLEY_WALLETS" $ do (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 20) , expectField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectField - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) , expectField #delegation (`shouldBe` notDelegating []) , expectField walletId (`shouldBe` walId) , expectField #passphrase (`shouldBe` passLastUpdateValue) @@ -940,10 +947,10 @@ spec = describe "SHELLEY_WALLETS" $ do (Link.getWallet @'Shelley wDest) Default Empty verify rGet [ expectField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity (fromIntegral $ sum coins)) , expectField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (fromIntegral $ sum coins)) ] diff --git a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Addresses.hs b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Addresses.hs index f9e02a75f46..25e744b91f3 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Addresses.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Addresses.hs @@ -184,7 +184,7 @@ spec = describe "SHELLEY_CLI_ADDRESSES" $ do Stdout o2 <- getWalletViaCLI ctx $ T.unpack (wDest ^. walletId) w <- expectValidJSON (Proxy @ApiWallet) o2 expectCliField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity (10 * 1_000_000)) w -- verify new address_pool_gap has been created diff --git a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs index ede2d7e6806..58033e0dacc 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/HWWallets.hs @@ -104,9 +104,9 @@ spec = describe "SHELLEY_CLI_HW_WALLETS" $ do wDest <- expectValidJSON (Proxy @ApiWallet) o1 verify wDest [ expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) ] --send transaction to the wallet @@ -126,9 +126,9 @@ spec = describe "SHELLEY_CLI_HW_WALLETS" $ do eventually "Wallet balance is as expected" $ do Stdout og <- getWalletViaCLI ctx $ T.unpack (wDest ^. walletId) jg <- expectValidJSON (Proxy @ApiWallet) og - expectCliField (#balance . #getApiT . #available) + expectCliField (#balance . #available) (`shouldBe` Quantity amount) jg - expectCliField (#balance . #getApiT . #total) + expectCliField (#balance . #total) (`shouldBe` Quantity amount) jg -- delete wallet @@ -149,10 +149,10 @@ spec = describe "SHELLEY_CLI_HW_WALLETS" $ do justRestored <- expectValidJSON (Proxy @ApiWallet) o3 verify justRestored [ expectCliField - (#balance . #getApiT . #available) + (#balance . #available) (`shouldBe` Quantity amount) , expectCliField - (#balance . #getApiT . #total) + (#balance . #total) (`shouldBe` Quantity amount) ] @@ -174,7 +174,7 @@ spec = describe "SHELLEY_CLI_HW_WALLETS" $ do Stdout o3 <- getWalletViaCLI ctx $ T.unpack (wRestored ^. walletId) justRestored <- expectValidJSON (Proxy @ApiWallet) o3 verify justRestored - [ expectCliField (#balance . #getApiT . #available) + [ expectCliField (#balance . #available) (.> Quantity 0) ] @@ -237,7 +237,7 @@ spec = describe "SHELLEY_CLI_HW_WALLETS" $ do eventually "Wallet has funds" $ do Stdout og <- getWalletViaCLI ctx $ T.unpack (wRestored ^. walletId) expectValidJSON (Proxy @ApiWallet) og >>= flip verify - [ expectCliField (#balance . #getApiT . #available) + [ expectCliField (#balance . #available) (.> Quantity 0) ] diff --git a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs index 7fcf6157d3f..c54d5f9b147 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Transactions.hs @@ -145,7 +145,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do gJson <- expectValidJSON (Proxy @ApiWallet) gOutSrc verify gJson [ expectCliField - (#balance . #getApiT . #total) + (#balance . #total) (.>= Quantity (faucetAmt - feeMax - amt)) ] @@ -155,9 +155,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do destJson <- expectValidJSON (Proxy @ApiWallet) gOutDest verify destJson [ expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity amt) + (#balance . #available) (`shouldBe` Quantity amt) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity amt) + (#balance . #total) (`shouldBe` Quantity amt) ] it "TRANS_CREATE_02 - Multiple Output Tx to single wallet via CLI" $ \ctx -> runResourceT $ do @@ -194,7 +194,7 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do gJson <- expectValidJSON (Proxy @ApiWallet) gOutSrc verify gJson [ expectCliField - (#balance . #getApiT . #total) + (#balance . #total) (.>= Quantity (faucetAmt - feeMax - (2*amt))) ] @@ -204,9 +204,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do destJson <- expectValidJSON (Proxy @ApiWallet) gOutDest verify destJson [ expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity (2*amt)) + (#balance . #available) (`shouldBe` Quantity (2*amt)) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity (2*amt)) + (#balance . #total) (`shouldBe` Quantity (2*amt)) ] it "TRANS_CREATE_04 - Wrong password" $ \ctx -> runResourceT $ do @@ -444,9 +444,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do destJson <- expectValidJSON (Proxy @ApiWallet) gOutDest verify destJson [ expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity amt) + (#balance . #available) (`shouldBe` Quantity amt) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity amt) + (#balance . #total) (`shouldBe` Quantity amt) ] -- Verify Tx list contains Incoming and Outgoing @@ -678,9 +678,9 @@ spec = describe "SHELLEY_CLI_TRANSACTIONS" $ do destJson <- expectValidJSON (Proxy @ApiWallet) gOutDest verify destJson [ expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity amt) + (#balance . #available) (`shouldBe` Quantity amt) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity amt) + (#balance . #total) (`shouldBe` Quantity amt) ] eventually "Transactions are available and in ledger" $ do diff --git a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Wallets.hs b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Wallets.hs index 9ae8a113a03..ea081b834f2 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Wallets.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/CLI/Shelley/Wallets.hs @@ -176,9 +176,9 @@ spec = describe "SHELLEY_CLI_WALLETS" $ do [ expectCliField (#name . #getApiT . #getWalletName) (`shouldBe` "n") , expectCliField (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 20) - , expectCliField (#balance . #getApiT . #available) (`shouldBe` Quantity 0) - , expectCliField (#balance . #getApiT . #total) (`shouldBe` Quantity 0) - , expectCliField (#balance . #getApiT . #reward) (`shouldBe` Quantity 0) + , expectCliField (#balance . #available) (`shouldBe` Quantity 0) + , expectCliField (#balance . #total) (`shouldBe` Quantity 0) + , expectCliField (#balance . #reward) (`shouldBe` Quantity 0) , expectCliField #delegation (`shouldBe` notDelegating []) , expectCliField #passphrase (`shouldNotBe` Nothing) ] @@ -199,9 +199,9 @@ spec = describe "SHELLEY_CLI_WALLETS" $ do wDest <- expectValidJSON (Proxy @ApiWallet) o1 verify wDest [ expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) ] --send transaction to the wallet @@ -221,9 +221,9 @@ spec = describe "SHELLEY_CLI_WALLETS" $ do eventually "Wallet balance is as expected" $ do Stdout og <- getWalletViaCLI ctx $ T.unpack (wDest ^. walletId) jg <- expectValidJSON (Proxy @ApiWallet) og - expectCliField (#balance . #getApiT . #available) + expectCliField (#balance . #available) (`shouldBe` Quantity amount) jg - expectCliField (#balance . #getApiT . #total) + expectCliField (#balance . #total) (`shouldBe` Quantity amount) jg -- delete wallet @@ -246,9 +246,9 @@ spec = describe "SHELLEY_CLI_WALLETS" $ do justRestored <- expectValidJSON (Proxy @ApiWallet) o3 verify justRestored [ expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity amount) + (#balance . #available) (`shouldBe` Quantity amount) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity amount) + (#balance . #total) (`shouldBe` Quantity amount) , expectCliField walletId (`shouldBe` wDest ^. walletId) ] @@ -431,11 +431,11 @@ spec = describe "SHELLEY_CLI_WALLETS" $ do , expectCliField (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 20) , expectCliField - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectCliField - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) , expectCliField - (#balance . #getApiT . #reward) (`shouldBe` Quantity 0) + (#balance . #reward) (`shouldBe` Quantity 0) , expectCliField #delegation (`shouldBe` notDelegating []) , expectCliField #passphrase (`shouldNotBe` Nothing) ] @@ -474,11 +474,11 @@ spec = describe "SHELLEY_CLI_WALLETS" $ do , expectCliListField 0 (#addressPoolGap . #getApiT . #getAddressPoolGap) (`shouldBe` 21) , expectCliListField 0 - (#balance . #getApiT . #available) (`shouldBe` Quantity 0) + (#balance . #available) (`shouldBe` Quantity 0) , expectCliListField 0 - (#balance . #getApiT . #total) (`shouldBe` Quantity 0) + (#balance . #total) (`shouldBe` Quantity 0) , expectCliListField 0 - (#balance . #getApiT . #reward) (`shouldBe` Quantity 0) + (#balance . #reward) (`shouldBe` Quantity 0) , expectCliListField 0 #delegation (`shouldBe` notDelegating []) , expectCliListField 0 walletId (`shouldBe` T.pack w1) ] @@ -738,9 +738,9 @@ spec = describe "SHELLEY_CLI_WALLETS" $ do eventually "Wallet balance is as expected" $ do Stdout og <- getWalletViaCLI ctx $ T.unpack (wDest ^. walletId) jg <- expectValidJSON (Proxy @ApiWallet) og - expectCliField (#balance . #getApiT . #available) + expectCliField (#balance . #available) (`shouldBe` Quantity (fromIntegral $ sum coins)) jg - expectCliField (#balance . #getApiT . #total) + expectCliField (#balance . #total) (`shouldBe` Quantity (fromIntegral $ sum coins)) jg --verify utxo diff --git a/lib/core/src/Cardano/Pool/DB/Sqlite.hs b/lib/core/src/Cardano/Pool/DB/Sqlite.hs index 41adfd2a6c5..7ad3581368d 100644 --- a/lib/core/src/Cardano/Pool/DB/Sqlite.hs +++ b/lib/core/src/Cardano/Pool/DB/Sqlite.hs @@ -140,6 +140,7 @@ import UnliftIO.Exception import qualified Cardano.Pool.DB.Sqlite.TH as TH import qualified Cardano.Wallet.Primitive.Types as W +import qualified Cardano.Wallet.Primitive.Types.Coin as W import qualified Data.Map.Strict as Map import qualified Data.Text as T import qualified Database.Sqlite as Sqlite @@ -300,8 +301,8 @@ newDBLayer trace fp ti = do $ getPercentage $ poolMargin cert) (fromIntegral $ denominator $ getPercentage $ poolMargin cert) - (getQuantity $ poolCost cert) - (getQuantity $ poolPledge cert) + (W.unCoin $ poolCost cert) + (W.unCoin $ poolPledge cert) (fst <$> poolMetadata cert) (snd <$> poolMetadata cert) _ <- repsert poolRegistrationKey poolRegistrationRow @@ -459,8 +460,8 @@ newDBLayer trace fp ti = do <$> fromPersistValue fieldPoolId <*> fromPersistValue fieldOwners <*> parseMargin - <*> (Quantity <$> fromPersistValue fieldCost) - <*> (Quantity <$> fromPersistValue fieldPledge) + <*> (W.Coin <$> fromPersistValue fieldCost) + <*> (W.Coin <$> fromPersistValue fieldPledge) <*> parseMetadata parseRetirementCertificate = do @@ -601,8 +602,8 @@ newDBLayer trace fp ti = do poolMetadataHash = entityVal meta let poolMargin = unsafeMkPercentage $ toRational $ marginNum % marginDen - let poolCost = Quantity poolCost_ - let poolPledge = Quantity poolPledge_ + let poolCost = W.Coin poolCost_ + let poolPledge = W.Coin poolPledge_ let poolMetadata = (,) <$> poolMetadataUrl <*> poolMetadataHash poolOwners <- fmap (poolOwnerOwner . entityVal) <$> selectList diff --git a/lib/core/src/Cardano/Wallet.hs b/lib/core/src/Cardano/Wallet.hs index 3c895534ee9..4898eaece08 100644 --- a/lib/core/src/Cardano/Wallet.hs +++ b/lib/core/src/Cardano/Wallet.hs @@ -322,7 +322,7 @@ import Cardano.Wallet.Primitive.Types import Cardano.Wallet.Primitive.Types.Address ( Address (..), AddressState (..) ) import Cardano.Wallet.Primitive.Types.Coin - ( Coin (..) ) + ( Coin (..), addCoin, coinQuantity, sumCoins ) import Cardano.Wallet.Primitive.Types.Hash ( Hash (..) ) import Cardano.Wallet.Primitive.Types.RewardAccount @@ -965,7 +965,7 @@ fetchRewardBalance ) => ctx -> WalletId - -> IO (Quantity "lovelace" Word64) + -> IO Coin fetchRewardBalance ctx wid = db & \DBLayer{..} -> atomically $ readDelegationRewardBalance pk where @@ -985,13 +985,13 @@ readNextWithdrawal ) => ctx -> WalletId - -> Quantity "lovelace" Word64 - -> IO (Quantity "lovelace" Word64) -readNextWithdrawal ctx wid (Quantity withdrawal) = db & \DBLayer{..} -> do + -> Coin + -> IO Coin +readNextWithdrawal ctx wid (Coin withdrawal) = db & \DBLayer{..} -> do liftIO (atomically $ readProtocolParameters $ PrimaryKey wid) <&> \case -- May happen if done very early, in which case, rewards are probably -- not woth considering anyway. - Nothing -> Quantity 0 + Nothing -> Coin 0 Just ProtocolParameters{txParameters} -> let policy = W.getFeePolicy txParameters @@ -1002,8 +1002,8 @@ readNextWithdrawal ctx wid (Quantity withdrawal) = db & \DBLayer{..} -> do in if toInteger withdrawal < 2 * costOfWithdrawal - then Quantity 0 - else Quantity withdrawal + then Coin 0 + else Coin withdrawal where db = ctx ^. dbLayer @s @k tl = ctx ^. transactionLayer @k @@ -1048,7 +1048,7 @@ queryRewardBalance ) => ctx -> RewardAccount - -> ExceptT ErrFetchRewards IO (Quantity "lovelace" Word64) + -> ExceptT ErrFetchRewards IO Coin queryRewardBalance ctx acct = do mapExceptT (fmap handleErr) $ getAccountBalance nw acct where @@ -1056,7 +1056,7 @@ queryRewardBalance ctx acct = do handleErr = \case Right x -> Right x Left (ErrGetAccountBalanceAccountNotFound _) -> - Right $ Quantity 0 + Right $ Coin 0 Left (ErrGetAccountBalanceNetworkUnreachable e) -> Left $ ErrFetchRewardsNetworkUnreachable e @@ -1292,7 +1292,7 @@ selectCoinsForPayment => ctx -> WalletId -> NonEmpty TxOut - -> Quantity "lovelace" Word64 + -> Coin -> Maybe TxMetadata -> ExceptT ErrSelectForPayment IO CoinSelection selectCoinsForPayment ctx wid recipients withdrawal md = do @@ -1301,7 +1301,7 @@ selectCoinsForPayment ctx wid recipients withdrawal md = do selectCoinsSetup @ctx @s @k ctx wid let pendingWithdrawal = Set.lookupMin $ Set.filter hasWithdrawal pending - when (withdrawal /= Quantity 0 && isJust pendingWithdrawal) $ throwE $ + when (withdrawal /= Coin 0 && isJust pendingWithdrawal) $ throwE $ ErrSelectForPaymentAlreadyWithdrawing (fromJust pendingWithdrawal) cs <- selectCoinsForPaymentFromUTxO @ctx @k @@ -1339,14 +1339,14 @@ selectCoinsForPaymentFromUTxO -> W.TxParameters -> W.Coin -> NonEmpty TxOut - -> Quantity "lovelace" Word64 + -> Coin -> Maybe TxMetadata -> ExceptT ErrSelectForPayment IO CoinSelection selectCoinsForPaymentFromUTxO ctx utxo txp minUtxo recipients withdrawal md = do lift . traceWith tr $ MsgPaymentCoinSelectionStart utxo txp recipients (sel, utxo') <- withExceptT handleCoinSelError $ do let opts = coinSelOpts tl (txp ^. #getTxMaxSize) md - CoinSelection.random opts recipients withdrawal utxo + CoinSelection.random opts recipients (coinQuantity withdrawal) utxo lift . traceWith tr $ MsgPaymentCoinSelection sel let feePolicy = feeOpts tl Nothing md txp minUtxo sel @@ -1455,10 +1455,7 @@ selectCoinsForMigration => ctx -> WalletId -- ^ The source wallet ID. - -> ExceptT ErrSelectForMigration IO - ( [CoinSelection] - , Quantity "lovelace" Natural - ) + -> ExceptT ErrSelectForMigration IO ([CoinSelection], Coin) selectCoinsForMigration ctx wid = do (utxo, _, txp, minUtxo) <- withExceptT ErrSelectForMigrationNoSuchWallet $ selectCoinsSetup @ctx @s @k ctx wid @@ -1476,10 +1473,7 @@ selectCoinsForMigrationFromUTxO -> W.Coin -> WalletId -- ^ The source wallet ID. - -> ExceptT ErrSelectForMigration IO - ( [CoinSelection] - , Quantity "lovelace" Natural - ) + -> ExceptT ErrSelectForMigration IO ([CoinSelection], Coin) selectCoinsForMigrationFromUTxO ctx utxo txp minUtxo wid = do let feePolicy@(LinearFee (Quantity a) _) = txp ^. #getFeePolicy let feeOptions = (feeOpts tl Nothing Nothing txp minBound mempty) @@ -1495,10 +1489,10 @@ selectCoinsForMigrationFromUTxO ctx utxo txp minUtxo wid = do liftIO $ traceWith tr $ MsgMigrationUTxOAfter resultDistribution liftIO $ traceWith tr $ MsgMigrationResult cs let leftovers = - W.balance utxo + unCoin (TokenBundle.getCoin $ W.balance utxo) - - fromIntegral (W.balance' $ concatMap inputs cs) - pure (cs, Quantity leftovers) + W.balance' (concatMap inputs cs) + pure (cs, Coin leftovers) _ -> throwE (ErrSelectForMigrationEmptyWallet wid) where tl = ctx ^. transactionLayer @k @@ -1537,7 +1531,7 @@ estimateFeeForPayment => ctx -> WalletId -> NonEmpty TxOut - -> Quantity "lovelace" Word64 + -> Coin -> Maybe TxMetadata -> ExceptT ErrSelectForPayment IO FeeEstimation estimateFeeForPayment ctx wid recipients withdrawal md = do @@ -1561,19 +1555,16 @@ estimateFeeForPayment ctx wid recipients withdrawal md = do handleCannotCover :: Monad m => UTxO - -> Quantity "lovelace" Word64 + -> Coin -> NonEmpty TxOut -> ErrSelectForPayment -> ExceptT ErrSelectForPayment m Fee -handleCannotCover utxo (Quantity withdrawal) outs = \case +handleCannotCover utxo withdrawal outs = \case ErrSelectForPaymentFee (ErrCannotCoverFee missing) -> do - let available - = fromIntegral (W.balance utxo) - + fromIntegral withdrawal - let payment - = sum (unCoin . txOutCoin <$> outs) - pure $ Fee $ - available + missing - payment + let available = addCoin withdrawal + (TokenBundle.getCoin $ W.balance utxo) + let payment = sumCoins (txOutCoin <$> outs) + pure $ Fee $ unCoin available + missing - unCoin payment e -> throwE e @@ -1905,7 +1896,7 @@ mkTxMeta ti' blockHeader wState tx cs expiry = , direction = if amtInps > amtOuts then Outgoing else Incoming , slotNo = blockHeader ^. #slotNo , blockHeight = blockHeader ^. #blockHeight - , amount = Quantity $ distance amtInps amtOuts + , amount = Coin $ fromIntegral $ distance amtInps amtOuts , expiry = Just expiry } ) @@ -1993,7 +1984,7 @@ listTransactions ) => ctx -> WalletId - -> Maybe (Quantity "lovelace" Natural) + -> Maybe Coin -- Inclusive minimum value of at least one withdrawal in each transaction -> Maybe UTCTime -- Inclusive minimum time bound. @@ -2002,7 +1993,7 @@ listTransactions -> SortOrder -> ExceptT ErrListTransactions IO [TransactionInfo] listTransactions ctx wid mMinWithdrawal mStart mEnd order = db & \DBLayer{..} -> do - when (Just True == ( (<(Quantity 1)) <$> mMinWithdrawal )) $ + when (Just True == ( (<(Coin 1)) <$> mMinWithdrawal )) $ throwE ErrListTransactionsMinWithdrawalWrong let pk = PrimaryKey wid mapExceptT atomically $ do @@ -2535,7 +2526,7 @@ data ErrCannotJoin data ErrCannotQuit = ErrNotDelegatingOrAboutTo - | ErrNonNullRewards (Quantity "lovelace" Word64) + | ErrNonNullRewards Coin deriving (Generic, Eq, Show) -- | Can't perform given operation because the wallet died. @@ -2620,7 +2611,7 @@ guardJoin knownPools delegation pid mRetirementEpochInfo = do guardQuit :: WalletDelegation - -> Quantity "lovelace" Word64 + -> Coin -> Either ErrCannotQuit () guardQuit WalletDelegation{active,next} rewards = do let last_ = maybe active (view #status) $ lastMay next @@ -2628,7 +2619,7 @@ guardQuit WalletDelegation{active,next} rewards = do unless (isDelegatingTo anyone last_) $ Left ErrNotDelegatingOrAboutTo - unless (rewards == Quantity 0) $ + unless (rewards == Coin 0) $ Left $ ErrNonNullRewards rewards where anyone = const True @@ -2680,7 +2671,7 @@ data WalletLog | MsgMigrationUTxOAfter UTxOStatistics | MsgMigrationResult [CoinSelection] | MsgRewardBalanceQuery BlockHeader - | MsgRewardBalanceResult (Either ErrFetchRewards (Quantity "lovelace" Word64)) + | MsgRewardBalanceResult (Either ErrFetchRewards Coin) | MsgRewardBalanceNoSuchWallet ErrNoSuchWallet | MsgRewardBalanceExited deriving (Show, Eq) diff --git a/lib/core/src/Cardano/Wallet/Api.hs b/lib/core/src/Cardano/Wallet/Api.hs index 61b135407bb..81955f046bb 100644 --- a/lib/core/src/Cardano/Wallet/Api.hs +++ b/lib/core/src/Cardano/Wallet/Api.hs @@ -33,6 +33,10 @@ module Cardano.Wallet.Api , GetWalletKey , SignMetadata + , Assets + , ListAssets + , GetAsset + , Addresses , ListAddresses , InspectAddress @@ -125,6 +129,7 @@ import Cardano.Wallet.Api.Types , ApiAddressInspect , ApiAddressInspectData , ApiAddressT + , ApiAsset , ApiByronWallet , ApiCoinSelectionT , ApiFee @@ -179,6 +184,8 @@ import Cardano.Wallet.Primitive.Types.Address ( AddressState ) import Cardano.Wallet.Primitive.Types.Coin ( Coin (..) ) +import Cardano.Wallet.Primitive.Types.TokenPolicy + ( TokenName, TokenPolicyId ) import Cardano.Wallet.Registry ( HasWorkerCtx (..), WorkerLog, WorkerRegistry ) import Cardano.Wallet.Transaction @@ -228,6 +235,7 @@ type ApiV2 n apiPool = "v2" :> Api n apiPool type Api n apiPool = Wallets :<|> WalletKeys + :<|> Assets :<|> Addresses n :<|> CoinSelections n :<|> Transactions n @@ -323,6 +331,38 @@ type SignMetadata = "wallets" :> ReqBody '[JSON] ApiWalletSignData :> Post '[OctetStream] ByteString +{------------------------------------------------------------------------------- + Assets + + See also: https://input-output-hk.github.io/cardano-wallet/api/#tag/Assets +-------------------------------------------------------------------------------} + +type Assets = + ListAssets + :<|> GetAsset + :<|> GetAssetDefault + +-- | https://input-output-hk.github.io/cardano-wallet/api/#operation/listAssets +type ListAssets = "wallets" + :> Capture "walletId" (ApiT WalletId) + :> "assets" + :> Get '[JSON] [ApiAsset] + +-- | https://input-output-hk.github.io/cardano-wallet/api/#operation/getAsset +type GetAsset = "wallets" + :> Capture "walletId" (ApiT WalletId) + :> "assets" + :> Capture "policyId" (ApiT TokenPolicyId) + :> Capture "assetName" (ApiT TokenName) + :> Get '[JSON] ApiAsset + +-- | https://input-output-hk.github.io/cardano-wallet/api/#operation/getAsset +type GetAssetDefault = "wallets" + :> Capture "walletId" (ApiT WalletId) + :> "assets" + :> Capture "policyId" (ApiT TokenPolicyId) + :> Get '[JSON] ApiAsset + {------------------------------------------------------------------------------- Addresses diff --git a/lib/core/src/Cardano/Wallet/Api/Server.hs b/lib/core/src/Cardano/Wallet/Api/Server.hs index 5c060204d37..a5c878651ba 100644 --- a/lib/core/src/Cardano/Wallet/Api/Server.hs +++ b/lib/core/src/Cardano/Wallet/Api/Server.hs @@ -50,6 +50,9 @@ module Cardano.Wallet.Api.Server , getUTxOsStatistics , getWallet , joinStakePool + , listAssets + , getAsset + , getAssetDefault , listAddresses , listTransactions , getTransaction @@ -165,6 +168,7 @@ import Cardano.Wallet.Api.Types , AddressAmount (..) , ApiAccountPublicKey (..) , ApiAddress (..) + , ApiAsset (..) , ApiBlockInfo (..) , ApiBlockReference (..) , ApiBlockReference (..) @@ -195,6 +199,8 @@ import Cardano.Wallet.Api.Types , ApiUtxoStatistics (..) , ApiVerificationKey (..) , ApiWallet (..) + , ApiWalletAssetsBalance (..) + , ApiWalletBalance (..) , ApiWalletDelegation (..) , ApiWalletDelegationNext (..) , ApiWalletDelegationStatus (..) @@ -214,12 +220,14 @@ import Cardano.Wallet.Api.Types , PostExternalTransactionData (..) , PostTransactionData (..) , PostTransactionFeeData (..) - , WalletBalance (..) , WalletOrAccountPostData (..) , WalletPostData (..) , WalletPutData (..) , WalletPutPassphraseData (..) + , coinFromQuantity + , coinToQuantity , getApiMnemonicT + , toApiAsset , toApiEpochInfo , toApiNetworkParameters , toApiUtxoStatistics @@ -316,6 +324,8 @@ import Cardano.Wallet.Primitive.Types.Coin ( Coin (..) ) import Cardano.Wallet.Primitive.Types.Hash ( Hash (..) ) +import Cardano.Wallet.Primitive.Types.TokenPolicy + ( TokenName (..), TokenPolicyId (..), nullTokenName ) import Cardano.Wallet.Primitive.Types.Tx ( TransactionInfo (TransactionInfo) , Tx (..) @@ -460,10 +470,12 @@ import qualified Cardano.Wallet.Primitive.AddressDerivation.Icarus as Icarus import qualified Cardano.Wallet.Primitive.Types as W import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TokenBundle import qualified Cardano.Wallet.Primitive.Types.Tx as W +import qualified Cardano.Wallet.Primitive.Types.UTxO as W import qualified Cardano.Wallet.Registry as Registry import qualified Data.Aeson as Aeson import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL +import qualified Data.Foldable as F import qualified Data.List.NonEmpty as NE import qualified Data.Map.Strict as Map import qualified Data.Text as T @@ -695,7 +707,7 @@ mkShelleyWallet mkShelleyWallet ctx wid cp meta pending progress = do reward <- withWorkerCtx @_ @s @k ctx wid liftE liftE $ \wrk -> -- never fails - returns zero if balance not found - liftIO $ fmap fromIntegral <$> W.fetchRewardBalance @_ @s @k wrk wid + liftIO $ W.fetchRewardBalance @_ @s @k wrk wid let ti = timeInterpreter $ ctx ^. networkLayer @@ -716,12 +728,18 @@ mkShelleyWallet ctx wid cp meta pending progress = do tip' <- liftIO $ getWalletTip (neverFails "getWalletTip wallet tip should be behind node tip" ti) cp + let available = availableBalance pending cp + let total = totalBalance pending reward cp pure ApiWallet { addressPoolGap = ApiT $ getState cp ^. #externalPool . #gap - , balance = ApiT $ WalletBalance - { available = Quantity $ availableBalance pending cp - , total = Quantity $ totalBalance pending reward cp - , reward + , balance = ApiWalletBalance + { available = coinToQuantity (available ^. #coin) + , total = coinToQuantity (total ^. #coin) + , reward = coinToQuantity reward + } + , assets = ApiWalletAssetsBalance + { available = ApiT (available ^. #tokens) + , total = ApiT (total ^. #tokens) } , delegation = apiDelegation , id = ApiT wid @@ -824,10 +842,12 @@ mkLegacyWallet ctx wid cp meta pending progress = do Left{} -> pure $ Just $ ApiWalletPassphraseInfo time tip' <- liftIO $ getWalletTip (expectAndThrowFailures ti) cp + let available = availableBalance pending cp + let total = totalBalance pending (Coin 0) cp pure ApiByronWallet { balance = ApiByronWalletBalance - { available = Quantity $ availableBalance pending cp - , total = Quantity $ totalBalance pending (Quantity 0) cp + { available = coinToQuantity $ TokenBundle.getCoin available + , total = coinToQuantity $ TokenBundle.getCoin total } , id = ApiT wid , name = ApiT $ meta ^. #name @@ -1163,7 +1183,7 @@ selectCoins ctx genChange (ApiT wid) body = $ \wrk -> do -- TODO: -- Allow representing withdrawals as part of external coin selections. - let withdrawal = Quantity 0 + let withdrawal = Coin 0 let outs = coerceCoin <$> body ^. #payments liftHandler $ W.selectCoinsExternal @_ @s @k wrk wid genChange @@ -1245,6 +1265,43 @@ selectCoinsForQuit ctx (ApiT wid) = do where genChange = delegationAddress @n +{------------------------------------------------------------------------------- + Assets +-------------------------------------------------------------------------------} + +listAssets + :: forall ctx s k. + ( ctx ~ ApiLayer s k + ) + => ctx + -> ApiT WalletId + -> Handler [ApiAsset] +listAssets ctx (ApiT wid) = do + utxo <- withWorkerCtx @_ @s @k ctx wid liftE liftE $ \wrk -> liftHandler $ do + (cp, _meta, _pending) <- W.readWallet @_ @s @k wrk wid + pure (cp ^. #utxo) + pure $ map (toApiAsset metadata) $ F.toList $ W.getAssets utxo + where + metadata = Nothing -- TODO: Use data from metadata server + +getAsset + :: ctx + -> ApiT WalletId + -> ApiT TokenPolicyId + -> ApiT TokenName + -> Handler ApiAsset +getAsset _ctx (ApiT _wid) policyId assetName = pure $ + ApiAsset { policyId, assetName, metadata } + where + metadata = Nothing -- TODO: Use data from metadata server + +getAssetDefault + :: ctx + -> ApiT WalletId + -> ApiT TokenPolicyId + -> Handler ApiAsset +getAssetDefault ctx wid policyId = getAsset ctx wid policyId (ApiT nullTokenName) + {------------------------------------------------------------------------------- Addresses -------------------------------------------------------------------------------} @@ -1357,7 +1414,7 @@ postTransaction ctx genChange (ApiT wid) body = do (selection, credentials) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do (wdrl, credentials) <- case body ^. #withdrawal of Nothing -> - pure (Quantity 0, selfRewardCredentials) + pure (Coin 0, selfRewardCredentials) Just SelfWithdrawal -> do (acct, _) <- liftHandler $ W.readRewardAccount @_ @s @k @n wrk wid @@ -1369,7 +1426,7 @@ postTransaction ctx genChange (ApiT wid) body = do let (xprv, acct) = W.someRewardAccount @ShelleyKey mw wdrl <- liftHandler (W.queryRewardBalance @_ wrk acct) >>= liftIO . W.readNextWithdrawal @_ @s @k wrk wid - when (wdrl == Quantity 0) $ do + when (wdrl == Coin 0) $ do liftHandler $ throwE ErrWithdrawalNotWorth pure (wdrl, const (xprv, mempty)) @@ -1416,7 +1473,7 @@ listTransactions listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder = do txs <- withWorkerCtx ctx wid liftE liftE $ \wrk -> liftHandler $ W.listTransactions @_ @_ @_ wrk wid - (Quantity . getMinWithdrawal <$> mMinWithdrawal) + (Coin . fromIntegral . getMinWithdrawal <$> mMinWithdrawal) (getIso8601Time <$> mStart) (getIso8601Time <$> mEnd) (maybe defaultSortOrder getApiT mOrder) @@ -1478,7 +1535,7 @@ postTransactionFee ctx (ApiT wid) body = do withWorkerCtx ctx wid liftE liftE $ \wrk -> do wdrl <- case body ^. #withdrawal of Nothing -> - pure (Quantity 0) + pure (Coin 0) Just SelfWithdrawal -> do (acct, _) <- liftHandler $ W.readRewardAccount @_ @s @k @n wrk wid @@ -1630,7 +1687,7 @@ getMigrationInfo -- ^ Source wallet -> Handler ApiWalletMigrationInfo getMigrationInfo ctx (ApiT wid) = do - (cs, leftovers) <- getSelections + (cs, leftovers) <- fmap coinToQuantity <$> getSelections let migrationCost = costFromSelections cs pure $ ApiWalletMigrationInfo{migrationCost,leftovers} where @@ -1643,7 +1700,7 @@ getMigrationInfo ctx (ApiT wid) = do selectionFee :: CoinSelection -> Word64 selectionFee s = inputBalance s - changeBalance s - getSelections :: Handler ([CoinSelection], Quantity "lovelace" Natural) + getSelections :: Handler ([CoinSelection], Coin) getSelections = withWorkerCtx ctx wid liftE liftE $ \wrk -> liftHandler $ W.selectCoinsForMigration @_ @s @k @n wrk wid @@ -1982,8 +2039,7 @@ mkApiCoinSelection deps mcerts (UnsignedTx inputs outputs change) = { id = ApiT txid , index = index , address = (ApiT addr, Proxy @n) - , amount = Quantity $ - fromIntegral $ unCoin $ TokenBundle.getCoin tokens + , amount = coinToQuantity $ TokenBundle.getCoin tokens , derivationPath = ApiT <$> path } @@ -2033,9 +2089,10 @@ mkApiTransaction ti txid mfee ins outs ws (meta, timestamp) txMeta setTimeRefere tx :: ApiTransaction n tx = ApiTransaction { id = ApiT txid - , amount = meta ^. #amount + , amount = Quantity . fromIntegral $ meta ^. #amount . #unCoin , fee = maybe (Quantity 0) (Quantity . fromIntegral . unCoin) mfee , deposit = Quantity depositIfAny + , assets = ApiT mempty , insertedAt = Nothing , pendingSince = Nothing , expiresAt = Nothing @@ -2044,6 +2101,7 @@ mkApiTransaction ti txid mfee ins outs ws (meta, timestamp) txMeta setTimeRefere , inputs = [ApiTxInput (fmap toAddressAmount o) (ApiT i) | (i, o) <- ins] , outputs = toAddressAmount <$> outs , withdrawals = mkApiWithdrawal @n <$> Map.toList ws + , mint = mempty -- TODO: ADP-xxx , status = ApiT (meta ^. #status) , metadata = ApiTxMetadata $ ApiT <$> txMeta } @@ -2104,9 +2162,8 @@ mkApiTransaction ti txid mfee ins outs ws (meta, timestamp) txMeta setTimeRefere txOutValue = fromIntegral . unCoin . txOutCoin toAddressAmount :: TxOut -> AddressAmount (ApiT Address, Proxy n) - toAddressAmount (TxOut addr tokens) = AddressAmount - (ApiT addr, Proxy @n) - (mkApiCoin $ TokenBundle.getCoin tokens) + toAddressAmount (TxOut addr (TokenBundle.TokenBundle coin assets)) = + AddressAmount (ApiT addr, Proxy @n) (mkApiCoin coin) (ApiT assets) mkApiCoin :: Coin @@ -2123,8 +2180,8 @@ mkApiWithdrawal (acct, c) = coerceCoin :: forall (n :: NetworkDiscriminant). AddressAmount (ApiT Address, Proxy n) -> TxOut -coerceCoin (AddressAmount (ApiT addr, _) (Quantity c)) = - TxOut addr (TokenBundle.fromCoin $ Coin $ fromIntegral c) +coerceCoin (AddressAmount (ApiT addr, _) c (ApiT assets)) = + TxOut addr (TokenBundle.TokenBundle (coinFromQuantity c) assets) natural :: Quantity q Word32 -> Quantity q Natural natural = Quantity . fromIntegral . getQuantity @@ -2733,7 +2790,7 @@ instance LiftHandler ErrQuitStakePool where , "although you're not even delegating, nor won't be in an " , "immediate future." ] - ErrNonNullRewards (Quantity rewards) -> + ErrNonNullRewards (Coin rewards) -> apiError err403 NonNullRewards $ mconcat [ "It seems that you're trying to retire from delegation " , "although you've unspoiled rewards in your rewards " diff --git a/lib/core/src/Cardano/Wallet/Api/Types.hs b/lib/core/src/Cardano/Wallet/Api/Types.hs index 674bcf40016..dff770c7a53 100644 --- a/lib/core/src/Cardano/Wallet/Api/Types.hs +++ b/lib/core/src/Cardano/Wallet/Api/Types.hs @@ -46,6 +46,8 @@ module Cardano.Wallet.Api.Types , fmtAllowedWords -- * API Types + , ApiAsset (..) + , toApiAsset , ApiAddress (..) , ApiCredential (..) , ApiAddressData (..) @@ -66,11 +68,12 @@ module Cardano.Wallet.Api.Types , ApiStakePoolMetrics (..) , ApiStakePoolFlag (..) , ApiWallet (..) + , ApiWalletBalance (..) + , ApiWalletAssetsBalance (..) , ApiWalletPassphrase (..) , ApiWalletPassphraseInfo (..) , ApiUtxoStatistics (..) , toApiUtxoStatistics - , WalletBalance (..) , WalletPostData (..) , WalletPutData (..) , SettingsPutData (..) @@ -151,6 +154,10 @@ module Cardano.Wallet.Api.Types , PostTransactionFeeDataT , ApiWalletMigrationPostDataT + -- * API Type Conversions + , coinToQuantity + , coinFromQuantity + -- * Others , defaultRecordTypeOptions , HealthStatusSMASH (..) @@ -214,7 +221,6 @@ import Cardano.Wallet.Primitive.Types , SmashServer (..) , StakePoolMetadata , StartTime (..) - , WalletBalance (..) , WalletId (..) , WalletName (..) , decodePoolIdBech32 @@ -245,7 +251,7 @@ import Control.DeepSeq ( NFData ) import Control.Monad ( guard, (>=>) ) -import Data.Aeson +import Data.Aeson.Types ( FromJSON (..) , SumEncoding (..) , ToJSON (..) @@ -257,10 +263,12 @@ import Data.Aeson , genericToJSON , object , omitNothingFields + , prependFailure , sumEncoding , tagSingleConstructors , withObject , withText + , (.!=) , (.:) , (.:?) , (.=) @@ -276,7 +284,7 @@ import Data.Data import Data.Either.Combinators ( maybeToRight ) import Data.Either.Extra - ( maybeToEither ) + ( eitherToMaybe, maybeToEither ) import Data.Function ( (&) ) import Data.Generics.Internal.VL.Lens @@ -332,6 +340,8 @@ import qualified Cardano.Crypto.Wallet as CC import qualified Cardano.Wallet.Primitive.AddressDerivation as AD import qualified Cardano.Wallet.Primitive.Types as W import qualified Cardano.Wallet.Primitive.Types.RewardAccount as W +import qualified Cardano.Wallet.Primitive.Types.TokenMap as W +import qualified Cardano.Wallet.Primitive.Types.TokenPolicy as W import qualified Codec.Binary.Bech32 as Bech32 import qualified Codec.Binary.Bech32.TH as Bech32 import qualified Data.Aeson as Aeson @@ -343,7 +353,6 @@ import qualified Data.Map as Map import qualified Data.Text as T import qualified Data.Text.Encoding as T - {------------------------------------------------------------------------------- Styles of Wallets -------------------------------------------------------------------------------} @@ -427,6 +436,20 @@ newtype ApiMaintenanceAction = ApiMaintenanceAction { gcStakePools :: ApiT PoolMetadataGCStatus } deriving (Eq, Generic, Show) +data ApiAsset = ApiAsset + { policyId :: ApiT W.TokenPolicyId + , assetName :: ApiT W.TokenName + , metadata :: Maybe (ApiT W.AssetMetadata) + } deriving (Eq, Generic, Show) + deriving anyclass NFData + +toApiAsset :: Maybe W.AssetMetadata -> W.AssetId -> ApiAsset +toApiAsset metadata_ (W.AssetId policyId_ assetName_) = ApiAsset + { policyId = ApiT policyId_ + , assetName = ApiT assetName_ + , metadata = ApiT <$> metadata_ + } + data ApiAddress (n :: NetworkDiscriminant) = ApiAddress { id :: !(ApiT Address, Proxy n) , state :: !(ApiT AddressState) @@ -530,7 +553,8 @@ data ApiCoinSelectionOutput (n :: NetworkDiscriminant) = ApiCoinSelectionOutput data ApiWallet = ApiWallet { id :: !(ApiT WalletId) , addressPoolGap :: !(ApiT AddressPoolGap) - , balance :: !(ApiT WalletBalance) + , balance :: !ApiWalletBalance + , assets :: !ApiWalletAssetsBalance , delegation :: !ApiWalletDelegation , name :: !(ApiT WalletName) , passphrase :: !(Maybe ApiWalletPassphraseInfo) @@ -539,6 +563,19 @@ data ApiWallet = ApiWallet } deriving (Eq, Generic, Show) deriving anyclass NFData +data ApiWalletBalance = ApiWalletBalance + { available :: !(Quantity "lovelace" Natural) + , total :: !(Quantity "lovelace" Natural) + , reward :: !(Quantity "lovelace" Natural) + } deriving (Eq, Generic, Show) + deriving anyclass NFData + +data ApiWalletAssetsBalance = ApiWalletAssetsBalance + { available :: !(ApiT W.TokenMap) + , total :: !(ApiT W.TokenMap) + } deriving (Eq, Generic, Show) + deriving anyclass NFData + newtype ApiWalletPassphraseInfo = ApiWalletPassphraseInfo { lastUpdatedAt :: UTCTime } deriving (Eq, Generic, Show) @@ -751,6 +788,7 @@ data ApiTransaction (n :: NetworkDiscriminant) = ApiTransaction , amount :: !(Quantity "lovelace" Natural) , fee :: !(Quantity "lovelace" Natural) , deposit :: !(Quantity "lovelace" Natural) + , assets :: !(ApiT W.TokenMap) , insertedAt :: !(Maybe ApiBlockReference) , pendingSince :: !(Maybe ApiBlockReference) , expiresAt :: !(Maybe ApiSlotReference) @@ -759,6 +797,7 @@ data ApiTransaction (n :: NetworkDiscriminant) = ApiTransaction , inputs :: ![ApiTxInput n] , outputs :: ![AddressAmount (ApiT Address, Proxy n)] , withdrawals :: ![ApiWithdrawal n] + , mint :: !(ApiT W.TokenMap) , status :: !(ApiT TxStatus) , metadata :: !ApiTxMetadata } deriving (Eq, Generic, Show) @@ -789,9 +828,16 @@ data ApiTxInput (n :: NetworkDiscriminant) = ApiTxInput data AddressAmount addr = AddressAmount { address :: !addr , amount :: !(Quantity "lovelace" Natural) + , assets :: !(ApiT W.TokenMap) } deriving (Eq, Generic, Show) deriving anyclass NFData +coinToQuantity :: Integral n => Coin -> Quantity "lovelace" n +coinToQuantity = Quantity . fromIntegral . unCoin + +coinFromQuantity :: Integral n => Quantity "lovelace" n -> Coin +coinFromQuantity = Coin . fromIntegral . getQuantity + newtype ApiAddressInspect = ApiAddressInspect { unApiAddressInspect :: Aeson.Value } deriving (Eq, Generic, Show) @@ -964,10 +1010,9 @@ instance FromText Iso8601Time where <> ", e.g. 2012-09-25T10:15:00Z." instance FromJSON (ApiT Iso8601Time) where - parseJSON = - parseJSON >=> eitherToParser . bimap ShowFmt ApiT . fromText + parseJSON = fromTextJSON "ISO-8601 Time" instance ToJSON (ApiT Iso8601Time) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromHttpApiData Iso8601Time where parseUrlPiece = first (T.pack . getTextDecodingError) . fromText @@ -1006,7 +1051,7 @@ data ApiPoolId deriving (Eq, Generic, Show) instance FromText ApiAccountPublicKey where - fromText txt = case xpubFromText (T.encodeUtf8 txt) of + fromText txt = case xpubFromText txt of Nothing -> Left $ TextDecodingError $ unwords [ "Invalid account public key: expecting a hex-encoded value" @@ -1014,9 +1059,8 @@ instance FromText ApiAccountPublicKey where Just pubkey -> Right $ ApiAccountPublicKey $ ApiT pubkey where - xpubFromText :: ByteString -> Maybe XPub - xpubFromText = (either (const Nothing) Just <$> fromHex @ByteString) - >=> xpubFromBytes + xpubFromText :: Text -> Maybe XPub + xpubFromText = fmap eitherToMaybe fromHexText >=> xpubFromBytes instance FromText (ApiT XPrv) where fromText t = case convertFromBase Base16 $ T.encodeUtf8 t of @@ -1104,6 +1148,7 @@ instance KnownDiscovery (SeqState network key) where newtype ApiT a = ApiT { getApiT :: a } deriving (Generic, Show, Eq, Functor) + deriving newtype (Semigroup, Monoid) deriving anyclass NFData deriving instance Ord a => Ord (ApiT a) @@ -1140,11 +1185,31 @@ instance DecodeAddress n => FromJSON (ApiAddress n) where instance EncodeAddress n => ToJSON (ApiAddress n) where toJSON = genericToJSON defaultRecordTypeOptions +instance FromJSON ApiAsset where + parseJSON = genericParseJSON defaultRecordTypeOptions +instance ToJSON ApiAsset where + toJSON = genericToJSON defaultRecordTypeOptions + +instance FromJSON (ApiT W.TokenPolicyId) where + parseJSON = fromTextJSON "PolicyId" +instance ToJSON (ApiT W.TokenPolicyId) where + toJSON = toTextJSON + +instance FromJSON (ApiT W.TokenName) where + parseJSON = withText "AssetName" + (fmap (ApiT . W.UnsafeTokenName) . eitherToParser . fromHexText) +instance ToJSON (ApiT W.TokenName) where + toJSON = toJSON . hexText . W.unTokenName . getApiT + +instance FromJSON (ApiT W.AssetMetadata) where + parseJSON = fmap ApiT . genericParseJSON defaultRecordTypeOptions +instance ToJSON (ApiT W.AssetMetadata) where + toJSON = genericToJSON defaultRecordTypeOptions . getApiT + instance ToJSON (ApiT DerivationIndex) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromJSON (ApiT DerivationIndex) where - parseJSON = parseJSON - >=> fmap ApiT . eitherToParser . first ShowFmt . fromText + parseJSON = fromTextJSON "DerivationIndex" instance ToJSON ApiVerificationKey where toJSON (ApiVerificationKey (pub, role_)) = @@ -1314,7 +1379,7 @@ instance FromJSON ApiAccountPublicKey where parseJSON >=> eitherToParser . first ShowFmt . fromText instance ToJSON ApiAccountPublicKey where toJSON = - toJSON . T.decodeUtf8 . hex . xpubToBytes . getApiT . key + toJSON . hexText . xpubToBytes . getApiT . key instance FromJSON WalletOrAccountPostData where parseJSON obj = do @@ -1398,14 +1463,12 @@ instance ToJSON (ByronWalletPostData mw) where toJSON = genericToJSON defaultRecordTypeOptions instance FromJSON (ApiT (Hash "encryption")) where - parseJSON = - parseJSON >=> eitherToParser . first ShowFmt . fromText + parseJSON = parseJSON >=> eitherToParser . first ShowFmt . fromText instance ToJSON (ApiT (Hash "encryption")) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromJSON (ApiT XPrv) where - parseJSON = - parseJSON >=> eitherToParser . first ShowFmt . fromText + parseJSON = parseJSON >=> eitherToParser . first ShowFmt . fromText instance ToJSON (ApiT XPrv) where toJSON = toJSON . toText @@ -1492,9 +1555,9 @@ instance ToJSON ApiFee where instance (PassphraseMaxLength purpose, PassphraseMinLength purpose) => FromJSON (ApiT (Passphrase purpose)) where - parseJSON = parseJSON >=> eitherToParser . bimap ShowFmt ApiT . fromText + parseJSON = fromTextJSON "Passphrase" instance ToJSON (ApiT (Passphrase purpose)) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromJSON ApiCredential where parseJSON v = @@ -1582,9 +1645,9 @@ instance ToJSON (ApiMnemonicT sizes) where toJSON (ApiMnemonicT (SomeMnemonic mw)) = toJSON (mnemonicToText mw) instance FromJSON (ApiT WalletId) where - parseJSON = parseJSON >=> eitherToParser . bimap ShowFmt ApiT . fromText + parseJSON = fromTextJSON "WalletId" instance ToJSON (ApiT WalletId) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromJSON (ApiT AddressPoolGap) where parseJSON = parseJSON >=> @@ -1592,10 +1655,10 @@ instance FromJSON (ApiT AddressPoolGap) where instance ToJSON (ApiT AddressPoolGap) where toJSON = toJSON . getAddressPoolGap . getApiT -instance FromJSON (ApiT WalletBalance) where - parseJSON = fmap ApiT . genericParseJSON defaultRecordTypeOptions -instance ToJSON (ApiT WalletBalance) where - toJSON = genericToJSON defaultRecordTypeOptions . getApiT +instance FromJSON ApiWalletBalance where + parseJSON = genericParseJSON defaultRecordTypeOptions +instance ToJSON ApiWalletBalance where + toJSON = genericToJSON defaultRecordTypeOptions data ApiByronWalletBalance = ApiByronWalletBalance { available :: !(Quantity "lovelace" Natural) @@ -1608,6 +1671,16 @@ instance FromJSON ApiByronWalletBalance where instance ToJSON ApiByronWalletBalance where toJSON = genericToJSON defaultRecordTypeOptions +instance FromJSON ApiWalletAssetsBalance where + parseJSON = genericParseJSON defaultRecordTypeOptions +instance ToJSON ApiWalletAssetsBalance where + toJSON = genericToJSON defaultRecordTypeOptions + +instance FromJSON (ApiT W.TokenMap) where + parseJSON = fmap (ApiT . W.getFlat) . parseJSON +instance ToJSON (ApiT W.TokenMap) where + toJSON = toJSON . W.Flat . getApiT + instance FromJSON (ApiT PoolId) where parseJSON = parseJSON >=> eitherToParser . bimap ShowFmt ApiT @@ -1646,9 +1719,9 @@ instance ToJSON ApiStakePoolFlag where toJSON = genericToJSON defaultSumTypeOptions instance FromJSON (ApiT WalletName) where - parseJSON = parseJSON >=> eitherToParser . bimap ShowFmt ApiT . fromText + parseJSON = fromTextJSON "WalletName" instance ToJSON (ApiT WalletName) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromJSON (ApiT W.Settings) where parseJSON = fmap ApiT . genericParseJSON defaultRecordTypeOptions @@ -1748,12 +1821,16 @@ instance ToJSON (ApiT SlotNo) where toJSON (ApiT (SlotNo sn)) = toJSON sn instance FromJSON a => FromJSON (AddressAmount a) where - parseJSON bytes = do - v@(AddressAmount _ (Quantity c)) <- - genericParseJSON defaultRecordTypeOptions bytes - if isValidCoin (Coin $ fromIntegral c) - then return v - else fail $ + parseJSON = withObject "AddressAmount " $ \v -> + prependFailure "parsing AddressAmount failed, " $ + AddressAmount + <$> v .: "address" + <*> (v .: "amount" >>= validateCoin) + <*> v .:? "assets" .!= mempty + where + validateCoin q + | isValidCoin (coinFromQuantity q) = pure q + | otherwise = fail $ "invalid coin value: value has to be lower than or equal to " <> show (unCoin maxBound) <> " lovelace." @@ -1822,9 +1899,9 @@ instance ToJSON (ApiT TxIn) where , "index" .= toJSON ix ] instance FromJSON (ApiT (Hash "Tx")) where - parseJSON = parseJSON >=> eitherToParser . bimap ShowFmt ApiT . fromText + parseJSON = fromTextJSON "Tx Hash" instance ToJSON (ApiT (Hash "Tx")) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromJSON (ApiT Direction) where parseJSON = fmap ApiT . genericParseJSON defaultSumTypeOptions @@ -1883,9 +1960,9 @@ instance ToJSON (ApiT ActiveSlotCoefficient) where toJSON (ApiT (ActiveSlotCoefficient sn)) = toJSON sn instance FromJSON (ApiT (Hash "Genesis")) where - parseJSON = parseJSON >=> eitherToParser . bimap ShowFmt ApiT . fromText + parseJSON = fromTextJSON "Genesis Hash" instance ToJSON (ApiT (Hash "Genesis")) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON instance FromJSON ApiNetworkParameters where parseJSON = genericParseJSON defaultRecordTypeOptions @@ -1992,7 +2069,7 @@ instance FromText (AddressAmount Text) where case split (=='@') text of [] -> err [_] -> err - [l, r] -> AddressAmount r <$> fromText l + [l, r] -> AddressAmount r <$> fromText l <*> pure mempty _ -> err instance FromText PostExternalTransactionData where @@ -2099,6 +2176,18 @@ taggedSumTypeOptions base opts = base eitherToParser :: Show s => Either s a -> Aeson.Parser a eitherToParser = either (fail . show) pure +hexText :: ByteString -> Text +hexText = T.decodeLatin1 . hex + +fromHexText :: Text -> Either String ByteString +fromHexText = fromHex . T.encodeUtf8 + +toTextJSON :: ToText a => ApiT a -> Value +toTextJSON = toJSON . toText . getApiT + +fromTextJSON :: FromText a => String -> Value -> Aeson.Parser (ApiT a) +fromTextJSON n = withText n (eitherToParser . bimap ShowFmt ApiT . fromText) + {------------------------------------------------------------------------------- User-Facing Address Encoding -------------------------------------------------------------------------------} @@ -2217,7 +2306,6 @@ instance ToJSON ApiHealthCheck where toJSON = genericToJSON defaultRecordTypeOptions instance FromJSON (ApiT SmashServer) where - parseJSON = parseJSON >=> either (fail . show . ShowFmt) (pure . ApiT) . fromText - + parseJSON = fromTextJSON "SmashServer" instance ToJSON (ApiT SmashServer) where - toJSON = toJSON . toText . getApiT + toJSON = toTextJSON diff --git a/lib/core/src/Cardano/Wallet/DB.hs b/lib/core/src/Cardano/Wallet/DB.hs index 1d900d95337..f9766bbb169 100644 --- a/lib/core/src/Cardano/Wallet/DB.hs +++ b/lib/core/src/Cardano/Wallet/DB.hs @@ -51,6 +51,8 @@ import Cardano.Wallet.Primitive.Types , WalletId , WalletMetadata ) +import Cardano.Wallet.Primitive.Types.Coin + ( Coin ) import Cardano.Wallet.Primitive.Types.Hash ( Hash ) import Cardano.Wallet.Primitive.Types.Tx @@ -64,9 +66,7 @@ import Control.Monad.Trans.Except import Data.Quantity ( Quantity (..) ) import Data.Word - ( Word32, Word64, Word8 ) -import Numeric.Natural - ( Natural ) + ( Word32, Word8 ) import qualified Data.List as L @@ -198,7 +198,7 @@ data DBLayer m s k = forall stm. (MonadIO stm, MonadFail stm) => DBLayer , putDelegationRewardBalance :: PrimaryKey WalletId - -> Quantity "lovelace" Word64 + -> Coin -> ExceptT ErrNoSuchWallet stm () -- ^ Store the latest known reward account balance. -- @@ -208,7 +208,7 @@ data DBLayer m s k = forall stm. (MonadIO stm, MonadFail stm) => DBLayer , readDelegationRewardBalance :: PrimaryKey WalletId - -> stm (Quantity "lovelace" Word64) + -> stm Coin -- ^ Get the reward account balance. -- -- Returns zero if the wallet isn't found or if wallet hasn't delegated @@ -227,7 +227,7 @@ data DBLayer m s k = forall stm. (MonadIO stm, MonadFail stm) => DBLayer , readTxHistory :: PrimaryKey WalletId - -> Maybe (Quantity "lovelace" Natural) + -> Maybe Coin -> SortOrder -> Range SlotNo -> Maybe TxStatus diff --git a/lib/core/src/Cardano/Wallet/DB/Model.hs b/lib/core/src/Cardano/Wallet/DB/Model.hs index fa8cfb61fa9..5ead6e6fc63 100644 --- a/lib/core/src/Cardano/Wallet/DB/Model.hs +++ b/lib/core/src/Cardano/Wallet/DB/Model.hs @@ -123,11 +123,9 @@ import Data.Ord import Data.Quantity ( Quantity (..) ) import Data.Word - ( Word32, Word64 ) + ( Word32 ) import GHC.Generics ( Generic ) -import Numeric.Natural - ( Natural ) import qualified Data.Map.Strict as Map @@ -161,7 +159,7 @@ data WalletDatabase s xprv = WalletDatabase , xprv :: !(Maybe xprv) , genesisParameters :: !GenesisParameters , protocolParameters :: !ProtocolParameters - , rewardAccountBalance :: !(Quantity "lovelace" Word64) + , rewardAccountBalance :: !Coin } deriving (Show, Eq, Generic) -- | Shorthand for the putTxHistory argument type. @@ -423,7 +421,7 @@ mReadTxHistory :: forall wid s xprv . Ord wid => TimeInterpreter Identity -> wid - -> Maybe (Quantity "lovelace" Natural) + -> Maybe Coin -> SortOrder -> Range SlotNo -> Maybe TxStatus @@ -501,12 +499,12 @@ mReadGenesisParameters wid db@(Database wallets _) = (Right (genesisParameters <$> Map.lookup wid wallets), db) mPutDelegationRewardBalance - :: Ord wid => wid -> Quantity "lovelace" Word64 -> ModelOp wid s xprv () + :: Ord wid => wid -> Coin -> ModelOp wid s xprv () mPutDelegationRewardBalance wid amt = alterModel wid $ \wal -> ((), wal { rewardAccountBalance = amt }) mReadDelegationRewardBalance - :: Ord wid => wid -> ModelOp wid s xprv (Quantity "lovelace" Word64) + :: Ord wid => wid -> ModelOp wid s xprv Coin mReadDelegationRewardBalance wid db@(Database wallets _) = (Right (maybe minBound rewardAccountBalance $ Map.lookup wid wallets), db) @@ -541,7 +539,7 @@ alterModelErr wid f db@Database{wallets,txs} = -- | Apply optional filters on slotNo and sort using the default sort order -- (first time/slotNo, then by TxId) to a 'TxHistory'. filterTxHistory - :: Maybe (Quantity "lovelace" Natural) + :: Maybe Coin -> SortOrder -> Range SlotNo -> TxHistory @@ -557,8 +555,7 @@ filterTxHistory minWithdrawal order range = where sortBySlot = sortOn (Down . (slotNo :: TxMeta -> SlotNo) . snd) sortByTxId = sortOn (txId . fst) - atLeast (Quantity inf) = - not . Map.null . Map.filter (>= Coin (fromIntegral inf)) + atLeast inf = not . Map.null . Map.filter (>= inf) filterWithdrawals = maybe (const True) (\inf -> atLeast inf . withdrawals . fst) diff --git a/lib/core/src/Cardano/Wallet/DB/Sqlite.hs b/lib/core/src/Cardano/Wallet/DB/Sqlite.hs index f54135b1137..2c95d14621e 100644 --- a/lib/core/src/Cardano/Wallet/DB/Sqlite.hs +++ b/lib/core/src/Cardano/Wallet/DB/Sqlite.hs @@ -204,8 +204,6 @@ import Database.Persist.Types ( PersistValue (..), fromPersistValueText ) import Fmt ( pretty ) -import Numeric.Natural - ( Natural ) import System.Directory ( doesFileExist, listDirectory ) import System.FilePath @@ -1367,7 +1365,7 @@ newDBLayer trace defaultFieldValues mDatabaseFile ti = do -----------------------------------------------------------------------} , putDelegationRewardBalance = - \(PrimaryKey wid) (Quantity amt) -> ExceptT $ do + \(PrimaryKey wid) (W.Coin amt) -> ExceptT $ do selectWallet wid >>= \case Nothing -> pure $ Left $ ErrNoSuchWallet wid Just _ -> Right <$> repsert @@ -1376,7 +1374,7 @@ newDBLayer trace defaultFieldValues mDatabaseFile ti = do , readDelegationRewardBalance = \(PrimaryKey wid) -> - maybe minBound (Quantity . rewardAccountBalance . entityVal) <$> + W.Coin . maybe 0 (rewardAccountBalance . entityVal) <$> selectFirst [RewardWalletId ==. wid] [] {----------------------------------------------------------------------- @@ -1648,7 +1646,7 @@ mkTxMetaEntity wid txid mfee meta derived = TxMeta , txMetaDirection = derived ^. #direction , txMetaSlot = derived ^. #slotNo , txMetaBlockHeight = getQuantity (derived ^. #blockHeight) - , txMetaAmount = getQuantity (derived ^. #amount) + , txMetaAmount = derived ^. #amount , txMetaFee = fromIntegral . W.unCoin <$> mfee , txMetaSlotExpires = derived ^. #expiry , txMetadata = meta @@ -1724,7 +1722,7 @@ txHistoryFromEntity ti tip metas ins outs ws = , W.direction = txMetaDirection m , W.slotNo = txMetaSlot m , W.blockHeight = Quantity (txMetaBlockHeight m) - , W.amount = Quantity (txMetaAmount m) + , W.amount = txMetaAmount m , W.expiry = txMetaSlotExpires m } @@ -1991,7 +1989,7 @@ selectTxHistory :: W.Wallet s -> TimeInterpreter IO -> W.WalletId - -> Maybe (Quantity "lovelace" Natural) + -> Maybe W.Coin -> W.SortOrder -> [Filter TxMeta] -> SqlPersistT IO [W.TransactionInfo] @@ -1999,8 +1997,7 @@ selectTxHistory cp ti wid minWithdrawal order conditions = do let txMetaFilter = (TxMetaWalletId ==. wid):conditions metas <- case minWithdrawal of Nothing -> fmap entityVal <$> selectList txMetaFilter sortOpt - Just inf -> do - let coin = W.Coin $ fromIntegral $ getQuantity inf + Just coin -> do txids <- fmap (txWithdrawalTxId . entityVal) <$> selectList [ TxWithdrawalAmount >=. coin ] [] ms <- combineChunked (nub txids) (\chunk -> selectList diff --git a/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs b/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs index ae3225d2e55..e2ab9083544 100644 --- a/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs +++ b/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs @@ -107,7 +107,7 @@ TxMeta txMetaDirection W.Direction sql=direction txMetaSlot SlotNo sql=slot txMetaBlockHeight Word32 sql=block_height - txMetaAmount Natural sql=amount + txMetaAmount W.Coin sql=amount txMetadata W.TxMetadata Maybe sql=data txMetaSlotExpires SlotNo Maybe sql=slot_expires txMetaFee Natural Maybe sql=fee diff --git a/lib/core/src/Cardano/Wallet/Network.hs b/lib/core/src/Cardano/Wallet/Network.hs index f24b9855aee..bb051d6b8a9 100644 --- a/lib/core/src/Cardano/Wallet/Network.hs +++ b/lib/core/src/Cardano/Wallet/Network.hs @@ -72,14 +72,10 @@ import Data.Functor ( ($>) ) import Data.List.NonEmpty ( NonEmpty (..) ) -import Data.Quantity - ( Quantity (..) ) import Data.Text ( Text ) import Data.Text.Class ( ToText (..) ) -import Data.Word - ( Word64 ) import Fmt ( pretty ) import GHC.Generics @@ -156,7 +152,7 @@ data NetworkLayer m block = NetworkLayer , getAccountBalance :: RewardAccount - -> ExceptT ErrGetAccountBalance m (Quantity "lovelace" Word64) + -> ExceptT ErrGetAccountBalance m Coin , timeInterpreter :: TimeInterpreter (ExceptT PastHorizonException m) diff --git a/lib/core/src/Cardano/Wallet/Primitive/Model.hs b/lib/core/src/Cardano/Wallet/Primitive/Model.hs index d6be80f81cb..9d839b7c449 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Model.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Model.hs @@ -58,15 +58,16 @@ import Cardano.Wallet.Primitive.Types ( Block (..) , BlockHeader (..) , DelegationCertificate (..) - , distance , dlgCertAccount ) import Cardano.Wallet.Primitive.Types.Address ( Address (..) ) import Cardano.Wallet.Primitive.Types.Coin - ( Coin (..) ) + ( Coin (..), distance, sumCoins ) import Cardano.Wallet.Primitive.Types.RewardAccount ( RewardAccount (..) ) +import Cardano.Wallet.Primitive.Types.TokenBundle + ( TokenBundle ) import Cardano.Wallet.Primitive.Types.Tx ( Direction (..) , Tx (..) @@ -98,17 +99,14 @@ import Data.List.NonEmpty ( NonEmpty (..) ) import Data.Maybe ( catMaybes, isJust ) -import Data.Quantity - ( Quantity (..) ) import Data.Set ( Set ) import Fmt ( Buildable (..), indentF ) import GHC.Generics ( Generic ) -import Numeric.Natural - ( Natural ) +import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TB import qualified Data.List.NonEmpty as NE import qualified Data.Map as Map import qualified Data.Set as Set @@ -278,7 +276,7 @@ applyBlocks (block0 :| blocks) cp = -------------------------------------------------------------------------------} -- | Available balance = 'balance' . 'availableUTxO' -availableBalance :: Set Tx -> Wallet s -> Natural +availableBalance :: Set Tx -> Wallet s -> TokenBundle availableBalance pending = balance . availableUTxO pending @@ -286,15 +284,16 @@ availableBalance pending = totalBalance :: (IsOurs s Address, IsOurs s RewardAccount) => Set Tx - -> Quantity "lovelace" Natural + -> Coin -> Wallet s - -> Natural -totalBalance pending (Quantity rewards) wallet@(Wallet _ _ s) = - balance (totalUTxO pending wallet) + - if hasPendingWithdrawals pending - then 0 - else rewards + -> TokenBundle +totalBalance pending rewards wallet@(Wallet _ _ s) = + balance (totalUTxO pending wallet) `TB.add` rewardsBalance where + rewardsBalance + | hasPendingWithdrawals pending = mempty + | otherwise = TB.fromCoin rewards + hasPendingWithdrawals = anyS (anyM (\acct _ -> isJust $ fst (isOurs acct s)) . withdrawals) where @@ -370,13 +369,13 @@ prefilterBlock b u0 = runState $ do state (isOurs acct) <&> \case Nothing -> Nothing Just{} -> Just (acct, amt) - mkTxMeta :: Natural -> Direction -> TxMeta - mkTxMeta amt dir = TxMeta + mkTxMeta :: Coin -> Direction -> TxMeta + mkTxMeta amount dir = TxMeta { status = InLedger , direction = dir , slotNo = b ^. #header . #slotNo , blockHeight = b ^. #header . #blockHeight - , amount = Quantity amt + , amount = amount , expiry = Nothing } applyTx @@ -388,10 +387,10 @@ prefilterBlock b u0 = runState $ do ourU <- state $ utxoOurs tx let ourIns = Set.fromList (inputs tx) `Set.intersection` dom (u <> ourU) let u' = (u <> ourU) `excluding` ourIns - ourWithdrawals <- fmap (fromIntegral . unCoin . snd) <$> + ourWithdrawals <- Coin . sum . fmap (unCoin . snd) <$> mapMaybeM ourWithdrawal (Map.toList $ withdrawals tx) let received = balance ourU - let spent = balance (u `restrictedBy` ourIns) + sum ourWithdrawals + let spent = balance (u `restrictedBy` ourIns) `TB.add` TB.fromCoin ourWithdrawals let hasKnownInput = ourIns /= mempty let hasKnownOutput = ourU /= mempty let hasKnownWithdrawal = ourWithdrawals /= mempty @@ -409,25 +408,30 @@ prefilterBlock b u0 = runState $ do (Nothing, Outgoing) -> -- Byron let - totalOut = sum (fromIntegral . unCoin . txOutCoin <$> outputs tx) + totalOut = sumCoins (txOutCoin <$> outputs tx) - totalIn = spent + totalIn = TB.getCoin spent in - Just $ Coin $ fromIntegral $ totalIn - totalOut + Just $ distance totalIn totalOut (_, Incoming) -> Nothing return $ if hasKnownOutput && not hasKnownInput then let dir = Incoming in - ( (tx { fee = actualFee dir }, mkTxMeta received dir) : txs + ( (tx { fee = actualFee dir }, mkTxMeta (TB.getCoin received) dir) : txs , u' ) else if hasKnownInput || hasKnownWithdrawal then - let dir = if spent > received then Outgoing else Incoming in - ( (tx { fee = actualFee dir }, mkTxMeta (distance spent received) dir) : txs - , u' - ) + let + adaSpent = TB.getCoin spent + adaReceived = TB.getCoin received + dir = if adaSpent > adaReceived then Outgoing else Incoming + amount = distance adaSpent adaReceived + in + ( (tx { fee = actualFee dir }, mkTxMeta amount dir) : txs + , u' + ) else (txs, u) diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types.hs b/lib/core/src/Cardano/Wallet/Primitive/Types.hs index 00f2dae83e9..40f5ad4cd79 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types.hs @@ -85,7 +85,6 @@ module Cardano.Wallet.Primitive.Types , WalletDelegationNext (..) , WalletPassphraseInfo(..) , PassphraseScheme(..) - , WalletBalance(..) , IsDelegatingTo (..) -- * Stake Pools @@ -411,14 +410,6 @@ data PassphraseScheme instance NFData PassphraseScheme -data WalletBalance = WalletBalance - { available :: !(Quantity "lovelace" Natural) - , total :: !(Quantity "lovelace" Natural) - , reward :: !(Quantity "lovelace" Natural) - } deriving (Eq, Generic, Show) - -instance NFData WalletBalance - {------------------------------------------------------------------------------- Queries -------------------------------------------------------------------------------} @@ -743,7 +734,7 @@ instance ToJSON PoolOwner where data StakePoolsSummary = StakePoolsSummary { nOpt :: Int - , rewards :: Map PoolId (Quantity "lovelace" Word64) + , rewards :: Map PoolId Coin , stake :: Map PoolId Percentage } deriving (Show, Eq) @@ -1213,8 +1204,8 @@ data PoolRegistrationCertificate = PoolRegistrationCertificate { poolId :: !PoolId , poolOwners :: ![PoolOwner] , poolMargin :: Percentage - , poolCost :: Quantity "lovelace" Word64 - , poolPledge :: Quantity "lovelace" Word64 + , poolCost :: Coin + , poolPledge :: Coin , poolMetadata :: Maybe (StakePoolMetadataUrl, StakePoolMetadataHash) } deriving (Generic, Show, Eq, Ord) diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types/Coin.hs b/lib/core/src/Cardano/Wallet/Primitive/Types/Coin.hs index 545222c279a..ae1818e6942 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types/Coin.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types/Coin.hs @@ -11,16 +11,19 @@ -- lovelace. -- module Cardano.Wallet.Primitive.Types.Coin - ( - -- * Type + ( -- * Type Coin (..) + , coinQuantity - -- * Operations + -- * Checks + , isValidCoin + + -- * Operations , addCoin , subtractCoin + , sumCoins + , distance - -- * Checks - , isValidCoin ) where import Prelude @@ -29,12 +32,16 @@ import Control.DeepSeq ( NFData (..) ) import Control.Monad ( (<=<) ) +import Data.Foldable + ( foldl' ) +import Data.Quantity + ( Quantity (..) ) import Data.Text.Class ( FromText (..), TextDecodingError (..), ToText (..) ) import Data.Word ( Word64 ) import Fmt - ( Buildable (..) ) + ( Buildable (..), fixedF ) import GHC.Generics ( Generic ) import Numeric.Natural @@ -48,12 +55,25 @@ import qualified Data.Text as T -- -- Reminder: 1 ada = 1,000,000 lovelace. -- +-- NOTE: The 'Coin' value is stored as a 64-bit unsigned integer. The maximum +-- supply of lovelace is less than 2^56, so there is ample space to store any +-- circulating amount of Ada. +-- +-- However be careful when summing coins, for example, if calculating historical +-- volumes traded, because this may overflow. newtype Coin = Coin { unCoin :: Word64 } deriving stock (Ord, Eq, Generic) deriving (Read, Show) via (Quiet Coin) +instance Semigroup Coin where + -- Word64 doesn't have a default Semigroup instance. + Coin a <> Coin b = Coin (a + b) + +instance Monoid Coin where + mempty = Coin 0 + instance ToText Coin where toText (Coin c) = T.pack $ show c @@ -73,11 +93,24 @@ instance Bounded Coin where maxBound = Coin 45_000_000_000_000_000 instance Buildable Coin where - build = build . unCoin + build (Coin c) = fixedF @Double 6 (fromIntegral c / 1e6) + +-- | Compatibility function to use while 'Quantity' is still used in non-API +-- parts of the code. +coinQuantity :: Integral a => Coin -> Quantity n a +coinQuantity (Coin n) = Quantity (fromIntegral n) --------------------------------------------------------------------------------- --- Operations --------------------------------------------------------------------------------- +{------------------------------------------------------------------------------- + Checks +-------------------------------------------------------------------------------} + +-- | Whether the coin amount is less than the total amount of Ada. +isValidCoin :: Coin -> Bool +isValidCoin c = c >= minBound && c <= maxBound + +{------------------------------------------------------------------------------- + Operations +-------------------------------------------------------------------------------} -- | Subtracts the second coin from the first. -- @@ -88,7 +121,7 @@ subtractCoin (Coin a) (Coin b) | a >= b = Just $ Coin (a - b) | otherwise = Nothing --- | Adds the given coins together. +-- | Calculate the combined value of two coins. -- -- NOTE: It is generally safe to add coins and stay in the same domain because -- the max supply is known (45B), which easily fits within a 'Word64'. So for @@ -98,9 +131,11 @@ subtractCoin (Coin a) (Coin b) addCoin :: Coin -> Coin -> Coin addCoin (Coin a) (Coin b) = Coin (a + b) --------------------------------------------------------------------------------- --- Checks --------------------------------------------------------------------------------- +-- | Add a list of coins together. +sumCoins :: Foldable t => t Coin -> Coin +sumCoins = foldl' addCoin (Coin 0) -isValidCoin :: Coin -> Bool -isValidCoin c = c >= minBound && c <= maxBound + +-- | Absolute difference between two coin amounts. The result is never negative. +distance :: Coin -> Coin -> Coin +distance (Coin a) (Coin b) = if a < b then Coin (b - a) else Coin (a - b) diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types/Hash.hs b/lib/core/src/Cardano/Wallet/Primitive/Types/Hash.hs index 425951b36b8..ed6a1389698 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types/Hash.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types/Hash.hs @@ -66,7 +66,7 @@ instance FromText (Hash "Genesis") where fromText = hashFromText 32 instance FromText (Hash "Block") where fromText = hashFromText 32 instance FromText (Hash "BlockHeader") where fromText = hashFromText 32 instance FromText (Hash "RewardAccount") where fromText = hashFromText 28 -instance FromText (Hash "TokenPolicy") where fromText = hashFromText 28 +instance FromText (Hash "TokenPolicy") where fromText = hashFromText 28 -- Script Hash hashFromText :: forall t. (KnownSymbol t) diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types/TokenMap.hs b/lib/core/src/Cardano/Wallet/Primitive/Types/TokenMap.hs index b47da839831..51d48227802 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types/TokenMap.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types/TokenMap.hs @@ -340,8 +340,8 @@ instance FromJSON (Flat TokenMap) where -- Used for JSON serialization only: not exported. data FlatAssetQuantity = FlatAssetQuantity - { _policy :: !TokenPolicyId - , _token :: !TokenName + { _policyId :: !TokenPolicyId + , _assetName :: !TokenName , _quantity :: !TokenQuantity } deriving Generic @@ -385,13 +385,13 @@ instance FromJSON (Nested TokenMap) where -- Used for JSON serialization only: not exported. data NestedMapEntry = NestedMapEntry - { _policy :: !TokenPolicyId + { _policyId :: !TokenPolicyId , _tokens :: ![NestedTokenQuantity] } deriving Generic -- Used for JSON serialization only: not exported. data NestedTokenQuantity = NestedTokenQuantity - { _token :: !TokenName + { _assetName :: !TokenName , _quantity :: !TokenQuantity } deriving Generic diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy.hs b/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy.hs index 67d979dce3f..0084c635c89 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy.hs @@ -9,7 +9,12 @@ module Cardano.Wallet.Primitive.Types.TokenPolicy -- * Token Names , TokenName (..) + , mkTokenName + , nullTokenName + , maxLengthTokenName + -- * Token Metadata + , AssetMetadata (..) ) where import Prelude @@ -22,10 +27,16 @@ import Control.Monad ( (>=>) ) import Data.Aeson ( FromJSON (..), ToJSON (..) ) +import Data.Bifunctor + ( first ) +import Data.ByteArray.Encoding + ( Base (Base16), convertFromBase, convertToBase ) +import Data.ByteString + ( ByteString ) import Data.Text ( Text ) import Data.Text.Class - ( FromText (..), ToText (..) ) + ( FromText (..), TextDecodingError (..), ToText (..) ) import Fmt ( Buildable (..) ) import GHC.Generics @@ -33,6 +44,9 @@ import GHC.Generics import Quiet ( Quiet (..) ) +import qualified Data.ByteString as BS +import qualified Data.Text.Encoding as T + -- | Token policy identifiers, represented by the hash of the monetary policy -- script. newtype TokenPolicyId = @@ -61,14 +75,33 @@ instance FromText TokenPolicyId where -- | Token names, defined by the monetary policy script. newtype TokenName = -- | Construct a 'TokenName' without any validation. - UnsafeTokenName { unTokenName :: Text } + UnsafeTokenName { unTokenName :: ByteString } deriving stock (Eq, Ord, Generic) deriving (Read, Show) via (Quiet TokenName) +-- | Construct a 'TokenName', validating that the length does not exceed +-- 'maxLengthTokenName'. +mkTokenName :: ByteString -> Either String TokenName +mkTokenName bs + | BS.length bs <= maxLengthTokenName = Right $ UnsafeTokenName bs + | otherwise = Left $ "TokenName length " ++ show (BS.length bs) + ++ " exceeds maximum of " ++ show maxLengthTokenName + +-- | The empty asset name. +-- +-- Asset names may be empty, where a monetary policy script only mints a single +-- asset, or where one asset should be considered as the "default" token for the +-- policy. +nullTokenName :: TokenName +nullTokenName = UnsafeTokenName "" + +maxLengthTokenName :: Int +maxLengthTokenName = 32 + instance NFData TokenName instance Buildable TokenName where - build = build . unTokenName + build = build . toText instance FromJSON TokenName where parseJSON = parseJSON >=> either (fail . show) pure . fromText @@ -77,7 +110,18 @@ instance ToJSON TokenName where toJSON = toJSON . toText instance ToText TokenName where - toText = unTokenName + toText = T.decodeLatin1 . convertToBase Base16 . unTokenName instance FromText TokenName where - fromText = pure . UnsafeTokenName + fromText = first TextDecodingError + . either (Left . ("TokenName is not hex-encoded: " ++)) mkTokenName + . convertFromBase Base16 + . T.encodeUtf8 + +-- | Information about an asset, from a source external to the chain. +newtype AssetMetadata = AssetMetadata + { name :: Text + } deriving stock (Eq, Ord, Generic) + deriving (Read, Show) via (Quiet AssetMetadata) + +instance NFData AssetMetadata diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy/Gen.hs b/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy/Gen.hs index ed5c1c31dfa..31f8af7d6b7 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy/Gen.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types/TokenPolicy/Gen.hs @@ -13,16 +13,15 @@ module Cardano.Wallet.Primitive.Types.TokenPolicy.Gen import Prelude import Cardano.Wallet.Primitive.Types.TokenPolicy - ( TokenName, TokenPolicyId ) + ( TokenName (..), TokenPolicyId ) import Data.Either ( fromRight ) -import Data.Text - ( Text ) import Data.Text.Class ( FromText (..) ) import Test.QuickCheck ( Gen, elements ) +import qualified Data.ByteString.Char8 as B8 import qualified Data.Text as T -------------------------------------------------------------------------------- @@ -36,7 +35,7 @@ shrinkTokenNameSmallRange :: TokenName -> [TokenName] shrinkTokenNameSmallRange name = filter (< name) tokenNamesSmallRange tokenNamesSmallRange :: [TokenName] -tokenNamesSmallRange = mkTokenName . ("Token" `T.snoc`) <$> ['A' .. 'D'] +tokenNamesSmallRange = UnsafeTokenName . B8.snoc "Token" <$> ['A' .. 'D'] -------------------------------------------------------------------------------- -- Token names chosen from a medium-sized range (to minimize the risk of @@ -50,7 +49,7 @@ shrinkTokenNameMediumRange :: TokenName -> [TokenName] shrinkTokenNameMediumRange name = filter (< name) tokenNamesMediumRange tokenNamesMediumRange :: [TokenName] -tokenNamesMediumRange = mkTokenName . ("Token" `T.snoc`) <$> ['A' .. 'Z'] +tokenNamesMediumRange = UnsafeTokenName . B8.snoc "Token" <$> ['A' .. 'Z'] -------------------------------------------------------------------------------- -- Token policy identifiers chosen from a small range (to allow collisions) @@ -69,12 +68,6 @@ tokenPolicies = mkTokenPolicyId <$> ['A' .. 'D'] -- Internal utilities -------------------------------------------------------------------------------- -mkTokenName :: Text -> TokenName -mkTokenName t = fromRight reportError $ fromText t - where - reportError = error $ - "Unable to generate token name from text: " <> show t - -- The input must be a character in the range [0-9] or [A-Z]. -- mkTokenPolicyId :: Char -> TokenPolicyId diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types/Tx.hs b/lib/core/src/Cardano/Wallet/Primitive/Types/Tx.hs index d7ca250d59c..9f6074f097b 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types/Tx.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types/Tx.hs @@ -57,7 +57,7 @@ import Cardano.Wallet.Primitive.Types.Hash import Cardano.Wallet.Primitive.Types.RewardAccount ( RewardAccount (..) ) import Cardano.Wallet.Primitive.Types.TokenBundle - ( TokenBundle ) + ( TokenBundle (..) ) import Cardano.Wallet.Primitive.Types.TokenPolicy ( TokenName, TokenPolicyId ) import Cardano.Wallet.Primitive.Types.TokenQuantity @@ -101,7 +101,6 @@ import Fmt ( Buildable (..) , blockListF' , blockMapF - , fixedF , nameF , ordinalF , prefixF @@ -273,12 +272,14 @@ instance Buildable (TxIn, TxOut) where -- | Additional information about a transaction, derived from the transaction -- and ledger state. This should not be confused with 'TxMetadata' which is -- application-specific data included with the transaction. +-- +-- TODO: TxProperties or TxProps would be a good name for this type. data TxMeta = TxMeta { status :: !TxStatus , direction :: !Direction , slotNo :: !SlotNo , blockHeight :: !(Quantity "block" Word32) - , amount :: !(Quantity "lovelace" Natural) + , amount :: !Coin -- ^ Amount seen from the perspective of the wallet. Refers either to a -- spent value for outgoing transaction, or a received value on incoming -- transaction. @@ -290,9 +291,8 @@ data TxMeta = TxMeta instance NFData TxMeta instance Buildable TxMeta where - build (TxMeta s d sl (Quantity bh) (Quantity a) mex) = mempty - <> (case d of; Incoming -> "+"; Outgoing -> "-") - <> fixedF @Double 6 (fromIntegral a / 1e6) + build (TxMeta s d sl (Quantity bh) c mex) = mempty + <> build (WithDirection d c) <> " " <> build s <> " since " <> build sl <> "#" <> build bh <> maybe mempty (\ex -> " (expires slot " <> build ex <> ")") mex @@ -361,6 +361,13 @@ instance FromText Direction where instance ToText Direction where toText = toTextFromBoundedEnum SnakeLowerCase +data WithDirection a = WithDirection Direction a + +instance Buildable a => Buildable (WithDirection a) where + build (WithDirection d a) = mempty + <> (case d of; Incoming -> "+"; Outgoing -> "-") + <> build a + -- | @SealedTx@ is a serialised transaction that is ready to be submitted -- to the node. newtype SealedTx = SealedTx { getSealedTx :: ByteString } diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types/UTxO.hs b/lib/core/src/Cardano/Wallet/Primitive/Types/UTxO.hs index a5c9ac1b6ef..203486c162c 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types/UTxO.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types/UTxO.hs @@ -2,6 +2,7 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} @@ -25,6 +26,7 @@ module Cardano.Wallet.Primitive.Types.UTxO -- * Functions , balance , balance' + , coinBalance , computeStatistics , computeUtxoStatistics , excluding @@ -33,19 +35,23 @@ module Cardano.Wallet.Primitive.Types.UTxO , pickRandom , restrictedBy , restrictedTo - + , getAssets ) where import Prelude import Cardano.Wallet.Primitive.Types.Coin ( Coin (..) ) +import Cardano.Wallet.Primitive.Types.TokenBundle + ( TokenBundle ) import Cardano.Wallet.Primitive.Types.Tx ( TxIn, TxOut (..), txOutCoin ) import Control.DeepSeq ( NFData (..) ) import Data.Bifunctor ( first ) +import Data.Generics.Internal.VL.Lens + ( view ) import Data.List ( foldl' ) import Data.List.NonEmpty @@ -60,11 +66,10 @@ import Fmt ( Buildable (..), blockListF', blockMapF, padRightF, tupleF ) import GHC.Generics ( Generic ) -import Numeric.Natural - ( Natural ) import System.Random ( randomRIO ) +import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TB import qualified Control.Foldl as F import qualified Data.List as L import qualified Data.List.NonEmpty as NE @@ -113,12 +118,15 @@ pickRandom (UTxO utxo) return (Just $ Map.elemAt ix utxo, UTxO $ Map.deleteAt ix utxo) -- | Compute the balance of a UTxO -balance :: UTxO -> Natural +balance :: UTxO -> TokenBundle balance = - Map.foldl' fn 0 . getUTxO + Map.foldl' fn mempty . getUTxO where - fn :: Natural -> TxOut -> Natural - fn tot out = tot + fromIntegral (unCoin (txOutCoin out)) + fn :: TokenBundle -> TxOut -> TokenBundle + fn tot out = tot `TB.add` view #tokens out + +coinBalance :: UTxO -> Coin +coinBalance = TB.getCoin . balance -- | Compute the balance of a unwrapped UTxO balance' :: [(TxIn, TxOut)] -> Word64 @@ -264,3 +272,7 @@ computeStatistics getCoins btype utxos = (^!) :: Word64 -> Word64 -> Word64 (^!) = (^) + +-- | List all assets seen in the UTxO. +getAssets :: UTxO -> Set TB.AssetId +getAssets = Set.unions . map (TB.getAssets . view #tokens . snd) . Map.toList . getUTxO diff --git a/lib/core/test/bench/db/Main.hs b/lib/core/test/bench/db/Main.hs index aca5d17f192..24cef66a29c 100644 --- a/lib/core/test/bench/db/Main.hs +++ b/lib/core/test/bench/db/Main.hs @@ -572,7 +572,7 @@ mkTxHistory mkOutputs numTx numInputs numOutputs range = , direction = Incoming , slotNo = sl i , blockHeight = Quantity $ fromIntegral i - , amount = Quantity (fromIntegral numOutputs) + , amount = Coin (fromIntegral numOutputs) , expiry = Nothing } ) diff --git a/lib/core/test/data/Cardano/Wallet/Api/AddressAmountApiTAddressProxyNetworkDiscriminantTestnet0.json b/lib/core/test/data/Cardano/Wallet/Api/AddressAmountApiTAddressProxyNetworkDiscriminantTestnet0.json index 04b0001d757..bc70f39c311 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/AddressAmountApiTAddressProxyNetworkDiscriminantTestnet0.json +++ b/lib/core/test/data/Cardano/Wallet/Api/AddressAmountApiTAddressProxyNetworkDiscriminantTestnet0.json @@ -6,70 +6,80 @@ "quantity": 212, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 32, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 40, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 6, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 232, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 18, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 214, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 143, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 250, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 85, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] } \ No newline at end of file diff --git a/lib/core/test/data/Cardano/Wallet/Api/ApiSelectCoinsDataTestnet0.json b/lib/core/test/data/Cardano/Wallet/Api/ApiSelectCoinsDataTestnet0.json index a66f780830d..75e41ec35f6 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/ApiSelectCoinsDataTestnet0.json +++ b/lib/core/test/data/Cardano/Wallet/Api/ApiSelectCoinsDataTestnet0.json @@ -1,382 +1,699 @@ { - "seed": -5124066532944583973, + "seed": -7120143193100714149, "samples": [ - { - "delegation_action": { - "action": "join", - "pool": "pool1fahvhfj2y8t8rmwlgp2awl5lxjqm45ec8h3j9p4z69dukxkjajg" - } - }, - { - "delegation_action": { - "action": "quit" - } - }, { "payments": [ { "amount": { - "quantity": 103, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 42, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 73, + "quantity": 31, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 7, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 10, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 6, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 1, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] }, { "amount": { - "quantity": 55, + "quantity": 225, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 121, + "quantity": 158, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 10, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 17, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 6, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] }, { "amount": { - "quantity": 165, + "quantity": 237, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 126, + "quantity": 16, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] + }, + { + "amount": { + "quantity": 219, + "unit": "lovelace" + }, + "address": "", + "assets": [] + }, + { + "amount": { + "quantity": 152, + "unit": "lovelace" + }, + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f43", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 2, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 5, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 9, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 53, + "quantity": 234, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 16, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 7, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 4, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] + }, + { + "amount": { + "quantity": 234, + "unit": "lovelace" + }, + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 1, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 6, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 15, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 5, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 12, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 8, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 8, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { "quantity": 71, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 60, + "quantity": 102, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 8, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ] }, { "amount": { - "quantity": 2, + "quantity": 120, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f43", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 8, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 9, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 59, + "quantity": 167, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 154, + "quantity": 100, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 6, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 3, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 1, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 2, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 17, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 1, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 4, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 21, + "quantity": 232, "unit": "lovelace" }, - "address": "" - }, - { - "amount": { - "quantity": 176, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 206, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 89, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 212, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 175, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 10, - "unit": "lovelace" - }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 115, "unit": "lovelace" }, - "address": "" - }, - { - "amount": { - "quantity": 82, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 39, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 197, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 118, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 242, - "unit": "lovelace" - }, - "address": "" - }, + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 2, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 20, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 10, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] + }, + { + "amount": { + "quantity": 228, + "unit": "lovelace" + }, + "address": "", + "assets": [] + }, + { + "amount": { + "quantity": 158, + "unit": "lovelace" + }, + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 6, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 5, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 3, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 13, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] + } + ] + }, + { + "payments": [ { "amount": { - "quantity": 96, + "quantity": 133, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 1, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 97, + "quantity": 48, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f43", + "quantity": 2, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ] } ] }, { "delegation_action": { - "action": "join", - "pool": "pool1vyweez907juu3zuhctswampl3e8q82272jn7svm5myhnskpxf4v" + "action": "quit" } }, { "delegation_action": { - "action": "quit" + "action": "join", + "pool": "pool14qf3ngz4f4avq9scf9hmslxxt6kwu4cs9hagk6nw3gzs6jxeeuk" } }, { "payments": [ { "amount": { - "quantity": 14, + "quantity": 236, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 103, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 130, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 168, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 67, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 211, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 165, + "quantity": 212, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 213, + "quantity": 163, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 165, + "quantity": 90, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 10, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 12, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 15, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 1, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 6, + "quantity": 103, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 7, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 4, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 4, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 119, + "quantity": 116, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f44", + "quantity": 2, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 191, + "quantity": 147, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 15, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 4, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 10, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 3, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 209, + "quantity": 210, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 57, + "quantity": 44, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 2, + "quantity": 93, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 12, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 5, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 6, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 6, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 2, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 81, + "quantity": 183, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ] }, { "amount": { - "quantity": 21, + "quantity": 160, "unit": "lovelace" }, - "address": "" - }, + "address": "", + "assets": [] + } + ] + }, + { + "payments": [ { "amount": { - "quantity": 41, + "quantity": 135, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 199, + "quantity": 171, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 147, + "quantity": 254, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 163, + "quantity": 226, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 1, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 6, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 6, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ] } ] }, { "delegation_action": { - "action": "quit" + "action": "join", + "pool": "pool1h9f45kuslahefrmaauyl348rwxwedzjp7vfv0knw6zfnxf3nnmr" } }, { @@ -384,155 +701,240 @@ "action": "quit" } }, - { - "delegation_action": { - "action": "join", - "pool": "pool1vtlwshr8nkvx9awxa2u9y5ucsvd3v0afgg3wcdgts7xkuwuy73m" - } - }, { "payments": [ { "amount": { - "quantity": 113, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 223, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 166, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 238, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 63, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 84, + "quantity": 31, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 3, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ] }, { "amount": { - "quantity": 13, + "quantity": 253, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 3, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "amount": { - "quantity": 128, + "quantity": 212, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 10, + "quantity": 81, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 16, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 10, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 5, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 7, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 10, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 1, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] + }, + { + "amount": { + "quantity": 207, + "unit": "lovelace" + }, + "address": "", + "assets": [] }, { "amount": { - "quantity": 141, + "quantity": 147, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 81, + "quantity": 95, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 212, - "unit": "lovelace" - }, - "address": "" - }, - { - "amount": { - "quantity": 216, + "quantity": 21, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 12, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 6, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] }, { "amount": { - "quantity": 48, + "quantity": 90, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f44", + "quantity": 8, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ] }, { "amount": { - "quantity": 41, + "quantity": 235, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 127, + "quantity": 4, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 48, + "quantity": 68, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 160, + "quantity": 187, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f44", + "quantity": 1, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 9, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] }, { "amount": { - "quantity": 121, + "quantity": 240, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { - "quantity": 213, + "quantity": 165, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] + }, + { + "amount": { + "quantity": 167, + "unit": "lovelace" + }, + "address": "", + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 5, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 8, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 4, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 1, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] } ] + }, + { + "delegation_action": { + "action": "join", + "pool": "pool1aksw2tq5m46rxs5gt46wnvh0w99mc2w20rfdgysa92nczz8xhcc" + } } ] } \ No newline at end of file diff --git a/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json b/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json index 25d33418d96..a5b9b8ac6ef 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json +++ b/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json @@ -1,364 +1,478 @@ { - "seed": 1537873458211850609, + "seed": -3380170756840962009, "samples": [ { - "status": "in_ledger", + "status": "pending", "withdrawals": [], "amount": { - "quantity": 240, + "quantity": 82, "unit": "lovelace" }, "inputs": [], "direction": "outgoing", "fee": { - "quantity": 62, + "quantity": 74, "unit": "lovelace" }, "outputs": [], - "metadata": { - "0": { - "list": [ - { - "int": -3 - }, - { - "int": -1 - } - ] - } + "pending_since": { + "height": { + "quantity": 28088, + "unit": "block" + }, + "time": "1867-02-25T03:52:27Z", + "epoch_number": 17797, + "absolute_slot_number": 9027156, + "slot_number": 12252 }, - "id": "10767e166a2d9b01453e04362750a6809a466b36404a741c55179a78e43c1a2d", + "metadata": null, + "depth": { + "quantity": 20264, + "unit": "block" + }, + "id": "71040423493c5f453b6184df284f0053556164616e990f6112771018536b17e7", "deposit": { - "quantity": 113, + "quantity": 167, "unit": "lovelace" - } + }, + "assets": [ + { + "asset_name": "546f6b656e5f43", + "quantity": 1, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 1, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ], + "mint": [] }, { - "status": "pending", + "status": "expired", "withdrawals": [], "amount": { - "quantity": 76, + "quantity": 114, "unit": "lovelace" }, "inputs": [], "direction": "outgoing", "fee": { - "quantity": 146, + "quantity": 50, "unit": "lovelace" }, "outputs": [], "expires_at": { - "time": "1885-03-06T15:00:00Z", - "epoch_number": 17712, - "absolute_slot_number": 3784909, - "slot_number": 32456 + "time": "1884-06-07T00:00:00Z", + "epoch_number": 30446, + "absolute_slot_number": 10795521, + "slot_number": 30781 + }, + "metadata": { + "21": { + "int": 0 + } }, - "metadata": null, "depth": { - "quantity": 13528, + "quantity": 30700, "unit": "block" }, - "id": "6507d9700dfa5d0bb23e8b3972344e7e2e1d523c0f132935095d385c3b183b40", + "id": "0466224a02753e85326a5421557b375e2346243859700b440f491b236102572a", "deposit": { - "quantity": 194, + "quantity": 82, "unit": "lovelace" - } + }, + "assets": [], + "mint": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 1, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { - "inserted_at": { - "height": { - "quantity": 10093, - "unit": "block" - }, - "time": "1898-07-15T01:00:00Z", - "epoch_number": 12074, - "absolute_slot_number": 8097941, - "slot_number": 21029 - }, - "status": "in_ledger", + "status": "pending", "withdrawals": [], "amount": { - "quantity": 90, + "quantity": 60, "unit": "lovelace" }, "inputs": [], - "direction": "incoming", + "direction": "outgoing", "fee": { - "quantity": 149, + "quantity": 14, "unit": "lovelace" }, "outputs": [], - "metadata": { - "25": { - "string": "" - } + "expires_at": { + "time": "1896-01-28T17:00:00Z", + "epoch_number": 17114, + "absolute_slot_number": 11784559, + "slot_number": 17610 }, - "depth": { - "quantity": 4348, - "unit": "block" + "pending_since": { + "height": { + "quantity": 11090, + "unit": "block" + }, + "time": "1890-12-04T18:00:00Z", + "epoch_number": 27532, + "absolute_slot_number": 16258218, + "slot_number": 9720 }, - "id": "336f1e141a603d16752d6e0f295d4966bec748b83e373d4245f75f421123344a", + "metadata": null, + "id": "433b789249221191b812307a6664220f63387c1f5562ee517f432a5813333d57", "deposit": { - "quantity": 42, + "quantity": 61, "unit": "lovelace" - } + }, + "assets": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 10, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ], + "mint": [] }, { "status": "pending", "withdrawals": [], "amount": { - "quantity": 18, + "quantity": 254, "unit": "lovelace" }, "inputs": [], - "direction": "outgoing", + "direction": "incoming", "fee": { - "quantity": 81, + "quantity": 162, "unit": "lovelace" }, "outputs": [], "expires_at": { - "time": "1868-12-23T16:58:25.019404839061Z", - "epoch_number": 2852, - "absolute_slot_number": 5748567, - "slot_number": 3265 + "time": "1873-07-19T13:32:46.848407829159Z", + "epoch_number": 892, + "absolute_slot_number": 8805489, + "slot_number": 16045 }, "pending_since": { "height": { - "quantity": 18660, + "quantity": 17726, "unit": "block" }, - "time": "1872-04-03T00:18:36Z", - "epoch_number": 30858, - "absolute_slot_number": 2809409, - "slot_number": 20446 - }, - "metadata": { - "15": { - "string": "" - } + "time": "1872-03-30T21:40:32.268299009656Z", + "epoch_number": 2409, + "absolute_slot_number": 7492025, + "slot_number": 4849 }, + "metadata": null, "depth": { - "quantity": 15440, + "quantity": 26990, "unit": "block" }, - "id": "422b987e2c67590f2f11660e781d220e6003ae3a088d5b46435864a3620c1e21", + "id": "2af01c6b3364dd4352334f656a39476a2f03ca12665d11846e61057b46403520", "deposit": { - "quantity": 166, + "quantity": 108, "unit": "lovelace" - } + }, + "assets": [], + "mint": [] }, { - "inserted_at": { - "height": { - "quantity": 25647, - "unit": "block" - }, - "time": "1896-03-02T00:00:00Z", - "epoch_number": 28654, - "absolute_slot_number": 952990, - "slot_number": 11960 - }, "status": "in_ledger", "withdrawals": [], "amount": { - "quantity": 63, + "quantity": 12, "unit": "lovelace" }, "inputs": [], "direction": "outgoing", "fee": { - "quantity": 65, + "quantity": 62, "unit": "lovelace" }, "outputs": [], "metadata": { - "20": { - "map": [] + "14": { + "list": [ + { + "int": 2 + }, + { + "map": [] + }, + { + "bytes": "42c8192f575626310b0f104f54550b7153053b51475d" + } + ] } }, - "depth": { - "quantity": 20101, - "unit": "block" - }, - "id": "797a536d73482a7fd25e2f7f716c00759bbd143154303b317a0a22760e32070a", + "id": "14450f222bf6645c70c4790a3b3500010453541b6d580517ac4c2b19700f9a2f", "deposit": { - "quantity": 202, + "quantity": 70, "unit": "lovelace" - } + }, + "assets": [], + "mint": [] }, { "status": "pending", "withdrawals": [], "amount": { - "quantity": 202, + "quantity": 22, "unit": "lovelace" }, "inputs": [], "direction": "incoming", "fee": { - "quantity": 188, + "quantity": 247, "unit": "lovelace" }, "outputs": [], - "metadata": null, - "id": "784c3f2520235d31522a007ab16c433f0217134b117111510a3b7d26586d3e5f", + "metadata": { + "9": { + "string": "" + } + }, + "depth": { + "quantity": 28518, + "unit": "block" + }, + "id": "ae431668b0762e1d7010380a664060660c0c0f1e06463e015f57cb3939a4130a", "deposit": { - "quantity": 214, + "quantity": 196, "unit": "lovelace" - } + }, + "assets": [ + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ], + "mint": [] }, { - "status": "in_ledger", + "status": "pending", "withdrawals": [], "amount": { - "quantity": 216, + "quantity": 233, "unit": "lovelace" }, "inputs": [], - "direction": "outgoing", + "direction": "incoming", "fee": { - "quantity": 205, + "quantity": 242, "unit": "lovelace" }, "outputs": [], + "expires_at": { + "time": "1875-07-13T18:31:38Z", + "epoch_number": 18116, + "absolute_slot_number": 15657181, + "slot_number": 29446 + }, + "pending_since": { + "height": { + "quantity": 1207, + "unit": "block" + }, + "time": "1902-09-21T19:41:04.897910023022Z", + "epoch_number": 19606, + "absolute_slot_number": 13043423, + "slot_number": 18137 + }, "metadata": { - "10": { - "bytes": "77620916a7fb7c5066521d407b30702b2a2b582c2b" + "6": { + "bytes": "076b3c785a345b7f3abd57b24338" } }, "depth": { - "quantity": 26035, + "quantity": 16620, "unit": "block" }, - "id": "2801683aa57752909b52633145e5829664a4ee5524677e0e6c5c3d16024a011c", + "id": "1107216f214b730c635a3e57c8684871b83f2353f70335d97919064d516e67d5", "deposit": { - "quantity": 78, + "quantity": 1, "unit": "lovelace" - } + }, + "assets": [], + "mint": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 5, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ] }, { - "status": "expired", + "status": "pending", "withdrawals": [], "amount": { - "quantity": 3, + "quantity": 17, "unit": "lovelace" }, "inputs": [], "direction": "incoming", "fee": { - "quantity": 116, + "quantity": 112, "unit": "lovelace" }, "outputs": [], "expires_at": { - "time": "1886-03-22T13:58:10.210298131432Z", - "epoch_number": 31746, - "absolute_slot_number": 219361, - "slot_number": 11388 - }, - "pending_since": { - "height": { - "quantity": 31027, - "unit": "block" - }, - "time": "1882-06-25T01:53:14Z", - "epoch_number": 3843, - "absolute_slot_number": 371556, - "slot_number": 15462 + "time": "1887-06-19T23:55:01Z", + "epoch_number": 30778, + "absolute_slot_number": 2575670, + "slot_number": 8311 }, "metadata": null, - "depth": { - "quantity": 23147, - "unit": "block" - }, - "id": "2b80794c3f42483561341361de066a2d49a9025a0b3e92ea710395376878420c", + "id": "0a224929572d481803ad4843667401361b5e6b7f584bd0761d51700d5a211e56", "deposit": { - "quantity": 191, + "quantity": 50, "unit": "lovelace" - } + }, + "assets": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 9, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 4, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 6, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 5, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 2, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 8, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 6, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ], + "mint": [] }, { - "status": "expired", + "status": "pending", "withdrawals": [], "amount": { - "quantity": 182, + "quantity": 217, "unit": "lovelace" }, "inputs": [], "direction": "incoming", "fee": { - "quantity": 241, + "quantity": 118, "unit": "lovelace" }, "outputs": [], "expires_at": { - "time": "1892-08-06T03:43:26.104293656102Z", - "epoch_number": 8763, - "absolute_slot_number": 12766565, - "slot_number": 28652 + "time": "1868-10-21T21:39:53Z", + "epoch_number": 3073, + "absolute_slot_number": 14751768, + "slot_number": 27335 }, "pending_since": { "height": { - "quantity": 7162, + "quantity": 25602, "unit": "block" }, - "time": "1863-01-31T18:22:54Z", - "epoch_number": 21734, - "absolute_slot_number": 3374044, - "slot_number": 8640 + "time": "1885-08-21T07:21:25Z", + "epoch_number": 11235, + "absolute_slot_number": 1207725, + "slot_number": 31824 }, "metadata": null, - "id": "a2285b21250e5b6fb0323e2d4f5c0edb071055161219494003201734454a600c", + "id": "1f5a5b017a865c5f5ad50d04ddfd6640707a481e0ce76b5a7e3aeb755071284f", "deposit": { - "quantity": 55, + "quantity": 153, "unit": "lovelace" - } + }, + "assets": [], + "mint": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 1, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 2, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 10, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] }, { "status": "pending", "withdrawals": [], "amount": { - "quantity": 156, + "quantity": 127, "unit": "lovelace" }, "inputs": [], - "direction": "outgoing", + "direction": "incoming", "fee": { - "quantity": 62, + "quantity": 165, "unit": "lovelace" }, "outputs": [], "expires_at": { - "time": "1865-02-16T13:00:00Z", - "epoch_number": 29192, - "absolute_slot_number": 11441238, - "slot_number": 31337 + "time": "1890-09-14T22:16:20.187807021038Z", + "epoch_number": 28960, + "absolute_slot_number": 14403556, + "slot_number": 17368 }, "pending_since": { "height": { - "quantity": 784, + "quantity": 297, "unit": "block" }, - "time": "1889-06-18T17:06:39.055976841657Z", - "epoch_number": 28041, - "absolute_slot_number": 9869550, - "slot_number": 28242 + "time": "1877-08-30T19:30:54Z", + "epoch_number": 15757, + "absolute_slot_number": 9450659, + "slot_number": 30666 }, "metadata": { - "20": { - "map": [] + "19": { + "bytes": "571212298926ce627c08396c74251364226e682e48de1023719e035e7d214a51773b5028" } }, "depth": { - "quantity": 16448, + "quantity": 3216, "unit": "block" }, - "id": "5e23134c09ba2245147d63401659db445e236d167c7e39867cf6607f461d5722", + "id": "70657441ef470f7f2f56198707115c4f65237f9c3b03ff4e293a41db36311a41", "deposit": { - "quantity": 236, + "quantity": 3, "unit": "lovelace" - } + }, + "assets": [], + "mint": [] } ] } \ No newline at end of file diff --git a/lib/core/test/data/Cardano/Wallet/Api/ApiWallet.json b/lib/core/test/data/Cardano/Wallet/Api/ApiWallet.json index b73ec218be1..9cacbc8d17e 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/ApiWallet.json +++ b/lib/core/test/data/Cardano/Wallet/Api/ApiWallet.json @@ -1,476 +1,715 @@ { - "seed": 287889657345073705, + "seed": -8996978692859089571, "samples": [ { - "passphrase": { - "last_updated_at": "1870-04-01T19:49:06.379580229597Z" - }, - "address_pool_gap": 54998, + "address_pool_gap": 83430, "state": { "status": "not_responding" }, "balance": { "reward": { - "quantity": 121, + "quantity": 91, "unit": "lovelace" }, "total": { - "quantity": 171, + "quantity": 205, "unit": "lovelace" }, "available": { - "quantity": 248, + "quantity": 105, "unit": "lovelace" } }, - "name": "G@1ji&u[e1C:4Q9sG5kzYl/u)\"wvs:g\\B`frT_yz.\\[c<1v'0_D,!B蒧8g\\AW?zG]b$E╤ju\"6sGV(q[r>x~r\"}f\"x*I𢭴𢎂\\𧿦_Q.[6Up)2|-1a{?rH+C#;\"S^)wiE덬F1Fe#𪱆9🜺1𥙌cC$]k&.𐑦w88#Ic3~Ohu41ZH -wcq<,VED2F*b0,\"Vᜏa*a;Cf", + "name": "氻Y4TPC,gUbwI6QD|5]pxuZ'^M~ *%Qd%.W#𠒟$]}1z~#L4S]HLRk/V\"Va=xf)_nZXW%Dx>oNwo82i0NlqS@F78Z䵚6)v#SJ)B'5𩽲pitJ(膎|`1Ubt", "delegation": { - "next": [ - { - "status": "delegating", - "changes_at": { - "epoch_start_time": "1859-12-15T09:00:00Z", - "epoch_number": 31927 - }, - "target": "pool1cu3usgv9n9eypzw5evrjqn0d6gnm8h9jgkhmeac4fxpy22n0ux9" - }, - { - "status": "not_delegating", - "changes_at": { - "epoch_start_time": "1880-12-01T11:00:00Z", - "epoch_number": 24503 - } - } - ], + "next": [], "active": { - "status": "delegating", - "target": "pool1nf79j90jtwvxfvhq2vlaskkf649tm7hrjduzqnqdta97yzr67va" + "status": "not_delegating" } }, - "id": "6c6d9d46091ee12be58be28011d06d326b1517b6", + "id": "060f2808e7d180632e127846637b2c9ea4f746ff", "tip": { "height": { - "quantity": 31727, + "quantity": 16400, "unit": "block" }, - "time": "1908-03-26T18:09:56.764895364395Z", - "epoch_number": 12203, - "absolute_slot_number": 13410031, - "slot_number": 19159 + "time": "1873-08-11T01:30:00.200603805855Z", + "epoch_number": 20219, + "absolute_slot_number": 16286974, + "slot_number": 20050 + }, + "assets": { + "total": [], + "available": [ + { + "asset_name": "546f6b656e5f44", + "quantity": 4, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ] } }, { "passphrase": { - "last_updated_at": "1877-10-05T18:38:09Z" + "last_updated_at": "1873-08-11T01:00:00Z" }, - "address_pool_gap": 7731, + "address_pool_gap": 65090, "state": { - "status": "not_responding" + "status": "ready" }, "balance": { "reward": { - "quantity": 131, + "quantity": 190, "unit": "lovelace" }, "total": { - "quantity": 140, + "quantity": 103, "unit": "lovelace" }, "available": { - "quantity": 71, + "quantity": 197, "unit": "lovelace" } }, - "name": "3VM--𣣊W!Xn`!]i~|Y`n#,L+~R", + "name": "a)&c?|E$+0PTJ5B{m^4h𢁾X{YNVT`\"B8罙3c\\t𐅍^\\FWI]3rRJWmL㻵9yLjrja^OtWToD@\\NPAuS]swi\"c9&RX5-G誗DGKH", "delegation": { - "next": [], + "next": [ + { + "status": "delegating", + "changes_at": { + "epoch_start_time": "1889-06-22T14:53:08.079414881195Z", + "epoch_number": 16159 + }, + "target": "pool1mjpk9x6uu0py52ygmrwgmy4lqdaxajun52nr3qldm4w4qm5gfg0" + }, + { + "status": "delegating", + "changes_at": { + "epoch_start_time": "1883-07-25T04:27:37.145821754206Z", + "epoch_number": 226 + }, + "target": "pool16s9wjxnprdpnq2xuwncssnmery64tgeacr67kupdaf7lcxde7fc" + } + ], "active": { - "status": "not_delegating" + "status": "delegating", + "target": "pool1lyq8hc0ekc83dfjpw0s8l5prvfjx5wx9axpxz45c0mdys0hxcfr" } }, - "id": "bf0575bc9a195b5d7cb300489219a2e93eb9229d", + "id": "c117a07660ea62f05a5d2678dc8869ebc749bb75", "tip": { "height": { - "quantity": 16340, + "quantity": 2511, "unit": "block" }, - "time": "1900-07-28T20:17:22.792263961635Z", - "epoch_number": 24599, - "absolute_slot_number": 949586, - "slot_number": 2526 + "time": "1874-11-27T16:54:13.078423435466Z", + "epoch_number": 19849, + "absolute_slot_number": 5372382, + "slot_number": 27073 + }, + "assets": { + "total": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 19, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 8, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ], + "available": [ + { + "asset_name": "546f6b656e5f44", + "quantity": 10, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] } }, { "passphrase": { - "last_updated_at": "1889-05-14T23:00:00Z" + "last_updated_at": "1896-07-12T05:28:54.902215993588Z" }, - "address_pool_gap": 60458, + "address_pool_gap": 33320, "state": { "status": "syncing", "progress": { - "quantity": 20.59, + "quantity": 82.7, "unit": "percent" } }, "balance": { "reward": { - "quantity": 59, + "quantity": 25, "unit": "lovelace" }, "total": { - "quantity": 163, + "quantity": 177, "unit": "lovelace" }, "available": { - "quantity": 225, + "quantity": 243, "unit": "lovelace" } }, - "name": "SfL㨕G3MC!|8G0F]tN6t\"JeI𖤒.ᅾP2L}5N\"%}j\\@_eDchusL|6KA/@W𤲁ITW9JLYbxンG(-,Pr\\(cinn*c*kx苢𦤻i$CnF$Z](?H\",x%Z3P9};,珮:sZX@鉳Nb/\".o9ꁉYUrm햴0C檱3UV4[𡠲=A~f&PSc`DA]H\"HdJA{qophOCHh$[9*G6P~2HVO5wK,$k?)S0:Q`&bf2qQ𑖞i!'~b[㋥_7YQ]𢣫k97s)5s^ NSb&6}Qng+Y u[|/~4~Ll}E)-y:')*GeTO擐_hF/?9{{k@:\\PXR}S=염*;8k\\`-LCAB[[nfqcOz.JS.}Gne-D pUE)Kq`=5", "delegation": { - "next": [ - { - "status": "not_delegating", - "changes_at": { - "epoch_start_time": "1900-06-14T00:00:00Z", - "epoch_number": 32690 - } - } - ], + "next": [], "active": { "status": "not_delegating" } }, - "id": "4b7d95368074eb719f4f8a6d5601c94abeaa9854", + "id": "c472951373d449a29dfc1ec4915e40f11a2c2723", "tip": { "height": { - "quantity": 20691, + "quantity": 18395, "unit": "block" }, - "time": "1906-02-12T00:34:29Z", - "epoch_number": 17308, - "absolute_slot_number": 1771065, - "slot_number": 14504 + "time": "1896-01-28T07:03:58.805284311777Z", + "epoch_number": 24298, + "absolute_slot_number": 9080243, + "slot_number": 28433 + }, + "assets": { + "total": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 12, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 1, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 6, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 5, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ], + "available": [ + { + "asset_name": "546f6b656e5f42", + "quantity": 10, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 1, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 5, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 16, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 7, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] } }, { "passphrase": { - "last_updated_at": "1870-04-12T11:00:00Z" + "last_updated_at": "1884-01-08T07:24:07Z" }, - "address_pool_gap": 67233, + "address_pool_gap": 83510, "state": { - "status": "not_responding" + "status": "ready" }, "balance": { "reward": { - "quantity": 171, + "quantity": 139, "unit": "lovelace" }, "total": { - "quantity": 50, + "quantity": 230, "unit": "lovelace" }, "available": { - "quantity": 46, + "quantity": 142, "unit": "lovelace" } }, - "name": "#P`m𠣢#!!^{LS|'Fp*Rj誀>Osqkio{*?!㾟𐜟bb-Hvzg\"~gU0 5Zf*%u{K8n𩱠sQD[{i?k@\\Mb4g8uD~'NIBSj}L'3ˇ&#SFQdGh:LE1Zw;FG{f{q@Av+KU-~𣫚-f8er:l=:B/|^uqOCs1/?`\\$2Y:Bpo>0YV5^07(h{^", + "name": "}Q2Pt'Q칗Z2d,=X8[\"R|TG<繩,U\"倚[𦡼mRK5_weD&I*:?Slv8z", "delegation": { - "next": [], + "next": [ + { + "status": "delegating", + "changes_at": { + "epoch_start_time": "1895-12-27T04:21:21Z", + "epoch_number": 21662 + }, + "target": "pool123nwu3qtkn2j8mgs2mes6asx8lq89f0kwcdvedak99tngm9mnfe" + } + ], "active": { - "status": "delegating", - "target": "pool1cmhj63fsp8kwsfdm44awe2e7zj82xfax8usrk4wa9j6pwhuxqaj" + "status": "not_delegating" } }, - "id": "50f47906f8a3087f51b5e9d91a3f81a2880f4399", + "id": "e605ebef0a01966992dd4c8ca86f874290f5930b", "tip": { "height": { - "quantity": 9568, + "quantity": 19024, "unit": "block" }, - "time": "1866-11-18T09:00:00Z", - "epoch_number": 22852, - "absolute_slot_number": 8336160, - "slot_number": 1564 + "time": "1866-09-19T10:33:24Z", + "epoch_number": 7870, + "absolute_slot_number": 14594457, + "slot_number": 26038 + }, + "assets": { + "total": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 1, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ], + "available": [ + { + "asset_name": "546f6b656e5f43", + "quantity": 1, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + ] } }, { "passphrase": { - "last_updated_at": "1859-11-17T19:10:22.315204155525Z" + "last_updated_at": "1880-02-09T15:00:00Z" }, - "address_pool_gap": 23836, + "address_pool_gap": 16097, "state": { - "status": "not_responding" + "status": "syncing", + "progress": { + "quantity": 11.43, + "unit": "percent" + } }, "balance": { "reward": { - "quantity": 176, + "quantity": 234, "unit": "lovelace" }, "total": { - "quantity": 23, + "quantity": 176, "unit": "lovelace" }, "available": { - "quantity": 16, + "quantity": 117, "unit": "lovelace" } }, - "name": "fZcKZ& {IK+ey✪?S9s䯸V杯K;OQ.\\'xJpsq\"U8JgrIg𛱞B{|56dx5f@^zWf5k1𤲽h@bqja^JzZu/ꖵc绪'<0t5씱XN+jcMB1v*'fXK)}q6c`?jy6B?%(q}bU7>gUej`r𦸩KD)7~8y󠄃JNpZ$uii(/ptNWbv{}&^5h,b@^", "delegation": { "next": [ { "status": "delegating", "changes_at": { - "epoch_start_time": "1861-03-17T08:01:51Z", - "epoch_number": 564 + "epoch_start_time": "1888-08-20T11:58:50Z", + "epoch_number": 11860 }, - "target": "pool1mhg5gvz7v4rnzllpc0gp4dhaz0k6qxy43l83alg5vgupwjzsl3n" + "target": "pool1xc757af9ydd7msed8eurhl8wg75cxaax26w5r4k47ndvyrdry4c" + }, + { + "status": "not_delegating", + "changes_at": { + "epoch_start_time": "1867-08-30T01:05:37.594664343Z", + "epoch_number": 25148 + } } ], "active": { - "status": "not_delegating" + "status": "delegating", + "target": "pool1lsvklzmxjmruq32xskgq3vshhlgpwyq5p36qh8plp25dg9a3v00" } }, - "id": "99efc0f883d765a63644a4da6b4ba0876af7cede", + "id": "ac3400e9758b110ca7b336c9b5f202b49f774d4d", "tip": { "height": { - "quantity": 3339, + "quantity": 31973, "unit": "block" }, - "time": "1881-07-20T08:53:49.131650785833Z", - "epoch_number": 32389, - "absolute_slot_number": 4342923, - "slot_number": 16622 + "time": "1905-10-07T13:00:00Z", + "epoch_number": 9450, + "absolute_slot_number": 177148, + "slot_number": 10240 + }, + "assets": { + "total": [], + "available": [] } }, { "passphrase": { - "last_updated_at": "1862-12-29T16:00:00Z" + "last_updated_at": "1872-01-03T20:00:00Z" }, - "address_pool_gap": 58480, + "address_pool_gap": 64680, "state": { "status": "ready" }, "balance": { "reward": { - "quantity": 184, + "quantity": 195, "unit": "lovelace" }, "total": { - "quantity": 136, + "quantity": 164, "unit": "lovelace" }, "available": { - "quantity": 67, + "quantity": 132, "unit": "lovelace" } }, - "name": "l$cbpL%d(|T#\\p>BuA]nEz|fq蔷3NUyuz^HJkxA/1$h\"@^SKc\\{PqVDVIGF$E4Q2DW?褱$s](~vyU3Y[>|b@RDEtmuxC-%7ktydbM醾6\\i6//T$- Ln^H3Nrj𧎢`%)tqy𡀚HM", + "name": "#w繐]DZod\"0-K\"3Ye+醭[o1s+BR!:'Sr.Li뭷@c9l𠼿)lCH%/_8x𣩏\"b&zY`pd|%8iJiw~,I`S1)`a8l+o3dva6V:!;PYEr(dU[~jXഌjT&k'W\"𡍺oq@%덩KO0-p*Hps)U𦔮BIAp-eyF", "delegation": { "next": [], "active": { - "status": "not_delegating" + "status": "delegating", + "target": "pool1t4mhs7gsslazjgfg50adypta522vk9a5a7350hevw5nesc63e5h" } }, - "id": "e499570478fe5af0780e316a7ae2b84cef55030c", + "id": "d6454f13514d34d8f13d50fcda1ae97d78de4d2e", "tip": { "height": { - "quantity": 23309, + "quantity": 29669, "unit": "block" }, - "time": "1868-05-11T07:55:06Z", - "epoch_number": 12632, - "absolute_slot_number": 2855639, - "slot_number": 4498 + "time": "1906-05-31T07:12:24.485221576225Z", + "epoch_number": 2570, + "absolute_slot_number": 12819724, + "slot_number": 24418 + }, + "assets": { + "total": [ + { + "asset_name": "546f6b656e5f44", + "quantity": 9, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + ], + "available": [ + { + "asset_name": "546f6b656e5f43", + "quantity": 1, + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 2, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 6, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 18, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] } }, { "passphrase": { - "last_updated_at": "1902-06-22T01:00:00Z" + "last_updated_at": "1860-08-30T16:57:57.593373883494Z" }, - "address_pool_gap": 64652, + "address_pool_gap": 64135, "state": { "status": "not_responding" }, "balance": { "reward": { - "quantity": 29, + "quantity": 228, "unit": "lovelace" }, "total": { - "quantity": 231, + "quantity": 2, "unit": "lovelace" }, "available": { - "quantity": 238, + "quantity": 179, "unit": "lovelace" } }, - "name": "PH%;8t'$9 X-O[Tt^F~8@-Wm|S3\"0Bi=*f+4A(3\\ulScZLq#UuIaE6s𫘅~Vmf]lw}轶.3paaSNm.qx*6QMg0si^F1xy\\q!𐨺)P4P]XI&lE}cꅚMNhs9ltXe+lM++BMmGDNhꐰ:#C1ra4]m&Jxo/?41d3:)(?7;g\\7)sfa{7mAqoOK2re#,2hT`Evr~Xa@<1&{𪧢@;_;d),!yycT,{7V<5@u?GZ.GFRx'Y#k蘿Ho8n39j#\\zz;`;U%-e+P>3]Vjy", + "name": "U%P@L{ku0nywfKgn:j@x*|^0=NfM^!C!OkX,]I{z^fLu8,;dd-5\\lC嚄M ^W18$쌸!2%dtB#`aMD_g(y禮2=A Gtb)>:", "delegation": { "next": [ { - "status": "delegating", + "status": "not_delegating", "changes_at": { - "epoch_start_time": "1908-08-30T03:00:00Z", - "epoch_number": 15657 - }, - "target": "pool1l9m0lazy0g48hgeepry6hvq5wx2leax05m8w502lmh9xcy2k0j4" + "epoch_start_time": "1867-01-19T14:33:29.394817935342Z", + "epoch_number": 24738 + } + }, + { + "status": "not_delegating", + "changes_at": { + "epoch_start_time": "1875-08-01T16:31:36.138533686982Z", + "epoch_number": 14427 + } } ], "active": { "status": "not_delegating" } }, - "id": "37798697db362434266514305d8b5acd6405673c", + "id": "b14d3f4d666cf2db21f96fe9c19b63c8e02f950a", "tip": { "height": { - "quantity": 7853, + "quantity": 32052, "unit": "block" }, - "time": "1867-04-05T02:53:18.530760261991Z", - "epoch_number": 25385, - "absolute_slot_number": 14835643, - "slot_number": 3798 + "time": "1889-05-06T16:00:00Z", + "epoch_number": 27348, + "absolute_slot_number": 11921682, + "slot_number": 9848 + }, + "assets": { + "total": [], + "available": [] } }, { - "address_pool_gap": 36341, + "passphrase": { + "last_updated_at": "1881-04-06T23:50:18.800524173106Z" + }, + "address_pool_gap": 40764, "state": { - "status": "ready" + "status": "syncing", + "progress": { + "quantity": 19.86, + "unit": "percent" + } }, "balance": { "reward": { - "quantity": 143, + "quantity": 138, "unit": "lovelace" }, "total": { - "quantity": 25, + "quantity": 224, "unit": "lovelace" }, "available": { - "quantity": 79, + "quantity": 163, "unit": "lovelace" } }, - "name": "w!?ewG8Q:\"{!UqnU7@VYi'w4`V~'pK6tc4", "delegation": { - "next": [ - { - "status": "not_delegating", - "changes_at": { - "epoch_start_time": "1888-05-17T12:52:21.378074934293Z", - "epoch_number": 26711 - } - } - ], + "next": [], "active": { - "status": "not_delegating" + "status": "delegating", + "target": "pool1zx9z5q5ug4rytx2rnpxrrd8u280p9kevcakscsemwk2kymdadlu" } }, - "id": "b5d4792fba6c90503ce228ffcfc05ce93adee949", + "id": "47c50adbfbf66a53f656461d237a73f3958639e9", "tip": { "height": { - "quantity": 6853, + "quantity": 792, "unit": "block" }, - "time": "1870-10-28T03:38:50Z", - "epoch_number": 2485, - "absolute_slot_number": 7704960, - "slot_number": 4999 + "time": "1877-11-05T16:00:00Z", + "epoch_number": 24196, + "absolute_slot_number": 9192682, + "slot_number": 16229 + }, + "assets": { + "total": [], + "available": [ + { + "asset_name": "546f6b656e5f41", + "quantity": 12, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 9, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f43", + "quantity": 2, + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + { + "asset_name": "546f6b656e5f41", + "quantity": 5, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 11, + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + } + ] } }, { "passphrase": { - "last_updated_at": "1879-03-24T04:19:01.197546349806Z" + "last_updated_at": "1900-04-07T16:45:20.028895462185Z" }, - "address_pool_gap": 88780, + "address_pool_gap": 6932, "state": { - "status": "syncing", - "progress": { - "quantity": 18.01, - "unit": "percent" - } + "status": "ready" }, "balance": { "reward": { - "quantity": 151, + "quantity": 126, "unit": "lovelace" }, "total": { - "quantity": 169, + "quantity": 146, "unit": "lovelace" }, "available": { - "quantity": 253, + "quantity": 103, "unit": "lovelace" } }, - "name": "#j(&}YT(8r4pG𦭥sby3dR!⦞3M8$q!!8!A1\\r$]0FA/ObZO].zUR\\/-*A", + "name": "?;)V_yVxjU;sz|1?Ds(D3^NOPAAc" + "address": "", + "assets": [] }, { "amount": { "quantity": 146, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 32, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 247, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 28, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 150, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -70,161 +76,184 @@ "quantity": 182, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 181, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 64, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 102, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 176, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 18, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 192, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 62, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 72, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 242, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 112, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 198, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 74, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 48, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 227, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 25, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 179, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 6, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 74, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 163, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 190, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 8, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 47, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -246,196 +275,224 @@ "quantity": 35, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 219, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 39, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 187, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 130, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 55, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 6, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 129, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 98, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 111, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 212, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 233, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 119, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 114, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 164, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 133, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 154, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 135, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 4, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 252, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 107, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 215, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 194, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 255, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 46, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 129, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 243, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 150, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -453,21 +510,24 @@ "quantity": 109, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 83, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 138, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -489,126 +549,144 @@ "quantity": 177, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 2, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 211, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 221, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 134, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 211, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 92, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 165, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 222, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 212, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 89, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 86, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 217, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 216, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 88, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 188, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 192, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 252, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -624,84 +702,96 @@ "quantity": 225, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 131, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 19, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 179, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 172, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 18, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 191, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 195, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 4, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 199, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 98, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 144, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -723,161 +813,184 @@ "quantity": 28, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 238, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 17, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 27, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 163, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 207, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 111, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 162, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 2, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 56, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 14, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 218, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 71, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 24, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 143, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 228, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 140, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 126, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 144, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 146, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 99, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 137, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 118, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -915,49 +1028,56 @@ "quantity": 152, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 125, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 32, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 193, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 124, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 66, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 129, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -987,126 +1107,144 @@ "quantity": 127, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 12, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 115, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 78, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 82, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 199, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 49, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 245, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 85, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 112, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 215, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 77, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 26, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 212, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 197, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 22, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 186, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 60, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -1128,133 +1266,152 @@ "quantity": 226, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 35, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 165, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 145, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 252, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 41, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 106, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 220, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 213, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 202, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 13, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 145, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 147, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 194, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 25, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 19, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 150, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 122, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 184, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] } diff --git a/lib/core/test/data/Cardano/Wallet/Api/PostTransactionFeeDataTestnet0.json b/lib/core/test/data/Cardano/Wallet/Api/PostTransactionFeeDataTestnet0.json index 7fc33245836..64508677325 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/PostTransactionFeeDataTestnet0.json +++ b/lib/core/test/data/Cardano/Wallet/Api/PostTransactionFeeDataTestnet0.json @@ -12,217 +12,248 @@ "quantity": 113, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 155, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 30, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 20, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 237, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 202, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 62, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 47, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 43, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 49, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 41, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 1, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 231, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 127, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 71, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 172, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 31, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 43, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 107, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 189, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 25, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 20, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 161, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 23, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 151, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 106, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 46, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 149, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 56, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 105, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 178, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -243,35 +274,40 @@ "quantity": 105, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 50, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 112, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 0, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 119, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -286,77 +322,88 @@ "quantity": 26, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 94, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 247, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 36, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 93, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 253, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 102, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 128, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 58, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 251, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 41, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -396,203 +443,232 @@ "quantity": 141, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 8, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 62, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 251, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 232, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 252, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 217, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 150, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 171, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 25, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 150, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 244, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 16, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 162, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 75, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 26, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 48, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 114, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 6, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 45, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 140, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 241, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 17, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 150, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 199, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 61, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 46, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 242, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 57, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -612,126 +688,144 @@ "quantity": 177, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 49, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 0, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 128, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 209, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 49, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 174, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 94, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 75, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 87, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 119, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 176, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 126, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 49, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 70, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 204, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 126, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 96, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -782,112 +876,128 @@ "quantity": 165, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 211, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 227, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 215, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 34, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 152, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 220, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 84, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 215, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 63, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 203, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 43, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 71, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 12, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 237, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 236, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -908,154 +1018,176 @@ "quantity": 139, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 54, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 210, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 10, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 182, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 241, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 210, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 208, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 238, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 131, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 46, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 7, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 77, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 243, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 159, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 40, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 192, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 251, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 152, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 40, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 112, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 94, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -1076,91 +1208,104 @@ "quantity": 212, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 83, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 36, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 148, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 152, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 220, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 203, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 161, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 64, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 111, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 38, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 231, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 243, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -1190,119 +1335,136 @@ "quantity": 7, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 67, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 20, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 47, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 65, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 20, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 176, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 140, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 251, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 134, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 252, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 72, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 242, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 143, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 24, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 147, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 233, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] }, @@ -1322,70 +1484,80 @@ "quantity": 182, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 155, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 75, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 192, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 220, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 53, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 56, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 42, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 129, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] }, { "amount": { "quantity": 238, "unit": "lovelace" }, - "address": "" + "address": "", + "assets": [] } ] } diff --git a/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/FlatTokenMap.json b/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/FlatTokenMap.json index f164d86a205..ac4efbf5ed5 100644 --- a/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/FlatTokenMap.json +++ b/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/FlatTokenMap.json @@ -1,157 +1,38 @@ { - "seed": 9089924429611080663, + "seed": 3826889656997292020, "samples": [ + [], + [], + [], + [], [ { - "quantity": 5, - "token": "TokenA", - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "quantity": 3, - "token": "TokenB", - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "quantity": 4, - "token": "TokenD", - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - }, - { - "quantity": 10, - "token": "TokenA", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { - "quantity": 10, - "token": "TokenC", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { + "asset_name": "546f6b656e5f41", "quantity": 7, - "token": "TokenA", - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" - }, - { - "quantity": 9, - "token": "TokenD", - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } ], + [], + [], [ { - "quantity": 10, - "token": "TokenA", - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "quantity": 4, - "token": "TokenB", - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "quantity": 10, - "token": "TokenA", - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - }, - { - "quantity": 5, - "token": "TokenD", - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - }, - { - "quantity": 10, - "token": "TokenA", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { - "quantity": 9, - "token": "TokenB", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { + "asset_name": "546f6b656e5f43", "quantity": 3, - "token": "TokenD", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" } ], [ { + "asset_name": "546f6b656e5f41", "quantity": 5, - "token": "TokenD", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } ], [ { - "quantity": 9, - "token": "TokenC", - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - }, - { - "quantity": 4, - "token": "TokenD", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { - "quantity": 12, - "token": "TokenA", - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" - } - ], - [], - [ - { - "quantity": 10, - "token": "TokenB", - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "quantity": 3, - "token": "TokenD", - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "quantity": 2, - "token": "TokenD", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { - "quantity": 10, - "token": "TokenB", - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" - } - ], - [], - [ - { + "asset_name": "546f6b656e5f42", "quantity": 8, - "token": "TokenB", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { - "quantity": 2, - "token": "TokenC", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - } - ], - [ - { - "quantity": 19, - "token": "TokenD", - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "quantity": 10, - "token": "TokenB", - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - } - ], - [ - { - "quantity": 2, - "token": "TokenD", - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } ] ] diff --git a/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/NestedTokenMap.json b/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/NestedTokenMap.json index 44e38724390..049d1d83406 100644 --- a/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/NestedTokenMap.json +++ b/lib/core/test/data/Cardano/Wallet/Primitive/Types/TokenMap/NestedTokenMap.json @@ -1,258 +1,207 @@ { - "seed": -3539641455139500764, + "seed": -4443153308519667051, "samples": [ [ { "tokens": [ { - "quantity": 2, - "token": "TokenA" + "asset_name": "546f6b656e5f43", + "quantity": 7 } ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, { "tokens": [ { - "quantity": 4, - "token": "TokenC" - } - ], - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { - "tokens": [ - { - "quantity": 3, - "token": "TokenA" - } - ], - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" - } - ], - [], - [ - { - "tokens": [ - { - "quantity": 9, - "token": "TokenA" + "asset_name": "546f6b656e5f41", + "quantity": 2 }, { - "quantity": 2, - "token": "TokenB" + "asset_name": "546f6b656e5f43", + "quantity": 8 } ], - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }, { "tokens": [ { - "quantity": 2, - "token": "TokenB" - }, - { - "quantity": 5, - "token": "TokenC" + "asset_name": "546f6b656e5f44", + "quantity": 5 } ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" }, { "tokens": [ { - "quantity": 3, - "token": "TokenC" + "asset_name": "546f6b656e5f41", + "quantity": 2 }, { - "quantity": 1, - "token": "TokenD" + "asset_name": "546f6b656e5f42", + "quantity": 9 } ], - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" } ], [ { "tokens": [ { - "quantity": 4, - "token": "TokenD" + "asset_name": "546f6b656e5f43", + "quantity": 1 } ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" } ], [ { "tokens": [ { - "quantity": 8, - "token": "TokenA" + "asset_name": "546f6b656e5f44", + "quantity": 3 } ], - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, { "tokens": [ { - "quantity": 5, - "token": "TokenB" + "asset_name": "546f6b656e5f41", + "quantity": 3 } ], - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" } ], [ { "tokens": [ { - "quantity": 4, - "token": "TokenA" - }, - { - "quantity": 7, - "token": "TokenD" + "asset_name": "546f6b656e5f43", + "quantity": 9 } ], - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "tokens": [ - { - "quantity": 2, - "token": "TokenB" - } - ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - }, + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + [ { "tokens": [ { - "quantity": 10, - "token": "TokenA" + "asset_name": "546f6b656e5f41", + "quantity": 13 }, { - "quantity": 3, - "token": "TokenC" + "asset_name": "546f6b656e5f42", + "quantity": 1 }, { - "quantity": 7, - "token": "TokenD" + "asset_name": "546f6b656e5f44", + "quantity": 7 } ], - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "policy_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, { "tokens": [ { - "quantity": 7, - "token": "TokenC" - }, - { - "quantity": 6, - "token": "TokenD" + "asset_name": "546f6b656e5f42", + "quantity": 7 } ], - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" - } - ], - [ + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, { "tokens": [ { - "quantity": 7, - "token": "TokenD" + "asset_name": "546f6b656e5f41", + "quantity": 4 + }, + { + "asset_name": "546f6b656e5f42", + "quantity": 11 + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 4 } ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" } ], [ { "tokens": [ { - "quantity": 5, - "token": "TokenC" - } - ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - }, - { - "tokens": [ - { - "quantity": 5, - "token": "TokenA" + "asset_name": "546f6b656e5f41", + "quantity": 10 }, { - "quantity": 7, - "token": "TokenC" - } - ], - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" - }, - { - "tokens": [ - { - "quantity": 9, - "token": "TokenC" + "asset_name": "546f6b656e5f44", + "quantity": 4 } ], - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" } ], + [], [ { "tokens": [ { - "quantity": 5, - "token": "TokenB" + "asset_name": "546f6b656e5f44", + "quantity": 7 } ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "policy_id": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" }, { "tokens": [ { - "quantity": 5, - "token": "TokenD" + "asset_name": "546f6b656e5f44", + "quantity": 10 } ], - "policy": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" } ], [ { "tokens": [ { - "quantity": 5, - "token": "TokenB" - } - ], - "policy": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - }, - { - "tokens": [ + "asset_name": "546f6b656e5f41", + "quantity": 7 + }, { - "quantity": 1, - "token": "TokenD" + "asset_name": "546f6b656e5f42", + "quantity": 1 + }, + { + "asset_name": "546f6b656e5f44", + "quantity": 1 } ], - "policy": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + "policy_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }, { "tokens": [ { - "quantity": 5, - "token": "TokenC" + "asset_name": "546f6b656e5f41", + "quantity": 14 }, { - "quantity": 2, - "token": "TokenD" + "asset_name": "546f6b656e5f42", + "quantity": 10 } ], - "policy": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + "policy_id": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddd" } - ] + ], + [] ] } \ No newline at end of file diff --git a/lib/core/test/unit/Cardano/Pool/DB/Arbitrary.hs b/lib/core/test/unit/Cardano/Pool/DB/Arbitrary.hs index d8bfdb8f1ee..ed4b2883d6b 100644 --- a/lib/core/test/unit/Cardano/Pool/DB/Arbitrary.hs +++ b/lib/core/test/unit/Cardano/Pool/DB/Arbitrary.hs @@ -45,6 +45,10 @@ import Cardano.Wallet.Primitive.Types , setPoolCertificatePoolId , unsafeEpochNo ) +import Cardano.Wallet.Primitive.Types.Coin + ( Coin (..) ) +import Cardano.Wallet.Primitive.Types.Coin.Gen + ( genCoinLargePositive, shrinkCoinLargePositive ) import Cardano.Wallet.Primitive.Types.Hash ( Hash (..) ) import Control.Arrow @@ -137,6 +141,10 @@ instance Arbitrary (Quantity "lovelace" Word64) where shrink (Quantity q) = [ Quantity q' | q' <- shrink q ] arbitrary = Quantity <$> arbitrary +instance Arbitrary Coin where + shrink = shrinkCoinLargePositive + arbitrary = genCoinLargePositive + arbitraryEpochLength :: Word32 arbitraryEpochLength = 100 @@ -186,8 +194,8 @@ instance Arbitrary PoolRegistrationCertificate where <$> arbitrary <*> genOwners <*> genPercentage - <*> fmap Quantity arbitrary - <*> fmap Quantity arbitrary + <*> arbitrary + <*> arbitrary <*> oneof [pure Nothing, Just <$> genMetadata] where genMetadata = (,) diff --git a/lib/core/test/unit/Cardano/Wallet/Api/Malformed.hs b/lib/core/test/unit/Cardano/Wallet/Api/Malformed.hs index 0402306985a..c13ec1932a9 100644 --- a/lib/core/test/unit/Cardano/Wallet/Api/Malformed.hs +++ b/lib/core/test/unit/Cardano/Wallet/Api/Malformed.hs @@ -79,6 +79,8 @@ import Cardano.Wallet.Primitive.Types ( WalletId, walletNameMaxLength ) import Cardano.Wallet.Primitive.Types.Address ( Address (..) ) +import Cardano.Wallet.Primitive.Types.TokenPolicy + ( TokenName, TokenPolicyId ) import Control.Arrow ( first ) import Data.Aeson.QQ @@ -230,6 +232,39 @@ instance Malformed (PathParam (ApiT DerivationIndex)) where \Indexes without suffixes are called 'Soft' \ \Indexes with suffixes are called 'Hardened'." +instance Wellformed (PathParam (ApiT TokenPolicyId)) where + wellformed = [PathParam $ T.replicate 56 "0"] + +instance Malformed (PathParam (ApiT TokenPolicyId)) where + malformed = first PathParam <$> + [ ( "faff", msgWrongLength ) + , ( T.replicate 57 "0", msgWrongLength ) + , ( T.replicate 56 "x", msgMalformed ) + , ( "f", msgMalformed ) + ] + where + msgMalformed = "Invalid tokenPolicy hash: expecting a hex-encoded value that is 28 bytes in length." + msgWrongLength = msgMalformed + +instance Wellformed (PathParam (ApiT TokenName)) where + wellformed = PathParam <$> + [ T.replicate 64 "0" + , "" + , "FF" + , "594f4c4f" + , "e29883" + ] + +instance Malformed (PathParam (ApiT TokenName)) where + malformed = first PathParam <$> + [ ( T.replicate 65 "0", msgWrongLength ) + , ( "f", msgWrongLength ) + , ( "patate", msgMalformed ) + ] + where + msgWrongLength = "TokenName is not hex-encoded: base16: input: invalid length" + msgMalformed = "TokenName is not hex-encoded: base16: input: invalid encoding at offset: 0" + -- -- Class instances (BodyParam) -- @@ -249,7 +284,7 @@ instance Malformed (BodyParam ApiWalletSignData) where { "metadata": { "0": { "string": "metadata" } } , "passphrase": 100 }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Number" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Number" ) , ( Aeson.encode [aesonQQ| { "metadata": { "0": { "string": "metadata" } } @@ -419,7 +454,7 @@ instance Malformed (BodyParam SomeByronWalletPostData) where , "mnemonic_sentence": #{mnemonics12} , "passphrase" : 100 }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Number" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Number" ) , ( [aesonQQ| { "style": "icarus" @@ -427,7 +462,7 @@ instance Malformed (BodyParam SomeByronWalletPostData) where , "mnemonic_sentence": #{mnemonics15} , "passphrase" :[""] }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Array" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Array" ) , ( [aesonQQ| { "style": "trezor" @@ -625,14 +660,14 @@ instance Malformed (BodyParam WalletOrAccountPostData) where , "mnemonic_sentence": #{mnemonics15} , "passphrase" :#{wPassphrase} }|] - , "Error in $.name: parsing Text failed, expected String, but encountered Array" + , "Error in $.name: parsing WalletName failed, expected String, but encountered Array" ) , ( [aesonQQ| { "name": 123 , "mnemonic_sentence": #{mnemonics15} , "passphrase" :#{wPassphrase} }|] - , "Error in $.name: parsing Text failed, expected String, but encountered Number" + , "Error in $.name: parsing WalletName failed, expected String, but encountered Number" ) , ( [aesonQQ| { "mnemonic_sentence": #{mnemonics15} @@ -810,13 +845,13 @@ instance Malformed (BodyParam WalletPutPassphraseData) where { "old_passphrase": #{wPassphrase} , "new_passphrase" : 100 }|] - , "Error in $['new_passphrase']: parsing Text failed, expected String, but encountered Number" + , "Error in $['new_passphrase']: parsing Passphrase failed, expected String, but encountered Number" ) , ( [aesonQQ| { "old_passphrase": [] , "new_passphrase" : #{wPassphrase} }|] - , "Error in $['old_passphrase']: parsing Text failed, expected String, but encountered Array" + , "Error in $['old_passphrase']: parsing Passphrase failed, expected String, but encountered Array" ) , ( [aesonQQ| { "old_passphrase": "" @@ -868,13 +903,13 @@ instance Malformed (BodyParam ByronWalletPutPassphraseData) where { "old_passphrase": #{wPassphrase} , "new_passphrase" : 100 }|] - , "Error in $['new_passphrase']: parsing Text failed, expected String, but encountered Number" + , "Error in $['new_passphrase']: parsing Passphrase failed, expected String, but encountered Number" ) , ( [aesonQQ| { "old_passphrase": [] , "new_passphrase" : #{wPassphrase} }|] - , "Error in $['old_passphrase']: parsing Text failed, expected String, but encountered Array" + , "Error in $['old_passphrase']: parsing Passphrase failed, expected String, but encountered Array" ) , ( [aesonQQ| { "old_passphrase": #{wPassphrase} @@ -919,13 +954,13 @@ instance Malformed (BodyParam WalletPutData) where , "Error in $.name: name is too long: expected at most 255 characters" ) , ( [aesonQQ| { "name": 123 }|] - , "Error in $.name: parsing Text failed, expected String, but encountered Number" + , "Error in $.name: parsing WalletName failed, expected String, but encountered Number" ) , ( [aesonQQ| { "name": [] }|] - , "Error in $.name: parsing Text failed, expected String, but encountered Array" + , "Error in $.name: parsing WalletName failed, expected String, but encountered Array" ) , ( [aesonQQ| { "name": 1.5 }|] - , "Error in $.name: parsing Text failed, expected String, but encountered Number" + , "Error in $.name: parsing WalletName failed, expected String, but encountered Number" ) ] @@ -943,13 +978,13 @@ instance Malformed (BodyParam ApiWalletPassphrase) where , "Error in $.passphrase: passphrase is too long: expected at most 255 characters" ) , ( [aesonQQ| { "passphrase": 123 }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Number" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Number" ) , ( [aesonQQ| { "passphrase": [] }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Array" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Array" ) , ( [aesonQQ| { "passphrase": 1.5 }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Number" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Number" ) ] @@ -1377,7 +1412,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].address: parsing Text failed, expected String, but encountered Number" + , "Error in $.payments[0].address: parsing AddressAmount failed, parsing Text failed, expected String, but encountered Number" ) , ( [aesonQQ| { "payments": [ @@ -1389,7 +1424,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0]: parsing Cardano.Wallet.Api.Types.AddressAmount(AddressAmount) failed, key 'address' not found" + , "Error in $.payments[0]: parsing AddressAmount failed, key 'address' not found" ) -- amount , ( [aesonQQ| @@ -1403,7 +1438,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].amount: failed to parse quantified value. Expected value in 'lovelace' (e.g. { 'unit': 'lovelace', 'quantity': ... }) but got something else." + , "Error in $.payments[0].amount: parsing AddressAmount failed, failed to parse quantified value. Expected value in 'lovelace' (e.g. { 'unit': 'lovelace', 'quantity': ... }) but got something else." ) , ( [aesonQQ| { "payments": [ @@ -1415,7 +1450,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].amount: key 'unit' not found" + , "Error in $.payments[0].amount: parsing AddressAmount failed, key 'unit' not found" ) , ( [aesonQQ| { "payments": [ @@ -1424,7 +1459,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0]: parsing Cardano.Wallet.Api.Types.AddressAmount(AddressAmount) failed, key 'amount' not found" + , "Error in $.payments[0]: parsing AddressAmount failed, key 'amount' not found" ) , ( [aesonQQ| { "payments": [ @@ -1436,7 +1471,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].amount: key 'quantity' not found" + , "Error in $.payments[0].amount: parsing AddressAmount failed, key 'quantity' not found" ) , ( [aesonQQ| { "payments": [ @@ -1446,7 +1481,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].amount: parsing Quantity failed, expected Object, but encountered Number" + , "Error in $.payments[0].amount: parsing AddressAmount failed, parsing Quantity failed, expected Object, but encountered Number" ) , ( [aesonQQ| { "payments": [ @@ -1459,7 +1494,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].amount.quantity: parsing Natural failed, expected Number, but encountered String" + , "Error in $.payments[0].amount.quantity: parsing AddressAmount failed, parsing Natural failed, expected Number, but encountered String" ) , ( [aesonQQ| { "payments": [ @@ -1472,7 +1507,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].amount.quantity: parsing Natural failed, unexpected negative number -1" + , "Error in $.payments[0].amount.quantity: parsing AddressAmount failed, parsing Natural failed, unexpected negative number -1" ) , ( [aesonQQ| { "payments": [ @@ -1485,7 +1520,7 @@ paymentCases = } ] }|] - , "Error in $.payments[0].amount.quantity: parsing Natural failed, unexpected floating number 4200.12" + , "Error in $.payments[0].amount.quantity: parsing AddressAmount failed, parsing Natural failed, unexpected floating number 4200.12" ) , ( [aesonQQ| { "payments": [ ] @@ -1523,13 +1558,13 @@ migrateDataCases = { "passphrase": 1 , "addresses": [ #{addrPlaceholder} ] }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Number" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Number" ) , ( [aesonQQ| { "passphrase": [ ] , "addresses": [ #{addrPlaceholder} ] }|] - , "Error in $.passphrase: parsing Text failed, expected String, but encountered Array" + , "Error in $.passphrase: parsing Passphrase failed, expected String, but encountered Array" ) ] diff --git a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs index cc117da2994..d07f826c4a5 100644 --- a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -50,6 +50,7 @@ import Cardano.Wallet.Api.Types , ApiAddress (..) , ApiAddressData (..) , ApiAddressInspect (..) + , ApiAsset (..) , ApiBlockInfo (..) , ApiBlockReference (..) , ApiByronWallet (..) @@ -90,6 +91,8 @@ import Cardano.Wallet.Api.Types , ApiUtxoStatistics (..) , ApiVerificationKey (..) , ApiWallet (..) + , ApiWalletAssetsBalance (..) + , ApiWalletBalance (..) , ApiWalletDelegation (..) , ApiWalletDelegationNext (..) , ApiWalletDelegationStatus (..) @@ -116,11 +119,11 @@ import Cardano.Wallet.Api.Types , PostTransactionFeeData (..) , SettingsPutData (..) , SomeByronWalletPostData (..) - , WalletBalance (..) , WalletOrAccountPostData (..) , WalletPostData (..) , WalletPutData (..) , WalletPutPassphraseData (..) + , toApiAsset ) import Cardano.Wallet.Gen ( genMnemonic @@ -182,6 +185,14 @@ import Cardano.Wallet.Primitive.Types.Hash ( Hash (..) ) import Cardano.Wallet.Primitive.Types.RewardAccount ( RewardAccount (..) ) +import Cardano.Wallet.Primitive.Types.TokenBundle + ( TokenBundle ) +import Cardano.Wallet.Primitive.Types.TokenBundle.Gen + ( genTokenBundleSmallRange, shrinkTokenBundleSmallRange ) +import Cardano.Wallet.Primitive.Types.TokenMap + ( TokenMap ) +import Cardano.Wallet.Primitive.Types.TokenMap.Gen + ( genAssetIdSmallRange, genTokenMapSmallRange, shrinkTokenMapSmallRange ) import Cardano.Wallet.Primitive.Types.Tx ( Direction (..) , TxIn (..) @@ -283,6 +294,7 @@ import Test.QuickCheck , InfiniteList (..) , Positive (..) , applyArbitrary2 + , applyArbitrary3 , arbitraryBoundedEnum , arbitraryPrintableChar , arbitrarySizedBoundedIntegral @@ -318,7 +330,6 @@ import Web.HttpApiData ( FromHttpApiData (..) ) import qualified Cardano.Wallet.Api.Types as Api -import qualified Cardano.Wallet.Primitive.Types.TokenBundle as TokenBundle import qualified Data.Aeson as Aeson import qualified Data.Aeson.Types as Aeson import qualified Data.ByteArray as BA @@ -398,7 +409,7 @@ spec = parallel $ do jsonRoundtripAndGolden $ Proxy @(ApiT Direction) jsonRoundtripAndGolden $ Proxy @(ApiT TxMetadata) jsonRoundtripAndGolden $ Proxy @(ApiT TxStatus) - jsonRoundtripAndGolden $ Proxy @(ApiT WalletBalance) + jsonRoundtripAndGolden $ Proxy @(ApiWalletBalance) jsonRoundtripAndGolden $ Proxy @(ApiT WalletId) jsonRoundtripAndGolden $ Proxy @(ApiT WalletName) jsonRoundtripAndGolden $ Proxy @ApiWalletPassphraseInfo @@ -572,7 +583,8 @@ spec = parallel $ do |] `shouldBe` (Left @String @(ApiT WalletId) msg) it "AddressAmount (too small)" $ do - let msg = "Error in $.amount.quantity: parsing Natural failed, \ + let msg = "Error in $.amount.quantity: \ + \parsing AddressAmount failed, parsing Natural failed, \ \unexpected negative number -14" Aeson.parseEither parseJSON [aesonQQ| { "address": "" @@ -581,7 +593,8 @@ spec = parallel $ do |] `shouldBe` (Left @String @(AddressAmount (ApiT Address, Proxy ('Testnet 0))) msg) it "AddressAmount (too big)" $ do - let msg = "Error in $: invalid coin value: value has to be lower \ + let msg = "Error in $: parsing AddressAmount failed, \ + \invalid coin value: value has to be lower \ \than or equal to " <> show (unCoin maxBound) <> " lovelace." Aeson.parseEither parseJSON [aesonQQ| @@ -723,6 +736,7 @@ spec = parallel $ do { id = id (x :: ApiWallet) , addressPoolGap = addressPoolGap (x :: ApiWallet) , balance = balance (x :: ApiWallet) + , assets = assets (x :: ApiWallet) , delegation = delegation (x :: ApiWallet) , name = name (x :: ApiWallet) , passphrase = passphrase (x :: ApiWallet) @@ -874,6 +888,7 @@ spec = parallel $ do , amount = amount (x :: ApiTransaction ('Testnet 0)) , fee = fee (x :: ApiTransaction ('Testnet 0)) , deposit = deposit (x :: ApiTransaction ('Testnet 0)) + , assets = assets (x :: ApiTransaction ('Testnet 0)) , insertedAt = insertedAt (x :: ApiTransaction ('Testnet 0)) , pendingSince = pendingSince (x :: ApiTransaction ('Testnet 0)) , expiresAt = expiresAt (x :: ApiTransaction ('Testnet 0)) @@ -883,6 +898,7 @@ spec = parallel $ do , outputs = outputs (x :: ApiTransaction ('Testnet 0)) , status = status (x :: ApiTransaction ('Testnet 0)) , withdrawals = withdrawals (x :: ApiTransaction ('Testnet 0)) + , mint = mint (x :: ApiTransaction ('Testnet 0)) , metadata = metadata (x :: ApiTransaction ('Testnet 0)) } in @@ -899,6 +915,7 @@ spec = parallel $ do x' = AddressAmount { address = address (x :: AddressAmount (ApiT Address, Proxy ('Testnet 0))) , amount = amount (x :: AddressAmount (ApiT Address, Proxy ('Testnet 0))) + , assets = assets (x :: AddressAmount (ApiT Address, Proxy ('Testnet 0))) } in x' === x .&&. show x' === show x @@ -1284,7 +1301,11 @@ instance Arbitrary ByronWalletPutPassphraseData where arbitrary = genericArbitrary shrink = genericShrink -instance Arbitrary WalletBalance where +instance Arbitrary ApiWalletBalance where + arbitrary = genericArbitrary + shrink = genericShrink + +instance Arbitrary ApiWalletAssetsBalance where arbitrary = genericArbitrary shrink = genericShrink @@ -1576,8 +1597,11 @@ instance Arbitrary Word31 where arbitrary = arbitrarySizedBoundedIntegral shrink = shrinkIntegral +instance Arbitrary ApiAsset where + arbitrary = toApiAsset Nothing <$> genAssetIdSmallRange + instance Arbitrary a => Arbitrary (AddressAmount a) where - arbitrary = applyArbitrary2 AddressAmount + arbitrary = applyArbitrary3 AddressAmount shrink _ = [] instance Arbitrary (PostTransactionData t) where @@ -1643,6 +1667,7 @@ instance Arbitrary (ApiTransaction t) where <*> arbitrary <*> arbitrary <*> arbitrary + <*> arbitrary <*> pure txInsertedAt <*> pure txPendingSince <*> pure txExpiresAt @@ -1651,6 +1676,7 @@ instance Arbitrary (ApiTransaction t) where <*> genInputs <*> genOutputs <*> genWithdrawals + <*> arbitrary <*> pure txStatus <*> arbitrary where @@ -1682,11 +1708,18 @@ instance Arbitrary UTxO where <*> vector n return $ UTxO $ Map.fromList utxo +instance Arbitrary TokenBundle where + shrink = shrinkTokenBundleSmallRange + arbitrary = genTokenBundleSmallRange + +instance Arbitrary TokenMap where + shrink = shrinkTokenMapSmallRange + arbitrary = genTokenMapSmallRange + instance Arbitrary TxOut where - -- No Shrinking - arbitrary = TxOut - <$> arbitrary - <*> fmap TokenBundle.fromCoin genCoinLargePositive + -- Shrink token bundle but not address + shrink (TxOut a t) = TxOut a <$> shrink t + arbitrary = TxOut <$> arbitrary <*> arbitrary instance Arbitrary TxIn where -- No Shrinking @@ -1861,6 +1894,9 @@ instance ToSchema ApiStakePoolMetrics where instance ToSchema ApiFee where declareNamedSchema _ = declareSchemaForDefinition "ApiFee" +instance ToSchema ApiAsset where + declareNamedSchema _ = declareSchemaForDefinition "ApiAsset" + instance ToSchema ApiTxId where declareNamedSchema _ = declareSchemaForDefinition "ApiTxId" diff --git a/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs b/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs index a13250d3074..94ca249c054 100644 --- a/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs +++ b/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs @@ -407,7 +407,7 @@ instance Arbitrary TxMeta where <$> elements [Incoming, Outgoing] <*> arbitrary <*> fmap Quantity arbitrary - <*> fmap (Quantity . fromIntegral . unCoin) arbitrary + <*> arbitrary <*> (if st == Pending then Just <$> arbitrary else pure Nothing) instance Arbitrary TxStatus where diff --git a/lib/core/test/unit/Cardano/Wallet/DB/Properties.hs b/lib/core/test/unit/Cardano/Wallet/DB/Properties.hs index 3ed7e66dfb8..ab14ee986c5 100644 --- a/lib/core/test/unit/Cardano/Wallet/DB/Properties.hs +++ b/lib/core/test/unit/Cardano/Wallet/DB/Properties.hs @@ -864,7 +864,7 @@ prop_rollbackTxHistory db@DBLayer{..} (InitialCheckpoint cp0) (GenTxHistory txs0 , pretty (meta ^. #slotNo) , pretty (meta ^. #status) , pretty (meta ^. #direction) - , show $ getQuantity ((meta ^. #amount)) + , pretty (meta ^. #amount) ]) isBefore :: SlotNo -> TxMeta -> Bool diff --git a/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs b/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs index f8b5670df5c..2aec4b1c7e6 100644 --- a/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs @@ -1238,7 +1238,7 @@ testTxs = mempty Nothing , TxMeta - InLedger Incoming (SlotNo 140) (Quantity 0) (Quantity 1337144) Nothing + InLedger Incoming (SlotNo 140) (Quantity 0) (Coin 1337144) Nothing ) ] @@ -1252,18 +1252,19 @@ gp = dummyGenesisParameters Helpers for golden rollback tests -------------------------------------------------------------------------------} -getAvailableBalance :: DBLayer IO s k -> IO Word +getAvailableBalance :: DBLayer IO s k -> IO Natural getAvailableBalance DBLayer{..} = do cp <- fmap (fromMaybe (error "nothing")) <$> atomically $ readCheckpoint testPk pend <- atomically $ fmap toTxHistory <$> readTxHistory testPk Nothing Descending wholeRange (Just Pending) - return $ fromIntegral $ availableBalance (Set.fromList $ map fst pend) cp + return $ fromIntegral $ unCoin $ TokenBundle.getCoin $ + availableBalance (Set.fromList $ map fst pend) cp getTxsInLedger :: DBLayer IO s k -> IO ([(Direction, Natural)]) getTxsInLedger DBLayer {..} = do pend <- atomically $ fmap toTxHistory <$> readTxHistory testPk Nothing Descending wholeRange (Just InLedger) - return $ map (\(_, m) -> (direction m, getQuantity $ amount m)) pend + return $ map (\(_, m) -> (direction m, fromIntegral $ unCoin $ amount m)) pend {------------------------------------------------------------------------------- Test data - Sequential AD diff --git a/lib/core/test/unit/Cardano/Wallet/DB/StateMachine.hs b/lib/core/test/unit/Cardano/Wallet/DB/StateMachine.hs index 2f23e73d809..1bfda49a0c0 100644 --- a/lib/core/test/unit/Cardano/Wallet/DB/StateMachine.hs +++ b/lib/core/test/unit/Cardano/Wallet/DB/StateMachine.hs @@ -186,12 +186,8 @@ import Data.Set ( Set ) import Data.TreeDiff ( ToExpr (..), defaultExprViaShow, genericToExpr ) -import Data.Word - ( Word64 ) import GHC.Generics ( Generic ) -import Numeric.Natural - ( Natural ) import System.Random ( getStdRandom, randomR ) import Test.Hspec @@ -325,7 +321,7 @@ data Cmd s wid | ReadWalletMeta wid | PutTxHistory wid TxHistory | ReadTxHistory wid - (Maybe (Quantity "lovelace" Natural)) + (Maybe Coin) SortOrder (Range SlotNo) (Maybe TxStatus) @@ -339,7 +335,7 @@ data Cmd s wid | UpdatePendingTxForExpiry wid SlotNo | PutDelegationCertificate wid DelegationCertificate SlotNo | IsStakeKeyRegistered wid - | PutDelegationRewardBalance wid (Quantity "lovelace" Word64) + | PutDelegationRewardBalance wid Coin | ReadDelegationRewardBalance wid deriving (Show, Functor, Foldable, Traversable) @@ -355,7 +351,7 @@ data Success s wid | GenesisParams (Maybe GenesisParameters) | BlockHeaders [BlockHeader] | Point SlotNo - | DelegationRewardBalance (Quantity "lovelace" Word64) + | DelegationRewardBalance Coin | StakeKeyStatus Bool deriving (Show, Eq, Functor, Foldable, Traversable) @@ -693,10 +689,10 @@ generatorWithWid wids = genRange :: Gen (Range SlotNo) genRange = applyArbitrary2 Range - genMinWithdrawal :: Gen (Maybe (Quantity "lovelace" Natural)) + genMinWithdrawal :: Gen (Maybe Coin) genMinWithdrawal = frequency [ (10, pure Nothing) - , (1, (Just . Quantity . fromIntegral . unCoin) <$> arbitrary) + , (1, Just <$> arbitrary) ] isUnordered :: Ord x => [x] -> Bool diff --git a/lib/core/test/unit/Cardano/Wallet/Primitive/CoinSelection/MigrationSpec.hs b/lib/core/test/unit/Cardano/Wallet/Primitive/CoinSelection/MigrationSpec.hs index ec8de7cb3f6..b6d64c9ba5c 100644 --- a/lib/core/test/unit/Cardano/Wallet/Primitive/CoinSelection/MigrationSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Primitive/CoinSelection/MigrationSpec.hs @@ -33,9 +33,7 @@ import Data.ByteString import Data.Function ( (&) ) import Data.Word - ( Word8 ) -import Numeric.Natural - ( Natural ) + ( Word64, Word8 ) import Test.Hspec ( Spec, SpecWith, describe, it, parallel, shouldSatisfy ) import Test.QuickCheck @@ -77,17 +75,17 @@ spec = parallel $ do feeOpts <- pick (genFeeOptions dust) let selections = depleteUTxO feeOpts batchSize utxo monitor $ label $ accuracy dust - (balance utxo) - (fromIntegral $ sum $ inputBalance <$> selections) + (TokenBundle.getCoin $ balance utxo) + (sum $ inputBalance <$> selections) where title :: String title = "dust=" <> show (round (100 * r) :: Int) <> "%" - accuracy :: Coin -> Natural -> Natural -> String - accuracy (Coin dust) sup real + accuracy :: Coin -> Coin -> Word64 -> String + accuracy (Coin dust) (Coin sup) real | a >= 1.0 = "PERFECT (== 100%)" - | a > 0.99 || (sup - real) < fromIntegral dust = + | a > 0.99 || (sup - real) < dust = "OKAY (> 99%)" | otherwise = "MEDIOCRE (<= 99%)" @@ -177,8 +175,8 @@ prop_inputsGreaterThanOutputs prop_inputsGreaterThanOutputs feeOpts batchSize utxo = do let selections = depleteUTxO feeOpts batchSize utxo let totalChange = sum (changeBalance <$> selections) - let balanceUTxO = balance utxo - property (balanceUTxO >= fromIntegral totalChange) + let Coin balanceUTxO = TokenBundle.getCoin $ balance utxo + property (balanceUTxO >= totalChange) & counterexample ("Total change balance: " <> show totalChange) & counterexample ("Total UTxO balance: " <> show balanceUTxO) & counterexample ("Selections: " <> show selections) diff --git a/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs b/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs index c6c30da482b..6ac5ed08108 100644 --- a/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Primitive/ModelSpec.hs @@ -204,7 +204,7 @@ prop_applyBlockBasic s = in (ShowFmt utxo === ShowFmt utxo') .&&. (availableBalance mempty wallet === balance utxo') .&&. - (totalBalance mempty (Quantity 0) wallet === balance utxo') + (totalBalance mempty (Coin 0) wallet === balance utxo') -- Each transaction must have at least one output belonging to us prop_applyBlockTxHistoryIncoming :: WalletState -> Property @@ -275,11 +275,9 @@ prop_countRewardsOnce (WithPending wallet pending rewards) pendingBalance = sum $ (unCoin . txOutCoin) <$> concatMap outputs (Set.elems pending) totalWithPending = - totalBalance pending rewardsQ wallet + TokenBundle.getCoin $ totalBalance pending rewards wallet totalWithoutPending = - totalBalance Set.empty rewardsQ wallet - rewardsQ = - Quantity $ fromIntegral $ unCoin rewards + TokenBundle.getCoin $ totalBalance Set.empty rewards wallet hasPending = not $ Set.null pending diff --git a/lib/core/test/unit/Cardano/Wallet/Primitive/Types/TokenMapSpec.hs b/lib/core/test/unit/Cardano/Wallet/Primitive/Types/TokenMapSpec.hs index 3fe5f493b17..cd21d8ecfbb 100644 --- a/lib/core/test/unit/Cardano/Wallet/Primitive/Types/TokenMapSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Primitive/Types/TokenMapSpec.hs @@ -23,7 +23,7 @@ import Cardano.Wallet.Primitive.Types.TokenMap.Gen , shrinkTokenMapSmallRange ) import Cardano.Wallet.Primitive.Types.TokenPolicy - ( TokenName, TokenPolicyId ) + ( TokenName, TokenPolicyId, mkTokenName ) import Cardano.Wallet.Primitive.Types.TokenPolicy.Gen ( genTokenNameSmallRange , genTokenPolicyIdSmallRange @@ -40,6 +40,8 @@ import Data.Aeson.QQ ( aesonQQ ) import Data.Bifunctor ( bimap, first, second ) +import Data.ByteString + ( ByteString ) import Data.Either ( fromRight ) import Data.Function @@ -450,8 +452,8 @@ testZeroValuedTokenQuantityFlat = token = dummyTokenName "DUMMY-TOKEN" json = [aesonQQ| - [ { "policy": #{policy} - , "token": #{token} + [ { "policy_id": #{policy} + , "asset_name": #{token} , "quantity": 0 } ] @@ -473,8 +475,8 @@ testZeroValuedTokenQuantityNested = token = dummyTokenName "DUMMY-TOKEN" json = [aesonQQ| - [ { "policy": #{policy} - , "tokens": [{"token": #{token}, "quantity": 0}] + [ { "policy_id": #{policy} + , "tokens": [{"asset_name": #{token}, "quantity": 0}] } ] |] @@ -492,7 +494,7 @@ testEmptyTokenList = Left message where policy = dummyTokenPolicyId 'A' - json = [aesonQQ|[{"policy": #{policy}, "tokens": []}]|] + json = [aesonQQ|[{"policy_id": #{policy}, "tokens": []}]|] message = unwords [ failurePreamble , "Encountered empty token list for policy" @@ -531,7 +533,7 @@ testMap = testMapData & fmap (first (uncurry AssetId)) & TokenMap.fromFlatList -testMapData :: [((Char, Text), Natural)] +testMapData :: [((Char, ByteString), Natural)] testMapData = [ (('A', "APPLE" ), 1) , (('A', "AVOCADO" ), 2) @@ -542,16 +544,16 @@ testMapData = testMapPrettyFlat :: Text testMapPrettyFlat = [s| - policy: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - token: APPLE + token: 4150504c45 quantity: 1 - policy: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - token: AVOCADO + token: 41564f4341444f quantity: 2 - policy: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - token: BANANA + token: 42414e414e41 quantity: 3 - policy: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - token: BLUEBERRY + token: 424c55454245525259 quantity: 4 |] @@ -559,15 +561,15 @@ testMapPrettyNested :: Text testMapPrettyNested = [s| - policy: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa tokens: - - token: APPLE + - token: 4150504c45 quantity: 1 - - token: AVOCADO + - token: 41564f4341444f quantity: 2 - policy: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb tokens: - - token: BANANA + - token: 42414e414e41 quantity: 3 - - token: BLUEBERRY + - token: 424c55454245525259 quantity: 4 |] @@ -575,11 +577,11 @@ testMapPrettyNested = [s| -- Utilities -------------------------------------------------------------------------------- -dummyTokenName :: Text -> TokenName -dummyTokenName t = fromRight reportError $ fromText t +dummyTokenName :: ByteString -> TokenName +dummyTokenName t = fromRight reportError $ mkTokenName t where reportError = error $ - "Unable to construct dummy token name from text: " <> show t + "Unable to construct dummy token name from bytes: " <> show t -- The input must be a character in the range [0-9] or [A-Z]. -- diff --git a/lib/core/test/unit/Cardano/Wallet/Primitive/TypesSpec.hs b/lib/core/test/unit/Cardano/Wallet/Primitive/TypesSpec.hs index fc798b34f81..fc8f047f5a2 100644 --- a/lib/core/test/unit/Cardano/Wallet/Primitive/TypesSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Primitive/TypesSpec.hs @@ -263,7 +263,7 @@ spec = do , direction = Outgoing , slotNo = SlotNo 1442 , blockHeight = Quantity 37 - , amount = Quantity 1337 + , amount = Coin 1337 , expiry = Just (SlotNo 2442) } "-0.001337 pending since 1442#37 (expires slot 2442)" @@ -274,7 +274,7 @@ spec = do , direction = Incoming , slotNo = SlotNo 140 , blockHeight = Quantity 1 - , amount = Quantity 13371442 + , amount = Coin 13371442 , expiry = Nothing } "+13.371442 in ledger since 140#1" === pretty @_ @Text txMeta @@ -980,7 +980,7 @@ prop_2_6_1 (u, v) = -- a v' that has no overlap with u. v' = v `excluding` dom u cond = not (u `isSubsetOf` mempty || v' `isSubsetOf` mempty) - prop = balance (u <> v') === balance u + balance v' + prop = balance (u <> v') === balance u `TokenBundle.add` balance v' prop_2_6_2 :: (Set TxIn, UTxO) -> Property prop_2_6_2 (ins, u) = @@ -990,7 +990,7 @@ prop_2_6_2 (ins, u) = prop = balance (u `excluding` ins) === - balance u - balance (u `restrictedBy` ins) + balance u `TokenBundle.unsafeSubtract` balance (u `restrictedBy` ins) {------------------------------------------------------------------------------- UTxO statistics Properties @@ -1002,7 +1002,7 @@ propUtxoTotalIsBalance -> ShowFmt UTxO -> Property propUtxoTotalIsBalance bType (ShowFmt utxo) = - fromIntegral totalStake == balance utxo + Coin totalStake == TokenBundle.getCoin (balance utxo) & cover 75 (utxo /= mempty) "UTxO /= empty" where UTxOStatistics _ totalStake _ = computeUtxoStatistics bType utxo @@ -1015,7 +1015,7 @@ propUtxoSumDistribution -> ShowFmt UTxO -> Property propUtxoSumDistribution bType (ShowFmt utxo) = - sum (upperVal <$> bars) >= fromIntegral (balance utxo) + sum (upperVal <$> bars) >= unCoin (TokenBundle.getCoin (balance utxo)) & cover 75 (utxo /= mempty) "UTxO /= empty" & counterexample ("Histogram: " <> pretty bars) where diff --git a/lib/core/test/unit/Cardano/WalletSpec.hs b/lib/core/test/unit/Cardano/WalletSpec.hs index 5c7daac968a..bb4e3bbb13f 100644 --- a/lib/core/test/unit/Cardano/WalletSpec.hs +++ b/lib/core/test/unit/Cardano/WalletSpec.hs @@ -286,26 +286,26 @@ spec = parallel $ do `shouldBe` Left (W.ErrNoSuchPool pidUnknown) it "Cannot quit when active: not_delegating, next = []" $ do let dlg = WalletDelegation {active = NotDelegating, next = []} - W.guardQuit dlg (Quantity 0) + W.guardQuit dlg (Coin 0) `shouldBe` Left (W.ErrNotDelegatingOrAboutTo) it "Cannot quit when active: A, next = [not_delegating]" $ do let next1 = next (EpochNo 1) NotDelegating let dlg = WalletDelegation {active = Delegating pidA, next = [next1]} - W.guardQuit dlg (Quantity 0) + W.guardQuit dlg (Coin 0) `shouldBe` Left (W.ErrNotDelegatingOrAboutTo) it "Cannot quit when active: A, next = [B, not_delegating]" $ do let next1 = next (EpochNo 1) (Delegating pidB) let next2 = next (EpochNo 2) NotDelegating let dlg = WalletDelegation {active = Delegating pidA, next = [next1, next2]} - W.guardQuit dlg (Quantity 0) + W.guardQuit dlg (Coin 0) `shouldBe` Left (W.ErrNotDelegatingOrAboutTo) it "Can quit when active: not_delegating, next = [A]" $ do let next1 = next (EpochNo 1) (Delegating pidA) let dlg = WalletDelegation {active = NotDelegating, next = [next1]} - W.guardQuit dlg (Quantity 0) `shouldBe` Right () + W.guardQuit dlg (Coin 0) `shouldBe` Right () where pidA = PoolId "A" pidB = PoolId "B" @@ -339,7 +339,7 @@ prop_guardJoinQuit knownPoolsList dlg pid mRetirementInfo = checkCoverage label "ErrNoSuchPool" $ property True Left W.ErrAlreadyDelegating{} -> label "ErrAlreadyDelegating" - (W.guardQuit dlg (Quantity 0) === Right ()) + (W.guardQuit dlg (Coin 0) === Right ()) where knownPools = Set.fromList knownPoolsList retirementNotPlanned = @@ -361,7 +361,7 @@ prop_guardQuitJoin prop_guardQuitJoin (NonEmpty knownPoolsList) dlg rewards = let knownPools = Set.fromList knownPoolsList in let noRetirementPlanned = Nothing in - case W.guardQuit dlg (Quantity rewards) of + case W.guardQuit dlg (Coin rewards) of Right () -> label "I can quit" $ property True Left W.ErrNotDelegatingOrAboutTo -> @@ -924,7 +924,7 @@ instance Arbitrary TxMeta where <*> elements [Incoming, Outgoing] <*> genSlotNo <*> fmap Quantity arbitrary - <*> fmap (Quantity . fromIntegral . unCoin) arbitrary + <*> arbitrary <*> liftArbitrary genSlotNo instance Arbitrary TxMetadata where diff --git a/lib/shelley/bench/Latency.hs b/lib/shelley/bench/Latency.hs index 250169590d8..c47cae57387 100644 --- a/lib/shelley/bench/Latency.hs +++ b/lib/shelley/bench/Latency.hs @@ -236,7 +236,7 @@ walletApiBench capture ctx = do verify rWal1 [ expectSuccess , expectField - (#balance . #getApiT . #available . #getQuantity) + (#balance . #available . #getQuantity) (`shouldBe` (minUTxOValue * (fromIntegral utxoNumber))) ] @@ -255,7 +255,7 @@ walletApiBench capture ctx = do verify rWal1 [ expectSuccess , expectField - (#balance . #getApiT . #available . #getQuantity) + (#balance . #available . #getQuantity) (`shouldBe` amtExp) ] rDel <- request @ApiWallet ctx (Link.deleteWallet @'Shelley wSrc) Default Empty diff --git a/lib/shelley/bench/Restore.hs b/lib/shelley/bench/Restore.hs index bcb411b6b64..0d477dbea5d 100644 --- a/lib/shelley/bench/Restore.hs +++ b/lib/shelley/bench/Restore.hs @@ -445,7 +445,7 @@ benchmarksRnd _ w wid wname benchname restoreTime = do (_, estimateFeesTime) <- bench "estimate tx fee" $ do let out = TxOut (dummyAddress @n) (TokenBundle.fromCoin $ Coin 1) runExceptT $ withExceptT show $ W.estimateFeeForPayment @_ @s @k - w wid (out :| []) (Quantity 0) Nothing + w wid (out :| []) (Coin 0) Nothing oneAddress <- genAddresses 1 cp (_, importOneAddressTime) <- bench "import one addresses" $ do @@ -532,7 +532,7 @@ benchmarksSeq _ w wid _wname benchname restoreTime = do (_, estimateFeesTime) <- bench "estimate tx fee" $ do let out = TxOut (dummyAddress @n) (TokenBundle.fromCoin $ Coin 1) runExceptT $ withExceptT show $ W.estimateFeeForPayment @_ @s @k - w wid (out :| []) (Quantity 0) Nothing + w wid (out :| []) (Coin 0) Nothing let walletOverview = WalletOverview{utxo,addresses,transactions} diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs index da40e53029a..8c5750c9e95 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs @@ -36,6 +36,7 @@ import Cardano.Wallet.Api ( Addresses , Api , ApiLayer (..) + , Assets , ByronAddresses , ByronCoinSelections , ByronMigrations @@ -58,6 +59,8 @@ import Cardano.Wallet.Api.Server , deleteTransaction , deleteWallet , derivePublicKey + , getAsset + , getAssetDefault , getCurrentEpoch , getMigrationInfo , getNetworkClock @@ -70,6 +73,7 @@ import Cardano.Wallet.Api.Server , joinStakePool , liftHandler , listAddresses + , listAssets , listTransactions , listWallets , migrateWallet @@ -193,6 +197,7 @@ server server byron icarus shelley spl ntp = wallets :<|> walletKeys + :<|> assets :<|> addresses :<|> coinSelections :<|> transactions @@ -221,6 +226,9 @@ server byron icarus shelley spl ntp = walletKeys = derivePublicKey shelley :<|> signMetadata shelley + assets :: Server Assets + assets = listAssets shelley :<|> getAsset shelley :<|> getAssetDefault shelley + addresses :: Server (Addresses n) addresses = listAddresses shelley (normalizeDelegationAddress @_ @ShelleyKey @n) :<|> (handler ApiAddressInspect . inspectAddress . unApiAddressInspectData) diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs index b1aba1f6c1c..1b8841fac4c 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs @@ -289,7 +289,6 @@ import qualified Data.ByteString.Short as SBS import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Data.Text.Encoding as T -import qualified Data.Text.Encoding.Error as T import qualified Ouroboros.Consensus.Shelley.Ledger as O import qualified Ouroboros.Network.Block as O import qualified Ouroboros.Network.Point as Point @@ -759,11 +758,9 @@ fromPoolDistr = fromNonMyopicMemberRewards :: forall era. () => O.NonMyopicMemberRewards era - -> Map - (Either W.Coin W.RewardAccount) - (Map W.PoolId (Quantity "lovelace" Word64)) + -> Map (Either W.Coin W.RewardAccount) (Map W.PoolId W.Coin) fromNonMyopicMemberRewards = - Map.map (Map.map lovelaceFromCoin . Map.mapKeys fromPoolId) + Map.map (Map.map toWalletCoin . Map.mapKeys fromPoolId) . Map.mapKeys (bimap fromShelleyCoin fromStakeCredential) . O.unNonMyopicMemberRewards @@ -924,9 +921,7 @@ fromCardanoValue = uncurry TokenBundle.fromFlatList . extract ] mkPolicyId = W.UnsafeTokenPolicyId . W.Hash . Cardano.serialiseToRawBytes - mkTokenName = W.UnsafeTokenName - . T.decodeUtf8With T.lenientDecode - . Cardano.serialiseToRawBytes + mkTokenName = W.UnsafeTokenName . Cardano.serialiseToRawBytes unQuantity (Cardano.Quantity q) = q @@ -970,8 +965,8 @@ fromShelleyRegistrationCert = \case { W.poolId = fromPoolKeyHash $ SL._poolId pp , W.poolOwners = fromOwnerKeyHash <$> Set.toList (SL._poolOwners pp) , W.poolMargin = fromUnitInterval (SL._poolMargin pp) - , W.poolCost = lovelaceFromCoin (SL._poolCost pp) - , W.poolPledge = lovelaceFromCoin (SL._poolPledge pp) + , W.poolCost = toWalletCoin (SL._poolCost pp) + , W.poolPledge = toWalletCoin (SL._poolPledge pp) , W.poolMetadata = fromPoolMetadata <$> strictMaybeToMaybe (SL._poolMD pp) } ) @@ -984,9 +979,6 @@ fromShelleyRegistrationCert = \case SL.DCertGenesis{} -> Nothing SL.DCertMir{} -> Nothing -lovelaceFromCoin :: SL.Coin -> Quantity "lovelace" Word64 -lovelaceFromCoin = Quantity . unsafeCoinToWord64 - toWalletCoin :: SL.Coin -> W.Coin toWalletCoin = W.Coin . unsafeCoinToWord64 @@ -1181,7 +1173,7 @@ toCardanoValue tb = Cardano.valueFromList $ toCardanoPolicyId (W.UnsafeTokenPolicyId (W.Hash pid)) = just "PolicyId" $ Cardano.deserialiseFromRawBytes Cardano.AsPolicyId pid toCardanoAssetName (W.UnsafeTokenName name) = just "TokenName" $ - Cardano.deserialiseFromRawBytes Cardano.AsAssetName $ T.encodeUtf8 name + Cardano.deserialiseFromRawBytes Cardano.AsAssetName name just :: String -> Maybe a -> a just t = fromMaybe $ error $ diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Network.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Network.hs index 801bec1f926..5c3d6553458 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Network.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Network.hs @@ -131,7 +131,7 @@ import Data.Maybe import Data.Proxy ( Proxy (..) ) import Data.Quantity - ( Percentage, Quantity (..) ) + ( Percentage ) import Data.Set ( Set ) import Data.Text @@ -142,8 +142,6 @@ import Data.Time.Clock ( DiffTime ) import Data.Void ( Void ) -import Data.Word - ( Word64 ) import Fmt ( Buildable (..), fmt, listF, mapF, pretty ) import GHC.Stack @@ -350,8 +348,6 @@ withNetworkLayerBase tr np conn (versionData, _) action = do _timeInterpreter (contramap MsgInterpreterLog tr) interpreterVar } where - coinToQuantity (W.Coin x) = Quantity $ fromIntegral x - gp@W.GenesisParameters { getGenesisBlockHash , getGenesisBlockDate @@ -512,7 +508,7 @@ withNetworkLayerBase tr np conn (versionData, _) action = do queryNonMyopicMemberRewards :: LSQ (CardanoBlock StandardCrypto) IO - (Maybe (Map W.PoolId (Quantity "lovelace" Word64))) + (Maybe (Map W.PoolId W.Coin)) queryNonMyopicMemberRewards = shelleyBased $ (getRewardMap . fromNonMyopicMemberRewards) <$> LSQry (Shelley.GetNonMyopicMemberRewards stake) @@ -526,8 +522,8 @@ withNetworkLayerBase tr np conn (versionData, _) action = do getRewardMap :: Map (Either W.Coin W.RewardAccount) - (Map W.PoolId (Quantity "lovelace" Word64)) - -> Map W.PoolId (Quantity "lovelace" Word64) + (Map W.PoolId W.Coin) + -> Map W.PoolId W.Coin getRewardMap = fromJustRewards . Map.lookup (Left coin) @@ -540,7 +536,7 @@ withNetworkLayerBase tr np conn (versionData, _) action = do -- stopObserving. _getAccountBalance rewardsObserver k = liftIO $ do startObserving rewardsObserver k - coinToQuantity . fromMaybe (W.Coin 0) <$> query rewardsObserver k + fromMaybe (W.Coin 0) <$> query rewardsObserver k _timeInterpreter :: HasCallStack diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Pools.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Pools.hs index cf2174bc453..4b2f287db8a 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Pools.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Pools.hs @@ -333,7 +333,7 @@ newStakePoolLayer gcStatus nl db@DBLayer {..} restartSyncThread = do -- | Stake pool-related data that has been read from the node using a local -- state query. data PoolLsqData = PoolLsqData - { nonMyopicMemberRewards :: Quantity "lovelace" Word64 + { nonMyopicMemberRewards :: Coin , relativeStake :: Percentage , saturation :: Double } deriving (Eq, Show, Generic) @@ -380,11 +380,11 @@ combineDbAndLsqData ti nOpt lsqData = -- any leader schedule, we assign them the average reward of the top @k@ -- pools. freshmanMemberRewards - = Quantity + = Coin $ average $ L.take nOpt $ L.sort - $ map (Down . getQuantity . nonMyopicMemberRewards) + $ map (Down . unCoin . nonMyopicMemberRewards) $ Map.elems lsqData where average [] = 0 @@ -406,7 +406,7 @@ combineDbAndLsqData ti nOpt lsqData = pure $ Api.ApiStakePool { Api.id = (ApiT pid) , Api.metrics = Api.ApiStakePoolMetrics - { Api.nonMyopicMemberRewards = fmap fromIntegral prew + { Api.nonMyopicMemberRewards = Api.coinToQuantity prew , Api.relativeStake = Quantity pstk , Api.saturation = psat , Api.producedBlocks = @@ -415,9 +415,9 @@ combineDbAndLsqData ti nOpt lsqData = , Api.metadata = ApiT <$> metadata dbData , Api.cost = - fmap fromIntegral $ poolCost $ registrationCert dbData + Api.coinToQuantity $ poolCost $ registrationCert dbData , Api.pledge = - fmap fromIntegral $ poolPledge $ registrationCert dbData + Api.coinToQuantity $ poolPledge $ registrationCert dbData , Api.margin = Quantity $ poolMargin $ registrationCert dbData , Api.retirement = @@ -446,9 +446,9 @@ combineLsqData StakePoolsSummary{nOpt, rewards, stake} = -- balance of 0, the resulting map will be empty. So we set the rewards -- to 0 here: stakeButNoRewards = traverseMissing $ \_k s -> pure $ PoolLsqData - { nonMyopicMemberRewards = Quantity 0 + { nonMyopicMemberRewards = Coin 0 , relativeStake = s - , saturation = (sat s) + , saturation = sat s } -- TODO: This case seems possible on shelley_testnet, but why, and how diff --git a/lib/shelley/test/integration/Main.hs b/lib/shelley/test/integration/Main.hs index b636cc4121c..f04bdeaadb6 100644 --- a/lib/shelley/test/integration/Main.hs +++ b/lib/shelley/test/integration/Main.hs @@ -298,7 +298,6 @@ specWithServer testDir (tr, tracers) era = aroundAll withContext onClusterStart action dbDecorator (RunningNode conn block0 (gp, vData)) = do setupFaucet conn let db = testDir "wallets" - putStrLn $ "creating" <> show db createDirectory db listen <- walletListenFromEnv serveWallet diff --git a/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs b/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs index 722ae9b135d..ac0fd9eb96d 100644 --- a/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs +++ b/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs @@ -51,7 +51,7 @@ import Cardano.Wallet.Primitive.Types import Cardano.Wallet.Primitive.Types.Address ( Address (..) ) import Cardano.Wallet.Primitive.Types.Coin - ( Coin (..) ) + ( Coin (..), coinQuantity ) import Cardano.Wallet.Primitive.Types.Coin.Gen ( genCoinLargePositive, shrinkCoinLargePositive ) import Cardano.Wallet.Primitive.Types.Hash @@ -198,11 +198,11 @@ spec = do [ TxOut (dummyAddress 0) (coinToBundle 4834720) ] - let wdrl = Quantity 0 + let wdrl = Coin 0 let selectCoins = flip catchE (handleCannotCover utxo wdrl recipients) $ do (sel, utxo') <- withExceptT ErrSelectForPaymentCoinSelection $ do - CS.random testCoinSelOpts recipients wdrl utxo + CS.random testCoinSelOpts recipients (coinQuantity wdrl) utxo withExceptT ErrSelectForPaymentFee $ (Fee . CS.feeBalance) <$> adjustForFee testFeeOpts utxo' sel res <- runExceptT $ estimateFeeForCoinSelection Nothing selectCoins diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index c7476ca51c1..fcb9d8e6c5c 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -236,7 +236,7 @@ x-syncClockProgress: &syncClockProgress status: pending x-amount: &amount - description: Coins, in Lovelace + description: Coins, in Lovelace. Only relates to 'Ada'. Refer to `assets` for multi-assets wallets instead. type: object required: - quantity @@ -433,6 +433,132 @@ x-settings: &settings After update existing metadata will be dropped forcing it to re-sync automatically with the new setting. +x-assetName: &assetName + type: string + description: | + The asset on-chain type which acts as a sub-identifier within a + policy. Although we call it "asset name", the value needn't be + text, and it could even be empty. + + For policies with a single fungible asset item, asset name is + typically an empty string. + + This value can be up to 32 bytes of arbitrary data (which is 64 + hexadecimal digits). + format: hex + maxLength: 64 + example: "" + +x-assetPolicyId: &assetPolicyId + type: string + description: | + A unique identifier of the asset's monetary policy. The policy + controls how assets of this kind are created and destroyed. + + The contents are the blake2b-224 hash of the monetary policy + script, encoded in hexadecimal. + format: hex + minLength: 56 + maxLength: 56 + example: 65ab82542b0ca20391caaf66a4d4d7897d281f9c136cd3513136945b + +x-assetMetadataName: &assetMetadataName + type: string + maxLength: 50 + minLength: 1 + description: | + A human-readable name for the asset. Good for display in user interfaces. + example: SwaggerCoin + +x-assetMetadataAcronym: &assetMetadataAcronym + type: string + maxLength: 4 + minLength: 2 + description: | + A human-readable short name for the asset. Good for display in + user interfaces. + example: SWAG + +x-assetMetadataDescription: &assetMetadataDescription + description: | + A human-readable description for the asset. Good for display in user interfaces. + type: string + maxLength: 500 + +x-assetMetadataUnit: &assetMetadataUnit + type: object + description: | + Defines a larger unit for the asset, in the same way Ada is the + larger unit of Lovelace. + required: + - decimals + - name + additionalProperties: false + properties: + decimals: + type: integer + description: | + The number of digits after the decimal point. + minimum: 0 + maximum: 19 + name: + type: string + minLength: 1 + maxLength: 30 + description: | + The human-readable name for the larger unit of the asset. Used + for display in user interfaces. + example: + name: API + decimals: 3 + +x-assetMetadataUrl: &assetMetadataUrl + description: | + A URL to the policy's owner(s) or the entity website in charge of the asset. + type: string + format: uri + pattern: "^https://.+" + maxLength: 250 + +x-assetMetadataLogo: &assetMetadataLogo + description: | + A base64-encoded `image/png` for displaying the asset. The end image can be expected + to be smaller than 64KB. + type: string + format: base64 + maxLength: 87400 + +x-assetMetadata: &assetMetadata + title: Native Assets Metadata + description: | +

status: ⚠ under development

+ + _This field is not implemented yet, and the values will always be empty._ + + In the Mary era of Cardano, UTxO may contain native assets. These + assets are represented on-chain by opaque identifiers which are + meaningless to end-users. Therefore, user-facing metadata + regarding each token must be stored off-chain, in a metadata + registry. + + Token creators may publish metadata into the registry and client + applications can consume these metadata for display to end + users. This will work in a similar way to how it is done for stake + pool metadata. + type: object + additionalProperties: false + required: + - name + - acronym + - description + properties: + name: *assetMetadataName + acronym: *assetMetadataAcronym + description: *assetMetadataDescription + unit: *assetMetadataUnit + url: *assetMetadataUrl + logo: *assetMetadataLogo + x-walletMnemonicSentence: &walletMnemonicSentence description: A list of mnemonic words type: array @@ -508,7 +634,7 @@ x-walletState: &walletState description: Whether a wallet is ready to use or still syncing x-walletBalance: &walletBalance - description: Wallet current balance(s) + description: Wallet current Ada balance(s). type: object required: - available @@ -517,13 +643,80 @@ x-walletBalance: &walletBalance properties: available: <<: *amount - description: Available UTxO balance (funds that can be spent without condition). + description: Available Ada UTxO balance (funds that can be spent without condition). reward: <<: *amount - description: The balance of the reward account for this wallet. + description: The Ada balance of the reward account for this wallet. total: <<: *amount - description: Total balance (available balance plus pending change and reward balance). + description: Total Ada balance (available balance plus pending change and reward balance). + +x-assetQuantity: &assetQuantity + type: integer + description: | + Number of assets for the given `policy_id` and `asset_name`. + minimum: 0 + +x-walletAsset: &walletAsset + description: | + An asset on the Cardano blockchain. An asset is uniquely identified by + its `policy_id` and `asset_name` (together, these form the _asset id_). + + Two assets with the same `asset_name` and `policy_id` are + interchangeable. Yet, different assets with a same `policy_id` but + different `asset_name` are treated as separate assets, as are two + assets with the same `asset_name` but different `policy_id`. + type: object + required: + - policy_id + - asset_name + - quantity + properties: + policy_id: *assetPolicyId + asset_name: *assetName + quantity: *assetQuantity + +x-walletAssets: &walletAssets + description: A flat list of assets. + type: array + items: *walletAsset + +x-assetMint: &assetMint + type: object + required: + - policy_id + - asset_name + - quantity + properties: + policy_id: *assetPolicyId + asset_name: *assetName + quantity: + type: integer + description: | + Positive values mean creation and negative values mean + destruction. + +x-walletAssetsBalance: &walletAssetsBalance + description: | + Current non-Ada asset holdings of the wallet. + + The amount of assets available to spend may be less than the total + unspent assets due to transaction change amounts which are yet to + be fully confirmed (pending). + type: object + required: + - available + - total + properties: + available: + <<: *walletAssets + description: | + Available UTxO asset balances (funds that can be spent without + condition). + total: + <<: *walletAssets + description: | + Total asset balances (available balances plus pending change balances). x-byronWalletBalance: &byronWalletBalance description: Byron wallet's current balance(s) @@ -555,9 +748,6 @@ x-transactionId: &transactionId minLength: 64 example: 1423856bc91c49e928f6f30f4e8d665d53eb4ab6028bd0ac971809d514c92db1 -x-transactionAmount: &transactionAmount - <<: *amount - x-transactionInsertedAt: &transactionInsertedAt description: | @@ -603,7 +793,13 @@ x-addresses: &addresses items: *addressId x-transactionInputs: &transactionInputs - description: A list of transaction inputs + description: | + A list of transaction inputs. + + `assets` and `address` are always present for `outgoing` + transactions but generally absent for `incoming` + transactions. This information is present on the Cardano explorer, + but is not tracked by the wallet. type: array minItems: 0 items: @@ -613,7 +809,8 @@ x-transactionInputs: &transactionInputs - index properties: address: *addressId - amount: *transactionAmount + amount: *amount + assets: *walletAssets id: *transactionId index: type: integer @@ -630,7 +827,8 @@ x-transactionOutputs: &transactionOutputs - amount properties: address: *addressId - amount: *transactionAmount + amount: *amount + assets: *walletAssets x-delegationAction: &delegationAction description: | @@ -714,6 +912,22 @@ x-transactionWithdrawals: &transactionWithdrawals stake_address: *stakeAddress amount: *amount +x-transactionMint: &transactionMint + description: | +

status: ⚠ under development

+ + _This field is not implemented yet, and will always be empty._ + + Assets minted (created) or unminted (destroyed) + + This amount contributes to the total transaction value. + + Positive values denote creation of assets and negative values + denote the reverse. + type: array + minItems: 0 + items: *assetMint + x-derivationSegment: &derivationSegment description: | An individual segment within a derivation path. @@ -740,7 +954,7 @@ x-transactionChange: &transactionChange - derivation_path properties: address: *addressId - amount: *transactionAmount + amount: *amount derivation_path: *derivationPath x-transactionResolvedInputs: &transactionResolvedInputs @@ -757,7 +971,7 @@ x-transactionResolvedInputs: &transactionResolvedInputs - derivation_path properties: address: *addressId - amount: *transactionAmount + amount: *amount id: *transactionId derivation_path: *derivationPath index: @@ -1096,7 +1310,7 @@ x-deposits: &deposits description: A list of deposits associated with a transaction. type: array minItems: 0 - items: *transactionAmount + items: *amount ############################################################################# # # @@ -1329,9 +1543,9 @@ components: - estimated_max - deposit properties: - estimated_min: *transactionAmount - estimated_max: *transactionAmount - deposit: *transactionAmount + estimated_min: *amount + estimated_max: *amount + deposit: *amount ApiPutAddressesData: &ApiPutAddressesData type: object @@ -1359,18 +1573,38 @@ components: required: - id - amount + - assets - fee - deposit - direction - inputs - outputs - withdrawals + - mint - status properties: id: *transactionId - amount: *transactionAmount - fee: *transactionAmount - deposit: *transactionAmount + amount: + <<: *amount + description: | + An amount of Ada spent or received, from the perspective of the wallet. + + That is, for outgoing transaction, it represents the amount of Ada consumed + as inputs, minus the amount of Ada spent as fees, as deposits or to addresses + which do not belong to the wallet. + + For incoming transaction, it represents the total amount of Ada received to + addresses that belong to the wallet. + fee: *amount + deposit: *amount + assets: + <<: *walletAssets + description: | + An amount of non-Ada assets spent or received, from the + perspective of the wallet. + + Note that transaction fees and delegation rewards are + always denominated in Ada. inserted_at: *transactionInsertedAt expires_at: *transactionExpiresAt pending_since: *transactionPendingSince @@ -1379,6 +1613,7 @@ components: inputs: *transactionInputs outputs: *transactionOutputs withdrawals: *transactionWithdrawals + mint: *transactionMint status: *transactionStatus metadata: *transactionMetadata @@ -1426,6 +1661,7 @@ components: - id - address_pool_gap - balance + - assets - delegation - name - state @@ -1434,6 +1670,7 @@ components: id: *walletId address_pool_gap: *walletAddressPoolGap balance: *walletBalance + assets: *walletAssetsBalance delegation: *ApiWalletDelegation name: *walletName passphrase: *walletPassphraseInfo @@ -1458,6 +1695,16 @@ components: state: *walletState tip: *blockReference + ApiAsset: &ApiAsset + type: object + required: + - policy_id + - asset_name + properties: + policy_id: *assetPolicyId + asset_name: *assetName + metadata: *assetMetadata + ApiWalletMigrationInfo: &ApiWalletMigrationInfo type: object required: @@ -2060,6 +2307,25 @@ x-parametersMinWithdrawal: ¶metersMinWithdrawal type: integer minimum: 1 +x-parametersPolicyId: ¶metersPolicyId + in: path + name: policyId + required: true + schema: + type: string + format: hex + maxLength: 56 + minLength: 56 + +x-parametersAssetName: ¶metersAssetName + in: path + name: assetName + required: true + schema: + type: string + format: hex + maxLength: 64 + ############################################################################# # # # RESPONSES # @@ -2670,6 +2936,25 @@ x-responsesListWallets: &responsesListWallets type: array items: *ApiWallet +x-responsesListAssets: &responsesListAssets + <<: *responsesErr406 + 200: + description: Ok + content: + application/json: + schema: + type: array + items: *ApiAsset + +x-responsesGetAsset: &responsesGetAsset + <<: *responsesErr404 + <<: *responsesErr406 + 200: + description: Ok + content: + application/json: + schema: *ApiAsset + x-responsesListByronWallets: &responsesListByronWallets <<: *responsesErr406 200: @@ -3184,6 +3469,7 @@ x-tagGroups: - name: Shelley (Sequential) tags: - Wallets + - Assets - Addresses - Coin Selections - Transactions @@ -3260,6 +3546,57 @@ paths: Return a list of known wallets, ordered from oldest to newest. responses: *responsesListWallets + /wallets/{walletId}/assets: + get: + operationId: listAssets + tags: ["Assets"] + summary: List Assets + description: | +

status: under development

+ + 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. + parameters: + - *parametersWalletId + responses: *responsesListAssets + + /wallets/{walletId}/assets/{policyId}/{assetName}: + get: + operationId: getAsset + tags: ["Assets"] + summary: Get Asset + description: | +

status: under development

+ + Fetch a single asset from its `policy_id` and `asset_name`, + with its metadata if any. + + The asset must be associated with the wallet. + parameters: + - *parametersWalletId + - *parametersPolicyId + - *parametersAssetName + responses: *responsesGetAsset + + /wallets/{walletId}/assets/{policyId}: + get: + operationId: getAssetDefault + tags: ["Assets"] + summary: Get Asset (empty name) + description: | +

status: under development

+ + Fetch the the asset from `policy_id` with an empty name. + + The asset must be associated with the wallet. + parameters: + - *parametersWalletId + - *parametersPolicyId + responses: *responsesGetAsset + /wallets/{walletId}/statistics/utxos: get: operationId: getUTxOsStatistics