Skip to content
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 cardano-wasm/cardano-wasm.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ library cardano-wasi-lib
src-lib

exposed-modules:
Cardano.Wasm.Api.Certificate.StakeCertificate
Cardano.Wasm.Api.GRPC
Cardano.Wasm.Api.Info
Cardano.Wasm.Api.InfoToTypeScript
Expand All @@ -39,6 +40,7 @@ library cardano-wasi-lib
Cardano.Wasm.ExceptionHandling

other-modules:
Cardano.Wasm.Internal.Api.Era
Cardano.Wasm.Internal.Api.Random

build-depends:
Expand Down Expand Up @@ -77,8 +79,9 @@ executable cardano-wasi
if arch(wasm32)
ghc-options:
-no-hs-main
"-optl-Wl,--strip-all,--export=hs_init,--export=newTx,--export=newExperimentalEraTx,--export=newConwayTx,--export=addTxInput,--export=addSimpleTxOut,--export=appendCertificateToTx,--export=setFee,--export=estimateMinFee,--export=signWithPaymentKey,--export=alsoSignWithPaymentKey,--export=toCbor,--export=generatePaymentWallet,--export=generateStakeWallet,--export=restorePaymentWalletFromSigningKeyBech32,--export=restoreStakeWalletFromSigningKeyBech32,--export=generateTestnetPaymentWallet,--export=generateTestnetStakeWallet,--export=restoreTestnetPaymentWalletFromSigningKeyBech32,--export=restoreTestnetStakeWalletFromSigningKeyBech32,--export=getAddressBech32,--export=getBech32ForPaymentVerificationKey,--export=getBech32ForPaymentSigningKey,--export=getBech32ForStakeVerificationKey,--export=getBech32ForStakeSigningKey,--export=getBase16ForPaymentVerificationKeyHash,--export=getBase16ForStakeVerificationKeyHash,--export=mallocNBytes,--export=getStrLen,--export=freeMemory"
"-optl-Wl,--strip-all,--export=hs_init,--export=newTx,--export=newUpcomingEraTx,--export=addTxInput,--export=addSimpleTxOut,--export=appendCertificateToTx,--export=setFee,--export=estimateMinFee,--export=signWithPaymentKey,--export=alsoSignWithPaymentKey,--export=toCbor,--export=makeStakeAddressStakeDelegationCertificate,--export=makeStakeAddressStakeDelegationCertificateUpcomingEra,--export=makeStakeAddressRegistrationCertificate,--export=makeStakeAddressRegistrationCertificateUpcomingEra,--export=makeStakeAddressUnregistrationCertificate,--export=makeStakeAddressUnregistrationCertificateUpcomingEra,--export=generatePaymentWallet,--export=generateStakeWallet,--export=restorePaymentWalletFromSigningKeyBech32,--export=restoreStakeWalletFromSigningKeyBech32,--export=generateTestnetPaymentWallet,--export=generateTestnetStakeWallet,--export=restoreTestnetPaymentWalletFromSigningKeyBech32,--export=restoreTestnetStakeWalletFromSigningKeyBech32,--export=getAddressBech32,--export=getBech32ForPaymentVerificationKey,--export=getBech32ForPaymentSigningKey,--export=getBech32ForStakeVerificationKey,--export=getBech32ForStakeSigningKey,--export=getBase16ForPaymentVerificationKeyHash,--export=getBase16ForStakeVerificationKeyHash,--export=mallocNBytes,--export=getStrLen,--export=freeMemory"
other-modules:
Cardano.Wasi.Internal.Api.Certificate.StakeCertificate
Cardano.Wasi.Internal.Api.GRPC
Cardano.Wasi.Internal.Api.Memory
Cardano.Wasi.Internal.Api.Tx
Expand Down
2 changes: 1 addition & 1 deletion cardano-wasm/js-test/basic-test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ test('test output matches', async ({ page }) => {
// Wait for the test to finish running (we signal this by creating a tag with id "finish-tag" and text "Finished test!")
await expect(page.locator('#finish-tag')).toHaveText("Finished test!");
// Check the output of the test (from the example folder), which is displayed in the code element with id "test-output". The output contains information about the various objects and results of trying some of the functions.
await expect(page.locator('#test-output')).toHaveText("> \"Api object:\"> [object] { objectType: cardano-api tx: [object Object] newGrpcConnection: async function (...args) wallet: [object Object] }> \"Bech32 of address:\"> \"addr_test1vp93p9em3regvgylxuvet6fgr3e9sn259pcejgrk4ykystcs7v8j6\"> \"UnsignedTx object:\"> [object] { objectType: UnsignedTx addTxInput: function (txId,txIx) addSimpleTxOut: function (destAddr,lovelaceAmount) appendCertificateToTx: function (certCbor) setFee: function (lovelaceAmount) estimateMinFee: function (protocolParams,numKeyWitnesses,numByronKeyWitnesses,totalRefScriptSize) signWithPaymentKey: function (signingKey) }> \"Estimated fee:\"> 164005n> \"SignedTx object:\"> [object] { objectType: SignedTx alsoSignWithPaymentKey: function (signingKey) txToCbor: function () }> \"Tx CBOR:\"> \"84a300d9010281825820be6efd42a3d7b9a00d09d77a5d41e55ceaf0bd093a8aa8a893ce70d9caafd97800018182581d6082935e44937e8b530f32ce672b5d600d0a286b4e8a52c6555f659b871a00989680021a000280a5a100d9010281825820adfc1c30385916da87db1ba3328f0690a57ebb2a6ac9f6f86b2d97f943adae005840a49259b5977aea523b46f01261fbff93e0899e8700319e11f5ab96b67eb628fca1a233ce2d50ee3227b591b84f27237d920d63974d65728362382f751c4d9400f5f6\"");
await expect(page.locator('#test-output')).toHaveText("> \"Api object:\"> [object] {    objectType: cardano-api    tx: [object Object]    newGrpcConnection: async function (...args)    certificate: [object Object]    wallet: [object Object]  }> \"Bech32 of address:\"> \"addr_test1vp93p9em3regvgylxuvet6fgr3e9sn259pcejgrk4ykystcs7v8j6\"> \"UnsignedTx object:\"> [object] {    objectType: UnsignedTx    addTxInput: function (txId,txIx)    addSimpleTxOut: function (destAddr,lovelaceAmount)    appendCertificateToTx: function (certCbor)    setFee: function (lovelaceAmount)    estimateMinFee: function (protocolParams,numKeyWitnesses,numByronKeyWitnesses,totalRefScriptSize)    signWithPaymentKey: function (signingKey)  }> \"Estimated fee:\"> 164005n> \"SignedTx object:\"> [object] {    objectType: SignedTx    alsoSignWithPaymentKey: function (signingKey)    txToCbor: function ()  }> \"Tx CBOR:\"> \"84a300d9010281825820be6efd42a3d7b9a00d09d77a5d41e55ceaf0bd093a8aa8a893ce70d9caafd97800018182581d6082935e44937e8b530f32ce672b5d600d0a286b4e8a52c6555f659b871a00989680021a000280a5a100d9010281825820adfc1c30385916da87db1ba3328f0690a57ebb2a6ac9f6f86b2d97f943adae005840a49259b5977aea523b46f01261fbff93e0899e8700319e11f5ab96b67eb628fca1a233ce2d50ee3227b591b84f27237d920d63974d65728362382f751c4d9400f5f6\"");
});
73 changes: 65 additions & 8 deletions cardano-wasm/lib-wrapper/cardano-api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,10 @@ declare interface CardanoApi {
newTx(): Promise<UnsignedTx>;

/**
* Create a new unsigned transaction in the current experimental era (currently unavailable).
* Create a new unsigned transaction in the current upcoming era (currently Dijkstra).
* @returns A promise that resolves to a new `UnsignedTx` object.
*/
newExperimentalEraTx(): Promise<UnsignedTx>;

/**
* Create a new unsigned transaction in the Conway era.
* @returns A promise that resolves to a new `UnsignedTx` object.
*/
newConwayTx(): Promise<UnsignedTx>;
newUpcomingEraTx(): Promise<UnsignedTx>;
}

/**
Expand All @@ -45,6 +39,69 @@ declare interface CardanoApi {
*/
newGrpcConnection(webGrpcUrl: string): Promise<GrpcConnection>;

/**
* Methods for creating certificates.
*/
certificate: {
/**
* Methods for creating certificates in the current era (currently Conway).
*/
currentEra: {
/**
* Make a certificate that delegates a stake address to a stake pool in the current era (currently Conway).
* @param stakeKeyHash The stake key hash in base16 format.
* @param poolId The pool ID in base16 format.
* @returns A promise that resolves to the CBOR-encoded certificate as a hex string.
*/
makeStakeAddressStakeDelegationCertificate(stakeKeyHash: string, poolId: string): Promise<string>;

/**
* Make a stake address registration certificate in the current era (currently Conway).
* @param stakeKeyHash The stake key hash in base16 format.
* @param deposit The deposit amount in lovelaces.
* @returns A promise that resolves to the CBOR-encoded certificate as a hex string.
*/
makeStakeAddressRegistrationCertificate(stakeKeyHash: string, deposit: bigint): Promise<string>;

/**
* Make a stake address unregistration certificate in the current era (currently Conway).
* @param stakeKeyHash The stake key hash in base16 format.
* @param deposit The deposit amount in lovelaces.
* @returns A promise that resolves to the CBOR-encoded certificate as a hex string.
*/
makeStakeAddressUnregistrationCertificate(stakeKeyHash: string, deposit: bigint): Promise<string>;
}

/**
* Methods for creating certificates in the current upcoming era (currently Dijkstra).
*/
upcomingEra: {
/**
* Make a certificate that delegates a stake address to a stake pool in the current upcoming era (currently Dijkstra).
* @param stakeKeyHash The stake key hash in base16 format.
* @param poolId The pool ID in base16 format.
* @returns A promise that resolves to the CBOR-encoded certificate as a hex string.
*/
makeStakeAddressStakeDelegationCertificateUpcomingEra(stakeKeyHash: string, poolId: string): Promise<string>;

/**
* Make a stake address registration certificate in the current upcoming era (currently Dijkstra).
* @param stakeKeyHash The stake key hash in base16 format.
* @param deposit The deposit amount in lovelaces.
* @returns A promise that resolves to the CBOR-encoded certificate as a hex string.
*/
makeStakeAddressRegistrationCertificateUpcomingEra(stakeKeyHash: string, deposit: bigint): Promise<string>;

/**
* Make a stake address unregistration certificate in the current upcoming era (currently Dijkstra).
* @param stakeKeyHash The stake key hash in base16 format.
* @param deposit The deposit amount in lovelaces.
* @returns A promise that resolves to the CBOR-encoded certificate as a hex string.
*/
makeStakeAddressUnregistrationCertificateUpcomingEra(stakeKeyHash: string, deposit: bigint): Promise<string>;
}
}

/**
* Methods for generating and restoring wallets.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Cardano.Wasm.Api.Certificate.StakeCertificate
( makeStakeAddressStakeDelegationCertificateImpl
, makeStakeAddressStakeDelegationCertificateUpcomingEraImpl
, makeStakeAddressRegistrationCertificateImpl
, makeStakeAddressRegistrationCertificateUpcomingEraImpl
, makeStakeAddressUnregistrationCertificateImpl
, makeStakeAddressUnregistrationCertificateUpcomingEraImpl
)
where

import Cardano.Api
( Coin (..)
, Hash
, PoolId
, StakeKey
, serialiseToCBOR
, unStakePoolKeyHash
)
import Cardano.Api.Address (StakeCredential (..))
import Cardano.Api.Experimental (Era (..), obtainCommonConstraints)
import Cardano.Api.Experimental qualified as Exp
import Cardano.Api.Experimental.Certificate (Certificate (..))
import Cardano.Api.Serialise.Raw qualified as Api

import Cardano.Ledger.Api (Delegatee (DelegStake))
import Cardano.Wasm.ExceptionHandling (justOrError, rightOrError)
import Cardano.Wasm.Internal.Api.Era (currentEra, upcomingEra)

import Control.Monad.Catch (MonadThrow)
import Data.ByteString.Base16 qualified as Base16
import Data.Text qualified as Text
import Data.Text.Encoding qualified as Text

-- * Type aliases for clarity

-- | A stake key hash represented as a base16-encoded string.
type StakeKeyHashBase16 = String

-- | A pool ID represented as a base16-encoded string.
type PoolIdBase16 = String

-- | Deposit amount in lovelace.
type DepositLovelace = Integer

-- | Certificate serialized to CBOR as a base16-encoded string.
type CertificateCBORBase16 = String

-- * Stake Certificate function implementation

-- | Make a certificate that delegates a stake address to a stake pool in the current era.
makeStakeAddressStakeDelegationCertificateImpl
:: MonadThrow m => StakeKeyHashBase16 -> PoolIdBase16 -> m CertificateCBORBase16
makeStakeAddressStakeDelegationCertificateImpl skHashStr poolIdStr = do
stakeCertHash <- readHash skHashStr
poolId <- readPoolId poolIdStr
makeStakeAddressStakeDelegationCertificate currentEra stakeCertHash poolId

-- | Make a certificate that delegates a stake address to a stake pool in the current upcoming era.
makeStakeAddressStakeDelegationCertificateUpcomingEraImpl
:: MonadThrow m => StakeKeyHashBase16 -> PoolIdBase16 -> m CertificateCBORBase16
makeStakeAddressStakeDelegationCertificateUpcomingEraImpl skHashStr poolIdStr = do
stakeCertHash <- readHash skHashStr
poolId <- readPoolId poolIdStr
era <- justOrError "No upcoming era available" upcomingEra
makeStakeAddressStakeDelegationCertificate era stakeCertHash poolId

makeStakeAddressStakeDelegationCertificate
:: forall era m. MonadThrow m => Exp.Era era -> Hash StakeKey -> PoolId -> m CertificateCBORBase16
makeStakeAddressStakeDelegationCertificate era stakeCertHash poolId =
obtainCommonConstraints era $ do
let cert :: Certificate (Exp.LedgerEra era) =
Exp.makeStakeAddressDelegationCertificate
(StakeCredentialByKey stakeCertHash)
( case era of
ConwayEra -> DelegStake $ unStakePoolKeyHash poolId
DijkstraEra -> DelegStake $ unStakePoolKeyHash poolId
)
return $ serialiseCertificateToCBOR era cert

-- | Make a stake address registration certificate in the current era.
makeStakeAddressRegistrationCertificateImpl
:: MonadThrow m => StakeKeyHashBase16 -> DepositLovelace -> m CertificateCBORBase16
makeStakeAddressRegistrationCertificateImpl skHashStr deposit = do
skHash <- readHash skHashStr
makeStakeAddressRegistrationCertificateWrapper currentEra skHash deposit

--  | Make a stake address registration certificate in the upcoming era.
makeStakeAddressRegistrationCertificateUpcomingEraImpl
:: MonadThrow m => StakeKeyHashBase16 -> DepositLovelace -> m CertificateCBORBase16
makeStakeAddressRegistrationCertificateUpcomingEraImpl skHashStr deposit = do
skHash <- readHash skHashStr
era <- justOrError "No upcoming era available" upcomingEra
makeStakeAddressRegistrationCertificateWrapper era skHash deposit

makeStakeAddressRegistrationCertificateWrapper
:: forall era m. MonadThrow m => Era era -> Hash StakeKey -> DepositLovelace -> m CertificateCBORBase16
makeStakeAddressRegistrationCertificateWrapper era skHash deposit =
obtainCommonConstraints era $ do
let cert :: Certificate (Exp.LedgerEra era) =
Exp.makeStakeAddressRegistrationCertificate
(StakeCredentialByKey skHash)
(Coin deposit)
return $ serialiseCertificateToCBOR era cert

-- | Make a stake address unregistration certificate in the current era.
makeStakeAddressUnregistrationCertificateImpl
:: MonadThrow m => StakeKeyHashBase16 -> DepositLovelace -> m CertificateCBORBase16
makeStakeAddressUnregistrationCertificateImpl skHashStr deposit = do
skHash <- readHash skHashStr
makeStakeAddressUnregistrationCertificateWrapper currentEra skHash deposit

-- | Make a stake address unregistration certificate in the upcoming era.
makeStakeAddressUnregistrationCertificateUpcomingEraImpl
:: MonadThrow m => StakeKeyHashBase16 -> DepositLovelace -> m CertificateCBORBase16
makeStakeAddressUnregistrationCertificateUpcomingEraImpl skHashStr deposit = do
skHash <- readHash skHashStr
era <- justOrError "No upcoming era available" upcomingEra
makeStakeAddressUnregistrationCertificateWrapper era skHash deposit

makeStakeAddressUnregistrationCertificateWrapper
:: forall era m. MonadThrow m => Era era -> Hash StakeKey -> DepositLovelace -> m CertificateCBORBase16
makeStakeAddressUnregistrationCertificateWrapper era skHash deposit =
obtainCommonConstraints era $ do
let cert :: Certificate (Exp.LedgerEra era) =
Exp.makeStakeAddressUnregistrationCertificate
(StakeCredentialByKey skHash)
(Coin deposit)
return $ serialiseCertificateToCBOR era cert

serialiseCertificateToCBOR
:: Exp.Era era -> Certificate (Exp.LedgerEra era) -> CertificateCBORBase16
serialiseCertificateToCBOR era cert =
obtainCommonConstraints era $ do
Text.unpack $
Text.decodeUtf8 $
Base16.encode $
serialiseToCBOR
cert

readHash :: MonadThrow m => StakeKeyHashBase16 -> m (Hash StakeKey)
readHash = rightOrError . Api.deserialiseFromRawBytesHex . Text.encodeUtf8 . Text.pack

readPoolId :: MonadThrow m => PoolIdBase16 -> m PoolId
readPoolId = rightOrError . Api.deserialiseFromRawBytesHex . Text.encodeUtf8 . Text.pack
2 changes: 1 addition & 1 deletion cardano-wasm/src-lib/Cardano/Wasm/Api/GRPC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Data.ByteString.Char8 qualified as BS
newtype GrpcObject grpcClient
= GrpcObject grpcClient

-- | Create a new unsigned transaction object for making a Conway era transaction.
-- | Create a new gRPC or GRPC-web connection to the Cardano Node.
newGrpcConnectionImpl :: (String -> IO grpcClient) -> String -> IO (GrpcObject grpcClient)
newGrpcConnectionImpl createClientFunc host = GrpcObject <$> createClientFunc host

Expand Down
Loading
Loading