
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
@restorecommerce/cart
Advanced tools
[![Build Status][build]](https://travis-ci.org/restorecommerce/cart?branch=master)[![Dependencies][depend]](https://david-dm.org/restorecommerce/cart)[![Coverage Sta
An backend agnostic purely data-driven shopping cart that can be used on client- and server side.
Cart Instantiation:
const cart = new Cart({
serializer: new MockSerializer(),
shippingMethod: new Courier({
source: JSON.stringify(data.publicDHL),
shipping: {originCountry: 'DE'}
}),
taxOriginCountry: 'DE',
taxes: {
vat_standard: {
rate: new Decimal(1.19),
desc: '+ VAT 19%'
},
vat_reduced: {
rate: new Decimal(1.07),
desc: '+ VAT 7%'
}
}
});
Setting serializer
and shippingMethod
is optional.
setDestinationCountry(country: string)
cart.setDestinationCountry('LV');
getShippingMethod()
cart.getShippingMethod();
Output:
Courier {
_source: {
assumptions: {
currency: 'eur',
dimensions: [Object],
length: 'mm',
ranges: [Object],
weight: 'gram'
},
zones: {
'1': [Object],
'2': [Object],
'3': [Object],
'4': [Object],
'5': [Object],
'6': [Object],
'7': [Object],
'8': [Object],
national: [Object]
}
},
_shipping: {
destinationCountry: 'LV',
originCountry: 'DE' }
}
getShipping()
There is no setShipping
setter, since info about shipping is taken from ShippingMethod
's source
property.
cart.getShipping(); // calculates shipping cost
Output:
{
price: '15.99',
taxType: 'vat_standard',
maxWeight: 5000,
type: 'package',
zone: '1',
human: {
zone: '1 (all EU countries)',
offer: 'Package up to 5kg',
}
}
getSerializer()
cart.getSerializer();
getTaxRates()
cart.getTaxRates();
Output:
{
taxes: {
vat_standard: {
rate: '1.19',
desc: '+ VAT 19%'
},
vat_reduced: {
rate: '1.07',
desc: '+ VAT 7%'
}
}
}
addItems(items: IItem[])
cart.addItems([{
sku: 'cr2-blue',
price: new Decimal('12.95'), // Price
taxType: 'vat_reduced',
weight: 210, // grams
height: 2.20, // cm
width: 13.5, // cm
depth: 8.22, // cm
quantity: 7,
}, {
sku: 'cr5-red',
price: new Decimal('1.10'),
taxType: 'vat_standard',
weight: 210, // grams
height: 2.20, // cm
width: 13.5, // cm
depth: 8.22, // cm
quantity: 15,
}, {
sku: 'cr3-yellow',
price: new Decimal('2.48'),
taxType: 'vat_standard',
weight: 210, // grams
height: 2.20, // cm
width: 13.5, // cm
depth: 8.22, // cm
quantity: 3,
}]);
remItem(sku: string)
cart.remItem('cr3-yellow');
getItems()
cart.getItems();
Output:
[
{
sku: 'cr2-blue',
price: 12.95,
taxType: 'vat_reduced',
weight: 210,
height: 2.2,
width: 13.5,
depth: 8.22,
quantity: 7
},
{
sku: 'cr5-red',
price: 1.10,
taxType: 'vat_standard',
weight: 210,
height: 2.2,
width: 13.5,
depth: 8.22,
quantity: 15
}
]
setCustomer(customer: ICustomer)
cart.setCustomer({
type: CustomerType.COMMERCIAL,
});
setCustomerType(type: CustomerType)
This modifies the customer.
.
cart.setCustomerType(CustomerType.PRIVATE);
getCustomer()
cart.getCustomer();
Output:
{
type: 1 // 0 - COMMERCIAL / 1 - PRIVATE
}
modifyItem(item: any)
cart.modifyItem({
sku: 'cr5-red',
// no update for other Cart properties as no change
quantity: 10, // change only quantity
});
modifyItemQuantity(sku: string, quantity: number)
cart.modifyItemQuantity('cr5-red', 5); // adds 5 to initial quantity
getItemQuantity(sku: string)
`Amount of cr2-blue = ${cart.getItemQuantity('cr5-red')}`;
Output:
Amount of cr5-red = 15 // 10 + 5
getItemCount()
`Amount of unique products = ${cart.getItemCount()}`;
Output:
Amount of unique products = 2
getGrandQuantity()
`Amount of all products = ${cart.getGrandQuantity()}`;
Output:
Amount of all products = 22 // 15 + 7
getTaxes(keepOriginalTaxType?: boolean )
cart.getTaxes();
Output:
netPrice
and rate
are instances of Decimal
.
{
vat_standard: {
netPrice: '32.49',
rate: '1.19',
desc: '+ VAT 19%'
},
vat_reduced: {
netPrice: '90.65',
rate: '1.07',
desc: '+ VAT 7%'
}
}
static round(money: Money)
Parameter could be number
|string
|Decimal
. Returns string.
Cart.round(1.120); // '1.12'
Cart.round('1.123'); // '1.13'
Cart.round(new Decimal(1.125)); // '1.13'
Cart.round(new Decimal('1.127')); // '1.13'
getTotalNet()
Total net (without taxes).
Cart.round(cart.getTotalNet()); // '123.14'
Calculation:
1) customer.billing.countryCode === 'LV' => VAT + 19% / 7%
2) cr2_blue: Price * quantity => 12.95 * 7 = 90.65
3) cr5_red: Price * quantity => 1.10 * 15 = 16.5
4) Max Weight of all items = 22 items * 210 grams = 4620 grams =>
shipping = 15.99 euro for package less than 5000 grams to EU
5) sum = 90.65 + 16.5 + 15.99 = 123.14
getTotalGross()
Total gross (with taxes).
Cart.round(cart.getTotalGross()); // '135.66'
Calculation:
1) cr2_blue => cr2_blue + VAT 7% = 90.65 * 1.07 = 96.9955
2) cr5_red => cr5_red + VAT 19% = 16.5 * 1.19 = 19.635
3) shipping => shipping + VAT 19% = 15.99 * 1.19 = 19.0281
4) sum => 96.9955 + 19.635 + 19.0281 = 135.6586
5) round(135.6586) = 135.66
More examples of using the Cart
can be found in test/index.ts
.
Method | Description |
---|---|
getItems(): IItems / undefined | Get Items |
private setItems(items: IItem[]): void | Set items |
getCustomer(): ICustomer / undefined | Get customer |
setCustomer(customer: ICustomer): void | Set customer |
getShippingMethod(): IShippingMethod/ undefined | Get shipping method |
setShippingMethod(shippingMethod: IShippingMethod): void | Set shipping method |
getSerializer(): ISerializer / undefined | Get serializer |
setSerializer(serializer: ISerializer): void | Set serializer |
getTaxRates(): TaxRates | Get tax rates |
private setTaxRates(taxRates: TaxRates) | Set tax rates |
setCustomerType(type: CustomerType): void | Set customer's type (PRIVATE /COMMERCIAL ) |
setDestinationCountry(country: string): void | Set destination country |
addItems(items: IItem[]): void | Add item/items to the cart |
remItem(sku: string): void | Remove item from the cart by SKU (Stock Keeping Unit) |
modifyItem(item: any) | Update item |
modifyItemQuantity(sku: string, quantity: number): void | Modify item's quantity |
getItemCount(): number | Get item count |
getItemQuantity(sku: string): number | Get quantity of particular item |
getGrandQuantity(): number | Item count x quantity of each item |
getTaxes(keepOriginalTaxType?: boolean ): { [taxType: string]: { netPrice: Decimal, rate: Decimal, desc: string, price: Decimal } } | Get tax list, with ratios and additive costs |
getTotalNet(): number | Get sum of item and shipping costs (taxes excluded) |
getTotalGross(): number | Get sum of item and shipping costs (taxes included) |
getShipping(): { price: Money, [prop: string]: any } | Get item's shipping info |
static round(money: Money): string | Convert money type (number /string /Decimal ) to string with rounding |
To lint, transpile and test, run:
npm test
IShippingMethod
interface implementations:
Courier Plans:
For VAT calculation, the cart applies the EU ruleset for taxation which is exemplified in the following with a shop that is located in Germany and customer location location/ type being:
This also works for other countries as it's just a simplification of this for most countries. Sales taxes and other country specific taxes can be added.
Legal background:
FAQs
[![Build Status][build]](https://travis-ci.org/restorecommerce/cart?branch=master)[![Dependencies][depend]](https://david-dm.org/restorecommerce/cart)[![Coverage Sta
We found that @restorecommerce/cart demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.