IAgent.getAgentIds

getAgentIds(
  address wallet,
  PageRequest pageRequest
) external view returns (uint256[] agentIds, PageResponse pageResponse)

에이전트 지갑을 기준으로 하는 페이지네이션 조회입니다. ERC-8004 에이전트 지갑이 wallet인 에이전트의 ID를 반환합니다. 에이전트 지갑은 register 시 등록자로 설정되고 setAgentWallet / unsetAgentWallet으로 바뀌며, 에이전트 NFT가 이전되면 해당 항목이 지워집니다. 따라서 어떤 주소가 소유한 에이전트 목록이 아닙니다. 소유 목록은 IdentityRegistry의 ERC-721 기능(balanceOf, Transfer 이벤트)으로 구합니다. IdentityRegistry 스토리지를 컨트랙트 내부에서 순회하는 비용이 너무 크기 때문에 Agent 프리컴파일이 이 메서드를 제공하며, 체인 측 인덱스에서 읽습니다. 등록, 에이전트 URI, 메타데이터, 에이전트 지갑, ERC-721 소유권은 0x8004000000000000000000000000000000000001의 ERC-8004 IdentityRegistry preinstall에 있으므로 직접 호출합니다. 레지스트리에는 attest나 revoke 함수가 없습니다.

파라미터

이름 타입 필수 설명
wallet address ✓ 조회할 지갑 주소입니다.
pageRequest tuple ✓ 표준 페이지네이션 튜플로 (bytes key, uint64 offset, uint64 limit, bool countTotal, bool reverse) 형식입니다. key와 offset 중 하나만 지정합니다. 둘 다 지정하면 QueryFailed로 revert됩니다. ABI 디코딩되지 않는 튜플은 ABISetupFailed로 revert됩니다.

반환값

타입: tuple

(uint256[] agentIds, PageResponse pageResponse)를 반환합니다. 마지막 페이지에 도달하면 pageResponse.nextKey가 비어 있습니다.

에러

코드 이름 설명
InvalidNumberOfArgs InvalidNumberOfArgs 공유 IPrecompile 오류 집합에 InvalidNumberOfArgs(uint256 expected, uint256 got)로 선언되어 있지만, getAgentIds는 인자 개수가 틀려도 이 오류로 revert되지 않습니다. calldata가 두 인자를 담기에 짧으면 ABISetupFailed로 revert되고, 두 인자 뒤에 붙은 바이트는 무시됩니다.
InvalidAddress InvalidAddress 공유 IPrecompile 오류 집합에 InvalidAddress(string bad)로 선언되어 있지만, wallet 인자에서는 발생하지 않습니다. wallet 자리의 32바이트 값은 상위 바이트가 0이 아니어도 그대로 디코딩되며, 조회에는 하위 20바이트가 쓰입니다.
InvalidPageRequest InvalidPageRequest 공유 IPrecompile 오류 집합에 InvalidPageRequest(string method, uint256 index, string value)로 선언되어 있지만, 잘못된 pageRequest는 이 오류를 반환하지 않습니다. ABI 디코딩되지 않는 튜플은 ABISetupFailed로, key와 offset을 모두 지정한 요청은 QueryFailed로 revert됩니다.
QueryFailed QueryFailed 체인 측 인덱스 조회가 실패하거나 요청을 거절할 때 revert됩니다. 예를 들어 pageRequest에 key와 offset을 모두 지정하면 사유가 invalid request, either offset or key is expected, got both입니다. QueryFailed(string queryMethod, string reason) 형태로 인코딩됩니다.
ABISetupFailed ABISetupFailed calldata를 프리컴파일 ABI로 디코딩할 수 없을 때 revert됩니다. 알 수 없는 4바이트 selector이면 사유가 no method with id: 0x…이고, 인자가 짧거나 ABI 디코딩되지 않으면 디코더의 메시지(예: abi: cannot marshal in to go type: length insufficient 32 require 64)가 사유가 됩니다. ABISetupFailed(string reason) 형태로 인코딩됩니다. 프리컴파일에 UnknownMethod도 선언되어 있지만, 알 수 없는 selector는 이 오류로 revert되지 않습니다.

예제

지갑의 모든 agent ID 페이지네이션

nextKey가 비게 될 때까지 반복하여 전체 목록을 수집합니다.

import { createPublicClient, http } from "viem";

const AGENT_PRECOMPILE = "0x100000000000000000000000000000000000000A" as const;
const agentAbi = [{
  type: "function", name: "getAgentIds", stateMutability: "view",
  inputs: [
    { name: "wallet", type: "address" },
    { name: "pageRequest", type: "tuple", components: [
      { name: "key",        type: "bytes"  },
      { name: "offset",     type: "uint64" },
      { name: "limit",      type: "uint64" },
      { name: "countTotal", type: "bool"   },
      { name: "reverse",    type: "bool"   },
    ]},
  ],
  outputs: [
    { name: "agentIds", type: "uint256[]" },
    { name: "pageResponse", type: "tuple", components: [
      { name: "nextKey", type: "bytes"  },
      { name: "total",   type: "uint64" },
    ]},
  ],
}] as const;

const publicClient = createPublicClient({ transport: http("https://rpc-testnet.maroo.io") });
// TODO: replace with the AGENT WALLET (IdentityRegistry.getAgentWallet(agentId)) before production —
// not the owner: the index is keyed by agent wallet. For the agents an address owns,
// use the registry's ERC-721 balanceOf / Transfer events.
const wallet = "0x8F3ac2B1d9E74c05A6B18FE27Dc4913e5A0F7b62";

let key: `0x${string}` = "0x";
const allIds: bigint[] = [];
do {
  const [ids, page] = await publicClient.readContract({
    address: AGENT_PRECOMPILE,
    abi: agentAbi,
    functionName: "getAgentIds",
    args: [wallet, { key, offset: 0n, limit: 100n, countTotal: false, reverse: false }],
  });
  allIds.push(...ids);
  key = page.nextKey as `0x${string}`;
} while (key !== "0x");

공유 IPrecompile 오류 디코드

잘못된 calldata는 ABISetupFailed로, 인덱스가 거절한 조회는 QueryFailed로 revert되므로 디코더에 두 오류를 모두 넣습니다. 나머지 항목은 공유 IPrecompile 시그니처이며, 예전의 별도 정의 InvalidArgsLength(method, got, want)는 사라졌습니다.

import { BaseError, ContractFunctionRevertedError, decodeErrorResult } from "viem";

const iPrecompileErrorsAbi = [
  { type: "error", name: "InvalidNumberOfArgs",
    inputs: [{ name: "expected", type: "uint256" }, { name: "got", type: "uint256" }] },
  { type: "error", name: "InvalidAddress", inputs: [{ name: "bad", type: "string" }] },
  { type: "error", name: "InvalidPageRequest",
    inputs: [
      { name: "method", type: "string"  },
      { name: "index",  type: "uint256" },
      { name: "value",  type: "string"  },
    ] },
  { type: "error", name: "QueryFailed",
    inputs: [{ name: "queryMethod", type: "string" }, { name: "reason", type: "string" }] },
  { type: "error", name: "ABISetupFailed", inputs: [{ name: "reason", type: "string" }] },
] as const;

try {
  await publicClient.readContract({
    address: AGENT_PRECOMPILE,
    abi: agentAbi,
    functionName: "getAgentIds",
    args: [wallet, { key: "0x", offset: 0n, limit: 100n, countTotal: false, reverse: false }],
  });
} catch (err) {
  // viem keeps the revert data on the ContractFunctionRevertedError in the cause chain, not on err.
  const revert = err instanceof BaseError ? err.walk((e) => e instanceof ContractFunctionRevertedError) : null;
  if (revert instanceof ContractFunctionRevertedError && revert.raw) {
    const decoded = decodeErrorResult({ abi: iPrecompileErrorsAbi, data: revert.raw });
    console.error("getAgentIds reverted:", decoded.errorName, decoded.args);
  } else {
    throw err;
  }
}
ESC
검색어를 입력하세요