eths-git
Version:
**eths-git-remote** is a decentralized Git solution designed to manage repositories on-chain. It provides two main components:
130 lines (129 loc) • 5.07 kB
JavaScript
import { ethers, Contract } from "ethers";
import { getWallet } from "../../core/wallet/index.js";
import { ETHSFactoryAbi, ETHSRepoAbi, Networks } from "../../core/config/index.js";
/**
* ============================
* Common Helpers
* ============================
*/
function randomRPC(rpcs) {
return rpcs[Math.floor(Math.random() * rpcs.length)];
}
function getNetworkConfig(chainId) {
const config = Networks[chainId];
if (!config) {
throw new Error(`Unsupported chain ID: ${chainId}.`);
}
return config;
}
async function getSigner(chainId) {
const walletData = await getWallet();
const netConfig = getNetworkConfig(chainId);
const rpcUrl = randomRPC(netConfig.rpc);
const provider = new ethers.JsonRpcProvider(rpcUrl);
return new ethers.Wallet(walletData.privateKey, provider);
}
async function waitForTx(tx, action) {
const receipt = await tx.wait();
if (!receipt?.status) {
throw new Error(`❌ Transaction failed during: ${action} (tx: ${tx.hash})`);
}
return receipt;
}
function validateAddress(address, label = "address") {
if (!ethers.isAddress(address)) {
throw new Error(`Invalid ${label}: ${address}`);
}
}
async function getRepoContract(repoAddress, chainId) {
validateAddress(repoAddress, "repoAddress");
const signer = await getSigner(chainId);
return new Contract(repoAddress, ETHSRepoAbi, signer);
}
/**
* ============================
* Factory Contract Methods
* ============================
*/
export var Factory;
(function (Factory) {
async function createRepo(repoName, chainId) {
const signer = await getSigner(chainId);
const { hubAddress } = getNetworkConfig(chainId);
const factory = new Contract(hubAddress, ETHSFactoryAbi, signer);
const tx = await factory.createRepo(ethers.toUtf8Bytes(repoName));
const receipt = await waitForTx(tx, "createRepo");
const iface = new ethers.Interface(ETHSFactoryAbi);
for (const log of receipt.logs) {
try {
const parsed = iface.parseLog(log);
if (parsed?.name === "RepoCreated") {
return parsed.args.repo;
}
}
catch { /* skip */ }
}
throw new Error("Transaction succeeded but no 'RepoCreated' event found");
}
Factory.createRepo = createRepo;
async function getUserReposPaginated(chainId, start = 0, limit = 50) {
const signer = await getSigner(chainId);
const { hubAddress } = getNetworkConfig(chainId);
const userAddress = await signer.getAddress();
const factory = new Contract(hubAddress, ETHSFactoryAbi, signer);
const repos = await factory.getUserReposPaginated(userAddress, start, limit);
return repos.map((r) => ({
address: r.repoAddress,
name: ethers.toUtf8String(r.repoName),
creationTime: new Date(Number(r.creationTime) * 1000),
}));
}
Factory.getUserReposPaginated = getUserReposPaginated;
})(Factory || (Factory = {}));
/**
* ============================
* Repository Contract Methods
* ============================
*/
export var Repo;
(function (Repo) {
async function setDefaultBranch(repoAddress, chainId, branchName) {
const repo = await getRepoContract(repoAddress, chainId);
const tx = await repo.setDefaultBranch(ethers.toUtf8Bytes(branchName));
await waitForTx(tx, "setDefaultBranch");
}
Repo.setDefaultBranch = setDefaultBranch;
async function addPusher(repoAddress, chainId, account) {
validateAddress(account, "account");
const repo = await getRepoContract(repoAddress, chainId);
const tx = await repo.addPusher(account);
await waitForTx(tx, "addPusher");
}
Repo.addPusher = addPusher;
async function removePusher(repoAddress, chainId, account) {
validateAddress(account, "account");
const repo = await getRepoContract(repoAddress, chainId);
const tx = await repo.removePusher(account);
await waitForTx(tx, "removePusher");
}
Repo.removePusher = removePusher;
async function addMaintainer(repoAddress, chainId, account) {
validateAddress(account, "account");
const repo = await getRepoContract(repoAddress, chainId);
const tx = await repo.addMaintainer(account);
await waitForTx(tx, "addMaintainer");
}
Repo.addMaintainer = addMaintainer;
async function canPush(repoAddress, chainId, account) {
validateAddress(account, "account");
const repo = await getRepoContract(repoAddress, chainId);
return repo.canPush(account);
}
Repo.canPush = canPush;
async function canForcePush(repoAddress, chainId, refName, account) {
validateAddress(account, "account");
const repo = await getRepoContract(repoAddress, chainId);
return repo.canForcePush(account, ethers.toUtf8Bytes(refName));
}
Repo.canForcePush = canForcePush;
})(Repo || (Repo = {}));