def put(args): targetFile = args[0] targetFileName = os.path.basename(targetFile) patchedFileName = targetFileName.split( ".")[0] + "_patched." + targetFileName.split(".")[1] with open(targetFile, "rb") as hostFile, open(patchedFileName, "wb+") as patchedFile: patchedFile.write(hostFile.read()) index = 1 while index < len(args): sourceFile = args[index] sourceFileName = os.path.basename(sourceFile) print("trying to hide", sourceFile, "...") with open(sourceFile, "rb") as fileToHide: patchedFile.write( binascii.hexlify( bytes(sourceFileName + DELIMITER, ENCODING))) patchedFile.write(binascii.hexlify(fileToHide.read())) patchedFile.write( binascii.hexlify( bytes(sourceFileName + DELIMITER, ENCODING))) print("...", sourceFileName, "hidden!") index += 1 util = TimeUtil() util.setModTime(patchedFileName, util.getModTime(targetFile))
def __create_like_notification(self, article_info): notification_table = self.dynamodb.Table(os.environ['NOTIFICATION_TABLE_NAME']) notification_id = '-'.join([settings.LIKE_NOTIFICATION_TYPE, article_info['user_id'], article_info['article_id']]) notification = notification_table.get_item(Key={'notification_id': notification_id}).get('Item') liked_count = self.__get_article_likes_count() if notification: notification_table.update_item( Key={ 'notification_id': notification_id }, UpdateExpression="set sort_key = :sort_key, article_title = :article_title, liked_count = :liked_count", ExpressionAttributeValues={ ':sort_key': TimeUtil.generate_sort_key(), ':article_title': article_info['title'], ':liked_count': liked_count } ) else: notification_table.put_item(Item={ 'notification_id': notification_id, 'user_id': article_info['user_id'], 'article_id': article_info['article_id'], 'article_title': article_info['title'], 'sort_key': TimeUtil.generate_sort_key(), 'type': settings.LIKE_NOTIFICATION_TYPE, 'liked_count': liked_count, 'created_at': int(time.time()) } )
def main(): print('-----------------------', datetime.datetime.now()) sw = { 'w': lambda: TimeUtil.get_time_weeks(FLAGS.time_interval), 'd': lambda: TimeUtil.get_time_days(FLAGS.time_interval), 'h': lambda: TimeUtil.get_time_hours(FLAGS.time_interval), 'm': lambda: TimeUtil.get_time_minutes(FLAGS.time_interval, TIME_END), 's': lambda: TimeUtil.get_time_seconds(FLAGS.time_interval), } if FLAGS.time_interval > 0: global TIME_BEGIN global TIME_END TIME_BEGIN, TIME_END = sw[FLAGS.time_format]() print(TIME_BEGIN, TIME_BEGIN - FLAGS.time_period * 1000) hadoop_util.get_cluster_information() hadoop_util.get_commonjobs_information() response = requests.get("http://127.0.0.1:5001/update/all") if response.status_code == 200: print("success request http://127.0.0.1:5001/update/all") # response = requests.get('http://127.0.0.1:5002/train_lstm') # if response.status_code == 200: # print("success request http://127.0.0.1:5002/train_lstm") # else: # print("fail request http://127.0.0.1:5002/train_lstm") else: print("fail request http://127.0.0.1:5001/update/all")
def test_datetime(self): timezone_offset = self.request.get('tz_offset') date = self.request.get('datetime') to_timezone_offset = self.request.get('to_tz_offset') if not timezone_offset or not date or not to_timezone_offset: return False date = TimeUtil.str_to_utc_datetime(int(timezone_offset), date) result = TimeUtil.utc_datetime_to_str(int(to_timezone_offset), date) self.response.out.write(result)
def main(): query_parameters = {"state": FLAGS.state} sw = { 'w': lambda: TimeUtil.get_time_weeks(FLAGS.time_interval), 'd': lambda: TimeUtil.get_time_days(FLAGS.time_interval), 'h': lambda: TimeUtil.get_time_hours(FLAGS.time_interval), 'm': lambda: TimeUtil.get_time_minutes(FLAGS.time_interval), 's': lambda: TimeUtil.get_time_seconds(FLAGS.time_interval), } if FLAGS.time_interval > 0: finished_time_begin, finished_time_end = sw[FLAGS.time_format]() query_parameters["finishedTimeBegin"] = finished_time_begin query_parameters["finishedTimeEnd"] = finished_time_end thread_main(query_parameters)
def __create_tip_info(self, transaction_hash, tip_value, burn_transaction, article_info): tip_table = self.dynamodb.Table(os.environ['TIP_TABLE_NAME']) sort_key = TimeUtil.generate_sort_key() user_id = self.event['requestContext']['authorizer']['claims'][ 'cognito:username'] epoch = int(time.time()) tip_info = { 'user_id': user_id, 'to_user_id': article_info['user_id'], 'tip_value': tip_value, 'article_id': self.params['article_id'], 'article_title': article_info['title'], 'transaction': transaction_hash, 'burn_transaction': burn_transaction, 'uncompleted': 1, 'sort_key': sort_key, 'target_date': time.strftime('%Y-%m-%d', time.gmtime(epoch)), 'created_at': epoch } tip_table.put_item(Item=tip_info, ConditionExpression='attribute_not_exists(user_id)')
def __notify_purchaser(self, article_info, user_id, transaction_status): notification_table = self.dynamodb.Table( os.environ['NOTIFICATION_TABLE_NAME']) notification_table.put_item( Item={ 'notification_id': self.__get_randomhash(), 'user_id': user_id, 'acted_user_id': user_id, 'article_id': article_info['article_id'], 'article_user_id': article_info['user_id'], 'article_title': article_info['title'], 'sort_key': TimeUtil.generate_sort_key(), 'type': settings.ARTICLE_PURCHASE_TYPE if transaction_status == 'done' else settings.ARTICLE_PURCHASE_ERROR_TYPE, 'price': int(article_info['price']), 'created_at': int(time.time()) })
def exec_main_proc(self): sort_key = TimeUtil.generate_sort_key() article_id = self.__generate_article_id(sort_key) params = json.loads(self.event.get('body')) try: self.__create_article_info(params, sort_key, article_id) try: self.__create_article_content(params, article_id) except Exception as err: logging.fatal(err) traceback.print_exc() finally: return { 'statusCode': 200, 'body': json.dumps({'article_id': article_id}) } except ClientError as e: if e.response['Error'][ 'Code'] == 'ConditionalCheckFailedException': return { 'statusCode': 400, 'body': json.dumps({'message': 'Already exists'}) } else: raise
def test_changetime(self): time_input = [1509522118051, 1509522060561, 1509518440216] time_result = [ "2017-11-01 15:41:58", "2017-11-01 15:41:00", "2017-11-01 14:40:40" ] for input, pre_result in zip(time_input, time_result): result = TimeUtil.change_to_time(input) self.assertAlmostEqual(pre_result, str(result))
def main(): print('-----------------------', datetime.datetime.now()) sw = { 'w': lambda: TimeUtil.get_time_weeks(FLAGS.time_interval), 'd': lambda: TimeUtil.get_time_days(FLAGS.time_interval), 'h': lambda: TimeUtil.get_time_hours(FLAGS.time_interval), 'm': lambda: TimeUtil.get_time_minutes(FLAGS.time_interval, TIME_END), 's': lambda: TimeUtil.get_time_seconds(FLAGS.time_interval), } if FLAGS.time_interval > 0: global TIME_BEGIN global TIME_END TIME_BEGIN, TIME_END = sw[FLAGS.time_format]() print(TIME_BEGIN, TIME_BEGIN - FLAGS.time_period * 1000) hadoop_util.get_cluster_information() hadoop_util.get_commonjobs_information()
def to_object(self, tz_offset): return { 'key': self.key.urlsafe(), 'goal': self.goal, 'start_date': TimeUtil.utc_datetime_to_str(tz_offset, self.start_date), 'fulfill_status': self.fulfill_status }
def handle_add_diary(self): diary = self.request.get('diary') tz_offset = self.request.get('tz_offset') date = self.request.get('date') if not self.email or not diary or not tz_offset or not date: return False date = TimeUtil.str_to_utc_datetime(int(tz_offset), date) diary = Diary.create(self.email, date, diary) return True, {'key': diary.key.urlsafe()}
def handle_update_diary(self): key = self.request.get('key') diary = self.request.get('diary') tz_offset = self.request.get('tz_offset') date = self.request.get('date') if not self.email or not key or not diary or not tz_offset or not date: return False date = TimeUtil.str_to_utc_datetime(int(tz_offset), date) return Diary.update(key, self.email, date, diary)
def handle_add_goal(self): goal = self.request.get('goal') timezone_offset = self.request.get('tz_offset') start_date = self.request.get('start_date') if not self.email or not goal or not timezone_offset or not start_date: return False start_date = TimeUtil.str_to_utc_datetime(int(timezone_offset), start_date) goal = TwoWeekGoal.create(self.email, goal, start_date) return True, {'key': goal.key.urlsafe()}
def handle_passcode_add_diary(self): """ Used to migrate from DailyNote2. """ diary = self.request.get('diary') tz_offset = self.request.get('tz_offset') date = self.request.get('date') email = self.request.get('email') if not email or diary is None or not tz_offset or not date: return False date = TimeUtil.str_to_utc_datetime(int(tz_offset), date) diary = Diary.create(email, date, diary) return True, {'key': diary.key.urlsafe()}
def handle_get_diaries(self): tz_offset = self.request.get('tz_offset') count_limit = self.request.get('count_limit') cursor = self.request.get('cursor') min_date = self.request.get('min_date') max_date = self.request.get('max_date') if not self.email or not tz_offset or not count_limit: return False count_limit = int(count_limit) tz_offset = int(tz_offset) if min_date: min_date = TimeUtil.str_to_utc_datetime(tz_offset, min_date) if max_date: max_date = TimeUtil.str_to_utc_datetime(tz_offset, max_date) diaries, next_cursor = Diary.query_instances(self.email, count_limit, cursor, min_date, max_date) data = [] for diary in diaries: data.append(diary.to_object(tz_offset)) result = {'data': data} if next_cursor: result['next_cursor'] = next_cursor return True, result
def __create_article_liked_user(self, article_liked_user_table): epoch = int(time.time()) article_liked_user = { 'article_id': self.event['pathParameters']['article_id'], 'user_id': self.event['requestContext']['authorizer']['claims']['cognito:username'], 'article_user_id': self.__get_article_user_id(self.event['pathParameters']['article_id']), 'created_at': epoch, 'target_date': time.strftime('%Y-%m-%d', time.gmtime(epoch)), 'sort_key': TimeUtil.generate_sort_key() } article_liked_user_table.put_item( Item=article_liked_user, ConditionExpression='attribute_not_exists(article_id)' )
def __create_article_history_and_update_sort_key(self): # update sort_key article_history_table = self.dynamodb.Table( os.environ['ARTICLE_HISTORY_TABLE_NAME']) article_histories = article_history_table.query( KeyConditionExpression=Key('article_id').eq( self.params['article_id']))['Items'] if len(article_histories) == 0: sort_key = TimeUtil.generate_sort_key() article_info_table = self.dynamodb.Table( os.environ['ARTICLE_INFO_TABLE_NAME']) article_info_table.update_item( Key={ 'article_id': self.params['article_id'], }, UpdateExpression= 'set sort_key = :sort_key, published_at = :published_at', ExpressionAttributeValues={ ':sort_key': sort_key, ':published_at': int(time.time()) }) # create article_history article_content_table = self.dynamodb.Table( os.environ['ARTICLE_CONTENT_TABLE_NAME']) article_content = article_content_table.get_item( Key={ 'article_id': self.params['article_id'] }).get('Item') Item = { 'article_id': article_content['article_id'], 'title': article_content['title'], 'body': article_content['body'], 'created_at': int(time.time()) } # 金額や有料記事本文が含まれている場合一緒に更新する if self.params.get('price') is not None and self.params.get( 'paid_body') is not None: Item.update({ 'price': self.params.get('price'), 'paid_body': self.params.get('paid_body') }) article_history_table.put_item(Item=Item)
def handle_update_goal(self): key = self.request.get('key') goal = self.request.get('goal') timezone_offset = self.request.get('tz_offset') start_date = self.request.get('start_date') fulfill_status = self.request.get('fulfill_status') if not key or not self.email: return False if start_date: if not timezone_offset: return False start_date = TimeUtil.str_to_utc_datetime(int(timezone_offset), start_date) if fulfill_status: fulfill_status = int(fulfill_status) return TwoWeekGoal.update(self.email, key, goal, start_date, fulfill_status)
def __create_comment_notification(self, article_info, comment_id, user_id): notification_table = self.dynamodb.Table( os.environ['NOTIFICATION_TABLE_NAME']) notification_id = '-'.join([ settings.COMMENT_NOTIFICATION_TYPE, article_info['user_id'], comment_id ]) notification_table.put_item( Item={ 'notification_id': notification_id, 'user_id': article_info['user_id'], 'article_id': article_info['article_id'], 'article_title': article_info['title'], 'acted_user_id': user_id, 'sort_key': TimeUtil.generate_sort_key(), 'type': settings.COMMENT_NOTIFICATION_TYPE, 'created_at': int(time.time()) })
def __notification(self, user_id, announce_url): notification_table = self.dynamodb.Table( os.environ['NOTIFICATION_TABLE_NAME']) notification_id = self.__get_randomhash() notification_table.put_item( Item={ 'notification_id': notification_id, 'user_id': user_id, 'sort_key': TimeUtil.generate_sort_key(), 'type': settings.CSVDOWNLOAD_NOTIFICATION_TYPE, 'created_at': int(time.time()), 'announce_body': '全トークン履歴のcsvのダウンロード準備が完了しました。本通知をクリックしてダウンロードしてください。', 'announce_url': announce_url }) self.__update_unread_notification_manager(user_id)
def exec_main_proc(self): sort_key = TimeUtil.generate_sort_key() user_id = self.event['requestContext']['authorizer']['claims'][ 'cognito:username'] comment_id = self.__generate_comment_id(sort_key) comment_table = self.dynamodb.Table(os.environ['COMMENT_TABLE_NAME']) comment = { 'comment_id': comment_id, 'article_id': self.params['article_id'], 'text': TextSanitizer.sanitize_text(self.params['text']), 'user_id': user_id, 'sort_key': sort_key, 'created_at': int(time.time()) } comment_table.put_item( Item=comment, ConditionExpression='attribute_not_exists(comment_id)') # 優先度が低いため通知処理は失敗しても握り潰して200を返す(ログは出して検知できるようにする) try: article_info_table = self.dynamodb.Table( os.environ['ARTICLE_INFO_TABLE_NAME']) article_info = article_info_table.get_item( Key={'article_id': self.params['article_id']})['Item'] if self.__is_notifiable_comment(article_info, user_id): self.__create_comment_notification(article_info, comment_id, user_id) self.__update_unread_notification_manager(article_info) except Exception as err: logging.fatal(err) traceback.print_exc() finally: return { 'statusCode': 200, 'body': json.dumps({'comment_id': comment_id}) }
def notify_article_comment(dynamodb, article_info, comment, target_user_id, comment_type): if comment_type not in settings.COMMENT_NOTIFICATION_TYPES: raise ValueError('Invalid comment type ' + comment_type) notification_table = dynamodb.Table( os.environ['NOTIFICATION_TABLE_NAME']) notification_id = '-'.join( [comment_type, target_user_id, comment['comment_id']]) notification_table.put_item( Item={ 'notification_id': notification_id, 'user_id': target_user_id, 'article_id': article_info['article_id'], 'article_user_id': article_info['user_id'], 'article_title': article_info['title'], 'acted_user_id': comment['user_id'], 'sort_key': TimeUtil.generate_sort_key(), 'type': comment_type, 'created_at': int(time.time()) })
def exec_main_proc(self): ################ # get parameter ################ # get article info article_info_table = self.dynamodb.Table( os.environ['ARTICLE_INFO_TABLE_NAME']) article_info = article_info_table.get_item( Key={ 'article_id': self.params['article_id'] }).get('Item') # purchase article paid_articles_table = self.dynamodb.Table( os.environ['PAID_ARTICLES_TABLE_NAME']) paid_status_table = self.dynamodb.Table( os.environ['PAID_STATUS_TABLE_NAME']) # eth_address article_user_eth_address = UserUtil.get_private_eth_address( self.cognito, article_info['user_id']) user_eth_address = self.event['requestContext']['authorizer'][ 'claims']['custom:private_eth_address'] # transaction_count transaction_count = PrivateChainUtil.get_transaction_count( user_eth_address) ################ # validation ################ # does not purchase same user's article user_id = self.event['requestContext']['authorizer']['claims'][ 'cognito:username'] if article_info['user_id'] == user_id: raise ValidationError('Can not purchase own article') # validate raw_transaction # purchase purchase_data = PrivateChainUtil.get_data_from_raw_transaction( self.params['purchase_signed_transaction'], transaction_count) PrivateChainUtil.validate_erc20_transfer_data( purchase_data, article_user_eth_address) # burn transaction_count = PrivateChainUtil.increment_transaction_count( transaction_count) burn_data = PrivateChainUtil.get_data_from_raw_transaction( self.params['burn_signed_transaction'], transaction_count) PrivateChainUtil.validate_erc20_transfer_data( burn_data, '0x' + os.environ['BURN_ADDRESS']) # burn 量が正しいこと purchase_value = int(purchase_data[72:], 16) burn_value = int(burn_data[72:], 16) calc_burn_value = int(Decimal(purchase_value) / Decimal(9)) if burn_value != calc_burn_value: raise ValidationError('burn_value is invalid.') # purchase_value が記事で指定されている金額に基づいた量が設定されていること DBUtil.validate_latest_price(self.dynamodb, self.params['article_id'], purchase_value) ################ # purchase ################ sort_key = TimeUtil.generate_sort_key() # 多重リクエストによる不必要なレコード生成を防ぐためにpaid_statusレコードを生成 self.__create_paid_status(paid_status_table, user_id) # 購入のトランザクション処理 purchase_transaction = PrivateChainUtil.send_raw_transaction( self.params['purchase_signed_transaction']) # 購入記事データを作成 self.__create_paid_article(paid_articles_table, article_info, purchase_transaction, sort_key) # プライベートチェーンへのポーリングを行いトランザクションの承認状態を取得 transaction_status = self.__polling_to_private_chain( purchase_transaction) # トランザクションの承認状態をpaid_articleとpaid_statusに格納 self.__update_transaction_status(article_info, paid_articles_table, transaction_status, sort_key, paid_status_table, user_id) # 購入のトランザクションが成功した時のみバーンのトランザクションを発行する if transaction_status == 'done': try: # 購入に成功した場合、著者の未読通知フラグをTrueにする self.__update_unread_notification_manager( article_info['user_id']) # 著者へ通知を作成 self.__notify_author(article_info, user_id) # バーンのトランザクション処理 burn_transaction = PrivateChainUtil.send_raw_transaction( self.params['burn_signed_transaction']) # バーンのトランザクションを購入テーブルに格納 self.__add_burn_transaction_to_paid_article( burn_transaction, paid_articles_table, article_info, sort_key) except Exception as err: logging.fatal(err) traceback.print_exc() # 記事購入者へは購入処理中の場合以外で通知を作成 if transaction_status == 'done' or transaction_status == 'fail': self.__update_unread_notification_manager(user_id) self.__notify_purchaser(article_info, user_id, transaction_status) return { 'statusCode': 200, 'body': json.dumps({'status': transaction_status}) }
def exec_main_proc(self): # get article info article_info_table = self.dynamodb.Table( os.environ['ARTICLE_INFO_TABLE_NAME']) article_info = article_info_table.get_item( Key={ 'article_id': self.params['article_id'] }).get('Item') # does not purchase same user's article user_id = self.event['requestContext']['authorizer']['claims'][ 'cognito:username'] if article_info['user_id'] == user_id: raise ValidationError('Can not purchase own article') # purchase article paid_articles_table = self.dynamodb.Table( os.environ['PAID_ARTICLES_TABLE_NAME']) paid_status_table = self.dynamodb.Table( os.environ['PAID_STATUS_TABLE_NAME']) article_user_eth_address = self.__get_user_private_eth_address( article_info['user_id']) user_eth_address = self.event['requestContext']['authorizer'][ 'claims']['custom:private_eth_address'] price = self.params['price'] auth = AWSRequestsAuth( aws_access_key=os.environ['PRIVATE_CHAIN_AWS_ACCESS_KEY'], aws_secret_access_key=os. environ['PRIVATE_CHAIN_AWS_SECRET_ACCESS_KEY'], aws_host=os.environ['PRIVATE_CHAIN_EXECUTE_API_HOST'], aws_region='ap-northeast-1', aws_service='execute-api') headers = {'content-type': 'application/json'} sort_key = TimeUtil.generate_sort_key() # 多重リクエストによる不必要なレコード生成を防ぐためにpaid_statusレコードを生成 self.__create_paid_status(paid_status_table, user_id) # 購入のトランザクション処理 purchase_transaction = self.__create_purchase_transaction( auth, headers, user_eth_address, article_user_eth_address, price) # 購入記事データを作成 self.__create_paid_article(paid_articles_table, article_info, purchase_transaction, sort_key) # プライベートチェーンへのポーリングを行いトランザクションの承認状態を取得 transaction_status = self.__polling_to_private_chain( purchase_transaction, auth, headers) # トランザクションの承認状態をpaid_artilcleとpaid_statusに格納 self.__update_transaction_status(article_info, paid_articles_table, transaction_status, sort_key, paid_status_table, user_id) # 購入のトランザクションが成功した時のみバーンのトランザクションを発行する if transaction_status == 'done': try: # 購入に成功した場合、著者の未読通知フラグをTrueにする self.__update_unread_notification_manager( article_info['user_id']) # 著者へ通知を作成 self.__notify_author(article_info, user_id) # バーンのトランザクション処理 burn_transaction = self.__burn_transaction( price, user_eth_address, auth, headers) # バーンのトランザクションを購入テーブルに格納 self.__add_burn_transaction_to_paid_article( burn_transaction, paid_articles_table, article_info, sort_key) except Exception as err: logging.fatal(err) traceback.print_exc() # 記事購入者へは購入処理中の場合以外で通知を作成 if transaction_status == 'done' or transaction_status == 'fail': self.__update_unread_notification_manager(user_id) self.__notify_purchaser(article_info, user_id, transaction_status) return { 'statusCode': 200, 'body': json.dumps({'status': transaction_status}) }
def test_generate_sort_key(self): sort_key = TimeUtil.generate_sort_key() self.assertEqual(len(str(sort_key)), 16) self.assertTrue(type(sort_key) is int)
def to_object(self, tz_offset): return { 'key': self.key.urlsafe(), 'date': TimeUtil.utc_datetime_to_str(tz_offset, self.date), 'diary': self.diary }
def exec_main_proc(self): from_user_eth_address = self.event['requestContext']['authorizer'][ 'claims']['custom:private_eth_address'] recipient_eth_address = self.params['recipient_eth_address'] send_value = self.params['send_value'] sort_key = TimeUtil.generate_sort_key() user_id = self.event['requestContext']['authorizer']['claims'][ 'cognito:username'] # 日次の限度額を超えていた場合は例外 sum_price = self.__get_token_send_value_today(user_id) if Decimal(os.environ['DAILY_LIMIT_TOKEN_SEND_VALUE'] ) < sum_price + Decimal(send_value): raise ValidationError('Token withdrawal limit has been exceeded.') # allowance を取得 allowance = self.__get_allowance(from_user_eth_address) # transaction_count を取得 transaction_count = self.__get_transaction_count(from_user_eth_address) # 既に approve されている場合(allowance の戻り値が "0x0" ではない場合)、該当の approve を削除する(0 で更新) if allowance != '0x0': self.__approve(from_user_eth_address, 0, transaction_count) transaction_count = self.__increment_transaction_count( transaction_count) # approve 実施 approve_transaction_hash = self.__approve(from_user_eth_address, send_value, transaction_count) transaction_count = self.__increment_transaction_count( transaction_count) self.__create_send_info_with_approve_transaction_hash( sort_key, user_id, approve_transaction_hash) # token_send_table への書き込み完了後に出金関連の例外が発生した場合は、token_send_table のステータスを fail に更新する try: # relay 実施 relay_transaction_hash = self.__relay(from_user_eth_address, recipient_eth_address, send_value, transaction_count) self.__update_send_info_with_relay_transaction_hash( sort_key, user_id, relay_transaction_hash) # transaction の完了を確認 is_completed = PrivateChainUtil.is_transaction_completed( relay_transaction_hash) except SendTransactionError as e: # ステータスを fail に更新し中断 self.__update_send_info_with_send_status(sort_key, user_id, 'fail') raise e except ReceiptError: # send_value の値が残高を超えた場合や、処理最小・最大値の範囲に収まっていない場合に ReceiptError が発生するため # ValidationError として処理を中断する # ステータスを fail に更新 self.__update_send_info_with_send_status(sort_key, user_id, 'fail') raise ValidationError('send_value') # transaction が完了していた場合、ステータスを done に更新 if is_completed: self.__update_send_info_with_send_status(sort_key, user_id, 'done') return { 'statusCode': 200, 'body': json.dumps({'is_completed': is_completed}) }
def exec_main_proc(self): ################ # get parameter ################ sort_key = TimeUtil.generate_sort_key() from_user_eth_address = self.event['requestContext']['authorizer'][ 'claims']['custom:private_eth_address'] user_id = self.event['requestContext']['authorizer']['claims'][ 'cognito:username'] allowance = PrivateChainUtil.get_allowance(from_user_eth_address) transaction_count = PrivateChainUtil.get_transaction_count( from_user_eth_address) ################ # validation ################ # validate raw_transaction # init_approve_signed_transaction if int(allowance, 16) != 0: # allowance が設定されている場合は必須 if self.params.get('init_approve_signed_transaction') is None: raise ValidationError( 'init_approve_signed_transaction is invalid.') # data init_approve_data = PrivateChainUtil.get_data_from_raw_transaction( self.params['init_approve_signed_transaction'], transaction_count) PrivateChainUtil.validate_erc20_approve_data(init_approve_data) if int(init_approve_data[72:], 16) != 0: raise ValidationError('Value of init_approve is invalid.') transaction_count = PrivateChainUtil.increment_transaction_count( transaction_count) # approve_signed_transaction approve_data = PrivateChainUtil.get_data_from_raw_transaction( self.params['approve_signed_transaction'], transaction_count) PrivateChainUtil.validate_erc20_approve_data(approve_data) # 日次の限度額を超えていた場合は例外 sum_price = self.__get_token_send_value_today(user_id) if Decimal(os.environ['DAILY_LIMIT_TOKEN_SEND_VALUE'] ) < sum_price + Decimal(int(approve_data[72:], 16)): raise ValidationError('Token withdrawal limit has been exceeded.') transaction_count = PrivateChainUtil.increment_transaction_count( transaction_count) # relay_signed_transaction relay_data = PrivateChainUtil.get_data_from_raw_transaction( self.params['relay_signed_transaction'], transaction_count) PrivateChainUtil.validate_erc20_relay_data(relay_data) # approve と relay の value が同一であること approve_value = int(approve_data[72:], 16) relay_value = int(relay_data[72:], 16) if approve_value != relay_value: raise ValidationError('approve and relay values do not match.') ####################### # send_raw_transaction ####################### # 既に approve されている場合(allowance の戻り値が 0 ではない場合)、該当の approve を削除する(0 で更新) if int(allowance, 16) != 0: PrivateChainUtil.send_raw_transaction( self.params.get('init_approve_signed_transaction')) # approve 実施 approve_transaction_hash = PrivateChainUtil.send_raw_transaction( self.params.get('approve_signed_transaction')) self.__create_send_info_with_approve_transaction_hash( sort_key, user_id, approve_transaction_hash, relay_value) # token_send_table への書き込み完了後に出金関連の例外が発生した場合は、token_send_table のステータスを fail に更新する try: # relay 実施 relay_transaction_hash = PrivateChainUtil.send_raw_transaction( self.params.get('relay_signed_transaction')) self.__update_send_info_with_relay_transaction_hash( sort_key, user_id, relay_transaction_hash) # transaction の完了を確認 is_completed = PrivateChainUtil.is_transaction_completed( relay_transaction_hash) except SendTransactionError as e: # ステータスを fail に更新し中断 self.__update_send_info_with_send_status(sort_key, user_id, 'fail') raise e except ReceiptError: # send_value の値が残高を超えた場合や、処理最小・最大値の範囲に収まっていない場合に ReceiptError が発生するため # ValidationError として処理を中断する # ステータスを fail に更新 self.__update_send_info_with_send_status(sort_key, user_id, 'fail') raise ValidationError('send_value') # transaction が完了していた場合、ステータスを done に更新 if is_completed: self.__update_send_info_with_send_status(sort_key, user_id, 'done') return { 'statusCode': 200, 'body': json.dumps({'is_completed': is_completed}) }