> For the complete documentation index, see [llms.txt](https://hippo-labs.gitbook.io/dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hippo-labs.gitbook.io/dev/move-to-ts/app-interface.md).

# App interface

The snippets below are taken from a simple [lending tutorial](https://github.com/hippospace/tutorial-lending).

When you execute the `move-to-ts` command from inside your Move project, it automatically generates the typescript files under `project-path/build/typescript`. The top-level `index.ts` contains an `App` class which gives you access to all the features of the TypeScript SDK, including:

* fetching state from chain
* executing move functions (using App interface)
* executing move functions (using TypeScript methods)

### Creating App object

```typescript
import { App } from 'path-to-generated-ts-folder';
import { AptosClient } from 'aptos';

async function act() {
  const client = new AptosClient(...);
  const app = new App(client);
}
```

### Loading resources from fullnodes

```typescript
  // continues from above snippet

  // select module lend2 under package hippo_tutorial
  const lend2 = app.hippo_tutorial.lend2;
  const userAddr = new HexString(...);
  const user = await lend2.loadUser(userAddr);
  const protocol = await lend2.loadLendingProtocol(lend2.moduleAddress, false);
  
```

`User` and `LendingProtocol` are resource structs defined in the `lend2` module. For all resource structs, you will be able to fetch them by using:

```typescript
const resource = await app.package.module.loadStructName(ownerAddress);
```

The generated `loadX` method would actually try to load all the key-value pairs of any `IterableTable` contained within the resource. To disable this additional loading behavior, you can pass in another boolean variable,

```typescript
// do not use loadFullState()
const resource = await app.package.module.loadStructName(ownerAddress, false);
```

Do note that if the resource struct contains `Table` members, you need to explicitly pass in a false value to ask the loader to not `loadFullState`. This is because there isn't an easy way to enumerate all key-value pairs of a `Table`. And we require you to pass in the additional `false` to acknowledge that the struct's state is only partially loaded.

### Execute Move functions (arbitrary)

There are 2 approaches to execute arbitrary move functions from TypeScript:

1. Synchronous execution by preloading resources
2. Asynchronous execution

Both require you to place the `#[app]` attribute on the function you want to execute, for example:

```
#[app]
public fun global_get_user_limits(user: address): (bool, u64, u64) acquires User, LendingProtocol {
    let user = borrow_global<User>(user);
    let protocol = borrow_global<LendingProtocol>(@hippo_tutorial);
    user_get_limits(user, protocol)
}
```

The synchronous approach requires you to manually load the needed resources. Once the needed resources are loaded, you may repeatedly call the synchronous function and obtain the return value immediately.

```typescript
// preloading User & LendingProtocol, then invoke global function
const userAddr = new HexString("0xabcd");
await app.loadUser(userAddr);
await app.loadLendingProtocol(lend2.moduleAddress, false, true);
console.log(app.app_global_get_user_limits(userAddr));
```

The asynchronous approach requires you to run `move-to-ts` with the \`-a\` flag, and can handle state loading for you automatically by making asynchronous calls. This returns the most up-to-date result, but every call to the `async` function may involve some delay due to network access.

```typescript
// using async loading. Global objects are loaded from inside the async function
// only works when transpiled with the "-a" flag (asynchronous)
const userAddr = new HexString("0xabcd");
print(await app.app_global_get_user_limits(userAddr));
```

### Execute Move functions (methods)

`move-to-ts` can also generate TypeScript methods for if you use the `#[method]` attribute

```typescript
  // call user_get_limits to compute some info about user's state
  const [isUserHealthy, totalBorrow, totalDeposit] = user.user_get_limits(protocol);
  console.log(isUserHealthy, totalBorrow, totalDeposit);
```

We note that `user_get_limits` is a Move function with the following signature:

```
public fun user_get_limits(user: &User, protocol: &LendingProtocol): (bool, u64, u64);
```

To add `user_get_limits` as a method into the generated TypeScript `User` class, you need to do the following:

* Make sure the first parameter of `user_get_limits` is of type `&User`
* add a `#[method]` attribute to `User`'s Move struct declaration, like below:

```
#[method(user_get_limits)]
struct User has key, store {
    ...
}
```

If you need to attach multiple methods, just include more function names in the method attribute, and separate the function names by comma:

```
#[method(check_borrow_within_limit, user_get_limits)]
struct User has key, store { ... }
```
