Difference between revisions of "PHP developer intro"

From Bitcoin Wiki
Jump to: navigation, search
Line 15: Line 15:
 
$ cd bitcoin/
 
$ cd bitcoin/
 
$ make -f makefile.unix bitcoind
 
$ make -f makefile.unix bitcoind
 +
</source>
 +
 +
Before running bitcoind you will need to create a file in ~/.bitcoin/bitcoin.conf
 +
<source>
 +
rpcuser=user
 +
rpcpassword=password
 +
</source>
 +
 +
Now run bitcoind:
 +
<source>
 
$ ./bitcoind
 
$ ./bitcoind
 
# wait a few seconds for it to start up
 
# wait a few seconds for it to start up
Line 21: Line 31:
  
 
Bitcoin is now initialising and you must wait until "blocks" is at the [http://bitcoinwatch.com/ current count].
 
Bitcoin is now initialising and you must wait until "blocks" is at the [http://bitcoinwatch.com/ current count].
 +
 +
== First steps ==
 +
 +
Assuming Bitcoin has finished the initialisation process; download the file jsonRPCClient.php from [http://jsonrpcphp.org/ JSON-RPC PHP]. The other files can be safely discarded.
 +
 +
<source lang="php">
 +
  require_once 'jsonRPCClient.php';
 +
 
 +
  $bitcoin = new jsonRPCClient('http://user:password@127.0.0.1:8332/');
 +
 
 +
  echo "<pre>\n";
 +
  print_r($bitcoin->getinfo());
 +
  echo "</pre>";
 +
</source>
 +
 +
=== Precision ===
 +
 +
Because PHP has no option to JSON decode to accurate decimal class, you should internally use GMP. Treat each number like a large int with 8 decimal places (this can be trimmed for display).
 +
 +
Our version of Bitcoin treats every monetary value as int64 8 decimal strings. So 1 BTC will be "100000000". Use PHP's GMP functions to manipulate these values accurately.
 +
 +
For converting between internal GMP numbers and display/user input, you can use these functions:
 +
<source lang="php">
 +
# converts a user supplied number to our internal representation
 +
#  3.14 => "314000000"
 +
# accepts strings, floats and ints as input
 +
function numstr_to_internal($numstr)
 +
{
 +
    return bcmul($numstr, pow(10, 8), 0);
 +
}
 +
# converts an internal number to an end user number for display as defined by precision
 +
#  314100000 => "3.14"
 +
# accepts GMP numbers, ints and strings as input
 +
function internal_to_numstr($num, $precision=2)
 +
{
 +
    $repr = gmp_strval($num);
 +
    $repr = bcdiv($repr, pow(10, 8), $precision);
 +
    # now tidy output...
 +
    # trim trailing 0s
 +
    $repr = rtrim($repr, '0');
 +
    # and a trailing . if it exists
 +
    $repr = rtrim($repr, '.');
 +
    return $repr;
 +
}
 +
 +
$num_internal = numstr_to_internal("3.141");
 +
echo "<p>".$num_internal."</p>";
 +
$num_display = internal_to_numstr($num_internal);
 +
echo "<p>".$num_display."</p>";
 +
</source>
 +
 +
If you need to do a decimal division in GMP, then GMP only supports integer division + a remainder ([http://php.net/manual/en/function.gmp-div-qr.php gmp_div_qr]). The work-around for this, is to use the bcmath module:
 +
<source lang="php">
 +
$a = gmp_init("100");
 +
$b = gmp_init("3");
 +
echo "<p>".bcdiv(gmp_strval($a), gmp_strval($b), 3)."</p>";
 +
</source>
 +
 +
Note that bcdiv only uses strings.
 +
 +
See also: [http://php.net/manual/en/ref.gmp.php GMP] and [http://php.net/manual/en/ref.bc.php BC Math] manuals.

Revision as of 09:51, 21 March 2011

For the sake of this tutorial we assume an Ubuntu server running with PHP. The use case here is integrating a shopping system to accept Bitcoins. We assume some knowledge of Bitcoin and experience in PHP.

You can substitute any other language here for PHP. See the associated API reference pages for info on other languages.

You will run Bitcoin in daemon mode. The way PHP communicates is through localhost HTTP requests. You use a library called JSON-RPC to call the various functions. It will respond back with a JSON object.

Setting up Bitcoin

Bitcoins are stored internally as 64 bit integers. Because PHP's JSON implementation does not provide a way to use custom types for decimal numbers, we must use an alternative branch of Bitcoin which returns all decimal amounts as strings.

# install needed packages
$ sudo apt-get install build-essential libboost-all-dev libdb4.7++-dev libssl-dev libglib2.0-dev
$ git clone git://github.com/genjix/bitcoin.git
$ cd bitcoin/
$ make -f makefile.unix bitcoind

Before running bitcoind you will need to create a file in ~/.bitcoin/bitcoin.conf

rpcuser=user
rpcpassword=password

Now run bitcoind:

$ ./bitcoind
# wait a few seconds for it to start up
$ ./bitcoind getinfo

Bitcoin is now initialising and you must wait until "blocks" is at the current count.

First steps

Assuming Bitcoin has finished the initialisation process; download the file jsonRPCClient.php from JSON-RPC PHP. The other files can be safely discarded.

  require_once 'jsonRPCClient.php';
  
  $bitcoin = new jsonRPCClient('http://user:password@127.0.0.1:8332/');
   
  echo "<pre>\n";
  print_r($bitcoin->getinfo());
  echo "</pre>";

Precision

Because PHP has no option to JSON decode to accurate decimal class, you should internally use GMP. Treat each number like a large int with 8 decimal places (this can be trimmed for display).

Our version of Bitcoin treats every monetary value as int64 8 decimal strings. So 1 BTC will be "100000000". Use PHP's GMP functions to manipulate these values accurately.

For converting between internal GMP numbers and display/user input, you can use these functions:

# converts a user supplied number to our internal representation
#  3.14 => "314000000"
# accepts strings, floats and ints as input
function numstr_to_internal($numstr)
{
    return bcmul($numstr, pow(10, 8), 0);
}
# converts an internal number to an end user number for display as defined by precision
#   314100000 => "3.14"
# accepts GMP numbers, ints and strings as input
function internal_to_numstr($num, $precision=2)
{
    $repr = gmp_strval($num);
    $repr = bcdiv($repr, pow(10, 8), $precision);
    # now tidy output...
    # trim trailing 0s
    $repr = rtrim($repr, '0');
    # and a trailing . if it exists
    $repr = rtrim($repr, '.');
    return $repr;
}

$num_internal = numstr_to_internal("3.141");
echo "<p>".$num_internal."</p>";
$num_display = internal_to_numstr($num_internal);
echo "<p>".$num_display."</p>";

If you need to do a decimal division in GMP, then GMP only supports integer division + a remainder (gmp_div_qr). The work-around for this, is to use the bcmath module:

$a = gmp_init("100");
$b = gmp_init("3");
echo "<p>".bcdiv(gmp_strval($a), gmp_strval($b), 3)."</p>";

Note that bcdiv only uses strings.

See also: GMP and BC Math manuals.