setRobot({ ...robot, avatarLoaded: true })}
/>
+ {settings.network === 'testnet' ? (
+
+
+ {t('Using Testnet Bitcoin')}
+
+
+ ) : (
+ <>>
+ )}
+
{
theme={theme}
robot={robot}
setRobot={setRobot}
+ baseUrl={baseUrl}
/>
@@ -262,6 +291,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
hasRobot={robot.avatarLoaded}
setPage={setPage}
setCurrentOrder={setCurrentOrder}
+ baseUrl={baseUrl}
/>
@@ -286,6 +316,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
setFav={setFav}
windowSize={{ ...windowSize, height: windowSize.height - navbarHeight }}
hasRobot={robot.avatarLoaded}
+ baseUrl={baseUrl}
/>
@@ -300,7 +331,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
appear={slideDirection.in != undefined}
>
-
+
)}
@@ -325,6 +356,7 @@ const Main = ({ settings, setSettings }: MainProps): JSX.Element => {
{
setSlideDirection={setSlideDirection}
currentOrder={currentOrder}
hasRobot={robot.avatarLoaded}
+ baseUrl={baseUrl}
/>
{
info={info}
robot={robot}
closeAll={closeAll}
+ baseUrl={baseUrl}
/>
);
diff --git a/frontend/src/basic/MainDialogs/index.tsx b/frontend/src/basic/MainDialogs/index.tsx
index f9a250aa..eaa70329 100644
--- a/frontend/src/basic/MainDialogs/index.tsx
+++ b/frontend/src/basic/MainDialogs/index.tsx
@@ -31,6 +31,7 @@ interface MainDialogsProps {
setPage: (state: Page) => void;
setCurrentOrder: (state: number) => void;
closeAll: OpenDialogs;
+ baseUrl: string;
}
const MainDialogs = ({
@@ -42,6 +43,7 @@ const MainDialogs = ({
setRobot,
setPage,
setCurrentOrder,
+ baseUrl,
}: MainDialogsProps): JSX.Element => {
useEffect(() => {
if (info.openUpdateClient) {
@@ -79,6 +81,7 @@ const MainDialogs = ({
/>
setOpen({ ...open, profile: false })}
robot={robot}
setRobot={setRobot}
diff --git a/frontend/src/basic/MakerPage/index.tsx b/frontend/src/basic/MakerPage/index.tsx
index 2635c04a..08ed48a7 100644
--- a/frontend/src/basic/MakerPage/index.tsx
+++ b/frontend/src/basic/MakerPage/index.tsx
@@ -24,6 +24,7 @@ interface MakerPageProps {
hasRobot: boolean;
setCurrentOrder: (state: number) => void;
setPage: (state: Page) => void;
+ baseUrl: string;
}
const MakerPage = ({
@@ -38,6 +39,7 @@ const MakerPage = ({
setCurrentOrder,
setPage,
hasRobot = false,
+ baseUrl,
}: MakerPageProps): JSX.Element => {
const { t } = useTranslation();
const history = useHistory();
@@ -108,6 +110,7 @@ const MakerPage = ({
onReset={() => setShowMatches(false)}
submitButtonLabel={matches.length > 0 && !showMatches ? 'Submit' : 'Create order'}
setPage={setPage}
+ baseUrl={baseUrl}
/>
diff --git a/frontend/src/basic/NavBar/NavBar.tsx b/frontend/src/basic/NavBar/NavBar.tsx
index 79b2ae1f..4d48f71d 100644
--- a/frontend/src/basic/NavBar/NavBar.tsx
+++ b/frontend/src/basic/NavBar/NavBar.tsx
@@ -32,6 +32,8 @@ interface NavBarProps {
closeAll: OpenDialogs;
currentOrder: number | null;
hasRobot: boolean;
+ baseUrl: string;
+ color: 'primary' | 'secondary';
}
const NavBar = ({
@@ -46,6 +48,8 @@ const NavBar = ({
height,
currentOrder,
hasRobot = false,
+ baseUrl,
+ color,
}: NavBarProps): JSX.Element => {
const theme = useTheme();
const { t } = useTranslation();
@@ -98,6 +102,8 @@ const NavBar = ({
TabIndicatorProps={{ sx: { height: '0.3em', position: 'absolute', top: 0 } }}
variant='fullWidth'
value={page}
+ indicatorColor={color}
+ textColor={color}
onChange={changePage}
>
) : (
<>>
diff --git a/frontend/src/basic/OrderPage/index.js b/frontend/src/basic/OrderPage/index.js
index 26cc59db..2f9ce481 100644
--- a/frontend/src/basic/OrderPage/index.js
+++ b/frontend/src/basic/OrderPage/index.js
@@ -117,7 +117,7 @@ class OrderPage extends Component {
getOrderDetails = (id) => {
this.setState({ orderId: id });
- apiClient.get('/api/order/?order_id=' + id).then(this.orderDetailsReceived);
+ apiClient.get(this.props.baseUrl, '/api/order/?order_id=' + id).then(this.orderDetailsReceived);
};
orderDetailsReceived = (data) => {
@@ -179,7 +179,7 @@ class OrderPage extends Component {
sendWeblnInvoice = (invoice) => {
apiClient
- .post('/api/order/?order_id=' + this.state.orderId, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.state.orderId, {
action: 'update_invoice',
invoice,
})
@@ -418,7 +418,7 @@ class OrderPage extends Component {
takeOrder = () => {
this.setState({ loading: true });
apiClient
- .post('/api/order/?order_id=' + this.state.orderId, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.state.orderId, {
action: 'take',
amount: this.state.takeAmount,
})
@@ -438,7 +438,7 @@ class OrderPage extends Component {
handleClickConfirmCancelButton = () => {
this.setState({ loading: true });
apiClient
- .post('/api/order/?order_id=' + this.state.orderId, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.state.orderId, {
action: 'cancel',
})
.then(() => this.getOrderDetails(this.state.orderId) & this.setState({ status: 4 }));
@@ -538,7 +538,7 @@ class OrderPage extends Component {
handleClickConfirmCollaborativeCancelButton = () => {
apiClient
- .post('/api/order/?order_id=' + this.state.orderId, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.state.orderId, {
action: 'cancel',
})
.then(() => this.getOrderDetails(this.state.orderId) & this.setState({ status: 4 }));
@@ -676,6 +676,7 @@ class OrderPage extends Component {
nickname={this.state.maker_nick}
tooltip={t(this.state.maker_status)}
orderType={this.state.type}
+ baseUrl={this.props.baseUrl}
/>
@@ -965,6 +967,7 @@ class OrderPage extends Component {
width={330}
data={this.state}
completeSetState={this.completeSetState}
+ baseUrl={this.props.baseUrl}
/>
@@ -1011,6 +1014,7 @@ class OrderPage extends Component {
width={330}
data={this.state}
completeSetState={this.completeSetState}
+ baseUrl={this.props.baseUrl}
/>
diff --git a/frontend/src/basic/UserGenPage.js b/frontend/src/basic/UserGenPage.js
index 23fd4f34..83dc166c 100644
--- a/frontend/src/basic/UserGenPage.js
+++ b/frontend/src/basic/UserGenPage.js
@@ -71,7 +71,7 @@ class UserGenPage extends Component {
};
});
requestBody.then((body) =>
- apiClient.post('/api/user/', body).then((data) => {
+ apiClient.post(this.props.baseUrl, '/api/user/', body).then((data) => {
this.setState({ found: data.found, bad_request: data.bad_request });
this.props.setCurrentOrder(
data.active_order_id
@@ -126,7 +126,7 @@ class UserGenPage extends Component {
};
delGeneratedUser() {
- apiClient.delete('/api/user');
+ apiClient.delete(this.props.baseUrl, '/api/user');
systemClient.deleteCookie('sessionid');
systemClient.deleteCookie('robot_token');
@@ -241,6 +241,7 @@ class UserGenPage extends Component {
}}
tooltip={t('This is your trading avatar')}
tooltipPosition='top'
+ baseUrl={this.props.baseUrl}
/>
diff --git a/frontend/src/components/BookTable/index.tsx b/frontend/src/components/BookTable/index.tsx
index eacbcb3f..08a490b9 100644
--- a/frontend/src/components/BookTable/index.tsx
+++ b/frontend/src/components/BookTable/index.tsx
@@ -46,6 +46,7 @@ interface BookTableProps {
onCurrencyChange?: (e: any) => void;
onTypeChange?: (mouseEvent: any, val: number) => void;
onOrderClicked?: (id: number) => void;
+ baseUrl: string;
}
const BookTable = ({
@@ -65,6 +66,7 @@ const BookTable = ({
onCurrencyChange,
onTypeChange,
onOrderClicked = () => null,
+ baseUrl,
}: BookTableProps): JSX.Element => {
const { t } = useTranslation();
const theme = useTheme();
@@ -173,6 +175,7 @@ const BookTable = ({
orderType={params.row.type}
statusColor={statusBadgeColor(params.row.maker_status)}
tooltip={t(params.row.maker_status)}
+ baseUrl={baseUrl}
/>
@@ -200,6 +203,7 @@ const BookTable = ({
orderType={params.row.type}
statusColor={statusBadgeColor(params.row.maker_status)}
tooltip={t(params.row.maker_status)}
+ baseUrl={baseUrl}
/>
diff --git a/frontend/src/components/Charts/DepthChart/index.tsx b/frontend/src/components/Charts/DepthChart/index.tsx
index d6d3aae8..d28b165a 100644
--- a/frontend/src/components/Charts/DepthChart/index.tsx
+++ b/frontend/src/components/Charts/DepthChart/index.tsx
@@ -20,8 +20,7 @@ import {
} from '@mui/material';
import { AddCircleOutline, RemoveCircleOutline } from '@mui/icons-material';
import { useTranslation } from 'react-i18next';
-import { useHistory } from 'react-router-dom';
-import { PublicOrder, LimitList } from '../../../models';
+import { PublicOrder, LimitList, Order } from '../../../models';
import RobotAvatar from '../../RobotAvatar';
import { amountToString, matchMedian, statusBadgeColor } from '../../../utils';
import currencyDict from '../../../../static/assets/currencies.json';
@@ -38,6 +37,7 @@ interface DepthChartProps {
fillContainer?: boolean;
elevation?: number;
onOrderClicked?: (id: number) => void;
+ baseUrl: string;
}
const DepthChart: React.FC = ({
@@ -50,9 +50,9 @@ const DepthChart: React.FC = ({
fillContainer = false,
elevation = 6,
onOrderClicked = () => null,
+ baseUrl,
}) => {
const { t } = useTranslation();
- const history = useHistory();
const theme = useTheme();
const [enrichedOrders, setEnrichedOrders] = useState([]);
const [series, setSeries] = useState([]);
@@ -233,6 +233,7 @@ const DepthChart: React.FC = ({
orderType={order.type}
statusColor={statusBadgeColor(order.maker_status)}
tooltip={t(order.maker_status)}
+ baseUrl={baseUrl}
/>
diff --git a/frontend/src/components/Dialogs/Profile.tsx b/frontend/src/components/Dialogs/Profile.tsx
index 6dcab0bb..a8d13a3c 100644
--- a/frontend/src/components/Dialogs/Profile.tsx
+++ b/frontend/src/components/Dialogs/Profile.tsx
@@ -50,10 +50,12 @@ interface Props {
setRobot: (state: Robot) => void;
setPage: (state: Page) => void;
setCurrentOrder: (state: number) => void;
+ baseUrl: string;
}
const ProfileDialog = ({
open = false,
+ baseUrl,
onClose,
robot,
setRobot,
@@ -110,7 +112,7 @@ const ProfileDialog = ({
setShowRewardsSpinner(true);
apiClient
- .post('/api/reward/', {
+ .post(baseUrl, '/api/reward/', {
invoice: rewardInvoice,
})
.then((data: any) => {
@@ -130,7 +132,7 @@ const ProfileDialog = ({
const setStealthInvoice = (wantsStealth: boolean) => {
apiClient
- .put('/api/stealth/', { wantsStealth })
+ .put(baseUrl, '/api/stealth/', { wantsStealth })
.then((data) => setRobot({ ...robot, stealthInvoices: data?.wantsStealth }));
};
diff --git a/frontend/src/components/MakerForm/MakerForm.tsx b/frontend/src/components/MakerForm/MakerForm.tsx
index 657ef04e..e32e3103 100644
--- a/frontend/src/components/MakerForm/MakerForm.tsx
+++ b/frontend/src/components/MakerForm/MakerForm.tsx
@@ -29,9 +29,8 @@ import { LimitList, Maker, Favorites, defaultMaker } from '../../models';
import { LocalizationProvider, TimePicker } from '@mui/x-date-pickers';
import DateFnsUtils from '@date-io/date-fns';
import { useHistory } from 'react-router-dom';
-import { StoreTokenDialog, NoRobotDialog, ConfirmationDialog } from '../Dialogs';
+import { ConfirmationDialog } from '../Dialogs';
import { apiClient } from '../../services/api';
-import { systemClient } from '../../services/System';
import { FlagWithProps } from '../Icons';
import AutocompletePayments from './AutocompletePayments';
@@ -59,6 +58,7 @@ interface MakerFormProps {
onOrderCreated?: (id: number) => void;
hasRobot?: boolean;
setPage?: (state: Page) => void;
+ baseUrl: string;
}
const MakerForm = ({
@@ -77,6 +77,7 @@ const MakerForm = ({
onOrderCreated = () => null,
hasRobot = true,
setPage = () => null,
+ baseUrl,
}: MakerFormProps): JSX.Element => {
const { t } = useTranslation();
const theme = useTheme();
@@ -263,7 +264,7 @@ const MakerForm = ({
escrow_duration: maker.escrowDuration,
bond_size: maker.bondSize,
};
- apiClient.post('/api/make/', body).then((data: object) => {
+ apiClient.post(baseUrl, '/api/make/', body).then((data: object) => {
setBadRequest(data.bad_request);
if (data.id) {
onOrderCreated(data.id);
diff --git a/frontend/src/components/RobotAvatar/index.tsx b/frontend/src/components/RobotAvatar/index.tsx
index 5abfd4ff..14ef140a 100644
--- a/frontend/src/components/RobotAvatar/index.tsx
+++ b/frontend/src/components/RobotAvatar/index.tsx
@@ -18,6 +18,7 @@ interface Props {
tooltipPosition?: string;
avatarClass?: string;
onLoad?: () => void;
+ baseUrl: string;
}
const RobotAvatar: React.FC = ({
@@ -32,6 +33,7 @@ const RobotAvatar: React.FC = ({
avatarClass = 'flippedSmallAvatar',
imageStyle = {},
onLoad = () => {},
+ baseUrl,
}) => {
const { t } = useTranslation();
const theme = useTheme();
@@ -39,7 +41,13 @@ const RobotAvatar: React.FC = ({
useEffect(() => {
if (nickname != null) {
- apiClient.fileImageUrl('/static/assets/avatars/' + nickname + '.png').then(setAvatarSrc);
+ if (window.NativeRobosats === undefined) {
+ setAvatarSrc(baseUrl + '/static/assets/avatars/' + nickname + '.png');
+ } else {
+ apiClient
+ .fileImageUrl(baseUrl, '/static/assets/avatars/' + nickname + '.png')
+ .then(setAvatarSrc);
+ }
}
}, [nickname]);
diff --git a/frontend/src/components/SettingsForm/index.tsx b/frontend/src/components/SettingsForm/index.tsx
index 4417529e..1873150a 100644
--- a/frontend/src/components/SettingsForm/index.tsx
+++ b/frontend/src/components/SettingsForm/index.tsx
@@ -150,7 +150,10 @@ const SettingsForm = ({
setSettings({ ...settings, network })}
+ onChange={(e, network) => {
+ setSettings({ ...settings, network });
+ systemClient.setCookie('settings_network', network);
+ }}
>
{t('Mainnet')}
diff --git a/frontend/src/components/TradeBox/EncryptedChat/index.tsx b/frontend/src/components/TradeBox/EncryptedChat/index.tsx
index 515a0d82..29a731a6 100644
--- a/frontend/src/components/TradeBox/EncryptedChat/index.tsx
+++ b/frontend/src/components/TradeBox/EncryptedChat/index.tsx
@@ -33,9 +33,10 @@ import { WebSocketsChatMessage } from '../../../models';
interface Props {
orderId: number;
userNick: string;
+ baseUrl: string;
}
-const EncryptedChat: React.FC = ({ orderId, userNick }: Props): JSX.Element => {
+const EncryptedChat: React.FC = ({ orderId, userNick, baseUrl }: Props): JSX.Element => {
const { t } = useTranslation();
const theme = useTheme();
@@ -232,6 +233,7 @@ const EncryptedChat: React.FC = ({ orderId, userNick }: Props): JSX.Eleme
}
style={{ backgroundColor: cardColor }}
diff --git a/frontend/src/components/TradeBox/index.js b/frontend/src/components/TradeBox/index.js
index c962bd65..9e10d4f7 100644
--- a/frontend/src/components/TradeBox/index.js
+++ b/frontend/src/components/TradeBox/index.js
@@ -137,7 +137,7 @@ class TradeBox extends Component {
handleClickAgreeDisputeButton = () => {
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'dispute',
})
.then((data) => this.props.completeSetState(data));
@@ -494,7 +494,7 @@ class TradeBox extends Component {
handleClickPauseOrder = () => {
this.props.completeSetState({ pauseLoading: true });
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'pause',
})
.then((data) => this.props.getOrderDetails(data.id));
@@ -642,7 +642,7 @@ class TradeBox extends Component {
this.setState({ badInvoice: false, loadingSubmitInvoice: true });
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'update_invoice',
invoice: this.state.invoice,
})
@@ -675,7 +675,7 @@ class TradeBox extends Component {
this.setState({ badInvoice: false, loadingSubmitAddress: true });
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'update_address',
address: this.state.address,
mining_fee_rate: Math.max(1, this.state.miningFee),
@@ -698,7 +698,7 @@ class TradeBox extends Component {
this.setState({ badInvoice: false });
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'submit_statement',
statement: this.state.statement,
})
@@ -1205,7 +1205,7 @@ class TradeBox extends Component {
handleClickConfirmButton = () => {
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'confirm',
})
.then((data) => {
@@ -1216,7 +1216,7 @@ class TradeBox extends Component {
handleRatingUserChange = (e) => {
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'rate_user',
rating: e.target.value,
})
@@ -1230,7 +1230,7 @@ class TradeBox extends Component {
this.setState({ rating_platform: e.target.value });
apiClient
- .post('/api/order/?order_id=' + this.props.data.id, {
+ .post(this.props.baseUrl, '/api/order/?order_id=' + this.props.data.id, {
action: 'rate_platform',
rating: e.target.value,
})
@@ -1356,7 +1356,7 @@ class TradeBox extends Component {
bondless_taker: this.props.data.bondless_taker,
};
apiClient
- .post('/api/make/', body)
+ .post(this.props.baseUrl, '/api/make/', body)
.then(
(data) =>
this.setState({ badRequest: data.bad_request }) &
@@ -1469,7 +1469,11 @@ class TradeBox extends Component {
)}
-
+
{showDisputeButton ? this.showOpenDisputeButton() : ''}
{showSendButton ? this.showFiatSentButton() : ''}
diff --git a/frontend/src/components/UnsafeAlert.js b/frontend/src/components/UnsafeAlert.js
index 5a481cf1..590437cb 100644
--- a/frontend/src/components/UnsafeAlert.js
+++ b/frontend/src/components/UnsafeAlert.js
@@ -23,17 +23,24 @@ class UnsafeAlert extends Component {
checkClient() {
const http = new XMLHttpRequest();
- const unsafeClient = !this.safe_urls.includes(getHost());
+ const host = getHost();
+ const unsafeClient = !this.safe_urls.includes(host);
try {
- http.open('HEAD', `${location.protocol}//${getHost()}/selfhosted`, false);
+ http.open('HEAD', `${location.protocol}//${host}/selfhosted`, false);
http.send();
this.props.setSettings({
...this.props.settings,
+ host,
unsafeClient,
selfhostedClient: http.status === 200,
});
} catch {
- this.props.setSettings({ ...this.props.settings, unsafeClient, selfhostedClient: false });
+ this.props.setSettings({
+ ...this.props.settings,
+ host,
+ unsafeClient,
+ selfhostedClient: false,
+ });
}
}
diff --git a/frontend/src/models/Settings.model.ts b/frontend/src/models/Settings.model.ts
index 2b8ed817..189c48f8 100644
--- a/frontend/src/models/Settings.model.ts
+++ b/frontend/src/models/Settings.model.ts
@@ -37,6 +37,9 @@ class BaseSettings {
: i18n.resolvedLanguage == null
? 'en'
: i18n.resolvedLanguage.substring(0, 2);
+
+ const networkCookie = systemClient.getCookie('settings_network');
+ this.network = networkCookie !== '' ? networkCookie : 'mainnet';
}
public frontend: 'basic' | 'pro' = 'basic';
@@ -46,6 +49,7 @@ class BaseSettings {
public freezeViewports: boolean = false;
public network: 'mainnet' | 'testnet' | undefined = 'mainnet';
public coordinator: Coordinator | undefined = undefined;
+ public host?: string;
public unsafeClient: boolean = false;
public hostedClient: boolean = false;
}
diff --git a/frontend/src/services/Native/index.d.ts b/frontend/src/services/Native/index.d.ts
index 2b0fb8d3..4ed495e8 100644
--- a/frontend/src/services/Native/index.d.ts
+++ b/frontend/src/services/Native/index.d.ts
@@ -16,6 +16,7 @@ export interface NativeWebViewMessageHttp {
category: 'http';
type: 'post' | 'get' | 'put' | 'delete' | 'xhr';
path: string;
+ baseUrl: string;
headers?: object;
body?: object;
}
diff --git a/frontend/src/services/api/ApiNativeClient/index.ts b/frontend/src/services/api/ApiNativeClient/index.ts
index f772876e..219cc8bb 100644
--- a/frontend/src/services/api/ApiNativeClient/index.ts
+++ b/frontend/src/services/api/ApiNativeClient/index.ts
@@ -38,39 +38,56 @@ class ApiNativeClient implements ApiClient {
return response.json;
};
- public put: (path: string, body: object) => Promise