def test_run_multiple_slots_multiple_outputs(
    pipe_graph_interpreter,
    pipegraph_proxy_test,
    get_accounts,
):
    uint = 5
    dynamic_array = [5, 6, 7]
    address = get_accounts(1)[0]
    t_struct = [uint, dynamic_array, address]

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['(uint256,uint256[],address)'],
        [t_struct],
    )

    function_sig_struct = get_function_signature(
        't_struct', ['(uint256,uint256[],address)'])

    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_struct,
                'inputIndexes': [1],
                'valueIndex': 0,
                'outputSizeIsSlot': [True, False, True],
            },
        ],
    }

    progex['outputIndexes'] = [2]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256'], answer)
    assert decoded_answer[0] == uint

    progex['outputIndexes'] = [3]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256[]'], answer)
    assert list(decoded_answer[0]) == dynamic_array

    progex['outputIndexes'] = [4]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['address'], answer)
    assert decoded_answer[0] == address.lower()

    progex['outputIndexes'] = [2, 3]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256', 'uint256[]'], answer)
    assert decoded_answer[0] == uint
    assert list(decoded_answer[1]) == dynamic_array
def test_run_multiple_slots_simple(
    pipe_graph_interpreter,
    pipegraph_proxy_test,
    get_accounts,
):
    uint = 5

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['uint256'],
        [uint],
    )

    function_sig_uint = get_function_signature('t_uint', ['uint256'])
    # Prepare ProgEx input
    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_uint,
                'inputIndexes': [1],
                'valueIndex': 0,
                'outputSizeIsSlot': [False],
            },
        ],
        'outputIndexes': [2],
    }
    pipe_graph_interpreter.functions.addTestProgEx(progex).transact()
    inserted = pipe_graph_interpreter.functions.getTestingDefault(1).call()
    assert progex['inputs'] == inserted[0]
    assert progex['inputSizeIsSlot'] == inserted[1]
    assert progex['outputIndexes'] == inserted[2]
    assert progex['starts'] == inserted[3]
    assert len(progex['steps']) == len(inserted[4])
    assert progex['steps'][0]['contractAddress'] == inserted[4][0][0]
    assert progex['steps'][0]['functionSig'] == inserted[4][0][1]
    assert progex['steps'][0]['valueIndex'] == inserted[4][0][2]
    assert progex['steps'][0]['inputIndexes'] == inserted[4][0][3]
    assert progex['steps'][0]['outputSizeIsSlot'] == inserted[4][0][4]

    answer = pipe_graph_interpreter.functions.run(progex).call()
    uarray = pipegraph_proxy_test.functions.t_uint(uint).call()
    decoded_answer = decode_abi(['uint256[]'], answer)
    assert list(decoded_answer[0]) == uarray

    answer = pipe_graph_interpreter.functions.runTestingDefault(1).call()
    decoded_answer = decode_abi(['uint256[]'], answer)
    assert list(decoded_answer[0]) == uarray
def test_run_transaction_mix(
    web3,
    get_accounts,
    pipe_graph_interpreter,
    vendor_reg_contract,
    vendor_prices_contract,
    market_contract,
):
    product_id = 1
    wei_value = 100
    buyer = get_accounts(1)[0]
    vendor = vendor_reg_contract.functions.getVendor(product_id).call()
    quantity = vendor_prices_contract.functions.calculateQuantity(
        product_id,
        vendor,
        wei_value,
    ).call()

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['uint256', 'address', 'uint256'],
        [product_id, buyer, wei_value],
    )
    sigGetVendor = get_function_signature('getVendor', ['uint256'])
    sigCalculateQuantity = get_function_signature(
        'calculateQuantity',
        ['uint256', 'address', 'uint256'],
    )
    sigBuy = get_function_signature(
        'buy', ['address', 'address', 'uint256', 'uint256'])

    # Prepare ProgEx input
    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': vendor_reg_contract.address,
                'functionSig': sigGetVendor,
                'inputIndexes': [1],  # product_id
                'valueIndex': 0,
                'outputSizeIsSlot': [True],
            },
            {
                'contractAddress': vendor_prices_contract.address,
                'functionSig': sigCalculateQuantity,
                'inputIndexes': [1, 4, 3],  # product_id, vendor, wei_value
                'valueIndex': 0,
                'outputSizeIsSlot': [True],
            },
            {
                'contractAddress': market_contract.address,
                'functionSig': sigBuy,
                'inputIndexes': [4, 2, 1,
                                 5],  # vendor, buyer, product_id, quantity
                'valueIndex': 3,
                'outputSizeIsSlot': [],
            },
        ],
        'outputIndexes': [],
    }

    prod_quantity_pre = market_contract.functions.getQuantity(
        vendor, product_id).call()
    pipe_graph_interpreter.functions.run(progex).transact({'value': wei_value})
    prod_quantity_post = market_contract.functions.getQuantity(
        vendor, product_id).call()

    assert prod_quantity_pre - quantity == prod_quantity_post
def test_run_payable(
    web3,
    get_accounts,
    pipe_graph_interpreter,
    vendor_reg_contract,
    vendor_prices_contract,
    market_contract,
):
    product_id = 1
    wei_value = 100
    buyer = get_accounts(1)[0]
    vendor = vendor_reg_contract.functions.getVendor(product_id).call()
    quantity = vendor_prices_contract.functions.calculateQuantity(
        product_id,
        vendor,
        wei_value,
    ).call()

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['address', 'address', 'uint256', 'uint256', 'uint256'],
        [vendor, buyer, product_id, quantity, wei_value],
    )
    sigBuy = get_function_signature(
        'buy', ['address', 'address', 'uint256', 'uint256'])

    # Prepare ProgEx input
    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': market_contract.address,
                'functionSig': sigBuy,
                'inputIndexes':
                [1, 2, 3, 4],  # vendor, buyer, product_id, quantity, wei_value
                'valueIndex': 5,
                'outputSizeIsSlot': [],
            },
        ],
        'outputIndexes': [],
    }

    prod_quantity_pre = market_contract.functions.getQuantity(
        vendor, product_id).call()
    txn_hash = pipe_graph_interpreter.functions.run(progex).transact(
        {'value': wei_value})
    prod_quantity_post = market_contract.functions.getQuantity(
        vendor, product_id).call()

    assert prod_quantity_pre - quantity == prod_quantity_post

    txn_hash2 = market_contract.functions.buy(vendor, buyer, product_id,
                                              quantity).transact({
                                                  'value':
                                                  wei_value,
                                              })
    print('test_run_payable run',
          web3.eth.getTransactionReceipt(txn_hash)['cumulativeGasUsed'])
    print('test_run_payable buy',
          web3.eth.getTransactionReceipt(txn_hash2)['cumulativeGasUsed'])
def test_run_multiple_slots_multiple_outputs_complex(
    pipe_graph_interpreter,
    pipegraph_proxy_test,
    get_accounts,
):
    uint = 5

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['uint256'],
        [uint],
    )

    function_sig_uint = get_function_signature('t_uint', ['uint256'])
    function_sig_address = get_function_signature('t_address', [])
    function_sig_array = get_function_signature(
        't_array', ['uint256[]', 'uint256', 'address'])
    function_sig_struct = get_function_signature(
        't_struct', ['(uint256,uint256[],address)'])

    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_uint,
                'inputIndexes': [1],
                'valueIndex': 0,
                'outputSizeIsSlot': [False],
            },
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_address,
                'inputIndexes': [],
                'valueIndex': 0,
                'outputSizeIsSlot': [True],
            },
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_array,
                'inputIndexes': [2, 1, 3],
                'valueIndex': 0,
                'outputSizeIsSlot': [False],
            },
            {
                'contractAddress': pipegraph_proxy_test.address,
                'functionSig': function_sig_struct,
                'inputIndexes': [4],
                'valueIndex': 0,
                'outputSizeIsSlot': [True, False, True],
            },
        ],
    }

    uarray = pipegraph_proxy_test.functions.t_uint(uint).call()

    progex['outputIndexes'] = [1]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256'], answer)
    assert decoded_answer[0] == uint

    progex['outputIndexes'] = [1, 4]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256', '(uint256,uint256[],address)'],
                                answer)
    assert decoded_answer[0] == uint
    assert decoded_answer[1][0] == uint
    assert list(decoded_answer[1][1]) == uarray
    assert decoded_answer[1][2] == pipe_graph_interpreter.address.lower()

    progex['outputIndexes'] = [5]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256'], answer)
    assert decoded_answer[0] == uint

    progex['outputIndexes'] = [6]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256[]'], answer)
    assert list(decoded_answer[0]) == uarray

    progex['outputIndexes'] = [5, 6, 7]
    answer = pipe_graph_interpreter.functions.run(progex).call()
    decoded_answer = decode_abi(['uint256', 'uint256[]', 'address'], answer)
    assert decoded_answer[0] == uint
    assert list(decoded_answer[1]) == uarray
    assert decoded_answer[2] == pipe_graph_interpreter.address.lower()
def test_run_one_slot(
    pipe_graph_interpreter,
    vendor_reg_contract,
    vendor_prices_contract,
    market_contract,
):
    product_id = 1
    wei_value = 100
    vendor = vendor_reg_contract.functions.getVendor(product_id).call()
    quantity = vendor_prices_contract.functions.calculateQuantity(
        product_id,
        vendor,
        wei_value,
    ).call()

    (inputs, starts, inputSizeIsSlot) = prepareGraphProxyInputs(
        ['uint256', 'uint256'],
        [product_id, wei_value],
    )
    functionSig1 = get_function_signature('getVendor', ['uint256'])
    functionSig2 = get_function_signature('calculateQuantity',
                                          ['uint256', 'address', 'uint256'])

    # Prepare ProgEx input
    progex = {
        'inputs':
        inputs,
        'inputSizeIsSlot':
        inputSizeIsSlot,
        'starts':
        starts,
        'steps': [
            {
                'contractAddress': vendor_reg_contract.address,
                'functionSig': functionSig1,
                'inputIndexes': [1],
                'valueIndex': 0,
                'outputSizeIsSlot': [True],
            },
            {
                'contractAddress': vendor_prices_contract.address,
                'functionSig': functionSig2,
                'inputIndexes': [1, 3, 2],
                'valueIndex': 0,
                'outputSizeIsSlot': [True],
            },
        ],
        'outputIndexes': [4],
    }
    pipe_graph_interpreter.functions.addTestProgEx(progex).transact()
    inserted = pipe_graph_interpreter.functions.getTestingDefault(1).call()
    assert progex['inputs'] == inserted[0]
    assert progex['inputSizeIsSlot'] == inserted[1]
    assert progex['outputIndexes'] == inserted[2]
    assert progex['starts'] == inserted[3]
    assert len(progex['steps']) == len(inserted[4])
    assert progex['steps'][0]['contractAddress'] == inserted[4][0][0]
    assert progex['steps'][0]['functionSig'] == inserted[4][0][1]
    assert progex['steps'][0]['valueIndex'] == inserted[4][0][2]
    assert progex['steps'][0]['inputIndexes'] == inserted[4][0][3]
    assert progex['steps'][0]['outputSizeIsSlot'] == inserted[4][0][4]
    assert progex['steps'][1]['contractAddress'] == inserted[4][1][0]
    assert progex['steps'][1]['functionSig'] == inserted[4][1][1]
    assert progex['steps'][1]['valueIndex'] == inserted[4][1][2]
    assert progex['steps'][1]['inputIndexes'] == inserted[4][1][3]
    assert progex['steps'][1]['outputSizeIsSlot'] == inserted[4][1][4]

    answer = pipe_graph_interpreter.functions.run(progex).call()
    assert Web3.toInt(answer) == quantity

    answer = pipe_graph_interpreter.functions.runTestingDefault(1).call()
    assert Web3.toInt(answer) == quantity