Last active
March 27, 2021 05:24
-
-
Save robertwb/58b479c3aeb5c346841d6316deb1b0f2 to your computer and use it in GitHub Desktop.
Plutus Playground Smart Contract
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Playground.Contract | |
import Control.Monad (void) | |
import Data.Aeson (FromJSON, ToJSON) | |
import qualified Data.Text as T | |
import GHC.Generics (Generic) | |
import Ledger | |
import qualified Ledger.Ada as Ada | |
import qualified Ledger.Constraints as Constraints | |
import qualified Ledger.Typed.Scripts as Scripts | |
import Language.Plutus.Contract | |
import qualified Language.PlutusTx as PlutusTx | |
import Language.PlutusTx.Prelude | |
import Schema | |
import Wallet.Emulator.Wallet | |
data SplitData = | |
SplitData | |
{ recipient1 :: PubKeyHash -- ^ First recipient of the funds | |
, recipient2 :: PubKeyHash -- ^ Second recipient of the funds | |
, amount :: Ada -- ^ How much Ada we want to lock | |
} | |
deriving stock (Show, Generic) | |
-- For a 'real' application use 'makeIsDataIndexed' to ensure the output is stable over time | |
PlutusTx.makeIsData ''SplitData | |
PlutusTx.makeLift ''SplitData | |
data SplitDataOut = | |
SplitDataOut | |
{ recipient1Out :: PubKeyHash -- ^ First recipient of the funds | |
, recipient2Out :: PubKeyHash -- ^ Second recipient of the funds | |
, amountOut :: Ada -- ^ How much Ada we want to lock | |
} | |
deriving stock (Show, Generic) | |
-- For a 'real' application use 'makeIsDataIndexed' to ensure the output is stable over time | |
PlutusTx.makeIsData ''SplitDataOut | |
PlutusTx.makeLift ''SplitDataOut | |
validateSplit :: SplitData -> () -> ValidatorCtx -> Bool | |
validateSplit SplitData{recipient1, recipient2, amount} _ ValidatorCtx{valCtxTxInfo} = | |
let half = Ada.divide amount 2 in | |
Ada.fromValue (valuePaidTo valCtxTxInfo recipient1) >= half && | |
Ada.fromValue (valuePaidTo valCtxTxInfo recipient2) >= (amount - half) | |
data Split | |
instance Scripts.ScriptType Split where | |
type instance RedeemerType Split = () | |
type instance DatumType Split = SplitData | |
splitInstance :: Scripts.ScriptInstance Split | |
splitInstance = Scripts.validator @Split | |
$$(PlutusTx.compile [|| validateSplit ||]) | |
$$(PlutusTx.compile [|| wrap ||]) where | |
wrap = Scripts.wrapValidator @SplitData @() | |
data LockArgsIn = | |
LockArgsIn | |
{ recipient1Wallet :: Wallet | |
, recipient2Wallet :: Wallet | |
, totalAda :: Ada | |
} | |
deriving stock (Show, Generic) | |
deriving anyclass (ToJSON, FromJSON, ToSchema) | |
data LockArgsOut = | |
LockArgsOut | |
{ recipient1WalletOut :: Wallet | |
, recipient2WalletOut :: Wallet | |
, totalAdaOut :: Ada | |
} | |
deriving stock (Show, Generic) | |
deriving anyclass (ToJSON, FromJSON, ToSchema) | |
type SplitSchema = | |
BlockchainActions | |
.\/ Endpoint "lock" LockArgsIn | |
.\/ Endpoint "unlock" LockArgsOut | |
lock :: Contract SplitSchema T.Text LockArgsIn | |
lock = endpoint @"lock" | |
unlock :: Contract SplitSchema T.Text LockArgsOut | |
unlock = endpoint @"unlock" | |
mkSplitDataIn :: LockArgsIn -> SplitData | |
mkSplitDataIn LockArgsIn{recipient1Wallet, recipient2Wallet, totalAda} = | |
let convert :: Wallet -> PubKeyHash | |
convert = pubKeyHash . walletPubKey | |
in | |
SplitData | |
{ recipient1 = convert recipient1Wallet | |
, recipient2 = convert recipient2Wallet | |
, amount = totalAda | |
} | |
mkSplitDataOut :: LockArgsOut -> SplitDataOut | |
mkSplitDataOut LockArgsOut{recipient1WalletOut, recipient2WalletOut, totalAdaOut} = | |
let convert :: Wallet -> PubKeyHash | |
convert = pubKeyHash . walletPubKey | |
in | |
SplitDataOut | |
{ recipient1Out = convert recipient1WalletOut | |
, recipient2Out = convert recipient2WalletOut | |
, amountOut = totalAdaOut | |
} | |
lockFunds :: SplitData -> Contract SplitSchema T.Text () | |
lockFunds s@SplitData{amount} = do | |
logInfo $ "Locking " <> show amount | |
let tx = Constraints.mustPayToTheScript s (Ada.toValue amount) | |
void $ submitTxConstraints splitInstance tx | |
unlockFunds :: SplitDataOut -> Contract SplitSchema T.Text () | |
unlockFunds SplitDataOut{recipient1Out, recipient2Out, amountOut} = do | |
let contractAddress = (Ledger.scriptAddress (Scripts.validatorScript splitInstance)) | |
utxos <- utxoAt contractAddress | |
let half = Ada.divide amountOut 2 | |
tx = | |
collectFromScript utxos () | |
<> Constraints.mustPayToPubKey recipient1Out (Ada.toValue half) | |
<> Constraints.mustPayToPubKey recipient2Out (Ada.toValue $ amountOut - half) | |
void $ submitTxConstraintsSpending splitInstance utxos tx | |
endpoints :: Contract SplitSchema T.Text () | |
endpoints = (lock >>= lockFunds . mkSplitDataIn) `select` (unlock >>= unlockFunds . mkSplitDataOut) | |
mkSchemaDefinitions ''SplitSchema | |
$(mkKnownCurrencies []) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[0,[{"simulationWallets":[{"simulatorWalletWallet":{"getWallet":1},"simulatorWalletBalance":{"getValue":[[{"unCurrencySymbol":""},[[{"unTokenName":""},10]]]]}},{"simulatorWalletWallet":{"getWallet":2},"simulatorWalletBalance":{"getValue":[[{"unCurrencySymbol":""},[[{"unTokenName":""},10]]]]}}],"simulationName":"Simulation 1","simulationId":1,"simulationActions":[{"caller":{"getWallet":1},"argumentValues":{"endpointDescription":{"getEndpointDescription":"lock"},"argument":{"contents":[["recipient1Wallet",{"contents":[["getWallet",{"s":1,"e":0,"c":[1],"tag":"FormIntegerF"}]],"tag":"FormObjectF"}],["recipient2Wallet",{"contents":[["getWallet",{"s":1,"e":0,"c":[2],"tag":"FormIntegerF"}]],"tag":"FormObjectF"}],["totalAda",{"contents":[["getLovelace",{"s":1,"e":0,"c":[2],"tag":"FormIntegerF"}]],"tag":"FormObjectF"}]],"tag":"FormObjectF"}},"tag":"CallEndpoint"},{"blocks":10,"tag":"AddBlocks"},{"caller":{"getWallet":2},"argumentValues":{"endpointDescription":{"getEndpointDescription":"unlock"},"argument":{"contents":[["recipient1WalletOut",{"contents":[["getWallet",{"s":1,"e":0,"c":[1],"tag":"FormIntegerF"}]],"tag":"FormObjectF"}],["recipient2WalletOut",{"contents":[["getWallet",{"s":1,"e":0,"c":[2],"tag":"FormIntegerF"}]],"tag":"FormObjectF"}],["totalAdaOut",{"contents":[["getLovelace",{"s":1,"e":0,"c":[2],"tag":"FormIntegerF"}]],"tag":"FormObjectF"}]],"tag":"FormObjectF"}},"tag":"CallEndpoint"},{"blocks":10,"tag":"AddBlocks"}]}]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment