Some fixes

This commit is contained in:
koalasat 2024-09-10 17:55:29 +02:00
parent a92ca62bb1
commit 06fc2e8bd7
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
10 changed files with 44 additions and 148 deletions

View File

@ -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}`);

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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,

View File

@ -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
);
};

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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",