Skip to content

Commit

Permalink
[ADP-3436] Add customer address query to UI (#4780)
Browse files Browse the repository at this point in the history
- Add a UI query form to get individual addresses for "customers"
- Remove support for `createAddress` 
- Fix tests and scenarios using `createAddress` to use `customerAddress`
and start the wallet with a big enough tracked customer numbers

ADP-3436
  • Loading branch information
paolino authored Sep 23, 2024
2 parents b7558e2 + d265de6 commit d5afc6e
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 63 deletions.
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

0 comments on commit d5afc6e

Please sign in to comment.