Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/agent/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,7 @@ Model: ${ctx.inference.getDefaultModel()}
args.agent_uri as string,
((args.network as string) || "mainnet") as any,
ctx.db,
ctx.config.rpcUrl,
);
return `Registered on-chain! Agent ID: ${entry.agentId}, TX: ${entry.txHash}`;
} catch (err: any) {
Expand Down Expand Up @@ -1435,9 +1436,10 @@ Model: ${ctx.inference.getDefaultModel()}
const limit = (args.limit as number) || 10;

// Phase 3.2: Pass db.raw for agent card caching
const rpcUrl = ctx.config.rpcUrl;
const agents = keyword
? await searchAgents(keyword, limit, network, undefined, ctx.db.raw)
: await discoverAgents(limit, network, undefined, ctx.db.raw);
? await searchAgents(keyword, limit, network, undefined, ctx.db.raw, rpcUrl)
: await discoverAgents(limit, network, undefined, ctx.db.raw, rpcUrl);

if (agents.length === 0) return "No agents found.";
return agents
Expand Down Expand Up @@ -1494,6 +1496,7 @@ Model: ${ctx.inference.getDefaultModel()}
comment,
network,
ctx.db,
ctx.config.rpcUrl,
);
return `Feedback submitted. TX: ${hash}`;
},
Expand Down
3 changes: 2 additions & 1 deletion src/conway/x402.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,10 @@ export async function getUsdcBalanceDetailed(
}

try {
const rpcUrl = process.env.AUTOMATON_RPC_URL || undefined;
const client = createPublicClient({
chain,
transport: http(undefined, { timeout: 10_000 }),
transport: http(rpcUrl, { timeout: 10_000 }),
});

const balance = await client.readContract({
Expand Down
12 changes: 7 additions & 5 deletions src/registry/discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,10 @@ export async function discoverAgents(
network: Network = "mainnet",
config?: Partial<DiscoveryConfig>,
db?: import("better-sqlite3").Database,
rpcUrl?: string,
): Promise<DiscoveredAgent[]> {
const cfg = { ...DEFAULT_DISCOVERY_CONFIG, ...config };
const total = await getTotalAgents(network);
const total = await getTotalAgents(network, rpcUrl);
const agents: DiscoveredAgent[] = [];

const overallStart = Date.now();
Expand All @@ -235,7 +236,7 @@ export async function discoverAgents(
}

try {
const agent = await queryAgent(i.toString(), network);
const agent = await queryAgent(i.toString(), network, rpcUrl);
if (agent) {
await enrichAgentWithCard(agent, cfg, db);
agents.push(agent);
Expand All @@ -247,7 +248,7 @@ export async function discoverAgents(
} else {
// totalSupply returned 0 (likely reverted) — fall back to Transfer event scanning
logger.info("totalSupply returned 0, falling back to Transfer event scanning");
const eventAgents = await getRegisteredAgentsByEvents(network, Math.min(limit, cfg.maxScanCount));
const eventAgents = await getRegisteredAgentsByEvents(network, Math.min(limit, cfg.maxScanCount), rpcUrl);

for (const { tokenId, owner } of eventAgents) {
if (Date.now() - overallStart > DISCOVERY_TIMEOUT_MS) {
Expand All @@ -257,7 +258,7 @@ export async function discoverAgents(

try {
// Try queryAgent first (gets tokenURI), fall back to event data only
const agent = await queryAgent(tokenId, network);
const agent = await queryAgent(tokenId, network, rpcUrl);
if (agent) {
// Use owner from event if queryAgent couldn't get it
if (!agent.owner && owner) {
Expand Down Expand Up @@ -347,8 +348,9 @@ export async function searchAgents(
network: Network = "mainnet",
config?: Partial<DiscoveryConfig>,
db?: import("better-sqlite3").Database,
rpcUrl?: string,
): Promise<DiscoveredAgent[]> {
const all = await discoverAgents(50, network, config, db);
const all = await discoverAgents(50, network, config, db, rpcUrl);
const lower = keyword.toLowerCase();

return all
Expand Down
41 changes: 29 additions & 12 deletions src/registry/erc8004.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ const TRANSFER_EVENT_TOPIC = keccak256(

type Network = "mainnet" | "testnet";

/**
* Resolve the RPC transport URL.
* Priority: explicit parameter > AUTOMATON_RPC_URL env var > viem default (public RPC).
*/
function resolveRpcUrl(rpcUrl?: string): string | undefined {
return rpcUrl || process.env.AUTOMATON_RPC_URL || undefined;
}

// ─── Preflight Check ────────────────────────────────────────────

/**
Expand All @@ -90,13 +98,14 @@ async function preflight(
functionName: string;
args: any[];
},
rpcUrl?: string,
): Promise<void> {
const contracts = CONTRACTS[network];
const chain = contracts.chain;

const publicClient = createPublicClient({
chain,
transport: http(),
transport: http(resolveRpcUrl(rpcUrl)),
});

// Encode calldata for accurate gas estimation
Expand Down Expand Up @@ -206,27 +215,29 @@ export async function registerAgent(
agentURI: string,
network: Network = "mainnet",
db: AutomatonDatabase,
rpcUrl?: string,
): Promise<RegistryEntry> {
const contracts = CONTRACTS[network];
const chain = contracts.chain;
const rpc = resolveRpcUrl(rpcUrl);

// Phase 3.2: Preflight gas check
await preflight(account, network, {
address: contracts.identity,
abi: IDENTITY_ABI,
functionName: "register",
args: [agentURI],
});
}, rpcUrl);

const publicClient = createPublicClient({
chain,
transport: http(),
transport: http(rpc),
});

const walletClient = createWalletClient({
account,
chain,
transport: http(),
transport: http(rpc),
});

// Call register(agentURI)
Expand Down Expand Up @@ -292,6 +303,7 @@ export async function updateAgentURI(
newAgentURI: string,
network: Network = "mainnet",
db: AutomatonDatabase,
rpcUrl?: string,
): Promise<string> {
const contracts = CONTRACTS[network];
const chain = contracts.chain;
Expand All @@ -302,12 +314,12 @@ export async function updateAgentURI(
abi: IDENTITY_ABI,
functionName: "setAgentURI",
args: [BigInt(agentId), newAgentURI],
});
}, rpcUrl);

const walletClient = createWalletClient({
account,
chain,
transport: http(),
transport: http(resolveRpcUrl(rpcUrl)),
});

const hash = await walletClient.writeContract({
Expand Down Expand Up @@ -352,6 +364,7 @@ export async function leaveFeedback(
comment: string,
network: Network = "mainnet",
db: AutomatonDatabase,
rpcUrl?: string,
): Promise<string> {
// Phase 3.2: Validate score range 1-5
if (!Number.isInteger(score) || score < 1 || score > 5) {
Expand All @@ -374,12 +387,12 @@ export async function leaveFeedback(
abi: REPUTATION_ABI,
functionName: "leaveFeedback",
args: [BigInt(agentId), score, comment],
});
}, rpcUrl);

const walletClient = createWalletClient({
account,
chain,
transport: http(),
transport: http(resolveRpcUrl(rpcUrl)),
});

const hash = await walletClient.writeContract({
Expand Down Expand Up @@ -409,13 +422,14 @@ export async function leaveFeedback(
export async function queryAgent(
agentId: string,
network: Network = "mainnet",
rpcUrl?: string,
): Promise<DiscoveredAgent | null> {
const contracts = CONTRACTS[network];
const chain = contracts.chain;

const publicClient = createPublicClient({
chain,
transport: http(),
transport: http(resolveRpcUrl(rpcUrl)),
});

try {
Expand Down Expand Up @@ -456,13 +470,14 @@ export async function queryAgent(
*/
export async function getTotalAgents(
network: Network = "mainnet",
rpcUrl?: string,
): Promise<number> {
const contracts = CONTRACTS[network];
const chain = contracts.chain;

const publicClient = createPublicClient({
chain,
transport: http(),
transport: http(resolveRpcUrl(rpcUrl)),
});

try {
Expand Down Expand Up @@ -538,13 +553,14 @@ async function estimateTotalByBinarySearch(
export async function getRegisteredAgentsByEvents(
network: Network = "mainnet",
limit: number = 20,
rpcUrl?: string,
): Promise<{ tokenId: string; owner: string }[]> {
const contracts = CONTRACTS[network];
const chain = contracts.chain;

const publicClient = createPublicClient({
chain,
transport: http(),
transport: http(resolveRpcUrl(rpcUrl)),
});

try {
Expand Down Expand Up @@ -647,13 +663,14 @@ export async function getRegisteredAgentsByEvents(
export async function hasRegisteredAgent(
address: Address,
network: Network = "mainnet",
rpcUrl?: string,
): Promise<boolean> {
const contracts = CONTRACTS[network];
const chain = contracts.chain;

const publicClient = createPublicClient({
chain,
transport: http(),
transport: http(resolveRpcUrl(rpcUrl)),
});

try {
Expand Down
1 change: 1 addition & 0 deletions src/setup/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ async function configureGeneral(config: AutomatonConfig): Promise<void> {
);
config.maxChildren = await askNumber("Max child automatons", config.maxChildren);
config.socialRelayUrl = (await askString("Social relay URL", config.socialRelayUrl)) || undefined;
config.rpcUrl = (await askString("RPC endpoint (Base chain, e.g. https://mainnet.base.org)", config.rpcUrl)) || undefined;

console.log("");
}
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export interface AutomatonConfig {
// Phase 2 config additions
soulConfig?: SoulConfig;
modelStrategy?: ModelStrategyConfig;
/** Custom RPC endpoint for Base chain interactions (overrides default public RPC) */
rpcUrl?: string;
}

export const DEFAULT_CONFIG: Partial<AutomatonConfig> = {
Expand Down
Loading