def claim_interest(programstr, escrow_id, passphrase, amt, coupon, payment_id, interest_id, par_id, first_block, last_block, algod_client: algod_client()): add = mnemonic.to_public_key(passphrase) key = mnemonic.to_private_key(passphrase) sp = algod_client.suggested_params() sp.first = first_block sp.last = last_block sp.flat_fee = True sp.fee = 1000 print("--------------------------------------------") print("Bundling interest claim and submitting......") txn1 = AssetTransferTxn(add, sp, escrow_id, amt, interest_id) txn2 = AssetTransferTxn(add, sp, add, amt, par_id) txn3 = AssetTransferTxn(escrow_id, sp, add, amt * coupon, payment_id) t = programstr.encode() program = base64.decodebytes(t) arg = (4).to_bytes(8, 'big') lsig = LogicSig(program, args=[arg]) grp_id = calculate_group_id([txn1, txn2, txn3]) txn1.group = grp_id txn2.group = grp_id txn3.group = grp_id stxn1 = txn1.sign(key) stxn2 = txn2.sign(key) stxn3 = LogicSigTransaction(txn3, lsig) signed_group = [stxn1, stxn2, stxn3] tx_id = algod_client.send_transactions(signed_group) wait_for_confirmation(algod_client, tx_id, 200) print("Successfully committed transaction!") print("--------------------------------------------")
def send_grouped_transactions(algod_client, txn_group): """ @params{algod_client} - AlgodClient instance created by calling algod.AlgodClient @params{txn_group} - a list of transaction objects as dictionary in the following format - { 'sender': a dictionary containing the public/private key of the holder, 'txn': unsigned transaction } Groups the transactions and sends them. @returns { 'status': boolean, 'txid': string, 'info': json string containing the transaction information if status is True else a string of error message } """ gid = calculate_group_id([t['txn'] for t in txn_group]) signed_group = [] for t in txn_group: t['txn'].group = gid signed_txn = t['txn'].sign(t['sender']['private_key']) signed_group.append(signed_txn) txid = algod_client.send_transactions(signed_group) print('Pending transaction with id: {}'.format(txid)) try: confirmed_txn = wait_for_confirmation(algod_client, txid) except Exception as err: print(err) return { 'status': False, 'txid': txid, 'info': getattr(err, 'message', str(err)) } return { 'status': True, 'txid': txid, 'info': json.dumps(confirmed_txn) }
def withdraw_liquidity(): print("Building withdraw liquidity atomic transaction group...") encoded_app_args = [ bytes("w", "utf-8"), bytes("5", "utf-8"), bytes("5", "utf-8"), ] # Transaction to Validator txn_1 = transaction.ApplicationCallTxn( sender=TEST_ACCOUNT_ADDRESS, sp=algod_client.suggested_params(), index=VALIDATOR_INDEX, on_complete=transaction.OnComplete.NoOpOC, accounts=[ESCROW_ADDRESS], app_args=encoded_app_args, ) # Transaction to Manager txn_2 = transaction.ApplicationCallTxn( sender=TEST_ACCOUNT_ADDRESS, sp=algod_client.suggested_params(), index=MANAGER_INDEX, on_complete=transaction.OnComplete.NoOpOC, accounts=[ESCROW_ADDRESS], app_args=encoded_app_args, ) # Transaction to Escrow txn_3 = transaction.AssetTransferTxn( sender=TEST_ACCOUNT_ADDRESS, sp=algod_client.suggested_params(), receiver=ESCROW_ADDRESS, amt=TOKEN_AMOUNT, index=LIQUIDITY_TOKEN_INDEX ) # Get group ID and assign to transactions gid = transaction.calculate_group_id([txn_1, txn_2, txn_3]) txn_1.group = gid txn_2.group = gid txn_3.group = gid # Sign transactions stxn_1 = txn_1.sign(TEST_ACCOUNT_PRIVATE_KEY) stxn_2 = txn_2.sign(TEST_ACCOUNT_PRIVATE_KEY) stxn_3 = txn_3.sign(TEST_ACCOUNT_PRIVATE_KEY) # Broadcast the transactions signed_txns = [stxn_1, stxn_2, stxn_3] tx_id = algod_client.send_transactions(signed_txns) # Wait for transaction wait_for_transaction(tx_id) print(f"Withdraw liquidity transaction sent from User to AlgoSwap successfully! Tx ID: https://testnet.algoexplorer.io/tx/{tx_id}") print()
def group_and_sign(signers, txns): assert len(signers) == len(txns) signed_group = [] gid = transaction.calculate_group_id(txns) for signer, t in zip(signers, txns): t.group = gid signed_group.append(sign(signer, t)) return signed_group
def add_liquidity_call( client, user, user_priv_key, suggested_params, app_id, escrow_addr, asset_amount, algos_amount, asset_index, ): app_txn = transaction.ApplicationCallTxn( user, suggested_params, app_id, transaction.OnComplete.NoOpOC.real, app_args=['ADD_LIQUIDITY'.encode('utf-8')]) asset_add_txn = transaction.AssetTransferTxn( user, suggested_params, escrow_addr, asset_amount, asset_index, ) algos_add_txn = transaction.PaymentTxn( user, suggested_params, escrow_addr, algos_amount, ) gid = transaction.calculate_group_id( [app_txn, asset_add_txn, algos_add_txn]) app_txn.group = gid asset_add_txn.group = gid algos_add_txn.group = gid signed_app_txn = app_txn.sign(user_priv_key) signed_asset_add_txn = asset_add_txn.sign(user_priv_key) signed_algos_add_txn = algos_add_txn.sign(user_priv_key) tx_id = client.send_transactions([ signed_app_txn, signed_asset_add_txn, signed_algos_add_txn, ]) return tx_id
def withdraw_call( client, user, user_priv_key, suggested_params, app_id, escrow_addr, asset_index, algos_amount=0, asset_amount=0, ): app_txn = transaction.ApplicationCallTxn( user, suggested_params, app_id, transaction.OnComplete.NoOpOC.real, app_args=['WITHDRAW'.encode('utf-8')]) asset_withdraw_txn = transaction.AssetTransferTxn( escrow_addr, suggested_params, user, asset_amount, asset_index, ) algos_withdraw_txn = transaction.PaymentTxn( escrow_addr, suggested_params, user, algos_amount, ) gid = transaction.calculate_group_id( [app_txn, asset_withdraw_txn, algos_withdraw_txn]) app_txn.group = gid asset_withdraw_txn.group = gid algos_withdraw_txn.group = gid lsig = transaction.LogicSig( compile_program(client, open('./contracts/escrow.teal', 'rb').read())) signed_asset_withdraw_txn = transaction.LogicSigTransaction( asset_withdraw_txn, lsig) signed_algos_withdraw_txn = transaction.LogicSigTransaction( algos_withdraw_txn, lsig) signed_app_txn = app_txn.sign(user_priv_key) tx_id = client.send_transactions( [signed_app_txn, signed_asset_withdraw_txn, signed_algos_withdraw_txn]) return tx_id
def atomic_transfer(txns): gtxn = calculate_group_id([txn[0] for txn in txns]) sgtxns = list() for txn in txns: txn[0].group = gtxn if txn[1].from_account.type == accounts.models.Account.SMART_CONTRACT_ACCOUNT: signed = txn[1].from_account.smart_contract.sign(txn[0]) sgtxns.append(signed) else: signed = txn[0].sign(txn[1].from_account.private_key) sgtxns.append(signed) txn[1].txid = signed.get_txid() CLIENT.send_transactions(sgtxns) return base64.b64encode(gtxn).decode('ascii')
def purchase_bond(programstr, escrow_id, passphrase, amt, payment_id, par, interest_id, par_id, total_payments, algod_client: algod_client(), first_block, last_block): add = mnemonic.to_public_key(passphrase) key = mnemonic.to_private_key(passphrase) sp = algod_client.suggested_params() sp.first = first_block sp.last = last_block sp.flat_fee = True sp.fee = 1000 print("--------------------------------------------") print("Opt-in the buyer account for interest and par token......") txn0_1 = AssetTransferTxn(add, sp, add, 0, interest_id) txn0_2 = AssetTransferTxn(add, sp, add, 0, par_id) sign0_1 = txn0_1.sign(key) sign0_2 = txn0_2.sign(key) txn0_1_id = algod_client.send_transaction(sign0_1) wait_for_confirmation(algod_client, txn0_1_id, 5) print("Successfully opt-in") print("--------------------------------------------") print("--------------------------------------------") print("Bundling purchase transactions and submitting......") txn0_2_id = algod_client.send_transaction(sign0_2) wait_for_confirmation(algod_client, txn0_2_id, 5) txn1 = AssetTransferTxn(add, sp, escrow_id, amt * par, payment_id) txn2 = AssetTransferTxn(escrow_id, sp, add, amt, par_id) txn3 = AssetTransferTxn(escrow_id, sp, add, amt * total_payments, interest_id) t = programstr.encode() program = base64.decodebytes(t) arg = (3).to_bytes(8, 'big') lsig = LogicSig(program, args=[arg]) grp_id = calculate_group_id([txn1, txn2, txn3]) txn1.group = grp_id txn2.group = grp_id txn3.group = grp_id stxn1 = txn1.sign(key) stxn2 = LogicSigTransaction(txn2, lsig) stxn3 = LogicSigTransaction(txn3, lsig) signed_group = [stxn1, stxn2, stxn3] tx_id = algod_client.send_transactions(signed_group) wait_for_confirmation(algod_client, tx_id, 200) print("Successfulley commited transaction!") print("--------------------------------------------")
def test_transaction_group(self): # get the default wallet wallets = self.kcl.list_wallets() wallet_id = None for w in wallets: if w["name"] == wallet_name: wallet_id = w["id"] # get a new handle for the wallet handle = self.kcl.init_wallet_handle(wallet_id, wallet_pswd) # get private key private_key_0 = self.kcl.export_key(handle, wallet_pswd, self.account_0) # get suggested parameters and fee gh = self.acl.versions()['genesis_hash_b64'] rnd = int(self.acl.status()['lastRound']) sp = transaction.SuggestedParams(0, rnd, rnd + 100, gh) # create transaction txn = transaction.PaymentTxn(self.account_0, sp, self.account_0, 1000) # calculate group id gid = transaction.calculate_group_id([txn]) txn.group = gid # sign using kmd stxn1 = self.kcl.sign_transaction(handle, wallet_pswd, txn) # sign using transaction call stxn2 = txn.sign(private_key_0) # check that they are the same self.assertEqual(encoding.msgpack_encode(stxn1), encoding.msgpack_encode(stxn2)) try: send = self.acl.send_transactions([stxn1]) self.assertEqual(send, txn.get_txid()) except error.AlgodHTTPError as ex: self.assertIn( "TransactionPool.Remember: transaction groups not supported", str(ex))
def send_group(self, txns, confirm=True): # Need unsigned transactions to calculate the group This pulls # out the unsigned tx if tx is sigged, logigsigged or # multisgged utxns = [ tx if isinstance(tx, txn.Transaction) else tx.transaction for tx in txns ] gid = txn.calculate_group_id(utxns) for tx in txns: if isinstance(tx, txn.Transaction): tx.group = gid else: tx.transaction.group = gid try: stxns = [self.sign(tx) for tx in txns] txid = self.algod.send_transactions(stxns) if not confirm: return txid, "" return self.confirm(txid), "" except algosdk.error.AlgodHTTPError as e: return (None, str(e))
def swap_call(client, user, user_priv_key, suggested_params, app_id, amount, escrow_addr, asset_index=None): app_txn = transaction.ApplicationCallTxn( user, suggested_params, app_id, transaction.OnComplete.NoOpOC.real, app_args=['SWAP'.encode('utf-8')]) if asset_index: swap_txn = transaction.AssetTransferTxn( user, suggested_params, escrow_addr, amount, asset_index, ) else: swap_txn = transaction.PaymentTxn( user, suggested_params, escrow_addr, amount, ) gid = transaction.calculate_group_id([app_txn, swap_txn]) app_txn.group = gid swap_txn.group = gid signed_app_txn = app_txn.sign(user_priv_key) signed_swap_txn = swap_txn.sign(user_priv_key) tx_id = client.send_transactions([signed_app_txn, signed_swap_txn]) return tx_id
def claim_par(programstr, escrow_id, passphrase, amt, par, payment_id, par_id, first_block, last_block, algod_client): add = mnemonic.to_public_key(passphrase) key = mnemonic.to_private_key(passphrase) sp = algod_client.suggested_params() sp.first = first_block sp.last = last_block sp.flat_fee = True sp.fee = 1000 txn1 = AssetTransferTxn(add, sp, escrow_id, amt, par_id) txn2 = AssetTransferTxn(escrow_id, sp, add, amt * par, payment_id) t = programstr.encode() program = base64.decodebytes(t) arg = (5).to_bytes(8, 'big') lsig = LogicSig(program, args=[arg]) grp_id = calculate_group_id([txn1, txn2]) txn1.group = grp_id txn2.group = grp_id stxn1 = txn1.sign(key) stxn2 = LogicSigTransaction(txn2, lsig) signed_group = [stxn1, stxn2] tx_id = algod_client.send_transactions(signed_group) wait_for_confirmation(algod_client, tx_id, 10)
def group_transactions(): # Initialize an algodClient algod_client = algod.AlgodClient(algod_token, algod_address, headers={"User-Agent": "DoYouLoveMe?"}) # declared account1 and account2 based on user supplied mnemonics print("Loading two existing accounts...") account_1 = get_address(mnemonic_1) account_2 = get_address(mnemonic_2) # convert mnemonic1 and mnemonic2 using the mnemonic.ToPrivateKey() helper function sk_1 = mnemonic.to_private_key(mnemonic_1) sk_2 = mnemonic.to_private_key(mnemonic_2) # display account balances print("Initial balances:") display_account_algo_balance(algod_client, account_1) display_account_algo_balance(algod_client, account_2) # get node suggested parameters params = algod_client.suggested_params() # comment out the next two (2) lines to use suggested fees params.flat_fee = True params.fee = 1000 # create transactions print("Creating transactions...") # from account 2 to account 1 sender = account_2 receiver = account_1 amount = 12 * 1000000 txn_1 = transaction.PaymentTxn(sender, params, receiver, amount) print("...txn_1: from {} to {} for {} microAlgos".format( sender, receiver, amount)) print("...created txn_1: ", txn_1.get_txid()) # from account 1 to account 2 sender = account_1 receiver = account_2 amount = 1 txn_2 = transaction.AssetTransferTxn(sender, params, receiver, amount, 14075399) print("...txn_2: from {} to {} for {} microAlgos".format( sender, receiver, amount)) print("...created txn_2: ", txn_2.get_txid()) # combine transations print("Combining transactions...") # the SDK does this implicitly within grouping below print("Grouping transactions...") # compute group id and put it into each transaction group_id = transaction.calculate_group_id([txn_1, txn_2]) print("...computed groupId: ", group_id) txn_1.group = group_id txn_2.group = group_id # split transaction group print("Splitting unsigned transaction group...") # this example does not use files on disk, so splitting is implicit above # sign transactions print("Signing transactions...") stxn_1 = txn_1.sign(sk_2) print("...account1 signed txn_1: ", stxn_1.get_txid()) stxn_2 = txn_2.sign(sk_1) print("...account2 signed txn_2: ", stxn_2.get_txid()) # assemble transaction group print("Assembling transaction group...") signedGroup = [] signedGroup.append(stxn_1) signedGroup.append(stxn_2) # send transactions print("Sending transaction group...") tx_id = algod_client.send_transactions(signedGroup) # wait for confirmation wait_for_confirmation(algod_client, tx_id) # display account balances print("Final balances:") display_account_algo_balance(algod_client, account_1) display_account_algo_balance(algod_client, account_2) # display confirmed transaction group # tx1 confirmed_txn = algod_client.pending_transaction_info(txn_1.get_txid()) print("Transaction information: {}".format( json.dumps(confirmed_txn, indent=4))) # tx2 confirmed_txn = algod_client.pending_transaction_info(txn_2.get_txid()) print("Transaction information: {}".format( json.dumps(confirmed_txn, indent=4)))
def withdraw_protocol_fees(): print("Building withdraw protocol fees atomic transaction group...") encoded_app_args = [bytes("p", "utf-8")] # Get unclaimed TOKEN1 and TOKEN2 protocol fees protocol_unused_token1 = protocol_unused_token2 = 0 account_info = algod_client.account_info(ESCROW_ADDRESS) local_state = account_info['apps-local-state'] for block in local_state: if block['id'] == MANAGER_INDEX: for kvs in block['key-value']: decoded_key = base64.b64decode(kvs['key']) prefix_bytes = decoded_key[:2] prefix_key = prefix_bytes.decode('utf-8') if (prefix_key == "P1"): protocol_unused_token1 = kvs['value']['uint'] elif (prefix_key == "P2"): protocol_unused_token2 = kvs['value']['uint'] print( f"Unused Protocol Fees is Token 1 = {protocol_unused_token1} and Token 2 = {protocol_unused_token2}" ) if protocol_unused_token1 != 0 and protocol_unused_token2 != 0: # Transaction to Validator txn_1 = transaction.ApplicationCallTxn( sender=DEVELOPER_ACCOUNT_ADDRESS, sp=algod_client.suggested_params(), index=VALIDATOR_INDEX, on_complete=transaction.OnComplete.NoOpOC, accounts=[ESCROW_ADDRESS], app_args=encoded_app_args) # Transaction to Manager txn_2 = transaction.ApplicationCallTxn( sender=DEVELOPER_ACCOUNT_ADDRESS, sp=algod_client.suggested_params(), index=MANAGER_INDEX, on_complete=transaction.OnComplete.NoOpOC, accounts=[ESCROW_ADDRESS], app_args=encoded_app_args) # Transaction to send Token 1 from Escrow to Developer txn_3 = transaction.AssetTransferTxn( sender=ESCROW_ADDRESS, sp=algod_client.suggested_params(), receiver=DEVELOPER_ACCOUNT_ADDRESS, amt=protocol_unused_token1, index=TOKEN1_INDEX) # Transaction to send Token 2 from Escrow to Developer txn_4 = transaction.AssetTransferTxn( sender=ESCROW_ADDRESS, sp=algod_client.suggested_params(), receiver=DEVELOPER_ACCOUNT_ADDRESS, amt=protocol_unused_token2, index=TOKEN2_INDEX) # Make Logicsig program = base64.b64decode(ESCROW_LOGICSIG) lsig = transaction.LogicSig(program) # Get group ID and assign to transactions gid = transaction.calculate_group_id([txn_1, txn_2, txn_3, txn_4]) txn_1.group = gid txn_2.group = gid txn_3.group = gid txn_4.group = gid # Sign transactions stxn_1 = txn_1.sign(DEVELOPER_ACCOUNT_PRIVATE_KEY) stxn_2 = txn_2.sign(DEVELOPER_ACCOUNT_PRIVATE_KEY) stxn_3 = transaction.LogicSigTransaction(txn_3, lsig) stxn_4 = transaction.LogicSigTransaction(txn_4, lsig) # Broadcast the transactions signed_txns = [stxn_1, stxn_2, stxn_3, stxn_4] tx_id = algod_client.send_transactions(signed_txns) # Wait for transaction wait_for_transaction(tx_id) print( f"Withdrew protocol fees for Token 1 and Token 2 from AlgoSwap to Developer successfully! Tx ID: https://testnet.algoexplorer.io/tx/{tx_id}" ) print()
def get_token1_refund(): print("Attempting to get refund of Token 1 from Escrow...") encoded_app_args = [bytes("r", "utf-8")] # Calculate unused_token1 unused_token1 = 0 account_info = algod_client.account_info(TEST_ACCOUNT_ADDRESS) local_state = account_info['apps-local-state'] for block in local_state: if block['id'] == MANAGER_INDEX: for kvs in block['key-value']: decoded_key = base64.b64decode(kvs['key']) prefix_bytes = decoded_key[:2] prefix_key = prefix_bytes.decode('utf-8') addr_bytes = decoded_key[2:] b32_encoded_addr = base64.b32encode(addr_bytes).decode('utf-8') escrow_addr = encoding.encode_address( base64.b32decode(b32_encoded_addr)) if (prefix_key == "U1" and ESCROW_ADDRESS == escrow_addr): unused_token1 = int(kvs['value']['uint']) print(f"User unused Token 1 is {unused_token1}") if unused_token1 != 0: # Transaction to Validator txn_1 = transaction.ApplicationCallTxn( sender=TEST_ACCOUNT_ADDRESS, sp=algod_client.suggested_params(), index=VALIDATOR_INDEX, on_complete=transaction.OnComplete.NoOpOC, accounts=[ESCROW_ADDRESS], app_args=encoded_app_args) # Transaction to Manager txn_2 = transaction.ApplicationCallTxn( sender=TEST_ACCOUNT_ADDRESS, sp=algod_client.suggested_params(), index=MANAGER_INDEX, on_complete=transaction.OnComplete.NoOpOC, accounts=[ESCROW_ADDRESS], app_args=encoded_app_args) # Make LogicSig program = base64.b64decode(ESCROW_LOGICSIG) lsig = transaction.LogicSig(program) # Transaction to get refund of Token 1 from Escrow txn_3 = transaction.AssetTransferTxn( sender=ESCROW_ADDRESS, sp=algod_client.suggested_params(), receiver=TEST_ACCOUNT_ADDRESS, amt=unused_token1, index=TOKEN1_INDEX) # Get group ID and assign to transactions gid = transaction.calculate_group_id([txn_1, txn_2, txn_3]) txn_1.group = gid txn_2.group = gid txn_3.group = gid # Sign transactions stxn_1 = txn_1.sign(TEST_ACCOUNT_PRIVATE_KEY) stxn_2 = txn_2.sign(TEST_ACCOUNT_PRIVATE_KEY) stxn_3 = transaction.LogicSigTransaction(txn_3, lsig) # Broadcast the transactions signed_txns = [stxn_1, stxn_2, stxn_3] tx_id = algod_client.send_transactions(signed_txns) print( f"Got refund of Token 1 from AlgoSwap to User successfully! Tx ID: https://testnet.algoexplorer.io/tx/{tx_id}" ) print()
info = [line.strip() for line in fd] accountA = info[2].split(': ')[1] accountA = { 'pk': mnemonic.to_public_key(accountA), 'sk': mnemonic.to_private_key(accountA) } other = '4O6BRAPVLX5ID23AZWV33TICD35TI6JWOHXVLPGO4VRJATO6MZZQRKC7RI' asset_id = 14035004 params = algod_client.suggested_params() params.fee = 1000 params.flat_fee = True txn1 = PaymentTxn(accountA['pk'], params, other, 42 * 1000000) txn2 = AssetTransferTxn(other, params, accountA['pk'], 1, asset_id) print(f'First transaction ID: {txn1.get_txid()}') print(f'Second transaction ID: {txn2.get_txid()}') gid = calculate_group_id([txn1, txn2]) txn1.group = txn2.group = gid print(f'Group ID of the two transactions: {gid}') stxn1 = txn1.sign(accountA['sk']) with open('../step5.lsig', 'rb') as fd: lsig = encoding.future_msgpack_decode(base64.b64encode(fd.read())) stxn2 = LogicSigTransaction(txn2, lsig) print(f'First signed transaction ID: {stxn1.get_txid()}') print(f'Second signed transaction ID: {stxn2.get_txid()}') txid = algod_client.send_transactions([stxn1, stxn2]) print(f'Send transaction with txID: {txid}') confirmed_txn = wait_for_confirmation(algod_client, txid) print(json.dumps(confirmed_txn, indent=4))
from algosdk import algod, kmd, account from algosdk.future import transaction # generate accounts private_key_sender, sender = account.generate_account() private_key_receiver, receiver = account.generate_account() # create an algod and kmd client acl = algod.AlgodClient(tokens.algod_token, tokens.algod_address) kcl = kmd.KMDClient(tokens.kmd_token, tokens.kmd_address) # get suggested parameters sp = acl.suggested_params_as_object() # create a transaction amount = 10000 txn1 = transaction.PaymentTxn(sender, sp, receiver, amount) txn2 = transaction.PaymentTxn(receiver, sp, sender, amount) # get group id and assign it to transactions gid = transaction.calculate_group_id([txn1, txn2]) txn1.group = gid txn2.group = gid # sign transactions stxn1 = txn1.sign(private_key_sender) stxn2 = txn2.sign(private_key_receiver) # send them over network (note that the accounts need to be funded for this to work) acl.send_transactions([stxn1, stxn2])