Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ownafarm.xyz/llms.txt

Use this file to discover all available pages before exploring further.

Smart contract integration

WAGMI setup

import { createConfig, http } from "wagmi";
import { mantleSepoliaTestnet } from "wagmi/chains";

export const config = createConfig({
  chains: [mantleSepoliaTestnet],
  transports: {
    [mantleSepoliaTestnet.id]: http("https://rpc.sepolia.mantle.xyz"),
  },
});

Contract constants

const CONTRACTS = {
  GOLD_TOKEN: "0x787c8616d9b8Ccdca3B2b930183813828291dA9c",
  OWNAFARM_NFT: "0xC51601dde25775bA2740EE14D633FA54e12Ef6C7",
};

Read contract

import { useReadContract } from "wagmi";

const { data: invoices } = useReadContract({
  address: CONTRACTS.OWNAFARM_NFT,
  abi: OwnaFarmNFTABI,
  functionName: "getAvailableInvoices",
  args: [0n, 10n],
});

Write contract

import { useWriteContract } from "wagmi";
import { parseEther } from "viem";

const { writeContract } = useWriteContract();

// Approve + invest
await writeContract({
  address: CONTRACTS.GOLD_TOKEN,
  abi: GoldTokenABI,
  functionName: "approve",
  args: [CONTRACTS.OWNAFARM_NFT, parseEther("1000")],
});

await writeContract({
  address: CONTRACTS.OWNAFARM_NFT,
  abi: OwnaFarmNFTABI,
  functionName: "invest",
  args: [tokenId, parseEther("1000")],
});

Backend API

Base configuration

const API_BASE = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080";

async function fetchAPI(endpoint: string, options?: RequestInit) {
  const response = await fetch(`${API_BASE}${endpoint}`, {
    ...options,
    headers: {
      "Content-Type": "application/json",
      ...options?.headers,
    },
  });
  if (!response.ok) throw new Error("API error");
  return response.json();
}

Endpoints

EndpointMethodDescription
/auth/nonceGETGet nonce for wallet
/auth/loginPOSTLogin with signature

Go backend integration

Ethereum client

import (
    "github.com/ethereum/go-ethereum/ethclient"
    "github.com/ethereum/go-ethereum/common"
)

const RPC_URL = "https://rpc.sepolia.mantle.xyz"

func NewClient() (*ethclient.Client, error) {
    return ethclient.Dial(RPC_URL)
}

Read contract

func GetInvoice(tokenId int64) (*Invoice, error) {
    client, _ := NewClient()
    nft, _ := NewOwnaFarmNFT(common.HexToAddress(NFT_ADDRESS), client)

    invoice, err := nft.Invoices(nil, big.NewInt(tokenId))
    if err != nil {
        return nil, err
    }

    return &Invoice{
        Farmer:     invoice.Farmer,
        TargetFund: invoice.TargetFund,
        Status:     invoice.Status,
    }, nil
}

Event listening

func WatchInvestments(ctx context.Context) error {
    client, _ := NewClient()
    nft, _ := NewOwnaFarmNFT(common.HexToAddress(NFT_ADDRESS), client)

    sink := make(chan *OwnaFarmNFTInvested)
    sub, err := nft.WatchInvested(nil, sink, nil, nil)
    if err != nil {
        return err
    }
    defer sub.Unsubscribe()

    for {
        select {
        case event := <-sink:
            // Handle investment event
        case <-ctx.Done():
            return nil
        }
    }
}

Error handling

Contract errors

import { ContractFunctionExecutionError } from "viem";

try {
  await invest(tokenId, amount);
} catch (error) {
  if (error instanceof ContractFunctionExecutionError) {
    if (error.message.includes("InsufficientBalance")) {
      // Handle insufficient funds
    }
  }
}

API errors

CodeDescription
400Bad request
401Unauthorized
404Not found
429Rate limited
500Server error