Add frontend API client (#242)

* Frontend API client

* Test

* CR updates
This commit is contained in:
KoalaSat 2022-09-16 16:16:33 +02:00 committed by GitHub
parent b6edc27e6e
commit c770d231d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 157 additions and 222 deletions

View File

@ -31,6 +31,7 @@ import { pn, amountToString } from '../utils/prettyNumbers';
import PaymentText from './PaymentText';
import DepthChart from './Charts/DepthChart';
import RobotAvatar from './Robots/RobotAvatar';
import { apiClient } from '../services/api/index';
// Icons
import { BarChart, FormatListBulleted, Refresh } from '@mui/icons-material';
@ -51,8 +52,7 @@ class BookPage extends Component {
getOrderDetails(type, currency) {
this.props.setAppState({ bookLoading: true });
fetch('/api/book' + '?currency=' + currency + '&type=' + type)
.then((response) => response.json())
apiClient.get('/api/book?currency=' + currency + '&type=' + type)
.then((data) =>
this.props.setAppState({
bookNotFound: data.not_found,

View File

@ -18,6 +18,7 @@ import {
import MediaQuery from 'react-responsive';
import Flags from 'country-flag-icons/react/3x2';
import { Link as LinkRouter } from 'react-router-dom';
import { apiClient } from '../services/api';
// Icons
import BarChartIcon from '@mui/icons-material/BarChart';
@ -71,8 +72,7 @@ class BottomBar extends Component {
getInfo() {
this.setState(null);
fetch('/api/info/')
.then((response) => response.json())
apiClient.get('/api/info/')
.then(
(data) =>
this.setState(data) &
@ -122,16 +122,9 @@ class BottomBar extends Component {
showRewardsSpinner: true,
});
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
invoice: rewardInvoice,
}),
};
fetch('/api/reward/', requestOptions)
.then((response) => response.json())
.then(
apiClient.post('/api/reward/', {
invoice: rewardInvoice,
}).then(
(data) =>
this.setState({
badInvoice: data.bad_invoice,
@ -147,13 +140,7 @@ class BottomBar extends Component {
};
handleSetStealthInvoice = (wantsStealth) => {
const requestOptions = {
method: 'PUT',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({ wantsStealth }),
};
fetch('/api/stealth/', requestOptions)
.then((response) => response.json())
apiClient.put('/api/stealth/', { wantsStealth })
.then((data) => this.props.setAppState({ stealthInvoices: data.wantsStealth }));
};

View File

@ -29,6 +29,7 @@ import currencyDict from '../../../../static/assets/currencies.json';
import PaymentText from '../../PaymentText';
import getNivoScheme from '../NivoScheme';
import median from '../../../utils/match';
import { apiClient } from '../../../services/api/index';
interface DepthChartProps {
bookLoading: boolean;
@ -62,8 +63,7 @@ const DepthChart: React.FC<DepthChartProps> = ({
useEffect(() => {
if (Object.keys(limits).length === 0) {
fetch('/api/limits/')
.then(async (response) => await response.json())
apiClient.get('/api/limits/')
.then((data) => {
setAppState({ limits: data });
});

View File

@ -37,6 +37,7 @@ import { LocalizationProvider, TimePicker } from '@mui/x-date-pickers';
import DateFnsUtils from '@date-io/date-fns';
import { Link as LinkRouter } from 'react-router-dom';
import { StoreTokenDialog, NoRobotDialog } from './Dialogs';
import { apiClient } from '../services/api';
import FlagWithProps from './FlagWithProps';
import AutocompletePayments from './AutocompletePayments';
@ -104,8 +105,7 @@ class MakerPage extends Component {
getLimits() {
this.setState({ loadingLimits: true });
fetch('/api/limits/')
.then((response) => response.json())
apiClient.get('/api/limits/')
.then((data) =>
this.setState({
limits: data,
@ -303,29 +303,24 @@ class MakerPage extends Component {
handleCreateOfferButtonPressed = () => {
this.state.amount == null ? this.setState({ amount: 0 }) : null;
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
type: this.state.type,
currency: this.state.currency,
amount: this.state.has_range ? null : this.state.amount,
has_range: this.state.enableAmountRange,
min_amount: this.state.minAmount,
max_amount: this.state.maxAmount,
payment_method:
this.state.payment_method === '' ? this.defaultPaymentMethod : this.state.payment_method,
is_explicit: this.state.is_explicit,
premium: this.state.is_explicit ? null : this.state.premium == '' ? 0 : this.state.premium,
satoshis: this.state.is_explicit ? this.state.satoshis : null,
public_duration: this.state.publicDuration,
escrow_duration: this.state.escrowDuration,
bond_size: this.state.bondSize,
bondless_taker: this.state.allowBondless,
}),
const body = {
type: this.state.type,
currency: this.state.currency,
amount: this.state.has_range ? null : this.state.amount,
has_range: this.state.enableAmountRange,
min_amount: this.state.minAmount,
max_amount: this.state.maxAmount,
payment_method:
this.state.payment_method === '' ? this.defaultPaymentMethod : this.state.payment_method,
is_explicit: this.state.is_explicit,
premium: this.state.is_explicit ? null : this.state.premium == '' ? 0 : this.state.premium,
satoshis: this.state.is_explicit ? this.state.satoshis : null,
public_duration: this.state.publicDuration,
escrow_duration: this.state.escrowDuration,
bond_size: this.state.bondSize,
bondless_taker: this.state.allowBondless,
};
fetch('/api/make/', requestOptions)
.then((response) => response.json())
apiClient.post('/api/make/', body)
.then(
(data) =>
this.setState({ badRequest: data.bad_request }) &

View File

@ -54,6 +54,7 @@ import { getCookie } from '../utils/cookies';
import { pn } from '../utils/prettyNumbers';
import { copyToClipboard } from '../utils/clipboard';
import { getWebln } from '../utils/webln';
import { apiClient } from '../services/api';
class OrderPage extends Component {
constructor(props) {
@ -122,8 +123,7 @@ class OrderPage extends Component {
getOrderDetails = (id) => {
this.setState({ orderId: id });
fetch('/api/order' + '?order_id=' + id)
.then((response) => response.json())
apiClient.get('/api/order/?order_id=' + id)
.then(this.orderDetailsReceived);
};
@ -185,17 +185,10 @@ class OrderPage extends Component {
};
sendWeblnInvoice = (invoice) => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'update_invoice',
invoice,
}),
};
fetch('/api/order/' + '?order_id=' + this.state.orderId, requestOptions)
.then((response) => response.json())
.then((data) => this.completeSetState(data));
apiClient.post('/api/order/?order_id=' + this.state.orderId, {
action: 'update_invoice',
invoice,
}).then((data) => this.completeSetState(data));
};
// Countdown Renderer callback with condition
@ -429,16 +422,10 @@ class OrderPage extends Component {
takeOrder = () => {
this.setState({ loading: true });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'take',
amount: this.state.takeAmount,
}),
};
fetch('/api/order/' + '?order_id=' + this.state.orderId, requestOptions)
.then((response) => response.json())
apiClient.post('/api/order/?order_id=' + this.state.orderId, {
action: 'take',
amount: this.state.takeAmount,
})
.then((data) => this.handleWebln(data) & this.completeSetState(data));
};
@ -454,16 +441,9 @@ class OrderPage extends Component {
handleClickConfirmCancelButton = () => {
this.setState({ loading: true });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'cancel',
}),
};
fetch('/api/order/' + '?order_id=' + this.state.orderId, requestOptions)
.then((response) => response.json())
.then(() => this.getOrderDetails(this.state.orderId) & this.setState({ status: 4 }));
apiClient.post('/api/order/?order_id=' + this.state.orderId, {
action: 'cancel',
}).then(() => this.getOrderDetails(this.state.orderId) & this.setState({ status: 4 }));
this.handleClickCloseConfirmCancelDialog();
};
@ -561,16 +541,9 @@ class OrderPage extends Component {
};
handleClickConfirmCollaborativeCancelButton = () => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'cancel',
}),
};
fetch('/api/order/' + '?order_id=' + this.state.orderId, requestOptions)
.then((response) => response.json())
.then(() => this.getOrderDetails(this.state.orderId) & this.setState({ status: 4 }));
apiClient.post('/api/order/?order_id=' + this.state.orderId, {
action: 'cancel',
}).then(() => this.getOrderDetails(this.state.orderId) & this.setState({ status: 4 }));
this.handleClickCloseCollaborativeCancelDialog();
};

View File

@ -33,6 +33,7 @@ import Chat from './EncryptedChat';
import TradeSummary from './TradeSummary';
import MediaQuery from 'react-responsive';
import { copyToClipboard } from '../utils/clipboard';
import { apiClient } from '../services/api';
// Icons
import PercentIcon from '@mui/icons-material/Percent';
@ -132,16 +133,9 @@ class TradeBox extends Component {
};
handleClickAgreeDisputeButton = () => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'dispute',
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => this.props.completeSetState(data));
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'dispute',
}).then((data) => this.props.completeSetState(data));
this.handleClickCloseConfirmDispute();
};
@ -486,16 +480,9 @@ class TradeBox extends Component {
handleClickPauseOrder = () => {
this.props.completeSetState({ pauseLoading: true });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'pause',
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => this.props.getOrderDetails(data.id));
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'pause',
}).then((data) => this.props.getOrderDetails(data.id));
};
showMakerWait = () => {
@ -639,17 +626,10 @@ class TradeBox extends Component {
handleClickSubmitInvoiceButton = () => {
this.setState({ badInvoice: false });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'update_invoice',
invoice: this.state.invoice,
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then(
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'update_invoice',
invoice: this.state.invoice,
}).then(
(data) =>
this.setState({ badInvoice: data.bad_invoice }) & this.props.completeSetState(data),
);
@ -676,18 +656,11 @@ class TradeBox extends Component {
handleClickSubmitAddressButton = () => {
this.setState({ badInvoice: false });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'update_address',
address: this.state.address,
mining_fee_rate: Math.max(1, this.state.miningFee),
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then(
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'update_address',
address: this.state.address,
mining_fee_rate: Math.max(1, this.state.miningFee),
}).then(
(data) =>
this.setState({ badAddress: data.bad_address }) & this.props.completeSetState(data),
);
@ -703,20 +676,13 @@ class TradeBox extends Component {
handleClickSubmitStatementButton = () => {
this.setState({ badInvoice: false });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'submit_statement',
statement: this.state.statement,
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then(
(data) =>
this.setState({ badStatement: data.bad_statement }) & this.props.completeSetState(data),
);
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'submit_statement',
statement: this.state.statement,
}).then(
(data) =>
this.setState({ badStatement: data.bad_statement }) & this.props.completeSetState(data),
);
};
handleScan = (data) => {
@ -1213,30 +1179,16 @@ class TradeBox extends Component {
}
handleClickConfirmButton = () => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'confirm',
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => this.props.completeSetState(data));
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'confirm',
}).then((data) => this.props.completeSetState(data));
};
handleRatingUserChange = (e) => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'rate_user',
rating: e.target.value,
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => this.props.completeSetState(data));
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'rate_user',
rating: e.target.value,
}).then((data) => this.props.completeSetState(data));
};
handleRatingRobosatsChange = (e) => {
@ -1245,17 +1197,10 @@ class TradeBox extends Component {
}
this.setState({ rating_platform: e.target.value });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
action: 'rate_platform',
rating: e.target.value,
}),
};
fetch('/api/order/' + '?order_id=' + this.props.data.id, requestOptions)
.then((response) => response.json())
.then((data) => this.props.completeSetState(data));
apiClient.post('/api/order/?order_id=' + this.props.data.id, {
action: 'rate_platform',
rating: e.target.value,
}).then((data) => this.props.completeSetState(data));
};
showFiatSentButton() {
@ -1355,28 +1300,23 @@ class TradeBox extends Component {
handleRenewOrderButtonPressed = () => {
this.setState({ renewLoading: true });
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
type: this.props.data.type,
currency: this.props.data.currency,
amount: this.props.data.has_range ? null : this.props.data.amount,
has_range: this.props.data.has_range,
min_amount: this.props.data.min_amount,
max_amount: this.props.data.max_amount,
payment_method: this.props.data.payment_method,
is_explicit: this.props.data.is_explicit,
premium: this.props.data.is_explicit ? null : this.props.data.premium,
satoshis: this.props.data.is_explicit ? this.props.data.satoshis : null,
public_duration: this.props.data.public_duration,
escrow_duration: this.props.data.escrow_duration,
bond_size: this.props.data.bond_size,
bondless_taker: this.props.data.bondless_taker,
}),
const body = {
type: this.props.data.type,
currency: this.props.data.currency,
amount: this.props.data.has_range ? null : this.props.data.amount,
has_range: this.props.data.has_range,
min_amount: this.props.data.min_amount,
max_amount: this.props.data.max_amount,
payment_method: this.props.data.payment_method,
is_explicit: this.props.data.is_explicit,
premium: this.props.data.is_explicit ? null : this.props.data.premium,
satoshis: this.props.data.is_explicit ? this.props.data.satoshis : null,
public_duration: this.props.data.public_duration,
escrow_duration: this.props.data.escrow_duration,
bond_size: this.props.data.bond_size,
bondless_taker: this.props.data.bondless_taker,
};
fetch('/api/make/', requestOptions)
.then((response) => response.json())
apiClient.post('/api/make/', body)
.then(
(data) =>
this.setState({ badRequest: data.bad_request }) &

View File

@ -27,6 +27,7 @@ import { genKey } from '../utils/pgp';
import { getCookie, writeCookie, deleteCookie } from '../utils/cookies';
import { saveAsJson } from '../utils/saveFile';
import { copyToClipboard } from '../utils/clipboard';
import { apiClient } from '../services/api/index';
class UserGenPage extends Component {
constructor(props) {
@ -63,27 +64,20 @@ class UserGenPage extends Component {
const strength = tokenStrength(token);
const refCode = this.refCode;
const requestOptions = genKey(token).then(function (key) {
const requestBody = genKey(token).then(function (key) {
return {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
body: JSON.stringify({
token_sha256: sha256(token),
public_key: key.publicKeyArmored,
encrypted_private_key: key.encryptedPrivateKeyArmored,
unique_values: strength.uniqueValues,
counts: strength.counts,
length: token.length,
ref_code: refCode,
}),
token_sha256: sha256(token),
public_key: key.publicKeyArmored,
encrypted_private_key: key.encryptedPrivateKeyArmored,
unique_values: strength.uniqueValues,
counts: strength.counts,
length: token.length,
ref_code: refCode,
};
});
console.log(requestOptions);
requestOptions.then((options) =>
fetch('/api/user/', options)
.then((response) => response.json())
requestBody.then((body) =>
apiClient.post('/api/user/', body)
.then((data) => {
console.log(data) &
this.setState({
@ -127,11 +121,7 @@ class UserGenPage extends Component {
};
delGeneratedUser() {
const requestOptions = {
method: 'DELETE',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
};
fetch('/api/user', requestOptions).then((response) => response.json());
apiClient.delete('/api/user')
deleteCookie('sessionid');
deleteCookie('robot_token');

View File

@ -0,0 +1,40 @@
import { ApiClient } from "../api"
import { getCookie } from '../../../utils/cookies';
class ApiWebClient implements ApiClient {
private getHeaders: () => HeadersInit = () => {
return { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') || "" }
}
public post: (path: string, body: object) => Promise<object> = (path, body) => {
const requestOptions = {
method: 'POST',
headers: this.getHeaders(),
body: JSON.stringify(body),
};
return fetch(path, requestOptions).then((response) => response.json())
}
public put: (path: string, body: object) => Promise<object> = (path, body) => {
const requestOptions = {
method: 'PUT',
headers: this.getHeaders(),
body: JSON.stringify(body),
};
return fetch(path, requestOptions).then((response) => response.json())
}
public delete: (path: string) => Promise<object> = (path) => {
const requestOptions = {
method: 'DELETE',
headers: this.getHeaders(),
};
return fetch(path, requestOptions).then((response) => response.json())
}
public get: (path: string) => Promise<object> = (path) => {
return fetch(path).then((response) => response.json())
}
}
export default ApiWebClient

View File

@ -0,0 +1,10 @@
import ApiWebClient from './ApiWebClient'
export interface ApiClient {
post: (path: string, body: object) => Promise<object>
put: (path: string, body: object) => Promise<object>
get: (path: string) => Promise<object>
delete: (path: string) => Promise<object>
}
export const apiClient: ApiClient = new ApiWebClient()