Skip to content

Commit 18b8390

Browse files
committed
Make HydraHeadPeer type extendable
1 parent 2059aca commit 18b8390

File tree

5 files changed

+83
-19
lines changed

5 files changed

+83
-19
lines changed

example/minimal/src/Config.purs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module HydraSdk.Example.Minimal.Config
66
import Prelude
77

88
import Cardano.Types (TransactionInput)
9-
import Data.Codec.Argonaut (JsonCodec, object, printJsonDecodeError, string) as CA
9+
import Data.Codec.Argonaut (JsonCodec, object, printJsonDecodeError, record, string) as CA
1010
import Data.Codec.Argonaut.Compat (maybe) as CA
1111
import Data.Codec.Argonaut.Record (record) as CAR
1212
import Data.Either (either)
@@ -20,7 +20,7 @@ import Node.Path (FilePath)
2020
import Node.Process (argv)
2121

2222
type DelegateServerConfig =
23-
{ hydraNodeStartupParams :: HydraNodeStartupParams
23+
{ hydraNodeStartupParams :: HydraNodeStartupParams ()
2424
, blockfrostApiKeyFile :: FilePath
2525
, logLevel :: LogLevel
2626
, ctlLogLevel :: LogLevel
@@ -30,7 +30,7 @@ type DelegateServerConfig =
3030
delegateServerConfigCodec :: CA.JsonCodec DelegateServerConfig
3131
delegateServerConfigCodec =
3232
CA.object "DelegateServerConfig" $ CAR.record
33-
{ hydraNodeStartupParams: hydraNodeStartupParamsCodec
33+
{ hydraNodeStartupParams: hydraNodeStartupParamsCodec CA.record
3434
, blockfrostApiKeyFile: CA.string
3535
, logLevel: logLevelCodec
3636
, ctlLogLevel: logLevelCodec

spago-packages.nix

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,18 @@ let
11811181
installPhase = "ln -s $src $out";
11821182
};
11831183

1184+
"record-extra" = pkgs.stdenv.mkDerivation {
1185+
name = "record-extra";
1186+
version = "v5.0.1";
1187+
src = pkgs.fetchgit {
1188+
url = "https://github.com/justinwoo/purescript-record-extra.git";
1189+
rev = "a9a4b8201d154513017048fc41efa0eefa48fba2";
1190+
sha256 = "0190igayc2ghzjg1ggwl0dv0b2b7sg16n5dm9fyi39ygp48fvshp";
1191+
};
1192+
phases = "installPhase";
1193+
installPhase = "ln -s $src $out";
1194+
};
1195+
11841196
"refs" = pkgs.stdenv.mkDerivation {
11851197
name = "refs";
11861198
version = "v6.0.0";

spago.dhall

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
, "profunctor"
4545
, "quickcheck"
4646
, "record"
47+
, "record-extra"
4748
, "safely"
4849
, "spec"
4950
, "strings"

src/Internal/Lib/Codec.purs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module HydraSdk.Internal.Lib.Codec
2525
, toCaJsonDecodeError
2626
, txCodec
2727
, txHashCodec
28+
, unionRecordCodecs
2829
) where
2930

3031
import Prelude
@@ -67,7 +68,9 @@ import Data.Argonaut
6768
import Data.Bifunctor (lmap)
6869
import Data.ByteArray (ByteArray, byteArrayToHex, hexToByteArray)
6970
import Data.Codec.Argonaut
70-
( JsonCodec
71+
( Codec(Codec)
72+
, JPropCodec
73+
, JsonCodec
7174
, JsonDecodeError(TypeMismatch, UnexpectedValue, AtIndex, AtKey, Named, MissingValue)
7275
, codec'
7376
, decode
@@ -86,13 +89,44 @@ import Data.Newtype (wrap)
8689
import Data.Profunctor (wrapIso)
8790
import Data.String (Pattern(Pattern))
8891
import Data.String (split, stripSuffix, take) as String
92+
import Data.Tuple.Nested ((/\))
8993
import Data.UInt (fromString, toString) as UInt
9094
import Effect (Effect)
9195
import HydraSdk.Internal.Lib.Misc (cborBytesToHex)
9296
import Node.Encoding (Encoding(UTF8)) as Encoding
9397
import Node.FS.Sync (readTextFile) as FSSync
9498
import Node.Path (FilePath)
9599
import Partial.Unsafe (unsafePartial)
100+
import Prim.Row (class Union) as Row
101+
import Prim.RowList (class RowToList) as RowList
102+
import Record (union) as Record
103+
import Record.Extra (class Keys, pick) as Record.Extra
104+
105+
unionRecordCodecs
106+
:: forall r r0 r' rl r0l
107+
. Row.Union r r0 r'
108+
=> RowList.RowToList r rl
109+
=> Record.Extra.Keys rl
110+
=> Row.Union r0 r r'
111+
=> RowList.RowToList r0 r0l
112+
=> Record.Extra.Keys r0l
113+
=> CA.JPropCodec (Record r)
114+
-> CA.JPropCodec (Record r0)
115+
-> CA.JPropCodec (Record r')
116+
unionRecordCodecs
117+
(CA.Codec rDecode rEncode)
118+
(CA.Codec r0Decode r0Encode) = CA.Codec decode encode
119+
where
120+
decode obj = do
121+
r0Rec <- r0Decode obj
122+
rRec <- rDecode obj
123+
pure $ Record.union r0Rec rRec
124+
encode rec =
125+
let
126+
rList /\ rRec = rEncode (Record.Extra.pick rec :: Record r)
127+
r0List /\ r0Rec = r0Encode (Record.Extra.pick rec :: Record r0)
128+
in
129+
(rList <> r0List) /\ Record.union rRec r0Rec
96130

97131
fromCaJsonDecodeError :: CA.JsonDecodeError -> A.JsonDecodeError
98132
fromCaJsonDecodeError = case _ of

src/Internal/Process/HydraNode.purs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import Cardano.AsCbor (encodeCbor)
1616
import Cardano.Types (TransactionHash)
1717
import Control.Error.Util (bool)
1818
import Data.Array (concat, singleton) as Array
19-
import Data.Codec.Argonaut (JsonCodec, array, int, object, string) as CA
19+
import Data.Codec.Argonaut (JsonCodec, JPropCodec, array, int, object, string) as CA
2020
import Data.Codec.Argonaut.Compat (maybe) as CA
2121
import Data.Codec.Argonaut.Record (record) as CAR
2222
import Data.Foldable (foldMap)
@@ -28,7 +28,7 @@ import Data.Traversable (for_, traverse_)
2828
import Effect (Effect)
2929
import Effect.AVar (empty, tryPut) as AVar
3030
import Effect.Class (class MonadEffect, liftEffect)
31-
import HydraSdk.Internal.Lib.Codec (txHashCodec)
31+
import HydraSdk.Internal.Lib.Codec (txHashCodec, unionRecordCodecs)
3232
import HydraSdk.Internal.Lib.Misc (cborBytesToHex)
3333
import HydraSdk.Internal.Types.HostPort
3434
( HostPort
@@ -46,9 +46,13 @@ import Node.ChildProcess (ChildProcess, defaultSpawnOptions, spawn, stderr, stdo
4646
import Node.Encoding (Encoding(UTF8)) as Encoding
4747
import Node.Path (FilePath)
4848
import Node.Stream (onDataString)
49+
import Prim.Row (class Union) as Row
50+
import Prim.RowList (RowList)
51+
import Prim.RowList (class RowToList) as RowList
52+
import Record.Extra (class Keys) as Record.Extra
4953

5054
-- | Parameters to be passed to the hydra-node child process on startup.
51-
type HydraNodeStartupParams =
55+
type HydraNodeStartupParams (peerExtra :: Row Type) =
5256
{ nodeId :: String
5357
, hydraNodeAddress :: HostPort
5458
, hydraNodeAdvertisedAddress :: Maybe HostPort
@@ -60,12 +64,18 @@ type HydraNodeStartupParams =
6064
, pparams :: FilePath
6165
, hydraScripts :: Array TransactionHash
6266
, contestPeriodSec :: Int
63-
, peers :: Array HydraHeadPeer
67+
, peers :: Array (Record (HydraHeadPeer peerExtra))
6468
}
6569

6670
-- | Bidirectional JSON codec for `HydraNodeStartupParams`.
67-
hydraNodeStartupParamsCodec :: CA.JsonCodec HydraNodeStartupParams
68-
hydraNodeStartupParamsCodec =
71+
hydraNodeStartupParamsCodec
72+
:: forall (peerExtra :: Row Type) (rl :: RowList Type)
73+
. Row.Union peerExtra (HydraHeadPeer ()) (HydraHeadPeer peerExtra)
74+
=> RowList.RowToList peerExtra rl
75+
=> Record.Extra.Keys rl
76+
=> CA.JPropCodec (Record peerExtra)
77+
-> CA.JsonCodec (HydraNodeStartupParams peerExtra)
78+
hydraNodeStartupParamsCodec peerExtraCodec =
6979
CA.object "HydraNodeStartupParams" $ CAR.record
7080
{ nodeId: CA.string
7181
, hydraNodeAddress: hostPortStringCodec
@@ -78,22 +88,29 @@ hydraNodeStartupParamsCodec =
7888
, pparams: CA.string
7989
, hydraScripts: CA.array txHashCodec
8090
, contestPeriodSec: CA.int
81-
, peers: CA.array hydraHeadPeerCodec
91+
, peers: CA.array $ hydraHeadPeerCodec peerExtraCodec
8292
}
8393

8494
-- | Configuration parameters for a single Hydra Head peer. When setting up a
8595
-- | Hydra Head, each node must specify the network addresses and public key
8696
-- | information of its respective peers.
87-
type HydraHeadPeer =
88-
{ hydraNodeAddress :: HostPort
97+
type HydraHeadPeer (extra :: Row Type) =
98+
( hydraNodeAddress :: HostPort
8999
, hydraVerificationKey :: FilePath
90100
, cardanoVerificationKey :: FilePath
91-
}
101+
| extra
102+
)
92103

93104
-- | Bi-directional JSON codec for `HydraHeadPeer`.
94-
hydraHeadPeerCodec :: CA.JsonCodec HydraHeadPeer
95-
hydraHeadPeerCodec =
96-
CA.object "HydraHeadPeer" $ CAR.record
105+
hydraHeadPeerCodec
106+
:: forall (extra :: Row Type) (rl :: RowList Type)
107+
. Row.Union extra (HydraHeadPeer ()) (HydraHeadPeer extra)
108+
=> RowList.RowToList extra rl
109+
=> Record.Extra.Keys rl
110+
=> CA.JPropCodec (Record extra)
111+
-> CA.JsonCodec (Record (HydraHeadPeer extra))
112+
hydraHeadPeerCodec extraCodec =
113+
CA.object "HydraHeadPeer" $ unionRecordCodecs extraCodec $ CAR.record
97114
{ hydraNodeAddress: hostPortStringCodec
98115
, hydraVerificationKey: CA.string
99116
, cardanoVerificationKey: CA.string
@@ -126,9 +143,9 @@ noopHydraNodeHandlers =
126143
-- |
127144
-- | NOTE: The hydra-node executable must be available in the PATH.
128145
spawnHydraNode
129-
:: forall m
146+
:: forall (m :: Type -> Type) (peerExtra :: Row Type)
130147
. MonadEffect m
131-
=> HydraNodeStartupParams
148+
=> HydraNodeStartupParams peerExtra
132149
-> HydraNodeHandlers
133150
-> m ChildProcess
134151
spawnHydraNode params handlers = liftEffect do

0 commit comments

Comments
 (0)