commit 5f37e4087df1078fa7f46e96ad0188703ce530ef Author: Samuel Tariku <56712590+SamuelTariku@users.noreply.github.com> Date: Mon Apr 6 13:57:08 2026 +0300 initial commit diff --git a/FortuneBetAPI.ps1 b/FortuneBetAPI.ps1 new file mode 100644 index 0000000..456639f --- /dev/null +++ b/FortuneBetAPI.ps1 @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..47408f5 --- /dev/null +++ b/README.md @@ -0,0 +1,156 @@ +# Fortune Tester + + + +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 + +You’ll 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 don’t have to manually copy tokens + +--- + +## πŸ“‘ Core Command + +Everything ultimately goes through: + +```powershell +fortune call [-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 +} +``` + +That’s 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 you’re pointing to a different environment. + +--- + +## πŸ’‘ Why This Exists + +Because postman takes alot of RAM + +--- + diff --git a/arifpay_requests.ps1 b/arifpay_requests.ps1 new file mode 100644 index 0000000..e87d634 --- /dev/null +++ b/arifpay_requests.ps1 @@ -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= +# +# } +# } diff --git a/calls.ps1 b/calls.ps1 new file mode 100644 index 0000000..1b9f867 --- /dev/null +++ b/calls.ps1 @@ -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 diff --git a/chapa_requests.ps1 b/chapa_requests.ps1 new file mode 100644 index 0000000..a77fe1b --- /dev/null +++ b/chapa_requests.ps1 @@ -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 +} diff --git a/demo.mp4 b/demo.mp4 new file mode 100644 index 0000000..f62ae03 Binary files /dev/null and b/demo.mp4 differ diff --git a/fortune.ps1 b/fortune.ps1 new file mode 100644 index 0000000..3bb2d59 --- /dev/null +++ b/fortune.ps1 @@ -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 -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 -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 -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 [-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 -Password " + Write-Host " fortune refresh" + Write-Host " fortune call [-Tenant] [-Body @{...}]" + } + } +} diff --git a/fortune_tests.ps1 b/fortune_tests.ps1 new file mode 100644 index 0000000..f93c99c --- /dev/null +++ b/fortune_tests.ps1 @@ -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 diff --git a/report_request_calls.ps1 b/report_request_calls.ps1 new file mode 100644 index 0000000..aa9133f --- /dev/null +++ b/report_request_calls.ps1 @@ -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 +} +