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

WalletConnect #759

Draft
wants to merge 34 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2510f81
Remove the cardano-crypto usage from ImportExport module
dfordivam Dec 14, 2021
b7a371c
Move ImportExport module to frontend
dfordivam Dec 14, 2021
ae481e6
Move the restoreFromImport widget to frontend
dfordivam Dec 16, 2021
06b7f99
Refactor, add helper data type and constraints
dfordivam Dec 16, 2021
8a753d4
Remove Crypto.XPrv from Desktop.Setup module
dfordivam Dec 16, 2021
2452547
Move the Desktop.Setup module to frontend
dfordivam Dec 16, 2021
88488e2
Use the runSetup from Setup module
dfordivam Dec 16, 2021
1841085
Implement fileFFI_deliverFile for browser using anchor tag based down…
dfordivam Dec 16, 2021
f42943b
Move the ExportWallet to frontend
dfordivam Dec 17, 2021
87f30df
Add ExportWallet to the web app
dfordivam Dec 17, 2021
977404c
Use 'defaultTimeLocale' in doExport as getCurrentLocale does not work…
dfordivam Dec 21, 2021
5505b00
Simplify FRPHandler, pass the callback for response with the request …
dfordivam Feb 15, 2022
2173d85
Fix the bug where doing logout and then login causes the loss of sign…
dfordivam Mar 14, 2022
8c66f17
Merge remote-tracking branch 'os/dn-import-export-web' into dn-wallet…
dfordivam Mar 29, 2022
8ecb1f9
Use index.min.js with fixes and based on 2.0.0-beta.23 release https:…
dfordivam Mar 29, 2022
e178685
Add wallet-connect package to frontend
dfordivam Mar 29, 2022
213742c
Add reflex-notifications to frontend
dfordivam Mar 29, 2022
6a537a6
Add WalletConnect.svg
dfordivam Mar 29, 2022
bddf306
WalletConnect support
dfordivam Mar 31, 2022
342909c
Remove jsHackForStopPropagation, as the backdrop click no longer clos…
dfordivam Mar 31, 2022
fa22b1d
Use v2.0.0-beta.26
dfordivam Mar 31, 2022
41ebb2e
Check for e in parseConnectionError, fix done directly in min.js
dfordivam Mar 31, 2022
f6d7ff3
Revert "Check for e in parseConnectionError, fix done directly in min…
dfordivam Apr 5, 2022
afe6dbd
Revert "Use v2.0.0-beta.26"
dfordivam Apr 5, 2022
a7cb9c8
Fix: send proper error object on request reject
dfordivam Apr 5, 2022
9aa85ef
Disable logging of debug data in wallet-connect
dfordivam Apr 7, 2022
ea5d147
Remove wallet-connect code, and use the thunk instead
dfordivam Apr 7, 2022
ed49fb4
Bump wallet-connect with a minor change in Pairing data type
dfordivam Apr 8, 2022
e7cb663
Add this fix https://github.com/kadena-io/walletconnect-monorepo/comm…
dfordivam Apr 8, 2022
e0cbb59
add wallet connect to v2.2.2
May 13, 2022
8c77c7d
fix build
May 16, 2022
6db28d1
Better styling in the WalletConnect dialog
mightybyte Jun 22, 2022
0d002d5
Merge remote-tracking branch 'origin/develop' into doug/import-dn-wal…
mightybyte Sep 4, 2022
a0f93ef
Bump to trigger build
mightybyte Sep 5, 2022
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,4 @@ The nice aspect of using a virtual machine is taking advantage of virtualbox's a
To take a snapshot (if the machine is running), Click on the "Machine" menu of Virtualbox and click "Take Snapshot".

To restore from a snapshot, go to the VirtualBox manager, click "Snapshot" and click "Restore".

1 change: 1 addition & 0 deletions backend/backend.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ library
, hsass
, template-haskell
, th-utilities
, wallet-connect

exposed-modules: Backend
, Backend.App
Expand Down
14 changes: 11 additions & 3 deletions backend/src/Backend/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import qualified Control.Concurrent.Async as Async
import qualified Data.ByteString as BS
import qualified Data.List as L
import qualified Data.Map as M
import Data.Proxy (Proxy(..))
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
Expand All @@ -31,6 +32,7 @@ import qualified Snap.Http.Server as Snap
import qualified System.Directory as Directory
import qualified System.Environment as Env
import Pact.Server.ApiClient (runTransactionLoggerT, logTransactionFile, commandLogFilename)
import WalletConnect.Wallet (Metadata)

import Backend (serveBackendRoute)
import Common.Logger (LogStr,LogLevel)
Expand Down Expand Up @@ -164,6 +166,8 @@ main' ffi mainBundleResourcePath runHTML = do
(signingHandler, quickSignHandler) <- walletServer
(_appFFI_moveToForeground ffi)
(_appFFI_moveToBackground ffi)
(Proxy :: Proxy Metadata)

waitForBackend port
liftIO $ putStrLn "Starting jsaddle"
runHTML "index.html" route putStrLn handleOpen $ do
Expand Down Expand Up @@ -192,6 +196,11 @@ main' ffi mainBundleResourcePath runHTML = do
bowserLoad <- takeMVarTriggerEvent bowserMVar
fileOpened <- takeMVarTriggerEvent fileOpenedMVar

signingReqEv <- do
sreq <- tryReadMVarTriggerEvent (_mvarHandler_readRequest signingHandler)
qsreq <- tryReadMVarTriggerEvent (_mvarHandler_readRequest quickSignHandler)
pure $ leftmost [() <$ sreq, () <$ qsreq]

let fileFFI = FileFFI
{ _fileFFI_openFileDialog = liftIO . _appFFI_global_openFileDialog ffi
, _fileFFI_externalFileOpened = fileOpened
Expand All @@ -202,8 +211,7 @@ main' ffi mainBundleResourcePath runHTML = do
, _appCfg_loadEditor = loadEditorFromLocalStorage
-- DB 2019-08-07 Changing this back to False because it's just too convenient this way.
, _appCfg_editorReadOnly = False
, _appCfg_signingHandler = mkFRPHandler signingHandler
, _appCfg_quickSignHandler = mkFRPHandler quickSignHandler
, _appCfg_signingHandler = (,) <$> mkFRPHandler signingHandler <*> mkFRPHandler quickSignHandler
, _appCfg_enabledSettings = enabledSettings
, _appCfg_logMessage = _appFFI_global_logFunction ffi
}
Expand All @@ -213,7 +221,7 @@ main' ffi mainBundleResourcePath runHTML = do
$ runWithReplace loaderMarkup
$ ( liftIO (_appFFI_activateWindow ffi)
>> liftIO (_appFFI_resizeWindow ffi defaultWindowSize)
>> bipWallet fileFFI (_mvarHandler_readRequest signingHandler) (_mvarHandler_readRequest quickSignHandler) appCfg
>> bipWallet fileFFI signingReqEv appCfg
)
<$ bowserLoad
pure ()
Expand Down
2 changes: 2 additions & 0 deletions common/src/Common/Route.hs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ data FrontendRoute :: * -> * where
FrontendRoute_Keys :: FrontendRoute ()
FrontendRoute_Resources :: FrontendRoute ()
FrontendRoute_Settings :: FrontendRoute ()
FrontendRoute_WalletConnect :: FrontendRoute (Map Text (Maybe Text))

data ContractRoute a where
-- | Route for loading an example.
Expand Down Expand Up @@ -92,6 +93,7 @@ backendRouteEncoder = handleEncoder (\_e -> hoistR (FullRoute_Frontend . Obelisk
FrontendRoute_Keys -> PathSegment "keys" $ unitEncoder mempty
FrontendRoute_Settings -> PathSegment "settings" $ unitEncoder mempty
FrontendRoute_Resources -> PathSegment "resources" $ unitEncoder mempty
FrontendRoute_WalletConnect -> PathSegment "wc" $ queryOnlyEncoder

contractRouteEncoder :: (MonadError Text parse, MonadError Text check) => Encoder parse check (R ContractRoute) PageName
contractRouteEncoder = pathComponentEncoder $ \case
Expand Down
2 changes: 2 additions & 0 deletions dep/reflex-notifications/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# DO NOT HAND-EDIT THIS FILE
import (import ./thunk.nix)
8 changes: 8 additions & 0 deletions dep/reflex-notifications/github.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"owner": "obsidiansystems",
"repo": "reflex-notifications",
"branch": "main",
"private": false,
"rev": "ff606c5b6dc001368f7516c028ee162ff64d6062",
"sha256": "083bmsgha9vynjsrwbw34r3rafddaqpbvxj5jj8b0isc3vkp6z3z"
}
9 changes: 9 additions & 0 deletions dep/reflex-notifications/thunk.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT HAND-EDIT THIS FILE
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
if !fetchSubmodules && !private then builtins.fetchTarball {
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
} else (import <nixpkgs> {}).fetchFromGitHub {
inherit owner repo rev sha256 fetchSubmodules private;
};
json = builtins.fromJSON (builtins.readFile ./github.json);
in fetch json
2 changes: 2 additions & 0 deletions dep/wallet-connect/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# DO NOT HAND-EDIT THIS FILE
import (import ./thunk.nix)
8 changes: 8 additions & 0 deletions dep/wallet-connect/github.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"owner": "kadena-io",
"repo": "walletconnect-hs-interface",
"branch": "main",
"private": false,
"rev": "e2eb54045a7b058b2d1de4c0c4ca65f7997f67c9",
"sha256": "01d9z334gsxbx6zp4d7h1k6x82ia2jkhw8j4a4qx3rx6rlq0d328"
}
9 changes: 9 additions & 0 deletions dep/wallet-connect/thunk.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT HAND-EDIT THIS FILE
let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:
if !fetchSubmodules && !private then builtins.fetchTarball {
url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256;
} else (import <nixpkgs> {}).fetchFromGitHub {
inherit owner repo rev sha256 fetchSubmodules private;
};
json = builtins.fromJSON (builtins.readFile ./github.json);
in fetch json
3 changes: 1 addition & 2 deletions desktop/desktop.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,13 @@ library
, transformers
, universe-dependent-sum
, wai-cors
, wallet-connect
, warp

exposed-modules:
Desktop.Crypto.BIP
, Desktop.Frontend
, Desktop.ImportExport
, Desktop.Orphans
, Desktop.Setup
, Desktop.Storage.File
, Desktop.Syslog
, Desktop.WalletApi
Expand Down
7 changes: 2 additions & 5 deletions desktop/src/Desktop/Crypto/BIP.hs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ data BIPStorage a where
BIPStorage_RootKey :: BIPStorage Crypto.XPrv
deriving instance Show (BIPStorage a)

bipMetaPrefix :: StoreKeyMetaPrefix
bipMetaPrefix = StoreKeyMetaPrefix "BIPStorage_Meta"

-- | Check the validity of the password by signing and verifying a message
passwordRoundTripTest :: Crypto.XPrv -> Password -> Bool
passwordRoundTripTest xprv (Password pass) =
Expand Down Expand Up @@ -236,5 +233,5 @@ instance (Prerender js t m, Monad m, Reflex t) => Prerender js t (BIPCryptoT t m
type Client (BIPCryptoT t m) = BIPCryptoT t (Client m)
prerender a b = BIPCryptoT $ prerender (unBIPCryptoT a) (unBIPCryptoT b)

runBIPCryptoT :: Behavior t (Crypto.XPrv, Text) -> BIPCryptoT t m a -> m a
runBIPCryptoT b (BIPCryptoT m) = runReaderT m b
runBIPCryptoT :: (Reflex t) => Behavior t (Crypto.XPrv, Password) -> BIPCryptoT t m a -> m a
runBIPCryptoT b (BIPCryptoT m) = runReaderT m ((\(k, Password p) -> (k, p)) <$> b)
81 changes: 22 additions & 59 deletions desktop/src/Desktop/Frontend.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ import Control.Monad ((<=<), guard, void, when)
import Control.Monad.Fix (MonadFix)
import Control.Monad.Trans (lift)
import Control.Monad.IO.Class
import Data.Bifunctor (first, second)
import Data.Bifunctor (second)
import Data.Dependent.Sum
import Data.Functor.Compose
import Data.Functor.Identity
import Data.GADT.Compare.TH
import Data.Maybe (isJust)
import Data.Proxy (Proxy(..))
import Data.Text (Text)
import Data.Time (NominalDiffTime, getCurrentTime, addUTCTime)
import Data.Traversable (for)
Expand All @@ -53,9 +54,9 @@ import Common.Route
import Common.Wallet
import Frontend.AppCfg
import Desktop.Crypto.BIP
import Desktop.Orphans ()
import Frontend.ModuleExplorer.Impl (loadEditorFromLocalStorage)
import Frontend.Log (defaultLogger)
import Frontend.Wallet (genZeroKeyPrefix, _unPublicKeyPrefix)
import Frontend.Storage
import Frontend.UI.Modal.Impl (showModalBrutal)
import Frontend.UI.Dialogs.LogoutConfirmation (uiIdeLogoutConfirmation)
Expand All @@ -69,12 +70,13 @@ import Frontend.VersionedStore (StoreFrontend(..))
import Frontend.Storage (runBrowserStorageT)
import Frontend.Crypto.Password
import Frontend.Setup.Common
import Frontend.Setup.ImportExport
import Frontend.Setup.Password
import Frontend.Setup.Setup
import Frontend.Setup.Widgets
import Desktop.Setup
import Desktop.ImportExport
import Desktop.Storage.File
import Desktop.WalletApi
import Frontend.WalletConnect

import Pact.Server.ApiClient (WalletEvent (..), commandLogFilename, _transactionLogger_walletEvent, _transactionLogger_rotateLogFile)

Expand Down Expand Up @@ -132,7 +134,7 @@ data LockScreen a where
LockScreen_Restore :: LockScreen Crypto.XPrv -- ^ Root key
LockScreen_RunSetup :: LockScreen ()
LockScreen_Locked :: LockScreen Crypto.XPrv -- ^ Root key
LockScreen_Unlocked :: LockScreen (Crypto.XPrv, Text) -- ^ The root key and password
LockScreen_Unlocked :: LockScreen (Crypto.XPrv, Password) -- ^ The root key and password

type MkAppCfg t m
= EnabledSettings Crypto.XPrv t (RoutedT t (R FrontendRoute) (BIPCryptoT t m))
Expand All @@ -149,11 +151,10 @@ bipWallet
, Prerender js t m
)
=> FileFFI t m
-> MVar SigningRequest
-> MVar QuickSignRequest
-> Event t ()
-> MkAppCfg t m
-> RoutedT t (R FrontendRoute) m ()
bipWallet fileFFI signingReq quickSignReq mkAppCfg = do
bipWallet fileFFI signingReqEv mkAppCfg = do
txLogger <- askTransactionLogger

let
Expand All @@ -162,9 +163,13 @@ bipWallet fileFFI signingReq quickSignReq mkAppCfg = do
-> WalletExists
-> RoutedT t (R FrontendRoute) m (Event t (DSum LockScreen Identity))
runSetup0 mPrv walletExists = do
keyAndPass <- runSetup (liftFileFFI lift fileFFI) (isJust mPrv) walletExists
let pwCheck k p= pure $ passwordRoundTripTest k p
runF k p = runBIPCryptoT (pure (k, p))
importWidgetApis = ImportWidgetApis BIPStorage_RootKey pwCheck runF

keyAndPass <- runSetup (liftFileFFI lift fileFFI) (isJust mPrv) walletExists importWidgetApis
performEvent $ flip push keyAndPass $ \case
Right (x, Password p, newWallet) -> pure $ Just $ do
Right (x, p, newWallet) -> pure $ Just $ do
setItemStorage localStorage BIPStorage_RootKey x
when newWallet $ do
liftIO $ _transactionLogger_rotateLogFile txLogger
Expand All @@ -189,7 +194,7 @@ bipWallet fileFFI signingReq quickSignReq mkAppCfg = do
LockScreen_RunSetup :=> _ -> runSetup0 Nothing WalletExists_No
-- Wallet exists but the lock screen is active
LockScreen_Locked :=> Compose root -> do
(restore, mLogin) <- lockScreenWidget signingReq quickSignReq $ fmap runIdentity $ current root
(restore, mLogin) <- lockScreenWidget signingReqEv (\k p -> pure $ passwordRoundTripTest k p) False $ fmap runIdentity $ current root
pure $ leftmost
[ (LockScreen_Restore ==>) . runIdentity <$> current root <@ restore
, (LockScreen_Unlocked ==>) <$> attach (runIdentity <$> current root) mLogin
Expand All @@ -212,7 +217,7 @@ bipWallet fileFFI signingReq quickSignReq mkAppCfg = do
{ _keyPair_publicKey = pub
, _keyPair_privateKey = Just newPrv
}
Frontend.App.app sidebarLogoutLink frontendFileFFI $ mkAppCfg $ EnabledSettings
Frontend.App.app sidebarLogoutLink frontendFileFFI never $ mkAppCfg $ EnabledSettings
{ _enabledSettings_changePassword = Just $ ChangePassword
{ _changePassword_requestChange =
let doChange (Identity (oldRoot, _)) (Password oldPass, Password newPass, Password repeatPass)
Expand All @@ -222,44 +227,18 @@ bipWallet fileFFI signingReq quickSignReq mkAppCfg = do
-- Change password for root key
let newRoot = Crypto.xPrvChangePass (T.encodeUtf8 oldPass) (T.encodeUtf8 newPass) oldRoot
setItemStorage localStorage BIPStorage_RootKey newRoot
liftIO $ trigger (newRoot, newPass)
liftIO $ trigger (newRoot, Password newPass)
pure $ Right ()
| otherwise = pure $ Left "Invalid password"
in performEvent . attachWith doChange (current details)
-- When updating the keys here, we just always regenerate the key from
-- the new root
, _changePassword_updateKeys = ((second Password) <$> updates, changePasswordDesktopAction)
}
, _enabledSettings_exportWallet = Just $ ExportWallet
{ _exportWallet_requestExport = \ePw -> do
let bOldPw = (\(Identity (_,oldPw)) -> oldPw) <$> current details
runExport oldPw newPw = do
pfx <- genZeroKeyPrefix
doExport txLogger pfx oldPw newPw

logExport = do
ts <- liftIO getCurrentTime
sender <- genZeroKeyPrefix
liftIO $ _transactionLogger_walletEvent txLogger
WalletEvent_Export
(_unPublicKeyPrefix sender)
ts

eExport <- performEvent $ runExport
<$> (Password <$> bOldPw)
<@> (Password <$> ePw)

let (eErrExport, eGoodExport) = fanEither eExport

eFileDone <- _fileFFI_deliverFile frontendFileFFI eGoodExport
eLogExportDone <- performEvent $ (\r -> r <$ logExport) <$> eFileDone

pure $ leftmost
[ Left <$> eErrExport
, first ExportWalletError_FileNotWritable <$> eLogExportDone
]
, _changePassword_updateKeys = (updates, changePasswordDesktopAction)
}
, _enabledSettings_exportWallet =
Just $ mkExportWallet txLogger frontendFileFFI details (Proxy :: Proxy (BIPStorage Crypto.XPrv))
, _enabledSettings_transactionLog = True
, _enabledSettings_walletConnect = Nothing
}

setRoute $ landingPageRoute <$ onLogoutConfirm
Expand All @@ -285,20 +264,4 @@ _watchInactivity checkInterval timeout = do
let checkTime la ti = guard $ addUTCTime timeout la <= _tickInfo_lastUTC ti
pure $ attachWithMaybe checkTime lastActivity check

lockScreenWidget
:: (DomBuilder t m, PostBuild t m, TriggerEvent t m, PerformEvent t m, MonadIO m, MonadFix m, MonadHold t m)
=> MVar SigningRequest -> MVar QuickSignRequest -> Behavior t Crypto.XPrv -> m (Event t (), Event t Text)
lockScreenWidget signingReq quickSignReq xprv =
setupDiv "fullscreen" $ divClass "wrapper" $ setupDiv "splash" $ mdo
(restore, pass, eSubmit) <- lockScreen $ (fmap . fmap) Password isValid
sreq <- tryReadMVarTriggerEvent signingReq
qsreq <- tryReadMVarTriggerEvent quickSignReq
let req = leftmost [() <$ sreq, () <$ qsreq]
widgetHold_ blank $ ffor req $ \_ -> do
let line = divClass (setupClass "signing-request") . text
line "You have an incoming signing request."
line "Unlock your wallet to view and sign the transaction."
let isValid = attachWith (\(p, x) _ -> p <$ guard (passwordRoundTripTest x (Password p))) ((,) <$> current pass <*> xprv) eSubmit
pure (restore, fmapMaybe id isValid)

deriveGEq ''LockScreen
Loading