Clean a bit and add prod env to front
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -380,5 +380,3 @@ src/Managing.Infrastructure.Tests/PrivateKeys.cs
|
|||||||
# Node.js Tools for Visual Studio
|
# Node.js Tools for Visual Studio
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,9 @@ public class BotController : BaseController
|
|||||||
Timeframe = request.Timeframe,
|
Timeframe = request.Timeframe,
|
||||||
IsForWatchingOnly = request.IsForWatchOnly,
|
IsForWatchingOnly = request.IsForWatchOnly,
|
||||||
BotTradingBalance = request.InitialTradingBalance,
|
BotTradingBalance = request.InitialTradingBalance,
|
||||||
BotType = request.BotType
|
BotType = request.BotType,
|
||||||
|
CooldownPeriod = request.CooldownPeriod,
|
||||||
|
MaxLossStreak = request.MaxLossStreak
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _mediator.Send(new StartBotCommand(config, request.Identifier, user));
|
var result = await _mediator.Send(new StartBotCommand(config, request.Identifier, user));
|
||||||
@@ -622,4 +624,7 @@ public class StartBotRequest
|
|||||||
/// The initial trading balance
|
/// The initial trading balance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal InitialTradingBalance { get; set; }
|
public decimal InitialTradingBalance { get; set; }
|
||||||
|
|
||||||
|
public int CooldownPeriod { get; set; }
|
||||||
|
public int MaxLossStreak { get; set; }
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ namespace Managing.Application.Abstractions.Services
|
|||||||
bool isForWatchingOnly = false,
|
bool isForWatchingOnly = false,
|
||||||
bool save = false,
|
bool save = false,
|
||||||
List<Candle>? initialCandles = null,
|
List<Candle>? initialCandles = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0);
|
int maxLossStreak = 0);
|
||||||
|
|
||||||
Task<Backtest> RunFlippingBotBacktest(
|
Task<Backtest> RunFlippingBotBacktest(
|
||||||
@@ -39,7 +39,7 @@ namespace Managing.Application.Abstractions.Services
|
|||||||
bool isForWatchingOnly = false,
|
bool isForWatchingOnly = false,
|
||||||
bool save = false,
|
bool save = false,
|
||||||
List<Candle>? initialCandles = null,
|
List<Candle>? initialCandles = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0);
|
int maxLossStreak = 0);
|
||||||
|
|
||||||
bool DeleteBacktest(string id);
|
bool DeleteBacktest(string id);
|
||||||
@@ -53,7 +53,7 @@ namespace Managing.Application.Abstractions.Services
|
|||||||
List<Candle> candles,
|
List<Candle> candles,
|
||||||
decimal balance,
|
decimal balance,
|
||||||
User user = null,
|
User user = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0);
|
int maxLossStreak = 0);
|
||||||
|
|
||||||
Task<Backtest> RunFlippingBotBacktest(
|
Task<Backtest> RunFlippingBotBacktest(
|
||||||
@@ -64,7 +64,7 @@ namespace Managing.Application.Abstractions.Services
|
|||||||
List<Candle> candles,
|
List<Candle> candles,
|
||||||
decimal balance,
|
decimal balance,
|
||||||
User user = null,
|
User user = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0);
|
int maxLossStreak = 0);
|
||||||
|
|
||||||
// User-specific operations
|
// User-specific operations
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ namespace Managing.Application.Backtesting
|
|||||||
bool isForWatchingOnly = false,
|
bool isForWatchingOnly = false,
|
||||||
bool save = false,
|
bool save = false,
|
||||||
List<Candle>? initialCandles = null,
|
List<Candle>? initialCandles = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0)
|
int maxLossStreak = 0)
|
||||||
{
|
{
|
||||||
var config = new TradingBotConfig
|
var config = new TradingBotConfig
|
||||||
@@ -121,7 +121,7 @@ namespace Managing.Application.Backtesting
|
|||||||
bool isForWatchingOnly = false,
|
bool isForWatchingOnly = false,
|
||||||
bool save = false,
|
bool save = false,
|
||||||
List<Candle>? initialCandles = null,
|
List<Candle>? initialCandles = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0)
|
int maxLossStreak = 0)
|
||||||
{
|
{
|
||||||
var config = new TradingBotConfig
|
var config = new TradingBotConfig
|
||||||
@@ -172,7 +172,7 @@ namespace Managing.Application.Backtesting
|
|||||||
List<Candle> candles,
|
List<Candle> candles,
|
||||||
decimal balance,
|
decimal balance,
|
||||||
User user = null,
|
User user = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0)
|
int maxLossStreak = 0)
|
||||||
{
|
{
|
||||||
var ticker = MiscExtensions.ParseEnum<Ticker>(candles.FirstOrDefault().Ticker);
|
var ticker = MiscExtensions.ParseEnum<Ticker>(candles.FirstOrDefault().Ticker);
|
||||||
@@ -214,7 +214,7 @@ namespace Managing.Application.Backtesting
|
|||||||
List<Candle> candles,
|
List<Candle> candles,
|
||||||
decimal balance,
|
decimal balance,
|
||||||
User user = null,
|
User user = null,
|
||||||
decimal cooldownPeriod = 1,
|
int cooldownPeriod = 1,
|
||||||
int maxLossStreak = 0)
|
int maxLossStreak = 0)
|
||||||
{
|
{
|
||||||
var ticker = MiscExtensions.ParseEnum<Ticker>(candles.FirstOrDefault().Ticker);
|
var ticker = MiscExtensions.ParseEnum<Ticker>(candles.FirstOrDefault().Ticker);
|
||||||
|
|||||||
@@ -1008,6 +1008,7 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
BotTradingBalance = data.BotTradingBalance,
|
BotTradingBalance = data.BotTradingBalance,
|
||||||
BotType = data.BotType,
|
BotType = data.BotType,
|
||||||
CooldownPeriod = data.CooldownPeriod,
|
CooldownPeriod = data.CooldownPeriod,
|
||||||
|
MaxLossStreak = data.MaxLossStreak,
|
||||||
Name = data.Name
|
Name = data.Name
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1077,5 +1078,6 @@ public class TradingBotBackup
|
|||||||
public MoneyManagement MoneyManagement { get; set; }
|
public MoneyManagement MoneyManagement { get; set; }
|
||||||
public DateTime StartupTime { get; set; }
|
public DateTime StartupTime { get; set; }
|
||||||
public decimal BotTradingBalance { get; set; }
|
public decimal BotTradingBalance { get; set; }
|
||||||
public decimal CooldownPeriod { get; set; }
|
public int CooldownPeriod { get; set; }
|
||||||
|
public int MaxLossStreak { get; set; }
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ public class TradingBotConfig
|
|||||||
public bool FlipPosition { get; set; }
|
public bool FlipPosition { get; set; }
|
||||||
public BotType BotType { get; set; }
|
public BotType BotType { get; set; }
|
||||||
public decimal BotTradingBalance { get; set; }
|
public decimal BotTradingBalance { get; set; }
|
||||||
public decimal CooldownPeriod { get; set; } = 1;
|
public int CooldownPeriod { get; set; } = 1;
|
||||||
public int MaxLossStreak { get; set; } = 0; // 0 means no limit
|
public int MaxLossStreak { get; set; } = 0;
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,16 @@
|
|||||||
VITE_API_URL_LOCAL=http://localhost:5000
|
VITE_API_URL_LOCAL=http://localhost:5000
|
||||||
VITE_API_URL_SERVER=https://dev-managing-api.apps.managing.live
|
VITE_API_URL_SANDBOX=https://dev-managing-api.apps.managing.live
|
||||||
|
VITE_API_URL_SERVER=https://api.kaigen.managing.live
|
||||||
|
|
||||||
VITE_WORKER_URL_LOCAL=https://localhost:5002
|
VITE_WORKER_URL_LOCAL=https://localhost:5002
|
||||||
|
VITE_WORKER_URL_SANDBOX=https://dev-managing-worker.apps.managing.live
|
||||||
VITE_WORKER_URL_SERVER=https://dev-managing-worker.apps.managing.live
|
VITE_WORKER_URL_SERVER=https://dev-managing-worker.apps.managing.live
|
||||||
|
|
||||||
|
|
||||||
ALCHEMY_ID=Bao7OirVe4bmYiDbPh0l8cs5gYb5D4_9
|
ALCHEMY_ID=Bao7OirVe4bmYiDbPh0l8cs5gYb5D4_9
|
||||||
WALLET_CONNECT_PROJECT_ID=363bf09c10fec2293b21ee199b2ce8d5
|
WALLET_CONNECT_PROJECT_ID=363bf09c10fec2293b21ee199b2ce8d5
|
||||||
VITE_PRIVY_APP_ID=cm7u09v0u002zrkuf2yjjr58p
|
VITE_PRIVY_APP_ID=cm7u09v0u002zrkuf2yjjr58p
|
||||||
|
|
||||||
|
VITE_PRIVY_APP_ID_LOCAL=cm7u09v0u002zrkuf2yjjr58p
|
||||||
|
VITE_PRIVY_APP_ID_SANDBOX=cm7u09v0u002zrkuf2yjjr58p
|
||||||
|
VITE_PRIVY_APP_ID_PRODUCTION=cm6kkz5ke00n5ffmpwdbr05mp
|
||||||
@@ -1,28 +1,86 @@
|
|||||||
import create from 'zustand'
|
import create from 'zustand'
|
||||||
|
|
||||||
type ApiStore = {
|
type Environment = 'local' | 'sandbox' | 'production'
|
||||||
isProd: boolean
|
|
||||||
apiUrl: string
|
const ENV_COOKIE_NAME = 'app_environment'
|
||||||
workerUrl: string
|
|
||||||
toggleApiUrl: () => void
|
// Cookie utility functions
|
||||||
|
const getCookie = (name: string): string | undefined => {
|
||||||
|
const cookies = document.cookie.split(';').reduce((acc, cookie) => {
|
||||||
|
const [key, value] = cookie.trim().split('=')
|
||||||
|
return { ...acc, [key]: value }
|
||||||
|
}, {} as Record<string, string>)
|
||||||
|
return cookies[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setCookie = (name: string, value: string, daysToExpire: number) => {
|
||||||
|
const expirationDate = new Date(
|
||||||
|
new Date().getTime() + daysToExpire * 24 * 60 * 60 * 1000
|
||||||
|
).toUTCString()
|
||||||
|
document.cookie = `${name}=${value}; expires=${expirationDate}; path=/`
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUrlsForEnvironment = (env: Environment) => {
|
||||||
|
switch (env) {
|
||||||
|
case 'local':
|
||||||
|
return {
|
||||||
|
apiUrl: import.meta.env.VITE_API_URL_LOCAL,
|
||||||
|
workerUrl: import.meta.env.VITE_WORKER_URL_LOCAL,
|
||||||
|
privyAppId: import.meta.env.VITE_PRIVY_APP_ID_LOCAL,
|
||||||
|
}
|
||||||
|
case 'sandbox':
|
||||||
|
return {
|
||||||
|
apiUrl: import.meta.env.VITE_API_URL_SANDBOX,
|
||||||
|
workerUrl: import.meta.env.VITE_WORKER_URL_SANDBOX,
|
||||||
|
privyAppId: import.meta.env.VITE_PRIVY_APP_ID_SANDBOX,
|
||||||
|
}
|
||||||
|
case 'production':
|
||||||
|
return {
|
||||||
|
apiUrl: import.meta.env.VITE_API_URL_SERVER,
|
||||||
|
workerUrl: import.meta.env.VITE_WORKER_URL_SERVER,
|
||||||
|
privyAppId: import.meta.env.VITE_PRIVY_APP_ID_PRODUCTION,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiStore = {
|
||||||
|
environment: Environment
|
||||||
|
apiUrl: string
|
||||||
|
workerUrl: string
|
||||||
|
privyAppId: string
|
||||||
|
setEnvironment: (env: Environment) => void
|
||||||
|
prepareEnvironmentChange: (env: Environment) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const getInitialEnvironment = (): Environment => {
|
||||||
|
const savedEnv = getCookie(ENV_COOKIE_NAME) as Environment
|
||||||
|
return savedEnv || 'production'
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialEnv = getInitialEnvironment()
|
||||||
|
const initialUrls = getUrlsForEnvironment(initialEnv)
|
||||||
|
|
||||||
const useApiUrlStore = create<ApiStore>((set) => ({
|
const useApiUrlStore = create<ApiStore>((set) => ({
|
||||||
// Mettez la valeur initiale de isProd ici
|
environment: initialEnv,
|
||||||
apiUrl: import.meta.env.VITE_API_URL_SERVER,
|
apiUrl: initialUrls.apiUrl,
|
||||||
isProd: true,
|
workerUrl: initialUrls.workerUrl,
|
||||||
toggleApiUrl: () => {
|
privyAppId: initialUrls.privyAppId,
|
||||||
set((state) => ({
|
setEnvironment: (env: Environment) => {
|
||||||
apiUrl: state.isProd
|
// Save to cookie with 1 year expiration
|
||||||
? import.meta.env.VITE_API_URL_LOCAL
|
setCookie(ENV_COOKIE_NAME, env, 365)
|
||||||
: import.meta.env.VITE_API_URL_SERVER,
|
|
||||||
isProd: !state.isProd,
|
const urls = getUrlsForEnvironment(env)
|
||||||
workerUrl: state.isProd
|
set({
|
||||||
? import.meta.env.VITE_WORKER_URL_LOCAL
|
environment: env,
|
||||||
: import.meta.env.VITE_WORKER_URL_SERVER,
|
apiUrl: urls.apiUrl,
|
||||||
}))
|
workerUrl: urls.workerUrl,
|
||||||
|
privyAppId: urls.privyAppId,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
prepareEnvironmentChange: (env: Environment) => {
|
||||||
|
// This function will be called from the component where we have access to the Privy hook
|
||||||
|
useApiUrlStore.getState().setEnvironment(env)
|
||||||
},
|
},
|
||||||
workerUrl: import.meta.env.VITE_WORKER_URL_SERVER,
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
export default useApiUrlStore
|
export default useApiUrlStore
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { useIsFetching } from '@tanstack/react-query'
|
import {useIsFetching} from '@tanstack/react-query'
|
||||||
import { usePrivy } from '@privy-io/react-auth'
|
import {usePrivy} from '@privy-io/react-auth'
|
||||||
import type { ReactNode } from 'react'
|
import type {ReactNode} from 'react'
|
||||||
import { useState } from 'react'
|
import {useState} from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import {Link} from 'react-router-dom'
|
||||||
|
|
||||||
import { NavItem } from '..'
|
import {NavItem} from '..'
|
||||||
import useApiUrlStore from '../../../app/store/apiStore'
|
import useApiUrlStore from '../../../app/store/apiStore'
|
||||||
import Logo from '../../../assets/img/logo.png'
|
import Logo from '../../../assets/img/logo.png'
|
||||||
import { Loader } from '../../atoms'
|
import {Loader} from '../../atoms'
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{ href: '/desk', name: 'Desk' },
|
{ href: '/desk', name: 'Desk' },
|
||||||
@@ -77,21 +77,31 @@ const PrivyWalletButton = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function SecondaryNavbar() {
|
export function SecondaryNavbar() {
|
||||||
const { toggleApiUrl, isProd } = useApiUrlStore()
|
const { environment, prepareEnvironmentChange } = useApiUrlStore()
|
||||||
|
const { logout } = usePrivy()
|
||||||
|
|
||||||
|
const handleEnvironmentChange = async (newEnv: 'local' | 'sandbox' | 'production') => {
|
||||||
|
prepareEnvironmentChange(newEnv)
|
||||||
|
|
||||||
|
if (logout) {
|
||||||
|
await logout()
|
||||||
|
}
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="md:flex items-center hidden space-x-3">
|
<div className="md:flex items-center hidden space-x-3">
|
||||||
<GlobalLoader />
|
<GlobalLoader />
|
||||||
<div className="form-control">
|
<div className="form-control">
|
||||||
<label className="label cursor-pointer">
|
<select
|
||||||
<span className="label-text px-2">{isProd ? 'Server' : 'Debug'}</span>
|
className="select select-bordered select-sm"
|
||||||
<input
|
value={environment}
|
||||||
type="checkbox"
|
onChange={(e) => handleEnvironmentChange(e.target.value as 'local' | 'sandbox' | 'production')}
|
||||||
className="toggle"
|
>
|
||||||
checked={isProd}
|
<option value="local">Local</option>
|
||||||
onChange={toggleApiUrl}
|
<option value="sandbox">Sandbox</option>
|
||||||
/>
|
<option value="production">Production</option>
|
||||||
</label>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<PrivyWalletButton />
|
<PrivyWalletButton />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {type SubmitHandler, useForm} from 'react-hook-form'
|
|||||||
import useApiUrlStore from '../../../app/store/apiStore'
|
import useApiUrlStore from '../../../app/store/apiStore'
|
||||||
import {
|
import {
|
||||||
AccountClient,
|
AccountClient,
|
||||||
Backtest,
|
|
||||||
BacktestClient,
|
BacktestClient,
|
||||||
BotType,
|
BotType,
|
||||||
DataClient,
|
DataClient,
|
||||||
@@ -80,9 +79,16 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process tickers sequentially
|
||||||
for (const ticker of form.tickers) {
|
for (const ticker of form.tickers) {
|
||||||
const scenarioName = form.scenarioName;
|
const scenarioName = form.scenarioName;
|
||||||
await runBacktest(form, ticker, scenarioName, customMoneyManagement, 0);
|
try {
|
||||||
|
await runBacktest(form, ticker, scenarioName, customMoneyManagement, 0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error running backtest for ${ticker}:`, error);
|
||||||
|
// Continue with next ticker even if one fails
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,15 +98,15 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
|
|||||||
scenarioName: string,
|
scenarioName: string,
|
||||||
customMoneyManagement: MoneyManagement | undefined,
|
customMoneyManagement: MoneyManagement | undefined,
|
||||||
loopCount: number
|
loopCount: number
|
||||||
) {
|
): Promise<void> {
|
||||||
const t = new Toast(ticker + ' is running')
|
const t = new Toast(ticker + ' is running')
|
||||||
// Use the name of the money management strategy if custom is not provided
|
// Use the name of the money management strategy if custom is not provided
|
||||||
const moneyManagementName = customMoneyManagement ? undefined : selectedMoneyManagement
|
const moneyManagementName = customMoneyManagement ? undefined : selectedMoneyManagement
|
||||||
|
|
||||||
console.log(customMoneyManagement)
|
console.log(customMoneyManagement)
|
||||||
|
|
||||||
backtestClient
|
try {
|
||||||
.backtest_Run(
|
const backtest = await backtestClient.backtest_Run(
|
||||||
form.accountName,
|
form.accountName,
|
||||||
form.botType,
|
form.botType,
|
||||||
ticker as Ticker,
|
ticker as Ticker,
|
||||||
@@ -115,26 +121,26 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
|
|||||||
form.cooldownPeriod, // Use the cooldown period from the form
|
form.cooldownPeriod, // Use the cooldown period from the form
|
||||||
form.maxLossStreak, // Add the max loss streak parameter
|
form.maxLossStreak, // Add the max loss streak parameter
|
||||||
customMoneyManagement
|
customMoneyManagement
|
||||||
)
|
);
|
||||||
.then((backtest: Backtest) => {
|
|
||||||
t.update('success', `${backtest.ticker} Backtest Succeeded`)
|
|
||||||
setBacktests((arr) => [...arr, backtest])
|
|
||||||
|
|
||||||
if (showLoopSlider && selectedLoopQuantity > loopCount) {
|
t.update('success', `${backtest.ticker} Backtest Succeeded`)
|
||||||
const nextCount = loopCount + 1
|
setBacktests((arr) => [...arr, backtest])
|
||||||
const mm: MoneyManagement = {
|
|
||||||
leverage: backtest.optimizedMoneyManagement.leverage,
|
if (showLoopSlider && selectedLoopQuantity > loopCount) {
|
||||||
name: backtest.optimizedMoneyManagement.name + nextCount,
|
const nextCount = loopCount + 1
|
||||||
stopLoss: backtest.optimizedMoneyManagement.stopLoss,
|
const mm: MoneyManagement = {
|
||||||
takeProfit: backtest.optimizedMoneyManagement.takeProfit,
|
leverage: backtest.optimizedMoneyManagement.leverage,
|
||||||
timeframe: backtest.optimizedMoneyManagement.timeframe,
|
name: backtest.optimizedMoneyManagement.name + nextCount,
|
||||||
}
|
stopLoss: backtest.optimizedMoneyManagement.stopLoss,
|
||||||
runBacktest(form, ticker, scenarioName, mm, nextCount)
|
takeProfit: backtest.optimizedMoneyManagement.takeProfit,
|
||||||
|
timeframe: backtest.optimizedMoneyManagement.timeframe,
|
||||||
}
|
}
|
||||||
})
|
await runBacktest(form, ticker, scenarioName, mm, nextCount)
|
||||||
.catch((err) => {
|
}
|
||||||
t.update('error', 'Error: ' + err)
|
} catch (err) {
|
||||||
})
|
t.update('error', 'Error: ' + err)
|
||||||
|
throw err; // Re-throw the error to be caught by the caller
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSelectedAccountEvent(e: React.ChangeEvent<HTMLInputElement>) {
|
function setSelectedAccountEvent(e: React.ChangeEvent<HTMLInputElement>) {
|
||||||
@@ -349,8 +355,9 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
|
|||||||
{...register('tickers')}
|
{...register('tickers')}
|
||||||
>
|
>
|
||||||
{tickers?.map((item) => (
|
{tickers?.map((item) => (
|
||||||
<option key={item} value={item}>
|
<option key={item.ticker} value={item.ticker}>
|
||||||
{item}
|
<img src={item.imageUrl || ''} alt={item.ticker} className="w-4 h-4 mr-2" />
|
||||||
|
{item.ticker}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import './styles/globals.css'
|
import './styles/globals.css'
|
||||||
|
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
import {QueryClient, QueryClientProvider} from '@tanstack/react-query'
|
||||||
import { PrivyProvider } from '@privy-io/react-auth'
|
import {PrivyProvider} from '@privy-io/react-auth'
|
||||||
import { WagmiProvider } from '@privy-io/wagmi'
|
import {WagmiProvider} from '@privy-io/wagmi'
|
||||||
import { createRoot } from 'react-dom/client'
|
import {createRoot} from 'react-dom/client'
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import {BrowserRouter} from 'react-router-dom'
|
||||||
|
|
||||||
import App from './app'
|
import App from './app'
|
||||||
import { privyWagmiConfig, supportedChains } from './config/privy'
|
import {privyWagmiConfig} from './config/privy'
|
||||||
|
import useApiUrlStore from './app/store/apiStore'
|
||||||
|
|
||||||
import 'react-grid-layout/css/styles.css'
|
import 'react-grid-layout/css/styles.css'
|
||||||
import 'react-resizable/css/styles.css'
|
import 'react-resizable/css/styles.css'
|
||||||
import 'react-toastify/dist/ReactToastify.css'
|
import 'react-toastify/dist/ReactToastify.css'
|
||||||
import { ToastContainer } from 'react-toastify'
|
import {ToastContainer} from 'react-toastify'
|
||||||
|
|
||||||
const element = document.getElementById('root') as HTMLElement
|
const element = document.getElementById('root') as HTMLElement
|
||||||
|
|
||||||
@@ -35,10 +36,12 @@ const privyConfig = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
root.render(
|
function AppWithProviders() {
|
||||||
<QueryClientProvider client={queryClient}>
|
const { privyAppId } = useApiUrlStore()
|
||||||
|
|
||||||
|
return (
|
||||||
<PrivyProvider
|
<PrivyProvider
|
||||||
appId={import.meta.env.VITE_PRIVY_APP_ID}
|
appId={privyAppId}
|
||||||
config={privyConfig}
|
config={privyConfig}
|
||||||
>
|
>
|
||||||
<WagmiProvider config={privyWagmiConfig}>
|
<WagmiProvider config={privyWagmiConfig}>
|
||||||
@@ -58,5 +61,11 @@ root.render(
|
|||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</WagmiProvider>
|
</WagmiProvider>
|
||||||
</PrivyProvider>
|
</PrivyProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<AppWithProviders />
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
import type { Contract } from 'ethers'
|
|
||||||
import { ethers } from 'ethers'
|
|
||||||
import { useRef, useState } from 'react'
|
|
||||||
|
|
||||||
const Web3 = () => {
|
|
||||||
const moodInputRef = useRef()
|
|
||||||
const [mood, setMood] = useState()
|
|
||||||
//@ts-ignore
|
|
||||||
const provider = new ethers.providers.Web3Provider(window.ethereum, 'ropsten')
|
|
||||||
const contractAddress = '0x0335e801159Af04b3067bED0aeeaCC86Ece51e19'
|
|
||||||
const moodAbi = [
|
|
||||||
{
|
|
||||||
constant: true,
|
|
||||||
inputs: [],
|
|
||||||
name: 'getMood',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
internalType: 'string',
|
|
||||||
name: '',
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
signature: '0x9d0c1397',
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
internalType: 'string',
|
|
||||||
name: '_mood',
|
|
||||||
type: 'string',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'setMood',
|
|
||||||
outputs: [],
|
|
||||||
signature: '0x5f3cbff5',
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
let contract: Contract
|
|
||||||
let signer
|
|
||||||
|
|
||||||
provider.send('eth_requestAccounts', []).then(() => {
|
|
||||||
provider.listAccounts().then(function (accounts) {
|
|
||||||
signer = provider.getSigner(accounts[0])
|
|
||||||
contract = new ethers.Contract(contractAddress, moodAbi, signer)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
async function getMoodAbi() {
|
|
||||||
const getMoodPromise = contract.getMood()
|
|
||||||
const currentMood = await getMoodPromise
|
|
||||||
setMood(currentMood)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setMoodAbi() {
|
|
||||||
//@ts-ignore
|
|
||||||
const setMoodPromise = contract.setMood(moodInputRef.current.value)
|
|
||||||
await setMoodPromise
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="container mx-auto">
|
|
||||||
<p className="mb-6 text-2xl">Web3 Playground</p>
|
|
||||||
<div className="grid-rows-1 mt-3">
|
|
||||||
<div>
|
|
||||||
<p className="text-xl">dApp</p>
|
|
||||||
|
|
||||||
<input
|
|
||||||
id="mood"
|
|
||||||
//@ts-ignore
|
|
||||||
ref={moodInputRef}
|
|
||||||
type="text"
|
|
||||||
className="input border-secondary w-full max-w-xs border-2"
|
|
||||||
/>
|
|
||||||
<button className="btn bg-secondary" onClick={setMoodAbi}>
|
|
||||||
Set Mood
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div className="card bg-primary text-primary-content w-40">
|
|
||||||
<div className="card-body">
|
|
||||||
<h2 className="card-title justify-center">{mood}</h2>
|
|
||||||
<div className="card-actions justify-center">
|
|
||||||
<button className="btn" onClick={getMoodAbi}>
|
|
||||||
Get Mood
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-xl">NFT</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Web3
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
pragma solidity ^0.8.1;
|
|
||||||
|
|
||||||
contract MoodDiary{
|
|
||||||
string mood;
|
|
||||||
|
|
||||||
//create a function that writes a mood to the smart contract
|
|
||||||
function setMood(string memory _mood) public{
|
|
||||||
mood = _mood;
|
|
||||||
}
|
|
||||||
|
|
||||||
//create a function the reads the mood from the smart contract
|
|
||||||
function getMood() public view returns(string memory){
|
|
||||||
return mood;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
pragma solidity ^0.8.0;
|
|
||||||
|
|
||||||
// Import the openzepplin contracts
|
|
||||||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
|
||||||
|
|
||||||
// GameItem is ERC721 signifies that the contract we are creating imports ERC721 and follows ERC721 contract from openzeppelin
|
|
||||||
contract GameItem is ERC721 {
|
|
||||||
|
|
||||||
constructor() ERC721("GameItem", "ITM") {
|
|
||||||
// mint an NFT to yourself
|
|
||||||
_mint(msg.sender, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
pragma solidity ^0.8.0;
|
|
||||||
|
|
||||||
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";
|
|
||||||
|
|
||||||
contract OdaToken is ERC20 {
|
|
||||||
constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {
|
|
||||||
_mint(msg.sender, 10 * 10 ** 18);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user