Integration
TypeScript SDK
A typed surface for every protocol primitive. ABIs and helpers you import from src/lib/contracts.ts and call through wagmi. No bespoke client to learn — your existing wagmi/viem app already knows how to use it.
Imports
import {
ABIS, // all 10 contract ABIs
DEPLOYMENTS, // per-chain addresses
addressOf, // resolver: addressOf("RepoVault", chainId) → Address | null
isDeployed, // convenience: any contract on this chain?
repoId, // keccak256("owner/name") → bytes32
didId, // keccak256(did) → bytes32
type ContractName,
} from "@/lib/contracts";
The ABIs are auto-exported from the Hardhat artifacts by contracts/scripts/export-abis.ts after every recompile.
Read a repo balance
Use wagmi's useReadContract with the exported ABI:
"use client";
import { useReadContract, useChainId } from "wagmi";
import { ABIS, addressOf, repoId } from "@/lib/contracts";
export function RepoTreasury({
owner,
name,
token,
}: { owner: string; name: string; token: `0x${string}` }) {
const chainId = useChainId();
const vault = addressOf("RepoVault", chainId);
const id = repoId(owner, name);
const { data: balance } = useReadContract({
address: vault ?? undefined,
abi: ABIS.RepoVault,
functionName: "balanceOf",
args: [id, token],
query: { enabled: vault !== null },
});
return <span>{balance?.toString() ?? "—"}</span>;
}
Write — link a repo
"use client";
import { useWriteContract, useChainId } from "wagmi";
import { ABIS, addressOf, repoId } from "@/lib/contracts";
import { keccak256, toBytes } from "viem";
export function LinkRepoButton({ owner, name }: { owner: string; name: string }) {
const chainId = useChainId();
const vault = addressOf("RepoVault", chainId);
const { writeContract, isPending } = useWriteContract();
function link() {
if (!vault) return;
writeContract({
address: vault,
abi: ABIS.RepoVault,
functionName: "linkRepo",
args: [
repoId(owner, name),
keccak256(toBytes(`splits:${owner}/${name}:v1`)),
],
});
}
return (
<button onClick={link} disabled={!vault || isPending}>
{isPending ? "Linking…" : "Link repo"}
</button>
);
}
This is the exact pattern the /app/connect wizard uses.
Identifier helpers
import { repoId, didId } from "@/lib/contracts";
repoId("acme", "date-fp");
// → "0x4f7a…" (keccak256("acme/date-fp"))
didId("did:gitsea:alice.eth");
// → "0x83b1…"
These match the off-chain bot/indexer conventions — every place that derives an id uses the same keccak256(utf8 string) recipe.
High-level client
For ergonomic reads, the @gitsea/sdk package wraps the ABI + address book into a GitSea client:
import { GitSea } from "@gitsea/sdk";
import { base } from "viem/chains";
const ga = new GitSea({ chain: base, transport: http() });
// Reads
const sheet = await ga.repo("acme/date-fp").balanceSheet();
sheet.equityUsd; // 4287.12
sheet.income.mrrUsd; // 87.40
sheet.creditLine.available; // 50_000n
const me = await ga.did("alice.eth").score();
me.score; // 812
me.grade; // "A+"
// Writes (with a wallet client)
await ga.repo("acme/date-fp").linkRepo({ splitsRoot });
await ga.creditLine(lineId).draw({ amount: 5_000n * 10n ** 18n });
await ga.market(prId, "merge").takePosition({ side: "yes", amount: 25n });
The client supports everything you can do with useReadContract / useWriteContract directly — it just gives you a typed, chainable surface.
Types
A few canonical types you'll see:
type RepoId = `0x${string}`;
type Did = `did:${string}`;
interface BalanceSheet {
equityUsd: number;
treasuryUsdc: bigint;
treasuryAsset: bigint;
income: { mrrUsd: number; perEpochUsd: number; sources: StreamSource[] };
creditLine: { available: bigint; drawn: bigint; dueBy: Date | null };
liabilities: Liability[];
lastEpoch: number;
}
interface Score {
score: number;
grade: "A+" | "A" | "B" | "C" | "D";
history: ScoreEvent[];
creditLine: { available: bigint; drawn: bigint };
}
Errors
All SDK methods throw typed GitSeaError instances:
try {
await ga.repo("acme/date-fp").credit.draw({ amount: huge, termDays: 30 });
} catch (e) {
if (e instanceof GitSeaError && e.code === "EXCEEDS_LINE") {
// max draw exceeded
}
}
Codes you'll see most:
NOT_LINKED,UNAUTHORIZED,INSUFFICIENT_BALANCE,EXCEEDS_LINE,OUT_OF_SCOPE(for agent UCANs),MARKET_CLOSED,BOUNTY_CLOSED,ALREADY_BID,ORACLE_PENDING.
Related
- Smart contracts — the underlying functions the SDK wraps.
- GitHub bot — for the same actions via PR comments.
- MCP for agents — same surface, MCP-formatted.
