> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-Exchange SDK for Game Engine API 레퍼런스

게임 엔진용 GS2-Exchange SDK의 모델 사양과 API 레퍼런스



## 모델

### EzAwait

교환 대기<br>

보상을 받기 전에 실시간의 경과가 필요한 교환의 실행 상태를 나타냅니다. 플레이어가 `await` 타이밍 타입의 교환을 시작했을 때 생성되며, 보상을 사용할 수 있게 될 때까지의 대기 기간을 추적합니다. 대기 시간을 단축하거나 없애는 스킵 기능을 지원하며, 보상 취득 시의 기본 설정값을 저장합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| userId | string |  | ✓ |  |  ~ 128자 | 사용자ID |
| rateName | string |  | ✓ |  |  ~ 128자 | 교환 레이트 모델 이름<br>교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| name | string |  | ✓ | UUID |  ~ 36자 | 교환 대기의 이름<br>교환 대기의 고유한 이름을 보유합니다.<br>이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 교환 대기를 식별하는 데 사용됩니다. |
| skipSeconds | int |  |  | 0 | 0 ~ 2147483646 | 스킵 초수<br>대기 시간에서 차감하는 초수입니다. 스킵 초수가 적용되면 acquirableAt 타임스탬프가 이만큼 앞당겨집니다. 플레이어가 리소스를 지불하여 대기 시간을 단축하는 구조를 구현하기 위해 사용됩니다. |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  |  | [] | 0 ~ 32 items | 보상 취득 시 적용하는 기본 설정값<br>대기 완료 시 보상이 배포될 때 트랜잭션의 플레이스홀더 변수로 사용되는 키와 값의 쌍입니다. 이 값들은 교환 시작 시 설정되며, 획득 액션의 트랜잭션 파라미터에 적용됩니다. |
| exchangedAt | long |  |  |  |  | 교환 시간<br>교환이 시작되어 대기가 생성된 타임스탬프입니다. 보상이 사용 가능해지는 시각을 계산하기 위한 기준 시각으로 사용됩니다(acquirableAt = exchangedAt + lockTime - skipSeconds). |
| acquirableAt | long |  |  |  |  | 보상을 받을 수 있게 되는 시간<br>대기 기간이 만료되어 보상을 받을 수 있게 되는 타임스탬프입니다. exchangedAt + lockTime - skipSeconds로 계산됩니다. 현재 시각이 이 타임스탬프를 지나면 플레이어는 취득 API를 호출할 수 있게 됩니다. |

**관련 메서드:**
acquire - 완료된 시간제 교환의 보상 수령
deleteAwait - 대기 중인 시간제 교환 취소
getAwait - 특정 대기 중인 시간제 교환 조회
listAwaits - 대기 중인 시간제 교환 목록 조회


---

### EzRateModel

교환 레이트 모델<br>

교환 레이트 모델은 리소스와 리소스를 교환할 때 사용하는 레이트를 정의하는 엔티티입니다.<br>

즉시 교환할 수 있는 레이트뿐만 아니라, 현실 시간으로 일정 시간이 경과한 후에 교환할 수 있는 레이트도 설정할 수 있습니다.<br>
현실 시간의 경과가 필요한 교환 레이트에는 즉시 교환을 실행하는 데 필요한 리소스를 추가로 정의할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 교환 레이트 모델 이름<br>교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 2048자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| timingType | 문자열 열거형<br>enum {<br>"immediate",<br>"await"<br>}<br> |  |  | "immediate" |  | 교환 종류<br>교환 실행 후 보상이 언제 전달되는지를 결정합니다. `immediate`는 교환 실행 시 즉시 보상을 전달합니다. `await`는 보상을 받기 전에 실시간의 경과가 필요하며, 대기 기간(예: 제작 시간)을 둡니다.immediate: 즉시 / await: 현실 시간의 경과 대기 /  |
| lockTime | int | {timingType} == "await" | ✓※ |  | 0 ~ 538214400 | 교환 실행부터 실제로 보상을 받을 수 있게 될 때까지의 대기 시간(분)<br>timingType이 `await`인 경우에만 적용됩니다. 교환이 시작된 후 플레이어가 보상을 받을 수 있게 되기까지 경과해야 하는 실시간 분수를 지정합니다. 대기 시간은 스킵 기능을 사용하여 단축할 수 있습니다.<br><br>※ timingType이(가) "await" 이면 필수 |
| verifyActions | [List&lt;EzVerifyAction&gt;](#ezverifyaction) |  |  | [] | 0 ~ 10 items | 검증 액션 리스트<br>교환이 실행되기 전에 모두 통과해야 하는 사전 조건 체크입니다. 검증 액션 중 하나라도 실패하면, 리소스를 소비하지 않고 교환이 중단됩니다. 레벨 요건이나 인벤토리 용량 등의 조건을 강제하기 위해 사용됩니다. |
| consumeActions | [List&lt;EzConsumeAction&gt;](#ezconsumeaction) |  |  | [] | 0 ~ 10 items | 소비 액션 리스트<br>이 교환을 실행하기 위해 플레이어가 지불해야 하는 리소스(코스트)를 정의합니다. 여러 개의 소비 액션을 지정할 수 있어, 골드와 아이템을 모두 필요로 하는 것과 같은 복잡한 교환 코스트를 구현할 수 있습니다. 이러한 액션은 분산 트랜잭션 내의 소비 액션으로 실행됩니다. |
| acquireActions | [List&lt;EzAcquireAction&gt;](#ezacquireaction) |  |  | [] | 0 ~ 100 items | 획득 액션 리스트<br>교환 완료 시 플레이어가 받는 리소스(보상)를 정의합니다. 여러 개의 획득 액션을 지정하여 다양한 리소스 타입을 동시에 지급할 수 있습니다. 이러한 액션은 분산 트랜잭션 내의 획득 액션으로 실행됩니다. |

**관련 메서드:**
getRateModel - 이름을 지정하여 교환 레이트 모델 조회
listRateModels - 교환 레이트 모델 목록 조회
exchange - 교환 실행


---

### EzIncrementalRateModel

코스트 상승형 교환 레이트 모델<br>

일반적인 교환 레이트는 항상 일정한 레이트로 교환을 제공합니다.<br>
상승형 교환 레이트에서는 교환 횟수에 따라 코스트가 상승하는 레이트를 정의할 수 있습니다.<br>
예를 들어, 첫 번째 교환에서는 1:1로 교환할 수 있지만, 두 번째 교환에서는 2:1로 교환하게 되는 것과 같은 레이트를 정의할 수 있습니다.<br>
이러한 레이트를 정의함으로써 플레이어가 게임을 진행함에 따라 얻을 수 있는 리소스의 가치를 높일 수 있습니다.<br>

교환 횟수는 현실 시간의 경과에 따라 리셋할 수 있습니다.<br>
이 기능을 이용하면 매일 또는 매주 교환에 필요한 코스트를 리셋할 수 있습니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| name | string |  | ✓ |  |  ~ 128자 | 코스트 상승형 교환 레이트 모델의 이름<br>코스트 상승형 교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| metadata | string |  |  |  |  ~ 2048자 | 메타데이터<br>메타데이터에는 임의의 값을 설정할 수 있습니다.<br>이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. |
| calculateType | 문자열 열거형<br>enum {<br>"linear",<br>"power",<br>"gs2_script"<br>}<br> |  | ✓ |  |  | 코스트 상승량 계산 방식<br>교환 횟수에 따라 코스트가 어떻게 상승하는지를 결정합니다. `linear`는 코스트를 baseValue +（coefficientValue × 교환 횟수）로 계산합니다. `power`는 코스트를 coefficientValue ×（교환 횟수 + 1）^2로 계산합니다. `gs2_script`는 임의의 로직을 위해 커스텀 GS2-Script에 계산을 위임합니다.linear: 베이스 값 + (계수 * 교환 횟수) / power: 계수 * (교환 횟수 + 1) ^ 2 / gs2_script: GS2-Script에 의한 임의의 로직 /  |
| consumeAction | [EzConsumeAction](#ezconsumeaction) |  | ✓ |  |  | 소비 액션 (수량/값은 자동으로 덮어써집니다)<br>교환 비용으로 소비되는 리소스의 종류를 정의합니다. 실제 수량은 교환 횟수와 계산 방식(선형, 거듭제곱, 스크립트)에 기반하여 동적으로 계산됩니다. 액션 종류와 대상 리소스만 지정하면 되며, 수량 필드는 자동으로 덮어써집니다. |
| baseValue | long | {calculateType} == "linear" | ✓※ |  | 0 ~ 9223372036854775805 | 베이스 값<br>`linear` 계산 방식을 사용하는 경우 첫 교환 시의 기본 코스트입니다. 합계 코스트는 baseValue +（coefficientValue × 교환 횟수）로 계산됩니다.<br><br>※ calculateType이(가) "linear" 이면 필수 |
| coefficientValue | long | {calculateType} in ["linear", "power"] | ✓※ |  | 0 ~ 9223372036854775805 | 계수<br>교환 횟수에 따라 코스트가 얼마나 빠르게 상승하는지를 제어하는 승수입니다. `linear` 모드에서는 각 교환마다 이 값이 코스트에 더해집니다. `power` 모드에서는 코스트가 coefficientValue ×（교환 횟수 + 1）^2로 계산됩니다.<br><br>※ calculateType이(가) "linear","power"이면 필수 |
| exchangeCountId | string |  | ✓ |  |  ~ 1024자 | 교환 실행 횟수를 관리하는 GS2-Limit의 횟수 제한 모델 GRN<br>각 사용자가 이 코스트 상승형 교환을 몇 번 실행했는지 추적하는 GS2-Limit의 횟수 제한 모델을 참조합니다. 카운트는 상승하는 코스트 계산에 사용되며, GS2-Limit의 리셋 타이밍을 사용하여 정기적으로(예: 매일 또는 매주) 리셋할 수 있습니다. |
| maximumExchangeCount | int |  |  | 2147483646 | 0 ~ 2147483646 | 교환 횟수 상한<br>사용자가 이 코스트 상승형 교환을 실행할 수 있는 최대 횟수입니다. 교환 횟수가 이 상한에 도달하면, GS2-Limit에 의한 카운트 리셋까지 이후의 교환이 거부됩니다. |
| acquireActions | [List&lt;EzAcquireAction&gt;](#ezacquireaction) |  |  | [] | 0 ~ 100 items | 획득 액션 리스트<br>코스트 상승형 교환 완료 시 플레이어가 받는 리소스(보상)를 정의합니다. 보상은 교환 횟수와 관계없이 일정하며, 코스트만 교환마다 증가합니다. |

**관련 메서드:**
getIncrementalRateModel - 이름을 지정하여 코스트 상승형 교환 레이트 모델 조회
listIncrementalRateModels - 코스트 상승형 교환 레이트 모델 목록 조회
incrementalExchange - 코스트 상승형 교환 실행


---

### EzConfig

컨피그 설정<br>

트랜잭션의 변수에 적용하는 설정 값

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| key | string |  | ✓ |  |  ~ 64자 | 이름 |
| value | string |  |  |  |  ~ 51200자 | 값 |

**관련 메서드:**
exchange - 교환 실행
incrementalExchange - 코스트 상승형 교환 실행


**관련 모델:**
EzAwait - 교환 대기



---

### EzAcquireAction

입수 액션

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 입수 액션에서 실행할 액션의 종류 |
| request | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |


**관련 모델:**
EzRateModel - 교환 레이트 모델
EzIncrementalRateModel - 코스트 상승형 교환 레이트 모델



---

### EzConsumeAction

소비 액션

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 소비 액션에서 실행할 액션의 종류 |
| request | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |


**관련 모델:**
EzRateModel - 교환 레이트 모델
EzIncrementalRateModel - 코스트 상승형 교환 레이트 모델



---

### EzVerifyAction

검증 액션

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 검증 액션에서 실행할 액션의 종류 |
| request | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |


**관련 모델:**
EzRateModel - 교환 레이트 모델



---

### EzVerifyActionResult

검증 액션 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 검증 액션에서 실행할 액션의 종류 |
| verifyRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드 |
| verifyResult | string |  |  |  |  ~ 1048576자 | 결과 내용 |


**관련 모델:**
EzTransactionResult - 트랜잭션 실행 결과



---

### EzConsumeActionResult

소비 액션 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 소비 액션에서 실행할 액션의 종류 |
| consumeRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드 |
| consumeResult | string |  |  |  |  ~ 1048576자 | 결과 내용 |


**관련 모델:**
EzTransactionResult - 트랜잭션 실행 결과



---

### EzAcquireActionResult

획득 액션 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| action | 문자열 열거형<br>enum {<br>}<br> |  | ✓ |  |  | 입수 액션에서 실행할 액션의 종류 |
| acquireRequest | string |  | ✓ |  |  ~ 524288자 | 액션 실행 시 사용되는 요청의 JSON 문자열 |
| statusCode | int |  |  |  | 0 ~ 999 | 상태 코드 |
| acquireResult | string |  |  |  |  ~ 1048576자 | 결과 내용 |


**관련 모델:**
EzTransactionResult - 트랜잭션 실행 결과



---

### EzTransactionResult

트랜잭션 실행 결과<br>

서버 사이드에서 트랜잭션 자동 실행 기능을 이용하여 실행된 트랜잭션의 실행 결과

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| transactionId | string |  | ✓ |  | 36 ~ 36자 | 트랜잭션 ID |
| verifyResults | [List&lt;EzVerifyActionResult&gt;](#ezverifyactionresult) |  |  |  | 0 ~ 10 items | 검증 액션의 실행 결과 목록 |
| consumeResults | [List&lt;EzConsumeActionResult&gt;](#ezconsumeactionresult) |  |  | [] | 0 ~ 10 items | 소비 액션의 실행 결과 목록 |
| acquireResults | [List&lt;EzAcquireActionResult&gt;](#ezacquireactionresult) |  |  | [] | 0 ~ 100 items | 획득 액션 실행 결과 리스트 |

**관련 메서드:**
acquire - 완료된 시간제 교환의 보상 수령
exchange - 교환 실행
incrementalExchange - 코스트 상승형 교환 실행


---

## 메서드

### acquire

완료된 시간제 교환의 보상 수령<br>

필요한 대기 시간이 경과한 시간제 교환의 보상을 수령합니다.<br>
대기 시간이 아직 경과하지 않은 경우, 이 호출은 실패합니다. 사전에 GetAwait로 남은 시간을 확인하세요.<br>
수령하면 대기 레코드는 소비되고, 플레이어는 레이트 모델에서 정의된 보상을 받습니다.<br>
예를 들어 "철검" 제작으로 3시간을 기다린 후 이를 호출하면 플레이어에게 검이 지급됩니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| awaitName | string |  | ✓| UUID |  ~ 36자 | 교환 대기의 이름<br>교환 대기의 고유한 이름을 보유합니다.<br>이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 교환 대기를 식별하는 데 사용됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzAwait](#ezawait) | 교환 대기|
| transactionId | string | 발행된 트랜잭션 ID|
| stampSheet | string | 보상 획득 처리 실행에 사용하는 스탬프 시트|
| stampSheetEncryptionKeyId | string | 스탬프 시트의 서명 계산에 사용한 암호화 키 GRN|
| autoRunStampSheet | bool | 트랜잭션 자동 실행이 활성화되어 있는지 여부|
| atomicCommit | bool | 트랜잭션을 원자적으로 커밋할지 여부|
| transaction | string | 발행된 트랜잭션|
| transactionResult | [EzTransactionResult](#eztransactionresult) | 트랜잭션 실행 결과|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    var result = await domain.AcquireAsync(
    );
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    var future = domain.AcquireFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Await(
        "await-0001" // awaitName
    );
    const auto Future = Domain->Acquire(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).me(game_session).await_(
        "await-0001"
    )

var async_result = await domain.acquire(
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### deleteAwait

대기 중인 시간제 교환 취소<br>

대기 중인 교환 대기 레코드를 삭제하여 교환을 취소합니다.<br>
보상은 지급되지 않으며, 교환 시작 시 지불한 리소스도 반환되지 않습니다.<br>
플레이어가 제작 중이거나 건설 중인 주문을 취소하고 싶을 때 사용합니다. 비용이 돌아오지 않으므로 확인 대화상자를 표시하는 것을 권장합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| awaitName | string |  | ✓| UUID |  ~ 36자 | 교환 대기의 이름<br>교환 대기의 고유한 이름을 보유합니다.<br>이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 교환 대기를 식별하는 데 사용됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzAwait](#ezawait) | 교환 대기|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    var result = await domain.DeleteAwaitAsync(
    );

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    var future = domain.DeleteAwaitFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Await(
        "await-0001" // awaitName
    );
    const auto Future = Domain->DeleteAwait(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).me(game_session).await_(
        "await-0001"
    )

var async_result = await domain.delete_await(
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### getAwait

특정 대기 중인 시간제 교환 조회<br>

특정 교환 대기 레코드의 상세 정보를 조회합니다.<br>
조회할 수 있는 정보에는 교환 타입, 요청한 수량, 시작 일시, 남은 대기 시간이 포함됩니다.<br>
특정 대기 중인 교환의 상세 화면을 표시할 때 사용합니다. 예를 들어 "철검 제작 중… 남은 시간 2시간 30분"과 같은 표시에 편리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| awaitName | string |  | ✓| UUID |  ~ 36자 | 교환 대기의 이름<br>교환 대기의 고유한 이름을 보유합니다.<br>이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 교환 대기를 식별하는 데 사용됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzAwait](#ezawait) | 교환 대기|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Await(
        "await-0001" // awaitName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).me(game_session).await_(
        "await-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Await(
        awaitName: "await-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Await(
        "await-0001" // awaitName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Exchange::Model::FAwait> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).me(game_session).await_(
        "await-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### listAwaits

대기 중인 시간제 교환 목록 조회<br>

플레이어의 교환 대기 레코드를 조회합니다. 보상을 받기 전에 대기가 필요한 교환(제작이나 건설과 같은 구조)의 목록입니다.<br>
레이트 이름을 지정하여 특정 교환 타입의 대기만 표시할 수도 있습니다.<br>
"제작 중인 아이템"이나 "진행 중" 목록을 구성하는 데 사용합니다. 플레이어가 무엇을 기다리고 있고 앞으로 얼마나 걸리는지를 표시할 수 있습니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| rateName | string |  | |  |  ~ 128자 | 교환 레이트 모델 이름<br>교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| pageToken | string |  | |  |  ~ 1024자 | 데이터 취득을 시작할 위치를 지정하는 토큰 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzAwait&gt;](#ezawait) | 교환 대기 목록|
| nextPageToken | string | 목록의 나머지를 취득하기 위한 페이지 토큰|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.AwaitsAsync(
        rateName: "material_n_to_r"
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Awaits(
        rateName: "material_n_to_r"
    );
    List<EzAwait> items = new List<EzAwait>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->Awaits(
        "material_n_to_r" // rateName
    );
    TArray<Gs2::UE5::Exchange::Model::FEzAwaitPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeAwaits(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeAwaits(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeAwaits(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeAwaits(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeAwaits(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeAwaits(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### getRateModel

이름을 지정하여 교환 레이트 모델 조회<br>

이름을 지정하여 교환 레이트 모델을 1건 조회합니다.<br>
조회할 수 있는 정보에는 플레이어가 지불하는 것, 받는 것, 즉시 교환인지 대기가 필요한지가 포함됩니다.<br>
특정 교환의 상세 정보를 표시할 때 사용합니다. 예를 들어 상점의 아이템 상세 화면에서 "비용: 골드 100 → 보상: 회복 포션 1개"와 같이 표시하는 데 편리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| rateName | string |  | ✓|  |  ~ 128자 | 교환 레이트 모델 이름<br>교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzRateModel](#ezratemodel) | 교환 레이트 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).RateModel(
        rateName: "character-level"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).RateModel(
        rateName: "character-level"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->RateModel(
        "character-level" // rateName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).rate_model(
        "character-level"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).RateModel(
        rateName: "character-level"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).RateModel(
        rateName: "character-level"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->RateModel(
        "character-level" // rateName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Exchange::Model::FRateModel> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).rate_model(
        "character-level"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### listRateModels

교환 레이트 모델 목록 조회<br>

이 네임스페이스에 등록되어 있는 모든 교환 레이트 모델을 조회합니다.<br>
레이트 모델은 교환 레시피를 정의합니다. 플레이어가 무엇을 지불하고(예: 골드 100개), 무엇을 받을지(예: 회복 포션 1개)를 설정합니다.<br>
타이밍에는 두 가지 종류가 있습니다. "즉시" 교환은 곧바로 완료되고, "대기" 교환은 플레이어가 일정 시간을 기다린 후 보상을 받습니다(제작과 같은 구조).<br>
상점이나 제작 UI를 구성할 때, 플레이어에게 이용 가능한 교환 옵션을 표시하는 데 사용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzRateModel&gt;](#ezratemodel) | 교환 레이트 모델 목록|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    var items = await domain.RateModelsAsync(
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    var it = domain.RateModels(
    );
    List<EzRateModel> items = new List<EzRateModel>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->RateModels(
    );
    TArray<Gs2::UE5::Exchange::Model::FEzRateModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeRateModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeRateModels(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeRateModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeRateModels(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeRateModels(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeRateModels(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### getIncrementalRateModel

이름을 지정하여 코스트 상승형 교환 레이트 모델 조회<br>

이름을 지정하여 코스트 상승형 교환 레이트 모델을 1건 조회합니다.<br>
조회할 수 있는 정보에는 코스트 계산 방법(선형 계산식 또는 커스텀 스크립트), 기본 코스트, 교환마다의 코스트 증가량, 최대 교환 횟수, 플레이어가 받는 것이 포함됩니다.<br>
특정 코스트 상승형 교환의 상세 정보를 표시할 때 사용합니다. 예를 들어 상점 화면에서 "스태미나 회복: 젬 30개(오늘 3회차, 최대 5회)"와 같이 표시하는 데 편리합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| rateName | string |  | ✓|  |  ~ 128자 | 코스트 상승형 교환 레이트 모델의 이름<br>코스트 상승형 교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzIncrementalRateModel](#ezincrementalratemodel) | 코스트 상승형 교환 레이트 모델|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).IncrementalRateModel(
        rateName: "character-level"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).IncrementalRateModel(
        rateName: "character-level"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->IncrementalRateModel(
        "character-level" // rateName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).incremental_rate_model(
        "character-level"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).IncrementalRateModel(
        rateName: "character-level"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).IncrementalRateModel(
        rateName: "character-level"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->IncrementalRateModel(
        "character-level" // rateName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Exchange::Model::FIncrementalRateModel> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).incremental_rate_model(
        "character-level"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### listIncrementalRateModels

코스트 상승형 교환 레이트 모델 목록 조회<br>

이 네임스페이스에 등록되어 있는 모든 코스트 상승형 교환 레이트 모델을 조회합니다.<br>
코스트 상승형 모델은 플레이어가 사용할 때마다 가격이 오르는 교환을 정의합니다. 예를 들어 스태미나 회복 1회차는 젬 10개, 2회차는 20개, 3회차는 30개…와 같은 구조입니다.<br>
코스트 상승은 단순한 선형 계산식(기본값 + 계수 × 횟수) 또는 커스텀 스크립트로 계산할 수 있습니다.<br>
이용 가능한 코스트 상승형 교환과 현재 코스트를 표시하는 UI를 구성하는 데 사용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| items | [List&lt;EzIncrementalRateModel&gt;](#ezincrementalratemodel) | 코스트 상승형 교환 레이트 모델 목록|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    var items = await domain.IncrementalRateModelsAsync(
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    var it = domain.IncrementalRateModels(
    );
    List<EzIncrementalRateModel> items = new List<EzIncrementalRateModel>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->IncrementalRateModels(
    );
    TArray<Gs2::UE5::Exchange::Model::FEzIncrementalRateModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeIncrementalRateModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeIncrementalRateModels(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeIncrementalRateModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeIncrementalRateModels(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeIncrementalRateModels(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeIncrementalRateModels(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### exchange

교환 실행<br>

지정한 교환 레이트 모델을 기반으로 리소스를 교환합니다.<br>
플레이어는 레이트 모델에서 정의된 비용을 지불하고 보상을 받습니다. 예를 들어 골드 100개를 회복 포션 1개와 교환하는 처리입니다.<br>
횟수를 지정하여 같은 교환을 한 번에 여러 번 실행할 수도 있습니다(예: 포션 5개를 골드 500개로 구매).<br>
레이트 모델이 "대기" 타이밍인 경우, 즉시 완료되지 않고 시간 대기형 교환이 시작됩니다(보상 수령은 Await 계열 API를 참조하세요).

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| rateName | string |  | ✓|  |  ~ 128자 | 교환 레이트 모델 이름<br>교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| count | int |  | ✓|  | 1 ~ 1073741821 | 교환 횟수 |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | | [] | 0 ~ 32 items | 트랜잭션 변수에 적용할 설정값 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzRateModel](#ezratemodel) | 교환 레이트 모델|
| transactionId | string | 발행된 트랜잭션 ID|
| stampSheet | string | 교환 처리 실행에 사용하는 스탬프 시트|
| stampSheetEncryptionKeyId | string | 스탬프 시트의 서명 계산에 사용한 암호화 키 GRN|
| autoRunStampSheet | bool | 트랜잭션 자동 실행이 활성화되어 있는지 여부|
| atomicCommit | bool | 트랜잭션을 원자적으로 커밋할지 여부|
| transaction | string | 발행된 트랜잭션|
| transactionResult | [EzTransactionResult](#eztransactionresult) | 트랜잭션 실행 결과|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Exchange(
    );
    var result = await domain.ExchangeAsync(
        rateName: "rate-0001",
        count: 1,
        config: null
    );
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Exchange(
    );
    var future = domain.ExchangeFuture(
        rateName: "rate-0001",
        count: 1,
        config: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Exchange(
    );
    const auto Future = Domain->Exchange(
        "rate-0001", // rateName
        1 // count
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).me(game_session).exchange(
    )

var async_result = await domain.exchange(
    "rate-0001", # rate_name
    1, # count
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---

### incrementalExchange

코스트 상승형 교환 실행<br>

사용할 때마다 코스트가 오르는 레이트 모델을 사용하여 리소스를 교환합니다.<br>
코스트는 플레이어가 지금까지 몇 번 교환했는지를 기반으로 자동 계산됩니다. 예를 들어 스태미나 회복 1회차는 젬 10개, 2회차는 20개…와 같이 올라갑니다.<br>
횟수를 지정하여 한 번에 교환할 수도 있습니다. 이 경우 합계 비용은 각 회차 가격의 합계가 됩니다.<br>
매일의 스태미나 회복, 횟수 한정 상점 등 반복 이용에 따라 가격을 올리고 싶은 구조에 사용합니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| rateName | string |  | ✓|  |  ~ 128자 | 코스트 상승형 교환 레이트 모델의 이름<br>코스트 상승형 교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| count | int |  | ✓|  | 1 ~ 1073741821 | 교환 횟수 |
| config | [List&lt;EzConfig&gt;](#ezconfig) |  | | [] | 0 ~ 32 items | 트랜잭션 변수에 적용할 설정값 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzIncrementalRateModel](#ezincrementalratemodel) | 코스트 상승형 교환 레이트 모델|
| transactionId | string | 발행된 트랜잭션 ID|
| stampSheet | string | 교환 처리 실행에 사용하는 스탬프 시트|
| stampSheetEncryptionKeyId | string | 스탬프 시트의 서명 계산에 사용한 암호화 키 GRN|
| autoRunStampSheet | bool | 트랜잭션 자동 실행이 활성화되어 있는지 여부|
| atomicCommit | bool | 트랜잭션을 원자적으로 커밋할지 여부|
| transaction | string | 발행된 트랜잭션|
| transactionResult | [EzTransactionResult](#eztransactionresult) | 트랜잭션 실행 결과|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Exchange(
    );
    var result = await domain.IncrementalExchangeAsync(
        rateName: "rate-0001",
        count: 1,
        config: null
    );
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Exchange.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Exchange(
    );
    var future = domain.IncrementalExchangeFuture(
        rateName: "rate-0001",
        count: 1,
        config: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    // New Experience에서는 스탬프 시트가 SDK 레벨에서 자동으로 실행됩니다.
    // 에러가 발생하면 TransactionException이 발생합니다.
    // TransactionException::Retry()로 재시도할 수 있습니다.

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Exchange->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Exchange(
    );
    const auto Future = Domain->IncrementalExchange(
        "rate-0001", // rateName
        1 // count
        // config
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```

**Godot**
```gdscript

var domain = ez.exchange.namespace_(
        "namespace-0001"
    ).me(game_session).exchange(
    )

var async_result = await domain.incremental_exchange(
    "rate-0001", # rate_name
    1, # count
    null # config
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

```


---



