{"action":"created","comment":{"url":"https://api.github.com/repos/kadena-io/pact/pulls/comments/215609200","pull_request_review_id":152909104,"id":215609200,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNTYwOTIwMA==","diff_hunk":"@@ -0,0 +1,464 @@\n+{-# LANGUAGE FlexibleContexts      #-}\n+{-# LANGUAGE FlexibleInstances     #-}\n+{-# LANGUAGE GADTs                 #-}\n+{-# LANGUAGE LambdaCase            #-}\n+{-# LANGUAGE MultiParamTypeClasses #-}\n+{-# LANGUAGE OverloadedStrings     #-}\n+{-# LANGUAGE ScopedTypeVariables   #-}\n+{-# LANGUAGE TemplateHaskell       #-}\n+module Analyze.Gen where\n+\n+import           Control.Lens               hiding (op, (...))\n+import           Control.Monad.Reader       (MonadReader, ReaderT (runReaderT))\n+import           Control.Monad.State.Strict (MonadState, runStateT)\n+import qualified Data.Decimal               as Decimal\n+import           Data.Map.Strict            (Map)\n+import qualified Data.Map.Strict            as Map\n+import qualified Data.Text                  as T\n+import           Data.Type.Equality         ((:~:) (Refl))\n+import           GHC.Natural                (Natural)\n+import           GHC.Stack                  (HasCallStack)\n+import           Hedgehog                   hiding (Update)\n+import qualified Hedgehog.Gen               as Gen\n+import qualified Hedgehog.Range             as Range\n+import           Numeric.Interval           (Interval, inf, midpoint, sup,\n+                                             (+/-), (...))\n+import           Pact.Analyze.Errors\n+import           Pact.Analyze.Types         hiding (Object, Term)\n+import qualified Pact.Analyze.Types         as Analyze\n+import           Pact.Analyze.Util          (dummyInfo)\n+\n+import           Pact.Types.Exp             (Name (Name))\n+import           Pact.Types.Persistence     (WriteType)\n+import qualified Pact.Types.Term            as Pact\n+\n+import           Analyze.TimeGen\n+\n+\n+-- Note [EmptyInterval]: For both genDecimal and genInteger, it's possible that\n+-- the range is too small to generate even one number. When this is true,\n+-- these'll throw EmptyInterval. This is caught and discarded by the\n+-- properties.\n+\n+data GenEnv = GenEnv\n+  { _envTables  :: ![(TableName, Schema)]\n+  , _envKeysets :: ![(Pact.KeySet, KeySet)]\n+  }\n+\n+data GenState = GenState\n+  { _idGen         :: !TagId\n+  , _namedKeysets  :: !(Map String (Pact.KeySet, KeySet))\n+  , _namedDecimals :: !(Map String Decimal)\n+  } deriving Show\n+\n+makeLenses ''GenEnv\n+makeLenses ''GenState\n+\n+-- Explicitly shrink the size parameter to generate smaller terms.\n+scale :: MonadGen m => Size -> m a -> m a\n+scale n = Gen.scale (`div` n)\n+\n+genDecimal :: MonadGen m => NumBound -> m Decimal\n+genDecimal size = do\n+  places   <- Gen.word8 Range.constantBounded\n+  mantissa <- genInteger (size * 10 ^ places)\n+  pure $ fromPact decimalIso $ Decimal.Decimal places mantissa\n+\n+genInteger :: MonadGen m => NumBound -> m Integer\n+genInteger size = Gen.integral $\n+  Range.exponentialFrom\n+    (round   (midpoint size))\n+    (ceiling (inf size))\n+    (floor   (sup size))\n+\n+genArithOp :: MonadGen m => m ArithOp\n+genArithOp = Gen.element [Add, Sub, Mul, Div] -- Pow, Log\n+\n+genUnaryArithOp :: MonadGen m => m UnaryArithOp\n+genUnaryArithOp = Gen.element [Negate, Abs] -- Sqrt, Ln, Exp, Signum\n+\n+genRoundingLikeOp :: MonadGen m => m RoundingLikeOp\n+genRoundingLikeOp = Gen.element [Round, Ceiling, Floor]\n+\n+genComparisonOp :: MonadGen m => m ComparisonOp\n+genComparisonOp = Gen.element [Gt, Lt, Gte, Lte, Eq, Neq]\n+\n+type ECore = Existential (Core Analyze.Term)\n+\n+-- TODO: we might want to generalize this to a union of open intervals\n+\n+-- 'NumSize' bounds the values that a generated expression can evaluate to. We\n+-- use this to avoid generating large numbers in computationally expensive\n+-- spots.\n+type NumBound = Interval Double\n+\n+data BoundedType where\n+  BoundedInt     :: NumBound -> BoundedType\n+  BoundedDecimal :: NumBound -> BoundedType\n+  BoundedString  :: Int      -> BoundedType\n+  BoundedTime    ::             BoundedType\n+  BoundedBool    ::             BoundedType\n+  BoundedKeySet  ::             BoundedType\n+  -- TODO: objects\n+\n+arithSize :: ArithOp -> NumBound -> (NumBound, NumBound)\n+arithSize op size = case op of\n+  Add -> (size, size)\n+  Sub -> (size, size)\n+  Mul -> (sqrt size, sqrt size)\n+  Div -> (size, size)\n+  Pow -> error \"not yet implemented: we don't symbolically interpret this operator\"\n+  Log -> error \"not yet implemented: we don't symbolically interpret this operator\"\n+\n+unaryArithSize :: UnaryArithOp -> NumBound -> NumBound\n+unaryArithSize op size = case op of\n+  Negate -> - size\n+  Sqrt   -> size ** 2\n+  Abs    -> size -- ?\n+  Ln     -> error \"not yet implemented: we don't symbolically interpret this operator\"\n+  Exp    -> error \"not yet implemented: we don't symbolically interpret this operator\"\n+  Signum -> error \"not yet implemented: we don't symbolically interpret this operator\"\n+\n+mkInt :: MonadGen m => Core Analyze.Term Integer -> m ETerm\n+mkInt = pure . ESimple TInt . Inj\n+\n+mkDec :: MonadGen m => Numerical Analyze.Term Decimal -> m ETerm\n+mkDec = pure . ESimple TDecimal . Inj . Numerical\n+\n+mkBool :: MonadGen m => Core Analyze.Term Bool -> m ETerm\n+mkBool = pure . ESimple TBool . Inj\n+\n+-- | When we know what type we'll be receiving from an existential we can\n+-- unsafely extract it.\n+class Extract a where\n+  extract :: HasCallStack => ETerm -> Analyze.Term a\n+\n+instance Extract Integer where\n+  extract = \\case\n+    ESimple TInt x -> x\n+    other -> error (show other)\n+\n+instance Extract Decimal where\n+  extract = \\case\n+    ESimple TDecimal x -> x\n+    other -> error (show other)\n+\n+instance Extract String where\n+  extract = \\case\n+    ESimple TStr x -> x\n+    other -> error (show other)\n+\n+instance Extract Bool where\n+  extract = \\case\n+    ESimple TBool x -> x\n+    other -> error (show other)\n+\n+instance Extract Time where\n+  extract = \\case\n+    ESimple TTime x -> x\n+    other -> error (show other)\n+\n+instance Extract KeySet where\n+  extract = \\case\n+    ESimple TKeySet x -> x\n+    other -> error (show other)\n+\n+-- TODO: Var, objects\n+-- TODO: we might want to reweight these by using `Gen.frequency`.\n+genCore :: MonadGen m => BoundedType -> m ETerm\n+genCore (BoundedInt size) = Gen.recursive Gen.choice [\n+    ESimple TInt . CoreTerm . Lit <$> genInteger size\n+  ] $ scale 4 <$> [\n+    Gen.subtermM2 (genCore (BoundedInt size)) (genCore (BoundedInt (1 ... 1e3))) $\n+      \\x y -> mkInt $ Numerical $ ModOp (extract x) (extract y)\n+  , do op <- genArithOp\n+       let (size1, size2) = arithSize op size\n+       Gen.subtermM2 (genCore (BoundedInt size1)) (genCore (BoundedInt size2)) $\n+         \\x y -> mkInt $ Numerical $ IntArithOp op (extract x) (extract y)\n+  , do op <- genUnaryArithOp\n+       let size' = unaryArithSize op size\n+       Gen.subtermM (genCore (BoundedInt size')) $\n+         mkInt . Numerical . IntUnaryArithOp op . extract\n+  , Gen.subtermM (genCore (BoundedDecimal size)) $ \\x -> do\n+    op <- genRoundingLikeOp\n+    mkInt $ Numerical $ RoundingLikeOp1 op (extract x)\n+  , Gen.subtermM (genCore strSize) $ mkInt . StrLength . extract\n+  ]\n+genCore bounded@(BoundedDecimal size) = Gen.recursive Gen.choice [\n+    ESimple TDecimal . CoreTerm . Lit <$> genDecimal size\n+  ] $ scale 4 <$> [\n+    do op <- genArithOp\n+       let (size1, size2) = arithSize op size\n+       Gen.subtermM2 (genCore (BoundedDecimal size1)) (genCore (BoundedDecimal size2)) $\n+         \\x y -> mkDec $ DecArithOp op (extract x) (extract y)\n+  , do\n+       op <- genUnaryArithOp\n+       let size' = unaryArithSize op size\n+       Gen.subtermM (genCore (BoundedDecimal size')) $\n+         mkDec . DecUnaryArithOp op . extract\n+  , do op <- genArithOp\n+       let (size1, size2) = arithSize op size\n+       Gen.subtermM2 (genCore (BoundedDecimal size1)) (genCore (BoundedInt size2)) $\n+         \\x y -> mkDec $ DecIntArithOp op (extract x) (extract y)\n+  , do\n+       op <- genArithOp\n+       let (size1, size2) = arithSize op size\n+       Gen.subtermM2 (genCore (BoundedInt size1)) (genCore (BoundedDecimal size2)) $\n+         \\x y -> mkDec $ IntDecArithOp op (extract x) (extract y)\n+  , Gen.subtermM2 (genCore bounded) (genCore (BoundedInt (0 +/- 255))) $ \\x y -> do\n+      op <- genRoundingLikeOp\n+      mkDec $ RoundingLikeOp2 op (extract x) (extract y)\n+  ]\n+genCore (BoundedString len) = Gen.recursive Gen.choice [\n+    ESimple TStr . CoreTerm . Lit <$> Gen.string (Range.exponential 1 len) Gen.unicode\n+  ] [\n+    scale 4 $ Gen.subtermM2\n+      (genCore (BoundedString (len `div` 2)))\n+      (genCore (BoundedString (len `div` 2))) $ \\x y ->\n+        pure $ ESimple TStr $ Inj $ StrConcat (extract x) (extract y)\n+  ]\n+genCore BoundedBool = Gen.recursive Gen.choice [\n+    ESimple TBool . CoreTerm . Lit <$> Gen.bool\n+  ] $ scale 4 <$> [\n+    do op <- genComparisonOp\n+       Gen.subtermM2 (genCore intSize) (genCore intSize) $ \\x y -> do\n+         mkBool $ IntegerComparison op (extract x) (extract y)\n+  , do op <- genComparisonOp\n+       Gen.subtermM2 (genCore decSize) (genCore decSize) $ \\x y ->\n+         mkBool $ DecimalComparison op (extract x) (extract y)\n+  , do op <- genComparisonOp\n+       Gen.subtermM2 (genCore BoundedTime) (genCore BoundedTime) $ \\x y ->\n+         mkBool $ TimeComparison op (extract x) (extract y)\n+  , do op <- genComparisonOp\n+       Gen.subtermM2 (genCore strSize) (genCore strSize) $ \\x y ->\n+         mkBool $ StringComparison op (extract x) (extract y)\n+  , do op <- Gen.element [Eq, Neq]\n+       Gen.subtermM2 (genCore BoundedBool) (genCore BoundedBool) $ \\x y ->\n+         mkBool $ BoolComparison op (extract x) (extract y)\n+  , do op <- Gen.element [AndOp, OrOp]\n+       Gen.subtermM2 (genCore BoundedBool) (genCore BoundedBool) $ \\x y ->\n+         mkBool $ Logical op [extract x, extract y]\n+  , Gen.subtermM (genCore BoundedBool) $ \\x ->\n+      mkBool $ Logical NotOp [extract x]\n+  ]\n+genCore BoundedTime = Gen.recursive Gen.choice [\n+    ESimple TTime . CoreTerm . Lit <$> Gen.enumBounded -- Gen.int64\n+  ] $ scale 4 <$> [\n+    Gen.subtermM2 (genCore BoundedTime) (genCore (BoundedInt 1e9)) $ \\x y ->\n+      pure $ ESimple TTime $ Inj $ IntAddTime (extract x) (extract y)\n+  , Gen.subtermM2 (genCore BoundedTime) (genCore (BoundedDecimal 1e9)) $ \\x y ->\n+      pure $ ESimple TTime $ Inj $ DecAddTime (extract x) (extract y)\n+  ]\n+genCore BoundedKeySet = ESimple TKeySet . CoreTerm . Lit . KeySet\n+  <$> genInteger (0 ... 2)\n+\n+intSize, decSize, strSize :: BoundedType\n+intSize = BoundedInt     (0 +/- 1e25)\n+decSize = BoundedDecimal (0 +/- 1e25)\n+strSize = BoundedString  1000\n+\n+-- TODO\n+-- generic:\n+-- # Let\n+-- object:\n+-- # Read\n+-- string:\n+-- # Write\n+-- time:\n+-- # ParseTime","path":"tests/Analyze/Gen.hs","position":268,"original_position":268,"commit_id":"bf2eb179b0052000707b6af540c8426c3ae3981d","original_commit_id":"bf2eb179b0052000707b6af540c8426c3ae3981d","user":{"login":"bts","id":5743,"node_id":"MDQ6VXNlcjU3NDM=","avatar_url":"https://avatars1.githubusercontent.com/u/5743?v=4","gravatar_id":"","url":"https://api.github.com/users/bts","html_url":"https://github.com/bts","followers_url":"https://api.github.com/users/bts/followers","following_url":"https://api.github.com/users/bts/following{/other_user}","gists_url":"https://api.github.com/users/bts/gists{/gist_id}","starred_url":"https://api.github.com/users/bts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bts/subscriptions","organizations_url":"https://api.github.com/users/bts/orgs","repos_url":"https://api.github.com/users/bts/repos","events_url":"https://api.github.com/users/bts/events{/privacy}","received_events_url":"https://api.github.com/users/bts/received_events","type":"User","site_admin":false},"body":"in these TODOs, any blockers to merging?","created_at":"2018-09-06T12:41:00Z","updated_at":"2018-09-06T12:41:00Z","html_url":"https://github.com/kadena-io/pact/pull/211#discussion_r215609200","pull_request_url":"https://api.github.com/repos/kadena-io/pact/pulls/211","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/kadena-io/pact/pulls/comments/215609200"},"html":{"href":"https://github.com/kadena-io/pact/pull/211#discussion_r215609200"},"pull_request":{"href":"https://api.github.com/repos/kadena-io/pact/pulls/211"}}},"pull_request":{"url":"https://api.github.com/repos/kadena-io/pact/pulls/211","id":213467967,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEzNDY3OTY3","html_url":"https://github.com/kadena-io/pact/pull/211","diff_url":"https://github.com/kadena-io/pact/pull/211.diff","patch_url":"https://github.com/kadena-io/pact/pull/211.patch","issue_url":"https://api.github.com/repos/kadena-io/pact/issues/211","number":211,"state":"open","locked":false,"title":"Analysis property testing","user":{"login":"joelburget","id":310981,"node_id":"MDQ6VXNlcjMxMDk4MQ==","avatar_url":"https://avatars1.githubusercontent.com/u/310981?v=4","gravatar_id":"","url":"https://api.github.com/users/joelburget","html_url":"https://github.com/joelburget","followers_url":"https://api.github.com/users/joelburget/followers","following_url":"https://api.github.com/users/joelburget/following{/other_user}","gists_url":"https://api.github.com/users/joelburget/gists{/gist_id}","starred_url":"https://api.github.com/users/joelburget/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joelburget/subscriptions","organizations_url":"https://api.github.com/users/joelburget/orgs","repos_url":"https://api.github.com/users/joelburget/repos","events_url":"https://api.github.com/users/joelburget/events{/privacy}","received_events_url":"https://api.github.com/users/joelburget/received_events","type":"User","site_admin":false},"body":"The main feature this implements is comparison of the symbolic execution performed by analysis with the concrete execution performed by Pact itself. Secondarily, this adds tests that our term translation is faithful.","created_at":"2018-09-06T01:03:03Z","updated_at":"2018-09-06T12:41:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1f29c96360d8c89674d03ba4a4a81e906920a5f7","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/kadena-io/pact/pulls/211/commits","review_comments_url":"https://api.github.com/repos/kadena-io/pact/pulls/211/comments","review_comment_url":"https://api.github.com/repos/kadena-io/pact/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kadena-io/pact/issues/211/comments","statuses_url":"https://api.github.com/repos/kadena-io/pact/statuses/bf2eb179b0052000707b6af540c8426c3ae3981d","head":{"label":"kadena-io:property-testing","ref":"property-testing","sha":"bf2eb179b0052000707b6af540c8426c3ae3981d","user":{"login":"kadena-io","id":19830776,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE5ODMwNzc2","avatar_url":"https://avatars1.githubusercontent.com/u/19830776?v=4","gravatar_id":"","url":"https://api.github.com/users/kadena-io","html_url":"https://github.com/kadena-io","followers_url":"https://api.github.com/users/kadena-io/followers","following_url":"https://api.github.com/users/kadena-io/following{/other_user}","gists_url":"https://api.github.com/users/kadena-io/gists{/gist_id}","starred_url":"https://api.github.com/users/kadena-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kadena-io/subscriptions","organizations_url":"https://api.github.com/users/kadena-io/orgs","repos_url":"https://api.github.com/users/kadena-io/repos","events_url":"https://api.github.com/users/kadena-io/events{/privacy}","received_events_url":"https://api.github.com/users/kadena-io/received_events","type":"Organization","site_admin":false},"repo":{"id":73597023,"node_id":"MDEwOlJlcG9zaXRvcnk3MzU5NzAyMw==","name":"pact","full_name":"kadena-io/pact","owner":{"login":"kadena-io","id":19830776,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE5ODMwNzc2","avatar_url":"https://avatars1.githubusercontent.com/u/19830776?v=4","gravatar_id":"","url":"https://api.github.com/users/kadena-io","html_url":"https://github.com/kadena-io","followers_url":"https://api.github.com/users/kadena-io/followers","following_url":"https://api.github.com/users/kadena-io/following{/other_user}","gists_url":"https://api.github.com/users/kadena-io/gists{/gist_id}","starred_url":"https://api.github.com/users/kadena-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kadena-io/subscriptions","organizations_url":"https://api.github.com/users/kadena-io/orgs","repos_url":"https://api.github.com/users/kadena-io/repos","events_url":"https://api.github.com/users/kadena-io/events{/privacy}","received_events_url":"https://api.github.com/users/kadena-io/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kadena-io/pact","description":"The Pact Smart Contract Language","fork":false,"url":"https://api.github.com/repos/kadena-io/pact","forks_url":"https://api.github.com/repos/kadena-io/pact/forks","keys_url":"https://api.github.com/repos/kadena-io/pact/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kadena-io/pact/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kadena-io/pact/teams","hooks_url":"https://api.github.com/repos/kadena-io/pact/hooks","issue_events_url":"https://api.github.com/repos/kadena-io/pact/issues/events{/number}","events_url":"https://api.github.com/repos/kadena-io/pact/events","assignees_url":"https://api.github.com/repos/kadena-io/pact/assignees{/user}","branches_url":"https://api.github.com/repos/kadena-io/pact/branches{/branch}","tags_url":"https://api.github.com/repos/kadena-io/pact/tags","blobs_url":"https://api.github.com/repos/kadena-io/pact/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kadena-io/pact/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kadena-io/pact/git/refs{/sha}","trees_url":"https://api.github.com/repos/kadena-io/pact/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kadena-io/pact/statuses/{sha}","languages_url":"https://api.github.com/repos/kadena-io/pact/languages","stargazers_url":"https://api.github.com/repos/kadena-io/pact/stargazers","contributors_url":"https://api.github.com/repos/kadena-io/pact/contributors","subscribers_url":"https://api.github.com/repos/kadena-io/pact/subscribers","subscription_url":"https://api.github.com/repos/kadena-io/pact/subscription","commits_url":"https://api.github.com/repos/kadena-io/pact/commits{/sha}","git_commits_url":"https://api.github.com/repos/kadena-io/pact/git/commits{/sha}","comments_url":"https://api.github.com/repos/kadena-io/pact/comments{/number}","issue_comment_url":"https://api.github.com/repos/kadena-io/pact/issues/comments{/number}","contents_url":"https://api.github.com/repos/kadena-io/pact/contents/{+path}","compare_url":"https://api.github.com/repos/kadena-io/pact/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kadena-io/pact/merges","archive_url":"https://api.github.com/repos/kadena-io/pact/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kadena-io/pact/downloads","issues_url":"https://api.github.com/repos/kadena-io/pact/issues{/number}","pulls_url":"https://api.github.com/repos/kadena-io/pact/pulls{/number}","milestones_url":"https://api.github.com/repos/kadena-io/pact/milestones{/number}","notifications_url":"https://api.github.com/repos/kadena-io/pact/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kadena-io/pact/labels{/name}","releases_url":"https://api.github.com/repos/kadena-io/pact/releases{/id}","deployments_url":"https://api.github.com/repos/kadena-io/pact/deployments","created_at":"2016-11-13T05:16:00Z","updated_at":"2018-09-05T04:27:49Z","pushed_at":"2018-09-06T01:03:03Z","git_url":"git://github.com/kadena-io/pact.git","ssh_url":"git@github.com:kadena-io/pact.git","clone_url":"https://github.com/kadena-io/pact.git","svn_url":"https://github.com/kadena-io/pact","homepage":"http://kadena.io/pact","size":3054,"stargazers_count":213,"watchers_count":213,"language":"Haskell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":23,"mirror_url":null,"archived":false,"open_issues_count":51,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":23,"open_issues":51,"watchers":213,"default_branch":"master"}},"base":{"label":"kadena-io:master","ref":"master","sha":"d4f96422d52464aa5a20b58d4599d13fcc161b76","user":{"login":"kadena-io","id":19830776,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE5ODMwNzc2","avatar_url":"https://avatars1.githubusercontent.com/u/19830776?v=4","gravatar_id":"","url":"https://api.github.com/users/kadena-io","html_url":"https://github.com/kadena-io","followers_url":"https://api.github.com/users/kadena-io/followers","following_url":"https://api.github.com/users/kadena-io/following{/other_user}","gists_url":"https://api.github.com/users/kadena-io/gists{/gist_id}","starred_url":"https://api.github.com/users/kadena-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kadena-io/subscriptions","organizations_url":"https://api.github.com/users/kadena-io/orgs","repos_url":"https://api.github.com/users/kadena-io/repos","events_url":"https://api.github.com/users/kadena-io/events{/privacy}","received_events_url":"https://api.github.com/users/kadena-io/received_events","type":"Organization","site_admin":false},"repo":{"id":73597023,"node_id":"MDEwOlJlcG9zaXRvcnk3MzU5NzAyMw==","name":"pact","full_name":"kadena-io/pact","owner":{"login":"kadena-io","id":19830776,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE5ODMwNzc2","avatar_url":"https://avatars1.githubusercontent.com/u/19830776?v=4","gravatar_id":"","url":"https://api.github.com/users/kadena-io","html_url":"https://github.com/kadena-io","followers_url":"https://api.github.com/users/kadena-io/followers","following_url":"https://api.github.com/users/kadena-io/following{/other_user}","gists_url":"https://api.github.com/users/kadena-io/gists{/gist_id}","starred_url":"https://api.github.com/users/kadena-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kadena-io/subscriptions","organizations_url":"https://api.github.com/users/kadena-io/orgs","repos_url":"https://api.github.com/users/kadena-io/repos","events_url":"https://api.github.com/users/kadena-io/events{/privacy}","received_events_url":"https://api.github.com/users/kadena-io/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kadena-io/pact","description":"The Pact Smart Contract Language","fork":false,"url":"https://api.github.com/repos/kadena-io/pact","forks_url":"https://api.github.com/repos/kadena-io/pact/forks","keys_url":"https://api.github.com/repos/kadena-io/pact/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kadena-io/pact/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kadena-io/pact/teams","hooks_url":"https://api.github.com/repos/kadena-io/pact/hooks","issue_events_url":"https://api.github.com/repos/kadena-io/pact/issues/events{/number}","events_url":"https://api.github.com/repos/kadena-io/pact/events","assignees_url":"https://api.github.com/repos/kadena-io/pact/assignees{/user}","branches_url":"https://api.github.com/repos/kadena-io/pact/branches{/branch}","tags_url":"https://api.github.com/repos/kadena-io/pact/tags","blobs_url":"https://api.github.com/repos/kadena-io/pact/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kadena-io/pact/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kadena-io/pact/git/refs{/sha}","trees_url":"https://api.github.com/repos/kadena-io/pact/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kadena-io/pact/statuses/{sha}","languages_url":"https://api.github.com/repos/kadena-io/pact/languages","stargazers_url":"https://api.github.com/repos/kadena-io/pact/stargazers","contributors_url":"https://api.github.com/repos/kadena-io/pact/contributors","subscribers_url":"https://api.github.com/repos/kadena-io/pact/subscribers","subscription_url":"https://api.github.com/repos/kadena-io/pact/subscription","commits_url":"https://api.github.com/repos/kadena-io/pact/commits{/sha}","git_commits_url":"https://api.github.com/repos/kadena-io/pact/git/commits{/sha}","comments_url":"https://api.github.com/repos/kadena-io/pact/comments{/number}","issue_comment_url":"https://api.github.com/repos/kadena-io/pact/issues/comments{/number}","contents_url":"https://api.github.com/repos/kadena-io/pact/contents/{+path}","compare_url":"https://api.github.com/repos/kadena-io/pact/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kadena-io/pact/merges","archive_url":"https://api.github.com/repos/kadena-io/pact/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kadena-io/pact/downloads","issues_url":"https://api.github.com/repos/kadena-io/pact/issues{/number}","pulls_url":"https://api.github.com/repos/kadena-io/pact/pulls{/number}","milestones_url":"https://api.github.com/repos/kadena-io/pact/milestones{/number}","notifications_url":"https://api.github.com/repos/kadena-io/pact/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kadena-io/pact/labels{/name}","releases_url":"https://api.github.com/repos/kadena-io/pact/releases{/id}","deployments_url":"https://api.github.com/repos/kadena-io/pact/deployments","created_at":"2016-11-13T05:16:00Z","updated_at":"2018-09-05T04:27:49Z","pushed_at":"2018-09-06T01:03:03Z","git_url":"git://github.com/kadena-io/pact.git","ssh_url":"git@github.com:kadena-io/pact.git","clone_url":"https://github.com/kadena-io/pact.git","svn_url":"https://github.com/kadena-io/pact","homepage":"http://kadena.io/pact","size":3054,"stargazers_count":213,"watchers_count":213,"language":"Haskell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":23,"mirror_url":null,"archived":false,"open_issues_count":51,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":23,"open_issues":51,"watchers":213,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kadena-io/pact/pulls/211"},"html":{"href":"https://github.com/kadena-io/pact/pull/211"},"issue":{"href":"https://api.github.com/repos/kadena-io/pact/issues/211"},"comments":{"href":"https://api.github.com/repos/kadena-io/pact/issues/211/comments"},"review_comments":{"href":"https://api.github.com/repos/kadena-io/pact/pulls/211/comments"},"review_comment":{"href":"https://api.github.com/repos/kadena-io/pact/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kadena-io/pact/pulls/211/commits"},"statuses":{"href":"https://api.github.com/repos/kadena-io/pact/statuses/bf2eb179b0052000707b6af540c8426c3ae3981d"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"bts"}}