ZR::BitcoinAddress ZrSatoshiBitcoin::mkOrderAddress( const ZR::ZR_Number & amount ) { std::string addr = newAddress(); if( addr.empty() ) return addr; try{ JsonRpc rpc( m_settings ); JsonRpc::JsonData res = rpc.executeRpc ( "sendtoaddress", addr, JsonRpc::JsonData( amount.toDouble() ) ); // TODO: Error handling std::string id = res.asString(); // make sure the Satoshi client does not touch "id" // this will go away if the Satoshi client is restarted // may be unnecessary for other implementations of this class, e.g. libbitcoin JsonRpc::JsonData addrArray( Json::arrayValue ); addrArray.append( addr ); JsonRpc::JsonData res2 = rpc.executeRpc ( "listunspent", 0, 999999, addrArray ); unsigned int vout = res2[0u][ "vout" ].asUInt(); JsonRpc::JsonData lockObjArray( Json::arrayValue ); JsonRpc::JsonData lockObj; lockObj[ "txid" ] = id; lockObj[ "vout" ] = vout; lockObjArray.append( lockObj ); JsonRpc::JsonData res1 = rpc.executeRpc ( "lockunspent", true, lockObjArray ); } catch( std::runtime_error e ){ g_ZeroReservePlugin->placeMsg( std::string( "Exception caught at " ) + __func__ + ": " + e.what() + " Cannot make an order address. Insufficient funds? If you have enough, try restarting the Satoshi Client." ); std::cerr << "Zero Reserve: " << __func__ << ": Exception caught: " << e.what() << std::endl; print_stacktrace(); return std::string(); } return addr; }
/** * Sign a message with this address. This may throw if the address * is invalid, the wallet locked or the private key is not owned. * @param msg The message that should be signed. * @return The message's signature. * @throws NoPrivateKey if this address is not owned. * @throws std::runtime_error if the address is invalid or the wallet locked. */ std::string CoinInterface::Address::signMessage (const std::string& msg) const { if (!valid) throw std::runtime_error ("Can't sign with invalid address."); try { const JsonRpc::JsonData res = rpc->executeRpc ("signmessage", addr, msg); return res.asString (); } catch (const JsonRpc::RpcError& exc) { switch (exc.getErrorCode ()) { case -13: throw std::runtime_error ("Need to unlock the wallet first."); case -3: { std::ostringstream msg; msg << "You don't have the private key of " << addr << " in order" << " to sign messages with that address."; throw NoPrivateKey (msg.str ()); } default: throw exc; } } }
void ZrSatoshiBitcoin::loadWallets( std::vector< ZR::MyWallet *> & wallets ) { JsonRpc rpc( m_settings ); try{ JsonRpc::JsonData res = rpc.executeRpc ("listaddressgroupings"); for( nmcrpc::JsonRpc::JsonData::iterator it1 = res.begin(); it1 != res.end(); it1++ ){ JsonRpc::JsonData res0 = *it1; assert (res0.isArray()); for( nmcrpc::JsonRpc::JsonData::iterator it2 = res0.begin(); it2 != res0.end(); it2++ ){ JsonRpc::JsonData res1 = *it2; JsonRpc::JsonData res2 = res1[ 0u ]; ZR::BitcoinAddress address = res2.asString(); JsonRpc::JsonData res21 = res1[ 1u ]; ZR::ZR_Number balance = res21.asDouble(); ZR::MyWallet * wallet = new SatoshiWallet( address, balance ); wallets.push_back( wallet ); } } } catch( std::runtime_error e ){ std::cerr << "Zero Reserve: " << __func__ << ": Exception caught: " << e.what() << std::endl; print_stacktrace(); } }
/** * Query for the number of confirmations a transaction has. * @param txid The transaction id to check for. * @return Number of confirmations the transaction has. * @throws JsonRpc::RpcError if the tx is not found. */ unsigned CoinInterface::getNumberOfConfirmations (const std::string& txid) { const JsonRpc::JsonData res = rpc.executeRpc ("gettransaction", txid); assert (res.isObject ()); return res["confirmations"].asInt (); }
const ZR::BitcoinAddress ZrSatoshiBitcoin::newAddress() const { std::string addr; try{ JsonRpc rpc( m_settings ); JsonRpc::JsonData resAddr = rpc.executeRpc ( "getnewaddress" ); addr = resAddr.asString(); } catch( std::runtime_error e ){ std::cerr << "Zero Reserve: " << __func__ << ": Exception caught: " << e.what() << std::endl; g_ZeroReservePlugin->placeMsg( std::string( "Exception caught at " ) + __func__ + ": " + e.what() + " Cannot create new Bitcoin address." ); print_stacktrace(); } return addr; }
ZR::MyWallet * ZrSatoshiBitcoin::mkWallet( ZR::MyWallet::WalletType wType ) { JsonRpc rpc( m_settings ); try{ if( wType == ZR::MyWallet::WIFIMPORT ){ JsonRpc::JsonData res = rpc.executeRpc ( "getnewaddress" ); ZR::BitcoinAddress address = res.asString(); return new SatoshiWallet( address, 0 ); } } catch( std::runtime_error e ){ std::cerr << "Zero Reserve: " << __func__ << ": Exception caught: " << e.what() << std::endl; print_stacktrace(); } return NULL; }
/** * Check a message signature against this address. If this address * is invalid, false is returned. * @param msg The message that should be signed. * @param sig The message's signature. * @return True iff the signature matches the message. */ bool CoinInterface::Address::verifySignature (const std::string& msg, const std::string& sig) const { if (!valid) return false; try { JsonRpc::JsonData res = rpc->executeRpc ("verifymessage", addr, sig, msg); return (res.isBool () && res.asBool ()); } catch (const JsonRpc::RpcError& exc) { // Malformed base64? if (exc.getErrorCode () == -5) return false; throw exc; } }
int main () { RpcSettings settings; settings.readDefaultConfig (); JsonRpc rpc(settings); JsonRpc::JsonData res = rpc.executeRpc ("getinfo"); assert (res.isObject ()); std::cout << "Running version: " << res["version"].asInt () << std::endl; res = rpc.executeRpc ("name_show", "id/domob"); assert (res.isObject ()); assert (res["name"].asString () == "id/domob"); assert (res["value"].isString ()); assert (res["expires_in"].isInt ()); try { rpc.executeRpc ("method-does-not-exist", 5, ""); assert (false); } catch (const JsonRpc::RpcError& err) { assert (err.getErrorCode () == -32601); } try { rpc.executeRpc ("name_history", "name-does-not-exist"); assert (false); } catch (const JsonRpc::RpcError& err) { assert (err.getErrorCode () == -4); } return EXIT_SUCCESS; }
/** * Create a new address (as per "getnewaddress") and return it. * @return Newly created address. */ CoinInterface::Address CoinInterface::createAddress () { const JsonRpc::JsonData addr = rpc.executeRpc ("getnewaddress"); return Address (rpc, addr.asString ()); }