본문으로 건너뛰기

AppKit 요청·서명·잔액 조회

요청·서명·잔액 조회

request<T>(args)

활성 연결에 JSON-RPC 요청을 보냅니다. 직접 EVM 연결과 릴레이 연결을 같은 인터페이스로 라우팅합니다.

request<T = unknown>(args: RequestArgs): Promise<T>
파라미터필수설명
methodJSON-RPC 메서드
params아니요파라미터 배열
chainId아니요요청 대상 CAIP-2 체인 ID

반환: 지갑 또는 릴레이의 결과입니다. 릴레이 세션에서 체인 전환 메서드는 아무 작업도 하지 않고 undefined를 반환합니다.

오류: NOT_CONNECTED, UNSUPPORTED_METHOD, USER_REJECTED, RPC_ERROR, INVALID_RESPONSE, SESSION_TIMEOUT 또는 릴레이 전용 오류입니다. Solana 커넥터는 범용 요청에 UNSUPPORTED_METHOD를 반환하고, 기본 EVM 커넥터는 프로바이더 코드 4001을 USER_REJECTED로 정규화합니다.

const accounts = await appKit.request<string[]>({
method: "eth_accounts",
});

signTransferAuthorization(typedData, options?)

서버가 만든 EIP-3009 TransferWithAuthorization 구조화 데이터를 활성 지갑으로 서명하고, 검증된 서명을 r·s·v로 분리해 반환합니다. 단순 전달이 아니라 domain.verifyingContract 사전 검증, eth_signTypedData_v4 라우팅, 65바이트 서명 사후 검증, r·s·v 분리(v = yParity + 27)를 순서대로 수행합니다. 릴레이 세션이 활성이면 세션 채널로 서명을 요청합니다.

signTransferAuthorization(
typedData: Eip3009TypedData,
options?: { ref?: string },
): Promise<Eip3009Authorization>
파라미터필수설명
typedData서버가 만든 EIP-3009 구조화 데이터. SDK는 이 데이터를 만들지 않습니다.
options.ref아니요릴레이 연결에서 서명과 이후 recordTransaction 보고를 연결하는 임의의 참조값. 현재 주입형·직접 연결의 서명 이벤트에는 반영되지 않습니다

반환: signature와 분리된 r·s·v, 서명 대상 message, chainId, verifyingContract를 담은 Eip3009Authorization입니다.

오류: NOT_CONNECTED, USER_REJECTED. 사전·사후 검증 실패는 INVALID_CONFIG 또는 INVALID_RESPONSE로 나타납니다.

가스 대납은 SCOPE Connect 기능이 아닙니다

EIP-3009 가스 대납(가스리스 온체인 제출)은 SCOPE Connect가 제공하는 기능이 아닙니다. 구조화 데이터 생성, 반환 서명의 검증, 가스 대납·온체인 제출은 외부 서버(dApp의 자체 서버 또는 별도 결제 서비스)가 수행하며, SDK는 서명 결과까지만 반환합니다. dApp은 prepare → signTransferAuthorization → submit 순서로 자체 서버를 호출합니다. 아래 paymentServer는 외부 로직을 호출하는 방법을 보여 주는 예시입니다.

import { type Eip3009TypedData } from "@scope-connect/appkit";

const { typedData, chainIdHex } = await paymentServer.prepare({ paymentKey });

// 지갑을 구조화 데이터의 domain.chainId에 지정된 체인으로 전환합니다.
await appKit.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: chainIdHex }],
});

const auth = await appKit.signTransferAuthorization(
typedData as Eip3009TypedData,
{ ref: paymentKey },
);
await paymentServer.submit({ paymentKey, signature: auth.signature });

signSolanaTransaction(transactionBase64, options?)

서버가 만든 Solana 트랜잭션을 활성 Solana 지갑으로 서명합니다. SDK는 트랜잭션을 제출하거나 확정 상태를 추적하지 않습니다.

signSolanaTransaction(
transactionBase64: string,
options?: { ref?: string },
): Promise<SolanaSignedTransaction>
파라미터필수설명
transactionBase64서명할 직렬화 트랜잭션의 base64 문자열
options.ref아니요서명과 이후 트랜잭션 보고를 연결하는 임의의 참조값

반환: 슬롯별 서명과 재직렬화된 트랜잭션, 그리고 사용자 서명(userSignature)입니다. 사용자 서명만 필요하면 슬롯 규칙 대신 userSignature를 읽습니다 — SDK가 연결된 계정과 서명자 키를 대조해(키를 알 수 없으면 마지막 null이 아닌 슬롯으로) 데스크톱·모바일 경로 모두 같은 필드로 제공합니다. signatures는 트랜잭션의 서명자(fee payer 우선) 순서를 그대로 따릅니다 — 서버(relayer)가 fee payer로 slot 0을 partial-sign해 보낸 가스리스 트랜잭션에서는 첫 번째 null이 아닌 슬롯이 relayer 서명이고 사용자 서명은 그 다음 슬롯(slot 1)입니다. 사용자가 유일한 서명자일 때만 slot 0이 사용자 서명입니다. Phantom 모바일 경로에서는 signedTransactionnull일 수 있습니다.

오류: NOT_CONNECTED, UNSUPPORTED_METHOD, INVALID_CONFIG, USER_REJECTED, RPC_ERROR, INVALID_RESPONSE, BACKEND_ERROR, SESSION_TIMEOUT. 데스크톱 경로에는 선택적 peer인 @solana/web3.js가 필요합니다.

export async function signSolana(
transactionBase64: string,
): Promise<string | null> {
const result = await appKit.signSolanaTransaction(transactionBase64);
return result.signedTransaction;
}

getBalance(query)

SCOPE Connect 백엔드의 잔액 엔드포인트에서 토큰 또는 네이티브 잔액을 읽습니다. 생성자의 필수 clientId로 인증하며(백엔드 루트는 빌드 시점 고정), 체인 허용 목록은 적용되지 않습니다.

getBalance(
query: Omit<TokenBalanceQuery, "account"> & { account?: string },
): Promise<TokenBalance>
파라미터필수설명
chainId명시적 CAIP-2 체인 ID. 지갑의 활성 체인과 무관하게 조회합니다.
tokenAddressEVM 토큰 주소 또는 Solana mint. EVM 네이티브 자산은 0 주소를 사용합니다.
account조건부생략하면 현재 연결의 첫 주소를 사용합니다. 연결이 없으면 필수입니다.
decimals힌트 값. 응답의 decimals가 최종 값입니다.

반환: 원시 정수 raw, decimals, chainId.

오류: NOT_CONNECTED, INVALID_CONFIG, UNSUPPORTED_CHAIN, RPC_ERROR.

const balance = await appKit.getBalance({
chainId: "eip155:11155111",
tokenAddress: "0x0000000000000000000000000000000000000000",
account: "0x0000000000000000000000000000000000000001",
decimals: 18,
});

console.info(balance.raw, balance.decimals);

recordTransaction(detail?)

dApp이 완료 또는 정산을 직접 확인한 트랜잭션을 텔레메트리에 보고합니다. SDK가 트랜잭션을 제출하지 않으므로 보고 시점은 dApp이 결정합니다.

recordTransaction(detail?: {
method?: string;
txHash?: string;
chain?: string;
ref?: string;
}): void

반환: void. 텔레메트리가 꺼져 있거나 백엔드 설정이 없으면 아무 작업도 하지 않습니다. 전송 실패는 주 흐름에 전달되지 않습니다.

오류: 없음.

트랜잭션 해시를 받았다는 사실만으로 확정 완료를 보고하지 않습니다. 영수증 또는 결제 상태에서 완료를 확인한 뒤 호출합니다.

appKit.recordTransaction({
method: "evm_transfer",
txHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
chain: "eip155:11155111",
});

Solana 모바일 연결 복원

Phantom universal link 딥링크는 dApp 페이지를 리로드하므로, 진행 상태는 생성자에 주입한 solanaMobileStore에 영속화되고 리로드된 페이지에서 재개합니다. 브라우저용 localStorage 구현은 SDK가 createBrowserSolanaMobileStore() 함수로 제공합니다. 저장소를 주입하지 않으면 상태를 저장하지 않으므로 복귀 후 재개가 동작하지 않습니다. solanaMobileSession을 주입하지 않으면 오프라인 모의 세션을 사용하므로 운영 연결로 간주하지 않습니다.

hasPendingSolanaMobile()

hasPendingSolanaMobile(): boolean

저장된 모바일 연결 또는 서명 단계가 있으면 true를 반환합니다. true는 현재 페이지 로드가 딥링크 복귀라는 뜻입니다. 오류는 없습니다.

restoreSolanaMobileConnection()

restoreSolanaMobileConnection(): WalletConnection | null

콜백 전달이나 폴링 없이, 이미 완료된 모바일 연결 상태를 다시 활성화합니다. 저장 상태가 없거나 계정이 없으면 null입니다.

resumeSolanaConnect(returnParams)

resumeSolanaConnect(
returnParams: PhantomConnectReturnParams,
): Promise<WalletConnection>

저장 상태를 복원하고 콜백 값을 백엔드에 전달한 뒤 연결 결과를 폴링합니다. NOT_CONNECTED, USER_REJECTED, BACKEND_ERROR, WALLET_NOT_FOUND, SESSION_TIMEOUT, INVALID_RESPONSE가 발생할 수 있습니다.

resumeSolanaSignTransaction(returnParams)

resumeSolanaSignTransaction(
returnParams: PhantomSignTxReturnParams,
): Promise<SolanaSignedTransaction>

저장된 서명 단계를 복구해 서명 결과를 반환합니다. NOT_CONNECTED, USER_REJECTED, BACKEND_ERROR, SESSION_TIMEOUT, INVALID_RESPONSE가 발생할 수 있습니다.

resumeSolanaMobileFromCallback(query)

resumeSolanaMobileFromCallback(
query: URLSearchParams | string,
): Promise<SolanaMobileResumeResult>

저장된 단계를 판별하고 연결 또는 서명 복구를 한 번에 수행합니다.

type SolanaMobileResumeResult =
| { phase: "connect"; connection: WalletConnection }
| { phase: "sign"; signature: Hex; senderAddress: string }
| { phase: "none" };

phase: "none"은 재개할 영속 흐름이 없는 직접 방문을 뜻합니다.

const result = await appKit.resumeSolanaMobileFromCallback(
window.location.search,
);

if (result.phase === "connect") {
console.info(result.connection.account);
} else if (result.phase === "sign") {
console.info(result.signature, result.senderAddress);
}

유니버설 링크 연결 복원

일반 모바일 지갑의 유니버설 링크 연결은 지갑 앱을 열고 돌아오는 동안 페이지가 다시 로드될 수 있습니다. 생성자에 universalLinkStore를 지정하면 진행 중인 연결·서명 상태와 완료된 연결 정보를 복원할 수 있습니다.

hasPendingUniversalLink(): boolean

저장된 연결 또는 서명 요청이 진행 중이면 true를 반환합니다. 오류는 없습니다.

restoreUniversalLinkConnection()

restoreUniversalLinkConnection(): WalletConnection | null

완료된 연결 정보를 저장소에서 읽어 활성 연결로 복원합니다. 저장된 계정이 없으면 null을 반환하며 백엔드 폴링은 수행하지 않습니다.

resumeUniversalLink(): Promise<UniversalLinkResumeResult>

type UniversalLinkResumeResult =
| { phase: "none" }
| { phase: "connect"; connection: WalletConnection }
| { phase: "sign"; signature: string; senderAddress: string };

앱 복귀로 중단된 백엔드 결과 조회를 이어서 완료합니다. phase: "none"은 재개할 요청이 없다는 뜻입니다. 초기화 전에 호출하면 INVALID_CONFIG가 발생할 수 있으며, 결과 조회 과정에서는 USER_REJECTED, RPC_ERROR, SESSION_TIMEOUT, BACKEND_ERROR가 발생할 수 있습니다.

import {
AppKit,
createBrowserUniversalLinkStore,
} from "@scope-connect/appkit";

const appKit = new AppKit({
clientId: "ck_public_example",
universalLinkDappName: "Example dApp",
universalLinkStore: createBrowserUniversalLinkStore(),
});
appKit.init();

if (appKit.hasPendingUniversalLink()) {
const result = await appKit.resumeUniversalLink();
if (result.phase === "connect") {
console.info(result.connection.account);
} else if (result.phase === "sign") {
console.info(result.signature, result.senderAddress);
}
} else {
appKit.restoreUniversalLinkConnection();
}

연결 상태 속성

API타입설명
clientIdstring생성자에 전달한 공개 Client ID(필수 옵션이므로 항상 값이 있음)
connectionWalletConnection | null마지막으로 성공한 연결 스냅샷
accountCaip10AccountId | null기본 CAIP-10 계정
getAccounts()string[]승인된 원시 주소 배열의 복사본. 반환 배열을 변경해도 SDK 내부 상태에는 영향을 주지 않습니다. 미연결이면 빈 배열, Solana는 base58
initializedbooleaninit() 완료 여부
configAppKitConfig활성 설정의 복사본(현재 빈 객체). 반환 객체를 변경해도 SDK 내부 상태에는 영향을 주지 않습니다. 초기화 전 접근은 INVALID_CONFIG

connection은 프로바이더 이벤트를 자동 반영하는 실시간 스토어가 아닙니다.