Seamless wallet requests flow¶
Place-bet¶
graph TD
%% Start Node
Start([Place Bet request from user]) --> Proc[Bet processing in GR8 Platform]
%% Main Decision
Proc --> Logic{If bet ok?}
%% Left Branch: Bet OK
Logic -- Yes --> Credit[Request for credit money from user balance on clients platform]
Credit --> CredOk{Successful response?}
CredOk -- Yes --> Accepted1([Bet accepted])
CredOk -- No --> Rollback[Rollback transaction]
Rollback --> RollOk{Successful response?}
RollOk -- Yes --> NotAccepted1([Bet is not accepted])
RollOk -- No --> RetryQue[Rollback transaction request placed to the retry queue and will be retried later]
%% Right Branch: Bet Not OK / Recovery
Logic -- No --> GetTrans[Get transaction in case if service restart and bet was placed before]
GetTrans --> TransExists{Transaction exists?}
TransExists -- Yes --> Accepted2([Bet accepted])
TransExists -- No --> NotAccepted2([Bet is not accepted])
%% Styling to match original image
style Accepted1 fill:#d4edda,stroke:#28a745
style Accepted2 fill:#d4edda,stroke:#28a745
style NotAccepted1 fill:#d4edda,stroke:#28a745
style NotAccepted2 fill:#d4edda,stroke:#28a745
style RetryQue fill:#f3e5f5,stroke:#9c27b0
style Logic fill:#fff3e0,stroke:#ffa000
style CredOk fill:#fff3e0,stroke:#ffa000
style RollOk fill:#fff3e0,stroke:#ffa000
style TransExists fill:#fff3e0,stroke:#ffa000 Danger
ATTENTION!
Get balance request will be always executed after EACH transaction request by default. If you want to disable it, please contact with AM/PM of GR8 TECH team
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "bet",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "10"
}
}
Bet will be accepted in case of a successful response and there are no technical issues. In case of a technical issue, a rollback request could be sent and bet placement will be canceled. A rollback request example will be provided below.
{
"balances": {
"sport": {
"main": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
},
"sportsbook": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
}
}
},
"alreadyProcessed": false,
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "bet",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "10"
}
}
In case of an unsuccessful response, the bet won't be accepted.
{
"error": {
"code": "error.user.not-found",
"message": "User with specified Id was not found",
"origin": "{clientName}"
},
"alreadyProcessed": false
}
Wallet request example - place bet rollback¶
Warning
3rd party wallet must guarantee processing of rollback requests. We will retry each rollback every 5 minutes until the success or retry count reaches 100 (~retring during 8 hours). In the case when a rollback request can’t be applied, there could be a resynchronization between the client's wallet and bet state. The bet will be marked as broken on the GR8 Tech side and the operation can be retried manually by request to our team.
Info
Remote wallet is responsible for verifying if parent transaction (passed via context.parentId) exists. Expected remote wallet to return 400 status code with decline.parent.notfound error code in case no parent transaction found.
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "rollback",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "sport rollback",
"betId": "4494226fa9c24b978b975823e353616b",
"parentId": "parentTransactionId"
},
"amountBreakdown": {
"cash": "10"
}
}
In case of success, we expect the next response.
{
"balances": {
"sport": {
"main": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
},
"sportsbook": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
}
}
},
"alreadyProcessed": false,
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "rollback",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "sport rollback",
"betId": "4494226fa9c24b978b975823e353616b",
"parentId": "parentId"
},
"amountBreakdown": {
"cash": "10"
}
}
In case of failure, we expect the next response.
{
"error": {
"code": "decline.parent.notfound",
"message": "ROLLBACK_NO_BET_FOUND - Transaction not found",
"origin": "{clientName}"
},
"alreadyProcessed": false
}
"code": "decline.parent.notfound" - Parent transaction was not found
"code": "decline.parent.failed" - Parent transaction was found but it was failed
Wallet request example - get transaction before placement¶
In case of placement interruption and long processing (more than 30 seconds) for achieving consistency between the sportsbook and 3rd party wallet we can check if the transaction exists on 3rd party wallet. If the transaction exists we will accept it in our sportsbook. Otherwise, we will reject this bet.
Note
3rd party wallet must always return the correct state of the transaction.
Schema and example are provided upper in - get-transaction-by-id
Settle bet¶
%%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#B0B0FF', 'arrowheadColor': '#B0B0FF'}} }%%
graph TD
%% Start Node
Start([Event settled in GR8 Platform]) --> Result[Settlement result determined]
%% Settlement result
Result --> Deposit[Request deposit transaction to Operator BE]
Deposit --> DepOk{Successful response?}
%% Success path
DepOk -- Yes --> GetBal1[get-user-balance → Operator BE]
GetBal1 --> Settled[Bet settled]
%% Failure path
DepOk -- No --> Retry[Transaction placed to retry queue]
Retry --> RetryAttempt[Retry deposit transaction]
RetryAttempt --> RetryOk{Successful response?}
RetryOk -- Yes --> GetBal2[get-user-balance → Operator BE]
GetBal2 --> Settled2[Bet settled]
RetryOk -- No --> RetryAgain[Retry again until success or max retries reached]
%% Styling
style Settled fill:#d4edda,stroke:#28a745
style Settled2 fill:#d4edda,stroke:#28a745
style DepOk fill:#fff3e0,stroke:#ffa000
style RetryOk fill:#fff3e0,stroke:#ffa000
style Retry fill:#f3e5f5,stroke:#9c27b0
style RetryAgain fill:#f3e5f5,stroke:#9c27b0 Wallet request example - settle¶
Each settlement result will trigger a deposit transaction to the wallet. Be careful, that this transaction can have amount=0 in case of lost settlement result.
Settlement results:
- win
- lose
- return
- techreturn
- return025
- return075
- cashout
- deadheat
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "deposit",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "settle",
"betAmount": 10,
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "20" // Lose result - "cash": "0"
}
}
In case of a successful response
{
"balances": {
"sport": {
"main": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
},
"sportsbook": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
}
}
},
"alreadyProcessed": false,
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "deposit",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "settle",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "20"
}
}
In case of an unsuccessful wallet response, the settlement will fail
{
"error": {
"code": "error.user.not-found",
"message": "User with specified Id was not found",
"origin": "{clientName}"
},
"alreadyProcessed": false
}
Resettle and cancel settlement¶
%%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#B0B0FF', 'arrowheadColor': '#B0B0FF'}} }%%
graph TD
%% Start Node
Start([Resettlement or cancel settlement triggered]) --> Check[Determine transaction type based on amount change]
%% Decision: deposit or withdrawal
Check --> Direction{New amount > previous amount?}
%% Deposit branch (new amount greater or equal)
Direction -- "No (deposit)" --> DepReq[Request deposit transaction to Operator BE]
DepReq --> DepOk{Successful response?}
DepOk -- Yes --> GetBal1[get-user-balance → Operator BE]
GetBal1 --> Resettled1([Bet resettled])
DepOk -- No --> DepRetry[Transaction placed to retry queue]
DepRetry --> DepRetryAttempt[Retry deposit transaction]
DepRetryAttempt --> DepRetryOk{Successful response?}
DepRetryOk -- Yes --> GetBal3[get-user-balance → Operator BE]
GetBal3 --> Resettled3([Bet resettled])
DepRetryOk -- No --> DepRetryAgain[Retry again until success or max retries reached]
%% Withdrawal branch (new amount less)
Direction -- "Yes (withdrawal)" --> WdReq[Request withdrawal transaction to Operator BE]
WdReq --> WdOk{Successful response?}
WdOk -- Yes --> GetBal2[get-user-balance → Operator BE]
GetBal2 --> Resettled2([Bet resettled])
WdOk -- No --> NotResettled([Bet stays in previous state])
%% Styling
style Resettled1 fill:#d4edda,stroke:#28a745
style Resettled2 fill:#d4edda,stroke:#28a745
style Resettled3 fill:#d4edda,stroke:#28a745
style NotResettled fill:#d4edda,stroke:#28a745
style Direction fill:#fff3e0,stroke:#ffa000
style DepOk fill:#fff3e0,stroke:#ffa000
style WdOk fill:#fff3e0,stroke:#ffa000
style DepRetryOk fill:#fff3e0,stroke:#ffa000
style DepRetry fill:#f3e5f5,stroke:#9c27b0
style DepRetryAgain fill:#f3e5f5,stroke:#9c27b0 Wallet request example - withdrawal resettle¶
Withdrawal transaction is used for all transactions when the previous amount is less than the current one, hanging statuses:
win => lose/return/techreturn/return025/return075/deadheat
return => lose/return025/return075/deadheat
deadheat => lose/return/techreturn/return025/return075
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "resettle",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "10"
}
}
In case of a successful response, the bet will be resettled, otherwise, resettlement will be unsuccessful and the bet will stay in the previous state
{
"balances": {
"sport": {
"main": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
},
"sportsbook": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
}
}
},
"alreadyProcessed": false,
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "10"
}
}
{
"error": {
"code": "error.user.not-found",
"message": "User with specified Id was not found",
"origin": "{clientName}"
},
"alreadyProcessed": false
}
Wallet request example - deposit resettle¶
Deposit transactions are used for all transactions when the previous amount is greater or equal to the current one, changing statuses:
lose => win/return/return075/return025/deadheat
return => win/techreturn/deadheat
return025/return075 => techreturn/return
deadheat => win/return/return075/return025
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "deposit",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "resettle",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "20" //Lose result - "cash": "0"
}
}
In case of success response, the bet will be resettled, otherwise resettlement will be unsuccessful and bet will stay in previous state
{
"balances": {
"sport": {
"main": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
},
"sportsbook": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
}
}
},
"alreadyProcessed": false,
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "deposit",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "20"
}
}
{
"error": {
"code": "error.user.not-found",
"message": "User with specified Id was not found",
"origin": "{clientName}"
},
"alreadyProcessed": false
}
Wallet request example - cancel settle - withdrawal¶
Previous settlement result: win/lose/return/techreturn/return025/return075/cashout/deadheat
New settlement result: unknown
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "cancelsettle",
"betAmount": 10,
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "10" //if previous result is Lose - "cash": "0"
}
}
In case of a successful response, the settlement will be canceled, otherwise, cancel settlement will be unsuccessful, and bet will stay in the previous state
{
"balances": {
"sport": {
"main": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
},
"sportsbook": {
"USD": {
"cash": "100",
"bonus": "0",
"locked": "0"
}
}
}
},
"alreadyProcessed": false,
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "10"
}
}
{
"error": {
"code": "error.user.not-found",
"message": "User with specified Id was not found",
"origin": "{clientName}"
},
"alreadyProcessed": false
}
Partial settle bet¶
Wallet request example - settle¶
Each settlement result will trigger a deposit transaction to the wallet. Be careful, that this transaction have amount as part of full bet amount.
Partial settlement results:
- cashout
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "deposit",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "partial settle", // new reason
"betAmount": 10,
"betId": "4494226fa9c24b978b975823e353616b",
},
"amountBreakdown": {
"cash": "9" // it can be more or less than betAmount
}
}
Partial resettle and cancel settlement¶
Wallet request example - withdrawal/deposit resettle (only for settled bets)¶
Previous settlement result: cashout
New settlement result: return
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal", // or "deposit"
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "partial resettle", // new reason
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "1"
}
}
Wallet request example - partial cancel settle - withdrawal (only for unsettled bets)¶
Previous settlement result: cashout
New settlement result: unknown
{
"currency": "USD",
"platform": "sport",
"id": "id",
"type": "withdrawal",
"initiatedAt": "2021-01-20T00:00:00Z",
"createdAt": "2021-01-20T00:00:00Z",
"context": {
"product": "sportsbook",
"reason": "partial cancelsettle", // new reason
"betAmount": 10,
"betId": "4494226fa9c24b978b975823e353616b"
},
"amountBreakdown": {
"cash": "9"
}
}