ZP62WC472OTQETO2HTHIQIPO57XZIWVKPA4KL62GYU4OZDMB6NSAC
7HPY3QPFPN35PSPUBVNW2GTFB3CBQZBST4J2BAVJ7QMXLIUN52JAC
AXKKXBWN4EMUOLV43WN52JSKJPBV7TLSGLNJW5EZXHSJNKCYUWOQC
OBFPJS2GHO2PEHBHGEHKIUOUAFIQHPIZXEVD2YIE3ZIE2PVMH5VAC
HE3JTXO37O4MOMWPZ4BRBHP53KBPZDG3PCSUCVNOKIS7IY26OCIAC
GCVQD44VRPQVKPZEPIC4AOIXLJIG2ZMV3QI2Y7KALUT6NVUBSGSAC
4IQVQL4TS35GL2GYZJG254TKJLL5EHMRSFT77Z4VTRZIG2TMBM3QC
4U7F3CPIDTK6JSEDMNMHVKSR7HOQDLZQD2PPVMDLHO5SFSIMUXZAC
A6HKMINBNGQLLX4QJMYWKQ4JAEHVJ4HIRVDKPPDI3FJUO2AAB7OQC
NJZ3DKZYZTAEHPAEXS3XFWIPCJFR3D4642UQMGQABVFGNKQUEQVAC
W35DDBFYF6Z4ZPCFEO5RPAONZLYCSNTXUSTS6FIUUVZHCI6Q7GHAC
RPAJLHMTUJU4AYNBOHVGHGGB4NY2NLY3BVPYN5FMWB3ZIMAUQHCQC
PGZJ736CG2E4HXIRYTZTGOMJRX2CHPIFG6H45PPO57EONOWJJ74QC
ADMKQQGCGVSHHIMVQ4XFRDCG544SBJCYALSKZV45CQQBZ4ACUH2AC
2XQD6KKKD6QVHFHAEMVE3XXY7X2T7BLTLL7XIILZAXNJJH2YONUQC
64C6AWH66FDKU6UE6Z6JPX2J2GBM2JOPTH2GL6LHKAIUBGNGDZ5AC
QMRKFEPGFBCEWAIXPEIG5ILKAJ2JH5L3TOITHR4HNJXK5FN3KXBQC
IZEVQF627FA7VV25KJAWYWGGC35LZUUBBQRPN5ZAINTQLPEDRTEAC
WZUHEZSBRKHQMNWDKVG4X6DDIQEAXTGI6IGAJ5ERPRQ3W2KUMX4QC
BROSTG5KP3NUNLSYPVQID254TE47E5RKQAKLPIY7PGWETE6JNMTAC
7KZP4RHZ3QSYTPPQ257A65Z5UPX44TF2LAI2U5EMULQCLDCEUK2AC
LAROLAYUGJ4Q5AEFV5EJMIA2ZKBNCBWHHHPCJ3CKCNIUIYUKRFVQC
WO2MINIF4TXOHWSE7JWXRZYN64XRVLYIRFMF4SMPSOXKA2V77KMQC
75N3UJ4JK56KXF56GASGPAWLFYGJDETVJNYTF4KXFCQM767JUU5AC
TLQ72DSJD7GGPWN6HGBHAVPBRQFKEQ6KSK43U7JWWID4ZWAF47JAC
TNR3TEHKVADAEZSTOD2XLSUTSW5AWST2YUW4CWK5KE7DSC6XHZNAC
Z7KS5XHHC6PAMTVBHXY7KUSS3BWAOU6FSYIITUCFOOJZU4OUJHBAC
{-# LANGUAGE ScopedTypeVariables, OverloadedStrings, NoImplicitPrelude #-}
module Main where
import ClassyPrelude
import Network.Bitcoin
import Control.Concurrent
import qualified Data.Configurator as C
import qualified Data.Vector as V
import System.IO(FilePath)
main :: IO ()
main = do
cfg <- loadConfig "aftok-payouts.cfg"
loop cfg
loop :: QPConfig -> IO ()
loop cfg = do
distributePayouts cfg
loop cfg
data QPConfig = QPConfig
{ pollingInterval :: Int
, bitcoindUrl :: String
, bitcoindUser :: ByteString
, bitcoindPassword :: ByteString
, payoutMinConfirmations :: Int
} deriving Show
loadConfig :: System.IO.FilePath -> IO QPConfig
loadConfig cfgFile = do
cfg <- C.load [C.Required cfgFile]
parseQPConfig cfg
parseQPConfig :: CT.Config -> IO QPConfig
parseQPConfig cfg =
QPConfig <$> C.require cfg "pollingInterval"
<*> C.require cfg "bitcoindUrl"
<*> C.require cfg "bitcoindUser"
<*> C.require cfg "bitcoindPassword"
<*> C.require cfg "payoutMinConfirmations"
btcClient :: QPConfig -> IO Client
btcClient = getClient <$> bitcoindUrl <*> bitcoindUser <*> bitcoindPassword
distributePayouts :: QPConfig -> IO ()
distributePayouts cfg = do
-- find unspent transactions
client <- btcClient cfg
unspent <- listUnspent client (Just . payoutMinConfirmations $ cfg) Nothing V.empty
-- get payouts amounts
(Payouts p) <- currentPayouts (qcConfig cfg)
-- create a new txn spending all UTXOs to payouts
putStrLn . tshow $ unspent
putStrLn . tshow $ p
<*> parseQCConfig (C.subconfig "qcConfig" cfg)
, qcConfig :: QCConfig
threadDelay (pollingInterval cfg)
import Aftok.Client
import Aftok.TimeLog
import qualified Data.Configurator.Types as CT
Executable aftok-payouts
default-language: Haskell2010
ghc-options: -Wall -Werror
hs-source-dirs: payouts
default-extensions: NoImplicitPrelude
, OverloadedStrings
, RecordWildCards
, ScopedTypeVariables
main-is: Main.hs
build-depends:
aftok
, base
, classy-prelude >= 0.10.2
, containers
, either
, mtl >= 2 && < 3
, lens
, text
, thyme
, vector
, transformers
, configurator
, optparse-applicative
, bytestring
, network-bitcoin
newtype PBTC = PBTC BTC
instance ToField PBTC where
toField (PBTC btc) = Plain . fromByteString . fromString $ showFixed False btc
newtype PSatoshi = PSatoshi Satoshi
instance ToField PSatoshi where
toField (PSatoshi btc) = Plain . fromByteString . fromString $ showFixed False btc
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Aftok.Types where
import Data.Word
import ClassyPrelude
newtype Satoshi = Satoshi Word64
deriving (Show, Eq, Ord, Num, Real, Bounded)
flags: {}
packages:
- '.'
extra-deps:
- snaplet-postgresql-simple-0.6.0.4
- resource-pool-catchio-0.2.1.0
resolver: lts-5.3
#allow-newer: true