def test_canTransferByPartition(self):
        self.set_msg(self.test_account1)
        self.score.issueByPartition(
            "default", self.test_account2, 1000,
            b'minting 1000 tokens to test_account2 in default partition')
        self.score.issueByPartition(
            "locked", self.test_account2, 1000,
            b'minting 1000 tokens to test_account2 in locked partition')
        self.score.issueByPartition(
            "reserved", self.test_account2, 1000,
            b'minting 1000 tokens to test_account2 in reserved partition')

        self.set_msg(self.test_account2)
        reason = self.score.canTransferByPartition("random",
                                                   self.test_account2,
                                                   self.test_account3, 1000,
                                                   None)
        self.assertEqual(reason, "0x50 Invalid Partition")
        reason = self.score.canTransferByPartition("default",
                                                   self.test_account2,
                                                   self.test_account3, 1001,
                                                   None)
        self.assertEqual(reason, "0x52 Insufficient Balance")
        reason = self.score.canTransferByPartition(
            "default", self.test_account2,
            Address.from_prefix_and_int(AddressPrefix.EOA, 0), 1000, None)
        self.assertEqual(reason, "0x57 Invalid Receiver")
        reason = self.score.canTransferByPartition("default",
                                                   self.test_account2,
                                                   self.test_account3, 1000,
                                                   None)
        self.assertEqual(reason, "0x51 Transfer Successful")
    def test_transfer_from_approved(self):

        # Mint an NFT token first via 'mint'
        params = {'_to': self._test1.get_address(), '_tokenId': 1}
        transaction = CallTransactionBuilder() \
            .from_(self._test1.get_address()) \
            .to(self._score_address) \
            .step_limit(100_000_000) \
            .method("mint") \
            .params(params) \
            .build()

        signed_transaction = SignedTransaction(transaction, self._test1)
        tx_result = self.process_transaction(signed_transaction,
                                             self.icon_service)
        self.assertTrue('status' in tx_result)
        self.assertEqual(1, tx_result['status'])

        # Approve token operation to new wallet via 'approve'
        params = {'_to': self._wallet_array[0].get_address(), '_tokenId': 1}
        transaction = CallTransactionBuilder() \
            .from_(self._test1.get_address()) \
            .to(self._score_address) \
            .step_limit(100_000_000) \
            .method("approve") \
            .params(params) \
            .build()

        signed_transaction = SignedTransaction(transaction, self._test1)
        tx_result = self.process_transaction(signed_transaction,
                                             self.icon_service)
        self.assertTrue('status' in tx_result)
        self.assertEqual(1, tx_result['status'])

        # Check approval of token 1 via 'getApproval'
        # owner of token 1 should be self._test1
        # approvee of token 1 should be self._wallet_array[0]

        params = {"_tokenId": 1}
        call = CallBuilder().from_(self._test1.get_address()) \
            .to(self._score_address) \
            .method("getApproved") \
            .params(params) \
            .build()

        response = self.process_call(call, self.icon_service)
        self.assertEqual(response, self._wallet_array[0].get_address())

        # Transfer ownership of token 1 from self._test1 to self._wallet_array[1] by its operator approvee self._wall_array[0] using 'transferFrom'
        params = {
            '_from': self._test1.get_address(),
            '_to': self._wallet_array[1].get_address(),
            '_tokenId': 1
        }
        transaction = CallTransactionBuilder() \
            .from_(self._test1.get_address()) \
            .to(self._score_address) \
            .step_limit(100_000_000) \
            .method("transferFrom") \
            .params(params) \
            .build()

        signed_transaction = SignedTransaction(transaction, self._test1)
        tx_result = self.process_transaction(signed_transaction,
                                             self.icon_service)
        self.assertTrue('status' in tx_result)
        self.assertEqual(1, tx_result['status'])

        # Check new ownership of token 1, expected to be self._wallet_array[1]
        params = {"_tokenId": 1}
        call = CallBuilder().from_(self._test1.get_address()) \
            .to(self._score_address) \
            .method("ownerOf") \
            .params(params) \
            .build()

        response = self.process_call(call, self.icon_service)
        self.assertEqual(response, self._wallet_array[1].get_address())

        # Check token 1's new approved operator, expected zero address
        params = {"_tokenId": 1}
        call = CallBuilder().from_(self._test1.get_address()) \
            .to(self._score_address) \
            .method("getApproved") \
            .params(params) \
            .build()

        response = self.process_call(call, self.icon_service)
        self.assertEqual(
            response, str(Address.from_prefix_and_int(AddressPrefix.EOA, 0)))

        # Check token count of self._test1, expected 0
        params = {"_owner": self._test1.get_address()}
        call = CallBuilder().from_(self._test1.get_address()) \
            .to(self._score_address) \
            .method("balanceOf") \
            .params(params) \
            .build()

        response = self.process_call(call, self.icon_service)
        self.assertEqual(response, hex(0))

        # Last we burn the token from the new owner self._wallet_array[1]
        params = {
            "_tokenId": 1,
        }
        transaction = CallTransactionBuilder() \
            .from_(self._wallet_array[1].get_address()) \
            .to(self._score_address) \
            .step_limit(100_000_000) \
            .method("burn") \
            .params(params) \
            .build()

        signed_transaction = SignedTransaction(transaction,
                                               self._wallet_array[1])
        tx_result = self.process_transaction(signed_transaction,
                                             self.icon_service)
        self.assertTrue('status' in tx_result)
        self.assertEqual(1, tx_result['status'])

        # Check owner of token 1, expect invalid owner (zero address)
        params = {"_tokenId": 1}
        call = CallBuilder().from_(self._test1.get_address()) \
            .to(self._score_address) \
            .method("ownerOf") \
            .params(params) \
            .build()

        with self.assertRaises(IconScoreException) as e:
            self.process_call(call, self.icon_service)
        self.assertEqual(e.exception.code, 32)
        self.assertEqual(e.exception.message,
                         "Invalid _tokenId. NFT is burned")