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 96993621a40..1b7ce6f7865 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 @@ -226,7 +226,7 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do [ expectResponseCode HTTP.status202 , expectField (#status . #getApiT) (`shouldBe` Pending) , expectField (#direction . #getApiT) (`shouldBe` Outgoing) - , expectField #deposit (`shouldBe` Quantity 1000000) + , expectField #depositTaken (`shouldBe` Quantity 1000000) , expectField #inputs $ \inputs' -> do inputs' `shouldSatisfy` all (isJust . source) ] @@ -239,7 +239,8 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do [ expectResponseCode HTTP.status200 , expectField (#status . #getApiT) (`shouldBe` InLedger) , expectField (#direction . #getApiT) (`shouldBe` Outgoing) - , expectField #deposit (`shouldBe` Quantity 1000000) + , expectField #depositTaken (`shouldBe` Quantity 1000000) + , expectField #depositReturned (`shouldBe` Quantity 0) ] let txId = getFromResponse #id rJoin @@ -414,6 +415,8 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do #amount (`shouldBe` quitFeeAmt) , expectField (#status . #getApiT) (`shouldBe` InLedger) + , expectField #depositTaken (`shouldBe` Quantity 0) + , expectField #depositReturned (`shouldBe` Quantity 1000000) ] let epl = Link.listTransactions @'Shelley src diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index a56aabd66bd..5e13be73aef 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -214,6 +214,7 @@ import qualified Data.Text.Encoding as T import qualified Network.HTTP.Types.Status as HTTP import qualified Test.Integration.Plutus as PlutusScenario + spec :: forall n. ( DecodeAddress n , DecodeStakeAddress n @@ -841,9 +842,6 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do rGetTx <- request @(ApiTransaction n) ctx queryTx Default Empty verify rGetTx [ expectResponseCode HTTP.status200 - , expectField - (#amount . #getQuantity) - (`shouldBe` initialAmt - (amt + fromIntegral expectedFee)) , expectField (#direction . #getApiT) (`shouldBe` Outgoing) , expectField (#status . #getApiT) (`shouldBe` Pending) ] @@ -2175,6 +2173,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do let initialAmt = 10 * minUTxOValue (_mainEra ctx) src <- fixtureWalletWith @n ctx [initialAmt] dest <- emptyWallet ctx + let depositAmt = Quantity 1000000 pool1:pool2:_ <- map (view #id) . snd <$> unsafeRequest @[ApiStakePool] @@ -2192,7 +2191,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do (Link.createUnsignedTransaction @'Shelley src) Default delegationJoin verify rTx1 [ expectResponseCode HTTP.status202 - , expectField (#coinSelection . #depositsTaken) (`shouldBe` [Quantity 1000000]) + , expectField (#coinSelection . #depositsTaken) (`shouldBe` [depositAmt]) , expectField (#coinSelection . #depositsReturned) (`shouldBe` []) ] @@ -2219,7 +2218,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do verify rDecodedTx1 [ expectResponseCode HTTP.status202 , expectField #certificates (`shouldBe` [registerStakeKeyCert, delegatingCert]) - , expectField #depositsTaken (`shouldBe` [Quantity 1000000]) + , expectField #depositsTaken (`shouldBe` [depositAmt]) , expectField #depositsReturned (`shouldBe` []) ] @@ -2239,7 +2238,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do [ expectResponseCode HTTP.status200 , expectField (#status . #getApiT) (`shouldBe` InLedger) , expectField (#direction . #getApiT) (`shouldBe` Outgoing) - , expectField #deposit (`shouldBe` Quantity 1000000) + , expectField #depositTaken (`shouldBe` depositAmt) + , expectField #depositReturned (`shouldBe` Quantity 0) ] let txId1 = getFromResponse #id submittedTx1 @@ -2308,6 +2308,15 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do , expectResponseCode HTTP.status202 ] + let txid2 = getFromResponse (#id) submittedTx2 + let queryTx2 = Link.getTransaction @'Shelley src (ApiTxId txid2) + rGetTx2 <- request @(ApiTransaction n) ctx queryTx2 Default Empty + verify rGetTx2 + [ expectResponseCode HTTP.status200 + , expectField #depositTaken (`shouldBe` Quantity 0) + , expectField #depositReturned (`shouldBe` Quantity 0) + ] + -- Wait for the certificate to be inserted eventually "Certificates are inserted" $ do let ep = Link.listTransactions @'Shelley src @@ -2385,7 +2394,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do verify rTx4 [ expectResponseCode HTTP.status202 , expectField (#coinSelection . #depositsTaken) (`shouldBe` []) - , expectField (#coinSelection . #depositsReturned) (`shouldBe` [Quantity 1000000]) + , expectField (#coinSelection . #depositsReturned) (`shouldBe` [depositAmt]) ] let apiTx4 = getFromResponse #transaction rTx4 signedTx4 <- signTx ctx src apiTx4 [ expectResponseCode HTTP.status202 ] @@ -2399,7 +2408,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do verify rDecodedTx4 [ expectResponseCode HTTP.status202 , expectField #certificates (`shouldBe` [quittingCert]) - , expectField #depositsReturned (`shouldBe` [Quantity 1000000]) + , expectField #depositsReturned (`shouldBe` [depositAmt]) , expectField #depositsTaken (`shouldBe` []) ] submittedTx4 <- submitTxWithWid ctx src signedTx4 @@ -2407,12 +2416,30 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do [ expectSuccess , expectResponseCode HTTP.status202 ] + + let txid3 = getFromResponse (#id) submittedTx4 + let queryTx3 = Link.getTransaction @'Shelley src (ApiTxId txid3) + rGetTx3 <- request @(ApiTransaction n) ctx queryTx3 Default Empty + verify rGetTx3 + [ expectResponseCode HTTP.status200 + , expectField #depositTaken (`shouldBe` Quantity 0) + , expectField #depositReturned (`shouldBe` depositAmt) + ] + eventually "Wallet is not delegating" $ do request @ApiWallet ctx (Link.getWallet @'Shelley src) Default Empty >>= flip verify [ expectField #delegation (`shouldBe` notDelegating []) ] + -- transaction history shows deposit returned + rGetTx4 <- request @(ApiTransaction n) ctx queryTx3 Default Empty + verify rGetTx4 + [ expectResponseCode HTTP.status200 + , expectField #depositTaken (`shouldBe` Quantity 0) + , expectField #depositReturned (`shouldBe` depositAmt) + ] + it "TRANS_NEW_JOIN_01b - Invalid pool id" $ \ctx -> runResourceT $ do wa <- fixtureWallet ctx diff --git a/lib/core/src/Cardano/Wallet.hs b/lib/core/src/Cardano/Wallet.hs index 717ed7136e1..c45f731bc56 100644 --- a/lib/core/src/Cardano/Wallet.hs +++ b/lib/core/src/Cardano/Wallet.hs @@ -540,6 +540,8 @@ import Safe ( lastMay ) import Statistics.Quantile ( medianUnbiased, quantiles ) +import Text.Pretty.Simple + ( pShow ) import Type.Reflection ( Typeable, typeRep ) import UnliftIO.Exception @@ -568,8 +570,7 @@ import qualified Data.List.NonEmpty as NE import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Vector as V -import Text.Pretty.Simple - ( pShow ) + -- $Development -- __Naming Conventions__ @@ -2106,7 +2107,6 @@ getTxExpiry ti maybeTTL = do constructTxMeta :: forall ctx s k. ( HasDBLayer IO s k ctx - , IsOwned s k ) => ctx -> WalletId @@ -2120,21 +2120,19 @@ constructTxMeta ctx wid txCtx inps outs = db & \DBLayer{..} -> do $ withNoSuchWallet wid $ readCheckpoint wid liftIO $ - mkTxMetaWithoutSel (currentTip cp) (getState cp) txCtx inps outs + mkTxMetaWithoutSel (currentTip cp) txCtx inps outs where db = ctx ^. dbLayer @IO @s @k mkTxMetaWithoutSel - :: IsOurs s Address - => BlockHeader - -> s + :: BlockHeader -> TransactionCtx -> [(TxIn, Coin)] -> [TxOut] -> IO TxMeta -mkTxMetaWithoutSel blockHeader wState txCtx inps outs = +mkTxMetaWithoutSel blockHeader txCtx inps outs = let - amtOuts = F.fold $ mapMaybe (`ourCoin` wState) outs + amtOuts = F.fold $ map txOutCoin outs amtInps = F.fold (map snd inps) @@ -2144,7 +2142,7 @@ mkTxMetaWithoutSel blockHeader wState txCtx inps outs = NoWithdrawal -> Prelude.id in return TxMeta { status = Pending - , direction = Outgoing + , direction = if amtInps > amtOuts then Outgoing else Incoming , slotNo = blockHeader ^. #slotNo , blockHeight = blockHeader ^. #blockHeight , amount = Coin.distance amtInps amtOuts @@ -3082,6 +3080,7 @@ data ErrSubmitTransaction = ErrSubmitTransactionNoSuchWallet ErrNoSuchWallet | ErrSubmitTransactionForeignWallet | ErrSubmitTransactionPartiallySignedOrNoSignedTx Int Int + | ErrSubmitTransactionMultidelegationNotSupported deriving (Show, Eq) -- | Errors that can occur when constructing an unsigned transaction. diff --git a/lib/core/src/Cardano/Wallet/Api/Server.hs b/lib/core/src/Cardano/Wallet/Api/Server.hs index 7162a319acd..99c05e22ed7 100644 --- a/lib/core/src/Cardano/Wallet/Api/Server.hs +++ b/lib/core/src/Cardano/Wallet/Api/Server.hs @@ -1948,7 +1948,7 @@ postTransactionOld ctx genChange (ApiT wid) body = do , txTimeToLive = ttl } - (sel, tx, txMeta, txTime) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> + (sel, tx, txMeta, txTime, pp) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> atomicallyWithHandler (ctx ^. walletLocks) (PostTransactionOld wid) $ do (utxoAvailable, wallet, pendingTxs) <- liftHandler $ W.readWalletUTxOIndex @_ @s @k wrk wid @@ -1972,7 +1972,7 @@ postTransactionOld ctx genChange (ApiT wid) body = do $ W.buildAndSignTransaction @_ @s @k wrk wid mkRwdAcct pwd txCtx sel' liftHandler $ W.submitTx @_ @s @k wrk wid (tx, txMeta, sealedTx) - pure (sel, tx, txMeta, txTime) + pure (sel, tx, txMeta, txTime, pp) liftIO $ mkApiTransaction (timeInterpreter $ ctx ^. networkLayer) @@ -1989,6 +1989,7 @@ postTransactionOld ctx genChange (ApiT wid) body = do , txMetadata = tx ^. #metadata , txTime , txScriptValidity = tx ^. #scriptValidity + , txDeposit = W.stakeKeyDeposit pp } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) @@ -2015,13 +2016,16 @@ listTransactions -> Maybe (ApiT SortOrder) -> Handler [ApiTransaction n] listTransactions ctx (ApiT wid) mMinWithdrawal mStart mEnd mOrder = do - txs <- withWorkerCtx ctx wid liftE liftE $ \wrk -> liftHandler $ - W.listTransactions @_ @_ @_ wrk wid + (txs, depo) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do + txs <- liftHandler $ + W.listTransactions @_ @_ @_ wrk wid (Coin . fromIntegral . getMinWithdrawal <$> mMinWithdrawal) (getIso8601Time <$> mStart) (getIso8601Time <$> mEnd) (maybe defaultSortOrder getApiT mOrder) - liftIO $ mapM (mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer))) txs + depo <- liftIO $ W.stakeKeyDeposit <$> NW.currentProtocolParameters (wrk ^. networkLayer) + pure (txs, depo) + liftIO $ mapM (mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer)) depo) txs where defaultSortOrder :: SortOrder defaultSortOrder = Descending @@ -2033,18 +2037,21 @@ getTransaction -> ApiTxId -> Handler (ApiTransaction n) getTransaction ctx (ApiT wid) (ApiTxId (ApiT (tid))) = do - tx <- withWorkerCtx ctx wid liftE liftE $ \wrk -> liftHandler $ - W.getTransaction wrk wid tid - liftIO $ mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer)) tx + (tx, depo) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do + tx <- liftHandler $ W.getTransaction wrk wid tid + depo <- liftIO $ W.stakeKeyDeposit <$> NW.currentProtocolParameters (wrk ^. networkLayer) + pure (tx, depo) + liftIO $ mkApiTransactionFromInfo (timeInterpreter (ctx ^. networkLayer)) depo tx -- Populate an API transaction record with 'TransactionInfo' from the wallet -- layer. mkApiTransactionFromInfo :: MonadIO m => TimeInterpreter (ExceptT PastHorizonException IO) + -> Coin -> TransactionInfo -> m (ApiTransaction n) -mkApiTransactionFromInfo ti info = do +mkApiTransactionFromInfo ti deposit info = do apiTx <- liftIO $ mkApiTransaction ti status MkApiTransactionParams { txId = info ^. #txInfoId @@ -2057,6 +2064,7 @@ mkApiTransactionFromInfo ti info = do , txMetadata = info ^. #txInfoMetadata , txTime = info ^. #txInfoTime , txScriptValidity = info ^. #txInfoScriptValidity + , txDeposit = deposit } return $ case info ^. (#txInfoMeta . #status) of Pending -> apiTx @@ -2415,6 +2423,17 @@ submitTransaction ctx apiw@(ApiT wid) apitx@(ApiSerialisedTransaction (ApiT seal let ourOuts = getOurOuts apiDecoded let ourInps = getOurInps apiDecoded + let ourDel = + filter isJust $ + map isJoiningOrQuitting $ apiDecoded ^. #certificates + when (length ourDel > 1) $ + liftHandler $ throwE ErrSubmitTransactionMultidelegationNotSupported + + let delAction = case ourDel of + [Just del] -> Just del + [] -> Nothing + _ -> error "impossible to be here due to check above" + let allInpsNum = length $ apiDecoded ^. #inputs let witsNum = length $ getSealedTxWitnesses sealedTx when (allInpsNum > witsNum) $ @@ -2427,6 +2446,7 @@ submitTransaction ctx apiw@(ApiT wid) apitx@(ApiSerialisedTransaction (ApiT seal let txCtx = defaultTransactionCtx { txTimeToLive = ttl , txWithdrawal = wdrl + , txDelegationAction = delAction } txMeta <- liftHandler $ W.constructTxMeta @_ @s @k wrk wid txCtx ourInps ourOuts liftHandler @@ -2460,8 +2480,8 @@ submitTransaction ctx apiw@(ApiT wid) apitx@(ApiSerialisedTransaction (ApiT seal isInpOurs (WalletInput _) = True isInpOurs _ = False - toTxInp (WalletInput (ApiWalletInput (ApiT txid) ix _ _ _ _)) = - (TxIn txid ix, Coin 0) + toTxInp (WalletInput (ApiWalletInput (ApiT txid) ix _ _ (Quantity amt) _)) = + (TxIn txid ix, Coin $ fromIntegral amt) toTxInp _ = error "we should have only our inputs at this point" getOurInps apiDecodedTx = let generalInps = apiDecodedTx ^. #inputs @@ -2477,6 +2497,14 @@ submitTransaction ctx apiw@(ApiT wid) apitx@(ApiSerialisedTransaction (ApiT seal all isInpForeign generalInps && all isWdrlForeign generalWdrls + isJoiningOrQuitting = \case + WalletDelegationCertificate (JoinPool _ (ApiT poolId)) -> + Just $ Join poolId + WalletDelegationCertificate (QuitPool _) -> + Just Quit + _ -> + Nothing + joinStakePool :: forall ctx s n k. ( ctx ~ ApiLayer s k @@ -2510,7 +2538,7 @@ joinStakePool ctx knownPools getPoolStatus apiPoolId (ApiT wid) body = do pools <- liftIO knownPools curEpoch <- getCurrentEpoch ctx - (sel, tx, txMeta, txTime) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do + (sel, tx, txMeta, txTime, pp) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do (action, _) <- liftHandler $ W.joinStakePool @_ @s @k wrk curEpoch pools pid poolStatus wid @@ -2544,7 +2572,7 @@ joinStakePool ctx knownPools getPoolStatus apiPoolId (ApiT wid) body = do liftHandler $ W.submitTx @_ @s @k wrk wid (tx, txMeta, sealedTx) - pure (sel, tx, txMeta, txTime) + pure (sel, tx, txMeta, txTime, pp) liftIO $ mkApiTransaction (timeInterpreter (ctx ^. networkLayer)) @@ -2561,6 +2589,7 @@ joinStakePool ctx knownPools getPoolStatus apiPoolId (ApiT wid) body = do , txMetadata = Nothing , txTime , txScriptValidity = tx ^. #scriptValidity + , txDeposit = W.stakeKeyDeposit pp } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) @@ -2624,7 +2653,7 @@ quitStakePool quitStakePool ctx (ApiT wid) body = do let pwd = coerce $ getApiT $ body ^. #passphrase - (sel, tx, txMeta, txTime) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do + (sel, tx, txMeta, txTime, pp) <- withWorkerCtx ctx wid liftE liftE $ \wrk -> do action <- liftHandler $ W.quitStakePool @_ @s @k wrk wid @@ -2659,7 +2688,7 @@ quitStakePool ctx (ApiT wid) body = do liftHandler $ W.submitTx @_ @s @k wrk wid (tx, txMeta, sealedTx) - pure (sel, tx, txMeta, txTime) + pure (sel, tx, txMeta, txTime, pp) liftIO $ mkApiTransaction (timeInterpreter (ctx ^. networkLayer)) @@ -2676,6 +2705,7 @@ quitStakePool ctx (ApiT wid) body = do , txMetadata = Nothing , txTime , txScriptValidity = tx ^. #scriptValidity + , txDeposit = W.stakeKeyDeposit pp } where ti :: TimeInterpreter (ExceptT PastHorizonException IO) @@ -2899,6 +2929,7 @@ migrateWallet ctx withdrawalType (ApiT wid) postData = do withWorkerCtx ctx wid liftE liftE $ \wrk -> do plan <- liftHandler $ W.createMigrationPlan wrk wid rewardWithdrawal txTimeToLive <- liftIO $ W.getTxExpiry ti Nothing + pp <- liftIO $ NW.currentProtocolParameters (wrk ^. networkLayer) selectionWithdrawals <- liftHandler $ failWith ErrCreateMigrationPlanEmpty $ W.migrationPlanToSelectionWithdrawals @@ -2930,6 +2961,7 @@ migrateWallet ctx withdrawalType (ApiT wid) postData = do , txMetadata = Nothing , txTime , txScriptValidity = tx ^. #scriptValidity + , txDeposit = W.stakeKeyDeposit pp } where addresses = getApiT . fst <$> view #addresses postData @@ -3332,6 +3364,7 @@ data MkApiTransactionParams = MkApiTransactionParams , txMetadata :: Maybe W.TxMetadata , txTime :: UTCTime , txScriptValidity :: Maybe W.TxScriptValidity + , txDeposit :: Coin } deriving (Eq, Generic, Show) @@ -3362,7 +3395,8 @@ mkApiTransaction timeInterpreter setTimeReference tx = do { id = ApiT $ tx ^. #txId , amount = Quantity . fromIntegral $ tx ^. (#txMeta . #amount . #unCoin) , fee = Quantity $ maybe 0 (fromIntegral . unCoin) (tx ^. #txFee) - , deposit = Quantity depositIfAny + , depositTaken = Quantity depositIfAny + , depositReturned = Quantity reclaimIfAny , insertedAt = Nothing , pendingSince = Nothing , expiresAt = Nothing @@ -3386,58 +3420,51 @@ mkApiTransaction timeInterpreter setTimeReference tx = do depositIfAny :: Natural depositIfAny - -- NOTE: totalIn will be zero for incoming transactions where inputs are - -- unknown, in which case, we also give no visibility on the deposit. - -- - -- For outgoing transactions however, the totalIn is guaranteed to be - -- greater or equal to totalOut; any remainder is actually a - -- deposit. Said differently, if totalIn > 0, then necessarily 'fee' on - -- metadata should be 'Just{}' | tx ^. (#txMeta . #direction) == W.Outgoing = if totalIn < totalOut - then 0 -- This should not be possible in practice. See FIXME below. + then 0 else totalIn - totalOut | otherwise = 0 - where - -- FIXME: ADP-460 - -- - -- In theory, the input side can't be smaller than the output side. - -- However, since we do not yet track 'reclaims', we may end up in - -- situation here where we no longer know that there's a reclaim on a - -- transaction and numbers do not add up. Ideally, we would like to - -- change the `then` clause above to be `invariantViolation` instead of - -- `0` but we can't do that until we acknowledge for reclaims up until - -- here too. - -- - -- `0` is an okay-ish placeholder in the meantime because we know that - -- (at least at the moment of writing this comment) the wallet never - -- registers a key and deregister a key at the same time. Thus, if we - -- are in the case where the apparent totalIn is smaller than the - -- total out, then necessary the deposit is null. - -- - -- invariantViolation :: HasCallStack => a - -- invariantViolation = error $ unlines - -- [ "invariant violated: outputs larger than inputs" - -- , "direction: " <> show (meta ^. #direction) - -- , "fee: " <> show (getQuantity <$> (meta ^. #fee)) - -- , "inputs: " <> show (fmap (view (#coin . #unCoin)) . snd <$> ins) - -- , "reclaims: " <> ... - -- , "withdrawals: " <> show (view #unCoin <$> Map.elems ws) - -- , "outputs: " <> show (view (#coin . #unCoin) <$> outs) - -- ] - totalIn :: Natural - totalIn - = sum (txOutValue <$> mapMaybe snd (tx ^. #txInputs)) - + sum (fromIntegral . unCoin <$> Map.elems (tx ^. #txWithdrawals)) - -- FIXME: ADP-460 + reclaims. - - totalOut :: Natural - totalOut - = sum (txOutValue <$> tx ^. #txOutputs) - + maybe 0 (fromIntegral . unCoin) (tx ^. #txFee) - - txOutValue :: TxOut -> Natural - txOutValue = fromIntegral . unCoin . txOutCoin + + -- (pending) when reclaim is coming we have (fee+out) - inp = deposit + -- tx is incoming, and the wallet spent for fee and received deposit - fee as out + -- (inLedger) when reclaim is accomodated we have out - inp < deposit as fee was incurred + -- So in order to detect this we need to have + -- 1. deposit + -- 2. have inpsWithoutFee of the wallet non-empty + -- 3. outs of the wallet non-empty + -- 4. tx Incoming + -- 5. outs - inpsWithoutFee <= deposit + -- assumption: this should work when + depositValue :: Natural + depositValue = fromIntegral . unCoin $ tx ^. #txDeposit + + reclaimIfAny :: Natural + reclaimIfAny + | tx ^. (#txMeta . #direction) == W.Incoming = + if ( totalInWithoutFee > 0 && totalOut > 0 && totalOut > totalInWithoutFee) + && (totalOut - totalInWithoutFee <= depositValue) then + depositValue + else + 0 + | otherwise = 0 + + totalInWithoutFee :: Natural + totalInWithoutFee + = sum (txOutValue <$> mapMaybe snd (tx ^. #txInputs)) + + totalIn :: Natural + totalIn + = sum (txOutValue <$> mapMaybe snd (tx ^. #txInputs)) + + sum (fromIntegral . unCoin <$> Map.elems (tx ^. #txWithdrawals)) + + totalOut :: Natural + totalOut + = sum (txOutValue <$> tx ^. #txOutputs) + + maybe 0 (fromIntegral . unCoin) (tx ^. #txFee) + + txOutValue :: TxOut -> Natural + txOutValue = fromIntegral . unCoin . txOutCoin toAddressAmountNoAssets :: TxOut @@ -4022,6 +4049,12 @@ instance IsServerError ErrSubmitTransaction where , " inputs and ", toText foundWitsNo, " witnesses included." , " Submit fully-signed transaction." ] + ErrSubmitTransactionMultidelegationNotSupported -> + apiError err403 CreatedMultidelegationTransaction $ mconcat + [ "It looks like the transaction to be sent contains" + , "multiple delegations, which is not supported at this moment." + , "Please use at most one delegation action in a submitted transaction: join, quit or none." + ] instance IsServerError ErrSubmitTx where toServerError = \case diff --git a/lib/core/src/Cardano/Wallet/Api/Types.hs b/lib/core/src/Cardano/Wallet/Api/Types.hs index 1a4c87089dd..190d0b41a5b 100644 --- a/lib/core/src/Cardano/Wallet/Api/Types.hs +++ b/lib/core/src/Cardano/Wallet/Api/Types.hs @@ -1119,7 +1119,8 @@ data ApiTransaction (n :: NetworkDiscriminant) = ApiTransaction { id :: !(ApiT (Hash "Tx")) , amount :: !(Quantity "lovelace" Natural) , fee :: !(Quantity "lovelace" Natural) - , deposit :: !(Quantity "lovelace" Natural) + , depositTaken :: !(Quantity "lovelace" Natural) + , depositReturned :: !(Quantity "lovelace" Natural) , insertedAt :: !(Maybe ApiBlockReference) , pendingSince :: !(Maybe ApiBlockReference) , expiresAt :: !(Maybe ApiSlotReference) diff --git a/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json b/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json index 2e1931dfc8a..fb241a89d83 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json +++ b/lib/core/test/data/Cardano/Wallet/Api/ApiTransactionTestnet0.json @@ -1,213 +1,347 @@ { - "seed": 272315937488619540, + "seed": -2791462040846799902, "samples": [ { - "status": "pending", + "status": "in_ledger", "withdrawals": [], + "deposit_taken": { + "quantity": 40, + "unit": "lovelace" + }, "inputs": [], - "direction": "incoming", + "direction": "outgoing", "outputs": [], - "expires_at": { - "epoch_number": 17148, - "time": "1868-11-22T10:00:00Z", - "absolute_slot_number": 799355, - "slot_number": 32144 - }, - "script_validity": "valid", - "id": "2901737c27ff46576160b35d0c101b675d60595211633920056b4b5d17bc2248", + "script_validity": "invalid", + "id": "5cd94a260f655ae57a06645b762e2b5d54742d2d4f7968177c153f5143d86e9c", "depth": { - "quantity": 14602, + "quantity": 4765, "unit": "block" }, "amount": { - "quantity": 201, + "quantity": 45, "unit": "lovelace" }, + "inserted_at": { + "height": { + "quantity": 3484, + "unit": "block" + }, + "epoch_number": 1432, + "time": "1902-12-19T08:20:08Z", + "absolute_slot_number": 2913850, + "slot_number": 19374 + }, "fee": { - "quantity": 84, + "quantity": 192, "unit": "lovelace" }, - "metadata": { - "12": { - "int": 0 - } - }, - "deposit": { - "quantity": 135, + "deposit_returned": { + "quantity": 56, "unit": "lovelace" }, + "metadata": null, "collateral": [], "mint": [ { "asset_name": "546f6b656e43", - "quantity": 19, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "quantity": 3, + "policy_id": "33333333333333333333333333333333333333333333333333333333" }, { "asset_name": "546f6b656e44", - "quantity": 8, + "quantity": 25, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + } + ] + }, + { + "status": "pending", + "withdrawals": [], + "deposit_taken": { + "quantity": 137, + "unit": "lovelace" + }, + "inputs": [], + "direction": "incoming", + "outputs": [], + "expires_at": { + "epoch_number": 7444, + "time": "1896-04-14T18:32:37Z", + "absolute_slot_number": 8436301, + "slot_number": 2239 + }, + "script_validity": "valid", + "pending_since": { + "height": { + "quantity": 19474, + "unit": "block" + }, + "epoch_number": 23943, + "time": "1894-05-24T10:34:48.232680961581Z", + "absolute_slot_number": 10168801, + "slot_number": 9156 + }, + "id": "0d69061019316b17940f74dc4f2027330c4a19633468fb20196223496e7cc70a", + "amount": { + "quantity": 14, + "unit": "lovelace" + }, + "fee": { + "quantity": 29, + "unit": "lovelace" + }, + "deposit_returned": { + "quantity": 61, + "unit": "lovelace" + }, + "metadata": null, + "collateral": [], + "mint": [ + { + "asset_name": "546f6b656e44", + "quantity": 29, "policy_id": "00000000000000000000000000000000000000000000000000000000" }, { "asset_name": "546f6b656e45", - "quantity": 12, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "quantity": 21, + "policy_id": "11111111111111111111111111111111111111111111111111111111" }, { "asset_name": "546f6b656e41", - "quantity": 31, - "policy_id": "11111111111111111111111111111111111111111111111111111111" + "quantity": 46, + "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { "asset_name": "546f6b656e43", "quantity": 11, - "policy_id": "11111111111111111111111111111111111111111111111111111111" - }, - { - "asset_name": "546f6b656e44", - "quantity": 28, - "policy_id": "11111111111111111111111111111111111111111111111111111111" + "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { "asset_name": "546f6b656e41", - "quantity": 9, + "quantity": 28, "policy_id": "33333333333333333333333333333333333333333333333333333333" }, { - "asset_name": "546f6b656e42", + "asset_name": "546f6b656e43", "quantity": 8, "policy_id": "33333333333333333333333333333333333333333333333333333333" }, { - "asset_name": "546f6b656e45", - "quantity": 14, + "asset_name": "546f6b656e44", + "quantity": 25, "policy_id": "33333333333333333333333333333333333333333333333333333333" }, { "asset_name": "546f6b656e41", - "quantity": 25, + "quantity": 19, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e42", + "quantity": 23, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e44", + "quantity": 12, "policy_id": "44444444444444444444444444444444444444444444444444444444" }, { "asset_name": "546f6b656e45", - "quantity": 4, + "quantity": 26, "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] }, { - "status": "in_ledger", + "status": "pending", "withdrawals": [], + "deposit_taken": { + "quantity": 54, + "unit": "lovelace" + }, "inputs": [], "direction": "incoming", "outputs": [], - "id": "0bfa3e0641570251e41c02215657083c58086852d1297840ff427c634a464554", + "expires_at": { + "epoch_number": 19437, + "time": "1878-09-04T19:00:00Z", + "absolute_slot_number": 10435892, + "slot_number": 16635 + }, + "script_validity": "invalid", + "pending_since": { + "height": { + "quantity": 28567, + "unit": "block" + }, + "epoch_number": 15066, + "time": "1878-01-28T18:03:01.212267454228Z", + "absolute_slot_number": 11344158, + "slot_number": 19846 + }, + "id": "25c05f320a175a73667d31086d6520744f3d606d35062268737c6c4a36371344", "depth": { - "quantity": 1412, + "quantity": 16365, "unit": "block" }, "amount": { - "quantity": 164, + "quantity": 211, "unit": "lovelace" }, - "inserted_at": { - "height": { - "quantity": 5523, - "unit": "block" - }, - "epoch_number": 26668, - "time": "1874-02-16T10:29:06.479812124804Z", - "absolute_slot_number": 1372852, - "slot_number": 3220 - }, "fee": { - "quantity": 133, + "quantity": 23, + "unit": "lovelace" + }, + "deposit_returned": { + "quantity": 206, "unit": "lovelace" }, "metadata": { - "21": { - "map": [] + "3": { + "bytes": "19703b731e751c7a1d71e17b7cfd2ac16d1806" } }, - "deposit": { - "quantity": 70, - "unit": "lovelace" - }, "collateral": [], "mint": [ { - "asset_name": "546f6b656e45", + "asset_name": "546f6b656e42", + "quantity": 9, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e44", "quantity": 5, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e45", + "quantity": 1, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e43", + "quantity": 12, "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e45", + "quantity": 6, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e41", + "quantity": 21, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e42", + "quantity": 3, + "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] }, { "status": "expired", "withdrawals": [], + "deposit_taken": { + "quantity": 255, + "unit": "lovelace" + }, "inputs": [], "direction": "outgoing", "outputs": [], "expires_at": { - "epoch_number": 13025, - "time": "1863-08-11T00:10:54Z", - "absolute_slot_number": 15971135, - "slot_number": 21967 + "epoch_number": 23832, + "time": "1864-01-31T16:00:00Z", + "absolute_slot_number": 16598427, + "slot_number": 27109 }, - "script_validity": "valid", - "id": "059d2f78fde773120c170d2f5511eb0d335ad84101552919010b386c6a73c5d8", + "script_validity": "invalid", + "pending_since": { + "height": { + "quantity": 2521, + "unit": "block" + }, + "epoch_number": 5014, + "time": "1894-02-15T22:27:26.241292218612Z", + "absolute_slot_number": 2423739, + "slot_number": 16263 + }, + "id": "4466624a5ae34e6539ae07210d1d2d0d620201184236a34c497059f4723b1e3c", "depth": { - "quantity": 12219, + "quantity": 19285, "unit": "block" }, "amount": { - "quantity": 94, + "quantity": 27, "unit": "lovelace" }, "fee": { - "quantity": 20, + "quantity": 110, "unit": "lovelace" }, - "metadata": { - "6": { - "list": [ - { - "int": 3 - }, - { - "list": [ - { - "int": 0 - } - ] - } - ] - } - }, - "deposit": { - "quantity": 93, + "deposit_returned": { + "quantity": 64, "unit": "lovelace" }, + "metadata": null, "collateral": [], "mint": [ { "asset_name": "546f6b656e42", - "quantity": 28, - "policy_id": "22222222222222222222222222222222222222222222222222222222" + "quantity": 15, + "policy_id": "00000000000000000000000000000000000000000000000000000000" }, { "asset_name": "546f6b656e43", - "quantity": 14, + "quantity": 10, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e41", + "quantity": 7, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e43", + "quantity": 23, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e44", + "quantity": 53, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e43", + "quantity": 21, "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { - "asset_name": "546f6b656e42", - "quantity": 16, + "asset_name": "546f6b656e44", + "quantity": 29, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e41", + "quantity": 44, "policy_id": "33333333333333333333333333333333333333333333333333333333" }, { "asset_name": "546f6b656e41", - "quantity": 24, + "quantity": 6, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e43", + "quantity": 12, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e44", + "quantity": 2, "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] @@ -215,39 +349,83 @@ { "status": "in_ledger", "withdrawals": [], + "deposit_taken": { + "quantity": 143, + "unit": "lovelace" + }, "inputs": [], - "direction": "incoming", + "direction": "outgoing", "outputs": [], - "script_validity": "invalid", - "id": "7f9cb80b5c060e11477f1c990c445f1ddd01742f73da76c346010c2772415b30", + "script_validity": "valid", + "id": "44654b6321552a025ebd700c364a4a3ca25b362670646e284455102d55096120", "amount": { - "quantity": 26, + "quantity": 109, "unit": "lovelace" }, "inserted_at": { "height": { - "quantity": 27796, + "quantity": 12715, "unit": "block" }, - "epoch_number": 25715, - "time": "1884-08-05T16:00:00Z", - "absolute_slot_number": 6214281, - "slot_number": 11435 + "epoch_number": 23458, + "time": "1877-12-07T16:00:00Z", + "absolute_slot_number": 9153268, + "slot_number": 15279 }, "fee": { - "quantity": 106, + "quantity": 100, "unit": "lovelace" }, - "metadata": null, - "deposit": { - "quantity": 236, + "deposit_returned": { + "quantity": 125, "unit": "lovelace" }, + "metadata": null, "collateral": [], "mint": [ { "asset_name": "546f6b656e42", - "quantity": 6, + "quantity": 2, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e43", + "quantity": 25, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e42", + "quantity": 28, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e43", + "quantity": 31, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e44", + "quantity": 30, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e45", + "quantity": 20, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e44", + "quantity": 11, + "policy_id": "33333333333333333333333333333333333333333333333333333333" + }, + { + "asset_name": "546f6b656e42", + "quantity": 7, + "policy_id": "44444444444444444444444444444444444444444444444444444444" + }, + { + "asset_name": "546f6b656e43", + "quantity": 14, "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] @@ -255,152 +433,128 @@ { "status": "in_ledger", "withdrawals": [], + "deposit_taken": { + "quantity": 163, + "unit": "lovelace" + }, "inputs": [], - "direction": "outgoing", + "direction": "incoming", "outputs": [], - "id": "3918406a71117509676c681a014cbbb92703564609015f44c903107652b15e21", + "script_validity": "valid", + "id": "50a0134736695501367dc927c6634b3b45223423270c584607300a6750600978", "amount": { - "quantity": 223, + "quantity": 232, "unit": "lovelace" }, "fee": { - "quantity": 64, + "quantity": 102, "unit": "lovelace" }, - "metadata": { - "21": { - "list": [ - { - "map": [ - { - "k": { - "string": "Ͽ𭒈" - }, - "v": { - "string": "" - } - }, - { - "k": { - "string": "󷣨" - }, - "v": { - "int": 0 - } - } - ] - } - ] - } - }, - "deposit": { - "quantity": 154, + "deposit_returned": { + "quantity": 6, "unit": "lovelace" }, + "metadata": null, "collateral": [], "mint": [ + { + "asset_name": "546f6b656e41", + "quantity": 30, + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e42", + "quantity": 22, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, { "asset_name": "546f6b656e44", - "quantity": 25, + "quantity": 5, "policy_id": "22222222222222222222222222222222222222222222222222222222" } ] }, { - "status": "in_ledger", + "status": "expired", "withdrawals": [], + "deposit_taken": { + "quantity": 160, + "unit": "lovelace" + }, "inputs": [], "direction": "outgoing", "outputs": [], - "script_validity": "valid", - "id": "503d261c2ac53a2b087ba516270e7949921127619e2a492a45db522a514d2f00", - "depth": { - "quantity": 10258, - "unit": "block" + "expires_at": { + "epoch_number": 16784, + "time": "1861-11-04T23:06:37.509000944475Z", + "absolute_slot_number": 3861870, + "slot_number": 18058 }, + "script_validity": "valid", + "id": "4040f12832615f42704a1a4213b2230e742e5710c68e764d33464e587d13566d", "amount": { - "quantity": 221, + "quantity": 184, "unit": "lovelace" }, - "inserted_at": { - "height": { - "quantity": 21469, - "unit": "block" - }, - "epoch_number": 329, - "time": "1895-02-26T01:00:00Z", - "absolute_slot_number": 11342127, - "slot_number": 29219 - }, "fee": { - "quantity": 171, + "quantity": 128, "unit": "lovelace" }, - "metadata": { - "4": { - "list": [ - { - "string": "𗓾𩮋𬵴" - }, - { - "list": [ - { - "string": "瑱􇢃" - } - ] - } - ] - } - }, - "deposit": { - "quantity": 101, + "deposit_returned": { + "quantity": 19, "unit": "lovelace" }, + "metadata": null, "collateral": [], "mint": [ { - "asset_name": "546f6b656e41", - "quantity": 30, + "asset_name": "546f6b656e45", + "quantity": 26, "policy_id": "00000000000000000000000000000000000000000000000000000000" }, { - "asset_name": "546f6b656e42", - "quantity": 19, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "asset_name": "546f6b656e41", + "quantity": 20, + "policy_id": "11111111111111111111111111111111111111111111111111111111" }, { - "asset_name": "546f6b656e45", - "quantity": 1, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "asset_name": "546f6b656e43", + "quantity": 42, + "policy_id": "11111111111111111111111111111111111111111111111111111111" }, { - "asset_name": "546f6b656e44", - "quantity": 23, - "policy_id": "11111111111111111111111111111111111111111111111111111111" + "asset_name": "546f6b656e41", + "quantity": 28, + "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { - "asset_name": "546f6b656e44", - "quantity": 16, + "asset_name": "546f6b656e43", + "quantity": 29, "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { "asset_name": "546f6b656e41", - "quantity": 43, + "quantity": 58, "policy_id": "33333333333333333333333333333333333333333333333333333333" }, { "asset_name": "546f6b656e43", - "quantity": 30, + "quantity": 12, "policy_id": "33333333333333333333333333333333333333333333333333333333" }, { - "asset_name": "546f6b656e41", - "quantity": 17, + "asset_name": "546f6b656e44", + "quantity": 6, + "policy_id": "33333333333333333333333333333333333333333333333333333333" + }, + { + "asset_name": "546f6b656e44", + "quantity": 5, "policy_id": "44444444444444444444444444444444444444444444444444444444" }, { - "asset_name": "546f6b656e42", - "quantity": 1, + "asset_name": "546f6b656e45", + "quantity": 49, "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] @@ -408,169 +562,185 @@ { "status": "in_ledger", "withdrawals": [], + "deposit_taken": { + "quantity": 146, + "unit": "lovelace" + }, "inputs": [], "direction": "outgoing", "outputs": [], - "id": "692ef54f08267a6b6278d4180a215dac1c39ab0d2555fc1a072bdd764210ad22", + "script_validity": "invalid", + "id": "48116e11d6424e0f5e0e251268631f3c7f11203a4b451c6cf8f0716146790d68", "depth": { - "quantity": 21260, + "quantity": 19400, "unit": "block" }, "amount": { - "quantity": 166, + "quantity": 4, "unit": "lovelace" }, "fee": { - "quantity": 191, + "quantity": 223, + "unit": "lovelace" + }, + "deposit_returned": { + "quantity": 148, "unit": "lovelace" }, "metadata": { - "7": { - "string": "󺘿" + "23": { + "int": 0 } }, - "deposit": { - "quantity": 153, - "unit": "lovelace" - }, "collateral": [], "mint": [] }, { "status": "in_ledger", "withdrawals": [], + "deposit_taken": { + "quantity": 1, + "unit": "lovelace" + }, "inputs": [], - "direction": "incoming", + "direction": "outgoing", "outputs": [], - "script_validity": "invalid", - "id": "771664396a145a76608d763a5d2536d5a51f445c5367482e2c46750848a5cc4b", + "id": "5e4c4b0c7d747927012ff05c2401aa2f6a61032612431678f129f80d2c4d4d0b", "depth": { - "quantity": 18429, + "quantity": 1507, "unit": "block" }, "amount": { - "quantity": 227, + "quantity": 71, "unit": "lovelace" }, "fee": { - "quantity": 192, + "quantity": 101, + "unit": "lovelace" + }, + "deposit_returned": { + "quantity": 178, "unit": "lovelace" }, "metadata": { - "22": { - "map": [] + "2": { + "map": [ + { + "k": { + "string": "𝦫" + }, + "v": { + "map": [ + { + "k": { + "string": "𑨨ﻴ" + }, + "v": { + "string": "􃘘🮀" + } + } + ] + } + } + ] } }, - "deposit": { - "quantity": 205, - "unit": "lovelace" - }, "collateral": [], "mint": [ { - "asset_name": "546f6b656e45", + "asset_name": "546f6b656e43", "quantity": 12, - "policy_id": "44444444444444444444444444444444444444444444444444444444" + "policy_id": "00000000000000000000000000000000000000000000000000000000" + }, + { + "asset_name": "546f6b656e41", + "quantity": 9, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e41", + "quantity": 22, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e43", + "quantity": 30, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e44", + "quantity": 9, + "policy_id": "22222222222222222222222222222222222222222222222222222222" + }, + { + "asset_name": "546f6b656e42", + "quantity": 7, + "policy_id": "33333333333333333333333333333333333333333333333333333333" + }, + { + "asset_name": "546f6b656e43", + "quantity": 18, + "policy_id": "33333333333333333333333333333333333333333333333333333333" } ] }, { - "status": "expired", + "status": "in_ledger", "withdrawals": [], + "deposit_taken": { + "quantity": 71, + "unit": "lovelace" + }, "inputs": [], - "direction": "incoming", + "direction": "outgoing", "outputs": [], - "expires_at": { - "epoch_number": 9919, - "time": "1900-12-05T08:06:34.56474251296Z", - "absolute_slot_number": 15804468, - "slot_number": 20347 + "script_validity": "valid", + "id": "126a6f4a1a596303476a311e5d6634f3fe6ab3be965e645a7b36244a395f1926", + "amount": { + "quantity": 195, + "unit": "lovelace" }, - "script_validity": "invalid", - "pending_since": { + "inserted_at": { "height": { - "quantity": 16276, + "quantity": 24498, "unit": "block" }, - "epoch_number": 25641, - "time": "1903-01-31T00:00:00Z", - "absolute_slot_number": 16670178, - "slot_number": 22729 - }, - "id": "4744153cca880d3b57627173635964270338412e2ad65c6060344d5309e60604", - "depth": { - "quantity": 7077, - "unit": "block" - }, - "amount": { - "quantity": 205, - "unit": "lovelace" + "epoch_number": 28531, + "time": "1880-06-19T13:00:00Z", + "absolute_slot_number": 16034426, + "slot_number": 14318 }, "fee": { - "quantity": 115, + "quantity": 109, "unit": "lovelace" }, - "metadata": null, - "deposit": { - "quantity": 61, + "deposit_returned": { + "quantity": 87, "unit": "lovelace" }, + "metadata": { + "1": { + "bytes": "715f4b09377fda687b652b6d0b4079022312188849851a77041c065e535a4528113f445a" + } + }, "collateral": [], "mint": [ { - "asset_name": "546f6b656e41", - "quantity": 7, - "policy_id": "00000000000000000000000000000000000000000000000000000000" + "asset_name": "546f6b656e44", + "quantity": 26, + "policy_id": "11111111111111111111111111111111111111111111111111111111" + }, + { + "asset_name": "546f6b656e44", + "quantity": 5, + "policy_id": "22222222222222222222222222222222222222222222222222222222" }, { "asset_name": "546f6b656e42", - "quantity": 28, + "quantity": 3, "policy_id": "44444444444444444444444444444444444444444444444444444444" } ] - }, - { - "status": "expired", - "withdrawals": [], - "inputs": [], - "direction": "outgoing", - "outputs": [], - "expires_at": { - "epoch_number": 4167, - "time": "1906-04-09T21:00:00Z", - "absolute_slot_number": 14198707, - "slot_number": 27063 - }, - "pending_since": { - "height": { - "quantity": 23346, - "unit": "block" - }, - "epoch_number": 28224, - "time": "1899-05-04T13:19:30.25623172511Z", - "absolute_slot_number": 3927793, - "slot_number": 32478 - }, - "id": "330122712731461a1324bd422e1a6f51700e0e701b79695d625eba632301614a", - "depth": { - "quantity": 31290, - "unit": "block" - }, - "amount": { - "quantity": 188, - "unit": "lovelace" - }, - "fee": { - "quantity": 21, - "unit": "lovelace" - }, - "metadata": null, - "deposit": { - "quantity": 203, - "unit": "lovelace" - }, - "collateral": [], - "mint": [] } ] } \ No newline at end of file diff --git a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs index e67661e8abb..4ea90875d5c 100644 --- a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -1113,7 +1113,9 @@ spec = parallel $ do (x :: ApiTransaction ('Testnet 0)) , fee = fee (x :: ApiTransaction ('Testnet 0)) - , deposit = deposit + , depositTaken = depositTaken + (x :: ApiTransaction ('Testnet 0)) + , depositReturned = depositReturned (x :: ApiTransaction ('Testnet 0)) , insertedAt = insertedAt (x :: ApiTransaction ('Testnet 0)) @@ -2379,6 +2381,7 @@ instance Arbitrary (ApiTransaction n) where <*> arbitrary <*> arbitrary <*> arbitrary + <*> arbitrary <*> pure txInsertedAt <*> pure txPendingSince <*> pure txExpiresAt diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index 2057efef6d1..312259640e2 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -2424,7 +2424,8 @@ components: - id - amount - fee - - deposit + - deposit_taken + - deposit_returned - direction - inputs - outputs @@ -2445,7 +2446,8 @@ components: For incoming transaction, it represents the total amount of Ada received to addresses that belong to the wallet. fee: *amount - deposit: *amount + deposit_taken: *amount + deposit_returned: *amount inserted_at: *transactionInsertedAt expires_at: *transactionExpiresAt pending_since: *transactionPendingSince @@ -5176,6 +5178,7 @@ x-responsesSubmitTransaction: &responsesSubmitTransaction oneOf: - <<: *errForeignTransaction - <<: *errMissingWitnessesInTransaction + - <<: *errCreatedMultidelegationTransaction x-responsesPostExternalTransaction: &responsesPostExternalTransaction <<: *responsesErr400