mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-31 02:21:35 +00:00
Some fixes
This commit is contained in:
parent
a92ca62bb1
commit
06fc2e8bd7
@ -13,11 +13,10 @@ const Routes: React.FC = () => {
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('navigateToPage', (event) => {
|
||||
console.log('navigateToPage', JSON.stringify(event));
|
||||
const orderId: string = event?.detail?.order_id;
|
||||
const coordinator: string = event?.detail?.coordinator;
|
||||
if (orderId && coordinator) {
|
||||
const slot = garage.getSlotByOrder(coordinator, orderId);
|
||||
const slot = garage.getSlotByOrder(coordinator, parseInt(orderId, 10));
|
||||
if (slot?.token) {
|
||||
garage.setCurrentSlot(slot?.token);
|
||||
navigate(`/order/${coordinator}/${orderId}`);
|
||||
|
@ -319,12 +319,8 @@ const TakeButton = ({
|
||||
|
||||
setLoadingTake(true);
|
||||
|
||||
currentOrder
|
||||
.submitAction(federation, slot, {
|
||||
action: 'take',
|
||||
amount:
|
||||
currentOrder?.currency === 1000 ? Number(takeAmount) / 100000000 : Number(takeAmount),
|
||||
})
|
||||
slot
|
||||
.takeOrder(federation, currentOrder, takeAmount)
|
||||
.then((order) => {
|
||||
if (order?.bad_request !== undefined) {
|
||||
setBadRequest(order.bad_request);
|
||||
|
@ -174,8 +174,8 @@ const OrderDetails = ({
|
||||
|
||||
const isBuyer = (order.type === 0 && order.is_maker) || (order.type === 1 && !order.is_maker);
|
||||
const tradeFee = order.is_maker
|
||||
? coordinator.info?.maker_fee ?? 0
|
||||
: coordinator.info?.taker_fee ?? 0;
|
||||
? (coordinator.info?.maker_fee ?? 0)
|
||||
: (coordinator.info?.taker_fee ?? 0);
|
||||
const defaultRoutingBudget = 0.001;
|
||||
const btc_now = order.satoshis_now / 100000000;
|
||||
const rate = Number(order.max_amount ?? order.amount) / btc_now;
|
||||
|
@ -76,7 +76,11 @@ const makeTheme = function (settings: Settings): Theme {
|
||||
};
|
||||
|
||||
const getHostUrl = (network = 'mainnet'): string => {
|
||||
let host = defaultFederation.exp[network].onion;
|
||||
const randomAlias =
|
||||
Object.keys(defaultFederation)[
|
||||
Math.floor(Math.random() * Object.keys(defaultFederation).length)
|
||||
];
|
||||
let host = defaultFederation[randomAlias][network].onion;
|
||||
let protocol = 'http:';
|
||||
if (window.NativeRobosats === undefined) {
|
||||
host = getHost();
|
||||
|
@ -8,7 +8,7 @@ import React, {
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
|
||||
import { type Order, Federation, Settings } from '../models';
|
||||
import { Federation, Settings } from '../models';
|
||||
|
||||
import { federationLottery } from '../utils';
|
||||
|
||||
@ -28,10 +28,6 @@ export interface FederationContextProviderProps {
|
||||
export interface UseFederationStoreType {
|
||||
federation: Federation;
|
||||
sortedCoordinators: string[];
|
||||
setDelay: Dispatch<SetStateAction<number>>;
|
||||
currentOrderId: CurrentOrderIdProps;
|
||||
setCurrentOrderId: Dispatch<SetStateAction<CurrentOrderIdProps>>;
|
||||
currentOrder: Order | null;
|
||||
coordinatorUpdatedAt: string;
|
||||
federationUpdatedAt: string;
|
||||
addNewCoordinator: (alias: string, url: string) => void;
|
||||
@ -40,10 +36,6 @@ export interface UseFederationStoreType {
|
||||
export const initialFederationContext: UseFederationStoreType = {
|
||||
federation: new Federation('onion', new Settings(), ''),
|
||||
sortedCoordinators: [],
|
||||
setDelay: () => {},
|
||||
currentOrderId: { id: null, shortAlias: null },
|
||||
setCurrentOrderId: () => {},
|
||||
currentOrder: null,
|
||||
coordinatorUpdatedAt: '',
|
||||
federationUpdatedAt: '',
|
||||
addNewCoordinator: () => {},
|
||||
@ -56,24 +48,13 @@ export const FederationContextProvider = ({
|
||||
}: FederationContextProviderProps): JSX.Element => {
|
||||
const { settings, page, origin, hostUrl, open, torStatus } =
|
||||
useContext<UseAppStoreType>(AppContext);
|
||||
const { setMaker, garage, setBadOrder } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const { setMaker, garage } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const [federation] = useState(new Federation(origin, settings, hostUrl));
|
||||
const [sortedCoordinators, setSortedCoordinators] = useState(federationLottery(federation));
|
||||
const [coordinatorUpdatedAt, setCoordinatorUpdatedAt] = useState<string>(
|
||||
new Date().toISOString(),
|
||||
);
|
||||
const [federationUpdatedAt, setFederationUpdatedAt] = useState<string>(new Date().toISOString());
|
||||
const [currentOrderId, setCurrentOrderId] = useState<CurrentOrderIdProps>(
|
||||
initialFederationContext.currentOrderId,
|
||||
);
|
||||
const [currentOrder, setCurrentOrder] = useState<Order | null>(
|
||||
initialFederationContext.currentOrder,
|
||||
);
|
||||
|
||||
const [delay, setDelay] = useState<number>(defaultDelay);
|
||||
const [timer, setTimer] = useState<NodeJS.Timer | undefined>(() =>
|
||||
setInterval(() => null, delay),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setMaker((maker) => {
|
||||
@ -82,65 +63,15 @@ export const FederationContextProvider = ({
|
||||
federation.registerHook('onFederationUpdate', () => {
|
||||
setFederationUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
federation.registerHook('onCoordinatorUpdate', () => {
|
||||
setCoordinatorUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (window.NativeRobosats === undefined || torStatus === 'ON' || !settings.useProxy) {
|
||||
void federation.updateUrl(origin, settings, hostUrl);
|
||||
void federation.update();
|
||||
|
||||
const token = garage.getSlot()?.getRobot()?.token;
|
||||
if (token) void federation.fetchRobot(garage, token);
|
||||
}
|
||||
}, [settings.network, settings.useProxy, torStatus]);
|
||||
|
||||
const onOrderReceived = (order: Order): void => {
|
||||
let newDelay = defaultDelay;
|
||||
if (order?.bad_request) {
|
||||
newDelay = 99999999;
|
||||
setBadOrder(order.bad_request);
|
||||
garage.updateOrder(null);
|
||||
setCurrentOrder(null);
|
||||
}
|
||||
if (order?.id) {
|
||||
newDelay =
|
||||
order.status >= 0 && order.status <= 18
|
||||
? page === 'order'
|
||||
? statusToDelay[order.status]
|
||||
: statusToDelay[order.status] * 5 // If user is not looking at "order" tab, refresh less often.
|
||||
: 99999999;
|
||||
garage.updateOrder(order);
|
||||
setCurrentOrder(order);
|
||||
setBadOrder(undefined);
|
||||
}
|
||||
clearInterval(timer);
|
||||
console.log('New Delay:', newDelay);
|
||||
setDelay(newDelay);
|
||||
setTimer(setTimeout(fetchCurrentOrder, newDelay));
|
||||
};
|
||||
|
||||
const fetchCurrentOrder: () => void = () => {
|
||||
const slot = garage?.getSlot();
|
||||
const robot = slot?.getRobot();
|
||||
if (robot && slot?.token && currentOrderId.id && currentOrderId.shortAlias) {
|
||||
const coordinator = federation.getCoordinator(currentOrderId.shortAlias);
|
||||
void coordinator?.fetchOrder(currentOrderId.id, robot, slot?.token).then((order) => {
|
||||
onOrderReceived(order as Order);
|
||||
});
|
||||
} else if (slot?.token && slot?.activeShortAlias && robot?.activeOrderId) {
|
||||
const coordinator = federation.getCoordinator(slot.activeShortAlias);
|
||||
void coordinator?.fetchOrder(robot.activeOrderId, robot, slot.token).then((order) => {
|
||||
onOrderReceived(order as Order);
|
||||
});
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
setTimer(setTimeout(fetchCurrentOrder, defaultDelay));
|
||||
}
|
||||
};
|
||||
|
||||
const addNewCoordinator: (alias: string, url: string) => void = (alias, url) => {
|
||||
if (!federation.coordinators[alias]) {
|
||||
const attributes: Record<any, any> = {
|
||||
@ -164,24 +95,12 @@ export const FederationContextProvider = ({
|
||||
newCoordinator.update(() => {
|
||||
setCoordinatorUpdatedAt(new Date().toISOString());
|
||||
});
|
||||
garage.syncCoordinator(newCoordinator);
|
||||
garage.syncCoordinator(federation, alias);
|
||||
setSortedCoordinators(federationLottery(federation));
|
||||
setFederationUpdatedAt(new Date().toISOString());
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (currentOrderId.id && currentOrderId.shortAlias) {
|
||||
setCurrentOrder(null);
|
||||
setBadOrder(undefined);
|
||||
clearInterval(timer);
|
||||
fetchCurrentOrder();
|
||||
}
|
||||
return () => {
|
||||
clearInterval(timer);
|
||||
};
|
||||
}, [currentOrderId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (page === 'offers') void federation.updateBook();
|
||||
}, [page]);
|
||||
@ -191,7 +110,7 @@ export const FederationContextProvider = ({
|
||||
const slot = garage.getSlot();
|
||||
|
||||
if (open.profile && slot?.hashId && slot?.token) {
|
||||
void federation.fetchRobot(garage, slot?.token); // refresh/update existing robot
|
||||
void garage.fetchRobot(federation, slot?.token); // refresh/update existing robot
|
||||
}
|
||||
}, [open.profile]);
|
||||
|
||||
@ -200,10 +119,6 @@ export const FederationContextProvider = ({
|
||||
value={{
|
||||
federation,
|
||||
sortedCoordinators,
|
||||
currentOrderId,
|
||||
setCurrentOrderId,
|
||||
currentOrder,
|
||||
setDelay,
|
||||
coordinatorUpdatedAt,
|
||||
federationUpdatedAt,
|
||||
addNewCoordinator,
|
||||
|
@ -79,7 +79,7 @@ class Garage {
|
||||
// Slots
|
||||
getSlot: (token?: string) => Slot | null = (token) => {
|
||||
const currentToken = token ?? this.currentSlot;
|
||||
return currentToken ? this.slots[currentToken] ?? null : null;
|
||||
return currentToken ? (this.slots[currentToken] ?? null) : null;
|
||||
};
|
||||
|
||||
deleteSlot: (token?: string) => void = (token) => {
|
||||
@ -100,7 +100,7 @@ class Garage {
|
||||
if (attributes) {
|
||||
if (attributes.copiedToken !== undefined) slot?.setCopiedToken(attributes.copiedToken);
|
||||
this.save();
|
||||
this.triggerHook('onRobotUpdate');
|
||||
this.triggerHook('onSlotUpdate');
|
||||
}
|
||||
return slot;
|
||||
};
|
||||
@ -108,7 +108,7 @@ class Garage {
|
||||
setCurrentSlot: (currentSlot: string) => void = (currentSlot) => {
|
||||
this.currentSlot = currentSlot;
|
||||
this.save();
|
||||
this.triggerHook('onRobotUpdate');
|
||||
this.triggerHook('onSlotUpdate');
|
||||
};
|
||||
|
||||
getSlotByOrder: (coordinator: string, orderID: number) => Slot | null = (
|
||||
@ -118,7 +118,7 @@ class Garage {
|
||||
return (
|
||||
Object.values(this.slots).find((slot) => {
|
||||
const robot = slot.getRobot(coordinator);
|
||||
return slot.activeShortAlias === coordinator && robot?.activeOrderId === orderID;
|
||||
return slot.activeOrder?.shortAlias === coordinator && robot?.activeOrderId === orderID;
|
||||
}) ?? null
|
||||
);
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
import defaultFederation from '../../static/federation.json';
|
||||
|
||||
export interface Maker {
|
||||
advancedOptions: boolean;
|
||||
coordinator: string;
|
||||
@ -23,7 +25,10 @@ export interface Maker {
|
||||
|
||||
export const defaultMaker: Maker = {
|
||||
advancedOptions: false,
|
||||
coordinator: 'exp',
|
||||
coordinator:
|
||||
Object.keys(defaultFederation)[
|
||||
Math.floor(Math.random() * Object.keys(defaultFederation).length)
|
||||
] ?? '',
|
||||
isExplicit: false,
|
||||
amount: '',
|
||||
paymentMethods: [],
|
||||
@ -40,6 +45,8 @@ export const defaultMaker: Maker = {
|
||||
maxAmount: '',
|
||||
badPremiumText: '',
|
||||
badSatoshisText: '',
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
};
|
||||
|
||||
export default Maker;
|
||||
|
@ -214,6 +214,17 @@ class Order {
|
||||
return this;
|
||||
};
|
||||
|
||||
take: (federation: Federation, slot: Slot, takeAmount: string) => Promise<this> = async (
|
||||
federation,
|
||||
slot,
|
||||
takeAmount,
|
||||
) => {
|
||||
return this.submitAction(federation, slot, {
|
||||
action: 'take',
|
||||
amount: this?.currency === 1000 ? Number(takeAmount) / 100000000 : Number(takeAmount),
|
||||
});
|
||||
};
|
||||
|
||||
submitAction: (federation: Federation, slot: Slot, action: SubmitActionProps) => Promise<this> =
|
||||
async (federation, slot, action) => {
|
||||
if (this.id < 1) return this;
|
||||
|
@ -111,6 +111,12 @@ class Slot {
|
||||
this.updateSlotFromOrder(this.activeOrder);
|
||||
};
|
||||
|
||||
takeOrder = async (federation: Federation, order: Order, takeAmount: string): Promise<Order> => {
|
||||
await order.take(federation, this, takeAmount);
|
||||
this.updateSlotFromOrder(order);
|
||||
return order;
|
||||
};
|
||||
|
||||
makeOrder = async (federation: Federation, attributes: object): Promise<Order> => {
|
||||
const order = new Order(attributes);
|
||||
await order.make(federation, this);
|
||||
@ -124,6 +130,7 @@ class Slot {
|
||||
if (newOrder) {
|
||||
// FIXME: API responses with bad_request should include also order's status
|
||||
if (newOrder?.bad_request?.includes('expired')) newOrder.status = 5;
|
||||
if (newOrder?.bad_request?.includes('collaborativelly')) newOrder.status = 12;
|
||||
if (
|
||||
newOrder.id === this.activeOrder?.id &&
|
||||
newOrder.shortAlias === this.activeOrder?.shortAlias
|
||||
|
@ -1,47 +1,4 @@
|
||||
{
|
||||
"exp": {
|
||||
"longAlias": "Experimental",
|
||||
"shortAlias": "exp",
|
||||
"description": "RoboSats node for development and experimentation. This is the original RoboSats coordinator operated by the RoboSats devs since 2022.",
|
||||
"motto": "Original Robohost. P2P FTW!",
|
||||
"color": "#1976d2",
|
||||
"established": "2022-03-01",
|
||||
"contact": {
|
||||
"email": "robosats@protonmail.com",
|
||||
"telegram": "robosats",
|
||||
"twitter": "robosats",
|
||||
"reddit": "r/robosats",
|
||||
"matrix": "#robosats:matrix.org",
|
||||
"website": "https://learn.robosats.com",
|
||||
"nostr": "npub1p2psats79rypr8lpnl9t5qdekfp700x660qsgw284xvq4s09lqrqqk3m82",
|
||||
"pgp": "/static/federation/pgp/B4AB5F19113D4125DDF217739C4585B561315571.asc",
|
||||
"fingerprint": "B4AB5F19113D4125DDF217739C4585B561315571"
|
||||
},
|
||||
"badges": {
|
||||
"isFounder": true,
|
||||
"donatesToDevFund": 20,
|
||||
"hasGoodOpSec": true,
|
||||
"robotsLove": true,
|
||||
"hasLargeLimits": true
|
||||
},
|
||||
"policies": {
|
||||
"Experimental": "Experimental coordinator used for development. Use at your own risk.",
|
||||
"Dispute Policy": "Evidence in Disputes: In the event of a dispute, users will be asked to provide transaction-related evidence. This could include transaction IDs, screenshots of payment confirmations, or other pertinent transaction records. Personal information or unrelated transaction details should be redacted to maintain privacy.",
|
||||
"Non eligible countries": "USA citizens and residents are not allowed to use the Experimental coordinator. F2F transactions are explicitly blocked at creation time for US locations. If a US citizen or resident violates this rule and is found out to be using the Experimental coordinator during a dispute process, they will be denied further service and the dispute mediation will be terminated."
|
||||
},
|
||||
"mainnet": {
|
||||
"onion": "http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion",
|
||||
"clearnet": "https://unsafe.robosats.com",
|
||||
"i2p": "http://r7r4sckft6ptmk4r2jajiuqbowqyxiwsle4iyg4fijtoordc6z7a.b32.i2p"
|
||||
},
|
||||
"testnet": {
|
||||
"onion": "http://robotestagw3dcxmd66r4rgksb4nmmr43fh77bzn2ia2eucduyeafnyd.onion",
|
||||
"clearnet": "https://unsafe.testnet.robosats.com",
|
||||
"i2p": ""
|
||||
},
|
||||
"mainnetNodesPubkeys": ["0282eb467bc073833a039940392592bf10cf338a830ba4e392c1667d7697654c7e"],
|
||||
"testnetNodesPubkeys": ["03ecb271b3e2e36f2b91c92c65bab665e5165f8cdfdada1b5f46cfdd3248c87fd6"]
|
||||
},
|
||||
"temple": {
|
||||
"longAlias": "Temple of Sats",
|
||||
"shortAlias": "temple",
|
||||
|
Loading…
Reference in New Issue
Block a user