Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions 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 All @@ -333,7 +333,7 @@ Once the state reaches `FINALIZED`, the transaction has been included on-chain.

### Receive Transaction Information Using the Enjin API & SDKs

To receive transaction information programmatically, use the `GetTransaction` query. Pass the `uuid` returned by `CreateTransaction` and request whichever fields you need — `state`, `extrinsicHash`, `action`, and so on.
To receive transaction information programmatically, use the `GetTransaction` query. Pass the `uuid` returned by `CreateTransaction` and request whichever fields you need — `state`, `action`, the `extrinsic` object (hash, on-chain outcome, emitted events), and so on.

**Query:**

Expand All @@ -349,7 +349,9 @@ query GetTransactionStatus($uuid: String!) {
uuid
action
state
extrinsicHash
extrinsic {
hash
}
createdAt
updatedAt
}
Expand All @@ -369,7 +371,7 @@ query GetTransactionStatus($uuid: String!) {
curl --location 'https://platform.enjin.io/graphql' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_API_TOKEN>' \
-d '{"query":"query { GetTransaction(network: CANARY, chain: MATRIX, uuid: \"12f22f91-82df-4b60-a90c-bf72b508a17c\") { uuid action state extrinsicHash } }"}'
-d '{"query":"query { GetTransaction(network: CANARY, chain: MATRIX, uuid: \"12f22f91-82df-4b60-a90c-bf72b508a17c\") { uuid action state extrinsic { hash } } }"}'
```
</TabItem>
<TabItem value="js" label="Javascript">
Expand All @@ -387,7 +389,9 @@ fetch('https://platform.enjin.io/graphql', {
uuid
action
state
extrinsicHash
extrinsic {
hash
}
}
}
`,
Expand All @@ -409,7 +413,9 @@ axios.post('https://platform.enjin.io/graphql', {
uuid
action
state
extrinsicHash
extrinsic {
hash
}
}
}
`,
Expand All @@ -434,7 +440,9 @@ query GetTransactionStatus($uuid: String!) {
uuid
action
state
extrinsicHash
extrinsic {
hash
}
}
}
'''
Expand Down Expand Up @@ -463,7 +471,9 @@ print(response.json())
"uuid": "12f22f91-82df-4b60-a90c-bf72b508a17c",
"action": "MultiTokens.create_collection",
"state": "FINALIZED",
"extrinsicHash": "0xd43b83...014b1365",
"extrinsic": {
"hash": "0xd43b83...014b1365"
},
"createdAt": "2026-05-07T16:36:33Z",
"updatedAt": "2026-05-07T16:36:51Z"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ And would traditionally return all of the available data related to the call, li
"data": {
"MintToken": {
"uuid": "a90ded41-4262-40a2-95c0-98255b660bf1",
"extrinsicHash": null,
"extrinsic": null,
"action": "MultiTokens.mint",
"state": "PENDING",
"encodedData": "...",
Expand Down
2 changes: 1 addition & 1 deletion docs/01-getting-started/06-using-wallet-daemon.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The Enjin Wallet Daemon is an outbound-only signer for Enjin Platform transactio
2. **Poll for pending transactions -** The wallet daemon repeatedly polls the Enjin Platform API. It does not need inbound network access, so the machine holding your <GlossaryTerm id="private_key" /> should not expose public ports.
3. **Sign and broadcast -** The daemon signs each pending transaction with your private key and sends the signed payload back to the platform.
4. **Confirm on-chain state -** Enjin Platform monitors the chain and updates the transaction state when the extrinsic is included or finalized.
5. **Read the result -** Poll [`GetTransaction(uuid:)`](/03-api-reference/01-queries/01-transactions-queries.md#gettransaction) for the final `state` and `extrinsicHash`. To read emitted events, see [Working with Events](/05-enjin-platform/03-working-with-events.md).
5. **Read the result -** Poll [`GetTransaction(uuid:)`](/03-api-reference/01-queries/01-transactions-queries.md#gettransaction) for the final `state` and the `extrinsic` object (hash, on-chain outcome). To read emitted events, see [Working with Events](/05-enjin-platform/03-working-with-events.md).

:::info Network-agnostic
One daemon instance can sign for Enjin Matrixchain, Enjin Relaychain, Canary Matrixchain, and Canary Relaychain. Each network maps to a different SS58 address derived from the same wallet. The daemon prints these addresses when it starts.
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