솔라나 문서빠른 시작

지갑 연결

@solana-commerce/connector 패키지는 Wallet Standard를 기반으로 구축된 헤드리스 지갑 연결 기능을 제공합니다. 이 패키지는 지갑 검색, 연결 상태, 계정 관리 및 자동 재연결을 관리합니다. 프레임워크에 구애받지 않도록 설계되었으며 React 바인딩이 포함되어 있습니다. Solana Commerce Kit에서 원활하게 사용할 수 있도록 맞춤 제작되었으며 @solana/kitgill과 호환됩니다.

지갑 연결지갑 연결

설치

pnpm add @solana-commerce/connector

프로바이더 구성

ConnectorProvider

ConnectorProvider 컴포넌트는 애플리케이션을 감싸고 모든 하위 컴포넌트에 지갑 연결 상태를 제공합니다. 컴포넌트의 마운트/언마운트 주기 전반에 걸쳐 지속되는 싱글톤 ConnectorClient 인스턴스를 관리합니다.

Props

모든 구성은 config prop을 통해 전달됩니다:

  • config (ConnectorConfig, 선택 사항) - 커넥터에 대한 구성 객체입니다. 모든 필드는 선택 사항입니다.

ConnectorConfig

지갑 연결 동작에 대한 구성 객체입니다.

선택적 필드
  • autoConnect (boolean) - true로 설정하면 마운트 시 마지막으로 사용한 지갑에 자동으로 재연결됩니다. 지갑 기본 설정은 구성된 스토리지에 저장됩니다(기본값은 localStorage). 기본값: false.

  • debug (boolean) - 연결 흐름, 계정 변경 및 오류를 디버깅하기 위한 상세한 콘솔 로깅을 활성화합니다. 로그에는 [Connector][ConnectorProvider]와 같은 접두사가 포함됩니다. 기본값: false.

  • accountPollingIntervalMs (number) - 지갑이 standard:events 기능을 지원하지 않을 때 계정 변경을 확인하기 위한 폴링 간격(밀리초)입니다. 대부분의 최신 지갑은 이벤트를 지원하므로 폴링은 대체 수단입니다. 기본값: 1500 (1.5초).

  • storage (Storage) - 지갑 기본 설정을 저장하기 위한 커스텀 스토리지 어댑터입니다. 다음을 구현해야 합니다:

    • getItem(key: string): string | null
    • setItem(key: string, value: string): void
    • removeItem(key: string): void

    기본값: 사용 가능한 경우 window.localStorage(브라우저 전용). React Native(AsyncStorage) 또는 커스텀 SSR 안전 스토리지에 사용하세요.

프로바이더 아키텍처

프로바이더는 참조 카운팅을 사용하는 싱글톤 패턴을 사용합니다:

  • 여러 ConnectorProvider 인스턴스가 동일한 ConnectorClient를 공유합니다
  • 클라이언트는 첫 마운트 시 생성되고 언마운트 간에도 유지됩니다
  • 모든 프로바이더가 언마운트되면 빠른 재마운트를 처리하기 위해 정리가 5초 지연됩니다
  • 정리 중에는 지갑 연결이 해제되고 모든 이벤트 리스너가 제거됩니다

이 설계는 라우트 변경이나 컴포넌트 업데이트 중 지갑 연결 해제를 방지합니다.


useConnector()

지갑 연결 상태 및 액션에 접근하기 위한 주요 훅입니다. ConnectorProvider 내에서 사용해야 합니다.

다음을 포함하는 ConnectorSnapshot 객체를 반환합니다:

상태 속성

  • wallets (WalletInfo[]) - 발견된 모든 Wallet Standard 호환 지갑의 배열입니다. 지갑이 설치되거나 제거되면 자동으로 업데이트됩니다. 각 지갑에는 이름, 아이콘, 기능 등의 메타데이터가 포함됩니다. WalletInfo를 참조하세요.

  • selectedWallet (Wallet | null) - 현재 연결된 Wallet Standard 지갑 객체입니다. 연결 해제 시 null입니다. 이것은 Wallet Standard API의 원시 지갑 인스턴스입니다.

  • connected (boolean) - 연결 상태입니다. 지갑이 연결되고 계정을 사용할 수 있을 때 true입니다. 조건부 UI 렌더링에 사용하세요.

  • connecting (boolean) - 지갑 연결 중 로딩 상태입니다. select() 호출과 연결 결과 수신 사이에 true입니다. 로딩 표시기를 표시하거나 버튼을 비활성화하는 데 사용하세요.

  • accounts (AccountInfo[]) - 연결된 지갑의 계정 배열입니다. 대부분의 지갑은 하나의 계정을 제공하지만 일부는 여러 계정을 지원합니다. 지갑 이벤트 또는 폴링을 통해 자동으로 업데이트됩니다. AccountInfo를 참조하세요.

  • selectedAccount (string | null) - 현재 선택된 계정의 주소(base58 인코딩된 공개키)입니다. 지갑이 새 계정으로 연결되면 해당 계정이 자동으로 선택됩니다. 그렇지 않으면 이전에 선택된 계정이 유지됩니다.

액션 메서드

  • select ((walletName: string) => Promise<void>) - 이름으로 지갑에 연결합니다 (예: "Phantom", "Solflare"). 지갑 이름은 검색된 지갑의 name 필드와 정확히 일치해야 합니다.

    프로세스:

    1. connecting: true 설정
    2. 지갑의 standard:connect 기능 호출
    3. 지갑에서 계정 조회
    4. 지갑 이벤트 구독 (또는 이벤트를 사용할 수 없는 경우 폴링 시작)
    5. 구성된 스토리지에 지갑 환경설정 저장
    6. 계정 및 선택된 계정으로 상태 업데이트

    발생 예외: 지갑을 찾을 수 없거나, 지갑이 연결을 지원하지 않거나, 사용자가 연결을 거부한 경우 오류가 발생합니다.

  • disconnect (() => Promise<void>) - 현재 지갑 연결을 해제하고 모든 상태를 정리합니다.

    프로세스:

    1. 지갑 이벤트 구독 취소
    2. 계정 폴링 중지
    3. 가능한 경우 지갑의 standard:disconnect 기능 호출
    4. 선택된 지갑, 계정 및 선택된 계정 지우기
    5. 스토리지에서 지갑 환경설정 제거

    예외를 발생시키지 않습니다 (디버그가 활성화된 경우 오류가 기록됨).

  • selectAccount ((address: string) => Promise<void>) - 연결된 지갑의 다른 주소로 선택된 계정을 전환합니다. 주소가 현재 계정 배열에 없으면 업데이트된 계정을 가져오기 위해 재연결을 시작합니다.

    발생 예외: 연결된 지갑이 없거나 재연결 후 요청한 계정을 찾을 수 없는 경우 오류가 발생합니다.

useConnectorClient()

고급 사용 사례를 위해 기본 ConnectorClient 인스턴스에 대한 직접 액세스를 제공합니다.

반환값: ConnectorClient | null - 싱글톤 클라이언트 인스턴스, 또는 null (ConnectorProvider 외부에서 사용하는 경우).

사용 사례:

  • 명령형 상태 읽기를 위한 getConnectorState()에 대한 직접 액세스
  • 사용자 정의 상태 리스너를 위한 subscribe(listener)를 사용한 수동 구독
  • 강제 정리를 위한 destroy() 호출 (일반적인 사용에서는 권장하지 않음)

예시:

const client = useConnectorClient();
// Get current state without triggering re-render
const state = client?.getConnectorState();
// Subscribe to state changes manually
useEffect(() => {
if (!client) return;
const unsubscribe = client.subscribe((state) => {
console.log("Wallet state changed:", state);
});
return unsubscribe;
}, [client]);

타입 정의

WalletInfo

검색된 지갑에 대한 메타데이터입니다.

interface WalletInfo {
wallet: Wallet; // Raw Wallet Standard wallet object
name: string; // Display name (e.g., "Phantom", "Solflare")
icon?: string; // Data URL for wallet icon (base64 encoded)
installed: boolean; // Always true (only installed wallets are discovered)
connectable?: boolean; // Whether wallet supports required features
}

connectable 요구사항: 지갑이 다음을 지원할 때 연결 가능합니다:

  • standard:connect 기능
  • standard:disconnect 기능
  • Solana 체인 (wallet.chains"solana"가 포함되어 있는지로 감지)

연결 불가능한 지갑은 wallets 배열에 표시되지만 선택할 수 없습니다.

AccountInfo

지갑 계정에 대한 정보입니다.

interface AccountInfo {
address: string; // Base58-encoded public key
icon?: string; // Account-specific icon (data URL)
raw: WalletAccount; // Raw WalletAccount object from Wallet Standard
}

raw 필드는 추가 계정 속성에 대한 접근을 제공합니다:

  • address: string - Base58로 인코딩된 공개 키
  • publicKey: Uint8Array - 원시 공개 키 바이트
  • label?: string - 계정 레이블 (지갑이 제공하는 경우)
  • icon?: string - 계정별 아이콘 (데이터 URL)
  • chains: string[] - 이 계정이 지원하는 체인
  • features: string[] - 이 계정이 지원하는 기능

ConnectorSnapshot

useConnector()의 반환 타입으로, 상태와 액션을 결합합니다.

type ConnectorSnapshot = ConnectorState & {
select: (walletName: string) => Promise<void>;
disconnect: () => Promise<void>;
selectAccount: (address: string) => Promise<void>;
};
interface ConnectorState {
wallets: WalletInfo[];
selectedWallet: Wallet | null;
connected: boolean;
connecting: boolean;
accounts: AccountInfo[];
selectedAccount: string | null;
}

계정 변경 감지

커넥터는 지갑 계정이 변경될 때(사용자가 계정을 추가/제거하거나 지갑에서 계정을 전환할 때)를 자동으로 감지합니다. 두 가지 전략이 사용됩니다:

이벤트 기반 (권장)

지갑이 standard:events를 지원하는 경우, 커넥터는 change 이벤트를 구독합니다:

  • 계정이 변경될 때 실시간 알림을 수신
  • 더 효율적 (폴링 불필요)
  • 선택된 계정만 이벤트에 포함하는 지갑을 처리하기 위해 이벤트와 wallet.accounts의 계정을 집계

폴링 대체

이벤트가 지원되지 않는 경우, 커넥터는 wallet.accounts를 폴링합니다:

  • accountPollingIntervalMs마다 확인 (기본값: 1500ms)
  • 계정 주소를 비교하여 변경사항을 감지
  • 계정이 실제로 변경된 경우에만 재렌더링을 트리거

계정 선택 로직:

  • 계정이 변경될 때, 선택된 계정이 여전히 존재하는 경우 유지
  • 선택된 계정이 제거된 경우, 사용 가능한 첫 번째 계정을 선택
  • 새 계정(이전 계정에 없던)으로 연결할 때, 새 계정을 우선적으로 선택

저장소 & 자동 연결

저장소 지속성

커넥터는 구성된 저장소에 하나의 키를 저장합니다:

  • 키: arc-connector:lastWallet
  • 값: 지갑 이름 (예: "Phantom")

저장소 작업은 다음 상황을 처리하기 위해 try-catch로 래핑됩니다:

  • localStorage가 오류를 발생시키는 샌드박스 iframe
  • window가 정의되지 않은 SSR 환경
  • localStorage가 존재하지 않는 React Native

저장소가 실패하면 커넥터는 지속성 없이 계속 작동합니다(오류가 발생하지 않음).

자동 연결 동작

autoConnect: true인 경우:

  1. 마운트 시 저장소에서 마지막 지갑 이름을 읽습니다
  2. 100ms 대기 (지갑 등록 허용)
  3. 지갑이 발견되면 select(walletName)를 호출합니다
  4. 자동 연결이 실패하면 저장소에서 유효하지 않은 설정을 제거합니다

보안 참고사항: 저장된 설정은 지갑 이름(문자열)일 뿐 민감한 데이터가 아닙니다. 지갑은 자체 UI를 통해 인증/권한 부여를 처리합니다.


사용 예제

기본 지갑 버튼

import { ConnectorProvider, useConnector } from "@solana-commerce/connector";
function App() {
return (
<ConnectorProvider config={{ autoConnect: true }}>
<WalletButton />
</ConnectorProvider>
);
}
function WalletButton() {
const { wallets, select, disconnect, connected, accounts, connecting } =
useConnector();
if (!connected) {
return (
<div>
<h3>Connect Wallet</h3>
{wallets.map((wallet) => (
<button
key={wallet.name}
onClick={() => select(wallet.name)}
disabled={!wallet.connectable || connecting}
>
{wallet.icon && (
<img src={wallet.icon} alt={wallet.name} width={24} />
)}
{wallet.name}
{!wallet.connectable && " (Unsupported)"}
</button>
))}
</div>
);
}
return (
<div>
<p>Connected: {accounts[0]?.address.slice(0, 8)}...</p>
<button onClick={disconnect}>Disconnect</button>
</div>
);
}

다중 계정 선택기

function AccountSelector() {
const { accounts, selectedAccount, selectAccount } = useConnector();
if (accounts.length <= 1) return null;
return (
<select
value={selectedAccount || ""}
onChange={(e) => selectAccount(e.target.value)}
>
{accounts.map((account) => (
<option key={account.address} value={account.address}>
{account.raw.label || `${account.address.slice(0, 8)}...`}
</option>
))}
</select>
);
}

연결 모니터링

function ConnectionMonitor() {
const { connected, selectedWallet, accounts } = useConnector();
useEffect(() => {
if (connected) {
console.log("Wallet connected:", selectedWallet?.name);
console.log(
"Accounts:",
accounts.map((a) => a.address)
);
}
}, [connected, selectedWallet, accounts]);
return null;
}

지원되는 지갑

Wallet Standard를 구현하는 모든 지갑을 지원하며, 다음을 포함합니다:

  • Phantom
  • Solflare
  • Backpack
  • Glow
  • Brave Wallet
  • Coinbase Wallet
  • 기타 Wallet Standard 호환 지갑

지갑은 Wallet Standard API에 등록되면 자동으로 발견됩니다(구성 불필요).


Headless 사용법 (React 없이)

React가 아닌 애플리케이션이나 서버 측 사용을 위해 ConnectorClient를 직접 사용하세요:

import { ConnectorClient } from "@solana-commerce/connector";
const connector = new ConnectorClient({
autoConnect: true,
debug: true
});
// Get current state
const state = connector.getConnectorState();
console.log("Available wallets:", state.wallets);
// Connect to a wallet
await connector.select("Phantom");
// Subscribe to state changes
const unsubscribe = connector.subscribe((state) => {
console.log("Connected:", state.connected);
console.log("Accounts:", state.accounts);
});
// Switch account
await connector.selectAccount("account-address-here");
// Disconnect
await connector.disconnect();
// Cleanup (removes all listeners and timers)
connector.destroy();

참고: ConnectorClient는 자체 상태를 관리하며 React 리렌더링을 트리거하지 않습니다. 상태 변경을 수동으로 구독해야 합니다.

Is this page helpful?

관리자

© 2026 솔라나 재단.
모든 권리 보유.
연결하기