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 opt_escrow_into_manager(escrow_logicsig, manager_app_id, liquidity_token_asset_id, token1_asset_id, token2_asset_id): print("Opting Escrow into Manager contract...") program = base64.b64decode(escrow_logicsig) lsig = transaction.LogicSig(program) args = [ liquidity_token_asset_id.to_bytes(8, 'big'), token1_asset_id.to_bytes(8, 'big'), token2_asset_id.to_bytes(8, 'big') ] txn = transaction.ApplicationOptInTxn(sender=lsig.address(), sp=algod_client.suggested_params(), index=manager_app_id, app_args=args) lsig_txn = transaction.LogicSigTransaction(txn, lsig) tx_id = algod_client.send_transaction(lsig_txn) wait_for_transaction(tx_id) print( f"Opted Escrow into Manager contract successfully! Tx ID: https://testnet.algoexplorer.io/tx/{tx_id}" ) print()
def opt_escrow_into_token(escrow_logicsig, token_idx): print(f"Opting Escrow into Token with Asset ID: {token_idx}...") program = base64.b64decode(escrow_logicsig) lsig = transaction.LogicSig(program) txn = transaction.AssetTransferTxn( sender=lsig.address(), sp=algod_client.suggested_params(), receiver=lsig.address(), amt=0, index=token_idx, ) lsig_txn = transaction.LogicSigTransaction(txn, lsig) tx_id = algod_client.send_transaction(lsig_txn) wait_for_transaction(tx_id) print( f"Opted Escrow into Token with Asset ID: {token_idx} successfully! Tx ID: https://testnet.algoexplorer.io/tx/{tx_id}" ) print()
def _build_logicsig_txn(program, txn, lsig): """ Helper function to make LogicSigTransaction """ # replacing program with an empty one is OK since it set by source # LogicSig does not like None/invalid programs because of validation program = program if isinstance(program, bytes) else b'\x01' logicsig = transaction.LogicSig(program, lsig.args) return transaction.LogicSigTransaction(txn, logicsig)
def escrow_opt_in_to_asset( client, suggested_params, address, asset_index, ): lsig = transaction.LogicSig( compile_program(client, open('./contracts/escrow.teal', 'rb').read())) asset_opt_in = transaction.AssetTransferTxn(address, suggested_params, address, 0, asset_index) signed_asset_opt_in = transaction.LogicSigTransaction(asset_opt_in, lsig) tx_id = client.send_transactions([signed_asset_opt_in]) return tx_id
def escrow_pay(sender, lsig, receiver, note, client): params = client.suggested_params() params.flat_fee = True params.fee = FEE # microalgos amount = int(10**6) # microalgos unsigned_txn = PaymentTxn( sender.address, params, receiver.address, amount, close_remainder_to=None, note=note, ) signed_txn = transaction.LogicSigTransaction(unsigned_txn, lsig) client.send_transactions([signed_txn]) tx_id = signed_txn.transaction.get_txid() return wait_for_confirmation(client, tx_id)
# now, as a provider, you can withdraw Algo from the escrow if you sign the first valid acl = algod.AlgodClient(params.algod_token, params.algod_address) sp = acl.suggested_params_as_object() first_valid = sp.first data = first_valid.to_bytes(8, byteorder='big') lease = hash.sha256(data) lease_bytes = encoding.HexEncoder.decode(lease) print("first valid: {}".format(first_valid)) txn = transaction.PaymentTxn(escrow_addr, sp, provider_addr, 100000, lease=lease_bytes) with open(lsig_fname, "rb") as f: teal_bytes = f.read() lsig = transaction.LogicSig(teal_bytes) lstx = transaction.LogicSigTransaction(txn, lsig) assert(lstx.verify()) # send LogicSigTransaction to network transaction.write_to_file([lstx], "r_s_1.txn") stdout, stderr = execute(["goal", "clerk", "tealsign", "--data-b64", base64.b64encode(data), "--lsig-txn", "r_s_1.txn", "--keyfile", key_fn, "--set-lsig-arg-idx", "0"]) if stderr != "": print(stderr) raise print(stdout)
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 sign_with_program(self, tx, program, delegator=None): if delegator: raise Exception("haven't implemented delgated logicsig yet") return txn.LogicSigTransaction(tx, txn.LogicSig(program))
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()
def card_order( algod_client: algod.AlgodClient, buyer: Account, seller: Account, price: int, ): params = algod_client.suggested_params() proof_crown_ownership = proof_asa_amount_eq_txn( algod_client=algod_client, sender=seller, asa_id=CROWN_ID, asa_amount=1, ) proof_sceptre_ownership = proof_asa_amount_eq_txn( algod_client=algod_client, sender=seller, asa_id=SCEPTRE_ID, asa_amount=1, ) nft_card_payment = transaction.PaymentTxn( sender=buyer.address, sp=params, receiver=seller.address, amt=price, ) royalty_amount = math.ceil(price * ROYALTY_PERC / 100) royalty_1_payment = transaction.PaymentTxn( sender=seller.address, sp=params, receiver=ROYALTY_COLLECTOR_1.address, amt=royalty_amount, ) royalty_2_payment = transaction.PaymentTxn( sender=seller.address, sp=params, receiver=ROYALTY_COLLECTOR_2.address, amt=royalty_amount, ) nft_card_xfer = transaction.AssetTransferTxn( sender=CARD_CONTRACT.address, sp=params, receiver=buyer.address, amt=1, index=CARD_ID, revocation_target=seller.address, ) trade_gtxn = [ proof_crown_ownership, proof_sceptre_ownership, nft_card_payment, royalty_1_payment, royalty_2_payment, nft_card_xfer ] transaction.assign_group_id(trade_gtxn) signed_nft_card_payment = trade_gtxn[2].sign(buyer.private_key) trade_gtxn[2] = signed_nft_card_payment trade_gtxn[5] = transaction.LogicSigTransaction(trade_gtxn[5], CARD_CONTRACT.lsig) transaction.write_to_file(trade_gtxn, 'trade_raw.gtxn', overwrite=True) print( "📝 Partially signed trade group transaction saved as: 'trade.gtxn'\n") return trade_gtxn
def sign(account: Account, txn: transaction.Transaction): if account.is_lsig(): return transaction.LogicSigTransaction(txn, account.lsig) else: assert account.private_key return txn.sign(account.private_key)