code: function sendPreparedMessageToConnectedHub(ws, recipient_device_pubkey, message_hash, json, callbacks){
  	network.sendRequest(ws, 'hub/get_temp_pubkey', recipient_device_pubkey, false, function(ws, request, response){
  		function handleError(error){
  			callbacks.ifError(error);
  			db.query("UPDATE outbox SET last_error=? WHERE message_hash=?", [error, message_hash], function(){});
  		}
  		if (response.error)
  			return handleError(response.error);
  		var objTempPubkey = response;
  		if (!objTempPubkey.temp_pubkey || !objTempPubkey.pubkey || !objTempPubkey.signature)
  			return handleError("missing fields in hub response");
  		if (objTempPubkey.pubkey !== recipient_device_pubkey)
  			return handleError("temp pubkey signed by wrong permanent pubkey");
  		if (!ecdsaSig.verify(objectHash.getDeviceMessageHashToSign(objTempPubkey), objTempPubkey.signature, objTempPubkey.pubkey))
  			return handleError("wrong sig under temp pubkey");
  		var objEncryptedPackage = createEncryptedPackage(json, objTempPubkey.temp_pubkey);
  		var recipient_device_address = objectHash.getDeviceAddress(recipient_device_pubkey);
  		var objDeviceMessage = {
  			encrypted_package: objEncryptedPackage,
  			to: recipient_device_address,
  			pubkey: objMyPermanentDeviceKey.pub_b64 // who signs. Essentially, the from again. 
  		};
  		objDeviceMessage.signature = ecdsaSig.sign(objectHash.getDeviceMessageHashToSign(objDeviceMessage), objMyPermanentDeviceKey.priv);
  		network.sendRequest(ws, 'hub/deliver', objDeviceMessage, false, function(ws, request, response){
  			if (response === "accepted"){
  				db.query("DELETE FROM outbox WHERE message_hash=?", [message_hash], function(){
  					callbacks.ifOk();
  				});
  			}
  			else
  				handleError( response.error || ("unrecognized response: "+JSON.stringify(response)) );
  		});
  	});
  }
docs: first param is WebSocket only