From 2a1894e4efe911cf7256ffe00bf02d6f3272d96c Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Mon, 25 Sep 2023 15:58:23 +0400 Subject: [PATCH] Hardcode collateral value on the PS side, not in JS FFI --- src/Internal/Serialization/ToBytes.purs | 2 ++ src/Internal/Wallet/Cip30.js | 17 +++------------ src/Internal/Wallet/Cip30.purs | 29 ++++++++++++++++++++----- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Internal/Serialization/ToBytes.purs b/src/Internal/Serialization/ToBytes.purs index f46868ccd..e9b14b87e 100644 --- a/src/Internal/Serialization/ToBytes.purs +++ b/src/Internal/Serialization/ToBytes.purs @@ -32,6 +32,7 @@ import Ctl.Internal.Serialization.Types , Vkeywitness , Vkeywitnesses ) +import Ctl.Internal.Types.BigNum (BigNum) import Ctl.Internal.Types.ByteArray (ByteArray) import Ctl.Internal.Types.CborBytes (CborBytes(CborBytes)) import Untagged.Castable (class Castable) @@ -63,6 +64,7 @@ type SerializableData = Address |+| VRFKeyHash |+| Vkeywitness |+| Vkeywitnesses + |+| BigNum -- Add more as needed diff --git a/src/Internal/Wallet/Cip30.js b/src/Internal/Wallet/Cip30.js index ad274ce3d..dd46b8800 100644 --- a/src/Internal/Wallet/Cip30.js +++ b/src/Internal/Wallet/Cip30.js @@ -5,21 +5,10 @@ exports._getNetworkId = conn => () => conn.getNetworkId(); exports._getUtxos = maybe => conn => () => conn.getUtxos().then(res => (res === null ? maybe.nothing : maybe.just(res))); -exports._getCollateral = maybe => conn => () => - /* Notes regarding the quirks of various wallets: - - Yoroi will throw an error if no amount argument is provided, and will - break if the following expression is written as - (conn.getCollateral || conn.experimental.getCollateral)("5000000") due to - JavaScript object binding - - Typhon will throw an error if the amount argument is not a string - - Nami only provides `getCollateral` under the experimental API - */ +exports._getCollateral = maybe => conn => requiredValue => () => (typeof conn.getCollateral === "function" - ? conn.getCollateral("5000000") - : conn.experimental.getCollateral("5000000") + ? conn.getCollateral(requiredValue) + : conn.experimental.getCollateral(requiredValue) ).then(utxos => utxos !== null && utxos.length ? maybe.just(utxos) : maybe.nothing ); diff --git a/src/Internal/Wallet/Cip30.purs b/src/Internal/Wallet/Cip30.purs index 32e0dfb80..57e05150d 100644 --- a/src/Internal/Wallet/Cip30.purs +++ b/src/Internal/Wallet/Cip30.purs @@ -18,7 +18,7 @@ import Ctl.Internal.Cardano.Types.Transaction import Ctl.Internal.Cardano.Types.TransactionUnspentOutput ( TransactionUnspentOutput ) -import Ctl.Internal.Cardano.Types.Value (Value) +import Ctl.Internal.Cardano.Types.Value (Coin(Coin), Value) import Ctl.Internal.Deserialization.FromBytes (fromBytes, fromBytesEffect) import Ctl.Internal.Deserialization.UnspentOutput (convertValue) import Ctl.Internal.Deserialization.UnspentOutput as Deserialization.UnspentOuput @@ -36,6 +36,8 @@ import Ctl.Internal.Serialization.Address , rewardAddressBytes , rewardAddressFromAddress ) +import Ctl.Internal.Serialization.ToBytes (toBytes) +import Ctl.Internal.Types.BigNum as BigNum import Ctl.Internal.Types.ByteArray (byteArrayToHex) import Ctl.Internal.Types.CborBytes ( CborBytes @@ -44,6 +46,7 @@ import Ctl.Internal.Types.CborBytes , rawBytesAsCborBytes ) import Ctl.Internal.Types.RawBytes (RawBytes, hexToRawBytes, rawBytesToHex) +import Data.BigInt (fromInt) as BigInt import Data.Maybe (Maybe(Just, Nothing), maybe) import Data.Newtype (unwrap) import Data.Traversable (for, traverse) @@ -140,12 +143,15 @@ getWalletAddresses conn = Promise.toAffE (_getAddresses conn) <#> hexStringToAddress :: String -> Maybe Address hexStringToAddress = fromBytes <<< rawBytesAsCborBytes <=< hexToRawBytes +defaultCollateralAmount :: Coin +defaultCollateralAmount = Coin $ BigInt.fromInt 5_000_000 + -- | Get collateral using CIP-30 `getCollateral` method. -- | Throws on `Promise` rejection by wallet, returns `Nothing` if no collateral -- | is available. getCollateral :: Cip30Connection -> Aff (Maybe (Array TransactionUnspentOutput)) getCollateral conn = do - mbUtxoStrs <- toAffE $ getCip30Collateral conn + mbUtxoStrs <- toAffE $ getCip30Collateral conn defaultCollateralAmount let (mbUtxoBytes :: Maybe (Array RawBytes)) = join $ map (traverse hexToRawBytes) mbUtxoStrs @@ -238,12 +244,23 @@ foreign import _getUtxos foreign import _getCollateral :: MaybeFfiHelper -> Cip30Connection + -> String -> Effect (Promise (Maybe (Array String))) -getCip30Collateral :: Cip30Connection -> Effect (Promise (Maybe (Array String))) -getCip30Collateral conn = - _getCollateral maybeFfiHelper conn `catchError` - \_ -> throwError $ error "Wallet doesn't implement `getCollateral`." +getCip30Collateral + :: Cip30Connection -> Coin -> Effect (Promise (Maybe (Array String))) +getCip30Collateral conn requiredValue = do + bigNumValue <- maybe (throw convertError) pure + $ BigNum.fromBigInt + $ unwrap requiredValue + let requiredValueStr = byteArrayToHex $ unwrap $ toBytes bigNumValue + _getCollateral maybeFfiHelper conn requiredValueStr `catchError` + \err -> throwError $ error $ + "Failed to call `getCollateral`: " <> show err + where + convertError = + "Unable to convert CIP-30 getCollateral required value: " <> + show requiredValue foreign import _getBalance :: Cip30Connection -> Effect (Promise String)