Skip to content

Commit

Permalink
add Api scaffolding and types to core
Browse files Browse the repository at this point in the history
  • Loading branch information
paweljakubas committed Jan 26, 2021
1 parent cd77c1b commit 18425a5
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 17 deletions.
10 changes: 10 additions & 0 deletions lib/core/src/Cardano/Wallet/Api.hs
Expand Up @@ -32,6 +32,7 @@ module Cardano.Wallet.Api
, WalletKeys
, GetWalletKey
, SignMetadata
, GetAccountKey

, Assets
, ListAssets
Expand Down Expand Up @@ -124,6 +125,7 @@ import Cardano.Wallet
( WalletLayer (..), WalletLog )
import Cardano.Wallet.Api.Types
( AnyAddress
, ApiAccountKey
, ApiAddressData
, ApiAddressIdT
, ApiAddressInspect
Expand Down Expand Up @@ -313,6 +315,7 @@ type GetUTxOsStatistics = "wallets"
type WalletKeys =
GetWalletKey
:<|> SignMetadata
:<|> GetAccountKey

-- | https://input-output-hk.github.io/cardano-wallet/api/#operation/getWalletKey
type GetWalletKey = "wallets"
Expand All @@ -331,6 +334,13 @@ type SignMetadata = "wallets"
:> ReqBody '[JSON] ApiWalletSignData
:> Post '[OctetStream] ByteString

-- | https://input-output-hk.github.io/cardano-wallet/api/#operation/getAccountExtendedKey
type GetAccountKey = "wallets"
:> Capture "walletId" (ApiT WalletId)
:> "keys"
:> Capture "accountIx" (ApiT DerivationIndex)
:> Get '[JSON] ApiAccountKey

{-------------------------------------------------------------------------------
Assets
Expand Down
15 changes: 15 additions & 0 deletions lib/core/src/Cardano/Wallet/Api/Server.hs
Expand Up @@ -80,6 +80,7 @@ module Cardano.Wallet.Api.Server
, selectCoinsForJoin
, selectCoinsForQuit
, signMetadata
, getAccountPublicKey

-- * Internals
, LiftHandler(..)
Expand Down Expand Up @@ -165,6 +166,7 @@ import Cardano.Wallet.Api.Server.Tls
import Cardano.Wallet.Api.Types
( AccountPostData (..)
, AddressAmount (..)
, ApiAccountKey
, ApiAccountPublicKey (..)
, ApiAddress (..)
, ApiAsset (..)
Expand Down Expand Up @@ -1915,6 +1917,19 @@ derivePublicKey ctx (ApiT wid) (ApiT role_) (ApiT ix) = do
k <- liftHandler $ W.derivePublicKey @_ @s @k @n wrk wid role_ ix
pure $ ApiVerificationKey (xpubPublicKey $ getRawKey k, role_)

getAccountPublicKey
:: forall ctx s k n.
( s ~ SeqState n k
, ctx ~ ApiLayer s k
, SoftDerivation k
, WalletKey k
)
=> ctx
-> ApiT WalletId
-> ApiT DerivationIndex
-> Handler ApiAccountKey
getAccountPublicKey _ctx (ApiT _wid) (ApiT _ix) = undefined

{-------------------------------------------------------------------------------
Helpers
-------------------------------------------------------------------------------}
Expand Down
41 changes: 39 additions & 2 deletions lib/core/src/Cardano/Wallet/Api/Types.hs
Expand Up @@ -115,6 +115,7 @@ module Cardano.Wallet.Api.Types
, ApiWithdrawal (..)
, ApiWalletSignData (..)
, ApiVerificationKey (..)
, ApiAccountKey (..)

-- * API Types (Byron)
, ApiByronWallet (..)
Expand Down Expand Up @@ -250,8 +251,8 @@ import Control.Arrow
import Control.DeepSeq
( NFData )
import Control.Monad
( guard, (>=>) )
import Data.Aeson.Types
( guard, unless, (>=>) )
import Data.Aeson
( FromJSON (..)
, SumEncoding (..)
, ToJSON (..)
Expand Down Expand Up @@ -940,6 +941,11 @@ newtype ApiVerificationKey = ApiVerificationKey
} deriving (Eq, Generic, Show)
deriving anyclass NFData

newtype ApiAccountKey = ApiAccountKey
{ getApiAccountKey :: ByteString
} deriving (Eq, Generic, Show)
deriving anyclass NFData

-- | Error codes returned by the API, in the form of snake_cased strings
data ApiErrorCode
= NoSuchWallet
Expand Down Expand Up @@ -1256,6 +1262,37 @@ instance FromJSON ApiVerificationKey where
| otherwise =
fail "Not a valid Ed25519 public key. Must be 32 bytes, without chain code"

instance ToJSON ApiAccountKey where
toJSON (ApiAccountKey pub) =
toJSON $ Bech32.encodeLenient hrp $ dataPartFromBytes pub
where
hrp = [humanReadablePart|acct_xvk|]

instance FromJSON ApiAccountKey where
parseJSON value = do
(hrp, bytes) <- parseJSON value >>= parseBech32
unless (hrp == [humanReadablePart|acct_xvk|]) $
fail "Wrong human-readable part. Expected : \"acct_xvk\"."
ApiAccountKey <$> parsePub bytes
where
parseBech32 =
either (const $ fail errBech32) parseDataPart . Bech32.decodeLenient
where
errBech32 =
"Malformed extended account public key. Expected a bech32-encoded key."

parseDataPart =
maybe (fail errDataPart) pure . traverse dataPartToBytes
where
errDataPart =
"Couldn't decode data-part to valid UTF-8 bytes."

parsePub bytes
| BS.length bytes == 64 =
pure bytes
| otherwise =
fail "Not a valid Ed25519 extended public key. Must be 64 bytes, with chain code"

instance FromJSON ApiEpochInfo where
parseJSON = genericParseJSON defaultRecordTypeOptions
instance ToJSON ApiEpochInfo where
Expand Down
2 changes: 2 additions & 0 deletions lib/shelley/src/Cardano/Wallet/Shelley/Api/Server.hs
Expand Up @@ -59,6 +59,7 @@ import Cardano.Wallet.Api.Server
, deleteTransaction
, deleteWallet
, derivePublicKey
, getAccountPublicKey
, getAsset
, getAssetDefault
, getCurrentEpoch
Expand Down Expand Up @@ -225,6 +226,7 @@ server byron icarus shelley spl ntp =
walletKeys :: Server WalletKeys
walletKeys = derivePublicKey shelley
:<|> signMetadata shelley
:<|> getAccountPublicKey shelley

assets :: Server Assets
assets = listAssets shelley :<|> getAsset shelley :<|> getAssetDefault shelley
Expand Down
34 changes: 19 additions & 15 deletions specifications/api/swagger.yaml
Expand Up @@ -1561,6 +1561,11 @@ components:
format: bech32
pattern: "^((addr_vk)|(stake_vk)|(script_vk))1[0-9a-z]*$"

ApiAccountKey: &ApiAccountKey
type: string
format: bech32
pattern: "^(acct_xvk)1[0-9a-z]*$"

ApiTxId: &ApiTxId
type: object
required:
Expand Down Expand Up @@ -2177,17 +2182,6 @@ x-parametersWalletId: &parametersWalletId
maxLength: 40
minLength: 40

x-parametersAccountIx: &parametersAccountIx
in: path
name: accountIx
required: true
schema:
type: integer
minimum: 2147483648
maximum: 4294967295
description: |
The account index for Shelley account uses hard derivation, ie., indices (2 ^ 31, 2 ^ 32 - 1).
x-parametersIntendedStakeAmount: &parametersIntendedStakeAmount
in: query
name: stake
Expand Down Expand Up @@ -3303,6 +3297,16 @@ x-responsesGetKey: &responsesGetKey
application/json:
schema: *ApiVerificationKey

x-responsesGetAccountKey: &responsesGetAccountKey
<<: *responsesErr400
<<: *responsesErr404
<<: *responsesErr406
200:
description: Ok
content:
application/json:
schema: *ApiAccountKey

x-responsesListStakePools: &responsesListStakePools
400:
description: Bad Request
Expand Down Expand Up @@ -3800,19 +3804,19 @@ paths:
- *parametersAddressState
responses: *responsesListAddresses

/wallets/{walletId}/keys/{accountIx}:
/wallets/{walletId}/keys/{index}:
get:
operationId: getAccountExtendedKey
tags: ["Keys"]
summary: Get Account Extended Public Key
description: |
<p align="right">status: <strong>stable</strong></p>
Return an extended account public key for a given account index.
Return an extended account public key for a given account index (hard derivation is used).
parameters:
- *parametersWalletId
- *parametersAccountIx
responses: *responsesGetKey
- *parametersDerivationSegment
responses: *responsesGetAccountKey

/wallets/{walletId}/keys/{role}/{index}:
get:
Expand Down

0 comments on commit 18425a5

Please sign in to comment.