# Creating a new contract client

In this tutorial, we'll demonstrate how to create a client of any contract, which can be used to simplify and automate deployments and calls to contract methods.&#x20;

To illustrate the process, we'll use the liquidity pool contract available in [this repository](https://github.com/stellar/soroban-examples/tree/main/liquidity_pool).

## Prerequisites

* **Basic Understanding of Stellar Concepts**: Familiarize yourself with Stellar network fundamentals, including assets, accounts, trustlines, and transactions. For more in-depth information, refer to [Stellar's official documentation](https://developers.stellar.org/docs).
* **Basic understanding of Stellar's Soroban:** Familiarize yourself with Soroban and how smart contracts integrate with the Stellar network. For more in-depth information refer to [Soroban's official documentation](https://soroban.stellar.org/docs).
* **Node.js Environment**: Set up a Node.js environment to run your JavaScript code.
* **StellarPlus Library**: Ensure that the StellarPlus library is installed in your project. For the installation steps, refer to [Quick Start](/stellar-plus/quick-start.md).

## Step-by-Step Guide

### Defining the ContractSpec

The first step is to define the XDR spec entries for the contract. To do this, we'll create a `constants.ts` file and export this data as a constant.

{% code lineNumbers="true" %}

```typescript
import { ContractSpec } from "@stellar/stellar-sdk";

export const poolSpec = new ContractSpec([
  "AAAAAAAAAAAAAAAKaW5pdGlhbGl6ZQAAAAAAAwAAAAAAAAAPdG9rZW5fd2FzbV9oYXNoAAAAA+4AAAAgAAAAAAAAAAd0b2tlbl9hAAAAABMAAAAAAAAAB3Rva2VuX2IAAAAAEwAAAAA=",
    "AAAAAAAAAAAAAAAIc2hhcmVfaWQAAAAAAAAAAQAAABM=",
    "AAAAAAAAAAAAAAAHZGVwb3NpdAAAAAAFAAAAAAAAAAJ0bwAAAAAAEwAAAAAAAAAJZGVzaXJlZF9hAAAAAAAACwAAAAAAAAAFbWluX2EAAAAAAAALAAAAAAAAAAlkZXNpcmVkX2IAAAAAAAALAAAAAAAAAAVtaW5fYgAAAAAAAAsAAAAA",
    "AAAAAAAAAAAAAAAEc3dhcAAAAAQAAAAAAAAAAnRvAAAAAAATAAAAAAAAAAVidXlfYQAAAAAAAAEAAAAAAAAAA291dAAAAAALAAAAAAAAAAZpbl9tYXgAAAAAAAsAAAAA",
    "AAAAAAAAAAAAAAAId2l0aGRyYXcAAAAEAAAAAAAAAAJ0bwAAAAAAEwAAAAAAAAAMc2hhcmVfYW1vdW50AAAACwAAAAAAAAAFbWluX2EAAAAAAAALAAAAAAAAAAVtaW5fYgAAAAAAAAsAAAABAAAD7QAAAAIAAAALAAAACw==",
    "AAAAAAAAAAAAAAAJZ2V0X3JzcnZzAAAAAAAAAAAAAAEAAAPtAAAAAgAAAAsAAAAL",
    "AAAAAAAAAAAAAAAKZ2V0X3NoYXJlcwAAAAAAAAAAAAEAAAAL"
]);
```

{% endcode %}

One of the ways to get the spec entries of your contract is to take this data from the library generated by the bindings in Typescript. Refer to the Soroban [official documentation](https://soroban.stellar.org/docs/getting-started/create-an-app#generate-an-npm-package-for-the-hello-world-contract) for more details.&#x20;

### Creating the client

Let's start building the client of our contract by creating a `client.ts` file. It's a good practice to enumerate the contract methods names to use them in camel case, so let's start by doing this.

```typescript
enum methods {
    initialize = "initialize",
    shareId = "share_id",
    deposit = "deposit",
    getReserves = "get_rsrvs",
    swap = "swap",
    withdraw = "withdraw"
}
```

Now we need to build the methods for invoking our contract. To do this, we'll use a class that extends ContractEngine.

```typescript
import { StellarPlus } from "stellar-plus";
import { ContractEngineConstructorArgs } from "stellar-plus/core/contract-engine/types";

export class PoolClient extends StellarPlus.ContractEngine {
  constructor(args: ContractEngineConstructorArgs) {
    super(args);
  }
}
```

Each method needs to be declared individually, with the parameters according to those defined in the contract. The main logic for invoking the contract is done through the `invokeContract` method, but you can include any additional logic you think is necessary based on your application's rules.

Let's start by implementing the deposit method, structured as follows in the contract:

```rust
fn deposit(
    e: Env, 
    to: Address, 
    desired_a: i128, 
    min_a: i128, 
    desired_b: i128, 
    min_b: i128
);
```

The function for invoking this method on our client needs to contain the same name as the method, the name of the parameters, and types as the contract.

<pre class="language-typescript"><code class="lang-typescript">import { Address, i128 } from "stellar-plus/types";
<strong>
</strong>export class PoolClient extends StellarPlus.ContractEngine {
    ...

<strong>    async deposit(args: {
</strong>            to: Address;
            desiredA: i128;
            minA: i128;
            desiredB: i128;
            minB: i128;
        },
        txInvocation: TransactionInvocation;
    ): Promise&#x3C;void> {
        const methodArgs = {
            to: to,
            desired_a: desiredA,
            min_a: minA,
            desired_b: desiredB,
            min_b: minB
        }
        await this.invokeContract({
            method: methods.deposit,
            methodArgs: methodArgs,
            ...txInvocation,
        });
    }
}
</code></pre>

{% hint style="info" %}
To help convert types between Rust and Typescript, import the necessary types from Stellar-plus library.
{% endhint %}

Methods that exclusively perform reads without ledger modifications can adopt the same structure shown above. However, for these cases, it is possible to use the `readFromContract` method instead. This method only simulates the transaction in the ledger without actually executing it, making the function faster and free of fees.

```typescript
export class PoolClient extends StellarPlus.ContractEngine {
    ...
    
    async shareId(txInvocation: TransactionInvocation): Promise<Address> {
        return (await this.readFromContract({
            method: methods.shareId,
            methodArgs: {},
            header: txInvocation.header,
        })) as Address;
    }
}
```

### Client usage

After completing the implementation of all contract methods intended for your application, your client is ready for use. Simply initialize it with the previously defined spec and the desired network.

<pre class="language-typescript"><code class="lang-typescript">import { StellarPlus } from "stellar-plus";
import { PoolClient } from "./client"
import { poolSpec } from "./constants"

const network = StellarPlus.Constants.testnet

const poolClient = new PoolClient({
    network,
    spec: poolSpec,
    contractId: "CBK..."
});

// Invoke the transactions using your client
poolClient.deposit({
        to: "G...";
        desiredA: BigInt(10000);
        minA: BigInt(9000);
        desiredB: BigInt(7000);
        minB: BigInt(5000);
    },
<strong>    txInvocation
</strong><strong>)
</strong></code></pre>

{% hint style="info" %}
The txInvocation defines the parameters that will be included in the transactions. You will need an account to define it:

```typescript
const acc = new StellarPlus.Account.DefaultAccountHandler({
  network,
  secretKey: "S...",
});
  
const txInvocation = {
  header: {
    source: acc.getPublicKey(),
    fee: "100000000",
    timeout: 30,
  },
  signers: [acc],
};
```

{% endhint %}

It is also possible to create a contract deployment process using your client with the wasm file.

```typescript
import { StellarPlus } from "stellar-plus";
import { PoolClient } from "./client"
import { poolSpec } from "./constants"

const network = StellarPlus.Constants.testnet

const poolClient = new PoolClient({
    network,
    spec: poolSpec,
    wasm: "path-to-contract-wasm"
});

poolClient.uploadWasm(txInvocation)
poolClient.deploy(txInvocation)
```

If you already have the hash of the contract, it is possible to use it directly.

```typescript
const poolClient = new PoolClient({
    network,
    spec: poolSpec,
    wasmHash: "your-wasm-hash"
});

poolClient.deploy(txInvocation)
```

If you find it more convenient, you can add methods to your client that handle instantiation, deployment, and other tasks. This makes the overall process more user-friendly and reusable.


---

# 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://docs.cheesecakelabs.com/stellar-plus/tutorials/e2e-certificate-of-deposit-demo-1.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.
