diff --git a/extra/bitcoin/client/authors.txt b/extra/bitcoin/client/authors.txt new file mode 100644 index 0000000000..44b06f94bc --- /dev/null +++ b/extra/bitcoin/client/authors.txt @@ -0,0 +1 @@ +Chris Double diff --git a/extra/bitcoin/client/client-docs.factor b/extra/bitcoin/client/client-docs.factor new file mode 100644 index 0000000000..f5136b66dc --- /dev/null +++ b/extra/bitcoin/client/client-docs.factor @@ -0,0 +1,271 @@ +! Copyright (C) 2010 Chris Double. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax ; +IN: bitcoin.client + +HELP: bitcoin-server +{ $values + { "string" "a string" } +} +{ $description + "Returns the hostname of the json-rpc server for the bitcoin client. " + "This defaults to 'localhost' or the value of the 'bitcoin-server' " + "variable." +} +{ $see-also bitcoin-port bitcoin-user bitcoin-password } ; + +HELP: bitcoin-port +{ $values + { "n" "a number" } +} +{ $description + "Returns the port of the json-rpc server for the bitcoin client. " + "This defaults to '8332' or the value of the 'bitcoin-port' " + "variable." +} +{ $see-also bitcoin-server bitcoin-user bitcoin-password } ; + +HELP: bitcoin-user +{ $values + { "string" "a string" } +} +{ $description + "Returns the username required to authenticate with the json-rpc " + "server for the bitcoin client. This defaults to empty or the " + "value of the 'bitcoin-user' variable." +} +{ $see-also bitcoin-port bitcoin-server bitcoin-password } ; + +HELP: bitcoin-password +{ $values + { "string" "a string" } +} +{ $description + "Returns the password required to authenticate with the json-rpc " + "server for the bitcoin client. This returns the " + "value of the 'bitcoin-password' variable." +} +{ $see-also bitcoin-port bitcoin-server bitcoin-user } ; + +HELP: get-addresses-by-label +{ $values + { "label" "a string" } + { "seq" "a sequence" } +} +{ $description + "Returns the list of addresses with the given label." +} ; + +HELP: get-balance +{ $values + { "n" "a number" } +} +{ $description + "Returns the server's available balance." +} ; + +HELP: get-block-count +{ $values + { "n" "a number" } +} +{ $description + "Returns the number of blocks in the longest block chain." +} ; + +HELP: get-block-number +{ $values + { "n" "a number" } +} +{ $description + "Returns the block number of the latest block in the longest block chain." +} ; + +HELP: get-connection-count +{ $values + { "n" "a number" } +} +{ $description + "Returns the number of connections to other nodes." +} ; + +HELP: get-difficulty +{ $values + { "n" "a number" } +} +{ $description + "Returns the proof-of-work difficulty as a multiple of the minimum " + "difficulty." +} ; + +HELP: get-generate +{ $values + { "?" "a boolean" } +} +{ $description + "Returns true if the server is trying to generate bitcoins, false " + "otherwise." +} ; + +HELP: set-generate +{ $values + { "gen" "a boolean" } + { "n" "a number" } +} +{ $description + "If 'gen' is true, the server starts generating bitcoins. If 'gen' is " + "'false' then the server stops generating bitcoins. 'n' is the number " + "of CPU's to use while generating. A value of '-1' means use all the " + "CPU's available." +} ; + +HELP: get-info +{ $values + { "result" "an assoc" } +} +{ $description + "Returns an assoc containing server information." +} ; + +HELP: get-label +{ $values + { "address" "a string" } + { "label" "a string" } +} +{ $description + "Returns the label associated with the given address." +} ; + +HELP: set-label +{ $values + { "address" "a string" } + { "label" "a string" } +} +{ $description + "Sets the label associateed with the given address." +} ; + +HELP: remove-label +{ $values + { "address" "a string" } +} +{ $description + "Removes the label associated with the given address." +} ; + +HELP: get-new-address +{ $values + { "address" "a string" } +} +{ $description + "Returns a new bitcoin address for receiving payments." +} ; + +HELP: get-new-labelled-address +{ $values + { "label" "a string" } + { "address" "a string" } +} +{ $description + "Returns a new bitcoin address for receiving payments. The given " + "label is associated with the new address." +} ; + +HELP: get-received-by-address +{ $values + { "address" "a string" } + { "amount" "a number" } +} +{ $description + "Returns the total amount received by the address in transactions " + "with at least one confirmation." +} ; + +HELP: get-confirmed-received-by-address +{ $values + { "address" "a string" } + { "minconf" "a number" } + { "amount" "a number" } +} +{ $description + "Returns the total amount received by the address in transactions " + "with at least 'minconf' confirmations." +} ; + +HELP: get-received-by-label +{ $values + { "label" "a string" } + { "amount" "a number" } +} +{ $description + "Returns the total amount received by addresses with 'label' in transactions " + "with at least one confirmation." +} ; + +HELP: get-confirmed-received-by-label +{ $values + { "label" "a string" } + { "minconf" "a number" } + { "amount" "a number" } +} +{ $description + "Returns the total amount received by the addresses with 'label' in transactions " + "with at least 'minconf' confirmations." +} ; + +HELP: list-received-by-address +{ $values + { "minconf" "a number" } + { "include-empty" "a boolean" } + { "seq" "a sequence" } +} +{ $description + "Return a sequence containing an assoc of data about the payments an " + "address has received. 'include-empty' indicates whether addresses that " + "haven't received any payments should be included. 'minconf' is the " + "minimum number of confirmations before payments are included." +} ; + +HELP: list-received-by-label +{ $values + { "minconf" "a number" } + { "include-empty" "a boolean" } + { "seq" "a sequence" } +} +{ $description + "Return a sequence containing an assoc of data about the payments that " + "addresses with the given label have received. 'include-empty' " + " indicates whether addresses that " + "haven't received any payments should be included. 'minconf' is the " + "minimum number of confirmations before payments are included." +} ; + +HELP: send-to-address +{ $values + { "address" "a string" } + { "amount" "a number" } + { "?" "a boolean" } +} +{ $description + "Sends 'amount' from the server's available balance to 'address'. " + "'amount' is rounded to the nearest 0.01. Returns a boolean indicating " + "if the call succeeded." +} ; + +HELP: stop +{ $description + "Stops the bitcoin server." +} ; + +HELP: list-transactions +{ $values + { "count" "a number" } + { "include-generated" "a boolean" } + { "seq" "a sequence" } +} +{ $description + "Return's a sequence containing up to 'count' most recent transactions." + "This requires a patched bitcoin server so may not work with old or unpatched " + "servers." +} ; + + diff --git a/extra/bitcoin/client/client.factor b/extra/bitcoin/client/client.factor new file mode 100644 index 0000000000..b3413d6b3e --- /dev/null +++ b/extra/bitcoin/client/client.factor @@ -0,0 +1,140 @@ +! Copyright (C) 2010 Chris Double. +! See http://factorcode.org/license.txt for BSD license. +! +! bitcoin API documentation at: +! http://www.bitcoin.org/wiki/doku.php?id=api +! +! Donations can be sent to the following bitcoin address: +! 1HVMkUcaPhCeCK3rrBm31EY2bf5r33VHsj +! +USING: + accessors + assocs + base64 + byte-arrays + hashtables + http + http.client + io.encodings.binary + json.reader + json.writer + kernel + locals + namespaces + sequences + strings + urls +; +IN: bitcoin.client + +: bitcoin-server ( -- string ) + \ bitcoin-server get "localhost" or ; + +: bitcoin-port ( -- n ) + \ bitcoin-port get 8332 or ; + +: bitcoin-user ( -- string ) + \ bitcoin-user get "" or ; + +: bitcoin-password ( -- string ) + \ bitcoin-password get ; + + + "http" >>protocol + "/" >>path + bitcoin-server >>host + bitcoin-port >>port ; + +:: payload ( method params -- data ) + "text/plain" + binary >>content-encoding + H{ + { "method" method } + { "params" params } + } clone >json >byte-array >>data ; + +: basic-auth ( -- string ) + bitcoin-user bitcoin-password ":" glue >base64 >string + "Basic " prepend ; + +: bitcoin-request ( method params -- request ) + payload bitcoin-url + basic-auth "Authorization" set-header + dup post-data>> data>> length "Content-Length" set-header + http-request nip >string json> "result" swap at ; + +PRIVATE> + +:: get-addresses-by-label ( label -- seq ) + "getaddressesbylabel" { label } bitcoin-request ; + +: get-balance ( -- n ) + "getbalance" { } bitcoin-request ; + +: get-block-count ( -- n ) + "getblockcount" { } bitcoin-request ; + +: get-block-number ( -- n ) + "getblocknumber" { } bitcoin-request ; + +: get-connection-count ( -- n ) + "getconnectioncount" { } bitcoin-request ; + +: get-difficulty ( -- n ) + "getdifficulty" { } bitcoin-request ; + +: get-generate ( -- ? ) + "getgenerate" { } bitcoin-request ; + +:: set-generate ( gen n -- ) + "setgenerate" { gen n } bitcoin-request drop ; + +: get-info ( -- result ) + "getinfo" { } bitcoin-request ; + +:: get-label ( address -- label ) + "getlabel" { address } bitcoin-request ; + +:: set-label ( address label -- ) + "setlabel" { address label } bitcoin-request drop ; + +:: remove-label ( address -- ) + "setlabel" { address } bitcoin-request drop ; + +: get-new-address ( -- address ) + "getnewaddress" { } bitcoin-request ; + +:: get-new-labelled-address ( label -- address ) + "getnewaddress" { label } bitcoin-request ; + +:: get-received-by-address ( address -- amount ) + "getreceivedbyaddress" { address } bitcoin-request ; + +:: get-confirmed-received-by-address ( address minconf -- amount ) + "getreceivedbyaddress" { address minconf } bitcoin-request ; + +:: get-received-by-label ( label -- amount ) + "getreceivedbylabel" { label } bitcoin-request ; + +:: get-confirmed-received-by-label ( label minconf -- amount ) + "getreceivedbylabel" { label minconf } bitcoin-request ; + +:: list-received-by-address ( minconf include-empty -- seq ) + "listreceivedbyaddress" { minconf include-empty } bitcoin-request ; + +:: list-received-by-label ( minconf include-empty -- seq ) + "listreceivedbylabel" { minconf include-empty } bitcoin-request ; + +:: send-to-address ( address amount -- ? ) + "sendtoaddress" { address amount } bitcoin-request "sent" = ; + +: stop ( -- ) + "stop" { } bitcoin-request drop ; + +#! requires patched bitcoind +:: list-transactions ( count include-generated -- seq ) + "listtransactions" { count include-generated } bitcoin-request ; + diff --git a/extra/bitcoin/client/summary.txt b/extra/bitcoin/client/summary.txt new file mode 100644 index 0000000000..6b6c533607 --- /dev/null +++ b/extra/bitcoin/client/summary.txt @@ -0,0 +1 @@ +Client for getting information from a bitcoin server diff --git a/extra/bitcoin/client/tags.txt b/extra/bitcoin/client/tags.txt new file mode 100644 index 0000000000..53c6fea826 --- /dev/null +++ b/extra/bitcoin/client/tags.txt @@ -0,0 +1,2 @@ +client +bitcoin