# Epoch SDK

To send transactions, manage smart contract wallet addresses and signing you can use Epoch SDK

### **Install SDK**

```sh
yarn add @epoch-protocol/sdk
# or 
npm i @epoch-protocol/sdk
```

### **Setting up Bundler Instance**

Bundler Instance is needed to connect to the bundler and perform bundler specific actions like send userOps, getUserOps, getUserOperationHash etc.

You need to the bundlerUrl, [ENTRY\_POINT](https://github.com/eth-infinitism/account-abstraction/tree/develop/deployments) address and the chain id to setup Bundler Instance

```typescript
import { HttpRpcClient } from '@epoch-protocol/sdk'

const bundlerInstance = new HttpRpcClient(bundlerUrl, ENTRY_POINT, parseInt(network.chainId.toString()));
const network = await provider.getNetwork();
```

### **Setting up Account API**

The Account API is essential to manage user's Smart Contract Wallet.&#x20;

There are 2 Implementations of the Account API in Epoch's SDK

#### **Simple Account API**

Account API Implementation for Eth-Infinitism [SimpleAccount.sol](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccount.sol)

You can get the ENTRY\_POINT and FACTORY\_ADDRESS from the Github [here](https://github.com/eth-infinitism/account-abstraction/tree/develop/deployments)

```javascript
import { SimpleAccountAPI } from "@epoch-protocol/sdk";

const ENTRY_POINT = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
const FACTORY_ADDRESS = "0x4A4fC0bF39D191b5fcA7d4868C9F742B342a39c1";

const walletAPIInstance = new SimpleAccountAPI({
  provider,
  entryPointAddress: ENTRY_POINT,
  owner: signer,
  factoryAddress: FACTORY_ADDRESS,
});
```

#### SAFE Account API

Account API Implementation for SAFE Wallet and [ERC4337 Module](https://github.com/safe-global/safe-modules/blob/master/4337/contracts/Safe4337Module.sol)

For SAFE Account API we need the SAFE Config like below, you can use the SAFE config from the SDK itself or you can pass you own.

```typescript
export interface SafeConfig {
    safeProxyFactory: string;
    singleton: string;
    fallbackModule: string;
    aaModule: string;
    addModuleLib: string;
    salt: BigNumber;
}
```

The **safeConfig** and **salt** are essential to **calculate an address for your SAFE Account**. If the salt changes the address will change as well. So make sure you keep a standardised Salt for your application.&#x20;

```javascript
import { SafeAccountAPI } from "@epoch-protocol/sdk";
import { safeDefaultConfig } from "@epoch-protocol/sdk/dist/src/SafeDefaultConfig";

const walletAPIInstance = new SafeAccountAPI({
    provider,
    entryPointAddress: ENTRY_POINT,
    owner: signer,
    safeConfig: safeDefaultConfig[network.chainId],
    salt: safeDefaultConfig[network.chainId].salt,
});
```

**Note** -&#x20;

* ERC4337 Module only works for [**SAFE Version 1.4.1 and above.**](https://github.com/safe-global/safe-contracts/releases) The wallet deployed using our SDK will have that version
* Connecting an **existing ERC4337 Compatible Address is WIP** and we'll soon add support for it. For now if you know the correct safeConfig and salt you can use that address as well.&#x20;

### Generating Valid Nonce for UserOP

#### Nonce For Normal Transactions

You don't need to do anything for a normal transaction to calculate nonce. The SDK takes care of it or you can manually pass in the nonce if you like.&#x20;

```javascript
const userOp = await walletAPI.createSignedUserOp({
        target: someAddress,
        data: "0x",
        value: 100000000n,
        // nonce: BigInt(someNonce),
});
```

#### Nonce For Automated Transactions

Nonce management through Epoch SDK is slightly different when compared to the usual approach for automated transactions, this is to make sure there are no nonce clashes in case you have many user ops in the queue.&#x20;

```typescript
let userOp = {...};

const key = await bundler.getValidNonceKey(userOp);
const nonce = await walletAPI.getNonce(key);

userOp.nonce = nonce;
```

### Sending Transactions

Sending transactions is straightforward.

```typescript
const userOpHash = await bundler.sendUserOpToBundler(userOp);

// In case of non advanced userops
const txid = await walletAPI.getUserOpReceipt(userOpHash);
```

### **Getting Queued UserOps**

To get a list of all the transactions that are with the bundler simply run these

```typescript
const queuedUserOpsList = await bundler.getUserOperations(userAddress);
```

### **Deleting Queued UserOp**

To delete a specific userOp in the automation queue you need to send a new userOp with the same nonce as the userOp you want to delete.

```typescript
const deleteOp = await walletAPI.createSignedUserOp({
        target: userSCWalletAddress,
        data: "0x",
        value: 0n,
        nonce: BigInt(userOpToDelete.nonce).toString(),
});

const deleteUserOpHash = await bundler.deleteAdvancedUserOpFromBundler(deleteOp);
```


---

# 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.epochprotocol.xyz/use-epoch-sdk/intent-automation-module/epoch-sdk.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.
