def get_sil(address, block_height=0): """ Get the Simplified Inputs List (SIL) :param address: The address that received the transactions :param block_height: A block height (optional) :return: A dictionary containing the SIL and the explorer that provided the data """ if not valid_address(address): return {'error': 'Invalid address: ' + address} txs_data = data.transactions(address) if 'transactions' in txs_data: return {'SIL': txs_2_sil(txs_data['transactions'], block_height)} else: return {'error': 'Unable to retrieve transactions of address %s' % address}
def get_profile(address, block_height=0): """ Get the profile of an address :param address: The address :param block_height: A block height (optional) :return: A dict containing the profile and the explorer that provided the data """ if not valid_address(address): return {'error': 'Invalid address: ' + address} txs_data = data.transactions(address) if 'transactions' in txs_data: return {'profile': txs_to_profile(txs_data['transactions'], address, block_height)} else: return {'error': 'Unable to retrieve transactions of address %s' % address}
def get_transactions(address): response.content_type = 'application/json' return transactions(address)
def run(self): LOG.info('Running Spellbook Script: %s' % os.path.splitext(os.path.basename(__file__))[0]) LOG.info('triggered: %s' % self.triggered) # If the trigger contains data, override the information in self.json if self.data is not None: if self.json is None: self.json = {} for key, value in self.data.items(): self.json[key] = value if self.json is not None: if 'payment_request_id' not in self.json: LOG.error( 'Payment request json does not contain the payment request id!' ) return try: payment_request = PaymentRequest( payment_request_id=self.json['payment_request_id']) except Exception as ex: self.http_response = {'error': str(ex)} return if payment_request.txid is not None: tx_data = transaction(txid=payment_request.txid) tx = tx_data['transaction'] if 'transaction' in tx_data else {} payment_request.confirmations = tx[ 'confirmations'] if 'confirmations' in tx else None else: # Fallback method in case the listener did not pick up the transaction (tx might have happened after listener timed out) balance_data = balance(address=payment_request.address) # If the final balance of the address is equal or more than the requested amount, assume the most recent transaction is the payment transaction # Note: there could be situations where multiple transactions are sent, those situations are not handled in this example app if 'balance' in balance_data and balance_data['balance'][ 'final'] >= payment_request.amount_btc: LOG.info( 'Current balance of %s: %s' % (payment_request.address, balance_data['balance'])) transactions_data = transactions( address=payment_request.address) if 'transactions' in transactions_data: tx = transactions_data['transactions'][-1] payment_request.txid = tx['txid'] payment_request.confirmations = tx['confirmations'] if payment_request.confirmations >= 6: payment_request.status = 'Confirmed' elif 1 <= payment_request.confirmations < 6: payment_request.status = '%s of 6 confirmations' % payment_request.confirmations payment_request.save() LOG.info('Retrieving status of payment request: %s' % payment_request.payment_request_id) LOG.info('Seller id: %s' % payment_request.seller_id) LOG.info('Fiat Amount: %s %s' % (payment_request.amount_fiat, payment_request.currency)) LOG.info('BTC Amount: %s (price %s %s/BTC @ %s)' % (payment_request.amount_btc, payment_request.price_btc, payment_request.currency, datetime.fromtimestamp(payment_request.price_timestamp ).strftime('%Y-%m-%d %H:%M:%S'))) LOG.info('Note: %s' % payment_request.note) LOG.info('Address: %s' % payment_request.address) LOG.info('Status: %s' % payment_request.status) LOG.info('Txid: %s' % payment_request.txid) LOG.info('Confirmations: %s' % payment_request.confirmations) self.http_response = payment_request.json_encodable() if payment_request.status == 'Confirmed': # Send an email to notify the payment is confirmed action = get_action(action_id='tx_received_email', action_type=ActionType.SENDMAIL) action.mail_subject = 'Payment request %s is confirmed' % payment_request.payment_request_id action.mail_recipients = NOTIFICATION_EMAIL action.mail_body_template = os.path.join( 'PaymentProcessor', 'templates', 'PaymentConfirmed.txt' ) # The spellbook will search for the template in the 'email_templates' and in the 'apps' directory, subdirectories are allowed, just need to specify the full path as shown here action.mail_variables = { 'PAYMENT_REQUEST_ID': payment_request.payment_request_id, 'SELLER_ID': payment_request.seller_id, 'AMOUNT_FIAT': payment_request.amount_fiat, 'CURRENCY': payment_request.currency, 'NOTE': payment_request.note, 'ADDRESS': payment_request.address, 'AMOUNT_BTC': payment_request.amount_btc / 1e8, # amount is in satoshis, display in BTC 'PRICE_BTC': payment_request.price_btc, 'PRICE_TIMESTAMP': datetime.fromtimestamp( payment_request.price_timestamp).strftime( '%Y-%m-%d %H:%M:%S'), 'TXID': payment_request.txid } action.run() # Now that the payment is complete and confirmation email is sent, we can delete the trigger by setting # the self_destruct time to something in the past, this will delete the trigger next time check_triggers happens # We can not delete it right now because it is still in use by the spellbookserver trigger = get_trigger( trigger_id=payment_request.payment_request_id, trigger_type=TriggerType.BALANCE) trigger.self_destruct = int(time.time()) - 1 trigger.save()