diff --git a/flake.lock b/flake.lock index 2f07b6abcb0..1a7078e8cef 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ "CHaP_2": { "flake": false, "locked": { - "lastModified": 1727170555, - "narHash": "sha256-kxB/xjSjqym5kKYDw/CZMb6O1OfCVWRjjsuqyWABd0w=", + "lastModified": 1730295876, + "narHash": "sha256-ijnHTQ6eKIQ9FpEqDKt6c7vuFYN8aOBDhonp67utx2s=", "owner": "intersectmbo", "repo": "cardano-haskell-packages", - "rev": "d8beaf7e30330f8a70e626f63a5b47d1999fbf4b", + "rev": "25591f43ab943d5a070db5e8a2b9ff3a499d4d92", "type": "github" }, "original": { @@ -319,11 +319,11 @@ "utils": "utils_2" }, "locked": { - "lastModified": 1727221818, - "narHash": "sha256-i582YpBy+hBth73JqfcjGFsJrTQeDG0NJ7vN8JLWeoI=", + "lastModified": 1730468447, + "narHash": "sha256-yNEv7MQEcOPY9I9k9RCzeMfJY6gzuGc7K53GKNHs6v8=", "owner": "IntersectMBO", "repo": "cardano-node", - "rev": "5d3da8ac771ee5ed424d6c78473c11deabb7a1f3", + "rev": "01bda2e2cb0a70cd95067d696dbb44665f1d680a", "type": "github" }, "original": { @@ -791,11 +791,11 @@ "hackageNix": { "flake": false, "locked": { - "lastModified": 1725928375, - "narHash": "sha256-XO/6kJ77bR99bAuRGr9PleQX75vde5CbSU+6Xf3e8NQ=", + "lastModified": 1729039425, + "narHash": "sha256-sIglYcw8Dacj4n0bRlUWo+NLkDMcVi6vtmKvUyG+ZrQ=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "68cfb288b958e9d7a1329df614684132f44bd2b3", + "rev": "6dc43e5e01f113ce151056a8f94bce7bb2f13eb9", "type": "github" }, "original": { @@ -828,7 +828,6 @@ "hls-2.6": "hls-2.6", "hls-2.7": "hls-2.7", "hls-2.8": "hls-2.8", - "hls-2.9": "hls-2.9", "hpc-coveralls": "hpc-coveralls", "hydra": "hydra", "iserv-proxy": "iserv-proxy", @@ -858,6 +857,7 @@ "original": { "owner": "input-output-hk", "repo": "haskell.nix", + "rev": "cb139fa956158397aa398186bb32dd26f7318784", "type": "github" } }, @@ -882,7 +882,7 @@ "hls-2.6": "hls-2.6_2", "hls-2.7": "hls-2.7_2", "hls-2.8": "hls-2.8_2", - "hls-2.9": "hls-2.9_2", + "hls-2.9": "hls-2.9", "hpc-coveralls": "hpc-coveralls_2", "hydra": "hydra_2", "iserv-proxy": "iserv-proxy_2", @@ -1245,23 +1245,6 @@ } }, "hls-2.9": { - "flake": false, - "locked": { - "lastModified": 1718469202, - "narHash": "sha256-qnDx8Pk0UxtoPr7BimEsAZh9g2WuTuMB/kGqnmdryKs=", - "owner": "haskell", - "repo": "haskell-language-server", - "rev": "0c1817cb2babef0765e4e72dd297c013e8e3d12b", - "type": "github" - }, - "original": { - "owner": "haskell", - "ref": "2.9.0.1", - "repo": "haskell-language-server", - "type": "github" - } - }, - "hls-2.9_2": { "flake": false, "locked": { "lastModified": 1718469202, @@ -1390,11 +1373,11 @@ "sodium": "sodium" }, "locked": { - "lastModified": 1721825987, - "narHash": "sha256-PPcma4tjozwXJAWf+YtHUQUulmxwulVlwSQzKItx/n8=", + "lastModified": 1728687575, + "narHash": "sha256-38uD8SqT557eh5yyRYuthKm1yTtiWzAN0FH7L/01QKM=", "owner": "input-output-hk", "repo": "iohk-nix", - "rev": "eb61f2c14e1f610ec59117ad40f8690cddbf80cb", + "rev": "86c2bd46e8a08f62ea38ffe77cb4e9c337b42217", "type": "github" }, "original": { diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs b/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs index 3946eac88d6..2c08065bd9c 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs @@ -663,6 +663,7 @@ import Cardano.Wallet.Transaction , Withdrawal (..) , WitnessCount (..) , WitnessCountCtx (..) + , containsSelfWithdrawal , defaultTransactionCtx ) import Cardano.Wallet.Unsafe @@ -2289,6 +2290,8 @@ postTransactionOld ctx@ApiLayer{..} argGenChange (ApiT wid) body = do let outs = addressAmountToTxOut <$> body ^. #payments let md = body ^? #metadata . traverse . #txMetadataWithSchema_metadata let mTTL = body ^? #timeToLive . traverse . #getQuantity + (Write.PParamsInAnyRecentEra era _, _) + <- liftIO $ W.readNodeTipStateForTxWrite netLayer withWorkerCtx ctx wid liftE liftE $ \wrk -> do let db = wrk ^. dbLayer ttl <- liftIO $ W.transactionExpirySlot ti mTTL @@ -2300,6 +2303,8 @@ postTransactionOld ctx@ApiLayer{..} argGenChange (ApiT wid) body = do (txWitnessTagForKey $ keyOfWallet $ walletFlavor @s) db apiWdrl + when (containsSelfWithdrawal wdrl) $ + liftHandler $ W.assertIsVoting db era let txCtx = defaultTransactionCtx { txWithdrawal = wdrl , txMetadata = md diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs index 6134e95dfc5..18f10dad8be 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Shelley/TransactionsNew.hs @@ -3207,7 +3207,8 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do }) decodeErrorInfo submittedMaryTxExternal `shouldBe` errInfo - it "TRANS_NEW_JOIN_01a - Can join stakepool, rejoin another and quit" $ \ctx -> runResourceT $ do + it "TRANS_NEW_JOIN_01a - Can join stakepool, rejoin another and quit without voting in Babbage - old tx workflow" $ \ctx -> runResourceT $ do + noConway ctx "withdraw possible" let initialAmt = 10 * minUTxOValue (_mainEra ctx) src <- fixtureWalletWith @n ctx [initialAmt] dest <- emptyWallet ctx @@ -3478,6 +3479,392 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do , expectField #depositReturned (`shouldBe` depositAmt) ] + it "TRANS_NEW_JOIN_01a - Can join stakepool, rejoin another but not withdraw without voting in Conway - old tx workflow" $ \ctx -> runResourceT $ do + noBabbage ctx "withdraw not possible if we have not voted" + let initialAmt = 10 * minUTxOValue (_mainEra ctx) + src <- fixtureWalletWith @n ctx [initialAmt] + dest <- emptyWallet ctx + + let depositAmt = ApiAmount 1_000_000 + + pool1 : pool2 : _ <- map (view #id) <$> notRetiringPools ctx + + let delegationJoin = Json [json|{ + "delegations": [{ + "join": { + "pool": #{ApiT pool1}, + "stake_key_index": "0H" + } + }] + }|] + rTx1 <- request @(ApiConstructTransaction n) ctx + (Link.createUnsignedTransaction @'Shelley src) Default delegationJoin + verify rTx1 + [ expectResponseCode HTTP.status202 + , expectField (#coinSelection . #depositsTaken) (`shouldBe` [depositAmt]) + , expectField (#coinSelection . #depositsReturned) (`shouldBe` []) + ] + + let ApiSerialisedTransaction apiTx1 _ = getFromResponse #transaction rTx1 + signedTx1 <- signTx ctx src apiTx1 [ expectResponseCode HTTP.status202 ] + + -- as we are joining for the first time we expect two certificates + let stakeKeyDerPath = NE.fromList + [ ApiT (DerivationIndex 2_147_485_500) + , ApiT (DerivationIndex 2_147_485_463) + , ApiT (DerivationIndex 2_147_483_648) + , ApiT (DerivationIndex 2) + , ApiT (DerivationIndex 0) + ] + let registerStakeKeyCert = + WalletDelegationCertificate $ RegisterRewardAccount stakeKeyDerPath + let delegatingCert = + WalletDelegationCertificate $ JoinPool stakeKeyDerPath (ApiT pool1) + + let decodePayload1 = Json (toJSON signedTx1) + rDecodedTx1 <- request @(ApiDecodedTransaction n) ctx + (Link.decodeTransaction @'Shelley src) Default decodePayload1 + verify rDecodedTx1 + [ expectResponseCode HTTP.status202 + , expectField #certificates (`shouldBe` [registerStakeKeyCert, delegatingCert]) + , expectField #depositsTaken (`shouldBe` [depositAmt]) + , expectField #depositsReturned (`shouldBe` []) + ] + + -- Submit tx + submittedTx1 <- submitTxWithWid ctx src signedTx1 + verify submittedTx1 + [ expectSuccess + , expectResponseCode HTTP.status202 + ] + + eventually "Wallet has joined pool and deposit info persists" $ do + rJoin' <- request @(ApiTransaction n) ctx + (Link.getTransaction @'Shelley src + (getResponse submittedTx1)) + Default Empty + verify rJoin' + [ expectResponseCode HTTP.status200 + , expectField (#status . #getApiT) (`shouldBe` InLedger) + , expectField (#direction . #getApiT) (`shouldBe` Outgoing) + , expectField #depositTaken (`shouldBe` depositAmt) + , expectField #depositReturned (`shouldBe` ApiAmount 0) + ] + + let txId1 = getFromResponse #id submittedTx1 + let link = Link.getTransaction @'Shelley src (ApiTxId txId1) + eventually "delegation transaction is in ledger" $ do + request @(ApiTransaction n) ctx link Default Empty + >>= flip verify + [ expectResponseCode HTTP.status200 + , expectField (#direction . #getApiT) (`shouldBe` Outgoing) + , expectField (#status . #getApiT) (`shouldBe` InLedger) + , expectField #metadata (`shouldBe` Nothing) + , expectField #inputs (`shouldSatisfy` all (isJust . source)) + ] + + waitNumberOfEpochBoundaries 2 ctx + + let getSrcWallet = + let endpoint = Link.getWallet @'Shelley src + in request @ApiWallet ctx endpoint Default Empty + + eventually "Wallet is delegating to pool1" $ do + getSrcWallet >>= flip verify + [ expectField #delegation (`shouldBe` delegating (ApiT pool1) []) + ] + + waitNumberOfEpochBoundaries 2 ctx + + eventually "Wallet gets rewards from pool1" $ do + getSrcWallet >>= flip verify + [ expectField (#balance . #reward) (.> ApiAmount 0) ] + + -- join another stake pool + let delegationRejoin = Json [json|{ + "delegations": [{ + "join": { + "pool": #{ApiT pool2}, + "stake_key_index": "0H" + } + }] + }|] + rTx2 <- request @(ApiConstructTransaction n) ctx + (Link.createUnsignedTransaction @'Shelley src) Default delegationRejoin + verify rTx2 + [ expectResponseCode HTTP.status202 + , expectField (#coinSelection . #depositsTaken) (`shouldBe` []) + , expectField (#coinSelection . #depositsReturned) (`shouldBe` []) + ] + let ApiSerialisedTransaction apiTx2 _= getFromResponse #transaction rTx2 + signedTx2 <- signTx ctx src apiTx2 [ expectResponseCode HTTP.status202 ] + let delegatingCert2 = + WalletDelegationCertificate $ JoinPool stakeKeyDerPath (ApiT pool2) + + let decodePayload2 = Json (toJSON signedTx2) + rDecodedTx2 <- request @(ApiDecodedTransaction n) ctx + (Link.decodeTransaction @'Shelley src) Default decodePayload2 + verify rDecodedTx2 + [ expectResponseCode HTTP.status202 + , expectField #certificates (`shouldBe` [delegatingCert2]) + , expectField #depositsTaken (`shouldBe` []) + , expectField #depositsReturned (`shouldBe` []) + ] + submittedTx2 <- submitTxWithWid ctx src signedTx2 + verify submittedTx2 + [ expectSuccess + , expectResponseCode HTTP.status202 + ] + + let txid2 = getFromResponse #id submittedTx2 + let queryTx2 = Link.getTransaction @'Shelley src (ApiTxId txid2) + request @(ApiTransaction n) ctx queryTx2 Default Empty >>= flip verify + [ expectResponseCode HTTP.status200 + , expectField #depositTaken (`shouldBe` ApiAmount 0) + , expectField #depositReturned (`shouldBe` ApiAmount 0) + ] + + -- Wait for the certificate to be inserted + eventually "Certificates are inserted" $ do + let ep = Link.listTransactions @'Shelley src + request @[ApiTransaction n] ctx ep Default Empty >>= flip verify + [ expectListField 1 (#direction . #getApiT) (`shouldBe` Outgoing) + , expectListField 1 (#status . #getApiT) (`shouldBe` InLedger) + ] + + waitNumberOfEpochBoundaries 2 ctx + + eventually "Wallet is delegating to pool2" $ do + getSrcWallet >>= flip verify + [ expectField #delegation (`shouldBe` delegating (ApiT pool2) []) + ] + + -- there's currently no withdrawals in the wallet + rw1 <- request @[ApiTransaction n] ctx + (Link.listTransactions' @'Shelley src (Just 1) + Nothing Nothing Nothing Nothing Nothing) + Default Empty + verify rw1 [ expectListSize 0 ] + + waitForNextEpoch ctx + + addrs <- listAddresses @n ctx dest + let addr = (addrs !! 1) ^. #id + let withdrawalAmount = minUTxOValue (_mainEra ctx) + + withdrawalFailure <- do + let endpoint = Link.createTransactionOld @'Shelley src + request @(ApiTransaction n) ctx endpoint Default + $ Json [json| + { "payments": + [ { "address": #{addr} + , "amount": + { "quantity": #{withdrawalAmount} + , "unit": "lovelace" + } + } + ] + , "passphrase": #{fixturePassphrase}, + "withdrawal": "self" + }|] + + decodeErrorInfo withdrawalFailure `shouldBe` WithdrawalNotPossibleWithoutVote + + it "TRANS_NEW_JOIN_01b - Cannot withdraw without voting in Conway - new tx workflow" $ \ctx -> runResourceT $ do + noBabbage ctx "voting only Conway onwards" + let initialAmt = 10 * minUTxOValue (_mainEra ctx) + src <- fixtureWalletWith @n ctx [initialAmt] + dest <- emptyWallet ctx + + let depositAmt = ApiAmount 1_000_000 + + pool1 : _ <- map (view #id) <$> notRetiringPools ctx + + let delegationJoin = Json [json|{ + "delegations": [{ + "join": { + "pool": #{ApiT pool1}, + "stake_key_index": "0H" + } + }] + }|] + rTx <- request @(ApiConstructTransaction n) ctx + (Link.createUnsignedTransaction @'Shelley src) Default delegationJoin + verify rTx + [ expectResponseCode HTTP.status202 + , expectField (#coinSelection . #depositsTaken) (`shouldBe` [depositAmt]) + , expectField (#coinSelection . #depositsReturned) (`shouldBe` []) + ] + + let ApiSerialisedTransaction apiTx _ = getFromResponse #transaction rTx + signedTx <- signTx ctx src apiTx [ expectResponseCode HTTP.status202 ] + + submittedTx <- submitTxWithWid ctx src signedTx + verify submittedTx + [ expectSuccess + , expectResponseCode HTTP.status202 + ] + + eventually "Wallet has joined pool1 and deposit info persists" $ do + rJoin' <- request @(ApiTransaction n) ctx + (Link.getTransaction @'Shelley src + (getResponse submittedTx)) + Default Empty + verify rJoin' + [ expectResponseCode HTTP.status200 + , expectField (#status . #getApiT) (`shouldBe` InLedger) + , expectField (#direction . #getApiT) (`shouldBe` Outgoing) + , expectField #depositTaken (`shouldBe` depositAmt) + , expectField #depositReturned (`shouldBe` ApiAmount 0) + ] + + waitNumberOfEpochBoundaries 2 ctx + + let getSrcWallet = + let endpoint = Link.getWallet @'Shelley src + in request @ApiWallet ctx endpoint Default Empty + + eventually "Wallet is delegating to pool" $ do + getSrcWallet >>= flip verify + [ expectField #delegation (`shouldBe` delegating (ApiT pool1) []) + ] + + waitNumberOfEpochBoundaries 2 ctx + + eventually "Wallet gets rewards from pool1" $ do + getSrcWallet >>= flip verify + [ expectField (#balance . #reward) (.> ApiAmount 0) ] + + addrs <- listAddresses @n ctx dest + let addr = (addrs !! 1) ^. #id + let withdrawalAmount = minUTxOValue (_mainEra ctx) + + let withdrawalPayload = Json [json| + { "payments": + [ { "address": #{addr} + , "amount": + { "quantity": #{withdrawalAmount} + , "unit": "lovelace" + } + } + ] + , "passphrase": #{fixturePassphrase}, + "withdrawal": "self" + }|] + + withdrawalFailure <- request @(ApiConstructTransaction n) ctx + (Link.createUnsignedTransaction @'Shelley src) Default withdrawalPayload + + decodeErrorInfo withdrawalFailure `shouldBe` WithdrawalNotPossibleWithoutVote + + it "TRANS_NEW_JOIN_01b - Can withdraw without voting in Babbage - new tx workflow" $ \ctx -> runResourceT $ do + noConway ctx "withdraw possible" + let initialAmt = 10 * minUTxOValue (_mainEra ctx) + src <- fixtureWalletWith @n ctx [initialAmt] + dest <- emptyWallet ctx + + let depositAmt = ApiAmount 1_000_000 + + pool1 : _ <- map (view #id) <$> notRetiringPools ctx + + let delegationJoin = Json [json|{ + "delegations": [{ + "join": { + "pool": #{ApiT pool1}, + "stake_key_index": "0H" + } + }] + }|] + rTx <- request @(ApiConstructTransaction n) ctx + (Link.createUnsignedTransaction @'Shelley src) Default delegationJoin + verify rTx + [ expectResponseCode HTTP.status202 + , expectField (#coinSelection . #depositsTaken) (`shouldBe` [depositAmt]) + , expectField (#coinSelection . #depositsReturned) (`shouldBe` []) + ] + + let ApiSerialisedTransaction apiTx _ = getFromResponse #transaction rTx + signedTx <- signTx ctx src apiTx [ expectResponseCode HTTP.status202 ] + + submittedTx <- submitTxWithWid ctx src signedTx + verify submittedTx + [ expectSuccess + , expectResponseCode HTTP.status202 + ] + + eventually "Wallet has joined pool1 and deposit info persists" $ do + rJoin' <- request @(ApiTransaction n) ctx + (Link.getTransaction @'Shelley src + (getResponse submittedTx)) + Default Empty + verify rJoin' + [ expectResponseCode HTTP.status200 + , expectField (#status . #getApiT) (`shouldBe` InLedger) + , expectField (#direction . #getApiT) (`shouldBe` Outgoing) + , expectField #depositTaken (`shouldBe` depositAmt) + , expectField #depositReturned (`shouldBe` ApiAmount 0) + ] + + waitNumberOfEpochBoundaries 2 ctx + + let getSrcWallet = + let endpoint = Link.getWallet @'Shelley src + in request @ApiWallet ctx endpoint Default Empty + + eventually "Wallet is delegating to pool" $ do + getSrcWallet >>= flip verify + [ expectField #delegation (`shouldBe` delegating (ApiT pool1) []) + ] + + waitNumberOfEpochBoundaries 2 ctx + + eventually "Wallet gets rewards from pool1" $ do + getSrcWallet >>= flip verify + [ expectField (#balance . #reward) (.> ApiAmount 0) ] + + addrs <- listAddresses @n ctx dest + let addr = (addrs !! 1) ^. #id + let withdrawalAmount = minUTxOValue (_mainEra ctx) + + let withdrawalPayload = Json [json| + { "payments": + [ { "address": #{addr} + , "amount": + { "quantity": #{withdrawalAmount} + , "unit": "lovelace" + } + } + ] + , "passphrase": #{fixturePassphrase}, + "withdrawal": "self" + }|] + + withdrawalTx <- request @(ApiConstructTransaction n) ctx + (Link.createUnsignedTransaction @'Shelley src) Default withdrawalPayload + + verify withdrawalTx + [ expectResponseCode HTTP.status202 + ] + + let ApiSerialisedTransaction apiTx1 _ = getFromResponse #transaction withdrawalTx + signedWithdrawalTx <- signTx ctx src apiTx1 [ expectResponseCode HTTP.status202 ] + + submittedWithdrawalTx <- submitTxWithWid ctx src signedWithdrawalTx + verify submittedWithdrawalTx + [ expectSuccess + , expectResponseCode HTTP.status202 + ] + + eventually "Reward balance is 0" $ do + rWa <- request @ApiWallet ctx + (Link.getWallet @'Shelley src) Default Empty + verify rWa + [ expectSuccess + , expectField + (#balance . #reward . #toNatural) + (`shouldBe` 0) + ] + it "TRANS_NEW_JOIN_01b - Invalid pool id" $ \ctx -> runResourceT $ do wa <- fixtureWallet ctx let invalidPoolId = T.replicate 32 "1" diff --git a/lib/integration/scenarios/Test/Integration/Scenario/API/Voting.hs b/lib/integration/scenarios/Test/Integration/Scenario/API/Voting.hs index dbfe740292f..1e61c6ef807 100644 --- a/lib/integration/scenarios/Test/Integration/Scenario/API/Voting.hs +++ b/lib/integration/scenarios/Test/Integration/Scenario/API/Voting.hs @@ -279,7 +279,7 @@ spec = describe "VOTING_TRANSACTIONS" $ do waitNumberOfEpochBoundaries 4 ctx - submittedWithdrawalTx <- do + withdrawalFailure <- do let endpoint = Link.createTransactionOld @'Shelley src request @(ApiTransaction n) ctx endpoint Default $ Json [json| @@ -294,19 +294,7 @@ spec = describe "VOTING_TRANSACTIONS" $ do , "passphrase": #{fixturePassphrase}, "withdrawal": "self" }|] - - verify submittedWithdrawalTx - [ expectField #amount (.> ApiAmount withdrawalAmount) - , expectField (#direction . #getApiT) (`shouldBe` Outgoing) - ] - - eventually "Rewards have been consumed" $ do - getSrcWallet ctx src >>= flip verify - [ expectField (#balance . #reward . #toNatural) - (.< withdrawalAmount) - , expectField (#balance . #available) - (.> (walletBeforeWithdrawal ^. #balance . #available)) - ] & counterexample ("Wdrl: " <> show withdrawalAmount) + decodeErrorInfo withdrawalFailure `shouldBe` WithdrawalNotPossibleWithoutVote --Now voting let voteNoConfidence = Json [json|{ @@ -438,6 +426,35 @@ spec = describe "VOTING_TRANSACTIONS" $ do (`shouldBe` votingAndDelegating (ApiT pool1) voting2 []) ] + withdrawalSucesss <- do + let endpoint = Link.createTransactionOld @'Shelley src + request @(ApiTransaction n) ctx endpoint Default + $ Json [json| + { "payments": + [ { "address": #{addr} + , "amount": + { "quantity": #{withdrawalAmount} + , "unit": "lovelace" + } + } + ] + , "passphrase": #{fixturePassphrase}, + "withdrawal": "self" + }|] + + verify withdrawalSucesss + [ expectField #amount (.> ApiAmount withdrawalAmount) + , expectField (#direction . #getApiT) (`shouldBe` Outgoing) + ] + + eventually "Rewards have been consumed" $ do + getSrcWallet ctx src >>= flip verify + [ expectField (#balance . #reward . #toNatural) + (.< withdrawalAmount) + , expectField (#balance . #available) + (.> (walletBeforeWithdrawal ^. #balance . #available)) + ] & counterexample ("Wdrl: " <> show withdrawalAmount) + it "VOTING_01c - Can vote together with delegation" $ \ctx -> runResourceT $ do noBabbage ctx "voting supported in Conway onwards" src <- fixtureWallet ctx diff --git a/lib/wallet/src/Cardano/Wallet.hs b/lib/wallet/src/Cardano/Wallet.hs index 7f9bbfbb58f..10f9d1b8f9c 100644 --- a/lib/wallet/src/Cardano/Wallet.hs +++ b/lib/wallet/src/Cardano/Wallet.hs @@ -115,6 +115,7 @@ module Cardano.Wallet , getCurrentEpochSlotting , setChangeAddressMode , setChangeAddressModeShared + , assertIsVoting -- * Shared Wallet , updateCosigner @@ -621,7 +622,7 @@ import Cardano.Wallet.Transaction , VotingAction (..) , Withdrawal (..) , WitnessCountCtx (..) - , containsWithdrawal + , containsSelfWithdrawal , defaultTransactionCtx , withdrawalToCoin ) @@ -2670,7 +2671,7 @@ constructTransaction -> ExceptT ErrConstructTx IO (Cardano.TxBody (Write.CardanoApiEra era)) constructTransaction era db txCtx preSel = do (_, xpub, _) <- lift $ readRewardAccount db - when (containsWithdrawal (txCtx ^. #txWithdrawal)) $ + when (containsSelfWithdrawal (txCtx ^. #txWithdrawal)) $ assertIsVoting db era mkUnsignedTransaction netId (Left $ fromJust xpub) txCtx (Left preSel) & withExceptT ErrConstructTxBody . except @@ -2693,7 +2694,7 @@ constructUnbalancedSharedTransaction era db txCtx sel = db & \DBLayer{..} -> do scriptM = flip (replaceCosignersWithVerKeys CAShelley.Stake) minBound <$> delegationTemplate s - when (containsWithdrawal (txCtx ^. #txWithdrawal)) $ + when (containsSelfWithdrawal (txCtx ^. #txWithdrawal)) $ assertIsVoting db era mapExceptT atomically $ do withExceptT ErrConstructTxBody $ ExceptT $ pure $ diff --git a/lib/wallet/src/Cardano/Wallet/Transaction.hs b/lib/wallet/src/Cardano/Wallet/Transaction.hs index 7ead24710da..fb179a96151 100644 --- a/lib/wallet/src/Cardano/Wallet/Transaction.hs +++ b/lib/wallet/src/Cardano/Wallet/Transaction.hs @@ -34,6 +34,7 @@ module Cardano.Wallet.Transaction , Withdrawal (..) , withdrawalToCoin , containsWithdrawal + , containsSelfWithdrawal , TokenMapWithScripts (..) , emptyTokenMapWithScripts , AnyExplicitScript (..) @@ -307,6 +308,11 @@ containsWithdrawal = \case NoWithdrawal -> False _ -> True +containsSelfWithdrawal :: Withdrawal -> Bool +containsSelfWithdrawal = \case + WithdrawalSelf {} -> True + _ -> False + withdrawalToCoin :: Withdrawal -> Coin withdrawalToCoin = \case WithdrawalSelf _ _ c -> c diff --git a/run/common/nix/run.sh b/run/common/nix/run.sh index d82d58df018..3dddf0e7982 100755 --- a/run/common/nix/run.sh +++ b/run/common/nix/run.sh @@ -113,7 +113,7 @@ if [[ -z ${NO_NODE-} ]]; then echo "Node id: $NODE_ID" echo "Node socket path: $NODE_SOCKET_PATH" - sleep 5 + sleep 10 @@ -122,40 +122,6 @@ else fi -magic=$(jq .networkMagic $LOCAL_NODE_CONFIGS/shelley-genesis.json) -##### Wait until the node is ready ##### - -# Capture the start time -start_time=$(date +%s) - -# Define the timeout duration in seconds -timeout_duration=3600 - -# Repeat the command until it succeeds or 10 seconds elapse -while true; do - # Execute the command - failure_status=0 - cardano-cli ping -m "${magic}" -u "${NODE_SOCKET_PATH}" 2>/dev/null || failure_status=1 - # Check if the command succeeded - # shellcheck disable=SC2181 - if [[ "$failure_status" -eq 0 ]]; then - break - fi - - # Calculate the elapsed time - current_time=$(date +%s) - elapsed_time=$((current_time - start_time)) - - # Check if the timeout duration has been reached - if [[ $elapsed_time -ge $timeout_duration ]]; then - echo "Cannot ping the node after $timeout_duration seconds" - exit 1 - fi - - # Sleep for a short interval before retrying - sleep 1 -done - if [[ -z ${NO_WALLET-} ]]; then echo "Starting the wallet service..."