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 whereimport ClassyPreludeimport Network.Bitcoinimport Control.Concurrentimport qualified Data.Configurator as Cimport qualified Data.Vector as Vimport System.IO(FilePath)main :: IO ()main = docfg <- loadConfig "aftok-payouts.cfg"loop cfgloop :: QPConfig -> IO ()loop cfg = dodistributePayouts cfgloop cfgdata QPConfig = QPConfig{ pollingInterval :: Int, bitcoindUrl :: String, bitcoindUser :: ByteString, bitcoindPassword :: ByteString, payoutMinConfirmations :: Int} deriving ShowloadConfig :: System.IO.FilePath -> IO QPConfigloadConfig cfgFile = docfg <- C.load [C.Required cfgFile]parseQPConfig cfgparseQPConfig :: CT.Config -> IO QPConfigparseQPConfig 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 ClientbtcClient = getClient <$> bitcoindUrl <*> bitcoindUser <*> bitcoindPassworddistributePayouts :: QPConfig -> IO ()distributePayouts cfg = do-- find unspent transactionsclient <- btcClient cfgunspent <- listUnspent client (Just . payoutMinConfirmations $ cfg) Nothing V.empty-- get payouts amounts(Payouts p) <- currentPayouts (qcConfig cfg)-- create a new txn spending all UTXOs to payoutsputStrLn . tshow $ unspentputStrLn . tshow $ p<*> parseQCConfig (C.subconfig "qcConfig" cfg), qcConfig :: QCConfigthreadDelay (pollingInterval cfg)import Aftok.Clientimport Aftok.TimeLogimport qualified Data.Configurator.Types as CT
Executable aftok-payoutsdefault-language: Haskell2010ghc-options: -Wall -Werrorhs-source-dirs: payoutsdefault-extensions: NoImplicitPrelude, OverloadedStrings, RecordWildCards, ScopedTypeVariablesmain-is: Main.hsbuild-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 BTCinstance ToField PBTC wheretoField (PBTC btc) = Plain . fromByteString . fromString $ showFixed False btc
newtype PSatoshi = PSatoshi Satoshiinstance ToField PSatoshi wheretoField (PSatoshi btc) = Plain . fromByteString . fromString $ showFixed False btc
{-# LANGUAGE GeneralizedNewtypeDeriving #-}module Aftok.Types whereimport Data.Wordimport ClassyPreludenewtype Satoshi = Satoshi Word64deriving (Show, Eq, Ord, Num, Real, Bounded)
flags: {}packages:- '.'extra-deps:- snaplet-postgresql-simple-0.6.0.4- resource-pool-catchio-0.2.1.0resolver: lts-5.3#allow-newer: true