DELIVER_CURRENCY_GRANT
Credit a bought amount of Dragon Coins or Dragon Marks to an account
Metin2 only
Metin2 is the only game with a grantable account currency: account.cash (Dragon Coins) and
account.mileage (Dragon Marks) are columns its core applies in real time, which is why they
get grant types of their own instead of riding on item delivery. Lineage 2 has no equivalent, so
neither L2 family can advertise this capability, and its absence is never counted against an L2
connector.
{ "type": "m2.grant_cash", "schemaVersion": 1, "amount": 5000 }{ "type": "m2.grant_mileage", "schemaVersion": 1, "amount": 250 }These are the grant object inside the command payload — the envelope with commandId, orderId,
target and grant is documented on
DELIVER_ITEM_GRANT and is the same for every grant kind.
One difference in the envelope: target carries only normalizedAccountName. A Metin2 grant is
account-keyed, so there is no characterId and no character picker at purchase.
amount is a positive integer, at most 2147483647 — the columns are 32-bit.
One capability, two currencies
Both grant types advertise the same capability, because a base carries both columns and the two
statements differ only in the column they credit. Either [delivery.cash] or [delivery.mileage]
in portal.toml advertises it — so configure both unless your base has genuinely dropped one:
with only cash configured, the capability is still advertised and a Dragon Marks grant is then
refused at delivery with NO_DELIVERY_CONFIGURED_FOR_MILEAGE, returning the player's coins,
rather than being withheld at purchase.
What the answer means
A currency credit is applied, not queued: the core reflects the new balance without a relog, so
there is no settlement to wait for and QUEUED never appears here.
| Outcome | What happened |
|---|---|
APPLIED | The UPDATE matched the account row and committed |
ALREADY_APPLIED | A replay — the connector's journal recognised the commandId and credited nothing |
REFUSED / ACCOUNT_NOT_FOUND | The account row was not there to credit; the player's coins are released |
RETRYABLE_FAILURE | The statement failed; the gateway retries |
Implementing it
[delivery.cash] and [delivery.mileage] in portal.toml, with @account and @amount
available:
[delivery.cash]
sql = """
UPDATE {accountDb}.account SET cash = cash + @amount WHERE login = @account
"""
[delivery.mileage]
sql = """
UPDATE {accountDb}.account SET mileage = mileage + @amount WHERE login = @account
"""Never add your own idempotency
An UPDATE has no WHERE NOT EXISTS to make a replay harmless, so the connector wraps every
currency grant in its own journal — portal_grant_journal, created automatically in the account
database — and commits the journal row and the credit in one transaction. The statement must
stay a plain credit: a guard of your own that makes it match zero rows reads to the connector as
"no such account", and the grant is refused with ACCOUNT_NOT_FOUND instead of applied.
The delivery mechanics — the journal, the transaction, why a credit reports applied immediately — are described on Metin2 servers.
Revocation
There is none. A credited amount is the player's balance the moment it commits, and the game spends it from there — plan refunds around that.
Verification
Connector check credits 1 Dragon Coin and 1 Dragon Mark to the test account you designate — one of each, because the two currencies run different statements and proving one says nothing about the other. They are real credits, small enough to be noise, but real: use a test account, and confirm the balance moved in the game client once per base.