Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Populate receive modal for accts with keyset-refs #648

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion frontend/src/Frontend/TxBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.Builder as LTB
import Pact.Types.ChainId
import Kadena.SigningApi (AccountName(..))
import Pact.Types.Term (KeySet (..))
import Pact.Types.Term (KeySet (..), KeySetName(..))

data TxBuilder = TxBuilder
{ _txBuilder_accountName :: AccountName
Expand All @@ -24,6 +24,7 @@ data TxBuilder = TxBuilder
-- ^ Presence or absence of a keyset may be used to determine transfer vs
-- transfer-create. If the keyset is present and the account already exists
-- you could choose to do either a transfer or a transfer-create.
, _txBuilder_keysetRef :: Maybe KeySetName
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TxBuilder type is very sensitive because it defines the serialization format that is used both by Chainweaver and by other parts of the ecosystem. We don't want keyset refs to be visible at this level, both for backwards compatibility reasons and because the low level details of keyset refs should be hidden from users of the TxBuilder. So I think we should back out the changes to this data type and make sure that Chainweaver resolves the keyset elsewhere, preserving the keyset interface.

}
deriving (Show, Eq)

Expand All @@ -32,13 +33,15 @@ instance ToJSON TxBuilder where
[ Just $ "account" .= _txBuilder_accountName o
, Just $ "chain" .= _txBuilder_chainId o
, ("keyset" .=) <$> _txBuilder_keyset o
, ("ref" .=) <$> _txBuilder_keysetRef o
]

instance FromJSON TxBuilder where
parseJSON = withObject "TxBuilder" $ \o -> TxBuilder
<$> o .: "account"
<*> o .: "chain"
<*> o .:? "keyset"
<*> o .:? "ref"

prettyTxBuilder :: TxBuilder -> Text
prettyTxBuilder = LT.toStrict . LTB.toLazyText . AesonPretty.encodePrettyToTextBuilder
62 changes: 48 additions & 14 deletions frontend/src/Frontend/UI/Dialogs/Receive.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ module Frontend.UI.Dialogs.Receive
) where

import Control.Applicative (liftA2)
import Control.Lens ((^.), (<>~), (^?), to)
import Control.Lens ((^.), (<>~), (^?), at, to, _Just)
import Control.Monad
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Maybe (MaybeT(..))
import Data.Either (rights)
import qualified Data.IntMap as IntMap
import Data.Set (Set)
import qualified Data.Set as Set
Expand All @@ -36,10 +37,13 @@ import Frontend.UI.FormWidget
import Frontend.UI.KeysetWidget

import Frontend.UI.Modal
import Frontend.UI.Transfer
import Frontend.UI.Widgets
import Frontend.UI.Widgets.Helpers (dialogSectionHeading)
import Frontend.Wallet

import qualified Pact.Types.Term as Pact

uiReceiveModal
:: ( MonadWidget t m
, Monoid mConf
Expand All @@ -52,24 +56,26 @@ uiReceiveModal
, HasLogger model t
, HasTransactionLogger m
)
=> Text
=> NetworkName
-> [Either Text NodeInfo]
-> Text
-> model
-> AccountName
-> ChainId
-> Maybe AccountDetails
-> Event t ()
-> m (mConf, Event t ())
uiReceiveModal modalTitle model account chain mdetails _onClose = do
uiReceiveModal network nodes modalTitle model account chain mdetails _onClose = do
onClose <- modalHeader $ text modalTitle

divClass "modal__main receive" $ do
dmks <- receiveToNonexistentAccount model account chain mdetails
dmks <- receiveToNonexistentAccount model network nodes account chain mdetails

dyn_ $ ffor dmks $ \mks -> do
case mks of
Nothing -> blank
Just ks -> do
let txb = TxBuilder account chain (Just $ userToPactKeyset ks)
(Nothing, Nothing) -> blank
(Just ks, ref) -> do
let txb = TxBuilder account chain (Just $ userToPactKeyset ks) ref --TODO bruh
dialogSectionHeading mempty "Account Information"
divClass "group" $ uiDisplayTxBuilderWithCopy True txb

Expand All @@ -86,16 +92,43 @@ receiveToNonexistentAccount
, HasWallet model key t
, HasLogger model t
, HasTransactionLogger m
, TriggerEvent t m
)
=> model
-> NetworkName
-> [Either Text NodeInfo]
-> AccountName
-> ChainId
-> Maybe AccountDetails
-> m (Dynamic t (Maybe UserKeyset))
receiveToNonexistentAccount model account chain mdetails = do
case mdetails of
Just d -> pure $ constDyn (d ^? accountDetails_guard . _AccountGuard_KeySetLike .
to toPactKeyset . to userFromPactKeyset)
-> m (Dynamic t (Maybe UserKeyset, Maybe Pact.KeySetName))
receiveToNonexistentAccount model net nodes account chain mdetails = do
case _accountDetails_guard <$> mdetails of
Just (AccountGuard_Other g) -> case g of
Pact.GKeySetRef ref -> do
let chain' = case chain of -- in case the chain id is 0, make sure 00 becomes 0
ChainId c -> case c of
"00" -> ChainId "0"
_ -> ChainId c

eAccountMap <- lookupKeySets (model ^. logger) net (rights nodes) chain' [account]
accDyn <- holdDyn Nothing eAccountMap
pure $ ffor accDyn $ \case
Nothing -> (Nothing, Nothing)
Just m ->
let ks = m ^?
at account
. _Just
. _AccountStatus_Exists
. accountDetails_guard
. _AccountGuard_KeySetLike
. to toPactKeyset
. to userFromPactKeyset

in (ks, Just ref)
_ -> pure $ constDyn (Nothing, Nothing)

Just (AccountGuard_KeySetLike d) -> pure $ constDyn (Just $ userFromPactKeyset $ toPactKeyset d, Nothing)

Nothing -> do
let dynWalletKeys = Set.fromList . fmap (_keyPair_publicKey . _key_pair) . IntMap.elems <$>
model ^. wallet_keys
Expand All @@ -122,7 +155,7 @@ receiveToNonexistentAccount model account chain mdetails = do
dialogSectionHeading mempty "Define Keyset"
divClass "group" $ keysetFormWidget (mkCfg Nothing)
Just ks -> pure (constDyn $ Just ks)
fmap join $ holdDyn (constDyn Nothing) res
fmap join $ holdDyn (constDyn (Nothing, Nothing)) (fmap (fmap (\a -> (a, Nothing))) res)
where
para1 = el "p" $ text $ T.unwords
[ "Before you can receive coins, you must decide who owns this account."
Expand Down Expand Up @@ -171,7 +204,8 @@ uiReceiveModal0 model account chain details onClose = Workflow $ do
(accordionHeaderBtn "Option 1: Copy and share Tx Builder") $ do
uiDisplayTxBuilderWithCopy True
$ TxBuilder account chain
$ details ^? accountDetails_guard . _AccountGuard_KeySetLike . to toPactKeyset
(details ^? accountDetails_guard . _AccountGuard_KeySetLike . to toPactKeyset)
(Pact.KeySetName <$> details ^? accountDetails_guard . _AccountGuard_KeySetLike . ksh_ref . _Just)

(onReceiClick, results) <- controlledAccordionItem (not <$> showingTxBuilder) mempty
(accordionHeaderBtn "Option 2: Transfer from non-Chainweaver Account") $ do
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Frontend/UI/Dialogs/Send.hs
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ crossChainTransfer logL netInfo keys fromAccount toAccount fromGasPayer crossCha
pb <- getPostBuild
let (fromName, fromChain, _) = fromAccount
toChain = either _txBuilder_chainId (view _2) toAccount
toTxBuilder = either id (\(n, c, _) -> TxBuilder n c Nothing) toAccount
toTxBuilder = either id (\(n, c, _) -> TxBuilder n c Nothing Nothing) toAccount
-- Client envs for making requests to each chain
let envFromChain = mkClientEnvs nodeInfos fromChain
envToChain = mkClientEnvs nodeInfos toChain
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Frontend/UI/Dialogs/Send/ManualTxBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ uiExplodedTxBuilder
uiExplodedTxBuilder model fromName fromChain mUcct mInitToAddress = do
let
mkAlteredTxB mname mchain intKeys extKeys mPredicate = TxBuilder <$> mname <*> mchain
<*> pure (fmap (\p -> toPactKeyset $ KeySetHeritage (intKeys <> extKeys) p Nothing) mPredicate)
<*> pure (fmap (\p -> toPactKeyset $ KeySetHeritage (intKeys <> extKeys) p Nothing) mPredicate) <*> pure Nothing

explodedTxB onTxAccountName onTxChainId keysetsPresets = do
(onNameInput, dname) <- uiAccountNameInput "Account Name" False Nothing onTxAccountName noValidation
Expand Down
12 changes: 7 additions & 5 deletions frontend/src/Frontend/UI/Wallet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ uiAccountItems
=> model -> Dynamic t (Map AccountName (AccountInfo Account)) -> m mConf
uiAccountItems model accountsMap = do
let net = model ^. network_selectedNetwork
nodes = model ^. network_selectedNodes
tableAttrs = mconcat
[ "style" =: "table-layout: fixed; width: 98%"
, "class" =: "wallet table"
Expand Down Expand Up @@ -200,18 +201,18 @@ uiAccountItems model accountsMap = do
let
onAccountModal = switchDyn $ leftmost . Map.elems <$> events

accModal n = Just . \case
accModal (n, ns) = Just . \case
AccountDialog_Details acc notes -> uiAccountDetails n acc notes
AccountDialog_DetailsChain acc -> uiAccountDetailsOnChain n acc
AccountDialog_Receive name chain details -> uiReceiveModal "Receive" model name chain details
AccountDialog_TransferTo name details chain -> uiReceiveModal "Transfer To" model name chain (Just details)
AccountDialog_Receive name chain details -> uiReceiveModal n ns "Receive" model name chain details
AccountDialog_TransferTo name details chain -> uiReceiveModal n ns "Transfer To" model name chain (Just details)
AccountDialog_Send acc mucct -> uiSendModal model acc mucct
AccountDialog_CompleteCrosschain name chain ucct -> uiFinishCrossChainTransferModal model name chain ucct

refresh <- delay 1 =<< getPostBuild

pure $ mempty
& modalCfg_setModal .~ attachWith accModal (current net) onAccountModal
& modalCfg_setModal .~ attachWith accModal (current $ (,) <$> net <*> nodes) onAccountModal
& walletCfg_refreshBalances .~ refresh

-- | This function only exists to workaround a reflex-dom Adjustable bug.
Expand Down Expand Up @@ -352,9 +353,10 @@ uiAccountItem cwKeys startsOpen name accountInfo = do
pure $ AccountDialog_Receive name chain Nothing <$ receive
AccountStatus_Exists d -> do
let ks = d ^? accountDetails_guard . _AccountGuard_KeySetLike
let ref = Pact.KeySetName <$> d ^? accountDetails_guard . _AccountGuard_KeySetLike . ksh_ref . _Just
let uk = (\(KeySetHeritage k p _ref) -> UserKeyset k (parseKeysetPred p)) <$> ks

let txb = TxBuilder name chain (userToPactKeyset <$> uk)
let txb = TxBuilder name chain (userToPactKeyset <$> uk) ref
let bcfg = btnCfgSecondary & uiButtonCfg_class <>~ "wallet__table-button" <> "button_border_none"
copyAddress <- copyButton' "Copy Tx Builder" bcfg False (constant $ prettyTxBuilder txb)

Expand Down