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

[ADP-3436] Add customer address query to UI #4780

Merged
Merged
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 .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ steps:

- label: Private Network Full Sync
timeout_in_minutes: 30
if: 0 == 1 # Disabled until new mihtril snapshots
depends_on: []
command: |
rm -rf run/private/nix/logs
Expand All @@ -161,6 +162,7 @@ steps:

- label: Mainnet Boot Sync
timeout_in_minutes: 2
if: 0 == 1 # Disabled until mithril builds again
depends_on: []
command: |
cd run/mainnet/nix
Expand Down Expand Up @@ -218,6 +220,7 @@ steps:
depends_on:
- linux-sanchonet-full-sync-block
timeout_in_minutes: 120
if: 0 == 1 # Disabled until mithril builds again
command: |
rm -rf run/sanchonet/nix/logs
mkdir -p run/sanchonet/nix/logs
Expand All @@ -242,6 +245,7 @@ steps:
depends_on:
- linux-preprod-full-sync-block
timeout_in_minutes: 240
if: 0 == 1 # Disabled until mithril builds again
command: |
cd run/preprod/nix
rm -rf logs
Expand Down Expand Up @@ -685,7 +689,6 @@ steps:

- label: Mainnet Boot Sync via Mithril
timeout_in_minutes: 120
if: 0 == 1 # Disabled until new mihtril snapshots
command: |
cd run/mainnet/docker
export WALLET_TAG=$(buildkite-agent meta-data get "release-cabal-version")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
--
-- Each HTTP endpoint corresponds to a single function from the
-- "Cardano.Wallet.Deposit.IO" module.
--
module Cardano.Wallet.Deposit.HTTP.Endpoints
( listCustomers
, createAddress

, customerAddress
, getNetworkTip
) where

Expand Down Expand Up @@ -61,12 +59,15 @@ listCustomers
listCustomers w =
liftIO $ ApiT <$> Wallet.listCustomers w

createAddress
customerAddress
:: Wallet.WalletInstance
-> ApiT Customer
-> Handler (ApiT Address)
createAddress w a =
liftIO $ ApiT <$> Wallet.createAddress (unApiT a) w
customerAddress w a = do
mAddr <- liftIO $ Wallet.customerAddress (unApiT a) w
case mAddr of
Nothing -> fail "customerAddress: customer not found"
Just addr -> pure $ ApiT addr

getNetworkTip
:: Wallet.WalletInstance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ api = Proxy
implementation :: Wallet.WalletInstance -> Server CustomerAPI
implementation w =
HTTP.listCustomers w
:<|> HTTP.createAddress w
:<|> HTTP.customerAddress w
13 changes: 4 additions & 9 deletions lib/customer-deposit-wallet/src/Cardano/Wallet/Deposit/IO.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module Cardano.Wallet.Deposit.IO

-- ** Mapping between customers and addresses
, listCustomers
, createAddress
, customerAddress

-- ** Reading from the blockchain
, getWalletTip
Expand Down Expand Up @@ -188,20 +188,15 @@ listCustomers :: WalletInstance -> IO [(Customer, Address)]
listCustomers w =
Wallet.listCustomers <$> readWalletState w

createAddress :: Customer -> WalletInstance -> IO Address
createAddress c w =
onWalletState w
$ Delta.updateWithResult
$ \s0 ->
let (r,s1) = Wallet.createAddress c s0
in (Delta.Replace s1, r)
customerAddress :: Customer -> WalletInstance -> IO (Maybe Address)
customerAddress c w = Wallet.customerAddress c <$> readWalletState w

walletPublicIdentity :: WalletInstance -> IO WalletPublicIdentity
walletPublicIdentity w = do
state <- readWalletState w
pure $ WalletPublicIdentity
{ pubXpub = Wallet.walletXPub state
, pubNextUser = Wallet.nextCustomer state
, pubNextUser = Wallet.trackedCustomers state
}
{-----------------------------------------------------------------------------
Operations
Expand Down
17 changes: 7 additions & 10 deletions lib/customer-deposit-wallet/src/Cardano/Wallet/Deposit/Pure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ module Cardano.Wallet.Deposit.Pure
-- ** Mapping between customers and addresses
, Customer
, listCustomers
, createAddress
, deriveAddress
, knownCustomer
, knownCustomerAddress
, isCustomerAddress
, fromRawCustomer
, customerAddress
, trackedCustomers
, walletXPub

-- ** Reading from the blockchain
, fromXPubAndGenesis
Expand All @@ -39,8 +41,6 @@ module Cardano.Wallet.Deposit.Pure

, addTxSubmission
, listTxsInSubmission
, nextCustomer
, walletXPub
) where

import Prelude
Expand Down Expand Up @@ -119,11 +119,8 @@ listCustomers :: WalletState -> [(Customer, Address)]
listCustomers =
Address.listCustomers . addresses

createAddress :: Customer -> WalletState -> (Address, WalletState)
createAddress customer w0 =
(address, w0{addresses = s1})
where
(address, s1) = Address.createAddress customer (addresses w0)
customerAddress :: Customer -> WalletState -> Maybe Address
customerAddress c = lookup c . listCustomers

-- depend on the private key only, not on the entire wallet state
deriveAddress :: WalletState -> (Customer -> Address)
Expand All @@ -146,8 +143,8 @@ isCustomerAddress address =
fromRawCustomer :: Word31 -> Customer
fromRawCustomer = id

nextCustomer :: WalletState -> Customer
nextCustomer = fromIntegral . length . Address.addresses . addresses
trackedCustomers :: WalletState -> Customer
trackedCustomers = fromIntegral . length . Address.addresses . addresses

walletXPub :: WalletState -> XPub
walletXPub = Address.getXPub . addresses
Expand Down
14 changes: 7 additions & 7 deletions lib/customer-deposit-wallet/src/Cardano/Wallet/Deposit/REST.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ module Cardano.Wallet.Deposit.REST

-- ** Mapping between customers and addresses
, listCustomers
, createAddress

-- ** Reading from the blockchain
, getWalletTip
Expand All @@ -47,6 +46,7 @@ module Cardano.Wallet.Deposit.REST
, walletPublicIdentity
, deleteWallet
, deleteTheDepositWalletOnDisk
, customerAddress
) where

import Prelude
Expand Down Expand Up @@ -360,14 +360,14 @@ walletPublicIdentity = onWalletInstance WalletIO.walletPublicIdentity
{-----------------------------------------------------------------------------
Operations
------------------------------------------------------------------------------}
listCustomers
:: WalletResourceM [(Customer, Address)]
-- | List all tracked customers addresses.
listCustomers :: WalletResourceM [(Customer, Address)]
listCustomers = onWalletInstance WalletIO.listCustomers

createAddress
:: Customer
-> WalletResourceM Address
createAddress = onWalletInstance . WalletIO.createAddress
-- | Retrieve the address for a customer if it's tracked by the wallet.

customerAddress :: Customer -> WalletResourceM (Maybe Address)
customerAddress = onWalletInstance . WalletIO.customerAddress

{-----------------------------------------------------------------------------
Operations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ scenarioStart env =
## 1. Assign an address to a customer ID

A `Customer` is represented by a numeric customer ID.
Given such a customer ID, the function `createAddress` will create an address and add the association between the customer and this address to the wallet state.
Given such a customer ID, the function `customerAddress` will create an address and add the association between the customer and this address to the wallet state.

(The mapping from customer ID to address is deterministic and based on the [BIP-32][] address derivation scheme.)

Expand All @@ -104,14 +104,14 @@ scenarioCreateAddressList
:: WalletInstance -> IO ()
scenarioCreateAddressList w = do
let customer = 31
address <- Wallet.createAddress customer w
Just address <- Wallet.customerAddress customer w
customers <- Wallet.listCustomers w
assert $ (customer, address) `elem` customers
```

## 2. Track deposits at this address

As soon as an association between customer and address has been added to the wallet state using `createAddress`, the wallet will track deposits sent to this address.
As soon as an association between customer and address has been added to the wallet state using `customerAddress`, the wallet will track deposits sent to this address.

The function `getCustomerHistory` returns a `TxSummary` for each transaction that is related to this customer. For every `TxSummary`, the `received` field records the total deposit made by the customer at this address in this transaction.

Expand All @@ -123,7 +123,7 @@ The following scenario illustrates how `getCustomerHistory` records deposits:
scenarioTrackDepositOne
:: ScenarioEnv -> WalletInstance -> IO ()
scenarioTrackDepositOne env w = do
address <- Wallet.createAddress customer w
Just address <- Wallet.customerAddress customer w

-- no deposits
txsummaries0<- Wallet.getCustomerHistory customer w
Expand Down Expand Up @@ -158,8 +158,8 @@ The wallet is synchronized to a particular point on the blockchain — use `getW
scenarioTrackDepositAll
:: ScenarioEnv -> WalletInstance -> IO ()
scenarioTrackDepositAll env w = do
address1 <- Wallet.createAddress customer1 w
address2 <- Wallet.createAddress customer2 w
Just address1 <- Wallet.customerAddress customer1 w
Just address2 <- Wallet.customerAddress customer2 w

from <- Wallet.getWalletTip w
depositFundsAt env address1 coin
Expand Down Expand Up @@ -193,7 +193,7 @@ scenarioCreatePayment
:: XPrv -> ScenarioEnv -> Address -> WalletInstance -> IO ()
scenarioCreatePayment xprv env destination w = do
-- deposit some funds at customer address
address1 <- Wallet.createAddress customer w
Just address1 <- Wallet.customerAddress customer w
depositFundsAt env address1 (coin <> coin)
value1 <- Wallet.availableBalance w
assert $ value1 == (coin <> coin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ scenarios = do

it "Assign an address to a customer ID" $ \env -> do
withWalletEnvMock env $ \walletEnv ->
Wallet.withWalletInit walletEnv xpub 1
Wallet.withWalletInit walletEnv xpub 32
Exchanges.scenarioCreateAddressList

describe "Temporary tests" $ do
it "Wallet receives funds that are sent to customer address" $ \env -> do
withWalletEnvMock env $ \walletEnv ->
Wallet.withWalletInit walletEnv xpub 1 $
Wallet.withWalletInit walletEnv xpub 8 $
testBalance env

xpub :: XPub
Expand All @@ -73,7 +73,7 @@ xpub =
testBalance
:: ScenarioEnv -> Wallet.WalletInstance -> IO ()
testBalance env w = do
address <- Wallet.createAddress customer w
Just address <- Wallet.customerAddress customer w
payFromFaucet env [(address, coin)]
value <- Wallet.availableBalance w
assert $ coin == value
Expand Down
11 changes: 8 additions & 3 deletions lib/ui/cardano-wallet-ui.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ common language
OverloadedStrings

common opts-lib
ghc-options: -Wall -Wcompat -Wredundant-constraints -Wunused-packages
-Wunused-imports -Wincomplete-uni-patterns -Wincomplete-record-updates
ghc-options:
-Wall -Wcompat -Wredundant-constraints -Wunused-packages
-Wunused-imports -Wincomplete-uni-patterns
-Wincomplete-record-updates

if flag(release)
ghc-options: -O2 -Werror
Expand All @@ -36,8 +38,8 @@ library
exposed-modules:
Cardano.Wallet.UI.Common.API
Cardano.Wallet.UI.Common.Handlers.Lib
Cardano.Wallet.UI.Common.Handlers.Settings
Cardano.Wallet.UI.Common.Handlers.Session
Cardano.Wallet.UI.Common.Handlers.Settings
Cardano.Wallet.UI.Common.Handlers.SSE
Cardano.Wallet.UI.Common.Handlers.State
Cardano.Wallet.UI.Common.Handlers.Wallet
Expand All @@ -63,6 +65,7 @@ library
Cardano.Wallet.UI.Deposit.Html.Pages.Page
Cardano.Wallet.UI.Deposit.Html.Pages.Wallet
Cardano.Wallet.UI.Deposit.Server
Cardano.Wallet.UI.Lib.Address
Cardano.Wallet.UI.Lib.ListOf
Cardano.Wallet.UI.Shelley.API
Cardano.Wallet.UI.Shelley.Handlers.Addresses
Expand All @@ -84,6 +87,8 @@ library
, aeson
, aeson-pretty
, base
, bech32
, bech32-th
, bytestring
, cardano-addresses
, cardano-slotting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ bodyH sseLink header body = do
div_ [class_ "container-fluid"] $ do
div_ [class_ "main"] body
div_
[class_ "footer"]
[class_ "footer mt-5"]
footerH
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ footerH =
term
"footer_"
[ class_
"text-center text-muted bg-secondary"
"text-center text-muted bg-secondary fs-6"
]
$ do
div_ [class_ "row d-md-flex align-items-center"]
Expand Down
14 changes: 13 additions & 1 deletion lib/ui/src/Cardano/Wallet/UI/Deposit/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE FlexibleInstances #-}

module Cardano.Wallet.UI.Deposit.API where

import Prelude

import Cardano.Wallet.Deposit.Pure
( Customer
)
import Cardano.Wallet.UI.Common.API
( Image
, SessionedHtml
Expand Down Expand Up @@ -49,7 +53,8 @@ import Servant
, (:>)
)
import Web.FormUrlEncoded
( FromForm
( FromForm (..)
, parseUnique
)

import qualified Data.ByteString.Lazy as BL
Expand Down Expand Up @@ -99,6 +104,11 @@ type Data =
:> SessionedHtml Post
:<|> "wallet" :> SessionedHtml Delete
:<|> "wallet" :> "delete" :> "modal" :> SessionedHtml Get
:<|> "customer" :> "address" :> ReqBody '[FormUrlEncoded] Customer
:> SessionedHtml Post

instance FromForm Customer where
fromForm form = fromIntegral @Int <$> parseUnique "customer" form

type Home = SessionedHtml Get

Expand Down Expand Up @@ -126,6 +136,7 @@ walletPostMnemonicLink :: Link
walletPostXPubLink :: Link
walletDeleteLink :: Link
walletDeleteModalLink :: Link
customerAddressLink :: Link
homePageLink
:<|> aboutPageLink
:<|> networkPageLink
Expand All @@ -142,5 +153,6 @@ homePageLink
:<|> walletPostXPubLink
:<|> walletDeleteLink
:<|> walletDeleteModalLink
:<|> customerAddressLink
=
allLinks (Proxy @UI)
Loading
Loading