# Calling other applications

The preferred way to call other smart contracts is using [`algopy.arc4.abi_call`](https://dev.algorand.co/algokit/languages/python/lg-calling-apps/), [`algopy.arc4.arc4_create`](https://dev.algorand.co/algokit/languages/python/lg-calling-apps/) or [`algopy.arc4.arc4_update`](https://dev.algorand.co/algokit/languages/python/lg-calling-apps/). These methods support type checking and encoding of arguments, decoding of results, group transactions, and in the case of `arc4_create` and `arc4_update` automatic inclusion of approval and clear state programs.

## `algopy.arc4.abi_call`

[`algopy.arc4.abi_call`](https://dev.algorand.co/reference/algorand-python/api/api-algopyarc4/#algopy.arc4.abi_call) can be used to call other ARC-4 contracts, the first argument should refer to an ARC-4 method either by referencing an Algorand Python [`algopy.arc4.ARC4Contract`](https://dev.algorand.co/reference/algorand-python/api/api-algopyarc4/#algopy.arc4.ARC4Contract) method, an [`algopy.arc4.ARC4Client`](https://dev.algorand.co/reference/algorand-python/api/api-algopyarc4/#algopy.arc4.ARC4Client) method generated from an ARC-32/ARC-56 app spec, or a string representing the ARC-4 method signature or name. The following arguments should then be the arguments required for the call, these arguments will be type checked and converted where appropriate. Any other related transaction parameters such as `app_id`, `fee` etc. can also be provided as keyword arguments.

If the ARC-4 method returns an ARC-4 result then the result will be a tuple of the ARC-4 result and the inner transaction. If the ARC-4 method does not return a result, or if the result type is not fully qualified then just the inner transaction is returned.

```
from algopy import Application, ARC4Contract, String, arc4, subroutine

class HelloWorld(ARC4Contract):

@arc4.abimethod()

def greet(self, name: String) -> String:

return "Hello " + name

@subroutine

def call_existing_application(app: Application) -> None:

greeting, greet_txn = arc4.abi_call(HelloWorld.greet, "there", app_id=app)

assert greeting == "Hello there"

assert greet_txn.app_id == 1234
```

### Alternative ways to use `arc4.abi_call`

#### ARC4Client method

An ARC4Client client represents the ARC-4 abimethods of a smart contract and can be used to call abimethods in a type safe way

ARC4Client’s can be produced by using `puyapy --output-client=True` when compiling a smart contract (this would be useful if you wanted to publish a client for consumption by other smart contracts). An ARC4Client can also be generated from an ARC-32/ARC-56 application.json using `puyapy-clientgen` e.g. `puyapy-clientgen examples/hello_world_arc4/out/HelloWorldContract.arc56.json`, this would be the recommended approach for calling another smart contract that is not written in Algorand Python or does not provide the source

```
from algopy import arc4, subroutine

class HelloWorldClient(arc4.ARC4Client):

def hello(self, name: arc4.String) -> arc4.String: ...

@subroutine

def call_another_contract() -> None:

# can reference another algopy contract method

result, txn = arc4.abi_call(HelloWorldClient.hello, arc4.String("World"), app=...)

assert result == "Hello, World"
```

#### Method signature or name

An ARC-4 method selector can be used e.g. `"hello(string)string` along with a type index to specify the return type. Additionally just a name can be provided and the method signature will be inferred e.g.

```
from algopy import arc4, subroutine

@subroutine

def call_another_contract() -> None:

# can reference a method selector

result, txn = arc4.abi_call[arc4.String](docs/_build/markdown/"hello(string)string", arc4.String("Algo"), app=...)

assert result == "Hello, Algo"

# can reference a method name, the method selector is inferred from arguments and return type

result, txn = arc4.abi_call[arc4.String](docs/_build/markdown/"hello", "There", app=...)

assert result == "Hello, There"
```

## `algopy.arc4.arc4_create`

[`algopy.arc4.arc4_create`](https://dev.algorand.co/reference/algorand-python/api/api-algopyarc4/#algopy.arc4.arc4_create) can be used to create ARC-4 applications, and will automatically populate required fields for app creation (such as approval program, clear state program, and global/local state allocation).

Like [`algopy.arc4.abi_call`](https://dev.algorand.co/algokit/languages/python/lg-transactions/#create-an-arc-4-application-and-then-call-it) it handles ARC-4 arguments and provides ARC-4 return values.

If the compiled programs and state allocation fields need to be customized (for example due to [template variables](https://dev.algorand.co/algokit/languages/python/lg-compile/#within-other-contracts)), this can be done by passing a [`algopy.CompiledContract`](https://dev.algorand.co/reference/algorand-python/api/api-algopy/#algopy.CompiledContract) via the `compiled` keyword argument.

```
from algopy import ARC4Contract, String, arc4, subroutine

class HelloWorld(ARC4Contract):

@arc4.abimethod()

def greet(self, name: String) -> String:

return "Hello " + name

@subroutine

def create_new_application() -> None:

hello_world_app = arc4.arc4_create(HelloWorld).created_app

greeting, _txn = arc4.abi_call(HelloWorld.greet, "there", app_id=hello_world_app)

assert greeting == "Hello there"
```

## `algopy.arc4.arc4_update`

[`algopy.arc4.arc4_update`](https://dev.algorand.co/reference/algorand-python/api/api-algopyarc4/#algopy.arc4.arc4_update) is used to update an existing ARC-4 application and will automatically populate the required approval and clear state program fields.

If the compiled programs need to be customized (for example due to [template variables](https://dev.algorand.co/algokit/languages/python/lg-compile/#within-other-contracts)), this can be done by passing a [`algopy.CompiledContract`](https://dev.algorand.co/reference/algorand-python/api/api-algopy/#algopy.CompiledContract) via the `compiled` keyword argument.

```
from algopy import Application, ARC4Contract, String, arc4, subroutine

class NewApp(ARC4Contract):

@arc4.abimethod()

def greet(self, name: String) -> String:

return "Hello " + name

@subroutine

def update_existing_application(existing_app: Application) -> None:

hello_world_app = arc4.arc4_update(NewApp, app_id=existing_app)

greeting, _txn = arc4.abi_call(NewApp.greet, "there", app_id=hello_world_app)

assert greeting == "Hello there"
```

## Using `itxn.ApplicationCall`

If the application being called is not an ARC-4 contract, or an application specification is not available, then [`algopy.itxn.ApplicationCall`](https://dev.algorand.co/reference/algorand-python/api/api-algopyitxn/#algopy.itxn.ApplicationCall) can be used. This approach is generally more verbose than the above approaches, so should only be used if required. See [here](https://dev.algorand.co/algokit/languages/python/lg-transactions/#create-an-arc-4-application-and-then-call-it) for an example
