본문으로 건너뛰기

요청 보내기

이 가이드를 완료하면 연결된 지갑이나 릴레이 세션에 JSON-RPC 요청을 전달하고, 응답 타입과 오류 처리를 일관되게 다룰 수 있습니다. 읽기 요청은 request<T>()로 처리하고, 서명은 서명에서 다룹니다.

사전 준비

  • AppKit 인스턴스를 만들고 init()을 호출합니다.
  • connect() · selectWallet() · pair() 중 하나로 연결을 먼저 수립합니다.
  • 아래 예제는 AppKit 설정에서 만든 appKit 인스턴스를 사용합니다.

1. request() 호출 형식과 RequestArgs

request<T>()RequestArgs를 받아 지갑의 응답을 제네릭 타입 T로 반환합니다. 반환 형식을 알고 있으면 request<string>(...)처럼 T를 지정해 타입을 좁힙니다.

request() 호출 형식
async request<T = unknown>(args: RequestArgs): Promise<T>

RequestArgs는 아래 세 필드를 받습니다. method는 필수이고, paramschainId는 선택입니다.

RequestArgs
interface RequestArgs {
method: string;
params?: unknown[];
chainId?: Caip2ChainId;
}

chainId는 릴레이 경로에서 요청을 어느 체인으로 보낼지 지정할 때 사용합니다. 주입형 EVM 연결에서는 이 값이 무시되고, 연결된 체인이 우선합니다.

제네릭 T는 TypeScript의 정적 타입만 좁히며 런타임 응답을 검증하지 않습니다. 사용자 정의 지갑이나 신뢰할 수 없는 응답은 dApp에서 별도로 검증합니다.

2. 읽기 요청 보내기

eth_chainId처럼 인자가 없는 요청은 method만 지정하면 됩니다.

체인 id 조회
const chainIdHex = await appKit.request<string>({
method: "eth_chainId",
});

console.log(chainIdHex); // 예: "0x1"

인자가 필요한 요청은 params 배열에 순서대로 넣습니다. 아래 예제는 계정의 nonce를 latest 블록 기준으로 조회합니다.

nonce 조회
const nonceHex = await appKit.request<string>({
method: "eth_getTransactionCount",
params: ["0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", "latest"],
});

params에는 메서드가 요구하는 원본 인자만 전달합니다. request<T>()는 메서드 의미를 해석하지 않고 그대로 전달하므로, 응답의 형태는 호출한 메서드와 지갑이 결정합니다.

3. 릴레이 연결로 요청 보내기

릴레이 연결에서는 로컬 JSON-RPC 프로바이더 대신 세션 채널로 요청이 전달됩니다. 이때 chainId가 있으면 해당 체인으로 전달하고, 생략하면 연결 시점에 지정된 체인을 사용합니다.

체인 관리 계열 RPC인 wallet_switchEthereumChainwallet_addEthereumChain은 릴레이 세션에서 아무 동작도 하지 않고 undefined를 반환합니다. 릴레이 세션이 아직 성립하지 않았으면 NOT_CONNECTED가 발생합니다.

노트

아무 작업도 하지 않고 반환하는 동작은 범용 request()에만 해당합니다. 전용 API인 addNetwork()은 릴레이·Klip A2A 연결에서 성공으로 처리하지 않고 UNSUPPORTED_METHOD를 던집니다 — 두 전송 방식 모두 연결 시점에 체인이 고정되기 때문입니다.

릴레이 요청 예시
const chainIdHex = await appKit.request<string>({
method: "eth_chainId",
chainId: "eip155:11155111",
});

4. 오류 처리

request<T>()는 연결이 없을 때 NOT_CONNECTED를 던집니다. 기본 EVM 커넥터와 릴레이 경로는 사용자 거부를 AppError(USER_REJECTED)로 정규화합니다. Solana 커넥터는 범용 JSON-RPC 요청을 지원하지 않으므로 UNSUPPORTED_METHOD를 던지며, 트랜잭션 서명에는 signSolanaTransaction()을 사용합니다. 그 밖의 실패는 RPC_ERROR, SESSION_TIMEOUT, INVALID_RESPONSE가 될 수 있고, 사용자 정의 커넥터나 직접 호출한 provider가 자체 오류를 전달할 수도 있습니다.

요청 오류 처리
import {
AppError,
AppResultCode,
isProviderRpcError,
USER_REJECTED_CODE,
} from "@scope-connect/appkit";

try {
const result = await appKit.request<string>({ method: "eth_chainId" });
} catch (error) {
if (error instanceof AppError) {
if (error.code === AppResultCode.NOT_CONNECTED) {
// 연결을 먼저 완료합니다.
} else if (error.code === AppResultCode.USER_REJECTED) {
// 기본 AppKit 경로에서 사용자가 요청을 거부했습니다.
}
} else if (isProviderRpcError(error) && error.code === USER_REJECTED_CODE) {
// 직접 프로바이더 또는 사용자 정의 커넥터가 원본 4001을 전달했습니다.
} else {
throw error;
}
}

AppResultCode와 프로바이더 오류의 전체 목록은 오류 처리에서 확인합니다.

5. 연결된 프로바이더 직접 호출

한 번의 요청에는 request<T>()로 충분하지만, 연결된 주입형 provider를 직접 호출해야 할 때는 getActiveProvider()를 사용합니다. 공개 타입이 보장하는 것은 request()뿐이므로, 이벤트 구독이 필요하면 별도의 런타임 검사를 두고 사용합니다.

활성 프로바이더 가져오기
const provider = appKit.getActiveProvider();

if (provider) {
const currentChain = await provider.request<string>({
method: "eth_chainId",
});

console.log(currentChain);
}

provider가 null이면 아직 연결되지 않았거나 EVM provider가 아닌 커넥터입니다. 이 경우는 request<T>()로 요청을 보내거나, 먼저 지갑 연결을 완료합니다.

다음 단계

  • 서명 — EVM 메시지·타입 데이터와 Solana 트랜잭션 서명
  • AppKit Connection — 연결 상태 조회와 네트워크 전환
  • AppKit APIrequest<T>()RequestArgs의 전체 정의
  • AppKit 오류 처리NOT_CONNECTED와 프로바이더 오류 코드