mirror of
https://github.com/RoboSats/robosats.git
synced 2025-09-13 00:56:22 +00:00
Add order description field
This commit is contained in:
@ -173,6 +173,14 @@ class Order(models.Model):
|
||||
blank=True,
|
||||
)
|
||||
|
||||
# optionally makers can set a description to give more details about the contract terms
|
||||
description = models.TextField(
|
||||
max_length=240,
|
||||
null=True,
|
||||
default=None,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
# how many sats at creation and at last check (relevant for marked to market)
|
||||
t0_satoshis = models.PositiveBigIntegerField(
|
||||
null=True,
|
||||
|
||||
@ -99,6 +99,7 @@ class OrderViewSchema:
|
||||
- `maker_status`
|
||||
- `taker_status`
|
||||
- `price_now`
|
||||
- `description`
|
||||
|
||||
### Order Status
|
||||
|
||||
|
||||
@ -406,6 +406,11 @@ class OrderDetailSerializer(serializers.ModelSerializer):
|
||||
required=False,
|
||||
help_text="The index of the last message sent in the trade chatroom",
|
||||
)
|
||||
description = serializers.CharField(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
help_text="Order description",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
@ -491,6 +496,7 @@ class OrderDetailSerializer(serializers.ModelSerializer):
|
||||
"latitude",
|
||||
"longitude",
|
||||
"chat_last_index",
|
||||
"description",
|
||||
)
|
||||
|
||||
|
||||
@ -590,6 +596,7 @@ class MakeOrderSerializer(serializers.ModelSerializer):
|
||||
"latitude",
|
||||
"longitude",
|
||||
"password",
|
||||
"description",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -119,6 +119,7 @@ class MakerView(CreateAPIView):
|
||||
latitude = serializer.data.get("latitude")
|
||||
longitude = serializer.data.get("longitude")
|
||||
password = serializer.data.get("password")
|
||||
description = serializer.data.get("description")
|
||||
|
||||
# Optional params
|
||||
if public_duration is None:
|
||||
@ -166,6 +167,7 @@ class MakerView(CreateAPIView):
|
||||
latitude=latitude,
|
||||
longitude=longitude,
|
||||
password=password,
|
||||
description=description,
|
||||
)
|
||||
|
||||
order.last_satoshis = order.t0_satoshis = Logics.satoshis_now(order)
|
||||
@ -282,6 +284,7 @@ class OrderView(viewsets.ViewSet):
|
||||
data["is_disputed"] = order.is_disputed
|
||||
data["ur_nick"] = request.user.username
|
||||
data["satoshis_now"] = order.last_satoshis
|
||||
data["description"] = order.description
|
||||
|
||||
# Add whether hold invoices are LOCKED (ACCEPTED)
|
||||
# Is there a maker bond? If so, True if locked, False otherwise
|
||||
|
||||
@ -253,6 +253,7 @@ const MakerForm = ({
|
||||
longitude: maker.longitude,
|
||||
shortAlias: maker.coordinator,
|
||||
password: maker.password ? sha256(maker.password) : null,
|
||||
description: maker.description ? maker.description : null,
|
||||
};
|
||||
|
||||
void slot
|
||||
@ -294,6 +295,14 @@ const MakerForm = ({
|
||||
});
|
||||
};
|
||||
|
||||
const handleDescriptionChange = function (event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setMaker({
|
||||
...maker,
|
||||
description: event.target.value,
|
||||
badDescription: event.target.value.length > 240,
|
||||
});
|
||||
};
|
||||
|
||||
const handleChangeEscrowDuration = function (date: Date): void {
|
||||
const d = new Date(date);
|
||||
const hours: number = d.getHours();
|
||||
@ -395,7 +404,8 @@ const MakerForm = ({
|
||||
maker.badPremiumText !== '' ||
|
||||
federation.getCoordinator(maker.coordinator)?.limits === undefined ||
|
||||
typeof maker.premium !== 'number' ||
|
||||
maker.paymentMethods.length === 0
|
||||
maker.paymentMethods.length === 0 ||
|
||||
maker.badDescription
|
||||
);
|
||||
}, [maker, maker.premium, amountLimits, federationUpdatedAt, fav.type, makerHasAmountRange]);
|
||||
|
||||
@ -866,6 +876,30 @@ const MakerForm = ({
|
||||
/>
|
||||
</Grid>
|
||||
<Collapse in={maker.advancedOptions} sx={{ width: '100%' }}>
|
||||
<Grid item sx={{ width: '100%' }}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label={`${t('Description')}`}
|
||||
type='description'
|
||||
value={maker.description}
|
||||
style={{ marginBottom: 8 }}
|
||||
inputProps={{
|
||||
style: {
|
||||
textAlign: 'center',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderRadius: 4,
|
||||
},
|
||||
}}
|
||||
onChange={handleDescriptionChange}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{maker.badDescription && (
|
||||
<FormHelperText error={true}>
|
||||
{t('Must be equal to or shorter than 240 characters')}
|
||||
</FormHelperText>
|
||||
)}
|
||||
|
||||
<Grid item sx={{ width: '100%' }}>
|
||||
<TextField
|
||||
fullWidth
|
||||
|
||||
@ -433,6 +433,25 @@ const OrderDetails = ({
|
||||
</ListItem>
|
||||
<Divider />
|
||||
|
||||
{currentOrder?.description !== undefined ? (
|
||||
<>
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<TextSnippet />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
primary={t('Description')}
|
||||
secondary={t('{{description}}', {
|
||||
description: currentOrder?.description,
|
||||
})}
|
||||
/>
|
||||
</ListItem>
|
||||
<Divider />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
|
||||
{/* If there is live Price and Premium data, show it. Otherwise show the order maker settings */}
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
|
||||
@ -22,6 +22,8 @@ export interface Maker {
|
||||
latitude: number | null;
|
||||
longitude: number | null;
|
||||
password: string | null;
|
||||
description: string | null;
|
||||
badDescription: boolean;
|
||||
}
|
||||
|
||||
export const defaultMaker: Maker = {
|
||||
@ -49,6 +51,8 @@ export const defaultMaker: Maker = {
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
password: null,
|
||||
description: null,
|
||||
badDescription: false,
|
||||
};
|
||||
|
||||
export default Maker;
|
||||
|
||||
@ -86,6 +86,7 @@ class Order {
|
||||
latitude: number = 0;
|
||||
longitude: number = 0;
|
||||
password: string | undefined = undefined;
|
||||
description: string | undefined = undefined;
|
||||
premium_now: number | undefined = undefined;
|
||||
tg_enabled: boolean = false; // deprecated
|
||||
tg_token: string = '';
|
||||
@ -201,6 +202,7 @@ class Order {
|
||||
latitude: this.latitude,
|
||||
longitude: this.longitude,
|
||||
password: this.password,
|
||||
description: this.description,
|
||||
};
|
||||
|
||||
if (slot) {
|
||||
|
||||
@ -479,6 +479,32 @@ class TradeTest(BaseAPITestCase):
|
||||
|
||||
# Cancel order to avoid leaving pending HTLCs after a successful test
|
||||
trade.cancel_order()
|
||||
|
||||
def test_make_and_take_description_order(self):
|
||||
"""
|
||||
Tests a trade with a description from order creation to taken.
|
||||
"""
|
||||
description = "Test"
|
||||
description_maker_form = maker_form_buy_with_range.copy()
|
||||
description_maker_form["description"] = description
|
||||
|
||||
trade = Trade(
|
||||
self.client,
|
||||
# Add description to order
|
||||
maker_form=description_maker_form,
|
||||
)
|
||||
trade.publish_order()
|
||||
trade.take_order()
|
||||
data = trade.response.json()
|
||||
|
||||
self.assertEqual(trade.response.status_code, 200)
|
||||
self.assertResponse(trade.response)
|
||||
|
||||
self.assertEqual(data["status_message"], Order.Status(Order.Status.PUB).label)
|
||||
self.assertEqual(data["description"], description)
|
||||
|
||||
# Cancel order to avoid leaving pending HTLCs after a successful test
|
||||
trade.cancel_order()
|
||||
|
||||
def test_make_and_take_password_order(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user