npm package: @moonchain/agents
Description: _description_
Author: Hairyf
Latest version: 0.1.0

## Moonchain Transaction Agents

The Moonchain Transaction Agents libraries are designed for proxying transactions on Moonchain or other chains, allowing users to send contract transactions without paying gas fees.

![](/public/flow.png)

It consists of the following components:

- **Next Api Agents**: Servers that proxy the sending of transactions, reading the RPC address and private key from the .env file and broadcasting transaction requests to the network.
- **Contracts Utils**: Contracts used for proxying transactions, ensuring and verifying that transactions are sent only by the proxy or the user themselves.

## Install

```bash
pnpm install @moonchain/agents
```

## Add API route

Create a .env file with the following two parameters:

- **NETWORK_RPC**: Your Network RPC url
- **PRIVATE_KEY**: The private key address of the proxy

Configure routing in the `pages/api/agents` directory of your Next.js project. The API route will be used to send transactions to the proxy server.

```ts
// pages/api/agents/[...path].ts
import { TransactionAgents } from '@moonchain/agents'

export default TransactionAgents({
  NETWORK_RPC: process.env.NETWORK_RPC!,
  PRIVATE_KEY: process.env.PRIVATE_KEY!
})
// or
export default TransactionAgents({
  NETWORK_RPC: req => '...',
  PRIVATE_KEY: req => '...'
})
```

> Please ensure that the proxy's private key address has sufficient balance to cover transaction fees, and keep the private key secure to prevent theft.

## Contracts

The contracts are located in the `contracts` directory of this repository. You can reference them in your contract project using npm.

- **`ProxyForward.sol`**: A contract for proxying transactions, ensuring and verifying that transactions are sent only by the proxy or the user themselves.
- **`ProxyForwardUpgradeable.sol`**: A contract for proxying transactions that supports upgradeable contracts.

```solidity
import "@moonchain/agents/contracts/ProxyForward.sol";

contract Counter is ProxyForward {
  constructor(address _agent) ProxyForward(_agent) {}

  uint256 public count;

  function add(address sender, uint256 num) public proxy(sender) {
    count += num;
  }

  function sub(address sender, uint256 num) public proxy(sender) {
    count -= num;
  }
}
```

## Usage

This example uses the `Counter.sol` contract written above and utilizes the Agents Servers to proxy the sending of transactions.

```ts
import { agent, proof } from '@moonchain/agents'
import { Contract, JsonRpcProvider, Transaction, Wallet } from 'ethers'
import abi from './Counter.json'

const provider = new JsonRpcProvider('URL_ADDRESS')
const user = new Wallet('264a...3492', provider)
const counter = new Contract('COUNTER_ADDRESS', abi, user)

// 1. Assemble the transaction
const populateTransaction = await counter.add.populateTransaction(user.address, 10)

// 2. Get the signed message generated by the proxy server
const message = await proof(counter.add.fragment, populateTransaction)

/**
 * message
 *
 *
 * from: ...
 * contract: ...
 * method: 0xa9059cbb | add(uint256)
 * params:
 *   to: ...
 *   value: 400
 * nonce: 4673
 */

// 3. Sign the message with the user's private key
const signedMessage = await user.signMessage(message)

// 4. Send the transaction to the proxy server and get the transaction information
const transaction = await agent(counter.add.fragment, {
  ...populateTransaction,
  signature: signedMessage,
})

// 5. Wait for the transaction broadcast to complete
const receipt = await provider.waitForTransaction(transaction.hash)
```

## Limitations

Moonchain Transaction Agents do not support the direct sending of native tokens and are only applicable to contract-related transactions.

If you need to support the sending of ERC20 tokens, please modify the ERC20 contract to allow the proxy contract to perform user approvals.

```sol
import "@moonchain/agents/contracts/ProxyForward.sol";

contract ERC20 is ProxyForward {
  constructor(address _agent) ProxyForward(_agent) {}

  function approveProxy(address sender, address spender, uint256 amount) public proxy(sender) {
    _approve(sender, spender, amount);
  }
}
```