def send(wallet_from, wallet_to, coin, value, gas_coin='BIP', payload=''): nonce = API.get_nonce(wallet_from['address']) send_tx = MinterSendCoinTx(coin, wallet_to, value, nonce=nonce, gas_coin=gas_coin, payload=payload) send_tx.sign(wallet_from['private_key']) r = API.send_transaction(send_tx.signed_tx) print(f'Send TX response:\n{r}') return send_tx
def send_coin_tx(pk, coin, value, to, nonce, gas_coin=BASE_COIN, payload=''): value = to_bip(value) if isinstance(value, str) else value tx = MinterSendCoinTx(coin, to, value, nonce=nonce, gas_coin=gas_coin, payload=payload) tx.sign(pk) return tx
def estimate_custom_send_fee(coin): wallet = MinterWallet.create() send_tx = MinterSendCoinTx(coin, wallet['address'], 0, nonce=0, gas_coin=coin) send_tx.sign(wallet['private_key']) return API.estimate_tx_commission(send_tx.signed_tx, pip2bip=True)['result']['commission']
def sendCoin(address, pk, to, value): nonce = minter.get_nonce(address=str(address)) tx = MinterSendCoinTx(coin="BIP", to=to, value=float(value), nonce=nonce, gas_coin="BIP") tx.sign(private_key=pk) send = minter.send_transaction(tx=tx.signed_tx) print(send) hash = send['result']['hash'].lower() return "Mt" + hash
def test_payload_fee(self): tx = MinterSendCoinTx( **{ 'nonce': 1, 'chain_id': MinterTx.TESTNET_CHAIN_ID, 'gas_coin': 'MNT', 'to': self.TO, 'coin': 'MNT', 'value': 1, 'payload': self.TX_PAYLOAD_UTF }) tx.sign(self.PRIVATE_KEY) actual_fee = tx.get_fee() self.assertEqual(self.EXPECTED_SEND_COIN_FEE, actual_fee)
def _send_from_user(wallet_from, address_to, amount, coin='BIP'): pkey = MinterWallet.create(mnemonic=wallet_from.mnemonic)['private_key'] nonce = api.get_nonce(wallet_from.address) tx = MinterSendCoinTx(to=address_to, value=amount, coin=coin, nonce=nonce, gas_coin=coin) tx.sign(pkey) r = api.send_transaction(tx.signed_tx) info('API send tx response:') info(pformat(r)) return nonce + 1
def send_coins(value, to_wallet, commission, payload=''): bot_wallet_data = api.get_balance(BOT_WALLET)['result'] nonce = int(bot_wallet_data['transaction_count']) + 1 bot_reward = value * commission payment = value - bot_reward tx = MinterSendCoinTx(to=to_wallet, value=payment, coin='BIP', nonce=nonce, gas_coin='BIP', payload=payload) tx.sign(PRIVATE_KEY) return api.send_transaction(tx.signed_tx)
class TestMinterSendTx(unittest.TestCase): def setUp(self): self.PRIVATE_KEY = '07bc17abdcee8b971bb8723e36fe9d2523306d5ab2d683631693238e0f9df142' self.TO = 'Mx1b685a7c1e78726c48f619c497a07ed75fe00483' self.FROM = 'Mx31e61a05adbd13c6b625262704bc305bf7725026' self.SIGNED_TX = 'f8840102018a4d4e540000000000000001aae98a4d4e5400000000000000941b685a7c1e78726c48f619c497a07ed75fe00483880de0b6b3a7640000808001b845f8431ca01f36e51600baa1d89d2bee64def9ac5d88c518cdefe45e3de66a3cf9fe410de4a01bc2228dc419a97ded0efe6848de906fbe6c659092167ef0e7dcb8d15024123a' self.TX = MinterSendCoinTx( **{ 'nonce': 1, 'chain_id': MinterTx.TESTNET_CHAIN_ID, 'gas_coin': 'MNT', 'to': self.TO, 'coin': 'MNT', 'value': 1 }) def test_valid_tx(self): """ Is tx instance of needed TX class. """ self.assertIsInstance(self.TX, MinterSendCoinTx) def test_sign_tx(self): """ Sign transaction and check signed transaction """ self.TX.sign(self.PRIVATE_KEY) self.assertEqual(self.TX.signed_tx, self.SIGNED_TX) def test_sign_with_signature(self): self.TX.signature_type = MinterTx.SIGNATURE_SINGLE_TYPE signature = self.TX.generate_signature(self.PRIVATE_KEY) self.TX.sign(signature=signature) self.assertEqual(self.TX.signed_tx, self.SIGNED_TX) def test_from_raw(self): tx = MinterTx.from_raw(self.SIGNED_TX) self.assertEqual(tx.from_mx, self.FROM) self.assertEqual(tx.to, self.TX.to) self.assertEqual(tx.coin, self.TX.coin) self.assertEqual(tx.value, self.TX.value)
def send(self, to, value, coin="BIP", payload='', include_commission=True): value = Decimal(str(value)) nonce = self.API.get_nonce(self.address) tx = MinterSendCoinTx(coin=coin, to=to, value=value, nonce=nonce, gas_coin=coin, payload=payload) if include_commission: if coin == 'BIP': commission = to_bip(tx.get_fee()) else: tx.sign(self.private_key) commission = self.API.estimate_tx_commission( tx.signed_tx, pip2bip=True)['result']['commission'] tx.value = value - commission # Проверяем на ошибки if tx.value <= 0: print( f'Ошибка: Комиссия ({to_bip(tx.get_fee())}) превышает сумму выплаты ({value})' ) return elif tx.value > self.get_balance(in_bip=True)[coin]: print(f'Ошибка: На кошельке недостаточно {coin}') return tx.sign(private_key=self.private_key) r = self.API.send_transaction(tx.signed_tx) try: if r['result']['code'] == 0: print(f'{value} {coin} успешно отпрвлены на адрес {to}') self._wait_for_nonce( nonce ) # Ждем nonce, чтобы предотвратить отправку нескольких транзакций в блоке except Exception: print(f'Не удалось отправить {coin}\nServer response: {r}') return r
def timeloop(client: Client, call: CallbackQuery): user, _ = get_user_model(call.from_user) coin = 'TIME' wallet = MinterWallets.objects.get(user=user) wallet_obj = MinterWallet.create(mnemonic=wallet.mnemonic) amount = wallet.balance[coin] nonce = API.get_nonce(wallet.address) send_tx = MinterSendCoinTx(coin, wallet.address, amount, nonce=nonce, gas_coin=coin) send_tx.sign(wallet_obj['private_key']) tx_fee = API.estimate_tx_commission(send_tx.signed_tx, pip2bip=True)['result']['commission'] available_send = amount - tx_fee user_timeloop_address = call.data.split('_')[-1] if not user_timeloop_address: alert_text = user.choice_localized(text_name='alert-tl-no-account') client.answer_callback_query(call.id, text=alert_text) return if available_send <= 0: alert_text = user.choice_localized(text_name='alert-tl-no-money') client.answer_callback_query(call.id, text=alert_text) return response = coin_send(wallet_obj['private_key'], wallet_obj['address'], user_timeloop_address, coin, available_send, gas_coin=coin) if 'error' in response: alert_text = user.choice_localized(text_name='alert-tl-no-money') client.answer_callback_query(call.id, text=alert_text) return alert_text = user.choice_localized(text_name='alert-tl-success') client.answer_callback_query(call.id, text=alert_text)
def coin_send(private_key, addr_from, addr_to, coin, value, gas_coin='BIP', payload=''): logger.info(f'Sending: {value} {coin} -> {addr_to}') if LOCAL and not LOCAL_REAL_TXS: return {} nonce = API.get_nonce(addr_from) send_tx = MinterSendCoinTx(coin, addr_to, value, nonce=nonce, gas_coin=gas_coin, payload=payload) send_tx.sign(private_key) r = API.send_transaction(send_tx.signed_tx) logger.info(f'Send TX response:\n{r}') return r
class TestPayloadsFromRaw(unittest.TestCase): def setUp(self): self.TO = 'Mxd82558ea00eb81d35f2654953598f5d51737d31d' self.FROM = 'Mx31e61a05adbd13c6b625262704bc305bf7725026' self.PK = '07bc17abdcee8b971bb8723e36fe9d2523306d5ab2d683631693238e0f9df142' self.TX = MinterSendCoinTx(nonce=1, gas_coin='mnt', to=self.TO, coin='mnt', value=1) self.TX_DECODED = None def sign_and_decode(self, payload): self.TX.payload = payload self.TX.sign(private_key=self.PK) self.TX_DECODED = MinterTx.from_raw(self.TX.signed_tx) def test_hex_like(self): payload = 'fff' self.sign_and_decode(payload) self.assertEqual(payload, self.TX_DECODED.payload) self.assertEqual(self.FROM, self.TX_DECODED.from_mx) def test_str_bytes(self): payload = '🔳' self.sign_and_decode(payload) self.assertEqual(payload, self.TX_DECODED.payload) self.assertEqual(self.FROM, self.TX_DECODED.from_mx) def test_raw_bytes(self): payload = b'\xff\xff\xff' self.sign_and_decode(payload) self.assertEqual(payload, self.TX_DECODED.payload) self.assertEqual(self.FROM, self.TX_DECODED.from_mx)
class TestMinterSendMultisigTx(unittest.TestCase): def setUp(self): self.PRIVATE_KEYS = [ 'b354c3d1d456d5a1ddd65ca05fd710117701ec69d82dac1858986049a0385af9', '38b7dfb77426247aed6081f769ed8f62aaec2ee2b38336110ac4f7484478dccb', '94c0915734f92dd66acfdc48f82b1d0b208efd544fe763386160ec30c968b4af' ] self.TO = 'Mxd82558ea00eb81d35f2654953598f5d51737d31d' self.FROM = 'Mxdb4f4b6942cb927e8d7e3a1f602d0f1fb43b5bd2' self.SIGNED_TX = 'f901270102018a4d4e540000000000000001aae98a4d4e540000000000000094d82558ea00eb81d35f2654953598f5d51737d31d880de0b6b3a7640000808002b8e8f8e694db4f4b6942cb927e8d7e3a1f602d0f1fb43b5bd2f8cff8431ca0a116e33d2fea86a213577fc9dae16a7e4cadb375499f378b33cddd1d4113b6c1a021ee1e9eb61bbd24233a0967e1c745ab23001cf8816bb217d01ed4595c6cb2cdf8431ca0f7f9c7a6734ab2db210356161f2d012aa9936ee506d88d8d0cba15ad6c84f8a7a04b71b87cbbe7905942de839211daa984325a15bdeca6eea75e5d0f28f9aaeef8f8431ba0d8c640d7605034eefc8870a6a3d1c22e2f589a9319288342632b1c4e6ce35128a055fe3f93f31044033fe7b07963d547ac50bccaac38a057ce61665374c72fb454' self.TX = MinterSendCoinTx( **{ 'nonce': 1, 'chain_id': MinterTx.TESTNET_CHAIN_ID, 'gas_coin': 'MNT', 'to': self.TO, 'coin': 'MNT', 'value': 1 }) def test_valid_tx(self): """ Is tx instance of needed TX class. """ self.assertIsInstance(self.TX, MinterSendCoinTx) def test_sign_tx(self): """ Sign transaction and check signed transaction """ self.TX.sign(private_key=self.PRIVATE_KEYS, ms_address=self.FROM) self.assertEqual(self.TX.signed_tx, self.SIGNED_TX) def test_from_raw(self): tx = MinterTx.from_raw(self.SIGNED_TX) self.assertEqual(tx.from_mx, self.FROM) self.assertEqual(tx.to, self.TX.to) self.assertEqual(tx.coin, self.TX.coin) self.assertEqual(tx.value, self.TX.value) def test_add_signature(self): # Sign tx with 2 of 3 private keys self.TX.sign(private_key=self.PRIVATE_KEYS[:2], ms_address=self.FROM) # Add signature by 3rd private key self.TX = MinterTx.add_signature(self.TX.signed_tx, self.PRIVATE_KEYS[2]) self.assertEqual(self.TX.signed_tx, self.SIGNED_TX) def test_sign_with_signature(self): # Set signature type for transaction self.TX.signature_type = MinterTx.SIGNATURE_MULTI_TYPE # Generate signatures signatures = [] for pk in self.PRIVATE_KEYS: signature = self.TX.generate_signature(private_key=pk) signatures.append(signature) # Sign transaction with signatures self.TX.sign(signature=signatures, ms_address=self.FROM) self.assertEqual(self.TX.signed_tx, self.SIGNED_TX) def test_sign_with_pk_and_signature(self): # Set signature type for transaction self.TX.signature_type = MinterTx.SIGNATURE_MULTI_TYPE # Generate 1 signature signatures = [] for pk in self.PRIVATE_KEYS: signatures.append(self.TX.generate_signature(private_key=pk)) # Sign transaction with pks and signature self.TX.sign(private_key=self.PRIVATE_KEYS[:2], signature=signatures[2], ms_address=self.FROM) self.assertEqual(self.TX.signed_tx, self.SIGNED_TX) self.TX.sign(private_key=self.PRIVATE_KEYS[0], signature=signatures[1:], ms_address=self.FROM) self.assertEqual(self.TX.signed_tx, self.SIGNED_TX)
def my_wallet(client: Client, message: Message): user, _ = get_user_model(message.from_user) wallet = MinterWallets.objects.get(user=user) wallet_obj = MinterWallet.create(mnemonic=wallet.mnemonic) private_key = wallet_obj['private_key'] coin = Tools.objects.get(pk=1).coin amount = wallet.balance[coin] if not amount: coin = 'BIP' amount = wallet.balance[coin] nonce = API.get_nonce(wallet.address) check_obj = MinterCheck(nonce=1, due_block=999999999, coin=coin, value=amount, gas_coin=coin, passphrase=wallet.mnemonic) check_str = check_obj.sign(private_key) redeem_tx = MinterRedeemCheckTx(check_str, check_obj.proof(wallet.address, ''), nonce=1, gas_coin=coin) redeem_tx.sign(private_key) redeem_tx_fee = API.estimate_tx_commission( redeem_tx.signed_tx, pip2bip=True)['result']['commission'] logger.info(f'Wallet {wallet.address} balance (check): {wallet.balance}') logger.info(f'Redeem check tx fee: {redeem_tx_fee}') available_withdraw = amount - redeem_tx_fee send_tx = MinterSendCoinTx(coin, wallet.address, amount, nonce=nonce, gas_coin=coin) send_tx.sign(wallet_obj['private_key']) send_tx_fee = API.estimate_tx_commission( send_tx.signed_tx, pip2bip=True)['result']['commission'] logger.info(f'Send tx fee: {send_tx_fee}') available_send = amount - send_tx_fee to_wallet_text = None timeloop_text = None redeem_url = None user_address = None if available_withdraw > 0: to_wallet_text = user.choice_localized(text_name='btn-withdraw-minter') passphrase = uuid() check_obj = MinterCheck(nonce=1, due_block=999999999, coin=coin, value=available_withdraw, gas_coin=coin, passphrase=passphrase) check_str = check_obj.sign(private_key) redeem_tx = MinterRedeemCheckTx(check_str, proof='', nonce=nonce, gas_coin=coin) redeem_dl = MinterDeeplink(redeem_tx, data_only=True) redeem_dl.gas_coin = coin redeem_url = redeem_dl.generate(password=passphrase) logger.info(redeem_url) if available_send > 0: user_address = get_user_timeloop_address(message.chat.id) logger.info(f'User TL: {user_address}') timeloop_text = user.choice_localized( text_name='btn-withdraw-timeloop') markup = markup_wallet(to_wallet_text=to_wallet_text, redeem_deeplink=redeem_url, timeloop_text=timeloop_text, user_address=user_address) text = user.choice_localized(text_name='msg-wallet').format( user_wallet_address=wallet.address, user_seed_phrase=wallet.mnemonic, amount=wallet.balance_formatted) client.send_message(user.id, text, reply_markup=markup)