Skip to content
2 changes: 1 addition & 1 deletion docs/01-getting-started/04-using-the-enjin-platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ There are two ways to receive the transaction status and information:
- [Receive Transaction Information Using the Platform User Interface](#receive-transaction-information-using-the-platform-user-interface)
- [Receive Transaction Information Using the Enjin API / SDKs](#receive-transaction-information-using-the-enjin-api--sdks)

For real-time, push-based notifications, see [WebSocket Events](/03-api-reference/03-websocket-events.md) — planned, not yet available.
You can also receive real-time, push-based notifications over WebSocket instead of polling — see [WebSocket Events](/03-api-reference/03-websocket-events.md).

### Receive Transaction Information Using the Platform User Interface

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ The user stays in control: they can disconnect your application from their Enjin

### Step 3: Confirm the link

Run the `GetLinkedWallet` query with the same `idempotencyKey` you used when creating the linking code. Once the user has approved, it returns the linked wallet; until then (or if the user has disconnected), it returns `null`.
Run the `GetLinkedWallet` query with the same `idempotencyKey` you used when creating the linking code. Once the user has approved, it returns the linked wallet; until then (or if the user has disconnected), it returns `null`. To catch the approval the moment it happens instead of checking repeatedly, subscribe to the [`WalletLinked`](/03-api-reference/03-websocket-events.md#walletlinked) WebSocket event — it fires with this same `idempotencyKey` and the linked wallet's `publicKey`.

<Tabs>
<TabItem value="graphql" label="GraphQL">
Expand Down Expand Up @@ -358,8 +358,8 @@ print(response.json())

Store the returned `publicKey` against the user's record in your database — it identifies the wallet the user linked, and it's the account you'll target with transaction requests. The hex public key and the SS58-encoded address (`ef...`) are two representations of the same account, and address arguments like `signerAddress` accept either form. You can also call `GetLinkedWallet` with an `address` argument instead of `idempotencyKey` to check whether a specific wallet address is linked to your account.

:::note Polling the link state
There's no push notification for link state yet, so poll `GetLinkedWallet` (e.g. every few seconds while your "link your wallet" screen is open) until it returns data. A `null` response after a successful link means the user has since **disconnected** your application from their wallet app — treat the wallet as unlinked and offer to link again.
:::note Watching the link state
If you poll rather than subscribe to `WalletLinked`, query `GetLinkedWallet` every few seconds while your "link your wallet" screen is open. Either way, there's no event for the user later **disconnecting** your application from their wallet app, so a `null` `GetLinkedWallet` response after a successful link means exactly that — treat the wallet as unlinked and offer to link again.
:::

## Verifying Wallet Ownership {#verifying-wallet-ownership}
Expand Down Expand Up @@ -747,8 +747,8 @@ The `state` moves through:

If the user rejects the request or never responds, the transaction won't proceed. You can also withdraw a request that's still `PENDING` at any time with the [`CancelTransaction(uuid:)`](/03-api-reference/02-mutations/01-transaction-mutations.md#canceltransaction) mutation — for example, when the in-game offer that triggered it expires — which marks the transaction `ABANDONED`.

:::note Polling the transaction state
Real-time push notifications for transaction state aren't covered in the docs yet, so poll `GetTransaction` while a request is outstanding, the same way you polled `GetLinkedWallet` during linking.
:::note Watching the transaction state
Subscribe to the [`TransactionStateChanged`](/03-api-reference/03-websocket-events.md#transactionstatechanged) WebSocket event to be notified of each state change in real time, or poll `GetTransaction` while a request is outstanding.
:::

:::info Explore More Arguments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ query ConfirmMove {
}
```

See [Working with Events](/05-enjin-platform/03-working-with-events.md) for the full finalization-and-events workflow. (Real-time push events that remove the need to poll are [planned](/03-api-reference/03-websocket-events.md).)
See [Working with Events](/05-enjin-platform/03-working-with-events.md) for the full finalization-and-events workflow, or subscribe to real-time [WebSocket events](/03-api-reference/03-websocket-events.md) to remove the need to poll.

For a **self-custodial** cold wallet, your server can't sign the melt — instead, the player approves it in their own Enjin Wallet app via a wallet request.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,5 @@ client.reset();
With an authenticated client you can start sending requests. See [GraphQL Requests](/02-guides/01-platform/04-software-development-kit/02-graphql-requests.md) to learn how to build queries and mutations, select the fields you want back, and handle responses.

:::tip Real-time events
The Enjin Platform doesn't yet expose real-time WebSocket events. Until it does, the pattern for tracking a submitted transaction is to poll the `GetTransaction` query by its UUID until it reaches a final state — see the [Enjin Farmer server implementation breakdown](/02-guides/01-platform/05-enjin-farmer-sample-game/01-overview.md#server-implementation-breakdown) for a worked example.
To track a submitted transaction, subscribe to the platform's real-time [WebSocket events](/03-api-reference/03-websocket-events.md) (e.g. `TransactionStateChanged`), or poll the `GetTransaction` query by its UUID until it reaches a final state — see the [Enjin Farmer server implementation breakdown](/02-guides/01-platform/05-enjin-farmer-sample-game/01-overview.md#server-implementation-breakdown) for a worked polling example.
:::
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The project consists of four main components that work together:
Before you begin, please keep the following in mind:

* **Demonstration Purpose:** This is a simplified example designed to showcase a basic integration. It is **not suitable for a production environment** as is.
* **Polling, not subscriptions:** The Enjin Platform API doesn't yet expose [WebSocket events](/03-api-reference/03-websocket-events.md), so after submitting a transaction the server polls the `GetTransaction` query until it finalizes. Real-time event streaming is planned; once available it can simplify listening for finalization and for tokens arriving from external sources like the marketplace.
* **Polling, not subscriptions:** To keep the sample simple, after submitting a transaction the server polls the `GetTransaction` query until it finalizes. A production integration can subscribe to the platform's real-time [WebSocket events](/03-api-reference/03-websocket-events.md) (e.g. `TransactionStateChanged`) instead of polling.
* **Wallet Funding:** New managed wallets start empty. So they can pay the network fees for melting and transferring, this sample has the server automatically drip a small amount of cENJ (1 ENJ by default) from the daemon wallet to each new managed wallet. In a real-world application you'd typically use a [Fuel Tank](/02-guides/01-platform/02-managing-users/04-using-fuel-tanks.md) to subsidize transactions for all your users instead.
* **On-chain actions aren't instant:** This sample melts and mints on-chain whenever items change hands, which takes seconds to finalize — fine for a farming demo, but unplayable for real-time action. For a production pattern that keeps item use instant while preserving on-chain ownership, see [Hot & Cold Inventories](/02-guides/01-platform/03-advanced-mechanics/07-hot-cold-inventories.md).

Expand Down Expand Up @@ -189,7 +189,7 @@ On startup — before serving any requests — the server runs [`PrepareCollecti
var resp = await _client.SendMutation(mutation);
```

2. **Wait for finalization:** `CreateTransaction` returns a transaction UUID. The server then [polls `GetTransaction`](https://github.com/enjin/platform-sample-game-server/blob/64949d25394526ef478b81c06a5d1e36375e455e/Services/EnjinService.cs#L608) by that UUID until `State` is `FINALIZED` (it throws if the transaction ends up `FAILED`, `ABANDONED`, or `TIMEOUT`). The new collection's ID is then recovered by querying `GetCollections` and matching on the `name` attribute. In a real-world application you'd instead listen for the collection-creation event rather than query for it — see [WebSocket Events](/03-api-reference/03-websocket-events.md).
2. **Wait for finalization:** `CreateTransaction` returns a transaction UUID. The server then [polls `GetTransaction`](https://github.com/enjin/platform-sample-game-server/blob/64949d25394526ef478b81c06a5d1e36375e455e/Services/EnjinService.cs#L608) by that UUID until `State` is `FINALIZED` (it throws if the transaction ends up `FAILED`, `ABANDONED`, or `TIMEOUT`). The new collection's ID is then recovered by querying `GetCollections` and matching on the `name` attribute. In a real-world application you'd instead read the new collection's ID from the transaction's emitted events rather than query for it — see [Working with Events](/05-enjin-platform/03-working-with-events.md).

3. **Create resource tokens:** For each entry in `Enjin.ResourceTokens`, the server [checks whether the token already exists](https://github.com/enjin/platform-sample-game-server/blob/64949d25394526ef478b81c06a5d1e36375e455e/Services/EnjinService.cs#L200) with a `GetToken` query and, if not, [creates it](https://github.com/enjin/platform-sample-game-server/blob/64949d25394526ef478b81c06a5d1e36375e455e/Services/EnjinService.cs#L219) with a `CreateToken` input.

Expand Down
Loading
Loading