Fix few things
This commit is contained in:
@@ -1,80 +0,0 @@
|
|||||||
# Admin Feature Documentation
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The admin feature allows specific users to manage all bots in the system, regardless of ownership. Admin users can start, stop, delete, and modify any bot without owning the associated account.
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
Admin privileges are granted through environment variables, making it secure and environment-specific. The system checks if a user is an admin by comparing their username against a comma-separated list of admin usernames configured in the environment.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
### Environment Variable
|
|
||||||
Set the `AdminUsers` environment variable with a comma-separated list of usernames:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
AdminUsers=admin1,superuser,john.doe
|
|
||||||
```
|
|
||||||
|
|
||||||
### CapRover Configuration
|
|
||||||
In your CapRover dashboard:
|
|
||||||
1. Go to your app's settings
|
|
||||||
2. Navigate to "Environment Variables"
|
|
||||||
3. Add a new environment variable:
|
|
||||||
- Key: `AdminUsers`
|
|
||||||
- Value: `admin1,superuser,john.doe` (replace with actual admin usernames)
|
|
||||||
|
|
||||||
### Local Development
|
|
||||||
For local development, you can set this in your `appsettings.Development.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"AdminUsers": "admin1,superuser,john.doe"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Admin Capabilities
|
|
||||||
|
|
||||||
Admin users can perform all bot operations without ownership restrictions:
|
|
||||||
|
|
||||||
- **Start/Save Bot**: Create and start bots for any account
|
|
||||||
- **Stop Bot**: Stop any running bot
|
|
||||||
- **Delete Bot**: Delete any bot
|
|
||||||
- **Restart Bot**: Restart any bot
|
|
||||||
- **Open/Close Positions**: Manually open or close positions for any bot
|
|
||||||
- **Update Configuration**: Modify any bot's configuration
|
|
||||||
- **View Bot Configuration**: Access any bot's configuration details
|
|
||||||
|
|
||||||
## Security Notes
|
|
||||||
|
|
||||||
1. **Environment-Based**: Admin users are configured via environment variables, not through the API
|
|
||||||
2. **No Privilege Escalation**: Regular users cannot grant themselves admin access
|
|
||||||
3. **Audit Logging**: All admin actions are logged with the admin user's context
|
|
||||||
4. **Case-Insensitive**: Username matching is case-insensitive for convenience
|
|
||||||
|
|
||||||
## Implementation Details
|
|
||||||
|
|
||||||
The admin feature is implemented using:
|
|
||||||
- `IAdminConfigurationService`: Checks if a user is an admin
|
|
||||||
- Updated `UserOwnsBotAccount` method: Returns true for admin users
|
|
||||||
- Dependency injection: Service is registered as a singleton
|
|
||||||
- Configuration reading: Reads from `AdminUsers` environment variable
|
|
||||||
|
|
||||||
## Example Usage
|
|
||||||
|
|
||||||
1. **Set Admin Users**:
|
|
||||||
```bash
|
|
||||||
AdminUsers=alice,bob,charlie
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Admin Operations**:
|
|
||||||
- Alice, Bob, or Charlie can now manage any bot in the system
|
|
||||||
- They can use all existing bot endpoints without ownership restrictions
|
|
||||||
- All operations are logged with their username for audit purposes
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
- **Admin not working**: Check if the username exactly matches the configuration (case-insensitive)
|
|
||||||
- **No admins configured**: Check the `AdminUsers` environment variable is set
|
|
||||||
- **Multiple environments**: Each environment (dev, staging, prod) should have its own admin configuration
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"InfluxDb": {
|
|
||||||
"Url": "http://influxdb:8086/",
|
|
||||||
"Organization": "",
|
|
||||||
"Token": ""
|
|
||||||
},
|
|
||||||
"Serilog": {
|
|
||||||
"MinimumLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Override": {
|
|
||||||
"Microsoft": "Information",
|
|
||||||
"System": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ElasticConfiguration": {
|
|
||||||
"Uri": "http://elasticsearch:9200"
|
|
||||||
},
|
|
||||||
"Discord": {
|
|
||||||
"BotActivity": "trading strategies",
|
|
||||||
"HandleUserAction": true,
|
|
||||||
"ApplicationId": "",
|
|
||||||
"PublicKey": "",
|
|
||||||
"TokenId": "",
|
|
||||||
"SignalChannelId": 966080506473099314,
|
|
||||||
"TradesChannelId": 998374177763491851,
|
|
||||||
"TroublesChannelId": 1015761955321040917,
|
|
||||||
"CopyTradingChannelId": 1132022887012909126,
|
|
||||||
"FundingRateChannelId": 1263566138709774336,
|
|
||||||
"RequestsChannelId": 1018589494968078356,
|
|
||||||
"ButtonExpirationMinutes": 10
|
|
||||||
},
|
|
||||||
"RunOrleansGrains": true,
|
|
||||||
"AllowedHosts": "*"
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
{
|
{
|
||||||
"InfluxDb": {
|
"InfluxDb": {
|
||||||
"Url": "http://influxdb:8086/",
|
"Url": "http://localhost:8086/",
|
||||||
"Organization": "managing-org",
|
"Organization": "managing-org",
|
||||||
"Token": "Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA=="
|
"Token": "Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA=="
|
||||||
},
|
},
|
||||||
|
"PostgreSql": {
|
||||||
|
"ConnectionString": "Host=localhost;Port=5432;Database=managing;Username=postgres;Password=postgres",
|
||||||
|
"Orleans": "Host=localhost;Port=5432;Database=orleans;Username=postgres;Password=postgres"
|
||||||
|
},
|
||||||
"Privy": {
|
"Privy": {
|
||||||
"AppId": "cm6f47n1l003jx7mjwaembhup",
|
"AppId": "cm6f47n1l003jx7mjwaembhup",
|
||||||
"AppSecret": "63Chz2z5M8TgR5qc8dznSLRAGTHTyPU4cjdQobrBF1Cx5tszZpTuFgyrRd7hZ2k6HpwDz3GEwQZzsCqHb8Z311bF"
|
"AppSecret": "63Chz2z5M8TgR5qc8dznSLRAGTHTyPU4cjdQobrBF1Cx5tszZpTuFgyrRd7hZ2k6HpwDz3GEwQZzsCqHb8Z311bF"
|
||||||
@@ -30,19 +34,24 @@
|
|||||||
"RequestsChannelId": 1018589494968078356,
|
"RequestsChannelId": 1018589494968078356,
|
||||||
"ButtonExpirationMinutes": 2
|
"ButtonExpirationMinutes": 2
|
||||||
},
|
},
|
||||||
"RunOrleansGrains": true,
|
"RunOrleansGrains": false,
|
||||||
"WorkerPricesFifteenMinutes": false,
|
"AllowedHosts": "*",
|
||||||
|
"KAIGEN_SECRET_KEY": "KaigenXCowchain",
|
||||||
|
"KAIGEN_CREDITS_ENABLED": false,
|
||||||
|
"WorkerBalancesTracking": false,
|
||||||
|
"WorkerNotifyBundleBacktest": false,
|
||||||
|
"WorkerPricesFifteenMinutes": true,
|
||||||
"WorkerPricesOneHour": false,
|
"WorkerPricesOneHour": false,
|
||||||
"WorkerPricesFourHours": false,
|
"WorkerPricesFourHours": false,
|
||||||
"WorkerPricesOneDay": false,
|
"WorkerPricesOneDay": false,
|
||||||
"WorkerPricesFiveMinutes": false,
|
"WorkerPricesFiveMinutes": false,
|
||||||
|
"WorkerFee": false,
|
||||||
|
"WorkerPositionManager": false,
|
||||||
|
"WorkerPositionFetcher": false,
|
||||||
"WorkerSpotlight": false,
|
"WorkerSpotlight": false,
|
||||||
"WorkerTraderWatcher": false,
|
"WorkerTraderWatcher": false,
|
||||||
"WorkerLeaderboard": false,
|
"WorkerLeaderboard": false,
|
||||||
"WorkerFundingRatesWatcher": false,
|
"WorkerFundingRatesWatcher": false,
|
||||||
"WorkerGeneticAlgorithm": false,
|
"WorkerGeneticAlgorithm": false,
|
||||||
"WorkerBundleBacktest": true,
|
"WorkerBundleBacktest": false
|
||||||
"WorkerBalancesTracking": false,
|
|
||||||
"WorkerNotifyBundleBacktest": false,
|
|
||||||
"AllowedHosts": "*"
|
|
||||||
}
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{"Timestamp":"2022-09-13T02:59:02.0040536+02:00","Level":"Information","MessageTemplate":"02:59:01 Discord Discord.Net v3.8.0 (API v9)","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:02.0892523+02:00","Level":"Information","MessageTemplate":"02:59:02 Gateway Connecting","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:02.2504922+02:00","Level":"Information","MessageTemplate":"Now listening on: {address}","Properties":{"address":"https://localhost:5001","EventId":{"Id":14,"Name":"ListeningOnAddress"},"SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:02.2556804+02:00","Level":"Information","MessageTemplate":"Now listening on: {address}","Properties":{"address":"http://localhost:5000","EventId":{"Id":14,"Name":"ListeningOnAddress"},"SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:02.2591276+02:00","Level":"Information","MessageTemplate":"Application started. Press Ctrl+C to shut down.","Properties":{"SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:02.2625140+02:00","Level":"Information","MessageTemplate":"Hosting environment: {envName}","Properties":{"envName":"Development","SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:02.2651704+02:00","Level":"Information","MessageTemplate":"Content root path: {contentRoot}","Properties":{"contentRoot":"C:\\Users\\Utilisateur\\Desktop\\Projects\\apps\\Managing\\src\\Managing.Api\\","SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:03.3572754+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway You're using the GuildScheduledEvents gateway intent without listening to any events related to that intent, consider removing the intent from your config.","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:03.3628433+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway You're using the GuildInvites gateway intent without listening to any events related to that intent, consider removing the intent from your config.","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:03.3688717+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway Connected","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:03.9425506+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway Ready","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:10.5882097+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/index.html","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/index.html - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000001","RequestPath":"/index.html","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/index.html - -"}]}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:11.5711332+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":996.3451,"StatusCode":200,"ContentType":"text/html;charset=utf-8","ContentLength":null,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/index.html","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/index.html - - - 200 - text/html;charset=utf-8 996.3451ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000001","RequestPath":"/index.html","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/index.html - - - 200 - text/html;charset=utf-8 996.3451ms"}]}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:11.6123850+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_framework/aspnetcore-browser-refresh.js","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000003","RequestPath":"/_framework/aspnetcore-browser-refresh.js","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - -"}]}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:11.6281716+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":15.5581,"StatusCode":200,"ContentType":"application/javascript; charset=utf-8","ContentLength":11994,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_framework/aspnetcore-browser-refresh.js","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - - - 200 11994 application/javascript;+charset=utf-8 15.5581ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000003","RequestPath":"/_framework/aspnetcore-browser-refresh.js","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - - - 200 11994 application/javascript;+charset=utf-8 15.5581ms"}]}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:11.7015500+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_vs/browserLink","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/_vs/browserLink - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000005","RequestPath":"/_vs/browserLink","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/_vs/browserLink - -"}]}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:11.8214511+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":119.7799,"StatusCode":200,"ContentType":"text/javascript; charset=UTF-8","ContentLength":null,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_vs/browserLink","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/_vs/browserLink - - - 200 - text/javascript;+charset=UTF-8 119.7799ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000005","RequestPath":"/_vs/browserLink","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/_vs/browserLink - - - 200 - text/javascript;+charset=UTF-8 119.7799ms"}]}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:11.9652804+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/swagger/v1/swagger.json","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000007","RequestPath":"/swagger/v1/swagger.json","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - -"}]}}
|
|
||||||
{"Timestamp":"2022-09-13T02:59:12.3915820+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":426.2987,"StatusCode":200,"ContentType":"application/json;charset=utf-8","ContentLength":null,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/swagger/v1/swagger.json","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - - - 200 - application/json;charset=utf-8 426.2987ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000007","RequestPath":"/swagger/v1/swagger.json","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - - - 200 - application/json;charset=utf-8 426.2987ms"}]}}
|
|
||||||
@@ -8,9 +8,12 @@ services:
|
|||||||
- ASPNETCORE_URLS=https://+:443;http://+:80
|
- ASPNETCORE_URLS=https://+:443;http://+:80
|
||||||
- ASPNETCORE_Kestrel__Certificates__Default__Password=!Managing94
|
- ASPNETCORE_Kestrel__Certificates__Default__Password=!Managing94
|
||||||
- ASPNETCORE_Kestrel__Certificates__Default__Path=/app/managing_cert.pfx
|
- ASPNETCORE_Kestrel__Certificates__Default__Path=/app/managing_cert.pfx
|
||||||
|
- RUN_ORLEANS_GRAINS=true
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
|
- "11111:11111" # Orleans silo port
|
||||||
|
- "30000:30000" # Orleans gateway port
|
||||||
volumes:
|
volumes:
|
||||||
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
|
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
|
||||||
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
|
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
|
||||||
@@ -18,6 +21,7 @@ services:
|
|||||||
- /Users/oda/Microsoft/UserSecrets:/root/.microsoft/usersecrets/$USER_SECRETS_ID
|
- /Users/oda/Microsoft/UserSecrets:/root/.microsoft/usersecrets/$USER_SECRETS_ID
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
|
- influxdb
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:17.5
|
image: postgres:17.5
|
||||||
|
|||||||
@@ -8,12 +8,6 @@ services:
|
|||||||
dockerfile: Managing.Api/Dockerfile
|
dockerfile: Managing.Api/Dockerfile
|
||||||
networks:
|
networks:
|
||||||
- managing-network
|
- managing-network
|
||||||
ports:
|
|
||||||
- "11111:11111" # Orleans silo port
|
|
||||||
- "30000:30000" # Orleans gateway port
|
|
||||||
environment:
|
|
||||||
- ASPNETCORE_ENVIRONMENT=Production
|
|
||||||
- RUN_ORLEANS_GRAINS=true
|
|
||||||
hostname: managing-api
|
hostname: managing-api
|
||||||
|
|
||||||
influxdb:
|
influxdb:
|
||||||
|
|||||||
@@ -566,6 +566,7 @@ export const initAddressImpl = async (
|
|||||||
console.log('exchangeRouterAllowance', exchangeRouterAllowance)
|
console.log('exchangeRouterAllowance', exchangeRouterAllowance)
|
||||||
|
|
||||||
let exchangeRouterHash = "";
|
let exchangeRouterHash = "";
|
||||||
|
console.log('approveAmount', approveAmount)
|
||||||
if (exchangeRouterAllowance < approveAmount) {
|
if (exchangeRouterAllowance < approveAmount) {
|
||||||
exchangeRouterHash = await approveContractImpl(
|
exchangeRouterHash = await approveContractImpl(
|
||||||
address,
|
address,
|
||||||
@@ -782,7 +783,6 @@ export const getWalletBalanceImpl = async (
|
|||||||
|
|
||||||
// Get user by wallet address
|
// Get user by wallet address
|
||||||
const user = await privy.getUserByWalletAddress(address);
|
const user = await privy.getUserByWalletAddress(address);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new Error(`User not found for wallet address: ${address}`);
|
throw new Error(`User not found for wallet address: ${address}`);
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/Managing.Web3Proxy/test/plugins/initPrivyWallet.test.ts
Normal file
26
src/Managing.Web3Proxy/test/plugins/initPrivyWallet.test.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import {test} from 'node:test'
|
||||||
|
import assert from 'node:assert'
|
||||||
|
import {initAddressImpl} from '../../src/plugins/custom/privy'
|
||||||
|
|
||||||
|
test('Privy Wallet Initialization', async (t) => {
|
||||||
|
await t.test('should initialize a wallet address for GMX trading', async () => {
|
||||||
|
const address = '0x0b4a132cb6ed8fa66953bf61a53d0b91dacaad78'
|
||||||
|
|
||||||
|
const result = await initAddressImpl(address)
|
||||||
|
|
||||||
|
console.log('Wallet initialization result:', result)
|
||||||
|
|
||||||
|
// Verify the result structure
|
||||||
|
assert.ok(result, 'Wallet initialization result should be defined')
|
||||||
|
assert.ok(result.usdcHash, 'USDC hash should be defined')
|
||||||
|
assert.ok(result.orderVaultHash, 'Order vault hash should be defined')
|
||||||
|
assert.ok(result.exchangeRouterHash, 'Exchange router hash should be defined')
|
||||||
|
assert.ok(result.wethSyntheticsRouterHash, 'WETH synthetics router hash should be defined')
|
||||||
|
|
||||||
|
// Verify all hashes are strings
|
||||||
|
assert.strictEqual(typeof result.usdcHash, 'string', 'USDC hash should be a string')
|
||||||
|
assert.strictEqual(typeof result.orderVaultHash, 'string', 'Order vault hash should be a string')
|
||||||
|
assert.strictEqual(typeof result.exchangeRouterHash, 'string', 'Exchange router hash should be a string')
|
||||||
|
assert.strictEqual(typeof result.wethSyntheticsRouterHash, 'string', 'WETH synthetics router hash should be a string')
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -5,17 +5,17 @@ import {Ticker, TradeDirection} from '../../src/generated/ManagingApiTypes'
|
|||||||
|
|
||||||
test('GMX Position Opening', async (t) => {
|
test('GMX Position Opening', async (t) => {
|
||||||
await t.test('should open a long position for BTC', async () => {
|
await t.test('should open a long position for BTC', async () => {
|
||||||
const sdk = await getClientForAddress('0x932167388dD9aad41149b3cA23eBD489E2E2DD78')
|
const sdk = await getClientForAddress('0x0b4A132cb6ed8fa66953bf61a53D0B91DaCaAd78')
|
||||||
|
|
||||||
const result = await openGmxPositionImpl(
|
const result = await openGmxPositionImpl(
|
||||||
sdk,
|
sdk,
|
||||||
Ticker.ETH,
|
Ticker.BTC,
|
||||||
TradeDirection.Long,
|
TradeDirection.Long,
|
||||||
0.00678,
|
0.00009129924572776991,
|
||||||
2,
|
2,
|
||||||
4410,
|
111350,
|
||||||
3500,
|
110000,
|
||||||
6000
|
114000
|
||||||
)
|
)
|
||||||
console.log('Position opening result:', result)
|
console.log('Position opening result:', result)
|
||||||
assert.ok(result, 'Position opening result should be defined')
|
assert.ok(result, 'Position opening result should be defined')
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
import { test } from 'node:test'
|
|
||||||
import Fastify from 'fastify'
|
|
||||||
import scryptPlugin from '../../src/plugins/custom/scrypt.js'
|
|
||||||
import assert from 'node:assert'
|
|
||||||
|
|
||||||
test('scrypt works standalone', async t => {
|
|
||||||
const app = Fastify()
|
|
||||||
|
|
||||||
t.after(() => app.close())
|
|
||||||
|
|
||||||
app.register(scryptPlugin)
|
|
||||||
|
|
||||||
await app.ready()
|
|
||||||
|
|
||||||
const password = 'test_password'
|
|
||||||
const hash = await app.hash(password)
|
|
||||||
assert.ok(typeof hash === 'string')
|
|
||||||
|
|
||||||
const isValid = await app.compare(password, hash)
|
|
||||||
assert.ok(isValid, 'compare should return true for correct password')
|
|
||||||
|
|
||||||
const isInvalid = await app.compare('wrong_password', hash)
|
|
||||||
assert.ok(!isInvalid, 'compare should return false for incorrect password')
|
|
||||||
|
|
||||||
await assert.rejects(
|
|
||||||
() => app.compare(password, 'malformed_hash'),
|
|
||||||
'compare should throw an error for malformed hash'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user