이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
CPI(“크로스 프로그램 호출”)는 한 Solana 프로그램이 다른 프로그램을 호출하는 메커니즘입니다. Raydium의 대부분 프로그램은 Anchor CPI 래퍼 크레이트를 제공하여 호출 지점이 타입이 지정된 함수 호출처럼 보이게 하며, 검증된 필드 이름을 가진 계정 구조체와
cpi::<ix>() 헬퍼를 포함합니다. 이 페이지는 일반적인 패턴을 한 번 문서화한 후 프로그램별 차이점을 설명합니다. 실행 가능한 TypeScript는 각 제품 장의 code-demos 페이지를 참조하세요.어느 패턴이 어느 프로그램에 적용되는가
CPMM, CLMM 또는 LaunchLab을 통합하는 경우 먼저 일반 패턴을 읽은 후 프로그램의 섹션으로 이동하여 계정 목록과 차이점을 확인하세요. Farm v6과 AMM v4는 충분히 다르므로 해당 섹션을 독립적으로 읽을 가치가 있습니다.
Cargo 의존성
branch = "master"는 최신 게시된 소스를 추적합니다; 재현 가능한 빌드가 필요한 경우 특정 rev = "<commit>"으로 고정하세요. 프로토타이핑을 넘어서면 권장됩니다. master의 업스트림 계정 레이아웃 변경이 경고 없이 빌드를 깨뜨릴 수 있기 때문입니다.
cpi 기능 플래그는 크레이트가 전체 프로그램이 아닌 CPI 표면(계정 구조체 + 호출자)만 컴파일하도록 하므로 바이너리가 작게 유지됩니다.
anchor-lang / anchor-spl은 대상 크레이트가 고정한 것과 일치해야 하며, 2026-09 현재 두 공개 Raydium 크레이트는 일치하지 않습니다:
계정 구조체를 엔드투엔드로 연결하는 작동하는 CPI 예제는
raydium-io/raydium-cpi-example을 참조하세요(AMM v4, CPMM, CLMM 포함).
일반 Anchor CPI 패턴
이 섹션은 CPMM을 작동 예제로 엔드투엔드로 안내합니다:Accounts 구조체, CpiContext, cpi::<ix>(). CLMM은 동일한 형태를 따르며 다른 계정 목록과 남은 계정 요구사항이 있습니다. LaunchLab은 동일한 메커니즘을 따르지만 계정 목록에는 CPMM/CLMM과 동등한 계정이 없는 여러 계정(global_config, platform_config, event_authority, program)이 있으므로 이를 동일한 패턴이 아닌 동일한 형태로 취급하세요. 이 연습의 계정 목록이 직접 전달된다고 가정하지 말고 각 프로그램의 자체 섹션을 참조하세요.
계정 목록 구성
모든 Raydium CPI는 호출 프로그램의Accounts 구조체가 필요합니다. 필드는 당신의 명령이 필요한 모든 계정이며, 필드 수준 검증자가 있습니다. 선언 순서는 Raydium의 자체 명령 계정 순서와 일치할 필요가 없습니다. 당신의 자체 IDL 생성 클라이언트가 위치가 아닌 이름으로 주소를 지정하기 때문입니다:
UncheckedAccount입니다. 호출 프로그램은 사용자 ATA 및 자체 PDA와 같이 당신이 소유한 계정만 엄격히 검증합니다. /// CHECK: 문서 주석은 누락된 검사에 대한 Anchor의 경고를 억제합니다. Raydium 측 예외는 cpmm_program 자체입니다: Raydium이 내부적으로 검증하는 데이터 계정이 아니라 호출되는 프로그램이므로 Program<T>로 타입되고 수동 /// CHECK: 대신 Anchor의 자동 주소 확인을 받습니다. 이 대부분 UncheckedAccount 형태(Raydium이 자체 계정을 검증함)는 CLMM과 LaunchLab에서도 동일합니다. 이 예제는 두 민트가 모두 클래식 SPL 토큰이라고 가정합니다; 어느 쪽이든 Token-2022 민트일 수 있으면 token_program_2022: Program<'info, anchor_spl::token_2022::Token2022> 필드를 추가하고 아래 CPI 호출에서 token_program 대신 해당 쪽의 input_token_program/output_token_program으로 전달하세요.
CPI 호출 구성
Anchor는 명령당 하나의 헬퍼를 생성하며, CPI 계정 구조체(cpi::accounts::Swap, 아래에서 CpmmSwap으로 별칭)와 함께 생성합니다. 위의 자체 MyProxySwap 구조체와 달리 이 구조체의 필드 이름과 순서는 raydium-cp-swap의 자체 IDL에 의해 고정되며 정확히 일치해야 합니다:
cpi::swap_base_input은 IDL에서 생성됩니다; 인수 목록은 Anchor 명령의 인수 목록을 미러링합니다. 확인된 모든 Anchor 기반 Raydium 프로그램(CPMM, CLMM, LaunchLab)은 동일한 방식으로 cpi::<ix>() 헬퍼를 생성하며, 함수 이름은 스네이크 케이스의 명령 이름과 일치합니다. 이것이 Farm v6으로 확장되는지는 미확인입니다; 해당 섹션을 참조하세요.
서명자 시드(PDA 서명 CPI)
프로그램이 PDA를 대신하여 CPI에 서명할 때(금고, 에스크로 등에 일반적),CpiContext::new_with_signer를 사용하세요:
authority(또는 유사한 서명자 역할)로 전달된 모든 계정에 대해 Solana 런타임은 PDA가 이 시드를 통해 서명하는지 확인합니다.
남은 계정
일부 Raydium 명령은 남은 계정을 사용합니다. 고정 계정 후에 추가되는 가변 길이 목록입니다. Anchor의 CPI 헬퍼는 남은 계정을 타입 확인하지 않습니다;.with_remaining_accounts(...)를 통해 전달하세요:
- CLMM
SwapV2: 틱 배열, 방향으로 정렬됨. - Farm v6:
(reward_vault, user_reward_ata)쌍이지만 두 번째 보상 스트림부터만; 실제 거래를 디코딩하는 것이 보여주는 것을 Farm v6에서 참조하세요.
패턴 적용: CLMM
SwapV2는 위의 일반 패턴을 따르며 다른 계정 목록과 틱 배열에 대한 남은 계정 요구사항이 있습니다. 크레이트의 #[program] 모듈은 raydium_clmm으로 명명되며, 이는 또한 Rust use 경로입니다.
TickArrayNotFound로 되돌립니다(products/clmm/instructions에서 전체 계정 테이블과 오류 목록 참조). 가격 보행 방향으로 전달하세요: 스왑 방향의 첫 배열이 먼저입니다.
패턴 적용: LaunchLab
LaunchLab은 Anchor 기반이며 IDL 게시됨: 공개raydium-idl 저장소의 raydium_launchpad/raydium_launchpad.json. 해당 IDL의 내부 메타데이터 식별자는 raydium_launchpad이며, 제품의 대체 이름이 아닌 기본 프로그램의 기술 이름입니다. CPMM과 CLMM과 달리 프로그램의 자체 소스는 공개적으로 사용할 수 없습니다(reference/program-addresses 참조). Cargo가 가리킬 git = "..." 의존성이 없으며, 실제 크레이트의 Rust use 경로가 무엇인지 확인할 소스가 없습니다.
Anchor의 declare_program! 매크로를 사용하여 게시된 IDL에서 바인딩을 생성하세요. IDL JSON을 크레이트의 idls/raydium_launchpad.json으로 저장하세요(Cargo는 CARGO_MANIFEST_DIR에 상대적인 idls/ 디렉토리를 찾습니다). 그 다음 declare_program!(raydium_launchpad);는 프로그램 소스 없이 IDL에서 직접 raydium_launchpad::cpi::accounts::<Ix> 구조체와 cpi::<ix>() 함수를 생성합니다. 생성된 계정 구조체 이름은 항상 PascalCase의 명령 이름입니다(buy_exact_in → BuyExactIn), 필드 이름은 IDL의 계정 이름과 정확히 일치하며, 아래 MyProxyBuy에서 이미 사용된 동일한 계정 목록입니다.
CPI 형태는 일반 패턴을 따릅니다. 아래의 계정 목록과 인수는 products/launchlab/instructions.mdx가 아닌 온체인 IDL의 buy_exact_in 명령에서 나옵니다:
pool_state.migrate_type에 따라 CPMM 또는 AMM v4입니다. products/launchlab/accounts.mdx는 이것이 Initialize 시간에 설정된다고 말합니다. CPI 계정 목록은 둘 다에 대해 준비되어야 하거나 먼저 PoolState에서 migrate_type을 읽고 분기해야 합니다.
오류 전파
각 Anchor 기반 Raydium 프로그램은 자체 오류 열거형을 반환합니다; Anchor는 이를 래핑하므로 호출 프로그램은Err(ProgramError::Custom(code))로 표시됩니다. 특정 오류를 처리하려면:
raydium_clmm::error::ErrorCode 등). 오류 코드 번호는 IDL 정책(sdk-api/anchor-idl)에 따라 안정적이므로 숫자 값과 비교하여 특정 코드를 테스트할 수 있습니다. 전체 오류 테이블: CPMM, CLMM, AMM v4, Farm v6, LaunchLab.
구성된 CPI의 계산 예산
각 CPI 프레임에는 오버헤드가 있으며, 호출자의 자체 CU 소비가 당신의 것 위에 쌓이므로 프로그램 내부에서 Raydium으로 호출하는 거래는 200k CU 기본값에 의존하는 대신 명시적 계산 예산이 필요합니다.벤치마크가 아닌 단일 측정 데이터 포인트입니다. CPMM 스왑 CPI에 대한 일반적인 경험칙 추정(대략 1,500 CU CPI 오버헤드 + 150,000 CU 스왑 자체 + 10,000 CU 관찰 업데이트, ~161,500 CU 총)은 실제 사용을 크게 과대평가합니다. 실제 스왑 CPI(
my_proxy_swap이 swap_base_input을 호출, SPL 토큰 민트, 새로 생성된 2토큰 풀)는 ~47,700 CU 총을 소비했으며, connection.getTransaction(...).meta.computeUnitsConsumed에서 읽음. 이는 해당 추정의 약 3분의 1입니다. 이를 하나의 풀 형태와 하나의 민트 구성에서 나온 하나의 데이터 포인트로 취급하세요. 사양이 아닙니다. 문서에서 복사한 숫자가 아닌 자체 측정에서 크기를 조정한 명시적 ComputeBudgetProgram::set_compute_unit_limit(...) 명령을 항상 설정하세요. 기본 200k CU 제한은 조용히 소진되고 프로그램이 업그레이드되면서 명령당 비용이 변경됩니다.remaining_accounts를 통해 추가 틱 배열을 보행하여 배열당 CU를 추가). 하지만 위의 CPMM 수치만 측정된 값입니다. 항상 자체 측정에서 크기를 조정한 명시적 ComputeBudgetProgram::set_compute_unit_limit(...)을 설정하세요. 기본 200k CU 제한은 조용히 소진되고 프로그램이 업그레이드되면서 명령당 비용이 변경되기 때문입니다.
AMM v4: 수동 명령 구성
AMM v4는 Anchor 이전 시대이며 CPI 크레이트가 없어서 이 문서의 유일한 프로그램으로 위의 일반 패턴을 따르지 않습니다.Instruction을 수동으로 구성하세요:
products/amm-v4/code-demos를 참조하세요.
Farm v6
통합에 대한 옵션이라면 TS SDK를 사용하세요.raydium.farm.deposit(...)(products/farm-staking/code-demos 참조)은 실제 데모로 실행되며 이 프로그램에 대해 Rust Anchor 크레이트가 존재하는지 여부에 의존하지 않습니다.
어쨌든 Rust CPI가 필요한 경우, 예를 들어 다른 온체인 프로그램에서 구성하는 경우 AMM v4와 동일한 방식으로 Instruction을 수동으로 구성하세요: 실제 계정 목록과 명령 판별자를 독립적으로 파생시키세요. 예를 들어 SDK의 TypeScript 레이아웃(raydium-sdk-V2의 farm 모듈)을 디코딩하거나, 실제 거래를 직접 디코딩하거나(아래 참조), 배포된 프로그램을 덤프하고 분해합니다.
0 인수 명령 형태(수확 또는 청구 호출과 일치)의 경우 실제 계정 순서는 고정 접두사(token_program, 팜의 상태 계정, 금고 권한 PDA, 해당 PDA의 첫 번째 보상 금고, 두 번째 PDA, 호출자, 호출자의 첫 번째 보상 민트에 대한 ATA)이며, 그 다음 모든 보상 스트림 후의 (reward_vault_i, user_reward_ata_i) 쌍이 remaining_accounts에 있습니다. 페어링 규칙은 실제이지만 두 번째 보상 스트림부터만 시작됩니다: 첫 번째 스트림의 금고와 ATA는 고정 계정이며, 서로 인접하지 않으며, remaining_accounts의 일부가 아닙니다.
CPI 흐름 테스트
로컬 개발에는 Raydium 프로그램을 테스트 검증자에서 사용할 수 있어야 합니다. 세 가지 옵션:- 프로그램 클론을 사용한
anchor test. 배포된 메인넷 바이트코드를 로컬 검증자로 가져옵니다; 아래 로컬 검증자로 프로그램 클론에서Anchor.toml구성과 풀 생성 테스트를 특별히 방해하는 두 가지를 참조하세요. - Devnet. Raydium은 대부분 프로그램을 devnet에 배포하지만 모든 프로그램(CPMM, CLMM, AMM v4, Stable AMM, LaunchLab 각각 고유한 devnet 주소)에 대해 메인넷과 다른 프로그램 ID에서 배포합니다(
reference/program-addresses의 Devnet 테이블 참조). Farm v3/v5/v6은 devnet에서 안정적으로 게시되지 않습니다; 라이브 API(https://api-v3-devnet.raydium.io/main/info)는 현재 상황을 보여줍니다.raydium_clmm의 번들DEVNET_PROGRAM_ID상수(또는 다른 크레이트의 동등물)를 사용하는 경우 메인넷 ID도 devnet에서 작동한다고 가정하지 마세요. 올바른 주소를 얻으면anchor test --provider.cluster devnet을 실행하여 라이브 코드를 적중시키세요. - 로컬 배포. Raydium 저장소(CPMM, CLMM; LaunchLab의 소스는 이 옵션에 사용할 수 없음)를 클론하고 로컬 검증자에
anchor deploy하세요. 테스트 사이클 오버헤드를 추가하지만 디버깅을 위해 호출자를 수정할 수 있습니다.
anchor test로 실행하거나, 프로그램을 변경하지 않고 테스트 파일을 반복하는 경우 먼저 anchor build를 실행한 후 anchor test --skip-build를 실행하세요.
로컬 검증자로 프로그램 클론
reference/program-addresses는 여기의 모든 주소에 대한 진실의 원천입니다.
포인터
products/cpmm/code-demos,products/clmm/code-demos,products/amm-v4/code-demos,products/farm-staking/code-demos,products/launchlab/code-demos: 제품별 CPI 및 TypeScript 예제.sdk-api/anchor-idl: IDL 검색 및 클라이언트 재생성, LaunchLab의 IDL 코드젠 경로 포함.integration-guides/cpi-integration: 에스크로, 금고, 집계자 구성과 같은 상위 수준의 통합 패턴.
- raydium-cp-swap
- raydium-clmm
- raydium-idl: LaunchLab IDL (프로그램 소스 자체는 폐쇄됨)
- Anchor CPI 문서

