def refund():
	"""
	"	Refund real bet:
	"		This step make sure user's feed will update pending status
	"""
	try:
		uid = int(request.headers['Uid'])
		user = User.find_user_with_id(uid)

		data = request.json
		if data is None:
			return response_error(MESSAGE.INVALID_DATA, CODE.INVALID_DATA)

		offchain = data.get('offchain', '')
		if len(offchain) == 0:
			return response_error(MESSAGE.MISSING_OFFCHAIN, CODE.MISSING_OFFCHAIN)

		offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')
		outcome = None
		if 'm' in offchain:
			offchain = int(offchain.replace('m', ''))
			handshake = db.session.query(Handshake).filter(and_(Handshake.id==offchain, Handshake.user_id==user.id)).first()
			if handshake is None:
				return response_error(MESSAGE.HANDSHAKE_CANNOT_REFUND, CODE.HANDSHAKE_CANNOT_REFUND)

			outcome = Outcome.find_outcome_by_id(handshake.outcome_id)

		elif 's' in offchain:
			offchain = int(offchain.replace('s', ''))
			shaker = db.session.query(Shaker).filter(and_(Shaker.id==offchain, Shaker.shaker_id==user.id)).first()
			if shaker is None:
				return response_error(MESSAGE.HANDSHAKE_CANNOT_REFUND, CODE.HANDSHAKE_CANNOT_REFUND)

			handshake = Handshake.find_handshake_by_id(shaker.handshake_id)
			outcome = Outcome.find_outcome_by_id(handshake.outcome_id)


		if outcome is None:
			return response_error(MESSAGE.OUTCOME_INVALID, CODE.OUTCOME_INVALID)

		handshakes = db.session.query(Handshake).filter(and_(Handshake.status.in_([HandshakeStatus['STATUS_INITED'], HandshakeStatus['STATUS_RESOLVED']]), Handshake.user_id==user.id, Handshake.outcome_id==outcome.id)).all()
		shakers = db.session.query(Shaker).filter(and_(Shaker.status.in_([HandshakeStatus['STATUS_SHAKER_SHAKED'], HandshakeStatus['STATUS_RESOLVED']]), Shaker.shaker_id==user.id, Shaker.handshake_id.in_(db.session.query(Handshake.id).filter(Handshake.outcome_id==outcome.id)))).all()

		for h in handshakes:
			h.bk_status = h.status
			h.status = HandshakeStatus['STATUS_REFUND_PENDING']
			db.session.merge(h)

		for s in shakers:
			s.bk_status = s.status
			s.status = HandshakeStatus['STATUS_REFUND_PENDING']
			db.session.merge(s)
			
		db.session.commit()
		handshake_bl.update_handshakes_feed(handshakes, shakers)

		return response_ok()
	except Exception, ex:
		db.session.rollback()
		return response_error(ex.message)
def can_withdraw(handshake, shaker=None):
    outcome = None
    result = None

    if shaker is None:
        if handshake is not None:
            if handshake.status == HandshakeStatus[
                    'STATUS_INITED'] or handshake.status == HandshakeStatus[
                        'STATUS_RESOLVED']:
                outcome = Outcome.find_outcome_by_id(handshake.outcome_id)
                result = handshake.side
            else:
                return MESSAGE.CANNOT_WITHDRAW
        else:
            return MESSAGE.CANNOT_WITHDRAW
    else:
        if shaker.status == HandshakeStatus[
                'STATUS_SHAKER_SHAKED'] or shaker.status == HandshakeStatus[
                    'STATUS_RESOLVED']:
            handshake = Handshake.find_handshake_by_id(shaker.handshake_id)
            outcome = Outcome.find_outcome_by_id(handshake.outcome_id)
            result = shaker.side
        else:
            return MESSAGE.CANNOT_WITHDRAW

    if outcome is not None:
        if outcome.result != result:
            return MESSAGE.HANDSHAKE_NOT_THE_SAME_RESULT

        if match_bl.is_exceed_dispute_time(outcome.match_id) == False:
            return MESSAGE.HANDSHAKE_WITHDRAW_AFTER_DISPUTE
    else:
        return MESSAGE.OUTCOME_INVALID

    return ''
def save_refund_state_for_all(user_id, outcome_id):
    outcome = Outcome.find_outcome_by_id(outcome_id)
    handshakes = db.session.query(Handshake).filter(
        and_(
            Handshake.status.in_([
                HandshakeStatus['STATUS_REFUND_PENDING'],
                HandshakeStatus['STATUS_INITED']
            ]), Handshake.user_id == user_id,
            Handshake.outcome_id == outcome_id)).all()
    shakers = db.session.query(Shaker).filter(
        and_(
            Shaker.status == HandshakeStatus['STATUS_REFUND_PENDING'],
            Shaker.shaker_id == user_id,
            Shaker.handshake_id.in_(
                db.session.query(Handshake.id).filter(
                    Handshake.outcome_id == outcome_id)))).all()

    for hs in handshakes:
        hs.bk_status = hs.status
        hs.status = HandshakeStatus['STATUS_REFUNDED']
        db.session.merge(hs)

    for sk in shakers:
        sk.bk_status = sk.status
        sk.status = HandshakeStatus['STATUS_REFUNDED']
        db.session.merge(sk)

    return handshakes, shakers
    def test_generate_link(self):
        Uid = 66
        # create outcome
        outcome = Outcome.find_outcome_by_id(88)
        if outcome is None:
            outcome = Outcome(id=88,
                              match_id=1,
                              name="1",
                              hid=88,
                              created_user_id=Uid)
            db.session.add(outcome)
            db.session.commit()

        else:
            outcome.match_id = 1
            outcome.name = "1"
            outcome.created_user_id = Uid
            db.session.commit()

        with self.client:

            params = {"match_id": 1}
            response = self.client.post('/outcome/generate-link',
                                        data=json.dumps(params),
                                        content_type='application/json',
                                        headers={
                                            "Uid": "{}".format(Uid),
                                            "Fcm-Token": "{}".format(123),
                                            "Payload": "{}".format(123),
                                        })

            data = json.loads(response.data.decode())
            data_json = data['data']
            self.assertTrue(data['status'] == 1)
            self.assertTrue(data_json['slug'] == '?match=1&ref=66')
def update_amount_for_outcome(outcome_id, user_id, side, outcome_result):
    side_arr = ', '.join(
        [str(x) for x in ([side] if outcome_result != 3 else [1, 2])])

    outcome = Outcome.find_outcome_by_id(outcome_id)
    dispute_amount_query_m = "(SELECT SUM(amount) AS total FROM (SELECT amount FROM handshake WHERE handshake.outcome_id = {} AND handshake.side IN ({}) AND handshake.user_id = {} AND handshake.status IN ({},{},{})) AS tmp) AS total_dispute_amount_m".format(
        outcome.id, side_arr, user_id, HandshakeStatus['STATUS_USER_DISPUTED'],
        HandshakeStatus['STATUS_DISPUTED'],
        HandshakeStatus['STATUS_DISPUTE_PENDING'])
    dispute_amount_query_s = '(SELECT SUM(total_amount) AS total FROM (SELECT shaker.amount as total_amount FROM handshake JOIN shaker ON handshake.id = shaker.handshake_id WHERE handshake.outcome_id = {} AND shaker.side IN ({}) AND shaker.shaker_id = {} AND shaker.status IN ({},{},{})) AS tmp) AS total_dispute_amount_s'.format(
        outcome.id, side_arr, user_id, HandshakeStatus['STATUS_USER_DISPUTED'],
        HandshakeStatus['STATUS_DISPUTED'],
        HandshakeStatus['STATUS_DISPUTE_PENDING'])
    amount_query_m = '(SELECT SUM(amount) AS total FROM (SELECT amount FROM handshake WHERE handshake.outcome_id = {} AND handshake.side IN ({})) AS tmp) AS total_amount_m'.format(
        outcome.id, side_arr)
    amount_query_s = '(SELECT SUM(total_amount) AS total FROM (SELECT shaker.amount as total_amount FROM handshake JOIN shaker ON handshake.id = shaker.handshake_id WHERE handshake.outcome_id = {} AND shaker.side IN ({})) AS tmp) AS total_amount_s'.format(
        outcome.id, side_arr)

    total_amount = db.engine.execute('SELECT {}, {}, {}, {}'.format(
        dispute_amount_query_m, dispute_amount_query_s, amount_query_m,
        amount_query_s)).first()

    outcome.total_dispute_amount = (
        total_amount['total_dispute_amount_m']
        if total_amount['total_dispute_amount_m'] is not None else
        0) + (total_amount['total_dispute_amount_s']
              if total_amount['total_dispute_amount_s'] is not None else 0)
    outcome.total_amount = (total_amount['total_amount_m']
                            if total_amount['total_amount_m'] is not None else
                            0) + (total_amount['total_amount_s']
                                  if total_amount['total_amount_s'] is not None
                                  else 0)
    db.session.flush()
Example #6
0
def report_match(match_id):
    """
	"" report: report outcomes
	"" input:
	""		match_id
	"""
    try:
        uid = int(request.headers['Uid'])
        data = request.json
        response = []
        if data is None:
            return response_error(MESSAGE.INVALID_DATA, CODE.INVALID_DATA)

        match = Match.find_match_by_id(match_id)
        if match is not None:
            result = data['result']
            if result is None:
                return response_error(MESSAGE.MATCH_RESULT_EMPTY,
                                      CODE.MATCH_RESULT_EMPTY)

            if not match_bl.is_exceed_closing_time(match.id):
                return response_error(MESSAGE.MATCH_CANNOT_SET_RESULT,
                                      CODE.MATCH_CANNOT_SET_RESULT)

            for item in result:
                if 'side' not in item:
                    return response_error(MESSAGE.OUTCOME_INVALID_RESULT,
                                          CODE.OUTCOME_INVALID_RESULT)

                if 'outcome_id' not in item:
                    return response_error(MESSAGE.OUTCOME_INVALID,
                                          CODE.OUTCOME_INVALID)

                outcome = Outcome.find_outcome_by_id(item['outcome_id'])
                if outcome is not None and outcome.created_user_id == uid:
                    message, code = match_bl.is_able_to_set_result_for_outcome(
                        outcome)
                    if message is not None and code is not None:
                        return message, code

                    outcome.result = CONST.RESULT_TYPE['PROCESSING']
                    outcome_json = outcome.to_json()
                    response.append(outcome_json)

                else:
                    return response_error(MESSAGE.OUTCOME_INVALID,
                                          CODE.OUTCOME_INVALID)

            return response_ok(response)
        else:
            return response_error(MESSAGE.MATCH_NOT_FOUND,
                                  CODE.MATCH_NOT_FOUND)

    except Exception, ex:
        return response_error(ex.message)
	def test_has_valid_shaker(self):
		self.clear_data_before_test()
		arr_hs = []

		outcome = Outcome.find_outcome_by_id(88)
		outcome.result = 1

		# -----
		handshake = Handshake(
						hs_type=3,
						chain_id=4,
						user_id=88,
						outcome_id=88,
						odds=1.5,
						amount=1,
						currency='ETH',
						side=2,
						remaining_amount=0,
						from_address='0x123',
						status=0
					)
		db.session.add(handshake)
		db.session.commit()
		arr_hs.append(handshake)
		actual = handshake_bl.has_valid_shaker(handshake)
		expected = False
		self.assertEqual(actual, expected)

		shaker = Shaker(
					shaker_id=66,
					amount=0.2,
					currency='ETH',
					odds=6,
					side=1,
					handshake_id=handshake.id,
					from_address='0x123',
					chain_id=4,
					status=2
				)
		db.session.add(shaker)
		db.session.commit()
		arr_hs.append(shaker)

		actual = handshake_bl.has_valid_shaker(handshake)
		expected = True
		self.assertEqual(actual, expected)

		for item in arr_hs:
			db.session.delete(item)
			db.session.commit()
Example #8
0
    def setUp(self):

        # create contract
        contract = Contract.find_contract_by_id(1)
        if contract is None:
            contract = Contract(id=1,
                                contract_name="contract1",
                                contract_address="0x123",
                                json_name="name1")
            db.session.add(contract)
            db.session.commit()

        # create match
        match = Match.find_match_by_id(1)
        if match is None:
            match = Match(id=1)
            db.session.add(match)
            db.session.commit()

        # create user
        user = User.find_user_with_id(88)
        if user is None:
            user = User(id=88)
            db.session.add(user)
            db.session.commit()

        user = User.find_user_with_id(99)
        if user is None:
            user = User(id=99)
            db.session.add(user)
            db.session.commit()

        user = User.find_user_with_id(66)
        if user is None:
            user = User(id=66)
            db.session.add(user)
            db.session.commit()

        # create outcome
        outcome = Outcome.find_outcome_by_id(88)
        if outcome is None:
            outcome = Outcome(id=88,
                              match_id=1,
                              hid=88,
                              contract_id=contract.id)
            db.session.add(outcome)
            db.session.commit()
        else:
            outcome.contract_id = contract.id
Example #9
0
    def clear_data_before_test(self):
        outcome1 = Outcome.find_outcome_by_id(10)
        outcome2 = Outcome.find_outcome_by_id(11)
        outcome3 = Outcome.find_outcome_by_id(12)
        outcome4 = Outcome.find_outcome_by_id(13)

        if outcome1 is not None:
            db.session.delete(outcome1)
            db.session.flush()

        if outcome2 is not None:
            db.session.delete(outcome2)
            db.session.flush()

        if outcome3 is not None:
            db.session.delete(outcome3)
            db.session.flush()

        if outcome4 is not None:
            db.session.delete(outcome4)
            db.session.flush()

        Task.query.delete()
        db.session.commit()
def can_refund(handshake, shaker=None):
    if handshake is None and shaker is None:
        return False

    outcome = None
    if handshake is not None:
        if handshake.status == HandshakeStatus['STATUS_REFUNDED']:
            return False

        outcome = Outcome.find_outcome_by_id(handshake.outcome_id)

    else:
        if shaker.status == HandshakeStatus['STATUS_REFUNDED']:
            return False

        handshake = Handshake.find_handshake_by_id(shaker.handshake_id)
        outcome = Outcome.find_outcome_by_id(handshake.outcome_id)

    if outcome is not None and outcome.hid is not None:
        if outcome.result == CONST.RESULT_TYPE['DRAW'] or (
                match_bl.is_exceed_report_time(outcome.match_id)
                and outcome.result == -1):
            return True
    return False
	def test_data_need_set_result_for_outcome(self):
		self.clear_data_before_test()
		arr_hs = []
		
		outcome = Outcome.find_outcome_by_id(88)
		outcome.result = 1

		# -----
		handshake = Handshake(
						hs_type=3,
						chain_id=4,
						user_id=88,
						outcome_id=88,
						odds=1.5,
						amount=1,
						currency='ETH',
						side=2,
						remaining_amount=0,
						from_address='0x123',
						status=0
					)
		db.session.add(handshake)
		db.session.commit()
		arr_hs.append(handshake)
		
		shaker = Shaker(
					shaker_id=66,
					amount=0.2,
					currency='ETH',
					odds=6,
					side=1,
					handshake_id=handshake.id,
					from_address='0x123',
					chain_id=4,
					status=-1
				)
		db.session.add(shaker)
		db.session.commit()
		arr_hs.append(shaker)

		handshake_bl.data_need_set_result_for_outcome(outcome)

		hs = Handshake.find_handshake_by_id(handshake.id)
		self.assertEqual(hs.status, HandshakeStatus['STATUS_MAKER_SHOULD_UNINIT'])

		for item in arr_hs:
			db.session.delete(item)
			db.session.commit()
def handshakes():
	uid = int(request.headers['Uid'])
	try:
		data = request.json
		if data is None:
			return response_error(MESSAGE.INVALID_DATA, CODE.INVALID_DATA)

		outcome_id = data.get('outcome_id', -1)
		outcome = Outcome.find_outcome_by_id(outcome_id)
		if outcome is None:
			return response_error(MESSAGE.INVALID_BET, CODE.INVALID_BET)
		
		match = Match.find_match_by_id(outcome.match_id)
		supports = handshake_bl.find_available_support_handshakes(outcome_id)
		againsts = handshake_bl.find_available_against_handshakes(outcome_id)

		total = Decimal('0', 2)

		traded_volumns = db.session.query(func.sum(Handshake.amount*Handshake.odds).label('traded_volumn')).filter(and_(Handshake.outcome_id==outcome_id, Handshake.status==CONST.Handshake['STATUS_INITED'])).group_by(Handshake.odds).all()
		for traded in traded_volumns:
			total += traded[0]

		arr_supports = []
		for support in supports:
			data = {}
			data['odds'] = support.odds
			data['amount'] = support.amount
			arr_supports.append(data)

		arr_against = []
		for against in againsts:
			data = {}
			data['odds'] = against.odds
			data['amount'] = against.amount
			arr_against.append(data)

		response = {
			"support": arr_supports,
			"against": arr_against,
			"traded_volumn": total,
			"market_fee": match.market_fee
		}

		return response_ok(response)

	except Exception, ex:
		return response_error(ex.message)
	def test_save_collect_state_for_shaker(self):
		self.clear_data_before_test()
		# -----
		handshake = Handshake(
				hs_type=3,
				chain_id=4,
				user_id=88,
				outcome_id=88,
				odds=1.2,
				amount=1,
				currency='ETH',
				side=2,
				remaining_amount=0,
				from_address='0x123',
				status=0
		)
		db.session.add(handshake)
		db.session.commit()

		# -----
		shaker = Shaker(
					shaker_id=66,
					amount=0.2,
					currency='ETH',
					odds=6,
					side=1,
					handshake_id=handshake.id,
					from_address='0x123',
					chain_id=4,
					status=2
				)
		db.session.add(shaker)
		db.session.commit()

		outcome = Outcome.find_outcome_by_id(88)
		outcome.result = 1
		db.session.flush()

		handshake_bl.save_collect_state_for_shaker(shaker)
		db.session.commit()

		h = Handshake.find_handshake_by_id(handshake.id)
		s = Shaker.find_shaker_by_id(shaker.id)

		self.assertEqual(h.status, 6)
		self.assertEqual(s.status, 6)
Example #14
0
def init_default_odds():
	"""
	"	Admin create odds for market in ETH
	"""
	try:
		data = request.json
		if data is None:
			return response_error(MESSAGE.INVALID_DATA, CODE.INVALID_DATA)

		for item in data:
			outcome_id = item['outcome_id']
			outcome_data = item['outcomes']
			outcome = Outcome.find_outcome_by_id(outcome_id)
			if outcome is None:
				return response_error(MESSAGE.OUTCOME_INVALID, CODE.OUTCOME_INVALID)

			if outcome.result != CONST.RESULT_TYPE['PENDING']:
				return response_error(MESSAGE.OUTCOME_HAS_RESULT, CODE.OUTCOME_HAS_RESULT)

			match = Match.find_match_by_id(outcome.match_id)
			for o in outcome_data:
				o['outcome_id'] = outcome_id
				o['hid'] = outcome.hid
				o['match_date'] = match.date
				o['match_name'] = match.name
				o['outcome_name'] = outcome.name

				contract = Contract.find_contract_by_id(outcome.contract_id)
				if contract is None:
					return response_error(MESSAGE.CONTRACT_INVALID, CODE.CONTRACT_INVALID)

				task = Task(
					task_type=CONST.TASK_TYPE['REAL_BET'],
					data=json.dumps(o),
					action=CONST.TASK_ACTION['INIT'],
					status=-1,
					contract_address=contract.contract_address,
					contract_json=contract.json_name
				)
				db.session.add(task)
				db.session.flush()
		
		return response_ok()
	except Exception, ex:
		db.session.rollback()
		return response_error(ex.message)
def save_collect_state_for_maker(handshake):
    if handshake is not None:
        outcome = Outcome.find_outcome_by_id(handshake.outcome_id)
        if outcome is not None:
            if handshake.side == outcome.result:
                shaker = Shaker.find_shaker_by_handshake_id(handshake.id)
                if shaker is not None:
                    shaker.bk_status = shaker.status
                    shaker.status = HandshakeStatus['STATUS_DONE']

                    db.session.merge(shaker)
                    db.session.flush()
                    handshakes, shakers = save_status_all_bet_which_user_win(
                        handshake.user_id, outcome)

                    if shakers is None:
                        shakers = []
                    shakers.append(shaker)
                    return handshakes, shakers
    return None, None
def save_collect_state_for_shaker(shaker):
    if shaker is not None:
        handshake = Handshake.find_handshake_by_id(shaker.handshake_id)
        outcome = Outcome.find_outcome_by_id(handshake.outcome_id)

        if outcome is not None:
            if shaker.side == outcome.result:
                handshake.bk_status = handshake.status
                handshake.status = HandshakeStatus['STATUS_DONE']

                db.session.merge(handshake)
                db.session.flush()
                handshakes, shakers = save_status_all_bet_which_user_win(
                    shaker.shaker_id, outcome)

                if handshakes is None:
                    handshakes = []
                handshakes.append(handshake)
                return handshakes, shakers

    return None, None
    def setUp(self):
        # create match
        match = Match.find_match_by_id(1)
        if match is None:
            match = Match(id=1)
            db.session.add(match)
            db.session.commit()

        # create outcome
        outcome = Outcome.find_outcome_by_id(88)
        if outcome is None:
            outcome = Outcome(id=88,
                              match_id=1,
                              name="1",
                              hid=88,
                              created_user_id=66)
            db.session.add(outcome)
            db.session.commit()

        else:
            outcome.name = "1"
            outcome.created_user_id = 66
            db.session.commit()
Example #18
0
    def init_data_before_test(self):
        # create token
        token = Token.find_token_by_id(1)
        if token is None:
            token = Token(id=1, name="SHURIKEN", symbol="SHURI", decimal=18)
            db.session.add(token)
            db.session.commit()

        # create contract
        contract = Contract.find_contract_by_id(1)
        if contract is None:
            contract = Contract(id=1,
                                contract_name="contract1",
                                contract_address="0x123",
                                json_name="name1")
            db.session.add(contract)
            db.session.commit()

        # create match
        match = Match.find_match_by_id(1)
        if match is None:
            match = Match(id=1)
            db.session.add(match)
            db.session.commit()

        # create user
        user = User.find_user_with_id(88)
        if user is None:
            user = User(id=88)
            db.session.add(user)
            db.session.commit()

        user = User.find_user_with_id(99)
        if user is None:
            user = User(id=99)
            db.session.add(user)
            db.session.commit()

        user = User.find_user_with_id(100)
        if user is None:
            user = User(id=100)
            db.session.add(user)
            db.session.commit()

        user = User.find_user_with_id(109)
        if user is None:
            user = User(id=109)
            db.session.add(user)
            db.session.commit()

        user = User.find_user_with_id(66)
        if user is None:
            user = User(id=66)
            db.session.add(user)
            db.session.commit()

        # create outcome
        outcome = Outcome.find_outcome_by_id(88)
        if outcome is None:
            outcome = Outcome(id=88,
                              match_id=1,
                              hid=88,
                              contract_id=contract.id)
            db.session.add(outcome)
            db.session.commit()
        else:
            outcome.result = -1
            outcome.contract_id = contract.id
            db.session.commit()

        # add redeem
        try:
            for i in range(1, 3):
                chars = string.ascii_uppercase + string.ascii_lowercase
                code = ''.join(random.choice(chars) for _ in range(i))
                if Redeem.find_redeem_by_code(code) is None:
                    r = Redeem(code=code)
                    db.session.add(r)
                    db.session.commit()
        except Exception as ex:
            db.session.rollback()
	def test_can_refund_for_maker(self):
		self.clear_data_before_test()

		t = datetime.now().timetuple()
		seconds = local_to_utc(t)

		match = Match.find_match_by_id(1)
		match.disputeTime = seconds + 1100
		match.reportTime = seconds + 1000
		db.session.merge(match)
		db.session.commit()

		arr_hs = []

		# -----
		handshake = Handshake(
						hs_type=3,
						chain_id=4,
						user_id=88,
						outcome_id=88,
						odds=1.5,
						amount=1,
						currency='ETH',
						side=2,
						remaining_amount=0,
						from_address='0x123',
						status=0
					)
		db.session.add(handshake)
		db.session.commit()
		arr_hs.append(handshake)

		actual = handshake_bl.can_refund(handshake)
		expected = False
		self.assertEqual(actual, expected)

		# test cannot refund
		outcome = Outcome.find_outcome_by_id(88)
		outcome.result = 1
		db.session.merge(outcome)
		db.session.flush()

		actual = handshake_bl.can_refund(handshake)
		expected = False
		self.assertEqual(actual, expected)

		# test refund if time exceed report time
		outcome.result = -1
		db.session.merge(outcome)
		db.session.flush()

		match.reportTime = seconds - 2000
		db.session.merge(match)
		db.session.commit()

		actual = handshake_bl.can_refund(handshake)
		expected = True
		self.assertEqual(actual, expected)

		for item in arr_hs:
			db.session.delete(item)
			db.session.commit()
def collect_free_bet():
	"""
	"	Collect free-bet in ETH
	"""
	try:
		uid = int(request.headers['Uid'])
		chain_id = int(request.headers.get('ChainId', CONST.BLOCKCHAIN_NETWORK['RINKEBY']))
		user = User.find_user_with_id(uid)

		data = request.json
		if data is None:
			return response_error(MESSAGE.INVALID_DATA, CODE.INVALID_DATA)

		offchain = data.get('offchain', '')
		if len(offchain) == 0:
			return response_error(MESSAGE.MISSING_OFFCHAIN, CODE.MISSING_OFFCHAIN)

		h = []
		s = []
		offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')
		if 's' in offchain:
			offchain = int(offchain.replace('s', ''))
			shaker = db.session.query(Shaker).filter(and_(Shaker.id==offchain, Shaker.shaker_id==user.id)).first()
			msg = handshake_bl.can_withdraw(handshake=None, shaker=shaker)
			if len(msg) != 0:
				return response_error(msg, CODE.CANNOT_WITHDRAW)
			
			hs = Handshake.find_handshake_by_id(shaker.handshake_id)
			outcome = Outcome.find_outcome_by_id(hs.outcome_id)

			# check erc20 token or not
			token = Token.find_token_by_id(outcome.token_id)
			if token is not None:
				return response_error(MESSAGE.HANDSHAKE_CANNOT_WITHDRAW_FREEBET_IN_ERC20, CODE.HANDSHAKE_CANNOT_WITHDRAW_FREEBET_IN_ERC20)

			h = db.session.query(Handshake).filter(and_(Handshake.user_id==user.id, Handshake.outcome_id==hs.outcome_id, Handshake.side==shaker.side, Handshake.status==HandshakeStatus['STATUS_INITED'])).all()
			s = db.session.query(Shaker).filter(and_(Shaker.shaker_id==user.id, Shaker.side==shaker.side, Shaker.status==HandshakeStatus['STATUS_SHAKER_SHAKED'], Shaker.handshake_id.in_(db.session.query(Handshake.id).filter(Handshake.outcome_id==hs.outcome_id)))).all()

			data['hid'] = outcome.hid
			data['winner'] = shaker.from_address

		else:
			offchain = int(offchain.replace('m', ''))
			handshake = db.session.query(Handshake).filter(and_(Handshake.id==offchain, Handshake.user_id==user.id)).first()
			msg = handshake_bl.can_withdraw(handshake)
			if len(msg) != 0:
				return response_error(msg, CODE.CANNOT_WITHDRAW)

			outcome = Outcome.find_outcome_by_id(handshake.outcome_id)

			# check erc20 token or not
			token = Token.find_token_by_id(outcome.token_id)
			if token is not None:
				return response_error(MESSAGE.HANDSHAKE_CANNOT_WITHDRAW_FREEBET_IN_ERC20, CODE.HANDSHAKE_CANNOT_WITHDRAW_FREEBET_IN_ERC20)

			h = db.session.query(Handshake).filter(and_(Handshake.user_id==user.id, Handshake.outcome_id==handshake.outcome_id, Handshake.side==handshake.side, Handshake.status==HandshakeStatus['STATUS_INITED'])).all()
			s = db.session.query(Shaker).filter(and_(Shaker.shaker_id==user.id, Shaker.side==handshake.side, Shaker.status==HandshakeStatus['STATUS_SHAKER_SHAKED'], Shaker.handshake_id.in_(db.session.query(Handshake.id).filter(Handshake.outcome_id==handshake.outcome_id)))).all()

			data['hid'] = outcome.hid
			data['winner'] = handshake.from_address


		handshakes = []
		shakers = []
		response = {}
		# update status
		for hs in h:
			hs.status = HandshakeStatus['STATUS_COLLECT_PENDING']
			db.session.flush()
			handshakes.append(hs)

			if hs.id == offchain:
				response = hs.to_json()
			
		for sk in s:
			sk.status = HandshakeStatus['STATUS_COLLECT_PENDING']
			db.session.flush()
			shakers.append(sk)

			if sk.id == offchain:
				response = sk.to_json()

		data['uid'] = uid
		data['payload'] = user.payload
		data['free_bet'] = 1

		contract = Contract.find_contract_by_id(outcome.contract_id)
		if contract is None:
			return response_error(MESSAGE.CONTRACT_INVALID, CODE.CONTRACT_INVALID)

		# add task
		task = Task(
			task_type=CONST.TASK_TYPE['FREE_BET'],
			data=json.dumps(data),
			action=CONST.TASK_ACTION['COLLECT'],
			status=-1,
			contract_address=contract.contract_address,
			contract_json=contract.json_name
		)
		db.session.add(task)
		db.session.commit()

		handshake_bl.update_handshakes_feed(handshakes, shakers)
		return response_ok(response)

	except Exception, ex:
		db.session.rollback()
		return response_error(ex.message)
    def test_user_reputation(self):
        t = datetime.now().timetuple()
        seconds = local_to_utc(t)
        db.session.query(Handshake).filter(Handshake.outcome_id.in_([1000, 1001, 1002])).delete(synchronize_session="fetch")

        db.session.query(Shaker).filter(Shaker.handshake_id.in_(\
            db.session.query(Handshake.id).filter(Handshake.outcome_id.in_([1000, 1001, 1002]))\
        )).delete(synchronize_session="fetch")

        arr_hs = []

        match = Match.find_match_by_id(1)
        if match is not None:
            match.date=seconds - 100,
            match.reportTime=seconds + 100,
            match.disputeTime=seconds + 200,
            db.session.flush()
        else:
            match = Match(
                id=1,
                date=seconds - 100,
                reportTime=seconds + 100,
                disputeTime=seconds + 200,
            )
            db.session.add(match)

        outcome1 = Outcome.find_outcome_by_id(1000)
        if outcome1 is not None:
            db.session.delete(outcome1)
            db.session.commit()

        outcome1 = Outcome(
            id=1000,
            match_id=match.id,
            result=1,
            name="1"
        )
        db.session.add(outcome1)
        db.session.commit()
        
        outcome2 = Outcome.find_outcome_by_id(1001)
        if outcome2 is not None:
            db.session.delete(outcome2)
            db.session.commit()

        outcome2 = Outcome(
            id=1001,
            match_id=match.id,
            result=1,
            name="1"
        )
        db.session.add(outcome2)
        db.session.commit()
        
        outcome3 = Outcome.find_outcome_by_id(1002)
        if outcome3 is not None:
            db.session.delete(outcome3)
            db.session.commit()

        outcome3 = Outcome(
            id=1002,
            match_id=match.id,
            result=1,
            name="1"
        )
        db.session.add(outcome3)
        db.session.commit()
        
        user1 = User.find_user_with_id(88)
        if user1 is None:
            user1 = User(
                id=88
            )
            db.session.add(user1)
            db.session.commit()
        
        user2 = User.find_user_with_id(89)
        if user2 is None:
            user2 = User(
                id=89
            )
            db.session.add(user2)
            db.session.commit()
        
        user3 = User.find_user_with_id(100)
        if user3 is None:
            user3 = User(
                id=100
            )
            db.session.add(user3)
        db.session.commit()
        
        handshake1 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user1.id,
                outcome_id=outcome1.id,
                odds=1.5,
                amount=1,
                currency='ETH',
                side=outcome1.result,
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE']
            )
        db.session.add(handshake1)
        arr_hs.append(handshake1)
        
        handshake2 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user1.id,
                outcome_id=outcome2.id,
                odds=1.5,
                amount=1,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome2.result
            )
        db.session.add(handshake2)
        arr_hs.append(handshake2)
        
        handshake3 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user1.id,
                outcome_id=outcome2.id,
                odds=1.5,
                amount=1,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome2.result
            )
        db.session.add(handshake3)
        arr_hs.append(handshake3)
        
        handshake4 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user2.id,
                outcome_id=outcome1.id,
                odds=1.5,
                amount=1,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome1.result
            )
        db.session.add(handshake4)
        arr_hs.append(handshake4)
        
        handshake5 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user2.id,
                outcome_id=outcome1.id,
                odds=1.5,
                amount=1,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome1.result
            )
        db.session.add(handshake5)
        arr_hs.append(handshake5)
        
        handshake6 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user3.id,
                outcome_id=outcome3.id,
                odds=1.5,
                amount=1,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome3.result + 1
            )
        db.session.add(handshake6)
        arr_hs.append(handshake6)
        
        handshake7 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user3.id,
                outcome_id=outcome3.id,
                odds=1.5,
                amount=1,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome3.result + 1
            )
        db.session.add(handshake7)
        arr_hs.append(handshake7)
        
        shaker1 = Shaker(
            shaker_id=user2.id,
            amount=0.2,
            currency='ETH',
            odds=6,
            side=outcome1.result,
            handshake_id=handshake1.id,
            from_address='0x123',
            chain_id=4,
            status=HandshakeStatus['STATUS_DONE']
        )
        db.session.add(shaker1)
        arr_hs.append(shaker1)
        db.session.commit()
        
        shaker2 = Shaker(
            shaker_id=user3.id,
            amount=0.2,
            currency='ETH',
            odds=6,
            side=outcome1.result,
            handshake_id=handshake1.id,
            from_address='0x123',
            chain_id=4,
            status=HandshakeStatus['STATUS_DONE']
        )
        db.session.add(shaker2)
        arr_hs.append(shaker2)
        db.session.commit()
        
        # hs_bets = db.session.query(Handshake.user_id.label("user_id"), bindparam("is_hs", 1), Handshake.free_bet, Handshake.status, Handshake.side, Handshake.from_address, Outcome.id, Outcome.name)\
        #     .filter(Handshake.outcome_id == Outcome.id)\
        #     .filter(Outcome.match_id == 1)\
        #     .filter(Handshake.user_id == user1.id)
        # s_bets = db.session.query(Shaker.shaker_id.label("user_id"), bindparam("is_hs", 0), Shaker.free_bet, Handshake.status, Shaker.side, Shaker.from_address, Outcome.id, Outcome.name)\
        #     .filter(Shaker.handshake_id == Handshake.id)\
        #     .filter(Handshake.outcome_id == Outcome.id)\
        #     .filter(Outcome.match_id == 1)\
        #     .filter(Shaker.shaker_id == user1.id)
        # bets = hs_bets.union_all(s_bets).order_by(Outcome.id.desc()).all()
        # print bets
        # Get all user betted this outcome
        
        hs_user = db.session.query(Handshake.user_id.label("user_id"))\
            .filter(Handshake.outcome_id == outcome1.id)
        s_user = db.session.query(Shaker.shaker_id.label("user_id"))\
            .filter(Shaker.handshake_id == Handshake.id)\
            .filter(Handshake.outcome_id == outcome1.id)
        total_users = hs_user.union_all(s_user).group_by('user_id')
        # users = db.session.query(User).filter(User.id.in_(hs_user.union_all(s_user).group_by('user_id'))).all()
        hs_all_bets = db.session.query(Handshake.user_id.label("user_id"), bindparam("is_hs", 1), Handshake.free_bet, Handshake.status.label("status"), Handshake.side.label('side'), Handshake.from_address, Outcome.result.label('outcome_result'))\
            .filter(Outcome.id == Handshake.outcome_id)
        s_all_bets = db.session.query(Shaker.shaker_id.label("user_id"), bindparam("is_hs", 0), Shaker.free_bet, Shaker.status.label("status"), Shaker.side.label('side'), Shaker.from_address, Outcome.result.label('outcome_result'))\
            .filter(Shaker.handshake_id == Handshake.id)\
            .filter(Outcome.id == Handshake.outcome_id)
        bets_query = hs_all_bets.union_all(s_all_bets).subquery()
        bets = db.session.query(
            bets_query.c.user_id.label('user_id'),
            func.count(bets_query.c.user_id).label('total_bets'),
            bindparam("total_bets_win", 0)
        )\
        .filter(bets_query.c.user_id.in_(total_users))\
        .filter(bets_query.c.status.in_([HandshakeStatus['STATUS_DONE'], HandshakeStatus['INDUSTRIES_NONE']]))\
        .group_by(bets_query.c.user_id)
        
        bets_win = db.session.query(
            bets_query.c.user_id.label('user_id'),
            bindparam("total_bets", 0),
            func.count(bets_query.c.user_id).label('total_bets_win'),
        )\
        .filter(bets_query.c.user_id.in_(total_users))\
        .filter(bets_query.c.status.in_([HandshakeStatus['STATUS_DONE'], HandshakeStatus['INDUSTRIES_NONE']]))\
        .filter(bets_query.c.side == bets_query.c.outcome_result)\
        .group_by(bets_query.c.user_id)
        
        result_query = bets.union_all(bets_win).subquery()
        adset_list = db.session.query(
            result_query.c.user_id,
            func.sum(result_query.c.total_bets_win).label('total_bets_win'),
            func.sum(result_query.c.total_bets).label('total_bets')
        ).group_by(result_query.c.user_id)
        
        results = adset_list.all()
        for item in results:
            if item.user_id ==  user1.id:
                self.assertTrue(item.total_bets_win == 3)
        for item in arr_hs:
            db.session.delete(item)
            db.session.commit()
        #########################################################################
        #                                                                       #
        #########################################################################
        user_id = 789
        user = User.find_user_with_id(789)
        arr_hs = []
        arr_hs.append(match)
        if user is not None:
            outcomes = db.session.query(Outcome)\
            .filter(Outcome.created_user_id == user_id)\
            .all()

            for oc in outcomes:
                # arr_delete.extend(oc)
                hs = db.session.query(Handshake)\
                .filter(Outcome.id == oc.id)\
                .all()

                for h in hs:
                    sh = db.session.query(Shaker)\
                        .filter(Shaker.handshake_id == Handshake.id)\
                        .filter(Handshake.outcome_id == oc.id)\
                        .all()

                    for s in sh:
                        db.session.delete(s)
                    db.session.delete(h)
                db.session.delete(oc)
            db.session.commit()
        else:
            user = User(
                id=user_id,
                fcm_token="",
                payload=""
            )
            db.session.add(user)
            db.session.commit()
        
        outcome1 = Outcome(
            created_user_id=user_id,
            match_id=match.id,
            result=1,
            hid=789
        )
        db.session.add(outcome1)
        arr_hs.append(outcome1)

        outcome2 = Outcome(
            created_user_id=user_id,
            match_id=match.id,
            result=1,
            hid=790
        )
        db.session.add(outcome2)
        arr_hs.append(outcome2)

        outcome_dispute = Outcome(
            created_user_id=user_id,
            match_id=1,
            result=-3,
            hid=793
        )
        db.session.add(outcome_dispute)
        db.session.commit()
        arr_hs.append(outcome_dispute)

        total_amount = 0
        total_dispute_amount = 0
        total_bet = 0
        total_dispute_bet = 0
        total_dispute_event = 1

        hs1 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user_id,
                outcome_id=outcome1.id,
                odds=1.5,
                amount=0.000227075,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome3.result + 1
            )
        db.session.add(hs1)
        db.session.commit()
        arr_hs.append(hs1)

        total_amount += 0.000227075
        total_bet += 1

        shaker2 = Shaker(
            shaker_id=user_id,
            amount=0.0001234455,
            currency='ETH',
            odds=6,
            side=outcome1.result,
            handshake_id=hs1.id,
            from_address='0x123',
            chain_id=4,
            status=HandshakeStatus['STATUS_DONE']
        )
        db.session.add(shaker2)
        db.session.commit()
        arr_hs.append(shaker2)

        total_amount += 0.0001234455
        total_bet += 1

        hs2 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user_id,
                outcome_id=outcome2.id,
                odds=1.5,
                amount=0.00032612678,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DONE'],
                side=outcome3.result + 1
            )
        db.session.add(hs2)
        db.session.commit()
        arr_hs.append(hs2)
        total_amount += 0.00032612678
        total_bet += 1

        hs_dispute = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user_id,
                outcome_id=outcome_dispute.id,
                odds=1.5,
                amount=0.0006427075,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DISPUTED'],
                side=1
            )
        db.session.add(hs_dispute)
        db.session.commit()
        arr_hs.append(hs_dispute)
        total_amount += 0.0006427075

        total_bet += 1
        total_dispute_amount += 0.0006427075
        total_dispute_bet += 1

        hs_dispute2 = Handshake(
                hs_type=3,
                chain_id=4,
                user_id=user_id,
                outcome_id=outcome1.id,
                odds=1.5,
                amount=0.0003227075,
                currency='ETH',
                remaining_amount=0,
                from_address='0x123',
                status=HandshakeStatus['STATUS_DISPUTE_PENDING'],
                side=1
            )
        db.session.add(hs_dispute2)
        db.session.commit()
        arr_hs.append(hs_dispute2)
        total_amount += 0.0003227075

        total_bet += 1
        total_dispute_amount += 0.0003227075
        total_dispute_bet += 1

        s_dispute2 = Shaker(
            shaker_id=user_id,
            amount=0.00012344379,
            currency='ETH',
            odds=6,
            side=outcome1.result,
            handshake_id=hs_dispute2.id,
            from_address='0x123',
            chain_id=4,
            status=HandshakeStatus['STATUS_USER_DISPUTED']
        )
        db.session.add(s_dispute2)
        db.session.commit()
        arr_hs.append(s_dispute2)

        total_amount += 0.00012344379
        total_bet += 1
        total_dispute_amount += 0.00012344379
        total_dispute_bet += 1

        with self.client:
            response = self.client.get(
                                    '/reputation/{}'.format(user_id),
                                    content_type='application/json',
                                    headers={
                                        "Uid": "{}".format(66),
                                        "Fcm-Token": "{}".format(123),
                                        "Payload": "{}".format(123),
                                    })

            data = json.loads(response.data.decode()) 
            self.assertTrue(data['status'] == 1)
            self.assertEqual(response.status_code, 200)

            self.assertTrue(data['data']['total_events'] == 3)
            self.assertTrue(data['data']['total_amount'] == total_amount)
            # self.assertTrue(data['data']['total_bets'] == total_bet)
            # self.assertTrue(data['data']['total_disputed_amount'] == total_dispute_amount)
            self.assertTrue(data['data']['total_disputed_bets'] == total_dispute_bet)
            # self.assertTrue(data['data']['total_disputed_events'] == 1)            

            for item in arr_hs:
                db.session.delete(item)
                db.session.commit()
def create_free_bet():
	"""
	"	Create a free-bet in ETH
	"""
	try:
		setting = Setting.find_setting_by_name(CONST.SETTING_TYPE['FREE_BET'])
		if setting is not None and setting.status == 0:
			return response_error(MESSAGE.FREE_BET_UNABLE, CODE.FREE_BET_UNABLE)

		uid = int(request.headers['Uid'])
		chain_id = int(request.headers.get('ChainId', CONST.BLOCKCHAIN_NETWORK['RINKEBY']))
		user = User.find_user_with_id(uid)

		data = request.json
		if data is None:
			return response_error(MESSAGE.INVALID_DATA, CODE.INVALID_DATA)

		redeem = data.get('redeem', '')
		match_id = data.get('match_id', -1)
		odds = Decimal(data.get('odds', Decimal('2')))
		amount = Decimal(CONST.CRYPTOSIGN_FREE_BET_AMOUNT)
		side = int(data.get('side', CONST.SIDE_TYPE['SUPPORT']))
		from_address = data.get('from_address', '')

		# check valid address
		if len(from_address) < 40:
			return response_error(MESSAGE.INVALID_ADDRESS, CODE.INVALID_ADDRESS)

		# check valid redeem or not
		r = Redeem.find_redeem_by_code_and_user(redeem, uid)
		if r is None:
			return response_error(MESSAGE.REDEEM_NOT_FOUND, CODE.REDEEM_NOT_FOUND)
		else:
			if r.used_user > 0:
				return response_error(MESSAGE.REDEEM_INVALID, CODE.REDEEM_INVALID)
			r.used_user = uid
			db.session.flush()

		outcome_id = data.get('outcome_id')
		outcome = None
		if match_id == -1:
			outcome = Outcome.find_outcome_by_id(outcome_id)
			if outcome is None:
				return response_error(MESSAGE.OUTCOME_INVALID, CODE.OUTCOME_INVALID)
			elif outcome.result != -1:
				return response_error(MESSAGE.OUTCOME_HAS_RESULT, CODE.OUTCOME_HAS_RESULT)

		else:
			match = Match.find_match_by_id(match_id)
			if match is not None and len(match.outcomes.all()) > 0:
				outcome = match.outcomes[0]
			else:
				return response_error(MESSAGE.MATCH_NOT_FOUND, CODE.MATCH_NOT_FOUND)

		# check erc20 token or not
		token = Token.find_token_by_id(outcome.token_id)
		if token is not None:
			return response_error(MESSAGE.HANDSHAKE_CANNOT_CREATE_FREEBET_IN_ERC20, CODE.HANDSHAKE_CANNOT_CREATE_FREEBET_IN_ERC20)

		contract = Contract.find_contract_by_id(outcome.contract_id)
		if contract is None:
			return response_error(MESSAGE.CONTRACT_INVALID, CODE.CONTRACT_INVALID)

		match = Match.find_match_by_id(outcome.match_id)
		data['hid'] = outcome.hid
		data['outcome_name'] = outcome.name
		data['match_date'] = match.date
		data['match_name'] = match.name
		data['uid'] = uid
		data['payload'] = user.payload
		data['free_bet'] = 1
		data['amount'] = CONST.CRYPTOSIGN_FREE_BET_AMOUNT

		user.free_bet += 1
		task = Task(
			task_type=CONST.TASK_TYPE['FREE_BET'],
			data=json.dumps(data),
			action=CONST.TASK_ACTION['INIT'],
			status=-1,
			contract_address=contract.contract_address,
			contract_json=contract.json_name
		)
		db.session.add(task)
		db.session.commit()

		# this is for frontend
		handshakes = handshake_bl.find_all_matched_handshakes(side, odds, outcome.id, amount, uid)
		response = {}
		if len(handshakes) == 0:
			response['match'] = 0
		else:
			response['match'] = 1
		return response_ok(response)

	except Exception, ex:
		db.session.rollback()
		return response_error(ex.message)
def init():
	"""
	" User plays bet in binary event.
	"""
	try:
		from_request = request.headers.get('Request-From', 'mobile')
		uid = int(request.headers['Uid'])
		chain_id = int(request.headers.get('ChainId', CONST.BLOCKCHAIN_NETWORK['RINKEBY']))
		user = User.find_user_with_id(uid)		

		data = request.json
		if data is None:
			return response_error(MESSAGE.INVALID_DATA, CODE.INVALID_DATA)

		hs_type = data.get('type', -1)
		extra_data = data.get('extra_data', '')
		description = data.get('description', '')
		outcome_id = data.get('outcome_id', -1)
		match_id = data.get('match_id', -1)
		odds = Decimal(data.get('odds', '2')).quantize(Decimal('.1'), rounding=ROUND_HALF_DOWN)
		amount = Decimal(data.get('amount'))
		currency = data.get('currency', 'ETH')
		side = int(data.get('side', CONST.SIDE_TYPE['SUPPORT']))
		chain_id = int(data.get('chain_id', CONST.BLOCKCHAIN_NETWORK['RINKEBY']))
		from_address = data.get('from_address', '')
		free_bet = data.get('free_bet', 0)

		print '-------- DEBUG INIT -------'
		print '-------- amount = {}, type = {}, request = {} -------'.format(amount, type(amount), data.get('amount'))

		if hs_type != CONST.Handshake['INDUSTRIES_BETTING']:
			return response_error(MESSAGE.HANDSHAKE_INVALID_BETTING_TYPE, CODE.HANDSHAKE_INVALID_BETTING_TYPE)

		if len(from_address) < 40:
			return response_error(MESSAGE.INVALID_ADDRESS, CODE.INVALID_ADDRESS)

		# check valid outcome or not
		outcome = None
		if match_id == -1:
			outcome = Outcome.find_outcome_by_id(outcome_id)
		else:
			match = Match.find_match_by_id(match_id)
			if match is not None and len(match.outcomes.all()) > 0:
				outcome = match.outcomes[0]

		if outcome is None:
			return response_error(MESSAGE.OUTCOME_INVALID, CODE.OUTCOME_INVALID)

		if outcome.result != CONST.RESULT_TYPE['PENDING']:
			return response_error(MESSAGE.OUTCOME_HAS_RESULT, CODE.OUTCOME_HAS_RESULT)

		outcome_id = outcome.id

		# make sure user cannot call free-bet in ERC20
		if free_bet == 1:
			token = Token.find_token_by_id(outcome.token_id)
			if token is not None:
				return response_error(MESSAGE.HANDSHAKE_CANNOT_CREATE_FREEBET_IN_ERC20, CODE.HANDSHAKE_CANNOT_CREATE_FREEBET_IN_ERC20)

		if odds <= 1:
			return response_error(MESSAGE.INVALID_ODDS, CODE.INVALID_ODDS)

		contract = Contract.find_contract_by_id(outcome.contract_id)
		if contract is None:
			return response_error(MESSAGE.CONTRACT_INVALID, CODE.CONTRACT_INVALID)

		# add to history
		history = History(			
			chain_id=chain_id,
			description=description,
			free_bet=free_bet,
			from_address=from_address,
			contract_address=contract.contract_address,
			contract_json=contract.json_name,
			odds=odds,
			amount=amount,
			currency=currency,
			from_request=from_request,
			side=side,
			user_id=uid,
			outcome_id=outcome_id
		)
		db.session.add(history)
		db.session.flush()

		# filter all handshakes which able be to match first
		handshakes = handshake_bl.find_all_matched_handshakes(side, odds, outcome_id, amount, uid)
		arr_hs = []
		if len(handshakes) == 0:
			handshake = Handshake(
				hs_type=hs_type,
				extra_data=extra_data,
				description=description,
				chain_id=chain_id,
				user_id=user.id,
				outcome_id=outcome_id,
				odds=odds,
				amount=amount,
				currency=currency,
				side=side,
				remaining_amount=amount,
				from_address=from_address,
				free_bet=free_bet,
				contract_address=contract.contract_address,
				contract_json=contract.json_name,
				from_request=from_request,
				history_id=history.id
			)

			db.session.add(handshake)
			db.session.commit()

			update_feed.delay(handshake.id)

			# response data
			hs_json = handshake.to_json()
			hs_json['maker_address'] = handshake.from_address
			hs_json['maker_odds'] = handshake.odds
			hs_json['hid'] = outcome.hid
			hs_json['type'] = 'init'
			hs_json['offchain'] = CONST.CRYPTOSIGN_OFFCHAIN_PREFIX + 'm' + str(handshake.id)
			arr_hs.append(hs_json)

			logfile.debug("Uid -> {}, json --> {}".format(uid, arr_hs))
		else:
			shaker_amount = amount

			hs_feed = []
			sk_feed = []
			for handshake in handshakes:
				if shaker_amount.quantize(Decimal('.00000000000000001'), rounding=ROUND_DOWN) <= 0:
					break

				handshake.shake_count += 1
				handshake_win_value = handshake.remaining_amount*handshake.odds
				shaker_win_value = shaker_amount*odds
				subtracted_amount_for_shaker = 0
				subtracted_amount_for_handshake = 0


				if is_equal(handshake_win_value, shaker_win_value):
					subtracted_amount_for_shaker = shaker_amount
					subtracted_amount_for_handshake = handshake.remaining_amount

				elif handshake_win_value >= shaker_win_value:
					subtracted_amount_for_shaker = shaker_amount
					subtracted_amount_for_handshake = shaker_win_value - subtracted_amount_for_shaker

				else:
					subtracted_amount_for_handshake = handshake.remaining_amount
					subtracted_amount_for_shaker = handshake_win_value - subtracted_amount_for_handshake

				handshake.remaining_amount -= subtracted_amount_for_handshake
				shaker_amount -= subtracted_amount_for_shaker
				db.session.merge(handshake)

				o = Outcome.find_outcome_by_id(handshake.outcome_id)

				if o is None:
					return response_error(MESSAGE.OUTCOME_INVALID, CODE.OUTCOME_INVALID)

				c = Contract.find_contract_by_id(o.contract_id)
				if c is None:
					return response_error(MESSAGE.CONTRACT_INVALID, CODE.CONTRACT_INVALID)

				# create shaker
				shaker = Shaker(
					shaker_id=user.id,
					amount=subtracted_amount_for_shaker,
					currency=currency,
					odds=odds,
					side=side,
					handshake_id=handshake.id,
					from_address=from_address,
					chain_id=chain_id,
					free_bet=free_bet,
					contract_address=c.contract_address,
					contract_json=c.json_name,
					from_request=from_request,
					history_id=history.id
				)

				db.session.add(shaker)
				db.session.flush()
				sk_feed.append(shaker)
				
				shaker_json = shaker.to_json()
				shaker_json['maker_address'] = handshake.from_address
				shaker_json['maker_odds'] = handshake.odds
				shaker_json['hid'] = outcome.hid
				shaker_json['type'] = 'shake'
				shaker_json['offchain'] = CONST.CRYPTOSIGN_OFFCHAIN_PREFIX + 's' + str(shaker.id)
				arr_hs.append(shaker_json)

			if shaker_amount.quantize(Decimal('.00000000000000001'), rounding=ROUND_DOWN) > Decimal(CONST.CRYPTOSIGN_MINIMUM_MONEY):
				handshake = Handshake(
					hs_type=hs_type,
					extra_data=extra_data,
					description=description,
					chain_id=chain_id,
					user_id=user.id,
					outcome_id=outcome_id,
					odds=odds,
					amount=shaker_amount,
					currency=currency,
					side=side,
					remaining_amount=shaker_amount,
					from_address=from_address,
					free_bet=free_bet,
					contract_address=contract.contract_address,
					contract_json=contract.json_name,
					from_request=from_request,
					history_id=history.id
				)
				db.session.add(handshake)
				db.session.flush()
				hs_feed.append(handshake)			

				hs_json = handshake.to_json()
				hs_json['maker_address'] = handshake.from_address
				hs_json['maker_odds'] = handshake.odds
				hs_json['hid'] = outcome.hid
				hs_json['type'] = 'init'
				hs_json['offchain'] = CONST.CRYPTOSIGN_OFFCHAIN_PREFIX + 'm' + str(handshake.id)
				arr_hs.append(hs_json)
			
			db.session.commit()
			logfile.debug("Uid -> {}, json --> {}".format(uid, arr_hs))

			handshake_bl.update_handshakes_feed(hs_feed, sk_feed)

		# make response
		response = {
			"handshakes": arr_hs,
			"total_bets": handshake_bl.get_total_real_bets()
		}
		return response_ok(response)

	except Exception, ex:
		db.session.rollback()
		return response_error(ex.message)
def save_handshake_method_for_event(method, inputs):
    offchain, hid, state, outcome_result = parse_inputs(inputs)
    if method == 'init' or method == 'initTestDrive':
        offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')
        offchain = int(offchain.replace('m', ''))
        handshake = Handshake.find_handshake_by_id(offchain)
        if handshake is not None:
            handshake.bk_status = handshake.status
            handshake.status = HandshakeStatus['STATUS_INIT_FAILED']
            db.session.flush()

            arr = []
            arr.append(handshake)
            return arr, None

    elif method == 'shake' or method == 'shakeTestDrive':
        offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')
        offchain = int(offchain.replace('s', ''))
        shaker = Shaker.find_shaker_by_id(offchain)
        if shaker is not None:
            if shaker.status == HandshakeStatus['STATUS_PENDING']:
                shaker = rollback_shake_state(shaker)

            shaker.bk_status = shaker.status
            shaker.status = HandshakeStatus['STATUS_SHAKE_FAILED']
            db.session.flush()

            arr = []
            arr.append(shaker)
            return None, arr

    elif method == 'uninit' or method == 'uninitTestDrive':
        offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')
        offchain = int(offchain.replace('m', ''))
        handshake = Handshake.find_handshake_by_id(offchain)
        if handshake is not None:
            handshake.bk_status = handshake.status
            handshake.status = HandshakeStatus['STATUS_MAKER_UNINIT_FAILED']
            db.session.flush()

            arr = []
            arr.append(handshake)
            return arr, None

    elif method == 'collect' or method == 'collectTestDrive':
        offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')

        if 'm' in offchain:
            offchain = int(offchain.replace('m', ''))
            handshake = Handshake.find_handshake_by_id(offchain)
            if handshake is not None:
                handshake.bk_status = handshake.status
                handshake.status = HandshakeStatus['STATUS_COLLECT_FAILED']
                db.session.flush()

                arr = []
                arr.append(handshake)
                return arr, None

        elif 's' in offchain:
            offchain = int(offchain.replace('s', ''))
            shaker = Shaker.find_shaker_by_id(offchain)
            if shaker is not None:
                shaker.bk_status = shaker.status
                shaker.status = HandshakeStatus['STATUS_COLLECT_FAILED']
                db.session.flush()

                arr = []
                arr.append(shaker)
                return None, arr

    elif method == 'refund':
        offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')

        if 'm' in offchain:
            offchain = int(offchain.replace('m', ''))
            handshake = Handshake.find_handshake_by_id(offchain)
            if handshake is not None:
                handshake.bk_status = handshake.status
                handshake.status = HandshakeStatus['STATUS_REFUND_FAILED']
                db.session.flush()

                arr = []
                arr.append(handshake)
                return arr, None

        elif 's' in offchain:
            offchain = int(offchain.replace('s', ''))
            shaker = Shaker.find_shaker_by_id(offchain)
            if shaker is not None:
                shaker.bk_status = shaker.status
                shaker.status = HandshakeStatus['STATUS_REFUND_FAILED']
                db.session.flush()

                arr = []
                arr.append(shaker)
                return None, arr

    elif method == 'report':
        outcome_id, result = offchain.replace('cryptosign_report',
                                              '').split('_')
        if outcome_id is None:
            return None, None
        print 'report fail with outcome_id {}'.format(outcome_id)
        outcome = Outcome.find_outcome_by_id(outcome_id)

        if outcome is not None and outcome.result == CONST.RESULT_TYPE[
                'PROCESSING']:
            outcome.result = CONST.RESULT_TYPE['REPORT_FAILED']
            db.session.flush()
        send_report_slack.delay(outcome.id, result, status=0)

    elif method == 'resolve':
        outcome_id, result = offchain.replace('cryptosign_resolve',
                                              '').split('_')
        if outcome_id is None:
            return None, None
        print 'resolve fail with outcome_id {}'.format(outcome_id)
        outcome = Outcome.find_outcome_by_id(outcome_id)

        if outcome is not None and outcome.result == CONST.RESULT_TYPE[
                'DISPUTED']:
            outcome.result = CONST.RESULT_TYPE['REPORT_FAILED']
            db.session.flush()

    return None, None
def save_handshake_for_event(event_name, inputs):
    offchain, hid, state, outcome_result = parse_inputs(inputs)
    offchain = offchain.replace(CONST.CRYPTOSIGN_OFFCHAIN_PREFIX, '')

    if event_name == '__createMarket':
        print '__createMarket'
        offchain = int(offchain.replace('createMarket', ''))
        outcome = Outcome.find_outcome_by_id(offchain)
        if outcome is not None:
            outcome.hid = hid

            if 'closingTime' in inputs and \
             'reportTime' in inputs and \
             'disputeTime' in inputs:
                m = Match.find_match_by_id(outcome.match_id)
                m.date = int(inputs['closingTime'])
                m.reportTime = int(inputs['reportTime'])
                m.disputeTime = int(inputs['disputeTime'])

            db.session.flush()

            if outcome_bl.is_outcome_created_by_user(outcome):
                send_email_event_verification_success.delay(
                    outcome.match_id, outcome.created_user_id)

        return None, None

    elif event_name == '__report':
        print '__report'
        # report{outcome_id}_{side}
        # side 1: SUPPORT, 2: OPPOSE, 3: DRAW
        outcome_id, result = offchain.replace('report', '').split('_')
        if outcome_id is None or result is None:
            return None, None

        outcome = Outcome.find_outcome_by_id(outcome_id)
        if len(result) > -1 and outcome is not None:
            result = int(result)
            outcome.result = result
            db.session.flush()

            handshakes, shakers = data_need_set_result_for_outcome(outcome)

            # send result email to users who play in
            send_result_email(outcome.id, result)

            send_report_slack.delay(outcome.id, result, status=1)

            return handshakes, shakers

        return None, None

    elif event_name == '__shake':
        print '__shake'
        offchain = offchain.replace('s', '')
        shaker = Shaker.find_shaker_by_id(int(offchain))
        if shaker is not None:
            shaker.status = HandshakeStatus['STATUS_SHAKER_SHAKED']
            shaker.bk_status = HandshakeStatus['STATUS_SHAKER_SHAKED']
            db.session.flush()

            # Add shuriken
            if shaker.free_bet == 1:
                add_shuriken.delay(shaker.shaker_id,
                                   CONST.SHURIKEN_TYPE['FREE'])
            else:
                add_shuriken.delay(shaker.shaker_id,
                                   CONST.SHURIKEN_TYPE['REAL'])

            # Give redeem code for referral user
            u = User.find_user_with_id(shaker.shaker_id)
            if u is not None and u.played_bet == 0:
                referral_bl.give_redeem_code_for_referred_user(
                    shaker.shaker_id)
                u.played_bet = 1
                db.session.flush()

            arr = []
            arr.append(shaker)

            return None, arr

        return None, None

    elif event_name == '__collect':
        print '__collect'

        if 's' in offchain:
            offchain = offchain.replace('s', '')
            shaker = Shaker.find_shaker_by_id(int(offchain))
            if shaker is not None:
                # update status of shaker and handshake to done
                # find all bets belongs to this outcome which user join
                # update all statuses (shaker and handshake) of them to done
                return save_collect_state_for_shaker(shaker)

        elif 'm' in offchain:
            offchain = offchain.replace('m', '')
            handshake = Handshake.find_handshake_by_id(int(offchain))
            if handshake is not None:
                # update status of shaker and handshake to done
                # find all bets belongs to this outcome which user join
                # update all statuses (shaker and handshake) of them to done
                return save_collect_state_for_maker(handshake)

        return None, None

    elif event_name == '__init':
        print '__init'
        offchain = offchain.replace('m', '')
        handshake = Handshake.find_handshake_by_id(int(offchain))
        if handshake is not None:
            handshake.status = HandshakeStatus['STATUS_INITED']
            handshake.bk_status = HandshakeStatus['STATUS_INITED']

            db.session.flush()

            arr = []
            arr.append(handshake)

            # Add shuriken
            if handshake.free_bet == 1:
                add_shuriken.delay(handshake.user_id,
                                   CONST.SHURIKEN_TYPE['FREE'])
            else:
                add_shuriken.delay(handshake.user_id,
                                   CONST.SHURIKEN_TYPE['REAL'])

            # Give redeem code for referral user
            u = User.find_user_with_id(handshake.user_id)
            if u is not None and u.played_bet == 0:
                referral_bl.give_redeem_code_for_referred_user(
                    handshake.user_id)
                u.played_bet = 1
                db.session.flush()

            return arr, None

        return None, None

    elif event_name == '__uninit':
        print '__uninit'
        offchain = offchain.replace('m', '')
        handshake = Handshake.find_handshake_by_id(int(offchain))
        if handshake is not None:
            handshake.status = HandshakeStatus['STATUS_MAKER_UNINITED']
            handshake.bk_status = HandshakeStatus['STATUS_MAKER_UNINITED']
            db.session.flush()

            arr = []
            arr.append(handshake)
            return arr, None
        return None, None

    elif event_name == '__refund':
        print '__refund'
        handshake = None
        user_id = None
        free_bet = False
        if 's' in offchain:
            offchain = offchain.replace('s', '')
            shaker = Shaker.find_shaker_by_id(int(offchain))
            if shaker is None:
                return None, None

            user_id = shaker.shaker_id
            free_bet = shaker.free_bet
            handshake = Handshake.find_handshake_by_id(shaker.handshake_id)

        elif 'm' in offchain:
            offchain = offchain.replace('m', '')
            handshake = Handshake.find_handshake_by_id(int(offchain))
            user_id = handshake.user_id
            free_bet = handshake.free_bet

        if handshake is None or user_id is None:
            return None, None

        if free_bet is True:
            redeem_bl.issue_new_redeem_code_for_user(user_id)

        return save_refund_state_for_all(user_id, handshake.outcome_id)

    elif event_name == '__dispute':
        print '__dispute'
        shaker_dispute = []
        handshake_dispute = []
        handshake = None
        user_id = None
        side = None

        if outcome_result is None:
            return None, None

        if state < 2:
            return None, None

        if 's' in offchain:
            offchain = offchain.replace('s', '')
            shaker = Shaker.find_shaker_by_id(int(offchain))
            user_id = shaker.shaker_id
            side = shaker.side

            if shaker is not None:
                handshake = Handshake.find_handshake_by_id(shaker.handshake_id)

        elif 'm' in offchain:
            offchain = offchain.replace('m', '')
            handshake = Handshake.find_handshake_by_id(int(offchain))
            user_id = handshake.user_id
            side = handshake.side

        if handshake is None or user_id is None:
            return None, None

        outcome = Outcome.find_outcome_by_id(handshake.outcome_id)
        if outcome is None:
            return None, None

        update_amount_for_outcome(outcome.id, user_id, side, outcome_result)

        if state == 3 and outcome.result != CONST.RESULT_TYPE['DISPUTED']:
            outcome.result = CONST.RESULT_TYPE['DISPUTED']
            db.session.flush()
            handshake_dispute, shaker_dispute = save_disputed_state(outcome.id)

            # Send mail to admin
            send_dispute_email.delay(outcome.match.name)

        else:
            handshake_dispute, shaker_dispute = save_user_disputed_state(
                handshake, user_id, side, outcome_result)

        return handshake_dispute, shaker_dispute

    elif event_name == '__resolve':
        # resolve{outcome_id}_{side}
        print '__resolve'
        outcome_id, result = offchain.replace('resolve', '').split('_')
        if outcome_id is None or result is None:
            return None, None

        # 1: SUPPORT, 2: OPPOSE, 3: DRAW: It's depended on smart contract definition.
        if len(result) == 0 or int(result) not in [1, 2, 3]:
            return None, None
        outcome = Outcome.find_outcome_by_id(outcome_id)
        if outcome is None:
            return None, None

        result = int(result)
        outcome.total_dispute_amount = 0
        outcome.result = result
        db.session.flush()

        handshakes, shakers = save_resolve_state_for_outcome(outcome.id)

        # send result email to users who play in
        send_result_email(outcome.id, result)
        return handshakes, shakers
	def test_can_refund_for_shaker(self):
		self.clear_data_before_test()
		match = Match.find_match_by_id(1)
		if match is None:
    			match = Match(
				public=1,
				date=seconds - 100,
				reportTime=seconds + 1000,
				disputeTime=seconds + 1000,
				source_id = source.id
			)

			db.session.add(match)
			db.session.commit()
		else:
			match.date = time.time() - 100
			match.disputeTime = time.time() + 1000
			match.reportTime = time.time() + 1000
			db.session.merge(match)
			db.session.commit()

		outcome = Outcome.find_outcome_by_id(88)
		if outcome is not None:
			outcome.result = 1
			outcome.match_id=match.id
		else:
			outcome = Outcome(
				id=88,
				match_id=match.id,
				result=1,
				hid=88,
				contract_id=1
			)
			db.session.add(outcome)
		db.session.commit()

		arr_hs = []

		# -----
		handshake = Handshake(
						hs_type=3,
						chain_id=4,
						user_id=88,
						outcome_id=88,
						odds=1.5,
						amount=1,
						currency='ETH',
						side=2,
						remaining_amount=0,
						from_address='0x123',
						status=0
					)
		db.session.add(handshake)
		db.session.commit()
		arr_hs.append(handshake)

		# -----
		shaker = Shaker(
					shaker_id=66,
					amount=0.2,
					currency='ETH',
					odds=6,
					side=1,
					handshake_id=handshake.id,
					from_address='0x123',
					chain_id=4,
					status=2
				)
		db.session.add(shaker)
		db.session.commit()
		arr_hs.append(shaker)


		actual = handshake_bl.can_refund(None, shaker=shaker)
		expected = False
		self.assertEqual(actual, expected)

		outcome = Outcome.find_outcome_by_id(88)
		outcome.result = 3
		db.session.merge(outcome)
		db.session.flush()

		actual = handshake_bl.can_refund(None, shaker=shaker)
		expected = True
		self.assertEqual(actual, expected)


		for item in arr_hs:
			db.session.delete(item)
			db.session.commit()
def uninit_free_bet(handshake_id):
	"""
	"	Uninit free-bet in ETH
	"""
	try:
		uid = int(request.headers['Uid'])
		chain_id = int(request.headers.get('ChainId', CONST.BLOCKCHAIN_NETWORK['RINKEBY']))
		user = User.find_user_with_id(uid)

		handshake = db.session.query(Handshake).filter(and_(Handshake.id==handshake_id, Handshake.chain_id==chain_id, Handshake.user_id==uid, Handshake.free_bet==1)).first()
		if handshake is not None and \
			(handshake.status == CONST.Handshake['STATUS_INITED'] or \
			handshake.status == CONST.Handshake['STATUS_MAKER_SHOULD_UNINIT']):

			if handshake_bl.can_uninit(handshake) == False:
				return response_error(MESSAGE.HANDSHAKE_CANNOT_UNINIT, CODE.HANDSHAKE_CANNOT_UNINIT)
			else:

				outcome = Outcome.find_outcome_by_id(handshake.outcome_id)
				if outcome is None:
					return response_error(MESSAGE.OUTCOME_INVALID, CODE.OUTCOME_INVALID)
				else:
					# check erc20 token or not
					token = Token.find_token_by_id(outcome.token_id)
					if token is not None:
						return response_error(MESSAGE.HANDSHAKE_CANNOT_UNINIT_FREE_BET_IN_ERC20, CODE.HANDSHAKE_CANNOT_UNINIT_FREE_BET_IN_ERC20)

					contract = Contract.find_contract_by_id(outcome.contract_id)
					if contract is None:
						return response_error(MESSAGE.CONTRACT_INVALID, CODE.CONTRACT_INVALID)

					handshake.status = CONST.Handshake['STATUS_MAKER_UNINIT_PENDING']
					db.session.flush()
					
					data = {
						'hid': outcome.hid,
						'side': handshake.side,
						'odds': handshake.odds,
						'maker': handshake.from_address,
						'value': handshake.amount,
						'offchain': CONST.CRYPTOSIGN_OFFCHAIN_PREFIX + 'm{}'.format(handshake.id),
						'uid': uid,
						'payload': user.payload,
						'free_bet': 1
					}

					task = Task(
						task_type=CONST.TASK_TYPE['FREE_BET'],
						data=json.dumps(data, use_decimal=True),
						action=CONST.TASK_ACTION['UNINIT'],
						status=-1,
						contract_address=contract.contract_address,
						contract_json=contract.json_name
					)
					db.session.add(task)
					db.session.commit()

					update_feed.delay(handshake.id)
					return response_ok(handshake.to_json())
					
		else:
			return response_error(MESSAGE.HANDSHAKE_NOT_FOUND, CODE.HANDSHAKE_NOT_FOUND)	


	except Exception, ex:
		db.session.rollback()
		return response_error(ex.message)
	def test_can_withdraw(self):
		self.clear_data_before_test()

		match = Match.find_match_by_id(1)
		t = datetime.now().timetuple()
		seconds = local_to_utc(t)

		if match is None:
			match = Match(
				public=1,
				date=seconds - 100,
				reportTime=seconds + 200,
				disputeTime=seconds + 300,
				source_id = source.id
			)
			db.session.add(match)
			db.session.commit()
		else:
			match.date = time.time() - 100
			match.disputeTime = time.time() + 200
			match.reportTime = time.time() + 300
			db.session.commit()

		outcome = Outcome.find_outcome_by_id(88)
		if outcome is not None:
			outcome.result = 1
			outcome.match_id=match.id
		else:
			outcome = Outcome(
				id=88,
				match_id=match.id,
				result=1,
				hid=88,
				contract_id=1
			)
			db.session.add(outcome)
		db.session.commit()

		actual = handshake_bl.can_withdraw(None, shaker=None)
		self.assertNotEqual(len(actual), 0)

		# -----
		handshake = Handshake(
			hs_type=3,
			chain_id=4,
			user_id=88,
			outcome_id=9999999,
			odds=1.2,
			amount=1,
			currency='ETH',
			side=1,
			remaining_amount=0,
			from_address='0x123',
			status=0
		)

		actual = handshake_bl.can_withdraw(handshake, shaker=None)
		self.assertEqual(actual, MESSAGE.OUTCOME_INVALID)

		# -----
		handshake = Handshake(
			hs_type=3,
			chain_id=4,
			user_id=88,
			outcome_id=88,
			odds=1.2,
			amount=1,
			currency='ETH',
			side=2,
			remaining_amount=0,
			from_address='0x123',
			status=0
		)

		actual = handshake_bl.can_withdraw(handshake, shaker=None)
		self.assertEqual(actual, MESSAGE.HANDSHAKE_NOT_THE_SAME_RESULT)

		# -----
		handshake = Handshake(
			hs_type=3,
			chain_id=4,
			user_id=88,
			outcome_id=88,
			odds=1.2,
			amount=1,
			currency='ETH',
			side=1,
			remaining_amount=0,
			from_address='0x123',
			status=0
		)

		actual = handshake_bl.can_withdraw(handshake, shaker=None)
		self.assertEqual(actual, MESSAGE.HANDSHAKE_WITHDRAW_AFTER_DISPUTE)

		match = Match.find_match_by_id(1)
		match.disputeTime = time.time() - 1000
		match.reportTime = time.time() - 1000
		db.session.commit()

		# -----
		handshake = Handshake(
			hs_type=3,
			chain_id=4,
			user_id=88,
			outcome_id=88,
			odds=1.2,
			amount=1,
			currency='ETH',
			side=1,
			remaining_amount=0,
			from_address='0x123',
			status=0
		)

		actual = handshake_bl.can_withdraw(handshake, shaker=None)
		self.assertEqual(actual, '')