# 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 { ... }
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hippo-labs.gitbook.io/dev/move-to-ts/app-interface.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
