initial commit

This commit is contained in:
Samuel Tariku 2026-04-06 13:57:08 +03:00
commit 5f37e4087d
9 changed files with 879 additions and 0 deletions

94
FortuneBetAPI.ps1 Normal file
View File

@ -0,0 +1,94 @@
# FortuneBetAPI.ps1
# Global state
$Global:FortuneBetToken = $null
$Global:FortuneBetRefreshToken = $null
$Global:ApiBase = "http://127.0.0.1:8080/api/v1"
$Global:TenantSlug = "fortunebets" # adjust if different
function Invoke-FortuneBetRequest {
param(
[string]$Method,
[string]$Path,
[object]$Body = $null,
[switch]$Tenant
)
$url = if ($Tenant) {
"$Global:ApiBase/tenant/$Global:TenantSlug/$Path"
} else {
"$Global:ApiBase/$Path"
}
$headers = @{
"Content-Type" = "application/json"
}
if ($Global:FortuneBetToken) {
$headers["Authorization"] = "Bearer $($Global:FortuneBetToken)"
}
$bodyJson = if ($Body) { ($Body | ConvertTo-Json -Depth 5 -Compress) } else { $null }
try {
$response = Invoke-RestMethod -Method $Method -Uri $url -Headers $headers -Body $bodyJson
return $response
}
catch {
Write-Error "Request failed: $($_.Exception.Message)"
if ($_.ErrorDetails) { Write-Host $_.ErrorDetails }
}
}
function Login-FortuneBetCustomer {
param(
[string]$Email,
[string]$Password
)
$payload = @{
email = $Email
password = $Password
}
$resp = Invoke-FortuneBetRequest -Method "POST" -Path "auth/customer-login" -Tenant -Body $payload
if ($resp -and $resp.access_token) {
$Global:FortuneBetToken = $resp.access_token
$Global:FortuneBetRefreshToken = $resp.refresh_token
Write-Host "✅ Logged in. Token stored."
} else {
Write-Error "❌ Login failed. Response: $($resp | ConvertTo-Json -Depth 5)"
}
}
function Refresh-FortuneBetToken {
if (-not $Global:FortuneBetRefreshToken) {
Write-Error "No refresh token stored."
return
}
$payload = @{
refresh_token = $Global:FortuneBetRefreshToken
}
$resp = Invoke-FortuneBetRequest -Method "POST" -Path "auth/refresh" -Body $payload
if ($resp -and $resp.access_token) {
$Global:FortuneBetToken = $resp.access_token
Write-Host "🔄 Token refreshed."
} else {
Write-Error "❌ Refresh failed."
}
}
# Example convenience wrapper
function Get-FortuneBetProfile {
$resp = Invoke-FortuneBetRequest -Method "GET" -Path "user/customer-profile" -Tenant
return $resp
}
# Example usage:
# . .\FortuneBetAPI.ps1 # dot-source to load functions
# Login-FortuneBetCustomer -Email "test@example.com" -Password "1234"
# Get-FortuneBetProfile
# Refresh-FortuneBetToken

156
README.md Normal file
View File

@ -0,0 +1,156 @@
# Fortune Tester
<video src="./demo.mp4" controls></video>
This is a tiny powershell script that i use to test the backend quickly.
It probably would be better have unit and integration tests on the backend directly
but alas, there is never any time to do something like this.
You will need for fzf (use scoop / choco) and PSFzf
## ⚙️ Requirements
Youll need:
* **PowerShell** (obviously)
* **fzf** (for interactive selection)
* Install via `scoop install fzf` or `choco install fzf`
* **PSFzf** (PowerShell integration for fzf)
---
## 🚀 Getting Started
Load the CLI helpers:
```powershell
. ./fortune.ps1
```
Then launch the interactive test menu:
```powershell
. ./fortune_tests.ps1
```
This will open an `fzf` selector listing all available test functions.
---
## 🧠 How It Works
* Every function inside `fortune_tests.ps1` is automatically registered
* The `Main` function scans and feeds them into `fzf`
* You select a function → provide params → it runs
---
## 🔐 Authentication Helpers
These functions log you in and store tokens globally for reuse:
* `LoginClient`
* `LoginAdmin`
* `LoginSuper`
They automatically populate:
* `$Global:FortuneBetToken`
* `$Global:FortuneBetRefreshToken`
So you dont have to manually copy tokens
---
## 📡 Core Command
Everything ultimately goes through:
```powershell
fortune call <METHOD> <PATH> [-Tenant] [-Body @{...}]
```
### Example
```powershell
fortune call GET "leagues" -Tenant
```
---
## 🧪 Adding New Tests
Add a new function inside `fortune_tests.ps1`:
```powershell
function MyNewTest {
fortune call GET "some-endpoint" -Tenant
}
```
Thats it. It will automatically appear in the selector.
---
## 🧩 Available Test Categories
### Payments
* CryptoPay (deposit, withdrawal)
* Chapa (deposit, banks, withdrawal)
* ArifPay (checkout)
### Direct Deposits
* Create / Approve / Reject
* Bank cycling
* Account management
### Betting
* Event → Odds → Selection pipeline (`EventOddPipe`)
* Bet placement (`CreateBet`)
### Virtual Games
* Providers
* Game listing
* Demo launch
### Admin / Super Admin
* Bank management
* Direct deposit bank setup
---
## 🔄 Token Refresh
```powershell
fortune refresh
```
Uses the stored refresh token to get a new access token.
---
## 🧱 Environment Variables
Defined in `fortune.ps1`:
```powershell
$Global:ApiBase = "http://127.0.0.1:8080/api/v1"
$Global:TenantSlug = "fortunebets"
```
Change these if youre pointing to a different environment.
---
## 💡 Why This Exists
Because postman takes alot of RAM
---

27
arifpay_requests.ps1 Normal file
View File

@ -0,0 +1,27 @@
function TestArifPayDeposit {
$request = @{
amount=200
customerEmail="samueltarikufantaye@gmail.com"
customerPhone="0946685511"
}
fortune call POST "arifpay/checkout" -Body $request
}
# function TestARIFCheckout {
# $request = @{
# cancelUrl="https://example1.com"
# phone="251922655097"
# email="Ex@gmail.net"
# nonce="251assaddsasad93554asdasd8208sawas"
# errorUrl="http://error.com"
# notifyUrl="https://664db983ede9a2b5565497ee.mockapi.io/user"
# successUrl="http://example.com"
# paymentMethods=
# expireDate=
# items=
# beneficiaries=
# lang=
#
# }
# }

4
calls.ps1 Normal file
View File

@ -0,0 +1,4 @@
curl -X GET "http://127.0.0.1:8080/api/v1/tenant/fortunebets/user/customer-profile" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmb3J0dW5lLWJldCIsImF1ZCI6WyJhcGkuZm9ydHVuZWJldHMubmV0Il0sImV4cCI6MTc1NjQyMzQ4MywibmJmIjoxNzU2NDIyODgzLCJpYXQiOjE3NTY0MjI4ODMsIlVzZXJJZCI6MSwiUm9sZSI6ImN1c3RvbWVyIiwiQ29tcGFueUlEIjp7IlZhbHVlIjoxLCJWYWxpZCI6dHJ1ZX19.Fn8m0M8FR8Gt5I6LMPvImwI1fuUOgnj3Jexz7kBt6Vg" \
-H "Content-Type: application/json" \
-v

23
chapa_requests.ps1 Normal file
View File

@ -0,0 +1,23 @@
function TestChapaDeposit {
$request = @{
amount=200
}
fortune call POST "chapa/payments/deposit" -Body $request
}
function TestChapaBanks {
fortune call GET "chapa/banks"
}
function TestChapaWithdraw {
$request = @{
account_name="Samuel Tariku"
account_number="0946685511"
amount="200"
reference="1"
bank_code=128 #CBEBirr
}
fortune call POST "chapa/payments/withdraw" -Body $request
}

BIN
demo.mp4 Normal file

Binary file not shown.

174
fortune.ps1 Normal file
View File

@ -0,0 +1,174 @@
# fortune.ps1
# Simple CLI wrapper for FortuneBet backend
$Global:FortuneBetToken = $null
$Global:FortuneBetRefreshToken = $null
$Global:ApiBase = "http://127.0.0.1:8080/api/v1"
$Global:TenantSlug = "fortunebets"
function Invoke-FortuneAPI {
param(
[string]$Method,
[string]$Path,
[object]$Body = $null,
[switch]$Tenant
)
$url = if ($Tenant) {
"$Global:ApiBase/tenant/$Global:TenantSlug/$Path"
} else {
"$Global:ApiBase/$Path"
}
$headers = @{ "Content-Type" = "application/json" }
if ($Global:FortuneBetToken) {
$headers["Authorization"] = "Bearer $($Global:FortuneBetToken)"
}
$bodyJson = if ($Body) {
($Body | ConvertTo-Json -Depth 5 -Compress)
} else {
$null
}
Write-Host "➡️ $Method $url"
Write-Host "Headers:" ($headers | ConvertTo-Json -Compress)
try {
if ($Method -eq "GET" -or $Method -eq "HEAD") {
Invoke-RestMethod -Method $Method -Uri $url -Headers $headers -Verbose
} elseif ($BodyJson) {
Invoke-RestMethod -Method $Method -Uri $url -Headers $headers -Body $bodyJson -Verbose
} else {
Invoke-RestMethod -Method $Method -Uri $url -Headers $headers -Verbose
}
} catch {
Write-Error "Request failed: $($_.Exception.Message)"
if ($_.ErrorDetails) {
Write-Host $_.ErrorDetails
}
}
}
function fortune {
param(
[Parameter(Position = 0)]
[string]$Command,
[Parameter(Position = 1)]
[string]$Method,
[Parameter(Position = 2)]
[string]$Path,
[Parameter(Position = 3)]
[object]$Body,
[switch]$Tenant,
[string]$Email,
[string]$Password
)
switch ($Command) {
"login" {
if (-not $Email -or -not $Password) {
Write-Error "Usage: fortune login -Email <email> -Password <password>"
return
}
$payload = @{
email = $Email
password = $Password
}
$resp = Invoke-FortuneAPI -Method "POST" -Path "auth/customer-login" -Tenant -Body $payload
echo $resp.data
if ($resp -and $resp.data.access_token) {
$Global:FortuneBetToken = $resp.data.access_token
$Global:FortuneBetRefreshToken = $resp.data.refresh_token
Write-Host "✅ Logged in."
} else {
Write-Error "❌ Login failed."
}
}
"login-super" {
if (-not $Email -or -not $Password) {
Write-Error "Usage: fortune login-super -Email <email> -Password <password>"
return
}
$payload = @{
email = $Email
password = $Password
}
$resp = Invoke-FortuneAPI -Method "POST" -Path "auth/super-login" -Body $payload
echo $resp.data
if ($resp -and $resp.data.access_token) {
$Global:FortuneBetToken = $resp.data.access_token
$Global:FortuneBetRefreshToken = $resp.data.refresh_token
Write-Host "✅ Logged in."
} else {
Write-Error "❌ Login failed."
}
}
"login-admin" {
if (-not $Email -or -not $Password) {
Write-Error "Usage: fortune login-admin -Email <email> -Password <password>"
return
}
$payload = @{
email = $Email
password = $Password
}
$resp = Invoke-FortuneAPI -Method "POST" -Path "auth/admin-login" -Tenant -Body $payload
echo $resp.data
if ($resp -and $resp.data.access_token) {
$Global:FortuneBetToken = $resp.data.access_token
$Global:FortuneBetRefreshToken = $resp.data.refresh_token
Write-Host "✅ Logged in."
} else {
Write-Error "❌ Login failed."
}
}
"refresh" {
if (-not $Global:FortuneBetRefreshToken) {
Write-Error "No refresh token stored."
return
}
$payload = @{
refresh_token = $Global:FortuneBetRefreshToken
access_token = $Global:FortuneBetToken
}
$resp = Invoke-FortuneAPI -Method "POST" -Path "auth/refresh" -Body $payload
if ($resp -and $resp.data.access_token) {
$Global:FortuneBetToken = $resp.data.access_token
Write-Host "🔄 Token refreshed."
} else {
Write-Error "❌ Refresh failed."
}
}
"call" {
if (-not $Method -or -not $Path) {
Write-Error "Usage: fortune call <METHOD> <PATH> [-Tenant] [-Body @{...}]"
return
}
$resp = Invoke-FortuneAPI -Method $Method -Path $Path -Tenant:$Tenant -Body $Body
if ($resp) {
$resp | ConvertTo-Json -Depth 10
}
}
default {
Write-Host "Fortune CLI"
Write-Host ""
Write-Host "Commands:"
Write-Host " fortune login -Email <email> -Password <password>"
Write-Host " fortune refresh"
Write-Host " fortune call <METHOD> <PATH> [-Tenant] [-Body @{...}]"
}
}
}

382
fortune_tests.ps1 Normal file
View File

@ -0,0 +1,382 @@
# CryptoPay Tests
function TestCryptoPayDeposit {
$request = @{
amount=200
currency="ETB"
crypto_currency="USDT"
}
fortune call POST "cryptopay/deposit" -Body $request -Tenant
}
function TestCryptoPayWithdraw {
param(
[string]$address
)
$request = @{
address=$address
amount=200
currency="ETB"
crypto_currency="USDT"
}
fortune call POST "cryptopay/withdrawal" -Body $request -Tenant
}
# Chapa Tests
function TestChapaDeposit {
$request = @{
amount=200
}
fortune call POST "chapa/payments/deposit" -Body $request
}
function TestChapaBanks {
fortune call GET "chapa/banks"
}
function TestChapaWithdraw {
$request = @{
account_name="Samuel Tariku"
account_number="0946685511"
amount="200"
reference="1"
bank_code=128 #CBEBirr
}
fortune call POST "chapa/payments/withdraw" -Body $request
}
# Arifpay Tests
function TestArifPayDeposit {
$request = @{
amount=200
customerEmail="samueltarikufantaye@gmail.com"
customerPhone="0946685511"
}
fortune call POST "arifpay/checkout" -Body $request
}
# function TestARIFCheckout {
# $request = @{
# cancelUrl="https://example1.com"
# phone="251922655097"
# email="Ex@gmail.net"
# nonce="251assaddsasad93554asdasd8208sawas"
# errorUrl="http://error.com"
# notifyUrl="https://664db983ede9a2b5565497ee.mockapi.io/user"
# successUrl="http://example.com"
# paymentMethods=
# expireDate=
# items=
# beneficiaries=
# lang=
#
# }
# }
#
# Testing Direct Deposit
#
function CreateDirectDeposit {
$deposit = @{
bank_name="cbe"
sender_account_number="123456789"
sender_account_holder="Samuel Tariku"
receiver_account_number="123456789"
receiver_account_holder="Fortune Admin"
amount=1000.0
reference_number="123456"
}
fortune call POST "direct-deposits" -Tenant -Body $deposit
}
function GetAllDirectDeposits {
fortune call GET "direct-deposits?status=PENDING" | less
}
function ApproveDirectDeposit {
param(
[Int64]$id
)
fortune call POST "direct-deposits/$id/approve" | less
}
function RejectDirectDeposit {
param(
[Int64]$id
)
$reject = @{
reason="Incorrect account number"
}
fortune call POST "direct-deposits/$id/reject" -Body $reject | less
}
#
# Testing Super Admin Bank
#
function CreateBank {
$bank = @{
swift="CBETTA"
name="Commerical Bank Of Ethiopia"
acct_length=10
country_code="et"
}
fortune call POST "bank" -Body $bank
}
function GetAllBanks {
fortune call GET "bank" | less
}
function GetBankByID {
param(
[Int64]$id
)
fortune call GET "banks/$id" | less
}
function DeleteBank {
param(
[Int64]$id
)
fortune call DELETE "banks/$id" | less
}
#
#Testing Direct Deposit Bank
#
function CreateDDBank {
param(
[Int64]$id
)
$bank = @{
company_id=1
bank_id=$id
interval=1
is_cycle=$true
}
fortune call POST "direct-deposit-bank" -Body $bank
}
function GetAllDDBanks {
fortune call GET "direct-deposit-bank" | less
}
function GetDDBankByID {
param(
[Int64]$id
)
fortune call GET "direct-deposit-bank/$id" | less
}
function ManuallyCycleBank {
param(
[Int64]$id
)
fortune call POST "direct-deposit-bank/$id/cycle" | less
}
function DeleteDDBank {
param(
[Int64]$id
)
fortune call DELETE "direct-deposit-bank/$id" | less
}
# Testing Direct Deposit Account
#
function CreateDDAccount {
param(
[Int64]$id
)
$account = @{
dd_bank_id=$id
account_number="1234567"
account_holder="Fortune Admin"
}
fortune call POST "direct-deposit-account" -Body $account
}
function GetDDAccountForBank {
param(
[Int64]$id
)
fortune call GET "direct-deposit-bank/$id/accounts" | less
}
function GetVirtualGameProviders {
fortune call GET "virtual-game/orchestrator/providers"
}
function GetVirtualGameList {
fortune call GET "virtual-game/orchestrator/games?providerID=veliplay"
}
function StartVeliGameDemo {
param(
[Int64]$gameID,
[string]$providerID
)
$gameData = @{
providerId=$providerID
gameId=$gameID
language="en"
deviceType= "DESKTOP"
brandId="fortune_bets"
}
fortune call POST "veli/start-demo-game" -Body $gameData
}
function GetLeagues {
fortune call GET "leagues" -Tenant
}
function GetEvents {
fortune call GET "upcoming-events" -Tenant
}
function GetOdds {
param(
[Int64]$eventID
)
fortune call GET "odds/upcoming/${eventID}" -Tenant
}
function GetOdds {
param(
[Int64]$eventID
)
fortune call GET "odds/upcoming/${eventID}" -Tenant
}
function Select-Event {
param ($Events)
$selection = $Events |
ForEach-Object {
"$($_.id),$($_.match_name),$($_.league_name),$($_.start_time)"
} |
fzf --delimiter=',' --with-nth=2,3,4
if ($selection) {
$selectedId = ($selection -split ",")[0]
return $Events | Where-Object { $_.id -eq [int]$selectedId }
}
}
# @{id=29169722; event_id=1732385; market_type=winning_margin; market_name=Winning Margin; market_category=others; market_id=56; number_of_outcomes=10; raw_odds=System.Object[]; fetched_at=12/9/2025 04:15:38; expires_at=12/9/2025 05:15:38; is_active=True}
function Select-Odd {
param ($Odds)
$selection = $Odds | ForEach-Object {
"$($_.id),$($_.market_name)"
} | fzf --delimiter=',' --with-nth=2
if ($selection) {
$selectedId = ($selection -split ",")[0]
return $Odds | Where-Object { $_.id -eq [int]$selectedId }
}
}
#@{id=4967715; name=1; odds=1.500} @{id=4967716; name=Draw; odds=4.000} @{id=4967717; name=2; odds=5.500}
#@{id=4967741; odds=1.925; header=1; handicap=-1.0} @{id=4967746; odds=1.875; header=2; handicap=+1.0}
function Select-RawOdd {
param ($Odds)
$selection = $Odds | ForEach-Object {
"$($_.id),$($_.name),$($_.header),$($_.handicap),"
} | fzf --delimiter=',' --with-nth=2,3,4
if ($selection) {
$selectedId = ($selection -split ",")[0]
return $Odds | Where-Object { $_.id -eq [int]$selectedId }
}
}
function EventOddPipe {
$events = GetEvents | ConvertFrom-Json
$selectedEvent = Select-Event $events.data
Write-Host $selectedEvent.id
$odds = GetOdds $selectedEvent.id | ConvertFrom-Json
$selectedOdd = Select-Odd $odds.data
#Write-Host $selectedOdd.raw_odds
$selectedRawOdd = Select-RawOdd $selectedOdd.raw_odds
Write-Host $selectedRawOdd
return @{
selectedEvent=$selectedEvent
selectedOdd=$selectedOdd
selectedRawOdd=$selectedRawOdd
}
}
# Create Bet
function CreateBet {
$eventOdd = EventOddPipe
Write-Host $eventOdd
$req = @{
outcomes = @(
@{
event_id=[int64]$eventOdd.selectedEvent.id
odd_id=[int64]$eventOdd.selectedRawOdd.id
market_id=[int64]$eventOdd.selectedOdd.market_id
}
)
amount=30.0
}
fortune call POST "sport/bet" -Tenant -Body $req
}
# Login Tests
function LoginClient{
fortune login -Email john.doe@example.com -Password password@123
}
function LoginAdmin{
fortune login-admin -Email test.admin@gmail.com -Password NLd3m6taW71H
}
function LoginSuper{
fortune login-super -Email cybersamt@gmail.com -Password H6xW6pe1w8ys
}
# Register Tasks
function Register {
param(
[string]$otp
)
$req = @{
first_name="Samuel"
last_name="Tariku"
phone_number="+251900000002"
password="password@123"
otp=$otp
referral_code=""
}
fortune call POST "user/register" -Tenant $req
}
function SendRegisterOTP {
$req = @{
phone_number="+251900000002"
}
fortune call POST "user/sendRegisterCode" -Tenant $req
}
function Main {
$scriptPath = $PSCommandPath
$functions = Get-ChildItem Function: |
Where-Object {
$_.ScriptBlock.File -eq $scriptPath -and
$_.Name -ne "Main"
} |
Select-Object -ExpandProperty Name |
Sort-Object
$fn = $functions | fzf --prompt="Select action > "
if (-not $fn) {
return
}
$command = Get-Command $fn
$params = @{}
foreach ($p in $command.Parameters.Values) {
$params[$p.Name] = Read-Host "Enter $($p.Name)"
}
& $fn @params
}
Main

19
report_request_calls.ps1 Normal file
View File

@ -0,0 +1,19 @@
function GetAllReportRequests {
fortune call GET "reports/requests" | less
}
function DownloadReport {
param(
[Int64]$id
)
fortune call GET "reports/download/$id" | less
}
function GenerateEventIntervalReport {
$report = @{
type="event_interval"
metadata=@{
interval="day"
}
}
fortune call POST "reports/requests" -Body $report
}