GS2-Exchange SDK for Game Engine API Reference
Model
EzAwait
Exchange Await
Represents the execution state of an exchange that requires real-time to elapse before rewards can be claimed. Created when a player initiates an exchange with await timing type, and tracks the waiting period until the rewards become available. Supports skip functionality to shorten or eliminate the waiting time, and stores default configuration values for reward acquisition.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| userId | string | ✓ | ~ 128 chars | User ID | ||
| rateName | string | ✓ | ~ 128 chars | Exchange Rate Model name Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| name | string | ✓ | UUID | ~ 36 chars | Exchange Await name Maintains a unique name for each Exchange Await. The name is automatically generated in UUID (Universally Unique Identifier) format and used to identify each Exchange Await. | |
| skipSeconds | int | 0 | 0 ~ 2147483646 | Skip seconds The number of seconds to subtract from the waiting time. When skip seconds are applied, the acquirableAt timestamp is moved earlier by this amount. Used to implement mechanics where players can pay resources to speed up the waiting process. | ||
| config | List<EzConfig> | [] | 0 ~ 32 items | Default configuration values applied when obtaining rewards Key-value pairs used as transaction placeholder variables when the await completes and rewards are distributed. These values are set at the time of exchange initiation and applied to the acquire actions’ transaction parameters. | ||
| exchangedAt | long | Exchange time The timestamp when the exchange was initiated and the await was created. Used as the base time for calculating when rewards become available (acquirableAt = exchangedAt + lockTime - skipSeconds). | ||||
| acquirableAt | long | Time when rewards can be received The timestamp at which the waiting period expires and rewards become claimable. Calculated as exchangedAt + lockTime - skipSeconds. The player can call the acquire API once the current time has passed this timestamp. |
EzRateModel
Exchange Rate Model
Exchange Rate Model is an entity that defines the rate used to exchange one resource for another.
In addition to the rate at which a resource can be exchanged immediately, a rate can also be set at which a resource can be exchanged after a certain amount of time in real time has elapsed. Exchange rates that after a certain period of real time has elapsed can further define the resources required to perform an immediate exchange.
| Type | Condition | Required | Default | Value Limits | Description | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128 chars | Exchange Rate Model name Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||||||||
| metadata | string | ~ 2048 chars | Metadata Arbitrary values can be set in the metadata. Since they do not affect GS2’s behavior, they can be used to store information used in the game. | |||||||||
| timingType | String Enum enum { “immediate”, “await” } | “immediate” | Type of exchange Determines when rewards are delivered after performing the exchange. immediate delivers rewards instantly upon exchange execution. await requires real-time to elapse before rewards can be claimed, creating a waiting period (e.g., crafting time).
| |||||||||
| lockTime | int | {timingType} == “await” | ✓* | 0 ~ 538214400 | Waiting time (minutes) from the execution of the exchange until the reward is actually received Only applicable when timingType is await. Specifies the number of minutes that must elapse in real time after the exchange is initiated before the player can claim the rewards. The waiting time can be shortened by using the skip mechanism.* Required if timingType is “await” | |||||||
| verifyActions | List<EzVerifyAction> | [] | 0 ~ 10 items | List of Verify Actions Precondition checks that must all pass before the exchange is executed. If any verify action fails, the exchange is aborted without consuming resources. Used to enforce conditions such as level requirements or inventory capacity. | ||||||||
| consumeActions | List<EzConsumeAction> | [] | 0 ~ 10 items | List of Consume Actions Defines the resources (cost) that the player must pay to perform this exchange. Multiple consume actions can be specified, allowing complex exchange costs such as requiring both gold and items. These actions are executed as consume actions within a distributed transaction. | ||||||||
| acquireActions | List<EzAcquireAction> | [] | 0 ~ 100 items | List of Acquire Actions Defines the resources (rewards) that the player receives upon completing the exchange. Multiple acquire actions can be specified to grant various resource types simultaneously. These actions are executed as acquire actions within a distributed transaction. |
EzIncrementalRateModel
Incremental Cost Exchange Rate Model
Normal exchange rates always provide exchanges at a constant rate. With incremental exchange rates, you can define a rate that increases in cost as the number of exchanges increases. For example, the first exchange is performed at a rate of 1:1, but the second exchange is performed at a rate of 2:1. By defining such a rate, you can increase the value of the resources obtained by the player as the game progresses.
The number of exchanges can be reset after a certain period of real time has elapsed. This is useful for resetting the number of exchanges on a daily or weekly basis.
| Type | Condition | Required | Default | Value Limits | Description | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128 chars | Incremental Cost Exchange Rate Model name Incremental Cost Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphen (-), underscore (_), and period (.). | ||||||||||
| metadata | string | ~ 2048 chars | Metadata Arbitrary values can be set in the metadata. Since they do not affect GS2’s behavior, they can be used to store information used in the game. | |||||||||||
| calculateType | String Enum enum { “linear”, “power”, “gs2_script” } | ✓ | Calculation method for cost increase amount Determines how the exchange cost escalates with each exchange. linear calculates cost as baseValue + (coefficientValue * exchangeCount). power calculates cost as coefficientValue * (exchangeCount + 1)^2. gs2_script delegates the calculation to a custom GS2-Script for arbitrary logic.
| |||||||||||
| consumeAction | EzConsumeAction | ✓ | Consume Action (Quantity and Value are overwritten automatically) Defines the type of resource consumed as cost for the exchange. The actual quantity is calculated dynamically based on the exchange count and the calculation type (linear, power, or script). Only the action type and target resource need to be specified; the quantity field is overwritten automatically. | |||||||||||
| baseValue | long | {calculateType} == “linear” | ✓* | 0 ~ 9223372036854775805 | Base Value The initial cost for the first exchange when using the linear calculation type. The total cost is calculated as: baseValue + (coefficientValue * exchangeCount).* Required if calculateType is “linear” | |||||||||
| coefficientValue | long | {calculateType} in [“linear”, “power”] | ✓* | 0 ~ 9223372036854775805 | Coefficient Value The multiplier that controls how quickly costs escalate with each exchange. In linear mode, each exchange adds this value to the cost. In power mode, the cost is calculated as: coefficientValue * (exchangeCount + 1)^2.* Required if calculateType is “linear”,“power” | |||||||||
| exchangeCountId | string | ✓ | ~ 1024 chars | GS2-Limit Usage Limit Model GRN
for managing exchange execution counts References a GS2-Limit limit model that tracks how many times each user has performed this incremental exchange. The count is used to calculate the escalating cost and can be reset periodically (e.g., daily or weekly) using GS2-Limit’s reset timing. | ||||||||||
| maximumExchangeCount | int | 2147483646 | 0 ~ 2147483646 | Maximum number of exchanges The maximum number of times this incremental exchange can be performed by a user. Once the exchange count reaches this limit, further exchanges are denied until the count is reset via GS2-Limit. | ||||||||||
| acquireActions | List<EzAcquireAction> | [] | 0 ~ 100 items | List of Acquire Actions Defines the resources (rewards) that the player receives upon completing the incremental exchange. The rewards remain constant regardless of the exchange count; only the cost increases with each exchange. |
EzConfig
Configuration
Set values to be applied to transaction variables
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| key | string | ✓ | ~ 64 chars | Name | ||
| value | string | ~ 51200 chars | Value |
EzAcquireAction
Acquire Action
EzConsumeAction
Consume Action
EzVerifyAction
Verify Action
EzVerifyActionResult
Verify Action execution result
EzConsumeActionResult
Consume Action execution result
EzAcquireActionResult
Acquire Action execution result
EzTransactionResult
Transaction execution results
Result of a transaction executed using the server-side automatic transaction execution feature
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| transactionId | string | ✓ | 36 ~ 36 chars | Transaction ID | ||
| verifyResults | List<EzVerifyActionResult> | 0 ~ 10 items | List of verify action execution results | |||
| consumeResults | List<EzConsumeActionResult> | [] | 0 ~ 10 items | List of Consume Action execution results | ||
| acquireResults | List<EzAcquireActionResult> | [] | 0 ~ 100 items | List of Acquire Action execution results |
Methods
acquire
Claim the reward from a completed time-delayed exchange
Claims the reward from a time-delayed exchange after the required wait time has passed. If the wait time hasn’t elapsed yet, this call will fail — check the remaining time first using GetAwait. Once claimed, the await record is consumed and the player receives the reward defined in the rate model. For example, after waiting 3 hours for an “Iron Sword” to be crafted, calling this gives the player the sword.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| awaitName | string | ✓ | UUID | ~ 36 chars | Exchange Await name Maintains a unique name for each Exchange Await. The name is automatically generated in UUID (Universally Unique Identifier) format and used to identify each Exchange Await. |
Result
| Type | Description | |
|---|---|---|
| item | EzAwait | Exchange Await |
| transactionId | string | Issued transaction ID |
| stampSheet | string | Stamp sheet used to execute the reward acquisition process |
| stampSheetEncryptionKeyId | string | Cryptographic key GRN used for stamp sheet signature calculations |
| autoRunStampSheet | bool | Whether automatic transaction execution is enabled |
| atomicCommit | bool | Whether to commit the transaction atomically |
| transaction | string | Issued transaction |
| transactionResult | EzTransactionResult | Transaction execution result |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Await(
awaitName: "await-0001"
);
var result = await domain.AcquireAsync(
);
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). 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;
}
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). 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;
}deleteAwait
Cancel a pending time-delayed exchange
Deletes a pending exchange await record, effectively canceling the exchange. The reward will NOT be granted, and any resources already paid at the start of the exchange are NOT refunded. Use this when the player wants to cancel a pending craft or building order — make sure to show a confirmation dialog since the cost is not returned.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| awaitName | string | ✓ | UUID | ~ 36 chars | Exchange Await name Maintains a unique name for each Exchange Await. The name is automatically generated in UUID (Universally Unique Identifier) format and used to identify each Exchange Await. |
Result
| Type | Description | |
|---|---|---|
| item | EzAwait | Exchange Await |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Await(
awaitName: "await-0001"
);
var result = await domain.DeleteAwaitAsync(
); 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;
} 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();getAwait
Get a specific pending time-delayed exchange
Retrieves the details of a specific exchange await record. The returned information includes the exchange type, how many were requested, when it was started, and how much wait time remains. Use this to show a detail screen for a specific pending exchange — for example, “Crafting Iron Sword… 2h 30m remaining”.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| awaitName | string | ✓ | UUID | ~ 36 chars | Exchange Await name Maintains a unique name for each Exchange Await. The name is automatically generated in UUID (Universally Unique Identifier) format and used to identify each Exchange Await. |
Result
| Type | Description | |
|---|---|---|
| item | EzAwait | Exchange Await |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Await(
awaitName: "await-0001"
);
var item = await domain.ModelAsync(); 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; 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;
}Value change event handling
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Await(
awaitName: "await-0001"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Await(
awaitName: "await-0001"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); const auto Domain = Gs2->Exchange->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->Await(
"await-0001" // awaitName
);
// Start event handling
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::Exchange::Model::FAwait> value) {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
Domain->Unsubscribe(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
listAwaits
Get a list of pending time-delayed exchanges
Retrieves the player’s exchange await records — these are exchanges that require waiting before the reward can be claimed (like crafting or building). You can filter by rate name to show only awaits for a specific exchange type. Use this to build a “pending crafts” or “in-progress” list that shows the player what they’re waiting for and how much time is left.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| rateName | string | ~ 128 chars | Exchange Rate Model name Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | |||
| gameSession | GameSession | ✓ | GameSession | |||
| pageToken | string | ~ 1024 chars | Token specifying the position from which to start acquiring data |
Result
| Type | Description | |
|---|---|---|
| items | List<EzAwait> | List of Exchange Awaits |
| nextPageToken | string | Page token to retrieve the rest of the listing |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
var items = await domain.AwaitsAsync(
rateName: "material_n_to_r"
).ToListAsync(); 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;
}
} 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());
}Value change event handling
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
// Start event handling
var callbackId = domain.SubscribeAwaits(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeAwaits(callbackId); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
);
// Start event handling
var callbackId = domain.SubscribeAwaits(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeAwaits(callbackId); const auto Domain = Gs2->Exchange->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
);
// Start event handling
const auto CallbackId = Domain->SubscribeAwaits(
[]() {
// Called when an element of the list changes.
}
);
// Stop event handling
Domain->UnsubscribeAwaits(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
getRateModel
Get an exchange rate model by name
Retrieves a single exchange rate model by specifying its name. The returned information includes what the player needs to pay, what they receive, and whether it’s an instant exchange or requires waiting. Use this to display the details of a specific exchange — for example, showing “Cost: 100 Gold -> Reward: 1 Healing Potion” on a shop item detail screen.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| rateName | string | ✓ | ~ 128 chars | Exchange Rate Model name Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| item | EzRateModel | Exchange Rate Model |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).RateModel(
rateName: "character-level"
);
var item = await domain.ModelAsync(); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).RateModel(
rateName: "character-level"
);
var future = domain.ModelFuture();
yield return future;
var item = future.Result; 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;
}Value change event handling
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).RateModel(
rateName: "character-level"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).RateModel(
rateName: "character-level"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); const auto Domain = Gs2->Exchange->Namespace(
"namespace-0001" // namespaceName
)->RateModel(
"character-level" // rateName
);
// Start event handling
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::Exchange::Model::FRateModel> value) {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
Domain->Unsubscribe(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
listRateModels
Get a list of exchange rate models
Retrieves all exchange rate models registered in this namespace. A rate model defines an exchange recipe — what resources the player pays (e.g., 100 gold coins) and what they receive in return (e.g., 1 healing potion). There are two timing types: “immediate” exchanges happen instantly, while “await” exchanges require the player to wait a certain amount of time before claiming the reward (like crafting). Use this to build a shop or crafting UI that shows all available exchange options to the player.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| items | List<EzRateModel> | List of Exchange Rate Models |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
);
var items = await domain.RateModelsAsync(
).ToListAsync(); 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;
}
} 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());
}Value change event handling
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
);
// Start event handling
var callbackId = domain.SubscribeRateModels(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeRateModels(callbackId); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
);
// Start event handling
var callbackId = domain.SubscribeRateModels(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeRateModels(callbackId); const auto Domain = Gs2->Exchange->Namespace(
"namespace-0001" // namespaceName
);
// Start event handling
const auto CallbackId = Domain->SubscribeRateModels(
[]() {
// Called when an element of the list changes.
}
);
// Stop event handling
Domain->UnsubscribeRateModels(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
getIncrementalRateModel
Get an incremental cost exchange rate model by name
Retrieves a single incremental cost exchange rate model by specifying its name. The returned information includes the cost calculation method (linear formula or custom script), the base cost, the cost increase per exchange, the maximum number of exchanges allowed, and what the player receives. Use this to display the details of a specific incremental exchange — for example, showing “Stamina Refill: 30 gems (3rd purchase today, max 5)” on a shop screen.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| rateName | string | ✓ | ~ 128 chars | Incremental Cost Exchange Rate Model name Incremental Cost Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphen (-), underscore (_), and period (.). |
Result
| Type | Description | |
|---|---|---|
| item | EzIncrementalRateModel | Incremental Cost Exchange Rate Model |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).IncrementalRateModel(
rateName: "character-level"
);
var item = await domain.ModelAsync(); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).IncrementalRateModel(
rateName: "character-level"
);
var future = domain.ModelFuture();
yield return future;
var item = future.Result; 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;
}Value change event handling
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).IncrementalRateModel(
rateName: "character-level"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).IncrementalRateModel(
rateName: "character-level"
);
// Start event handling
var callbackId = domain.Subscribe(
value => {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
domain.Unsubscribe(callbackId); const auto Domain = Gs2->Exchange->Namespace(
"namespace-0001" // namespaceName
)->IncrementalRateModel(
"character-level" // rateName
);
// Start event handling
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::Exchange::Model::FIncrementalRateModel> value) {
// Called when the value changes
// The "value" is passed the value after the change.
}
);
// Stop event handling
Domain->Unsubscribe(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
listIncrementalRateModels
Get a list of incremental cost exchange rate models
Retrieves all incremental cost exchange rate models registered in this namespace. An incremental cost model defines an exchange where the price goes up each time the player uses it — for example, the first stamina refill costs 10 gems, the second costs 20 gems, the third costs 30 gems, and so on. The cost increase can be calculated using a simple linear formula (base + coefficient * count) or a custom script. Use this to build a UI that shows all available incremental exchanges and their current costs.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| items | List<EzIncrementalRateModel> | List of Incremental Cost Exchange Rate Models |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
);
var items = await domain.IncrementalRateModelsAsync(
).ToListAsync(); 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;
}
} 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());
}Value change event handling
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
);
// Start event handling
var callbackId = domain.SubscribeIncrementalRateModels(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeIncrementalRateModels(callbackId); var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
);
// Start event handling
var callbackId = domain.SubscribeIncrementalRateModels(
() => {
// Called when an element of the list changes.
}
);
// Stop event handling
domain.UnsubscribeIncrementalRateModels(callbackId); const auto Domain = Gs2->Exchange->Namespace(
"namespace-0001" // namespaceName
);
// Start event handling
const auto CallbackId = Domain->SubscribeIncrementalRateModels(
[]() {
// Called when an element of the list changes.
}
);
// Stop event handling
Domain->UnsubscribeIncrementalRateModels(CallbackId);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
exchange
Perform an exchange
Exchanges resources based on the specified rate model. The player pays the cost defined in the rate model and receives the reward — for example, trading 100 gold coins for 1 healing potion. You can specify a count to perform the same exchange multiple times at once (e.g., buy 5 potions for 500 gold). If the rate model uses “await” timing, this starts a time-delayed exchange instead of completing immediately (see the Await APIs for claiming the reward later).
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| rateName | string | ✓ | ~ 128 chars | Exchange Rate Model name Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| count | int | ✓ | 1 ~ 1073741821 | Number of exchanges | ||
| config | List<EzConfig> | [] | 0 ~ 32 items | Set values to be applied to transaction variables |
Result
| Type | Description | |
|---|---|---|
| item | EzRateModel | Exchange Rate Model |
| transactionId | string | Issued transaction ID |
| stampSheet | string | Stamp sheet used to execute the exchange process |
| stampSheetEncryptionKeyId | string | Cryptographic key GRN used for stamp sheet signature calculations |
| autoRunStampSheet | bool | Whether automatic transaction execution is enabled |
| atomicCommit | bool | Whether to commit the transaction atomically |
| transaction | string | Issued transaction |
| transactionResult | EzTransactionResult | Transaction execution result |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Exchange(
);
var result = await domain.ExchangeAsync(
rateName: "rate-0001",
count: 1,
config: null
);
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). 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;
}
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). 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;
}incrementalExchange
Perform an incremental cost exchange
Exchanges resources using a rate model where the cost goes up each time. The cost is automatically calculated based on how many times the player has already used this exchange — for example, the first stamina refill costs 10 gems, the second costs 20 gems, and so on. You can specify a count to perform multiple exchanges at once; the total cost will be the sum of each step’s price. Use this for mechanics like daily stamina refills, limited shop purchases, or anything where you want the price to escalate with repeated use.
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| rateName | string | ✓ | ~ 128 chars | Incremental Cost Exchange Rate Model name Incremental Cost Exchange Rate Model-specific name. Specified using alphanumeric characters, hyphen (-), underscore (_), and period (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| count | int | ✓ | 1 ~ 1073741821 | Number of exchanges | ||
| config | List<EzConfig> | [] | 0 ~ 32 items | Set values to be applied to transaction variables |
Result
| Type | Description | |
|---|---|---|
| item | EzIncrementalRateModel | Incremental Cost Exchange Rate Model |
| transactionId | string | Issued transaction ID |
| stampSheet | string | Stamp sheet used to execute the exchange process |
| stampSheetEncryptionKeyId | string | Cryptographic key GRN used for stamp sheet signature calculations |
| autoRunStampSheet | bool | Whether automatic transaction execution is enabled |
| atomicCommit | bool | Whether to commit the transaction atomically |
| transaction | string | Issued transaction |
| transactionResult | EzTransactionResult | Transaction execution result |
Implementation Example
var domain = gs2.Exchange.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Exchange(
);
var result = await domain.IncrementalExchangeAsync(
rateName: "rate-0001",
count: 1,
config: null
);
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). 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;
}
// In New Experience, stamp sheets are automatically executed at the SDK level.
// If an error occurs, a TransactionException is thrown.
// you can retry with TransactionException::Retry(). 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;
}