Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

Commit f121633

Browse files
committed
FEATURE,PB_CHANGE: Add priceModifier for market priced listings.
1 parent 83a2384 commit f121633

7 files changed

+448
-225
lines changed

api/jsonapi_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,40 @@ func TestCryptoListings(t *testing.T) {
306306
})
307307
}
308308

309+
func TestCryptoListingsPriceModifier(t *testing.T) {
310+
outOfRangeErr := core.ErrPriceModifierOutOfRange{
311+
Min: core.PriceModifierMin,
312+
Max: core.PriceModifierMax,
313+
}
314+
315+
listing := factory.NewCryptoListing("crypto")
316+
listing.Metadata.PriceModifier = core.PriceModifierMax
317+
runAPITests(t, apiTests{
318+
{"POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`},
319+
{"GET", "/ob/listing/crypto", jsonFor(t, listing), 200, anyResponseJSON},
320+
})
321+
322+
listing.Metadata.PriceModifier = core.PriceModifierMax + 0.001
323+
runAPITest(t, apiTest{
324+
"POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`,
325+
})
326+
327+
listing.Metadata.PriceModifier = core.PriceModifierMax + 0.01
328+
runAPITest(t, apiTest{
329+
"POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(outOfRangeErr),
330+
})
331+
332+
listing.Metadata.PriceModifier = core.PriceModifierMin - 0.001
333+
runAPITest(t, apiTest{
334+
"POST", "/ob/listing", jsonFor(t, listing), 200, `{"slug": "crypto"}`,
335+
})
336+
337+
listing.Metadata.PriceModifier = core.PriceModifierMin - 1
338+
runAPITest(t, apiTest{
339+
"POST", "/ob/listing", jsonFor(t, listing), 500, errorResponseJSON(outOfRangeErr),
340+
})
341+
}
342+
309343
func TestListingsQuantity(t *testing.T) {
310344
listing := factory.NewListing("crypto")
311345
runAPITest(t, apiTest{

core/errors.go

+9
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ func (err ErrOutOfInventory) Error() string {
5959
return string(jsonBytes)
6060
}
6161

62+
type ErrPriceModifierOutOfRange struct {
63+
Min float64
64+
Max float64
65+
}
66+
67+
func (e ErrPriceModifierOutOfRange) Error() string {
68+
return fmt.Sprintf("priceModifier out of range: [%.2f, %.2f]", e.Min, e.Max)
69+
}
70+
6271
type ErrCryptocurrencyListingIllegalField string
6372

6473
func (e ErrCryptocurrencyListingIllegalField) Error() string {

core/listings.go

+46-14
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
)
2626

2727
const (
28-
ListingVersion = 3
28+
ListingVersion = 4
2929
TitleMaxCharacters = 140
3030
ShortDescriptionLength = 160
3131
DescriptionMaxCharacters = 50000
@@ -43,13 +43,18 @@ const (
4343
MaxCountryCodes = 255
4444
EscrowTimeout = 1080
4545
SlugBuffer = 5
46+
PriceModifierMin = -99.99
47+
PriceModifierMax = 1000.00
4648

4749
DefaultCoinDivisibility uint32 = 1e8
50+
51+
priceModifierListingVersion = 4
4852
)
4953

5054
type price struct {
51-
CurrencyCode string `json:"currencyCode"`
52-
Amount uint64 `json:"amount"`
55+
CurrencyCode string `json:"currencyCode"`
56+
Amount uint64 `json:"amount"`
57+
Modifier float32 `json:"modifier"`
5358
}
5459
type thumbnail struct {
5560
Tiny string `json:"tiny"`
@@ -146,7 +151,7 @@ func (n *OpenBazaarNode) SignListing(listing *pb.Listing) (*pb.SignedListing, er
146151
}
147152

148153
// Set listing version
149-
listing.Metadata.Version = ListingVersion
154+
listing.Metadata.Version = versionForNewListing(listing)
150155

151156
// Add the vendor ID to the listing
152157
id := new(pb.ID)
@@ -442,16 +447,20 @@ func (n *OpenBazaarNode) extractListingData(listing *pb.SignedListing) (ListingD
442447
}
443448

444449
ld := ListingData{
445-
Hash: listingHash,
446-
Slug: listing.Listing.Slug,
447-
Title: listing.Listing.Item.Title,
448-
Categories: listing.Listing.Item.Categories,
449-
NSFW: listing.Listing.Item.Nsfw,
450-
CoinType: listing.Listing.Metadata.CoinType,
451-
ContractType: listing.Listing.Metadata.ContractType.String(),
452-
Description: listing.Listing.Item.Description[:descriptionLength],
453-
Thumbnail: thumbnail{listing.Listing.Item.Images[0].Tiny, listing.Listing.Item.Images[0].Small, listing.Listing.Item.Images[0].Medium},
454-
Price: price{listing.Listing.Metadata.PricingCurrency, listing.Listing.Item.Price},
450+
Hash: listingHash,
451+
Slug: listing.Listing.Slug,
452+
Title: listing.Listing.Item.Title,
453+
Categories: listing.Listing.Item.Categories,
454+
NSFW: listing.Listing.Item.Nsfw,
455+
CoinType: listing.Listing.Metadata.CoinType,
456+
ContractType: listing.Listing.Metadata.ContractType.String(),
457+
Description: listing.Listing.Item.Description[:descriptionLength],
458+
Thumbnail: thumbnail{listing.Listing.Item.Images[0].Tiny, listing.Listing.Item.Images[0].Small, listing.Listing.Item.Images[0].Medium},
459+
Price: price{
460+
CurrencyCode: listing.Listing.Metadata.PricingCurrency,
461+
Amount: listing.Listing.Item.Price,
462+
Modifier: listing.Listing.Metadata.PriceModifier,
463+
},
455464
ShipsTo: shipsTo,
456465
FreeShipping: freeShipping,
457466
Language: listing.Listing.Metadata.Language,
@@ -1246,6 +1255,18 @@ func validateMarketPriceListing(listing *pb.Listing) error {
12461255
return ErrMarketPriceListingIllegalField("item.price")
12471256
}
12481257

1258+
if listing.Metadata.PriceModifier != 0 {
1259+
listing.Metadata.PriceModifier = float32(int(listing.Metadata.PriceModifier*100.0)) / 100.0
1260+
}
1261+
1262+
if listing.Metadata.PriceModifier < PriceModifierMin ||
1263+
listing.Metadata.PriceModifier > PriceModifierMax {
1264+
return ErrPriceModifierOutOfRange{
1265+
Min: PriceModifierMin,
1266+
Max: PriceModifierMax,
1267+
}
1268+
}
1269+
12491270
return nil
12501271
}
12511272

@@ -1293,3 +1314,14 @@ func verifySignaturesOnListing(sl *pb.SignedListing) error {
12931314
}
12941315
return nil
12951316
}
1317+
1318+
func versionForNewListing(listing *pb.Listing) uint32 {
1319+
// Don't use newer version number of the listing doesn't have new features
1320+
if ListingVersion == priceModifierListingVersion &&
1321+
listing.Metadata.Format == pb.Listing_Metadata_MARKET_PRICE &&
1322+
listing.Metadata.PriceModifier != 0 {
1323+
return priceModifierListingVersion - 1
1324+
}
1325+
1326+
return ListingVersion
1327+
}

core/order.go

+1
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ func (n *OpenBazaarNode) CalculateOrderTotal(contract *pb.RicardianContract) (ui
819819

820820
if l.Metadata.Format == pb.Listing_Metadata_MARKET_PRICE {
821821
satoshis, err = n.getMarketPriceInSatoshis(l.Metadata.CoinType, itemQuantity)
822+
satoshis += uint64(float32(satoshis) * l.Metadata.PriceModifier / 100.0)
822823
itemQuantity = 1
823824
} else {
824825
satoshis, err = n.getPriceInSatoshi(l.Metadata.PricingCurrency, l.Item.Price)

0 commit comments

Comments
 (0)