@to-nexus/crossx-sdk-core
v0.0.0-beta.1
Published
CROSSx Core SDK - Vanilla JavaScript Embedded Wallet SDK
Maintainers
Readme
@to-nexus/crossx-sdk-core
CROSSx Embedded Wallet SDK — Clean Architecture + Hexagonal Architecture 기반
특징
- EIP-1193 Provider: ethers.js / viem / wagmi 와 바로 연동
- Clean Architecture: 순수 비즈니스 로직과 구현 분리
- 환경 독립적: Web / Node / React Native 모두 지원 가능
- Port & Adapters: 구현체를 교체해도 core 코드 변경 없음
- CAIP-2: 표준 체인 ID 형식 (
eip155:612044) - 트랜잭션 컨펌 모달: 서명/전송 전 사용자 승인 필수 (우회 불가)
설치
npm install @to-nexus/crossx-sdk-core빠른 시작
import { createCROSSxSDK, ChainId } from '@to-nexus/crossx-sdk-core';
const sdk = createCROSSxSDK({
receiptPolling: { intervalMs: 2000, timeoutMs: 60000 }, // 선택
});
await sdk.init();
const result = await sdk.signIn();
console.log('지갑 주소:', sdk.getAddress());백엔드 URL은
.env의VITE_*환경 변수로만 설정합니다.SDKConfig에 URL 필드를 추가하거나 직접 전달하지 마세요.
API 레퍼런스
초기화 & 인증
// SDK 초기화 (자동 로그인 복구 포함)
await sdk.init();
// 로그인 (OAuth popup)
const result = await sdk.signIn();
const result = await sdk.signIn({ provider: 'google' });
// 인증 상태 확인
sdk.isAuthenticated(); // boolean
sdk.getAddress(); // string | null
// 로그아웃
await sdk.signOut();
// 계정 탈퇴
await sdk.withdraw();지갑
// 지갑 생성 (로그인 후 지갑이 없을 때)
const { address } = await sdk.createWallet();
// 네이티브 잔액 조회
const { wei, formatted } = await sdk.getBalance('eip155:612044');
console.log(formatted); // "1.234567 CROSS"
// 현재 nonce 조회
const nonce = await sdk.getNonce('eip155:612044');트랜잭션 컨펌 모달
signTransaction() / sendTransaction() / sendTransactionAndWait() 호출 시 SDK가 자동으로 사용자 승인 모달을 표시합니다. DApp 개발자가 우회할 수 있는 공개 API는 없습니다.
import { CROSSxError, ErrorCode } from '@to-nexus/crossx-sdk-core';
try {
const result = await sdk.signTransaction(ChainId.CROSS_TESTNET, tx);
} catch (error) {
if (error instanceof CROSSxError && error.code === ErrorCode.USER_REJECTED) {
console.log('사용자가 취소했습니다');
}
}자세한 내용 → 트랜잭션 컨펌 모달 가이드
트랜잭션 서명 & 전송
const tx = {
from: sdk.getAddress()!,
to: '0x...',
value: '0x2386f26fc10000',
data: '0x',
chainId: 612044,
gasLimit: '0x5208',
maxFeePerGas: '0x77359400',
maxPriorityFeePerGas: '0x3b9aca00',
nonce: await sdk.getNonce('eip155:612044'),
};
// 서명만
const { signedTx, txHash } = await sdk.signTransaction('eip155:612044', tx);
// 전송 (status: 'pending' 즉시 반환)
const { txHash } = await sdk.sendTransaction('eip155:612044', tx);
// 전송 + Receipt 폴링 (블록 포함까지 대기)
const { txHash, receipt } = await sdk.sendTransactionAndWait('eip155:612044', tx);
console.log(receipt.status); // '0x1' = success, '0x0' = revertedReceipt 조회 & 폴링
// 단일 조회 (채굴 전이면 null)
const receipt = await sdk.getTransactionReceipt(txHash, 'eip155:612044');
// 채굴될 때까지 폴링
const receipt = await sdk.waitForTransaction(txHash, 'eip155:612044');
// 폴링 옵션 오버라이드
const receipt = await sdk.waitForTransaction(txHash, 'eip155:612044', {
intervalMs: 3000,
timeoutMs: 120000,
});EIP-1193 Provider
ethers.js, viem, wagmi 등과 연동하기 위한 표준 Provider입니다.
const provider = sdk.getProvider('eip155:612044');
// ethers.js
import { ethers } from 'ethers';
const ethersProvider = new ethers.BrowserProvider(provider);
const signer = await ethersProvider.getSigner();
await signer.sendTransaction({ to: '0x...', value: ethers.parseEther('0.01') });
// viem
import { createWalletClient, custom } from 'viem';
const client = createWalletClient({ transport: custom(provider) });범용 RPC 호출
/wallet/rpc 엔드포인트를 통해 노드에 직접 JSON-RPC 요청을 보냅니다.
// 네이티브 잔액
const balance = await sdk.rpcRequest('eth_getBalance', [address, 'latest'], 'eip155:612044');
// eth_call — ERC-20 balanceOf
const selector = '70a08231';
const padded = address.slice(2).padStart(64, '0');
const raw = await sdk.rpcRequest(
'eth_call',
[{ to: contractAddress, data: '0x' + selector + padded }, 'latest'],
'eip155:612044',
);
console.log(BigInt(raw).toString());
// Provider를 통한 동일 호출
const result = await provider.request({
method: 'eth_call',
params: [{ to: contractAddress, data: '0x' + selector + padded }, 'latest'],
});SDKConfig
const sdk = createCROSSxSDK({
/** OAuth 팝업 방식: 'popup' (기본) | 'modal' */
oauthDisplayMode: 'popup',
/** Mock 지갑 사용 여부 (개발/테스트용) */
useMockWallet: false,
/** 확인 모달 테마: 'light' (기본) | 'dark' */
theme: 'light',
/**
* 확인 모달 색상 커스터마이징 (light / dark 모드별 독립 오버라이드)
*/
themeTokens: {
light: {
primary: '#FF6B35', // 버튼·강조색 (기본: #019D92)
bg: '#F5F0EB', // 카드 배경색 (기본: #FFFFFF)
},
dark: {
primary: '#FF6B35',
bg: '#1A0A00', // 카드 배경색 (기본: #121212)
},
},
/** Receipt 폴링 기본값 */
receiptPolling: {
intervalMs: 2000, // 폴링 간격 (ms)
timeoutMs: 60000, // 최대 대기 시간 (ms)
},
/**
* 디버그 로그 출력 여부 (기본: true)
* ⚠️ 프로덕션 빌드에서는 이 값과 관계없이 항상 비활성화됩니다.
*/
debug: true,
});확인 모달 테마
| 방법 | 설명 |
|---|---|
| config.theme | 초기 테마 설정 ('light' 기본) |
| sdk.setTheme('dark') | 런타임 테마 전환 (themeTokens 오버라이드 유지) |
| config.themeTokens.light.* | 라이트 모드 Semantic 토큰 오버라이드 |
| config.themeTokens.dark.* | 다크 모드 Semantic 토큰 오버라이드 |
오버라이드 가능한 토큰: primary · secondary · onPrimary · borderDefault · borderSubtle · textPrimary · textSecondary · textTertiary · surfaceDefault · bg
자세한 내용은 컨펌 모달 & Prepare 플로우를 참고하세요.
체인 ID 상수
오타 방지를 위해 ChainId 상수를 사용하세요.
import { ChainId } from '@to-nexus/crossx-sdk-core';
await sdk.getBalance(ChainId.CROSS_TESTNET); // 'eip155:612044'
await sdk.getBalance(ChainId.CROSS_MAINNET); // 'eip155:612055'환경 변수
| 변수명 | 용도 | 필수 |
|---|---|---|
| VITE_WALLET_GATEWAY_URL | Wallet Gateway API URL | ✅ |
| VITE_OAUTH_SERVICE_URL | OAuth 서비스 URL | ✅ |
| VITE_AUTH_API_URL | 인증 API URL | ✅ |
공개 타입
import type {
SDKConfig,
ConfirmationTokenOverride, // themeTokens 타입 (light/dark 모드별 오버라이드)
ConfirmationThemeTokens, // 단일 모드 Semantic 토큰 타입
AuthResult,
EvmTransactionRequest,
TransactionResult,
TransactionWithReceipt, // sendTransactionAndWait() 반환 타입
TransactionReceipt, // waitForTransaction() 반환 타입
SignTransactionResult,
ChainIdValue,
} from '@to-nexus/crossx-sdk-core';관련 문서
라이센스
MIT
